关于自修改代码的一点浅析

Bug 为什么越改越多 理解bug产生的本质。 阅读详情

相信大家都在程序调试或者分析中碰到过自修改代码的情况吧。所谓自修改代码,就是程序自我保护的一种机制。它使我们的反汇编调试器看起来相当地无助。因为我们看到的所谓的反汇编代码并非执行过程中的代码,它表面上看起来不合逻辑甚至一塌糊涂,但是运行起来却井井有条。因此,这项技术被广泛用在那些反破解的商业软件中,在试图bypass杀毒软件的黑客软件中也颇有涉及。在另一方面,cracker初学者们对这类程序大伤脑筋,他们一边诅咒反汇编调试器一边对着一大堆非法指令符莫名其妙。他们必须不停地设置断点,慢慢地让程序在运行过程中将真正的代码暴露出来。

没错,这就是很多壳的基本运行原理。然而我并不打算在这里教大家怎么脱壳,大部分程序员都已经为我们做好了现成的脱壳程序,剩下的都是一些繁杂的充斥着各种SEH等保护机制的超级壳,也许强大到作者也没有办法写出脱壳脚本。我写这篇文章的目的就是对代码自修改技术做一点点分析而已。

为了更好地诠释代码自修改,我引用下面段代码。

FE 0D   xxxxxx            DEC byte ptr DS:[The_fake_jmp]        ;将装有The_fake_jmp入口地址的DS进行修改,即将The_fake_jmp的第一个字节内容减一。

......                          ;其他的代码

B8 01 000000          MOV eax,1

The_fake_jmp:

75 xx                          JNZ another_place                                 ;eax非零则跳转

......

如果没有看到前面的代码,也许很多程序员会想当然地认为一定会跳转到another_place,其实程序运行时已经将the_fake_jmp改成了74 xx,即改成了jz。这样程序运行的结果将与程序员所预料的完全相反。

通过这个例子大家也许会发现,存在自修改代码的程序调试起来确实要小心.难道我们必须要一步一步单步调试才能发现隐藏的陷阱吗?当然不是.前面已经提到了,不吝惜自己的断点可以很方便地识破这些小小的破绽。

下面我将通过调试著名木马Bifrost 1.2.1的脱壳服务端(该木马可以在chasenet.org下载到)来观察它的一些自修改代码片断。

传说中Bifrost的原始服务端是加壳的。有人已经做出了所谓的脱壳版本。实际上,我发现两者的区别不是很大。oep都没有经过修改。这里选用的调试器是网络上比较流行的应用层调试器Ollydbg。

载入服务端后我们可以看到OD的提示。说明该服务端存在大量自修改程序。我们随便就能找到一些调试器无法识别的指令。这里我选用00406111处.这里的代码如下:(这些代码也许在其他版本的服务端上是不同的)

00406111    F4              hlt
00406112    A4              movs    byte ptr es:[edi], byte ptr [esi>
00406113    64:9A 325427F8 >call    far D779:F8275432
0040611B    9B              wait
0040611C    F1              int1
0040611D    65:338D 355EF3B>xor     ecx, dword ptr gs:[ebp+BFF35E35]
00406124    DEBF D977A7B3   fidivr  word ptr [edi+B3A777D9]
0040612A    A8 62           test    al, 62
0040612C    9B              wait
0040612D    002A            add     byte ptr [edx], ch

不仅仅是这些代码,它的一大段上下文都让人莫名其妙。到这里我们假定它是自修改代码的一部分。我们在00406111点右键-断点-内存写入,然后F9运行,我们会到达尝试对这段代码进行修改的程序段。仔细看看,呵呵,不错,我们似乎到达了对代码进行修改的函数里。其附近代码如下,我在这里对它们加了一点简短的注释。

004073C0    55                  push    ebp
004073C1    8BEC            mov     ebp, esp
004073C3    56                  push    esi
004073C4    33F6              xor     esi, esi                                        ;清空esi
004073C6    3975 0C        cmp     dword ptr [ebp+C], esi          ;esi在这里做计数器
004073C9    7E 1B             jle     short 004073E6                        ;若解密完毕则跳转
004073CB    8B45 08        mov     eax, dword ptr [ebp+8]
004073CE    33D2              xor     edx, edx
004073D0    8D0C06         lea     ecx, dword ptr [esi+eax]         ;解密段指针
004073D3    8BC6              mov     eax, esi
004073D5    F775 14         div     dword ptr [ebp+14]
004073D8    8B45 10         mov     eax, dword ptr [ebp+10]
004073DB    8A0402          mov     al, byte ptr [edx+eax]             ;我们的密钥
004073DE    3001               xor     byte ptr [ecx], al                        ;xor加密解密方式
004073E0    46                    inc     esi
004073E1    3B75 0C        cmp     esi, dword ptr [ebp+C]
004073E4  ^ 7C E5            jl      short 004073CB
004073E6    5E                   pop     esi
004073E7    5D                  pop     ebp
004073E8    C3                   retn

有点像某些shellcode的编码器,不是吗?值得一提的是,xor的密钥并不是一个常数,它在加密解密过程中会发生变化。我们需要更多的调试来看清楚它是怎么工作的。我们在004073DE处设置一个断点,然后Ctrl+F2重载,F9运行,呵呵,我们可以看到它停在解密阶段。我们看各个寄存器的值:EAX:00407320  ECX:00407028  ESI:000000,其余的跟我们要观察的没有太多关系,我们就不看了,我们所知道的就是它从00407028处开始加密。不妨看看00407028这里是什么:

00407028   /75 5D           jnz     short 00407087
0040702A   |CC              int3
0040702B   |55              push    ebp
0040702C   |CC              int3
0040702D   |FA              cli
0040702E  ^|73 80           jnb     short 00406FB0
00407030   |77 3E           ja      short 00407070
00407032   |20D6            and     dh, dl
00407034   |20D6            and     dh, dl
00407036   |79 5F           jns     short 00407097
00407038   |6D              ins     dword ptr es:[edi], dx

又是一堆无聊的代码。我们再F9运行,它又停在了断点处,我们再看:EAX:004073D6   ECX:00407029  ESI:000001看,密钥变了,再运行一次,我们又看到EAX又变回了00407328。说明这是两个密钥轮流对代码进行xor修改。密钥看起来像个指针,但是我们没必要太关心它,根据修改前后数值对比我们也能找出密钥,不是吗?我们再来看它到底修改了多长的代码。我们将原来的断点取消,再在004073E6处设置断点,直接看看它自修改的结果。运行,我们发现ecx停在了00407380处,这是加密的结尾,esi的值为359(十六进制),我们知道它这次修改了0x359字节的东西 。我们来看看它修改过的,也就是真实的代码。

00407028    55              push    ebp
00407029    8BEC            mov     ebp, esp
0040702B    83EC 2C         sub     esp, 2C
0040702E    53              push    ebx
0040702F    56              push    esi
00407030    57              push    edi
00407031    E8 00000000     call    00407036
00407036    59              pop     ecx
00407037    894D E4         mov     dword ptr [ebp-1C], ecx
0040703A    EB 42           jmp     short 0040707E
0040703C    56              push    esi
0040703D    6972 74 75616C4>imul    esi, dword ptr [edx+74], 416C617>
00407044    6C              ins     byte ptr es:[edi], dx

呵呵,这回好看多了。但是我们刚才定的地址是00406111,它似乎不在这个区段里。所以我们还得看看这区段的解密过程。因此,再次在004073DE处设置断点,运行看它是否还继续有活干。果然,它又停下来了,此时各寄存器的值为:EAX:004073F6 ECX:00401028,取消004073DE的断点,再运行,看:EAX:004073F6 ECX:00407027,如果没有取消断点,我们会发现,这轮解密用的是同一个密钥:F6。我们来看看00406111处变成什么了。

00406111    0252 92         add     dl, byte ptr [edx-6E]
00406114    6C              ins     byte ptr es:[edi], dx
00406115    C4A2 D10E8F21   les     esp, fword ptr [edx+218F0ED1]
0040611B    6D              ins     dword ptr es:[edi], dx
0040611C    07              pop     es
0040611D    93              xchg    eax, ebx
0040611E    C57B C3         lds     edi, fword ptr [ebx-3D]
00406121    A8 05           test    al, 5
00406123    49              dec     ecx

呵呵,看起来比我想像的要麻烦,因为解密后的代码还是一团糟。我们继续设置内存写入断点看看,跑飞了。可能运行过程中没有碰到该函数段吧。我们换个地方试试,设在00405B48,结果来到了另外一处解码器处。代码如下:

00407122    85C9            test    ecx, ecx
00407124    8945 F4         mov     dword ptr [ebp-C], eax
00407127    7E 30           jle     short 00407159
00407129    894D F4         mov     dword ptr [ebp-C], ecx
0040712C    8B48 10         mov     ecx, dword ptr [eax+10]
0040712F    8B78 0C         mov     edi, dword ptr [eax+C]
00407132    8B70 14         mov     esi, dword ptr [eax+14]
00407135    037D 08         add     edi, dword ptr [ebp+8]
00407138    0333            add     esi, dword ptr [ebx]
0040713A    894D DC         mov     dword ptr [ebp-24], ecx
0040713D    8BD1            mov     edx, ecx
0040713F    897D D8         mov     dword ptr [ebp-28], edi
00407142    C1E9 02         shr     ecx, 2
00407145    F3:A5           rep     movs dword ptr es:[edi], dword ptr [esi]
00407147    8BCA            mov     ecx, edx
00407149    83C0 28         add     eax, 28
0040714C    83E1 03         and     ecx, 3
0040714F    FF4D F4         dec     dword ptr [ebp-C]
00407152    F3:A4           rep     movs byte ptr es:[edi], byte ptr [esi]
00407154  ^ 75 D6           jnz     short 0040712C
00407156    8945 F4         mov     dword ptr [ebp-C], eax
00407159    8B7D F0         mov     edi, dword ptr [ebp-10]
0040715C    837F 74 10      cmp     dword ptr [edi+74], 10
00407160    0F8C F2010000   jl      00407358
00407166    83BF 84000000 0>cmp     dword ptr [edi+84], 0

天啊,这是用VM保护过的代码,而且我们也会发现,这些内容是经第一个解码器解码过的内容。真的是相当复杂。由于有过多的vm保护指令,这里就不对该解码器进行具体分析了。

说到这里,也许有人要问,这样的保护技术是怎样实现的。Kris Kaspersky在他的著作中给出了几种实现的方法,其中堆栈自修改的方式比较复杂,而且修改的代码必须完全可重定位,即在内存中的任何位置都可以独立执行。。。这需要相当高的汇编技巧,这里不介绍了。我要介绍的是另外一种不需要太多技巧的方法。

顺便提一下很多人对自修改代码的误区。他们认为自修改技术只能在反汇编调试下得到完整分析,因此认为它的编写也只有汇编才能支持。事实上,包括现有的汇编编译器,没有任何一个程序语言编译器声明支持自修改代码。只要有这样的技巧,不仅是汇编,C语言也支持。

假若我们是商业软件的开发商,我们希望自己的软件不被破解,于是我们现在要对软件注册段的函数进行自修改以及加密。我们假设自己的检测注册码的代码如下:

int iRegister(char csEnterkey[24])

{
  //char csMykey[] = "ABCD-EFGH-IJKL-MNOP-QRST";
 if(!strcmp( "ABCD-EFGH-IJKL-MNOP-QRST",csEnterkey))
  
 {
  printf("Thank you for register!/n");
 return 0;
 }

 else printf("Invalid key,sorry./n");
 return -1;

}

这里我们使用类似Bifrost服务端的初级自修改加密方式,即xor加密这段函数,我用C语言写成的完整代码如下:(待续) 

五种主流源代码加密方案全解析:从混淆到虚拟化实战指南 在软件开发和交付过程中,代码保护是保障知识产权和商业机密的核心环节。其基本原理是通过技术手段对源代码或编译产物进行处理,防止未授权的访问、分析和篡改。从技术价值看,有效的代码保护不仅能避免核心算法泄露和商业纠纷,更是实现安全交付、合规协作的基础。常见的应用场景包括商业软件分发、前端代码防爬、算法模块保护以及外包项目交付等。本文聚焦于**构建时混淆**和**二进制加壳**等五种主流方案,通过对比其原理、强度与适用场景,为工程师提供兼顾安全与效能的工程实践参考。 阅读详情

相关推荐

Nextpy框架:编译时优化与KV缓存复用,构建高效AI应用新范式

在AI应用开发领域,大语言模型(LLM)的推理延迟和成本控制是核心挑战。传统基于运行时提示词拼接的方法,每次调用都需要模型重新计算完整上下文,导致冗余计算和令牌开销高昂。其技术原理在于Transformer模型生成文本时会计算键值缓存(KV Cache),但传统调用方式会丢弃该缓存。Nextpy框架通过引入编译时优化和会话状态管理,将确定性逻辑前置处理,并持久化复用KV缓存,从而显著提升推理效率。这一技术价值在于能够将AI应用的响应速度提升数倍,同时降低API调用成本。在代码生成、数据分析助手等需要多轮交互

weixin_42400643的博客 345

卧槽:IntelliJ IDEA 居然偷偷改代码。。

问题 要疯了,IDEA 居然自动修改代码? 明明我已经修改保存了,怎么测试都不行,后来我检查一看,并通过复现,发现,代码被 IDEA 自动改了。。 如下面动图所示: 本来是 类.方法,我改成了 实例.方法 调用了 原来,每次当我保存完之后,代码又复原了,太诡异了。。 这样一来,那我的实例对象不是没用到?又直接访问类的静态方法了。。 定位 看到上图,栈长突然灵机一动,这让我想起了之前分享过的《IntelliJ IDEA 2021.2 发布,这次要干掉 FindBugs 了!》这篇文章中的新功能:保存时动

Java技术栈,分享最主流的Java技术 1246

现代终端防护绕过技术:Shellcode投递与内存执行攻防解析

在网络安全领域,终端防护与恶意代码检测是保障系统安全的核心防线。其基本原理是通过静态特征扫描、动态行为监控和内存分析等多层次机制,识别和阻断恶意活动。这些技术的核心价值在于实时防御未知威胁,保护关键业务数据与系统完整性。在实际应用场景中,攻防对抗往往围绕代码执行权限展开,攻击者需要在不触发警报的前提下完成载荷投递。本文聚焦于**进程镂空**和**Shellcode加密**等关键技术,深入剖析如何通过精细化的内存操作和API调用伪装,绕过现代终端检测与响应系统。这些方法不仅涉及底层的系统调用机制,还涵盖了合法

diyu8056的博客 458

Java-面向对象

软件生命周期: 软件生命周期: 软件的产生直到报废的整个过程. 软件生命周期内有:问题定义, 可行性分析, 总体描述, 系统设计,编码, 调试和测试, 验收与运行, 维护升级到废弃等阶段 1):问题的定义及规划: 此阶段是软件开发方与需求方共同讨论,主要确定软件的开发目标及其可行性。 2):需求分析: 在确定软件开发可行的情况下,对软件需要实现的各功能进行详细分析。需求分析阶段是一个很重要的阶段,...

qq_37806415的博客 1万+

深入解析博世GTM MCS指令集:硬件确定性控制的核心机制

在嵌入式实时控制系统中,指令集与寻址模式是处理器架构的基石,它们定义了数据访问和程序执行的底层逻辑。其设计原理直接决定了系统的执行效率、时序确定性和资源访问能力。对于汽车电子和工业自动化等对延迟极度敏感的领域,专用的硬件协处理器通过精简指令集和高效的寻址模式,实现了传统CPU难以企及的纳秒级确定性。这种技术价值在于能够以硬件级的精度直接编排外设行为,例如生成精密的PWM波形或同步多个ADC采样。博世通用定时器模块(GTM)中的多通道序列器(MCS)正是这一理念的典范,其指令集专为硬件控制而生,通过**ARU

weixin_30872157的博客 749

用C/C++实现代码的动态修改(SMC)

所谓SMC(Self Modifying Code)技术,就是一种将可执行文件中的代码或数据进行加密,防止别人使用逆向工程工具(比如一些常见的反汇编工具)对程序进行静态分析的方法,只有程序运行时才对代码和数据进行解密,从而正常运行程序和访问数据。计算机病毒通常也会采用SMC技术动态修改内存中的可执行代码来达到变形或对代码加密的目的,从而躲过杀毒软件的查杀或者迷惑反病毒工作者对代码进行分析。由于该技术需要直接读写对内存中的机器码,所以多采用汇编语言实现,这使得很多想在自己的程序中使用SMC技术进行软件加密的C/C++程序员望而却步。针对这种现状,本文提出了几种基于C/C++语言的机器指令定位方法,从而用C/C++语言实现了动态代码修改技术。

修改代码的艺术 读书笔记(一,修改代码的四种原因)

修改代码的四个主要原因: 1 增加一个功能 2 修复一个bug 3 improve design 4 优化资源利用,例如内存或时间。 这四种修改代码的原因和它影响系统的方面:                                     Structure         Functionality          Resource Usage Adding a

hongchangfirst 1439

MOOS-ivp 实验三 MOOS简介(3)

MOOS-ivp 实验三 MOOS简介(3) 继上一篇文章继续对实验进行记录 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录MOOS-ivp 实验三 MOOS简介(3)六、A Simple Example with pXRelay1.pXRelay基本使用2.pXRelay简单例子3.pXRelay实验七、First Experiments in Modifying MOOS App Code1.下载一个MOOS模板文件2.打开MOOS模板文件总结 六、A Simple E

weixin_44151170的博客 2534

自修改代码浅析

相信大家都在程序调试或者分析中碰到过自修改代码的情况吧。所谓自修改代码,就是程序自我保护的一种机制。它使我们的反汇编调试器看起来相当地无助。因为我们看到的所谓的反汇编代码并非执行过程中的代码,它表面上看起来不合逻辑甚至一塌糊涂,但是运行起来却井井有条。因此,这项技术被广泛用在那些反破解的商业软件中,在试图bypass杀毒软件的黑客软件中也颇有涉及。在另一方面,cracker

憩园幽幽的专栏 3399

最新打赏系统打赏源码麒麟最新打赏源码喜盈门打赏知识付费课程教程直播讲解

打赏源码打赏系统

qq_41095398的博客 2034

超分算法 SwinIR: Image Restoration Using Swin Transformer

这篇文章结构比较简单,如果看过Swin-Transformer的话就没什么难点了。作者引入Swin-T结构应用于低级视觉任务,包括图像超分辨率重建、图像去噪、图像压缩伪影去除。网络由一个浅层特征提取模块、深层特征提取模块、重建模块构成。重建模块对不同的任务使用不同的结构。浅层特征提取就是一个3×3的卷积层。深层特征提取是k个RSTB块和一个卷积层构成。RSTB(Res- SwinIR: Image Restoration Using Swin Transformer[ICCV 2021]Abstract1.

qq_45122568的博客 1万+

浅析SMC技术

<br />今天让我们来看Win32ASM里面的高级一点的技术——SMC(当当当当……)!!!<br /><br />SMC是什么意思?它的英文名叫“Self Modifying Code”,顾名思义,就是“代码自修改”(?)(不好意思,小弟的英语六级还没过,只能翻译成这样啦……)<br /><br />“代码自修改”?哇,好高深啊!其实不然……<br /><br />我们知道,Win32应用程序是运行在保护模式下的,每个Win32应用程序都有相互独立的4GB地址空间,并且已经摒弃了16位时代的把代码分为D

m4nkey 1926

Unity与iOS原生交互实战指南

C#(DllImport) → C 接口(extern "C") → Objective‑C / SwiftObjective‑C → UnitySendMessage → C#(GameObject + public 方法)在写.mm文件;在里面写;C# 用声明;调用它,参数就是 string / 数值等;在.mm里做你想做的 iOS 原生操作。在 Unity 里准备一个常驻 GameObject,比如;上面挂一个脚本,写;在 iOS 插件中用;

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 1357

浅析进程地址空间

在linux下,当我们对我们所写好的程序.c文件进行gcc编译过程时,会出现一个a.out可执行文件,这个文件中到底包含什么呢,接下来我们来看一看。 在UNIX下可使用size命令查看可执行文件的段大小信息。如size a.out。 接下来,我进行测试的演示: 这个是我写好的测试程序。 首先我们来测试这个程序的段大小信息。 我们在这,可以知道,a.out中含有 text(文本段),

宇哲 529

小红书直播弹幕采集

本文主要介绍小红书直播间弹幕的采集,便于进行直播数据监控与直播数据进行分析。

tdl320721的博客 2540

BACnet协议栈基本对象BI、BO、AI、AO、AV以及device和File对象介绍

BACnet协议栈基本对象BI、BO、AI、AO、AV以及device和File对象介绍

shufawangzhang的博客 3988

C语言混淆代码解析:IOCCC获奖作品背后的编译原理与逆向工程

代码混淆是一种通过改变程序结构隐藏原始逻辑的技术,其核心原理在于利用编程语言的语法特性和编译器行为。在C语言中,宏展开、指针运算和未定义行为等技术常被用于实现混淆,这不仅考验开发者对语言标准的深入理解,也为编译器测试和逆向工程研究提供了独特价值。IOCCC(国际C语言混乱代码大赛)作品将这种技术推向极致,通过滥用预处理指令、视觉欺骗和底层技巧,在符合C标准的前提下创造出功能完整但难以阅读的程序。这类代码虽然不具备生产环境实用性,却成为研究编译原理、探索语言边界和训练逆向分析能力的绝佳材料,尤其适合安全研究人

weixin_34242509的博客 321

探索如何利用CST和ADS进行DDR的SIPI联合仿真

本文系统介绍了CST和ADS两款工具进行DDR信号完整性/电源完整性(SI/PI)联合仿真的方法。CST采用工作室协同方式,通过PCB布局导入、材料设置、模型分配等步骤,重点分析了电源阻抗优化和信号波形质量。ADS则利用SIPro、PIPro等专用工具,突出系统级验证和自动化优化功能。两者各有优势:CST擅长3D结构精确建模,ADS更适于快速系统验证。文章建议可根据项目需求混合使用两种工具,并提供了模型简化、频带选择等实用技巧。通过对比分析,为工程师选择仿真工具提供了决策参考。

一只豌豆象的博客 1150

MPC8544E L1缓存与MMU寄存器深度解析与嵌入式实战配置

在嵌入式系统开发中,内存管理单元(MMU)和缓存是处理器高效访问内存、保障系统稳定性的核心硬件机制。MMU负责虚拟地址到物理地址的转换,并通过TLB(转换后备缓冲器)加速这一过程,是实现内存隔离和保护的基础。缓存作为处理器与主存之间的高速缓冲区,其架构、替换策略和一致性维护直接决定了数据访问的效率和正确性。理解并配置这些底层硬件对于实现极致的性能优化、满足实时性要求以及调试复杂的内存一致性问题具有关键的技术价值。本文聚焦于Freescale PowerQUICC III系列处理器MPC8544E,深入剖析其

anshaobiao6449的博客 358

基于Java+SpringBoot+微信小程序实现奶茶点单系统

再不用担心逢年过节的第一杯奶茶有没有人送了,制作一个奶茶点单系统自己当店主,开怀畅饮,一劳永逸。

商务合作 / 项目定制 / 学习交流。个人vx:lovely_wml 1万+

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

MPC8548E核心寄存器深度解析:L1缓存、MMU与调试寄存器实战指南

在嵌入式系统开发中,处理器核心寄存器是控制硬件行为的底层接口,直接决定了系统的性能、稳定性和可调试性。其原理在于,通过配置特定的寄存器位域,开发者可以精细控制缓存行为、内存映射和调试事件。掌握核心寄存器编程的技术价值在于,它能实现从提升缓存命中率、优化内存访问到进行高效硬件调试等一系列关键目标,是进行BSP开发、性能调优和深度故障诊断的基石。在基于PowerPC e500核心(如MPC8548E)的网络设备、工业控制器等应用场景中,对L1缓存配置寄存器、MMU的TLB管理寄存器以及调试控制寄存器的深入理解与

weixin_33912638的博客 399

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

自修改代码(Self Modifying Code)详解

自修改代码的简要历史自修改代码有很广泛的用途:1.在10到20年前使用SMC(自保护代码)保护应用程序是很难的,即使是用它来把编译的代码放到内存里.2.在90年代中期95/NT出现了,那时的程序员对在新的操作系统下如何保护应用程序感到迷惑.不知道该如何将保护措施移植到这个新的版本下.已经不可能再自由的访问内存,硬件,和一般的操作系统,所有以前学会的技巧不得不放弃,开始人们认为除了使用V

jia_xiaoxin的专栏 9251

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

上一篇: ESP定律手工脱壳步骤
下一篇: Haxdoors of the Kaspersky Antivirus 6/7
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值