SDProtector Profesional Edition v1.12 脱壳分析
【文章标题】: SDProtector Profesional Edition v1.12 脱壳分析【文章作者】: huzhao23
【作者邮箱】: 304333002@QQ.COM
【作者主页】: hi.baidu.com/hacknight
【软件名称】: 黑洞2005企业版Build 20050328
【下载地址】: 自己搜索下载
【保护方式】: SDProtector Profesional Edition v1.12
【使用工具】: OD,LOADPE,IMPREC
【软件介绍】: 远程控制管理软件
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
一个朋友发给我这个软件,要我脱壳,发现是软件保护神的保护方式,老版本的壳,不过这个软件的ANTI 还是很有特点的。
记得有一篇国外的文章详细的分析了这个壳的反调试,大家可以去找找,1.16 版的脱壳方法大同小异。大家可以尝试着跟下。
好了,不多废话了,下面开始脱壳把
1. 设置好OD ,用hideolldbg 隐藏OD(记得每次调试都要隐藏) ,调试选项里忽略除INT3,单步,非法访问内存异常之外的异常,然后我们隐藏下OD
SHIFT+F9 运行,大概运行11次程序就跑飞了,我们在最后一次异常的时候停下来
代码如下:
00C71EFA 64:8F00 pop dword ptr fs: ; 0012FFE0 // SEH异常中断在这里
00C71EFD 5B pop ebx
00C71EFE E8 01000000 call 00C71F04
00C71F03 FF58 05 call far fword ptr
00C71F06 6BFF FF imul edi, edi, -1
看堆栈,跳出这个异常
0012FF98 0012FFE0指向下一个 SEH 记录的指针
0012FF9C 00C71ED3SE处理程序 // 这里是出口
来到出口处,代码如下:
00C71ED3 E8 01000000 call 00C71ED9 // 在这里下好断点之后,shift+F9运行到这里
00C71ED8 FF58 05 call far fword ptr
之后就是单步F7 往下走
到这里
00C71ED9 58 pop eax
00C71EDA 05 96FFFFFF add eax, -6A
00C71EDF 8038 E8 cmp byte ptr , 0E8 // 0E8 是异常标记
00C71EE2^ 75 B2 jnz short 00C71E96 // 这里不能跳,否则就跑飞
00C71EE4 C600 E9 mov byte ptr , 0E9 // 0E9 也是异常标记
00C71EE7 2BC0 sub eax, eax
00C71EE9 C3 retn
继续单步F7走,来到这里
7C92E48A 0AC0 or al, al
7C92E48C 74 0C je short 7C92E49A
7C92E48E 5B pop ebx
7C92E48F 59 pop ecx
7C92E490 6A 00 push 0
7C92E492 51 push ecx
7C92E493 E8 C6EBFFFF call ZwContinue // 这里也是异常
出口在00C71EFA地址处,同样在这里下断点,shift+f9 运行到00C71EFA地址处,继续F7 ,来到这里
00C71F04 58 pop eax
00C71F05 05 6BFFFFFF add eax, -95
00C71F0A 8038 E9 cmp byte ptr , 0E9
00C71F0D^ 75 87 jnz short 00C71E96 // 这里也不能跳转,否则出错
00C71F0F C600 E8 mov byte ptr , 0E8
00C71F12 9D popfd
00C71F13 61 popad
F7 ,来到这里
00C71F4A 58 pop eax
00C71F4B 9D popfd
00C71F4C 74 31 je short 00C71F7F ; 这里必须跳,修改标志位
00C71F4E 74 03 je short 00C71F53
00C71F50 75 01 jnz short 00C71F53
继续F7 ,走到这里
00C760BC 58 pop eax ; Client.00C760BB
00C760BD 05 45B0FFFF add eax, FFFFB045 ; 这个应该是加密因子,
00C760C2 C3 retn
然后SHIFT+F9 ,中断在
00C7213D 64:8F00 pop dword ptr fs: ; 0012FFE0
00C72140 5B pop ebx
00C72141 E8 01000000 call 00C72147
00C72146 FF58 05 call far fword ptr
00C72149 6BFF FF imul edi, edi, -1
00C7214C FF80 38E97587 inc dword ptr
同样是个SEH 异常,我们看堆栈,找到出口,然后shift+f9 运行到出口,接着又是一个context 结构体,走出来之后
继续F7 单步走 (要走很长一段时间)
来到这里
00C7213D 64:8F00 pop dword ptr fs: ; 到这里之后,堆栈里也显示一个SEH异常出口,但是我们不去那个出口,直接单步F8
00C72140 5B pop ebx
00C72141 E8 01000000 call 00C72147 ; F7 进这个call
00C72146 FF58 05 call far fword ptr
来到这里
00C72147 58 pop eax
00C72148 05 6BFFFFFF add eax, -95
00C7214D 8038 E9 cmp byte ptr , 0E9
00C72150^ 75 87 jnz short 00C720D9 ; 这里不能跳转,跳了就异常了,修改标志位不让它跳转
00C72152 C600 E8 mov byte ptr , 0E8
00C72155 9D popfd
00C72156 61 popad
然后继续F7 来到父子进程分离的地方
00C72194 /0F84 0E010000 je 00C722A8 ; 这里就是关键父子进程分离的地方
00C7219A |E8 01000000 call 00C721A0
00C7219F |FF58 05 call far fword ptr
00C72194 /0F84 0E010000 je 00C722A8 这里要修改标志位让跳转实现,否则程序将创建子进程运行,不利于我们脱壳
到这里关键的几个地方我们都找到了,下面用脚本实现以上修改,同时,到了这里之后还是会有反调试的机制存在,我们要在记录里看下还需要多少次
中断后就异常跑飞了,用脚本来实现
(借用了一个大牛的脚本修改了下),脚本如下
var SEH
var mess
//#log
eoe NighT1
eob NighT1
run
NighT1:
add SEH,1
log SEH
cmp SEH,a //第10次中断时跳转。
je stop1
esto
stop1:
coe
cob
mov SEH,0
bp 00C71F4C // 这个地址是那个关键的JE
esto
bc eip
mov !zf,1
sti
run
bp 00C72194 //子进程与父进程分流处。
esto
bc eip
mov eip,00C722A8 //直接跳过创建子进程,强行让父进程以子进程运行。
eoe NighT2
eob NighT2
run
NighT2:
add SEH,1
log SEH
esto
ret
运行这个脚本之后,在记录里看见了一共SEH 了30 次就跑飞了,我们在30 处让程序中断下来 ,修改脚本实现
将NighT2 过程改成这样
NighT2:
add SEH,1
log SEH
cmp SEH,30
je stop2
esto
stop2:
coe
cob
ret
再次运行脚本,中断在这里
00C7607A 64:8F00 pop dword ptr fs: ; // 中断再这里
00C7607D 5B pop ebx
00C7607E E8 01000000 call 00C76084 ; F7
00C76083 FF58 05 call far fword ptr
同样的方法走出着个异常
F7 进入这个CALL
00C76084 58 pop eax
00C76085 05 6BFFFFFF add eax, -95
00C7608A 8038 E9 cmp byte ptr , 0E9
00C7608D^ 75 87 jnz short 00C76016 // JNZ不能跳转,修改标志位不让它跳转
00C7608F C600 E8 mov byte ptr , 0E8
00C76092 9D popfd
00C76093 61 popad
00C76094 C3 retn ; 过了这个retn 就到了OEP
继续F7
来到OEP
005A9174 55 push ebp ; OEP
005A9175 8BEC mov ebp, esp
005A9177 83C4 F0 add esp, -10
005A917A B8 4C8A5A00 mov eax, 005A8A4C
005A917F E8 F0D6E5FF call 00406874
005A9184 A1 309B5E00 mov eax, dword ptr
005A9189 8B00 mov eax, dword ptr
005A918B E8 D43FEEFF call 0048D164
005A9190 8B0D 7C985E00 mov ecx, dword ptr ; Client.005EE228
005A9196 A1 309B5E00 mov eax, dword ptr
005A919B 8B00 mov eax, dword ptr
005A919D 8B15 442C5A00 mov edx, dword ptr ; Client.005A2C90
005A91A3 E8 D43FEEFF call 0048D17C
005A91A8 A1 309B5E00 mov eax, dword ptr
005A91AD 8B00 mov eax, dword ptr
005A91AF E8 4840EEFF call 0048D1FC
005A91B4 E8 DBAFE5FF call 00404194
005A91B9 8D40 00 lea eax, dword ptr
005A91BC 0000 add byte ptr , al
到这里DUMP
但是这个时候是DUMP 不了的,因为区段被修改了访问权限,修改权限为所有,然后就可以DUMP
2. IAT 的修复
SDPprotector 这个壳实在还原了IAT 之后,再来到OEP 的,所以,SEH<30 次的中断之后,对 IAT 进行处理的,我尝试了下 ,大概中断了12次就停在了壳对IAT
处理的地方。修改脚本
将NighT2 过程改成这样
NighT2:
add SEH,1
log SEH
cmp SEH,12
je stop2
esto
stop2:
coe
cob
ret
重载程序,重新运行脚本
00C764FB 90 nop ; 中断在这里
00C764FC 3C 04 cmp al, 4
00C764FE 74 32 je short 00C76532
00C76500 74 03 je short 00C76505
00C76502 75 01 jnz short 00C76505
00C76504 E8 E8010000 call 00C766F1
00C76509 00FF add bh, bh
00C7650B 58 pop eax
单步走
00C7653C 0F31 rdtsc ; 反调试
00C7653E 8BC8 mov ecx, eax
00C76540 8BDA mov ebx, edx
00C76542 7E 06 jle short 00C7654A
00C76544 7F 04 jg short 00C7654A
00C76546 0010 add byte ptr , dl
00C76548 40 inc eax
单步F7 走到这里
00C7656F 9D popfd
00C76570 58 pop eax
00C76571 0F31 rdtsc ; 反调试
00C76573 2BC1 sub eax, ecx
00C76575 1BD3 sbb edx, ebx
00C76577 83FA 00 cmp edx, 0 ; 这里要把edx 置为0
00C7657A^ 75 84 jnz short 00C76500
00C7657C 3D 00000060 cmp eax, 60000000 ; 这里把eax置为0
00C76581^ 0F87 79FFFFFF ja 00C76500
00C76587 74 39 je short 00C765C2 ; JE和jnz 是jmp 的变形
00C76589 75 37 jnz short 00C765C2
F7 到这里
00C7E182 8B8424 4C040000 mov eax, dword ptr ; 来到这里
00C7E189 33ED xor ebp, ebp ; 这里就是处理 IAT 的开始了
00C7E18B 85C0 test eax, eax
00C7E18D 896C24 14 mov dword ptr , ebp
00C7E191 75 6D jnz short 00C7E200
00C7E193 68 FDDE4000 push 0040DEFD
00C7E198 E8 007FFFFF call 00C7609D
00C7E19D 50 push eax
00C7E19E 68 C4AA4000 push 0040AAC4
00C7E1A3 E8 F57EFFFF call 00C7609D
F8 到这里
00C7E31A 53 push ebx
00C7E31B 895C24 54 mov dword ptr , ebx
00C7E31F E8 DCC4FFFF call 00C7A800
00C7E324 E8 16C5FFFF call 00C7A83F ; 这里有一个异常,F7 进去
进这个CALL
00C7A83F 83EC 68 sub esp, 68 ; F7 来到这里
00C7A842 53 push ebx
00C7A843 56 push esi
00C7A844 57 push edi
00C7A845 E8 6CB8FFFF call 00C760B6
00C7A84A 6A 00 push 0
00C7A84C 8BF8 mov edi, eax
00C7A84E E8 EC640000 call 00C80D3F
00C7A853 50 push eax
00C7A854 E8 6CC6FFFF call 00C76EC5
00C7A859 E8 58B8FFFF call 00C760B6
00C7A85E 8BF0 mov esi, eax
00C7A860 81EE 00010000 sub esi, 100
00C7A866 E8 84C0FFFF call 00C768EF
00C7A86B 8BD8 mov ebx, eax
00C7A86D 8D4424 1C lea eax, dword ptr
00C7A871 50 push eax
00C7A872 E8 85C7FFFF call 00C76FFC
00C7A877 68 00010000 push 100
00C7A87C 8D4C24 24 lea ecx, dword ptr
00C7A880 56 push esi
00C7A881 51 push ecx
00C7A882 E8 9DC7FFFF call 00C77024
00C7A887 81C3 A8FBFFFF add ebx, -458
00C7A88D 81C6 58040000 add esi, 458
00C7A893 53 push ebx
00C7A894 8D5424 30 lea edx, dword ptr
00C7A898 56 push esi
00C7A899 52 push edx
00C7A89A E8 85C7FFFF call 00C77024
00C7A89F 8D4424 38 lea eax, dword ptr
00C7A8A3 8D4C24 28 lea ecx, dword ptr
00C7A8A7 50 push eax
00C7A8A8 51 push ecx
00C7A8A9 E8 1AC8FFFF call 00C770C8
00C7A8AE 83C4 24 add esp, 24
00C7A8B1 83C7 60 add edi, 60
00C7A8B4 8D5424 0C lea edx, dword ptr
00C7A8B8 6A 10 push 10
00C7A8BA 57 push edi
00C7A8BB 52 push edx
00C7A8BC E8 31D0FFFF call 00C778F2
00C7A8C1 5F pop edi
00C7A8C2 5E pop esi
00C7A8C3 85C0 test eax, eax
00C7A8C5 5B pop ebx
00C7A8C6 EB 0A jmp short 00C7A8D2 ; 这要修改成JMP 否则就会在下面的 调试中调用异常处理函数
00C7A8C8 E8 FAB7FFFF call 00C760C7
00C7A8CD E8 ADFBFFFF call 00C7A47F
00C7A8D2 B8 01000000 mov eax, 1
00C7A8D7 83C4 68 add esp, 68
00C7A8DA C3 retn
继续F8
00C7E329 8B7C24 38 mov edi, dword ptr
00C7E32D 68 C4AA4000 push 0040AAC4
00C7E332 E8 667DFFFF call 00C7609D
00C7E337 50 push eax
00C7E338 53 push ebx
00C7E339 E8 BB96FFFF call 00C779F9
00C7E33E 85C0 test eax, eax
00C7E340 74 5C je short 00C7E39E ; nop
00C7E342 68 23DF4000 push 0040DF23
00C7E347 E8 517DFFFF call 00C7609D
00C7E34C 50 push eax
00C7E34D 53 push ebx
00C7E34E E8 A696FFFF call 00C779F9
00C7E353 85C0 test eax, eax
00C7E355 74 47 je short 00C7E39E ; nop
00C7E357 68 2EDF4000 push 0040DF2E
00C7E35C E8 3C7DFFFF call 00C7609D
00C7E361 50 push eax
00C7E362 53 push ebx
00C7E363 E8 9196FFFF call 00C779F9
00C7E368 85C0 test eax, eax
00C7E36A 74 32 je short 00C7E39E ; nop
00C7E36C 68 38DF4000 push 0040DF38
00C7E371 E8 277DFFFF call 00C7609D
00C7E376 50 push eax
00C7E377 53 push ebx
00C7E378 E8 7C96FFFF call 00C779F9
00C7E37D 85C0 test eax, eax
00C7E37F 74 1D je short 00C7E39E ; nop
00C7E381 68 45DF4000 push 0040DF45
00C7E386 E8 127DFFFF call 00C7609D
00C7E38B 50 push eax
00C7E38C 53 push ebx
00C7E38D E8 6796FFFF call 00C779F9
00C7E392 85C0 test eax, eax
00C7E394 C74424 24 00000>mov dword ptr , 0 ; 0是IAT 不加密的标志
00C7E39C 75 08 jnz short 00C7E3A6
00C7E39E C74424 24 01000>mov dword ptr , 1 ; 1是IAT 不加密的标志
00C7E3A6 68 51DF4000 push 0040DF51
00C7E3AB E8 ED7CFFFF call 00C7609D
00C7E3B0 50 push eax
00C7E3B1 53 push ebx
00C7E3B2 E8 4296FFFF call 00C779F9
00C7E3B7 85C0 test eax, eax
00C7E3B9 74 7F je short 00C7E43A ; nop
00C7E3BB 8B8424 4C040000 mov eax, dword ptr
继续F8
00C7EA4D 68 6AE04000 push 0040E06A
00C7EA52 E8 4676FFFF call 00C7609D
00C7EA57 50 push eax ; 对"MessageBoxA"特殊处理
00C7EA58 57 push edi
00C7EA59 E8 1480FFFF call 00C76A72
00C7EA5E 85C0 test eax, eax
00C7EA60 75 0E jnz short 00C7EA70 ; 这里改成jmp
00C7EA62 68 B1CE4000 push 0040CEB1
00C7EA67 E8 3176FFFF call 00C7609D
00C7EA6C 8906 mov dword ptr , eax
00C7EA6E EB 50 jmp short 00C7EAC0
00C7EA70 68 10CF4000 push 0040CF10
00C7EA75 E8 2376FFFF call 00C7609D
00C7EA7A 50 push eax ; 对 "MessageBoxW"特殊处理
00C7EA7B 57 push edi
00C7EA7C E8 F17FFFFF call 00C76A72
00C7EA81 85C0 test eax, eax
00C7EA83 75 0E jnz short 00C7EA93 ; 这里改成JMP
00C7EA85 68 27CF4000 push 0040CF27
00C7EA8A E8 0E76FFFF call 00C7609D
00C7EA8F 8906 mov dword ptr , eax
00C7EA91 EB 2D jmp short 00C7EAC0
00C7EA93 8B4C24 10 mov ecx, dword ptr
00C7EA97 57 push edi
00C7EA98 51 push ecx
00C7EA99 E8 FAB9FFFF call 00C7A498
00C7EA9E 8906 mov dword ptr , eax ; 这里就是获取了API 函数的真实地址给ESI内存
00C7EAA0 EB 1E jmp short 00C7EAC0
00C7EAA2 8B5424 10 mov edx, dword ptr
00C7EAA6 57 push edi
00C7EAA7 52 push edx
00C7EAA8 E8 EBB9FFFF call 00C7A498
00C7EAAD 8906 mov dword ptr , eax
00C7EAAF 8B4C24 14 mov ecx, dword ptr
00C7EAB3 85C9 test ecx, ecx
00C7EAB5 74 09 je short 00C7EAC0
00C7EAB7 8901 mov dword ptr , eax
00C7EAB9 83C1 04 add ecx, 4
00C7EABC 894C24 14 mov dword ptr , ecx
00C7EAC0 33C0 xor eax, eax
00C7EAC2 66:8B03 mov ax, word ptr
00C7EAC5 50 push eax
00C7EAC6 68 FF000000 push 0FF
00C7EACB 57 push edi
00C7EACC E8 5D8DFFFF call 00C7782E
00C7EAD1 66:C703 0000 mov word ptr , 0
00C7EAD6 8B7C24 10 mov edi, dword ptr
00C7EADA 3BEE cmp ebp, esi
00C7EADC 74 08 je short 00C7EAE6
00C7EADE 6A 04 push 4
00C7EAE0 55 push ebp
00C7EAE1 E8 B27FFFFF call 00C76A98
00C7EAE6 8B5C24 18 mov ebx, dword ptr
00C7EAEA 83C5 04 add ebp, 4
00C7EAED 83C6 04 add esi, 4
00C7EAF0^ E9 98F9FFFF jmp 00C7E48D ; 这里是DLL 里的各个函数循环
00C7EAF5 E8 8E7DFFFF call 00C76888
00C7EAFA 8B7424 20 mov esi, dword ptr
00C7EAFE 8B5424 3C mov edx, dword ptr
00C7EB02 8B4E 04 mov ecx, dword ptr
00C7EB05 51 push ecx
00C7EB06 68 FF000000 push 0FF
00C7EB0B 52 push edx
00C7EB0C E8 1D8DFFFF call 00C7782E
00C7EB11 6A 14 push 14
00C7EB13 56 push esi
00C7EB14 E8 7F7FFFFF call 00C76A98
00C7EB19 83C6 14 add esi, 14
00C7EB1C 8B5C24 14 mov ebx, dword ptr
00C7EB20 8B6C24 34 mov ebp, dword ptr
00C7EB24 897424 20 mov dword ptr , esi
00C7EB28^ E9 92F7FFFF jmp 00C7E2BF ; 这里是程序调用的各个DLL 循环
00C7EB2D 8B8424 4C040000 mov eax, dword ptr ; 走到这里就得到了一个完整的IAT了
00C7EB34 85C0 test eax, eax
走到这里了,我们就可以修复IAT了
填上OEP ,自动查找IAT 就可以了,然后转存,保存文件。
运行,程序能正常跑起来。脱壳完毕
--------------------------------------------------------------------------------
【经验总结】
老壳还是有些值得分析的价值的,这个壳的反调试的方法在其他的壳里也存在,所以,脱壳,单步跟踪分析壳的原理才是脱
壳的王道。
小小脱文,没什么太多的技术含量,大牛们飞过哈。呵呵
--------------------------------------------------------------------------------
【版权声明】: 本文原创于http://www.52pojie.cn, 转载请注明作者并保持文章的完整, 谢谢!
2009年12月12日 19:02:18 膜拜大侠,完全看不懂~ 支持一个 学习下。 不容易啊,呵呵,得到精华,自己庆祝下,来到LCG 有点时间了,没有啥贡献,对不住大家哈 楼主写了这么牛的文章还如此谦虚,让我等膜拜。 强悍的人。 厉害啊,进来膜拜一下 进来学习学习:loveliness: 强悍的人。 确定是你写的吗?我看着很眼熟 这个壳版本比较低但是特别不好的脱 我现在破的这个软件 就在这卡住了 一点头绪都没有
页:
[1]
2