OD学习记录19.05.08

修复IAT

首先第一步定位OEP,用OD加载CRACKME.UPX。
OD学习记录19.05.08
使用ESP定律来定位OEP,现在我们停在了入口点处,单击F7键执行PUSHAD。
OD学习记录19.05.08
在ESP寄存器值上面单击鼠标右键选择-数据窗口中跟随。
就可以在数据窗口中定位到刚刚PUSHAD指令保存到堆栈中的寄存器环境了,选中前4个字节,通过单击鼠标右键选择Breakpoint-Hardware,on access-Dword给这4个字节设置硬件访问断点。
OD学习记录19.05.08
运行起来,马上就断在了JMP OEP指令处。
OD学习记录19.05.08
直接按F7键单步到OEP处。
OD学习记录19.05.08
处于OEP处,原程序区段已经解密完毕,我们现在可以进行dump了。使用工具PE TOOLS来进行dump。因为没有修复IAT是不能够运行的。需要修复IAT,用到一个工具,名字叫做Import REConstructor,不要关闭OD,将让其断在OEP处,Import REConstructor需要用到它。运行Import REConstructor,定位到CRACKME UPX所在的进程。如何定位IAT的起始位置和结束位置呢?当前该CRACKME UPX进程停在了OEP处,此时壳已经将导入表破坏了,IID项的第四个字段为动态库名称字符串的指针,第五个字段为其对应IAT项第一个元素的地址,这些已经被壳破坏了,我们需要通过其他方式来定位。知道API函数的调用通常是通过间接跳转或者间接CALL来实现的。即JMP [?] or CALL [?]
OD学习记录19.05.08
OD提示调用的是Kernel32.dll中的GetModuleHandleA,是个间接跳转,我们选中这一行,单击鼠标右键选择-跟随。
OD学习记录19.05.08
这里定位到获取IAT中函数地址的跳转表,这里就是该程序将要调用到的一些API函数,这些跳转指令的都是以机器码FF 25开头的,有些教程里面说直接搜索二进制FF 25就可以快速的定位该跳表。通过定位某个API函数的调用处,然后Follow到跳表是这种方式才是有效的。这里我们看到JMP [403238]。
OD学习记录19.05.08
403238是IAT的其中一个元素,里面保存的是GetModuleHandleA这个API函数的入口地址,dump出来的程序的IAT部分跟这里是一样的。
OD学习记录19.05.08
直接上下拉,我们知道属于同一个动态库的API函数地址都是连续存放的,不同的动态库函数地址列表是用零隔开的。IAT开始于403184。发现结束时是以76····的形式结束所以,
OD学习记录19.05.08
后面全是零了,所以40328C是IAT的结束位置。
OD学习记录19.05.08
最后就是用工具修复IAT。
Import REConstructor重建IAT需要三项指标:
1)IAT的起始地址,这里是403184,减去映像基址400000就得到了3184(RVA:相对虚拟地址)。
2)IAT的大小
IAT的大小 = 40328C - 403184 = 108(十六进制)
3)OEP = 401000(虚拟地址)- 映像基址400000 = 1000(OEP的RVA)。
等待修复后导出文件即完成IAT修复。