欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]softdefender脱壳

[原创]softdefender脱壳

最近学习脱壳,在网上下了个softdefender加壳工具共享版。加壳工具本身就是用softdefender加的壳。就拿来试了下。希望高手多指教。
OD版本是OllyICE,用StrongOD隐藏插件隐藏OD。除BreakOnTls RemoveEPone-shot BreakOnLdr其它都选上。
PhantOm options选上protect DRx.
1.双进程转单进程
softdefender双进程转单进程参考peaceclub的方法。贴子中有详细介绍,为了完整性,我也还是再描述一下。
用kerberos加载程序,点击inject。生成rep文件。

SoftDefender | 004CCD53 | GetCommandLineA() returns: 002523A0
SoftDefender | 004CCDBF | CreateProcessA(00000000, 004CC24C: "F:\tools\hack\", 00000000, 00000000, 00000001, 00000000, 00000000, 00000000, 004CC350, 004CC23C) returns: 00000001
SoftDefender | 004CCDD7 | ExitProcess(00000000) 

在CreateProcessA前面一个api GetCommandLineA 004CCD53 处下硬件执行断点。
断下后往上拉就会看到一个je.
004CCD32    0010            add     byte ptr [eax], dl
004CCD34    40              inc     eax
004CCD35    00E8            add     al, ch
004CCD37    0F84 9A000000   je      004CCDD7                    ;修改z标志位跳转实现
004CCD3D    E8 01000000     call    004CCD43

在004CCD37处下硬件执行断点。把开始那断点删除。
重新加载,断下后修改z标志位让跳转实现。这样就变成单进程了。
2.跳过iat加密
alt+m打开内存镜像,在00401000段下内存访问断点。运行后断下处为解压代码处。
004C9E10    8917            mov     dword ptr [edi], edx
004C9E12    83C7 04         add     edi, 0x4
004C9E15    49              dec     ecx
004C9E16  ^ 75 F3           jnz     short 004C9E0B

右键删除内存断点。
这时可以在数据窗口中ctrl+g 到00401000。观察数据变化
往下拉到函数返回
004C9F5A    F7D8            neg     eax
004C9F5C    83C4 0C         add     esp, 0xC
004C9F5F    5A              pop     edx
004C9F60    59              pop     ecx
004C9F61    5B              pop     ebx
004C9F62    5E              pop     esi
004C9F63    5F              pop     edi
004C9F64    5D              pop     ebp
004C9F65    C3              retn

在retn处f4。
然后再次alt+m打开内存镜像,在00401000段下内存访问断点。这次断下来就是准备处理iat处。
004D3B4A    8B17            mov     edx, dword ptr [edi]
004D3B4C    8B47 10         mov     eax, dword ptr [edi+0x10]
004D3B4F    0BD0            or      edx, eax
004D3B51    0F84 0B050000   je      004D4062

右键删除内存断点。
这时候就一直f8单步。注意观察寄存器的变化。可以看到寄存器esi出现kernel32.dll,再单步到edi出现函数名IsBadReadPtr.并且有一个未实现的比较远的跳转.
004D3DE2    E8 11F4FFFF     call    004D31F8     ;这个call调用完edi出现函数名
004D3DE7    8B8424 44040000 mov     eax, dword ptr [esp+0x444]
004D3DEE    85C0            test    eax, eax
004D3DF0    0F84 D7010000   je      004D3FCD            ;改为jmp
004D3DF6    8B4424 18       mov     eax, dword ptr [esp+0x18]
004D3DFA    85C0            test    eax, eax

这个跳转就是决定iat是否加密的跳转.将je改为jmp.
再继续f8单步,这样就可以看到直接获取iat写入esi.
这时也可以在数据窗口中观察esi地址。查看iat是否加密。
再继续就会出现jmp往回跳循环处理。
004D401A    8B5C24 34       mov     ebx, dword ptr [esp+0x34]
004D401E    8B7C24 20       mov     edi, dword ptr [esp+0x20]
004D4022    83C5 04         add     ebp, 0x4
004D4025    83C6 04         add     esi, 0x4
004D4028  ^ E9 BAFCFFFF     jmp     004D3CE7
004D402D    E8 35E4FFFF     call    004D2467         ;此处 为校验call f7步入

在jmp的下一条语句处f4。这个call如果再音步,那么恭喜,又得重新来一次了。
这个call这里有校验,如果仅仅是将这个call nop掉,在处理下一个dll时,还会在上面调用一次,所以这里用f7进去,将call内的有一个je也更改为jmp.
004D24E9    5F              pop     edi
004D24EA    5E              pop     esi
004D24EB    85C0            test    eax, eax
004D24ED    5B              pop     ebx
004D24EE    74 2B           je      short 004D251B   ;改为jmp
004D24F0    E8 93EBFFFF     call    004D1088

单步到上层函数,又会碰到jmp往回跳,循环处理dll.
004D405D  ^\E9 E8FAFFFF     jmp     004D3B4A   ;循环处理dll
004D4062    5F              pop     edi
004D4063    5E              pop     esi
004D4064    5D              pop     ebp
004D4065    B8 01000000     mov     eax, 0x1
004D406A    5B              pop     ebx
004D406B    81C4 30040000   add     esp, 0x430
004D4071    C2 0400         retn    0x4                    ;f4执行

这里就可以直接在retn处f4。就可以看到iat全部处理完成。这时候就可以找oep了。
3.找oep
ctrl+g到00401000 
00401000    53              push    ebx
00401001    56              push    esi
00401002    57              push    edi
00401003    FF15 78E24400   call    dword ptr [0x44E278]             ; KERNEL32.GetVersion
00401009    3D 00000080     cmp     eax, 0x80000000
0040100E    0F83 9A000000   jnb     004010AE
00401014    68 94000000     push    0x94
00401019    BB 01000000     mov     ebx, 0x1
0040101E    E8 D06C0200     call    00427CF3

发现代码很像vc的程序。
先找一段vc程序入口特征码
004184AE  |.  8B45 EC       mov     eax, dword ptr [ebp-0x14]
004184B1  |.  8B08          mov     ecx, dword ptr [eax]
004184B3  |.  8B09          mov     ecx, dword ptr [ecx]
004184B5  |.  894D 98       mov     dword ptr [ebp-0x68], ecx
004184B8  |.  50            push    eax
004184B9  |.  51            push    ecx
8B 45 EC 8B 08 8B 09 89 4D 98 50 51

ctrl+b查找,果然找到特征码,往上拉就发现oep。
00429664    55              push    ebp                       ;oep
00429665    8BEC            mov     ebp, esp
00429667    6A FF           push    -0x1
00429669    68 E02C4500     push    00452CE0
0042966E    68 48C74200     push    0042C748
00429673    64:A1 00000000  mov     eax, dword ptr fs:[0]
00429679    50              push    eax                                       
0042967A    64:8925 0000000>mov     dword ptr fs:[0], esp
00429681    83EC 58         sub     esp, 0x58
00429684    53              push    ebx
00429685    56              push    esi
00429686    57              push    edi
00429687    8965 E8         mov     dword ptr [ebp-0x18], esp
0042968A    FF15 78E24400   call    dword ptr [0x44E278]             ; KERNEL32.GetVersion

然后迫不急待在oep下硬件执行断点,f9运行。结果程序跑飞了。
看来oep代码被偷了。重新来一次。
这次就在KERNEL32.GetVersion处下断,现在代码就变成这样
00429664    0000            add     byte ptr [eax], al
00429666    0000            add     byte ptr [eax], al
00429668    0000            add     byte ptr [eax], al
0042966A    0000            add     byte ptr [eax], al
0042966C    00FF            add     bh, bh
0042966E    15 28491600     adc     eax, 0x164928
00429673    64:A1 00000000  mov     eax, dword ptr fs:[0]  ;硬件执行断点
00429679    50              push    eax
0042967A    64:8925 0000000>mov     dword ptr fs:[0], esp
00429681    83EC 58         sub     esp, 0x58
00429684    53              push    ebx
00429685    56              push    esi
00429686    57              push    edi
00429687    8965 E8         mov     dword ptr [ebp-0x18], esp
0042968A    FF15 78E24400   call    dword ptr [0x44E278]             ; KERNEL32.GetVersion

还得再来一次,在偷代码的下的语句下硬件执行断点,大家可以跳过两次失败的硬件断点,直接在这下断点。我提示的晚吗?
得想个办法。让eip到oep.并且堆栈数据还原。具体壳是怎么偷取代码怎么处理的我就不分析了。因为我不会分析。
对比两次的代码就只push了四次。只需要pop出来就完事了。ecx为0,就借用一下。
在oep处新建eip.写代码 
00429664    59              pop     ecx
00429665    59              pop     ecx
00429666    59              pop     ecx                       ;只能pop三次,最后一个是ebp的值
00429667    33C9            xor     ecx, ecx               ;记得还原原来的值
00429669    8BE5            mov     esp, ebp            ;还原esp
0042966B    5D              pop     ebp                      ;还原ebp
0042966C    00FF            add     bh, bh                 ;执行到这里,这句不用执行了。

这样堆栈就还原了。然后再次将eip新建到oep处。将原先的代码还原。
55 8B EC 6A FF 68 E0 2C 45 00 68 48 C7 42 00   
4.dump修复
loadpe修正镜像大小,完全脱壳
importrec输入oep.搜索iat.获取输入表.全部有效.修复.
这样就可以直接运行了。优化没做。接下来看看破解。
破解在这里有介绍

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功