本来一直对upx3.0以后加密壳挺畏惧的,其逻辑看起来挺简单的,有想逆一把的想法,但是都没实施,今天又遇到了,没法,太急,去google了一下,找到几篇资料
但是年代都挺久远的,看到[1]中直接esp定律就脱了,有点不信,就试了试,靠,居然可以,只能表示,实践是检验真理的唯一标准。
#1. 查壳
[!] UPX 3.05 compressed !
查出来是3.05,也不知道是不是误报,比[1]中版本高了点,所以也就是尝试尝试esp定律拖一下
#2. 脱壳
OD加载(是个dll,通过load.exe加载),在DllMain断下,看到熟悉的pushad,感觉方法可能靠谱了1
2
3
4103432E0 > 807C24 08 01 cmp byte ptr ss:[esp+0x8],0x1
103432E5 0F85 9D0B0000 jnz xxx.10343E88
103432EB 60 pushad
103432EC BE 00C02C10 mov esi,xxx.102CC000
f8到103432EC ,在数据窗口显示esp值,然后右键下了个硬件访问断点(其实以前尝试过,但是下的是内存访问断点,失败了,也不知道是不是这个原因,待会儿试试)。接着F9,断在了下面的代码中,看不出啥,就有个 jmp xxx.100C3C71,地址离当前地址还算较远,可能是另一个节1
2
3
4
5
610343E7B 8D4424 80 lea eax,dword ptr ss:[esp-0x80] //这个就是先前pushad压入的吗??
10343E7F 6A 00 push 0x0
10343E81 39C4 cmp esp,eax
10343E83 ^ 75 FA jnz short xxx.10343E7F //循环了多次,F4直接到10343E85 ,应该是在清理堆栈吧??
10343E85 83EC 80 sub esp,-0x80
10343E88 - E9 E4FDD7FF jmp xxx.100C3C711
2100C3C71 /E9 CA371100 jmp xxx.101D7440
100C3C76 |E9 15311700 jmp xxx.10236D90 ; jmp 到 kernel32.UnlockFile
单步到jmp,F8跟到其代码中,看到了熟悉的一段入口代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16101D7440 8BFF mov edi,edi
101D7442 55 push ebp
101D7443 8BEC mov ebp,esp
101D7445 837D 0C 01 cmp dword ptr ss:[ebp+0xC],0x1
101D7449 75 05 jnz short xxx.101D7450
101D744B E8 32DFEEFF call xxx.100C5382
101D7450 8B45 10 mov eax,dword ptr ss:[ebp+0x10]
101D7453 50 push eax
101D7454 8B4D 0C mov ecx,dword ptr ss:[ebp+0xC]
101D7457 51 push ecx
101D7458 8B55 08 mov edx,dword ptr ss:[ebp+0x8]
101D745B 52 push edx
101D745C E8 1F000000 call xxx.101D7480
101D7461 83C4 0C add esp,0xC
101D7464 5D pop ebp
101D7465 C2 0C00 retn 0xC
通过堆栈参数,进一步确认了下,这是DllMain函数1
2
3
40006F880 7C92118A 返回到 ntdll.7C92118A
0006F884 10000000 xxx.10000000
0006F888 00000001
0006F88C 00000000
然后在101D7440地址,尝试dump,成功之后在检测壳信息
[CompilerDetect] -> Visual C++ 9.0 (Visual Studio 2008)
应该是脱壳成功了,但是iat没有修复,先ida看看是否需要修复
#3. 修复
如果需要修复,使用importRec工具
找到进程,选择目标dll,然后填入OEP,修复即可
#4. 参考
[1]: http://bbs.pediy.com/showthread.php?t=44125 【原创】手脱 UPX3.0
[2]: http://bbs.pediy.com/showthread.php?t=140312 【原创】UPX3.03脱壳机-学习版[代码更新]