一、工具及壳介绍
使用工具:Ollydbg,PEID,ImportREC,LoadPE,OllySubScript
未知IAT加密壳:
二、初步脱壳
尝试用ESP定律。
疑似OEP,VC6.0特征
进第一个CALL查看
确认是OEP。
OEP地址 = 47148b,RVA = 7148b
导入表函数信息出了问题。
查看IAT引用。
IAT表被加密。所以ImproREC才检测失败。
三、解析IAT加密方式
先API方面考虑。
壳修复exe IAT时,需要调用相关API,用LoadPE查看壳的导入表信息。
可见,推测,LoadLibrary 和 GetProAddress 是 隐藏调用 或 自我实现的。
采取硬件断点的方式:
在被加密的IAT表的最顶端,下硬件断点。
首次断下,执行代码是在内存地址上,说明壳是在自己申请的内存上执行代码的。
回溯分析函数。
进一步分析,确认是memcoy
查看memcoy参数,数据窗口跟随,发现是壳首次调用解密TEXT段。
改换在memcpy下断点,第二次断下。
第二次断下,是往IAT填RVA。
接下来断下的每一次,是往IAT填内存地址,内存地址数据窗口跟随。
IAT引用的顺序是这样的:
CALL à 壳的内存代码 à 真正的API
所以壳是在中间加了一层内存代码,并且内存代码里包含混淆花指令。
三、锁定IAT加密点
在memcpy进RVA后,依旧在IAT首部下硬件断点。
得知壳进行内存的操作后,顺便在API下断,VirtualAlloc
记录一下,一共申请了三次内存。
在硬件断点断下的地方。
由于汇编中掺杂着混淆和花指令,(具体见最后部分)。
确定目标:在壳修复IAT过程,寻 取出的函数地址 和 475000(往IAT填的内存地址)。
操作:多观察寄存器窗口 和 堆栈窗口
在当前指令下硬件断点,并开始单步步入(混淆代码的CALL F8会跑飞)
记录异样:
DLL基地址
查看地址,是遍历时的RVA
出现字符串,并在代码循环中逐步减少,疑似DLL INT取得的函数名。
查看地址,确认是。
按经验,在壳中,比较函数名的汇编代码有两种规律:
壳调用比较函数:在字符串完整或全没时,跟踪到返回指令,回溯分析函数和函数周围的函数调用。
壳采用比较循环:纯代码循环比较字符串。找到字符串比较条件的临界点,一般下一条是条件跳转指令,跳出循环。
由于代码是混淆过的,跳来跳出乱跳,很明显是属于比较循环。
比较字符串,如果采用rep的方式的话,结果一般会设置标志位跳转,再返回布尔值。
上面是TEST AL, AL,判断字符串是否结尾。壳可能进行长度记录,或是对整个字符串进行了特殊操作。
当比较结束时,跟踪结果,寻找函数地址 。
发现壳是对函数名进行哈希加密,并拿哈希值与 要寻函数的哈希值比较,来锁定函数。
下条件断点,当匹配正确后,下一步应该就是从DLL IAT取函数地址了
取出的函数地址:。
为后面OD脚本做准备:
跳过CALL,需在下一条指令下硬件断点:
记录下一条指令地址:0x002E08D5,RVA = 08D5
接下来找 把函数地址放进exe IAT的指令,观察475000开始的地址。
中间经过memcpy,应该是把内存代码往刚申请的内存上填,然后把内存地址赋给IAT。
寻到IAT的地址:
然后就是把内存地址往IAT地址上填了
为后面OD脚本做准备:
跳过CALL,需在下一条指令下硬件断点:
记录下一条指令地址:0x2E1A36,RVA =1A36
由于壳代码是在申请出来的内存上执行的,需要确定内存基址,就需要确定申请内存的指令。
寻到申请内存的指令:
为后面OD脚本做准备:
记录下一条指令地址:0x47A381。
四、OD脚本
前面的准备材料:
OEP 地址 = 0x47148b 得到申请内存地址:0x47A381 取IAT指令地址RVA:08D5 存IAT指令地址RVA:1A36
OD脚本:
//清除所有硬件断点 BPHWC //清除所有软件断点 BC //清除所有内存断点 BPMC //壳申请内存基地址 VAR BaseAddress //IAT地址 VAR IATAddress //得到申请内存基地址指令 BPHWS 47A381,"x" //OEP断点 BPHWS 47148b,"x" _LOOP: RUN //内存基地址判断 CMP eip,47A381 JNZ _Sign1 MOV BaseAddress,eax //取IAT指令 BPHWS BaseAddress+1A36,"x" //存IAT指令 BPHWS BaseAddress+08D5,"x" _Sign1: //取IAT判断 CMP eip,BaseAddress+1A36 JNZ _Sign2 MOV IATAddress,eax _Sign2: //存IAT的地方 CMP eip,BaseAddress+8D5 JNZ _Sign3 MOV [edx],IATAddress _Sign3: //OEP CMP eip,47148b JNZ _LOOP MSG "到达OEP"
再次Dump,成功解析。
成功运行。
五、混淆和花指令
代码中出现很多这样的指令:
call xxx xxx LEA ESP,DWORD PTR SS:[ESP+0x4] 实际上等价于jmp xxx
很多地方都是 混淆和花指令结合:
有关混淆和花指令详细,可以参考下一篇,下一个壳采用了大量的花指令和混淆:
手工脱壳之 PESpin加密壳【SHE链硬件反调试】【IAT重定向】【混淆+花指令】
个人总结:
附件:
KID