内嵌补丁
“内嵌补丁”是“内嵌代码补丁”(Inline Code Patch)的简称。常用于对象程序经过运行时压缩处理或加密处理难以直接修改的情况。
原理是:在文件中另外设置被称为“洞穴代码”的“补丁代码”,EP代码解码后修改JMP指令,运行洞穴代码。在洞穴代码中执行补丁代码后再跳转到OEP处。
patchme程序
运行
点击确定
修改上述两处字符串即可。
调试
OD打开程序,右键查看字符串:可以看到都是经过加密的,无法找到指定字符串。
EP如下所示:
查看:
查看:
首先执行一个循环解密,解密的区域为4010F5-401248:
接下来,跳转到4010BD:
4010BD处继续循环解密,有两个解密循环,解密区域分别为401007-401085,4010F5-401248:
解密结束后RETN返回4010B5,4010B6处调用401039:
查看:
首先执行一个循环累加,将4010F5-401248按字节相加,接下来调用40108A。
40108A处执行解密循环,解密区域为:40124A-401279:
解密后返回,对刚才累加结果进行校验,校验通过跳转至401083,继续跳转至40121E,该处即为EOP:
查看EOP:可以看到EOP代码调用DialogBoxParamA()函数形成对话框:
DialogBoxParamA()函数共五个参数,其中第四个参数用来指出Dialog Box Procedure地址,即PUSH 4010F5指令所指的区域:
查看4010F5处:
可以看到这个区域存储着要修改的字符串以及弹出对应窗口的指令。
代码结构分析
整个函数结构如下:
函数执行流程可以概括为:
[EP Code]调用[Decoding Code]解密,按照[B]-[A]-[B]的顺序解码,之后运行解码后的[A]区代码,求[B]区校验和后对[C]区解码,判断校验和与预设值相符后跳转至OEP处弹出对话框。
“内嵌补丁”破解程序
01 补丁代码要设置在何处
有三种方法:设置到文件空白区域、扩展最后节区后设置、添加新节区后设置。
这里使用第一种方法。
第一节区文件大小为400,内存空间大小为280,仅有280被加载进内存,其余区域680-800处于未使用状态。
可以查看到:
注:VirtualSize=280并不意味着实际节区大小为20,实际应为Section Aligment倍数1000。在OD中也可以查看到,代码区域为401000-101FFF。
02 制作补丁代码
680对应进程VA为40128,由此开始创建“补丁代码“。
思路是:使用rep movs指令将设置好的字符串填充到原本的窗口字符串处。
03 执行补丁代码
接下来只需要将原本的JMP OEP指令修改为JMP 401280即可。
该指令位于401083处,即[A]区域,该区域解码操作是XOR 0X7,解码范围是401007-401085。
可以看到该处指令解码后:
解码前:由于解码范围到401085,后面两字节00没有进行解码。
因此要使指令解码后变为jmp 401280,需要变为“E9 F8 01”:
XOR 0X7,结果为“EE FF 06”,也就是说再将483-485区域修改为"EE FF 06"即可。
保存修改指令后的文件:右键-copy to executable-all modifications。
使用UltraEdit打开文件修改后保存:
04 结果确认
运行修改后的文件:
点击确定:
可以看到修改成功。
使用OD打开,查看401083地址处,可以看到已经变为了JMP 401080:
401080处也可以看到补丁代码执行后,字符串被修改并跳转到OEP处:
原本的字符串被成功覆盖: