【作者声明】:没什么技术含量,失误之处敬请诸位大侠赐教
【软件名称】: 程序实例见附件
【调试环境】:WinXP sp 2、OD、PEiD、LordPE、ImportREC 

高手就飘过吧,接触脱壳有一段时间了,对于脱壳有一些感悟,愿与大家一起分享,对于一般的加密壳,修复正确的iat一般
都是这两种方法,一是在到达oep之前就改magic jump 或者 patch code修复;二是 到达oep之后,查看加密之后的函数调用,
根据其解密的方式编写代码还原,然后IR修复。下面我以UltraProtect加壳的记事本为例,其实这个壳不用这么复杂的,我只是
借这个实例说一下这两种方法,下面实例分析一下:

第一种方法:在到达oep之后修复 
这种方法主要是先到达oep,可以用两次内存断点法,最后一次异常法,等等。。。当然了有stolen code 等其他的保护方式要另当别论了,小菜我水平太烂

不忽略内存访问异常
0040D000 >  60                   pushad                                              ;加壳后程序入口
0040D001    F9                    stc                                                ;F8一下,命令行下断:hr esp  主要是找stolen code,不在本文讨论之列 F9 运行
0040D002    87D6                 xchg esi,edx
0040D004    72 03                jb short UltraPro.0040D009
0040D006    73 01                jnb short UltraPro.0040D009
0040D008    7A 81                jpe short UltraPro.0040CF8B
0040D00A    F7                   ???                                                 ; Unknown command
0040D00B    4A                   dec edx
0040D00C    C49F 9DE80100  es ebx,fword ptr ds:[edi+1E89D] ; Modification of segment register
0040D012    0000                 add byte ptr ds:[eax],al
0040D014    E8 83C40466      call 6645949C
0040D019    D3EA                 shr edx,cl


00415719    CD 01                int 1                                               ;到达此处
0041571B    40                    inc eax                                            ;F2下断 shift + F9 运行 断在此处    取消F2断点 F9
0041571C    40                   inc eax     
0041571D    0BC0                or eax,eax
0041571F    75 05                jnz short UltraPro.00415726
00415721    90                   nop
00415722    90                   nop
00415723    90                   nop
00415724    90                   nop
00415725    61                   popad
00415726    33C0                 xor eax,eax
00415728    64:8F00              pop dword ptr fs:[eax]
0041572B    58                   pop eax
0041572C    60                   pushad
0041572D    E8 00000000          call UltraPro.00415732


004254C9    55                    push ebp                                          ;stolen code 1
004254CA    8BEC                mov ebp,esp                                         ;stolen code 2
004254CC    83EC 44            sub esp,44                                           ;stolen code 3
004254CF    60                    pushad
004254D0    60                    pushad
004254D1    E8 00000000     call UltraPro.004254D6


此时取消开始下好的硬件    单步F7走到004254d6 对code段下断然后F9 运行 来到这里:
004010D2     56                    push esi
004010D3     FF15 E4634000   call dword ptr ds:[4063E4]                              ;  UltraPro.0040D1BA
004010D9     8BF0                  mov esi,eax
004010DB     8A00                  mov al,byte ptr ds:[eax]
004010DD     3C 22                 cmp al,22
004010DF     75 1B                 jnz short UltraPro.004010FC
004010E1     56                    push esi
004010E2     FF15 F4644000    call dword ptr ds:[4064F4]                             ; UltraPro.0040D4C6

补上stolen code 如下:
004010CC     55                    push ebp                                          ;可以在这里新建起源 再dump 不建也可以
004010CD     8BEC                  mov ebp,esp
004010CF     83EC 44               sub esp,44
004010D2     56                    push esi
004010D3     FF15 E4634000    call dword ptr ds:[4063E4]                             ; UltraPro.0040D1BA
004010D9     8BF0                  mov esi,eax
004010DB     8A00                  mov al,byte ptr ds:[eax]
004010DD     3C 22                 cmp al,22
004010DF     75 1B                 jnz short UltraPro.004010FC
004010E1     56                    push esi
004010E2     FF15 F4644000   call dword ptr ds:[4064F4]                             ; UltraPro.0040D4C6


LoadPE转存它

我们看到iat加密了 
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 ds:[4063E4]                            ;  这里enter键 跟进 
004010D9     8BF0                  mov esi,eax
004010DB     8A00                  mov al,byte ptr ds:[eax]
004010DD     3C 22                 cmp al,22
004010DF     75 1B                 jnz short UltraPro.004010FC
004010E1     56                    push esi
004010E2     FF15 F4644000  call dword ptr ds:[4064F4]                             ; UltraPro.0040D4C6
结果如下:
0040D1BA     68 DD43C07E           push 7EC043DD                                   ;在这里我们右键 此处新建eip
0040D1BF     813424 E06C4102       xor dword ptr ss:[esp],2416CE0
0040D1C6     C3                    retn                                            ;走到这里出现        返回到 7C812F3D (kernel32.GetCommandLineA)
说明正确的函数已被解出 

同样的方法我们可以看看其它函数的解密方式,发现都是这样的,我们开始patch 代码修复吧,在patch之前我们确定一下加密函数的范围,打开IR选中进程,oep 填 10cc, 获取输入表,显示无效的



我们可以看到加密的iat有两段 635c ~63F0, 6414 ~6500,找片空地写下如下代码:

    
以上面的例子:
0040D1BA     68 DD43C07E           push 7EC043DD                               
0040D1BF     813424 E06C4102       xor dword ptr ss:[esp],2416CE0
0040D1C6     C3                            retn 
说明一下这段代码: 
00404FD4    C7C0 14644000        mov eax,UltraPro.00406414                          ;加密函数开始的地址,另外一段将这里改成0040635c
00404FDA    8B18                 mov ebx,dword ptr ds:[eax]
00404FDC    43                   inc ebx
00404FDD    90                   nop
00404FDE    8B0B                 mov ecx,dword ptr ds:[ebx];7EC043DD  给ecx
00404FE0    81C3 07000000        add ebx,7                                          ;定位到2416CE0
00404FE6    330B                 xor ecx,dword ptr ds:[ebx]                         ;解码
00404FE8    8908                 mov dword ptr ds:[eax],ecx                         ;正确函数地址写入
00404FEA    81C0 04000000        add eax,4                                          ;处理下一个
00404FF0    81F8 04654000        cmp eax,UltraPro.00406504                          ;比较是否处理完,另外一段将这里改成004063f4
00404FF6  ^ 72 E1                jb short UltraPro.00404FD9                         ;没处理完则继续
00404FF8    90                   nop                                                           ;
00404FF9    90                   nop

我选在00404fd4 大家可以选在别处,然后在00404fd4处新建起源,在00404ff8处下硬件执行断点,执行这段程序,处理完成后
改一下上面说的两个地址,处理完成之后只有一个无效的,很显然这个是 MessageBoxA




填上之后 全部有效,IR修复dump的文件可以运行。



第二种方法:在到达oep之前修复iat

这种关键是定位处理iat的关键代码,常见的方法是先到达oep然后查找iat的范围,对其下硬件写入断点,基本可以定位到iat处理的地方。也可以结合getprocaddress loadlibrarya等函数来确定,但是不一定有效。

忽略所有异常 

对rdata段下断,F9运行,
00418A0F    8B46 0C              mov eax,dword ptr ds:[esi+C]                      ;来到此处 很明显了,这里是取dll的名字 
00418A12    0BC0                 or eax,eax                            
00418A14    0F84 C0010000        je UltraPro.00418BDA                              ;判断所有dll处理完毕 

00418A1A    8366 0C 00           and dword ptr ds:[esi+C],0                         ;取出之后清零
00418A1E    03C2                 add eax,edx                                       ; UltraPro.00400000  加上基址

00418A20    8BD8                mov ebx,eax
00418A22    56                   push esi
00418A23    57                   push edi
00418A24    50                   push eax
00418A25    8BF3                 mov esi,ebx                                       ; UltraPro.00406592
00418A27    8BFB                 mov edi,ebx
00418A29    AC                   lods byte ptr ds:[esi]
00418A2A    C0C0 03              rol al,3
00418A2D    AA                  stos byte ptr es:[edi]
00418A2E    803F 00              cmp byte ptr ds:[edi],0
00418A31  ^ 75 F6                 jnz short UltraPro.00418A29                      ;解出dll名
00418A33    58                   pop eax
00418A34    5F                   pop edi
00418A35    5E                   pop esi
00418A36    50                   push eax                                         ; UltraPro.00406592
00418A37    FF95 489C4100        call dword ptr ss:[ebp+419C48]                   ; kernel32.GetModuleHandleA
00418A3D    0BC0                 or eax,eax
00418A3F    75 43                jnz short UltraPro.00418A84
00418A41    90                   nop
00418A42    90                   nop
00418A43    90                   nop
00418A44    90                   nop
00418A45    53                   push ebx
00418A46    FF95 4C9C4100        call dword ptr ss:[ebp+419C4C]                    ;调用loadlibrarya 
00418A4C    0BC0                 or eax,eax
00418A4E    75 34                jnz short UltraPro.00418A84
00418A50    90                   nop
00418A51    90                   nop
00418A52    90                   nop
00418A53    90                   nop
00418A54    8B95 EA614000        mov edx,dword ptr ss:[ebp+4061EA]
00418A5A    0195 E41B4000        add dword ptr ss:[ebp+401BE4],edx
00418A60    0195 E81B4000        add dword ptr ss:[ebp+401BE8],edx
00418A66    6A 00                push 0
00418A68    FFB5 E41B4000        push dword ptr ss:[ebp+401BE4]
00418A6E    FFB5 E81B4000        push dword ptr ss:[ebp+401BE8]
00418A74    6A 00                push 0
00418A76    FF95 549C4100        call dword ptr ss:[ebp+419C54]
00418A7C    6A 00                push 0
00418A7E    FF95 509C4100        call dword ptr ss:[ebp+419C50]
00418A84    60                   pushad
00418A85    2BC0                 sub eax,eax
00418A87    8803                 mov byte ptr ds:[ebx],al
00418A89    43                   inc ebx
00418A8A    3803                 cmp byte ptr ds:[ebx],al                            ;擦除dll名字
00418A8C  ^ 75 F9                jnz short UltraPro.00418A87
00418A8E    61                   popad
00418A8F    8985 E2614000        mov dword ptr ss:[ebp+4061E2],eax
00418A95    C785 E6614000 000000>mov dword ptr ss:[ebp+4061E6],0
00418A9F    8B95 EA614000        mov edx,dword ptr ss:[ebp+4061EA]
00418AA5    8B06                 mov eax,dword ptr ds:[esi]                         ;取originalfirstthunk
00418AA7    0BC0                 or eax,eax
00418AA9    75 07                jnz short UltraPro.00418AB2
00418AAB    90                   nop
00418AAC    90                   nop
00418AAD    90                   nop
00418AAE    90                   nop
00418AAF    8B46 10              mov eax,dword ptr ds:[esi+10]
00418AB2    03C2                 add eax,edx
00418AB4    0385 E6614000        add eax,dword ptr ss:[ebp+4061E6]
00418ABA    8B18                 mov ebx,dword ptr ds:[eax]
00418ABC    8B7E 10              mov edi,dword ptr ds:[esi+10]                     ;取firstthunk
00418ABF    03FA                 add edi,edx
00418AC1    03BD E6614000        add edi,dword ptr ss:[ebp+4061E6]
00418AC7    85DB                 test ebx,ebx
00418AC9    0F84 FD000000        je UltraPro.00418BCC
00418ACF    F7C3 00000080        test ebx,80000000                                 ;判断是不是序号方式
00418AD5    75 1D                jnz short UltraPro.00418AF4
00418AD7    90                   nop
00418AD8    90                   nop
00418AD9    90                   nop
00418ADA    90                   nop
00418ADB    03DA                 add ebx,edx
00418ADD    83C3 02              add ebx,2
00418AE0    56                   push esi
00418AE1    57                   push edi
00418AE2    50                   push eax
00418AE3    8BF3                 mov esi,ebx
00418AE5    8BFB                 mov edi,ebx
00418AE7    AC                   lods byte ptr ds:[esi]
00418AE8    C0C0 03              rol al,3
00418AEB    AA                   stos byte ptr es:[edi]
00418AEC    803F 00              cmp byte ptr ds:[edi],0
00418AEF  ^ 75 F6                jnz short UltraPro.00418AE7                      ;解出函数名 
00418AF1    58                   pop eax
00418AF2    5F                   pop edi
00418AF3    5E                   pop esi
00418AF4    81E3 FFFFFF0F        and ebx,0FFFFFFF
00418AFA    53                   push ebx
00418AFB    FFB5 E2614000        push dword ptr ss:[ebp+4061E2]
00418B01    FF95 449C4100        call dword ptr ss:[ebp+419C44]                   ;getprocaddress
00418B07    3B9D EA614000        cmp ebx,dword ptr ss:[ebp+4061EA]
00418B0D    7C 0F                jl short UltraPro.00418B1E
00418B0F    90                   nop
00418B10    90                   nop
00418B11    90                   nop
00418B12    90                   nop
00418B13    60                   pushad
00418B14    2BC0                 sub eax,eax
00418B16    8803                 mov byte ptr ds:[ebx],al
00418B18    43                   inc ebx
00418B19    3803                 cmp byte ptr ds:[ebx],al
00418B1B  ^ 75 F9                jnz short UltraPro.00418B16                      ;擦除操作
00418B1D    61                   popad
00418B1E    0BC0                 or eax,eax
00418B20  ^ 0F84 2EFFFFFF        je UltraPro.00418A54
00418B26    3B85 549C4100        cmp eax,dword ptr ss:[ebp+419C54]                ; USER32.MessageBoxA
是否是特殊的函数
00418B2C    75 0A                jnz short UltraPro.00418B38
00418B2E    90                   nop
00418B2F    90                   nop
00418B30    90                   nop
00418B31    90                   nop
00418B32    8D85 8D674000        lea eax,dword ptr ss:[ebp+40678D]
00418B38    56                   push esi
00418B39    FFB5 E2614000        push dword ptr ss:[ebp+4061E2]
00418B3F    5E                   pop esi
00418B40    39B5 C1204000        cmp dword ptr ss:[ebp+4020C1],esi                 ;比较是否是kernel32.dll 是则加密
00418B46    74 15                je short UltraPro.00418B5D                                   ;nop掉 不让它加密
00418B48    90                   nop
00418B49    90                   nop
00418B4A    90                   nop
00418B4B    90                   nop
00418B4C    39B5 C5204000        cmp dword ptr ss:[ebp+4020C5],esi                ; 比较是否user32.dll 是则加密 
00418B52    74 09                je short UltraPro.00418B5D                                   ;nop掉 不让它加密
00418B54    90                   nop
00418B55    90                   nop
00418B56    90                   nop
00418B57    90                   nop
00418B58    EB 63                jmp short UltraPro.00418BBD                      ;不加密路线
00418B5A    90                   nop
00418B5B    90                   nop
00418B5C    90                   nop
00418B5D    80BD 6FCB4000 00    cmp byte ptr ss:[ebp+40CB6F],0
00418B64    74 57                je short UltraPro.00418BBD
00418B66    90                   nop
00418B67    90                   nop
00418B68    90                   nop
00418B69    90                   nop
00418B6A    EB 07                jmp short UltraPro.00418B73                      ;加密路线
00418B6C    90                   nop
00418B6D    90                   nop
00418B6E    90                   nop
00418B6F    0100                 add dword ptr ds:[eax],eax
00418B71    0000                 add byte ptr ds:[eax],al
00418B73    8BB5 AF624000        mov esi,dword ptr ss:[ebp+4062AF]
00418B79    83C6 0D              add esi,0D
00418B7C    81EE DF1B4000        sub esi,UltraPro.00401BDF
00418B82    2BF5                 sub esi,ebp
00418B84    83FE 00              cmp esi,0
00418B87    7F 34                jg short UltraPro.00418BBD
00418B89    90                   nop
00418B8A    90                   nop
00418B8B    90                   nop
00418B8C    90                   nop
00418B8D    8BB5 AF624000        mov esi,dword ptr ss:[ebp+4062AF]
00418B93    53                   push ebx
00418B94    50                   push eax
00418B95    E8 A4A5FFFF          call UltraPro.0041313E                             ;加密
00418B9A    8BD8                 mov ebx,eax
00418B9C    58                   pop eax
00418B9D    33C3                 xor eax,ebx
00418B9F    C606 68              mov byte ptr ds:[esi],68
00418BA2    8946 01              mov dword ptr ds:[esi+1],eax
00418BA5    C746 05 81342400     mov dword ptr ds:[esi+5],243481
00418BAC    895E 08              mov dword ptr ds:[esi+8],ebx
00418BAF    C646 0C C3           mov byte ptr ds:[esi+C],0C3
00418BB3    5B                   pop ebx
00418BB4    8BC6                 mov eax,esi
00418BB6    8385 AF624000 0D     add dword ptr ss:[ebp+4062AF],0D
00418BBD    5E                   pop esi
00418BBE    8907                 mov dword ptr ds:[edi],eax                        ;函数地址写入
00418BC0    8385 E6614000 04      add dword ptr ss:[ebp+4061E6],4                  ;继续下一个函数
00418BC7  ^ E9 D3FEFFFF          jmp UltraPro.00418A9F
00418BCC    83C6 14              add esi,14
00418BCF    8B95 EA614000        mov edx,dword ptr ss:[ebp+4061EA]
00418BD5  ^ E9 35FEFFFF          jmp UltraPro.00418A0F                             ;继续下一个dll

00418BDA    60                   pushad                                            ;这里F4
00418BDB    E8 00000000          call UltraPro.00418BE0
00418BE0    5E                   pop esi
00418BE1    83EE 06              sub esi,6


然后对code 下断,F9即可到达

004010D2     56                    push esi
004010D3     FF15 E4634000         call dword ptr ds:[4063E4]                     ; UltraPro.0040D1BA
004010D9     8BF0                  mov esi,eax
004010DB     8A00                  mov al,byte ptr ds:[eax]
004010DD     3C 22                 cmp al,22
004010DF     75 1B                 jnz short UltraPro.004010FC
004010E1     56                    push esi
004010E2     FF15 F4644000         call dword ptr ds:[4064F4]                      ; UltraPro.0040D4C6

补上stolen code LoadPE 转存程序,IR修复,同样有一个无效的,显然是MessageBoxA,填上,修复程序可以运行


总结:这是我学脱壳来对iat处理的心得体会,希望对像我一样的的菜鸟有帮助。

上传的附件 UltraProtect.rar [解压密码:pediy]