逆向工程核心原理--->内嵌补丁
参考:https://blog.csdn.net/ski_12/article/details/80670045
一 分析程序
1.1
此处循环,是对4010F5~401248的区域解密,对每一个字符和0x44异或。继续跟踪进入4010BD。
1.2
跟进4010BD函数后,发现两个循环。第一个仍然是对401007地址处的区域解密,循环7F次,所以是401007~401085的每一个字符和0x7异或。
第二个仍然是对4010F5~401248区域解密,每个字符和0x11异或。说明这4010F5~401248区域被加密了两次,所以此处解密两次。
1.3
继续往下分析,进入401039地址处的函数。上来就是一个循环,是对4010F5区域的字符的值,没每个字节,加到edx里面。然后到下面和0x31EB8DB比较。如果被修改过,直接跳向错误的地方。在401083处有一个跳向OEP的跳转。
1.4
来到OEP之后因为被解密过后的代码会被视为数据,而不是指令,所以我们需要点分析代码,就变为正常的代码了。开头就是GetModuleHandle,获取一个应用程序或动态链接库的模块句柄。只有在当前进程的场景中,这个句柄才会有效。说明下面一个DialogBoxParmA的四个参数(IpDialogFunc:指向对话框过程的指针
)是4010F5。跟踪到之后发现那些我们要修改的字符串了。
二 内嵌补丁
由上述分析可知,实际要打补丁的字符串都保存在经过两次加密的区域。
整个的操作过程为:先在文件适合的位置插入洞穴代码,该补丁代码更改字符串并通过JMP指令跳转至OEP处,再在004010F5~00401248区域将JMP OEP指令修改为JMP补丁代码。
当补丁代码较少时,使用第一种方法即在文件空白的区域插入补丁代码。
2.1
首先查看.text段的大小。
可以看到,第一节区的在磁盘文件的大小为400,映射到内存的大小为280,即第一节区从磁盘文件加载到内存后有大小为180(RAW 680~800区域 > RVA 1280~1400区域)的区域并未使用,该区域为空白区域(NULL-Padding),可以用来填写补丁代码。另外需要注意的是,1E4的属性值中添加的IMAGE_SCN_MEM_WRITE(可写属性),在程序进行解码操作时,必须在该节区头添加可写属性以获得相应内存的可写权限,否则会引发非法访问的异常。对于一个普通的PE文件,其代码节是无写权限的,但是压缩工具、Crypter等文件的代码节都有可写权限。
注意,内存中的节区大小为280,但实际节区的内存大小并非280,而是以Section Alignment的整数倍扩展,即实际大小为1000。
2.2
首先写洞穴代码,最后记得跳转到OEP处。
在跳向补丁代码的地方,因为此处的代码为和0x7解密之后的。即 E9 F8 01应该是我们修改经过解密之后的值,那解密之前呢?因为一个数的两次异或会回到本身。所以
E9 xor 7= EE F8 xor 7= FF 01 xor 7= 6
则EE FF 6 即为解密前的数据,所以我们应该修改此值。
2.3
首先是保存洞穴代码,复制到可执行文件,退出OD。在十六进制编辑器中修改上面的数据。
而文件中实际的加密形态为(VA 00401083 > RVA 1083 > RAW 483):
在此483处我们看到我们在上一步修改的值了,这个E9 F8 01 我们已经知道是解密后的,
所以修改为 EE FF 6 ,然后保存文件。
2.4 运行查看效果。