欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]自己动手修复ImpREC的Bug

[原创]自己动手修复ImpREC的Bug


--通过OD给ImpREC打补丁:
(在一次给inc2l.exe脱壳的作业中发现的问题)
用来测试BUG的程序:RadASM中Tools的inc2l.exe
首先用OD加载,发现他是一个加壳的程序,
 
入口有保存环境的代码(一般的加壳程序都会保存环境):
push eax  单步步过这条指令,
找到栈顶,数据窗口跟随
 
然后下硬件访问断点,因为它保存了环境,势必会在他恢复代码之后还原环境的,
 
然后就可以等着他来了,放开程序跑,F9
第一次来到是一个0x7C…开头的地址,可能是系统Dll的代码略过,继续F9
 
直到断在主程序的地址
 
经过两次F9后顺利来到了主程序的代码,然后把代码往下翻,看哪里有jmp,因为一般还原完代码都会有个jmp跳回OEP,不远处就发现了有个jmp ,选中该行F4程序跑到0x40AC1E处
 
 
发现代码已经被还原了,OD分析出是模块入口点。
F7单步过去,
 
然后右键脱壳,点脱壳,保存文件为dump.exe
 
一运行发现崩了,因为他这个程序的导入表在程序加载到内存的时候被抹掉了,这里用到impREC来修复导入表
 
 
因为这个程序是要通过手动定位IAT信息通过反推获取导入表信息(程序自带的自动查找IAT不准确),所以需要借助OD手动查看IAT表的起始位置和大小。在OD里面随便选择一个API点击一下,然后数据窗口跟随,选择数据窗口中跟随地址 
 
再在数据窗口选择长型地址,就发现API名称跟地址都出来了
 
再通过肉眼过滤,一般API都在很大的地址,所以得到从:
 开始到
 
大小0x1F0 
然后在ImpREC里填RVA:0x8050,Size:0x1F0,然后点获取导入表,发现导入表函数都是有效的,然后点修复。
 
选择刚保存的那个dump文件,确定
 
生成了一个 dump_.exe文件
然后打开发现这次不是访问内存错误了,直接是报应用程序初始化失败。到这里之前不会解析PE出错,只有用了ImpREC之后才出了错,然后我们来分析PE格式 
 
用WinHex打开dump_exe,手工分析PE结构,由于刚才我们修复转存文件的时候ImpREC添加了一个新节,不知道是不是节区文件的问题,首先看是不是没有修改节的个数,发现是4个节,对照一下是对的。
 
经过仔细对比之后,发现最后添加了一个节区之后,PE头部的总大小变成了0x218,然后ImpREC并没有修改PE中的SizeOfHeaders的大小0x200。现在我们通过winHex手动修改他的值为0x218保存,然后程序正常运行了。
思路:
我们要修改PE中的SizeOfHeaders要在写文件之前,前面我们看到源程序有修改PE的SizeOfImage的操作,所以可以找到源程序修改SizeOfImage的代码区域,然后在那附近找到合适的代码地址覆盖jmp跳到源程序没有使用的内存空间添加我们修改SizeOfHeaders的代码,修改操作完成后添加jmp覆盖的指令再jmp回去。
如何定位该区域呢?首先我们知道程序要创建并写文件,所以会调用CreateFileA,WriteFile.所以我们可以通过API的参数知道写文件的Buffer在哪里,然后再通过给SizeOfImage的4字节设访问断点可以定位源程序修改PE的SizeOfImage代码的地址了。
LAB:
用OD打开ImpREC程序,F9让他跑,选择inc2l.exe的进程,填写RVA, Size,获取导入表,然后点击修复转存文件,先不要点保存,回到OD右键查找当前模块的名称,找到CreateFileA右键设置在每个参考上设置断点,然后回到ImpREC选择Dump文件点保存,
 
OD断了下来,查看堆栈窗口,发现不是我们想要的dump_.exe
   
放开跑,第二次是创建我们想要的dump_.exe
   
跑到这里肯定会有写文件的操作,再下一个WriteFile断点。
然后F9,写文件的时候触发断点,查看堆栈窗口的buffer,
数据窗口跟随,他写入的大小是整个文件的大小, 
   
   
从这里可以印证添加了一个节,源程序修改了SizeOfImage,找到该程序操作这块内存的位置下访问断点,从而定位代码
   
通过对PE格式的分析,定位到0XC5CDD0,右键下断点,一个DWORD长度,然后重新跑程序,操作从LAB开始。
之后势必会再访问这个地址的时候断下来, F9的同时观察数据窗口PE数据是不是被读到内存中来了,如果没有,继续F9。之后再0x42CA12的地址又触发了断点,发现他的上一条指令是就修改SizeOfImage
   
这一切都是发生在写文件之前的,所以我们可以在这附近找一个合适的地方插jmp跳到别的地址添加代码,然后修复覆盖的指令再jmp回来。一个jmp指令对应的机器码是5个字节,我们只要找到一条指令大于等于5字节就可以了。刚好在0x42CA0F的下一条指令是6个字节,可以在这里插jmp,首先记下这条指令MOV EAX, DWORD PTR SS:[ebp+420],因为插入自己的代码之后还是要还原原指令的(我们只能添加代码,不能修改原有的代码),到代码的最后面找一块空白的地方,
  
0x448930 修改这里为jmp过去的地址,于是选中0x42CA12修改汇编代码:
jmp 0x448930
    
  
TAB:-----从这里跳过,请看分割线以下-------2015.9.16
然后:
1.再0x448930的地址添加汇编代码修改SizeOfHeaders:
ADD DWORD PTR DS:[EAX+3C],28
每次都加一个节的大小0x28.
2.保存jmp覆盖的原指令:
MOV EAX,DWORD PTR SS:[EBP+420]
3.修改完之后要跳回去继续执行原来的代码,添加:
jmp 0x42CA18
 
然后全选复制到可执行文件,再保存为ImpREC_fix.exe.到这里已经修复完了。
-------------------------------分割线---------------------------------
2015_9_16修改:
由于上次是用了OllyDump的时候没有取消他的默认选项重建导入表,但是OD并没有修复成功,又多出了一个节表。
然后我用ImpREC再次修复IAT的时候又多添加了一个节表,然后就出现了我遇到的问题......
我取消了重建输入表选项,之后用ImpREC修复就没有问题了。
这里多谢“Kisesy”的提醒。
然后我又想给打个补丁,让其在Dump出.exe后无论添加多少个节表用ImpREC修复都不会出错。
分析:
可能是ImpREC修复的时候没有检查Dump出来的文件有多少个节,直接在后面添加一个节,然后写导入表信息。我们可以在其写dump_.exe文件之前,算一下内存中dump文件的节表个数,写入SizeOfHeads就行了。
修复:
从上次最后修改补丁的地方开始.(TAB)
覆盖原来的修改代码加入如下汇编代码(经过分析PE格式写出的,望大家指教):

    pushad									;保存环境
    lea eax, dword ptr ss:[eax+0x98]				;获取MZ头地址
    mov ecx, dword ptr ds:[eax+0x3C]
    lea edx, dword ptr ds:[eax+ecx]				;获得PE标志地址	IMAGE_NT_HEADERS
    lea esi, dword ptr ds:[edx+0x18]
    xor ecx, ecx
    mov cx, word ptr ds:[edx+0x14]			
    add esi, ecx								;求得节表的首地址
    mov cx, word ptr ds:[edx+6]					;节表个数:edx+8
    imul ecx, 0x28							;求出当前的节表总大小
    add ecx, 0x28							;求出修复后的节表总大小
    add esi, ecx								;节表尾地址
    sub esi, eax								;节表尾减MZ头求出SizeOfHeaders
    mov dword ptr ds:[edx+0x54], esi				;复制SizeOfHeaders到Buffer			
    popad									;还原环境
    MOV EAX,DWORD PTR SS:[EBP+420]			;修复jmp覆盖的代码
    jmp 0042CA18


修复的ImpREC上传了
然后,我也是菜鸟一枚(还在科锐学习...),有什么地方写的不对可以指出来,大家可以互相交流~
一直都是潜水党.第一次发帖,求通过

上传的附件 image001.png
image003.png
image005.png
image007.png
image009.png
image011.png
image013.png
image015.png
image017.png
image019.png
image021.png
image023.png
image025.png
image027.png
image029.png
image031.png
image033.png
image035.png
image037.png
image039.png
image041.png
image043.png
image045.png
image047.png
image049.png
image051.png
image053.png
image055.png
image057.png
image059.png
image061.png
image063.png
9_16.png
ImportREC_fix_2015_9_16.rar

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功