softdenfender采用双进程来防脱壳,如ShineGood所言“父进程要做的事是建立临时文件,写入前面GetTickCount所得值的加密值,再 CreateProcessA建立子进程,随后自己

退出,”,因此我们可以参考peaceclub提供的方法强制转单进程:

代码:


00723D2E    /75 07              jnz short 00723D37                   ; Ns.00723D37
00723D30    |74 05              je short 00723D37                    ; Ns.00723D37
00723D32    |0010               add byte ptr ds:[eax],dl
00723D34    |40                 inc eax                              ; Ns.00723D1C
00723D35    |00E8               add al,ch
00723D37    \0F84 9A000000      je 00723DD7                          ; 强行跳转
00723D3D     E8 01000000        call 00723D43                        ; Ns.00723D43
00723D42     FF58 05            call far fword ptr ds:[eax+5]
00723D45     1100               adc dword ptr ds:[eax],eax           ; Ns.00723D1C

附:
代码:

0072C7FE     8B00               mov eax,dword ptr ds:[eax]           //api出int3断点检测,共检测五个字节
0072C800     8038 CC            cmp byte ptr ds:[eax],0CC
0072C803     74 22              je short 0072C827                    ; Ns.0072C827
0072C805     8078 01 CC         cmp byte ptr ds:[eax+1],0CC
0072C809     74 1C              je short 0072C827                    ; Ns.0072C827
0072C80B     8078 02 CC         cmp byte ptr ds:[eax+2],0CC
0072C80F     74 16              je short 0072C827                    ; Ns.0072C827
0072C811     8078 03 CC         cmp byte ptr ds:[eax+3],0CC
0072C815     74 10              je short 0072C827                    ; Ns.0072C827
0072C817     8078 04 CC         cmp byte ptr ds:[eax+4],0CC
0072C81B     74 0A              je short 0072C827                    ; Ns.0072C827
0072C81D     50                 push eax
0072C81E     C3                 retn

因为有断点检测,因此我们下硬件断点,当然也可以在函数开始五个字节以后下F2断点
he GetModuleHandleA
代码:

00406F50    53              push    ebx                               
00406F51    8BD8            mov     ebx, eax
00406F53    33C0            xor     eax, eax
00406F55    A3 C4805D00     mov     dword ptr [5D80C4], eax           
00406F5A    6A 00           push    0
00406F5C    E8 2BFFFFFF     call    00406E8C
00406F61    A3 68F65D00     mov     dword ptr [5DF668], eax            ;返回这里
00406F66    A1 68F65D00     mov     eax, dword ptr [5DF668]
00406F6B    A3 D0805D00     mov     dword ptr [5D80D0], eax

ctrl+F9执行到返回:
代码:

005D733C    55              push    ebp                                  ; oep
005D733D    8BEC            mov     ebp, esp
005D733F    83C4 F0         add     esp, -10
005D7342    53              push    ebx
005D7343    B8 246B5D00     mov     eax, 005D6B24
005D7348    E8 03FCE2FF     call    00406F50
005D734D    8B1D 44E55D00   mov     ebx, dword ptr [5DE544]              ; 返回这里
005D7353    8B03            mov     eax, dword ptr [ebx]
005D7355    E8 8E68EBFF     call    0048DBE8

可以看出:
OEP:005D733C
IAT:005E51F4--005E5B7C  SIZE:98C
可以dump了。

参考peaceclub的方法,我们可以写如下修复IAT的代码,当然你也可以用ImprREC的level2和level3或插件修复,不过我的机器由于装着kav,它会hook几个函数,导致ImprREC不能正常修复,所以我只能自己动手写代码修复了。
代码:

005E9A7C    60              pushad
005E9A7D    9C              pushfd
005E9A7E    BF F4515E00     mov     edi, 005E51F4
005E9A83    66:837F 02 14   cmp     word ptr [edi+2], 14
005E9A88    75 22           jnz     short 005E9AAC
005E9A8A    8B17            mov     edx, dword ptr [edi]
005E9A8C    90              nop
005E9A8D    90              nop
005E9A8E    90              nop
005E9A8F    8B42 12         mov     eax, dword ptr [edx+12]
005E9A92    8B18            mov     ebx, dword ptr [eax]
005E9A94    891F            mov     dword ptr [edi], ebx
005E9A96    90              nop
005E9A97    EB 13           jmp     short 005E9AAC
005E9A99    90              nop
005E9A9A    90              nop
005E9A9B    90              nop
005E9A9C    90              nop
005E9A9D    90              nop
005E9A9E    90              nop
005E9A9F    90              nop
005E9AA0    90              nop
005E9AA1    90              nop
005E9AA2    90              nop
005E9AA3    90              nop
005E9AA4    90              nop
005E9AA5    90              nop
005E9AA6    90              nop
005E9AA7    90              nop
005E9AA8    90              nop
005E9AA9    90              nop
005E9AAA    90              nop
005E9AAB    90              nop
005E9AAC    83C7 04         add     edi, 4
005E9AAF    81FF 7C5B5E00   cmp     edi, 005E5B80
005E9AB5    7D 02           jge     short 005E9AB9
005E9AB7  ^ EB CA           jmp     short 005E9A83
005E9AB9    9D              popfd
005E9ABA    61              popad

二进制:
代码:

60 9C BF F4 51 5E 00 66 83 7F 02 14 75 22 8B 17 90 90 90 8B 42 12 8B 18 89 1F 90 EB 13 90 90 90
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 83 C7 04 81 FF 80 5B 5E 00 7D 02 EB CA 9D 61

具体方法可参考peaceclub的文章。

不过这样修复后还是有8个指针修复不了,peaceclub说“找个delphi的程序把iat表保存下来和它对照一下”,我甚为不解,iat表会一样吗?这样做肯定不行的。



我们在005E51F4下内存访问断点,几次中断后会来到:
代码:

0072ACE7    837D 00 00      cmp     dword ptr [ebp], 0             
0072ACEB    0F84 3C030000   je      0072B02D                           ;为0则开始下一个dll
0072ACF1    8B7C24 14       mov     edi, dword ptr [esp+14]
0072ACF5    8D4C24 38       lea     ecx, dword ptr [esp+38]
0072ACF9    8D9424 3C010000 lea     edx, dword ptr [esp+13C]
...
...
0072AF26    68 E2894000     push    004089E2
0072AF2B    E8 31D1FFFF     call    00728061
0072AF30    50              push    eax
0072AF31    57              push    edi
0072AF32    E8 92E2FFFF     call    007291C9
0072AF37    85C0            test    eax, eax
0072AF39    75 11           jnz     short 0072AF4C
0072AF3B    68 867C4000     push    00407C86
0072AF40    E8 1CD1FFFF     call    00728061
0072AF45    8906            mov     dword ptr [esi], eax
0072AF47    E9 AA000000     jmp     0072AFF6
0072AF4C    68 F3894000     push    004089F3
0072AF51    E8 0BD1FFFF     call    00728061
0072AF56    50              push    eax
0072AF57    57              push    edi
0072AF58    E8 6CE2FFFF     call    007291C9
0072AF5D    85C0            test    eax, eax
0072AF5F    75 11           jnz     short 0072AF72
...
0072AFBC    57              push    edi
0072AFBD    52              push    edx
0072AFBE    E8 94E7FFFF     call    00729757
0072AFC3    50              push    eax
0072AFC4    E8 17F8FFFF     call    0072A7E0
0072AFC9    8906            mov     dword ptr [esi], eax
0072AFCB    EB 29           jmp     short 0072AFF6
0072AFCD    8B4424 10       mov     eax, dword ptr [esp+10]
0072AFD1    57              push    edi
0072AFD2    50              push    eax
0072AFD3    E8 7FE7FFFF     call    00729757
0072AFD8    8906            mov     dword ptr [esi], eax
0072AFDA    8B8C24 44040000 mov     ecx, dword ptr [esp+444]
0072AFE1    85C9            test    ecx, ecx
0072AFE3    75 11           jnz     short 0072AFF6
0072AFE5    8B4C24 1C       mov     ecx, dword ptr [esp+1C]
0072AFE9    85C9            test    ecx, ecx
0072AFEB    74 09           je      short 0072AFF6
0072AFED    8901            mov     dword ptr [ecx], eax
0072AFEF    83C1 04         add     ecx, 4
0072AFF2    894C24 1C       mov     dword ptr [esp+1C], ecx
0072AFF6    33C9            xor     ecx, ecx
0072AFF8    66:8B0B         mov     cx, word ptr [ebx]
0072AFFB    51              push    ecx
0072AFFC    68 FF000000     push    0FF
0072B001    57              push    edi
0072B002    E8 48E1FFFF     call    0072914F
0072B007    66:C703 0000    mov     word ptr [ebx], 0
0072B00C    3BEE            cmp     ebp, esi
0072B00E    74 0A           je      short 0072B01A
0072B010    6A 04           push    4
0072B012    6A 00           push    0
0072B014    55              push    ebp
0072B015    E8 35E1FFFF     call    0072914F
0072B01A    8B5C24 34       mov     ebx, dword ptr [esp+34]
0072B01E    8B7C24 20       mov     edi, dword ptr [esp+20]
0072B022    83C5 04         add     ebp, 4                                      ;下一个
0072B025    83C6 04         add     esi, 4
0072B028  ^ E9 BAFCFFFF     jmp     0072ACE7

大概有十一个这种判断,
代码:

0072AE26    50              push    eax
0072AE27    57              push    edi
0072AE28    E8 9CE3FFFF     call    007291C9                     ;判断是否是几个特殊的函数
0072AE2D    85C0            test    eax, eax
0072AE2F    75 11           jnz     short 0072AE42               ;我们要强制它跳,才能躲过特殊的函数的处理

代码:

0072AFBE    E8 94E7FFFF     call    00729757                     ;此时eax里是我们要的函数真实地址
0072AFC3    50              push    eax                          ;Nop掉,避开加密
0072AFC4    E8 17F8FFFF     call    0072A7E0                     ;Nop掉
0072AFC9    8906            mov     dword ptr [esi], eax
0072AFCB    EB 29           jmp     short 0072AFF6

不过壳还有内存校验,每patch过一个dll文件,我们要恢复原来的代码,很是麻烦,当然你可以在这里下内存访问断点,看哪里是检验处,修改之。我嫌麻烦,既然我们只剩下8个指针了,也不多,分别跟踪一下也不是很麻烦,经过跟踪我们得到那8个被特殊照顾的函数:
代码:

005E521C      kernel32.GetVersion

005E5234      kernel32.SetCurrentDirectoryA

005E5250      kernel32.GetStartupInfoA

005E5268      kernel32.GetCurrentDirectoryA

005E526C      kernel32.GetCommandLineA

005E53FC      GetVersionExA

005E5400      GetVersion

005E546C      GetCurrentProcessId

赶紧fix吧,可以收工了。