查看原文
其他

VMP导入表修复

coNg叶 看雪学苑 2022-07-01

本文为看雪论坛优秀文章
看雪论坛作者ID:coNg叶


1


VMP的IAT处理的几种情况


1、call ds:[xxx]

2、jmp ds:[xxx]

3、mov reg,ds:[xxx] + call reg

4、壳开始运行时填充到原来的导入表地址,不改变指令。

 
在1和2的情况下,原来都是FF 15或FF 25的6字节,vmp iat保护后,代码中也会变为1字节push/pop reg+5字节E8 call vmp0或5字节E8 call vmp0+1字节的的两种类型:
第一种类型:

原来:

保护后变为call vmp0 + 1字节,这里call 后面不全是填充的retn,有可能是其他字节:
第二种类型:

原来:

保护后变为push/pop reg + call vmp0:
 
在3的情况下,根据原来对寄存器是否为eax的赋值,也会有两种类型:

第一种:
5字节A1 开头的mov eax,ds:[xxx] 直接变为5字节的E8 call vmp0

第二种:
6字节8B 开头的mov reg,ds:[xxx],则变为5+1或1+5类型的E8 call vmp0
 
在4的情况下,原始的指令代码call ds:[xxx],jmp ds:[xxx],push ds:[xxx],mov reg,ds:[xxx]不改变,壳在启动时候直接填充函数地址到xxx。这类情况直接搜代码段FF??,8B??,A1????,获取到对应内存的函数地址进行修复。


2


获取call vmp0指令地址


这里我直接对text段进行爆搜E8字节,然后判断是否是call到的vmp0区段,这样筛选出一堆地址,分析时候发现call vmp0区段后是以nop 0x90开头,之后再通过unicorn模拟获取在retn指令时候的返回地址,如果返回地址是当前其他模块的导出函数,则认为是没加壳程序原来调用导入函数的地址。


3


判断哪种IAT处理类型


1、对于jmp ds:[xxx]类型,由于本身不会对堆栈进行操作,而保护后改为了E8 Call方式,所以vmp为了恢复堆栈在最后retn时候是采用retn 0x4方式,对应64位为retn 0x8。

2、对于mov reg,ds:[xxx]方式,通过unicorn模拟可以发现返回地址是在E8 call vmp0导致的+5或者+6位置,对应上面1+5和5+1情况,同时只会写入除了ESP外的一个寄存器。


3、对于call ds:[xxx]情况,返回时候是以retn返回,并且返回的地址不在调用call的地址附近。


4


判断5+1或者1+5或者只有5字节模式


判断这个的目的是确定还原代码开始的地址,最开始我这里是通过模拟得到retn时候的返回地址和E8 call的地址进行对比是+6还是+5从而判断是5+1还是1+5情况,但是这种方式对于jmp ds:[xxx]类型不能取到返回地址,对于mov reg,ds:[xxx]方式也会因为有5字节的mov eax,ds:[xxx]而判断错误。
 
后面分析的时候发现对于1+5情况使用push/pop reg + E8 call方式,模拟时候把除了esp外的寄存器值都初始化为0:

1、对于push reg +E8 call方式在 call内会通过pop reg来恢复call前因为push reg减少的堆栈,比如如下调用,模拟开始给的esp是0x1000,恢复堆栈的指令为:
pop ebx //恢复堆栈,同时ebx = 返回地址xchg ebx,[esp] //将返回地址和ebx值还原

所以此时会出现esp = 0x1004,并且堆栈为:

[0x1000+4] = 返回地址

[0x1000+8] = 0

2、pop reg+E8 call方式会在call中进行xchg reg,[esp],push reg操作,将原先保存在reg中的参数和返回地址互换,并且重新压入返回地址:
xchg edi,[esp] //执行后edi = 返回地址,[esp] = 之前的参数push edi //push 返回地址

所以当xchg指令执行后会出现esp = 0x1000,并且堆栈为:

[0x1000] = 0

[0x1000+4] = 0

 
3、其他除了5字节的mov eax,ds:[xxx]外都是E8 call + 1字节的情况。



5


代码


代码直接在这个基础上改动:

https://github.com/mike1k/VMPImportFixer


原代码把所有的指令都判断为FF 15类型,并且没有判断5+1、1+5和5的模式,以及mov reg,xxx类型和直接填充的类型。

 


6


参考


1、
https://github.com/mike1k/VMPImportFixer

2、使用模拟器进行x64驱动的Safengine脱壳+导入表修复(https://bbs.pediy.com/thread-249322.htm)

3、手动分析VMP加密的x64驱动导入表(https://bbs.pediy.com/thread-248812.htm)




 


看雪ID:coNg叶

https://bbs.pediy.com/user-home-753304.htm

*本文由看雪论坛 coNg叶 原创,转载请注明来自看雪社区






# 往期推荐

1. 初探Windows调试原理和反附加手段

2. 破解某抢票软件的VPN抓包

3.祥云杯2021 Windows R0题 Rev_APC

4. Android APK的加固方法

5. HITB CTF 2018 gundam分析

6. CVE-2010-2883漏洞分析与复现



公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com



球分享

球点赞

球在看



点击“阅读原文”,了解更多!

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存