好友
阅读权限25
听众
最后登录1970-1-1
|
【文章标题】: 不用Import REC 脱壳 之(二)EXE Stealth2.72篇
【文章作者】: qifeon
【使用工具】: OD、LordPE、
【操作平台】: Windows xp sp2
【作者声明】: 菜鸟初学脱壳,失误之处敬请诸位大侠赐教!
------------------------------------------------------------------------------
EXE Stealth2.72属于简单的加密壳,脱法不难,今天主要是学习下不用Import REC来脱。
OD载入,用俩次内存断点法到OEP看看。
004010CC 55 push ebp
004010CD 8BEC mov ebp, esp
004010CF 83EC 44 sub esp, 44
004010D2 56 push esi
004010D3 FF15 E4634000 call dword ptr [4063E4] ;kernel32.GetCommandLineA
004010D9 8BF0 mov esi, eax
004010DB 8A00 mov al, byte ptr [eax]
004010DD 3C 22 cmp al, 22
004010DF 75 1B jnz short 004010FC
004010E1 56 push esi
004010E2 FF15 F4644000 call dword ptr [4064F4]
004010E8 8BF0 mov esi, eax
004010EA 8A00 mov al, byte ptr [eax]
004010EC 84C0 test al, al
004010EE 74 04 je short 004010F4
004010F0 3C 22 cmp al, 22
数据窗口观察下IAT
004062E4 00153692 //iat起始部分
004062E8 00153697
004062EC 0015369C
004062F0 001536A1
004062F4 001536A6
---
00406358 00000000
0040635C 7C838B2F kernel32._lwrite
00406360 7C831EF5 kernel32.DeleteFileA
00406364 7C834EAC kernel32._lclose
部分IAT加密了,加密很简单,找个004062E4 处 00153692看看
00153692 - E9 0444C577 jmp ADVAPI32.RegQueryValueExA
00153697 - E9 6B35C577 jmp ADVAPI32.RegCloseKey
0015369C - E9 86B2C577 jmp ADVAPI32.RegSetValueExA
001536A1 - E9 62B7C577 jmp ADVAPI32.RegOpenKeyA
001536A6 - E9 5B10C677 jmp ADVAPI32.RegCreateKeyA
你可以写个简单脚本或利用Import REC等级1修复,就ok了。
不过我们要回到正题了,从iat起始部分004062E4往上看看
004062C8 00006D62
004062CC 00006D56
004062D0 00006D46
004062D4 00006D32
004062D8 00006D1A
004062DC 00006D84
看着眼熟,其实是输入表的INT部分,本来里面是指向API字符串的RVA,跟过去看大多是00,其实是被壳清除了。我们找到清除的代码,处理下就可以完美脱壳了。选IAT的一个地址,如40645c,下硬件访问断点,重载程序。大约6次,API真实地址出现。我们重载,5次后到达
0040D525 ^\75 F7 jnz short 0040D51E
0040D527 83C6 0C add esi, 0C
0040D52A 837E 04 00 cmp dword ptr [esi+4], 0
0040D52E ^ 75 E3 jnz short 0040D513
0040D530 33D2 xor edx, edx
0040D532 B8 05000000 mov eax, 5
单步跟一会,来到关键处,简单注释了下,水平太差,写不好。感兴趣的兄弟可以跟下。我后面主要讲俩点。
0040D580 53 push ebx ; ebx指向dll名
0040D581 FF95 12344000 call dword ptr [ebp+403412] ; 加载DLL
0040D587 85C0 test eax, eax
0040D589 0F84 16010000 je 0040D6A5
0040D58F 50 push eax
0040D590 F785 BE2F4000 0>test dword ptr [ebp+402FBE], 4
0040D59A 74 0E je short 0040D5AA
0040D59C 8D85 002D4000 lea eax, dword ptr [ebp+402D00]
0040D5A2 50 push eax
0040D5A3 8BC3 mov eax, ebx
0040D5A5 E9 48020000 jmp 0040D7F2 ; 跳向字符串清除位置
0040D5AA 5B pop ebx
0040D5AB 8B4E 08 mov ecx, dword ptr [esi+8] ; ecx为IID的OriginalFirstThunk
0040D5AE 0BC9 or ecx, ecx
0040D5B0 75 03 jnz short 0040D5B5
0040D5B2 8B4E 04 mov ecx, dword ptr [esi+4]
0040D5B5 038D B62F4000 add ecx, dword ptr [ebp+402FB6]
0040D5BB 8B56 04 mov edx, dword ptr [esi+4] ; edx为FirstThunk
0040D5BE 0395 B62F4000 add edx, dword ptr [ebp+402FB6]
0040D5C4 E9 C3000000 jmp 0040D68C
0040D5C9 F701 00000080 test dword ptr [ecx], 80000000 ; 是否序号取函数地址
0040D5CF 75 4B jnz short 0040D61C
0040D5D1 8B01 mov eax, dword ptr [ecx]
0040D5D3 83C0 02 add eax, 2
0040D5D6 0385 B62F4000 add eax, dword ptr [ebp+402FB6] ; 加基址
0040D5DC 50 push eax ; 加密前api名指针
0040D5DD E8 8BFFFFFF call 0040D56D ; 解密函数名字符串
0040D5E2 58 pop eax
0040D5E3 8BF8 mov edi, eax
0040D5E5 52 push edx
0040D5E6 51 push ecx
0040D5E7 50 push eax
0040D5E8 53 push ebx
0040D5E9 FF95 16344000 call dword ptr [ebp+403416] ; 取函数地址
0040D5EF 0BC0 or eax, eax
0040D5F1 75 07 jnz short 0040D5FA
0040D5F3 59 pop ecx
0040D5F4 5A pop edx
0040D5F5 E9 AB000000 jmp 0040D6A5
0040D5FA 59 pop ecx
0040D5FB 5A pop edx
0040D5FC 60 pushad
0040D5FD F785 BE2F4000 0>test dword ptr [ebp+402FBE], 4
0040D607 74 0E je short 0040D617
0040D609 8D85 6D2D4000 lea eax, dword ptr [ebp+402D6D]
0040D60F 50 push eax
0040D610 8BC7 mov eax, edi
0040D612 E9 DB010000 jmp 0040D7F2
0040D617 61 popad
0040D618 8902 mov dword ptr [edx], eax ; 真实地址填充iat
0040D61A EB 19 jmp short 0040D635
0040D61C 52 push edx
0040D61D 51 push ecx
0040D61E 8B01 mov eax, dword ptr [ecx]
0040D620 2D 00000080 sub eax, 80000000
0040D625 50 push eax
0040D626 53 push ebx
0040D627 FF95 16344000 call dword ptr [ebp+403416]
0040D62D 85C0 test eax, eax
0040D62F 74 74 je short 0040D6A5
0040D631 59 pop ecx
0040D632 5A pop edx
0040D633 8902 mov dword ptr [edx], eax
0040D635 F785 BE2F4000 2>test dword ptr [ebp+402FBE], 20
0040D63F 74 45 je short 0040D686
0040D641 83BD CA2F4000 0>cmp dword ptr [ebp+402FCA], 0
0040D648 74 14 je short 0040D65E
0040D64A 81FB 00000070 cmp ebx, 70000000
0040D650 72 08 jb short 0040D65A
0040D652 81FB FFFFFF77 cmp ebx, 77FFFFFF ; DLL模块基址与77FFFFFF比较
0040D658 76 0E jbe short 0040D668 ; 小于或等于则跳向iat加密,所以是传说中的Majic jmp
0040D65A EB 2A jmp short 0040D686
0040D65C EB 0A jmp short 0040D668
0040D65E 81FB 00000080 cmp ebx, 80000000
0040D664 73 02 jnb short 0040D668
0040D666 EB 1E jmp short 0040D686
0040D668 57 push edi ; 下面是IAT加密的一段代码,我们到达OEP后在IAT
0040D669 56 push esi ; 里看到的00153692等地址就是这里处理的
0040D66A 8DBD F4344000 lea edi, dword ptr [ebp+4034F4]
0040D670 8B77 04 mov esi, dword ptr [edi+4]
0040D673 8932 mov dword ptr [edx], esi
0040D675 2BC6 sub eax, esi
0040D677 83E8 05 sub eax, 5
0040D67A C606 E9 mov byte ptr [esi], 0E9
0040D67D 8946 01 mov dword ptr [esi+1], eax
0040D680 8347 04 05 add dword ptr [edi+4], 5
0040D684 5E pop esi
0040D685 5F pop edi
0040D686 83C1 04 add ecx, 4
0040D689 83C2 04 add edx, 4
0040D68C 8339 00 cmp dword ptr [ecx], 0 ; 比较是否结束
0040D68F ^ 0F85 34FFFFFF jnz 0040D5C9
0040D695 83C6 0C add esi, 0C
0040D698 837E 04 00 cmp dword ptr [esi+4], 0
0040D69C ^ 0F85 B4FEFFFF jnz 0040D556
0040D6A2 33C0 xor eax, eax
0040D6A4 40 inc eax
0040D6A5 83F8 01 cmp eax, 1
0040D6A8 74 02 je short 0040D6AC ; 所有IAT处理完则跳向这里,可以在这下个断
0040D6AA 61 popad
0040D6AB C3 retn
━━━━━━━━━━━━━━━━━━━━━━━━━━
主要阐述下俩个不用Import REC 脱这个壳的关键,一个是利用壳保存的源程序的IID数据构造新的IID组
0040D580 53 push ebx ; ebx指向dll名
0040D581 FF95 12344000 call dword ptr [ebp+403412]
跟踪下就知道,IAT处理的所使用的几个关键数据都在ESI指向的数据处,此时esi=0040D878
0040D878 92 65 00 00 F8 63 00 00 B4 61 00 00 B6 67 00 00 抏..鴆..碼..秅..
0040D888 5C 63 00 00 18 61 00 00 AC 6B 00 00 14 64 00 00 \c..a..琸..d..
0040D898 D0 61 00 00 10 6D 00 00 FC 62 00 00 B8 60 00 00 衋..m..黚..竊..
0040D8A8 94 6D 00 00 08 65 00 00 C4 62 00 00 F4 6D 00 00 攎..e..腷..鬽..
0040D8B8 E4 62 00 00 A0 60 00 00 00 00 00 00 00 00 00 00 鋌..燻..........
.
如 00006592是指向"SHELL32.dll"的RVA,000063f8是指向FirstThunk的RVA, 0061B4是指向OriginalFirstThunk
的RVA,所以壳把程序的IID三个主要部分保存下来,自己使用。我们可以拿来构建IID。
B4 61 00 00 00 00 00 00 00 00 00 00 92 65 00 00 F8 63 00 00 18 61 00 00 00 00 00 00 00 00 00 00
B6 67 00 00 5C 63 00 00 D0 61 00 00 00 00 00 00 00 00 00 00 AC 6B 00 00 14 64 00 00 B8 60 00 00
00 00 00 00 00 00 00 00 10 6D 00 00 FC 62 00 00 C4 62 00 00 00 00 00 00 00 00 00 00 94 6D 00 00
08 65 00 00 A0 60 00 00 00 00 00 00 00 00 00 00 F4 6D 00 00 E4 62 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
另外一个关键是DLL和API的字符串,不能让壳清除。字符串被壳加密保存,使用的时候解密,然后清除。出现的时间很短,大多数壳都是这样做的。
0040D5A5 E9 48020000 jmp 0040D7F2 ; 跳向字符串清除位置
0040D7F2 /EB 04 jmp short 0040D7F8
0040D7F4 |C600 00 mov byte ptr [eax], 0 ; 擦除解密字符串,nop
0040D7F7 |40 inc eax
0040D7F8 \8038 00 cmp byte ptr [eax], 0
0040D7FB ^ 75 F7 jnz short 0040D7F4
0040D7FD C3 retn
把0040D7F4 处的代码NOP掉即可。
0040D6A8 74 02 je short 0040D6AC 这里下断,然后运行。到 006592 + 00400000=00406592
指向的数据附近看看
00406592 53 48 45 4C 4C 33 32 2E 64 6C 6C 00 7F 00 45 78 SHELL32.dll..Ex
004065A2 69 74 50 72 6F 63 65 73 73 00 14 01 47 65 74 4D itProcess.GetM
004065B2 6F 64 75 6C 65 48 61 6E 64 6C 65 41 00 00 40 01 oduleHandleA..@
004065C2 47 65 74 53 74 61 72 74 75 70 49 6E 66 6F 41 00 GetStartupInfoA.
004065D2 D0 00 47 65 74 43 6F 6D 6D 61 6E 64 4C 69 6E 65 ?GetCommandLine
004065E2 41 00 74 01 47 6C 6F 62 61 6C 46 72 65 65 00 00 A.tGlobalFree..
004065F2 0A 01 47 65 74 4C 6F 63 61 6C 65 49 6E 66 6F 41 .GetLocaleInfoA
00406602 00 00 E1 02 6C 73 74 72 63 70 79 41 00 00 D6 01 ..?lstrcpyA..?
00406612 4D 75 6C 44 69 76 00 00 40 00 43 72 65 61 74 65 MulDiv..@.Create
00406622 46 69 6C 65 41 00 08 01 47 65 74 4C 61 73 74 45 FileA.GetLastE
00406632 72 72 6F 72 00 00 D8 02 6C 73 74 72 63 61 74 41 rror..?lstrcatA
OK,把新构建的IID组粘贴到406000处 。INT 完整,IAT填充什么就不管它了。此时DUMP,修正下OEP为10CC,
import table 地址为6000,优化下,还算完美。
EXE Stealth2.72.rar
(48.93 KB, 下载次数: 18)
|
|