qifeon 发表于 2010-9-20 00:05

不用Import REC 脱壳 之(二)EXE Stealth2.72篇

【文章标题】: 不用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       ;kernel32.GetCommandLineA
004010D9    8BF0            mov   esi, eax
004010DB    8A00            mov   al, byte ptr
004010DD    3C 22         cmp   al, 22
004010DF    75 1B         jnz   short 004010FC
004010E1    56            push    esi
004010E2    FF15 F4644000   call    dword ptr
004010E8    8BF0            mov   esi, eax
004010EA    8A00            mov   al, byte ptr
004010EC    84C0            test    al, al
004010EE    74 04         je      short 004010F4
004010F0    3C 22         cmp   al, 22
数据窗口观察下IAT
004062E400153692                  //iat起始部分
004062E800153697
004062EC0015369C
004062F0001536A1
004062F4001536A6
---
0040635800000000
0040635C7C838B2Fkernel32._lwrite
004063607C831EF5kernel32.DeleteFileA
004063647C834EACkernel32._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往上看看

004062C800006D62
004062CC00006D56
004062D000006D46
004062D400006D32
004062D800006D1A
004062DC00006D84

看着眼熟,其实是输入表的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 , 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          ; 加载DLL
0040D587    85C0            test    eax, eax
0040D589    0F84 16010000   je      0040D6A5
0040D58F    50            push    eax
0040D590    F785 BE2F4000 0>test    dword ptr , 4
0040D59A    74 0E         je      short 0040D5AA
0040D59C    8D85 002D4000   lea   eax, dword ptr
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          ; ecx为IID的OriginalFirstThunk
0040D5AE    0BC9            or      ecx, ecx
0040D5B0    75 03         jnz   short 0040D5B5
0040D5B2    8B4E 04         mov   ecx, dword ptr
0040D5B5    038D B62F4000   add   ecx, dword ptr
0040D5BB    8B56 04         mov   edx, dword ptr          ; edx为FirstThunk
0040D5BE    0395 B62F4000   add   edx, dword ptr
0040D5C4    E9 C3000000   jmp   0040D68C
0040D5C9    F701 00000080   test    dword ptr , 80000000      ; 是否序号取函数地址
0040D5CF    75 4B         jnz   short 0040D61C
0040D5D1    8B01            mov   eax, dword ptr
0040D5D3    83C0 02         add   eax, 2
0040D5D6    0385 B62F4000   add   eax, dword ptr       ; 加基址
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          ; 取函数地址
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 , 4
0040D607    74 0E         je      short 0040D617
0040D609    8D85 6D2D4000   lea   eax, dword ptr
0040D60F    50            push    eax
0040D610    8BC7            mov   eax, edi
0040D612    E9 DB010000   jmp   0040D7F2
0040D617    61            popad
0040D618    8902            mov   dword ptr , eax             ; 真实地址填充iat
0040D61A    EB 19         jmp   short 0040D635
0040D61C    52            push    edx
0040D61D    51            push    ecx
0040D61E    8B01            mov   eax, dword ptr
0040D620    2D 00000080   sub   eax, 80000000
0040D625    50            push    eax
0040D626    53            push    ebx
0040D627    FF95 16344000   call    dword ptr
0040D62D    85C0            test    eax, eax
0040D62F    74 74         je      short 0040D6A5
0040D631    59            pop   ecx
0040D632    5A            pop   edx
0040D633    8902            mov   dword ptr , eax
0040D635    F785 BE2F4000 2>test    dword ptr , 20
0040D63F    74 45         je      short 0040D686
0040D641    83BD CA2F4000 0>cmp   dword ptr , 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
0040D670    8B77 04         mov   esi, dword ptr
0040D673    8932            mov   dword ptr , esi
0040D675    2BC6            sub   eax, esi
0040D677    83E8 05         sub   eax, 5
0040D67A    C606 E9         mov   byte ptr , 0E9
0040D67D    8946 01         mov   dword ptr , eax
0040D680    8347 04 05      add   dword ptr , 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 , 0      ; 比较是否结束
0040D68F^ 0F85 34FFFFFF   jnz   0040D5C9
0040D695    83C6 0C         add   esi, 0C
0040D698    837E 04 00      cmp   dword ptr , 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

跟踪下就知道,IAT处理的所使用的几个关键数据都在ESI指向的数据处,此时esi=0040D878

0040D87892 65 00 00 F8 63 00 00 B4 61 00 00 B6 67 00 00抏..鴆..碼..秅..
0040D8885C 63 00 00 18 61 00 00 AC 6B 00 00 14 64 00 00\c..a..琸..d..
0040D898D0 61 00 00 10 6D 00 00 FC 62 00 00 B8 60 00 00衋..m..黚..竊..
0040D8A894 6D 00 00 08 65 00 00 C4 62 00 00 F4 6D 00 00攎..e..腷..鬽..
0040D8B8E4 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 , 0                ; 擦除解密字符串,nop
0040D7F7   |40            inc   eax
0040D7F8   \8038 00         cmp   byte ptr , 0
0040D7FB^ 75 F7         jnz   short 0040D7F4
0040D7FD    C3            retn

把0040D7F4 处的代码NOP掉即可。
0040D6A8    74 02         je      short 0040D6AC    这里下断,然后运行。到   006592 +00400000=00406592
指向的数据附近看看

0040659253 48 45 4C 4C 33 32 2E 64 6C 6C 00 7F 00 45 78SHELL32.dll..Ex
004065A269 74 50 72 6F 63 65 73 73 00 14 01 47 65 74 4DitProcess.GetM
004065B26F 64 75 6C 65 48 61 6E 64 6C 65 41 00 00 40 01oduleHandleA..@
004065C247 65 74 53 74 61 72 74 75 70 49 6E 66 6F 41 00GetStartupInfoA.
004065D2D0 00 47 65 74 43 6F 6D 6D 61 6E 64 4C 69 6E 65?GetCommandLine
004065E241 00 74 01 47 6C 6F 62 61 6C 46 72 65 65 00 00A.tGlobalFree..
004065F20A 01 47 65 74 4C 6F 63 61 6C 65 49 6E 66 6F 41.GetLocaleInfoA
0040660200 00 E1 02 6C 73 74 72 63 70 79 41 00 00 D6 01..?lstrcpyA..?
004066124D 75 6C 44 69 76 00 00 40 00 43 72 65 61 74 65MulDiv..@.Create
0040662246 69 6C 65 41 00 08 01 47 65 74 4C 61 73 74 45FileA.GetLastE
0040663272 72 6F 72 00 00 D8 02 6C 73 74 72 63 61 74 41rror..?lstrcatA

OK,把新构建的IID组粘贴到406000处 。INT 完整,IAT填充什么就不管它了。此时DUMP,修正下OEP为10CC,
import table 地址为6000,优化下,还算完美。

Hmily 发表于 2010-9-20 00:44

一个系列,这个也加精鼓励!

hixiaosheng 发表于 2010-9-20 01:12

不错、加分~

zapline 发表于 2010-9-20 08:48

:funk:eweqw用IREC都不会脱
学习

恋流沙 发表于 2010-9-20 09:22

收藏了。。

65302666 发表于 2010-9-20 11:44

学习学习。。。。发觉要学的东西好多。。谢谢大牛的分析

新鲜阳光 发表于 2010-9-20 13:29

学习了

楼主很厉害的说

qifeon 发表于 2010-9-20 17:50

用IREC都不会脱
学习
zapline 发表于 2010-9-20 08:48 http://www.52pojie.cn/images/common/back.gif


    汗!正期待小z大菜鸟的写壳第二系列呢。

qwerqwer89 发表于 2010-9-21 12:26

太牛了。我是真的好佩服
.

abacd1 发表于 2010-9-22 05:51

IAT填充什么就不管它了。此时DUMP,修正下OEP为10CC
原来 终于明白了
页: [1] 2
查看完整版本: 不用Import REC 脱壳 之(二)EXE Stealth2.72篇