文章来源 : 安全中国
首先感谢shoooo,forgot,fly的指点。
本来的试练品是一个XX的XX服务端,体积有点大,无法上传,有需要的请留言. 可以用附件中的abest写的一个专门用来练习脱壳的小程序代替(因为不是二次加密所以IAT需要修复). http://www.cracking.com.cn/dispbbs.asp?boardid=4&id=827&star=1#827
下面的过程是按脱服务端的过程写的. 已知: 1.这个是2次加密的,不会用SDK. 2.VC编译的
step0.抹掉TLS表 用lord-PE把数据目录(Directories)中TLS一项全部置0,然后save. 注意:不能把TLS CALLBACK ADDRESS 和TLS CALLBACK INDEX置0 !!!!(why?I Don’t Know)
BTW:这个"秘密"是forgot广播的.
step1. 经过step0后,就不用设置让OD停在系统断点了(设置停在EP).而且TLS中的"飞刀"也不用管了.但是还需要一个"核武器"----advencedolly插件.加上这个插件,EXEC的anti可以全过.
但是,本次脱壳用hideOD就可以了,因为我们没有KEY,无法跑到后面,也不需要跑到后面.所以很多anti是没有用的.
step2. 步骤其实很简单,经过上面的准备后.用OD载入,忽略所有异常:
0BB8CE4E > E8 F7FEFFFF call 0BB8CD4A 0BB8CE53 05 07480000 add eax, 4807 0BB8CE58 FFE0 jmp eax 0BB8CE5A E8 EBFEFFFF call 0BB8CD4A 0BB8CE5F 05 9F6A0000 add eax, 6A9F 0BB8CE64 FFE0 jmp eax 0BB8CE66 E8 04000000 call 0BB8CE6F 0BB8CE6B FFFF ??? ; 未知命令 0BB8CE6D FFFF ??? ; 未知命令 0BB8CE6F 5E pop esi 0BB8CE70 C3 retn
然后 1.HE GetProcAddress 2.F9 3.HD GetProcAddress 4.alt+f9 现在我们到了填充IAT的地方了:
0BB8CBE7 55 push ebp 0BB8CBE8 8BEC mov ebp, esp 0BB8CBEA 83C4 F4 add esp, -0C 0BB8CBED 56 push esi 0BB8CBEE 57 push edi 0BB8CBEF 53 push ebx 0BB8CBF0 BE 00F0AD0A mov esi, 0AADF000 0BB8CBF5 B8 00004000 mov eax, 00400000 0BB8CBFA 8945 FC mov dword ptr ss:[ebp-4], eax 0BB8CBFD 89C2 mov edx, eax 0BB8CBFF 8B46 0C mov eax, dword ptr ds:[esi+C] 0BB8CC02 09C0 or eax, eax 0BB8CC04 0F84 8E000000 je 0BB8CC98 0BB8CC0A 01D0 add eax, edx 0BB8CC0C 89C3 mov ebx, eax 0BB8CC0E 50 push eax 0BB8CC0F FF15 B480AA0B call dword ptr ds:[<&kernel32.GetModu>; kernel32.GetModuleHandleA 0BB8CC15 09C0 or eax, eax 0BB8CC17 0F85 0F000000 jnz 0BB8CC2C 0BB8CC1D 53 push ebx 0BB8CC1E FF15 B880AA0B call dword ptr ds:[<&kernel32.LoadLib>; kernel32.LoadLibraryA 0BB8CC24 09C0 or eax, eax 0BB8CC26 0F84 64000000 je 0BB8CC90 0BB8CC2C 8945 F8 mov dword ptr ss:[ebp-8], eax 0BB8CC2F 6A 00 push 0 0BB8CC31 8F45 F4 pop dword ptr ss:[ebp-C] 0BB8CC34 8B06 mov eax, dword ptr ds:[esi] 0BB8CC36 09C0 or eax, eax 0BB8CC38 8B55 FC mov edx, dword ptr ss:[ebp-4] 0BB8CC3B 0F85 03000000 jnz 0BB8CC44 0BB8CC41 8B46 10 mov eax, dword ptr ds:[esi+10] 0BB8CC44 01D0 add eax, edx 0BB8CC46 0345 F4 add eax, dword ptr ss:[ebp-C] 0BB8CC49 8B18 mov ebx, dword ptr ds:[eax] 0BB8CC4B 8B7E 10 mov edi, dword ptr ds:[esi+10] 0BB8CC4E 01D7 add edi, edx 0BB8CC50 037D F4 add edi, dword ptr ss:[ebp-C] 0BB8CC53 09DB or ebx, ebx 0BB8CC55 0F84 E2000000 je 0BB8CD3D 0BB8CC5B F7C3 00000080 test ebx, 80000000 0BB8CC61 0F85 04000000 jnz 0BB8CC6B 0BB8CC67 8D5C13 02 lea ebx, dword ptr ds:[ebx+edx+2] 0BB8CC6B 81E3 FFFFFF7F and ebx, 7FFFFFFF 0BB8CC71 53 push ebx 0BB8CC72 FF75 F8 push dword ptr ss:[ebp-8] 0BB8CC75 FF15 BC80AA0B call dword ptr ds:[<&kernel32.GetProc>; kernel32.GetProcAddress 0BB8CC7B 09C0 or eax, eax ; WS2_32.send //我们现在停在这里 0BB8CC7D 0F84 0D000000 je 0BB8CC90 0BB8CC83 8907 mov dword ptr ds:[edi], eax 0BB8CC85 8345 F4 04 add dword ptr ss:[ebp-C], 4 0BB8CC89 ^ E9 A6FFFFFF jmp 0BB8CC34 0BB8CC8E 0000 add byte ptr ds:[eax], al 0BB8CC90 53 push ebx 0BB8CC91 89D8 mov eax, ebx 0BB8CC93 E8 07000000 call 0BB8CC9F 0BB8CC98 5B pop ebx //走到这里后IAT就填充完毕了,在这里F4 0BB8CC99 5F pop edi 0BB8CC9A 5E pop esi 0BB8CC9B 8BE5 mov esp, ebp 0BB8CC9D 5D pop ebp 0BB8CC9E C3 retn
观察上面代码发现,者个函数就是填充IAT的函数,退出这个函数后IAT就处理完了.所以在0BB8CC98 上F4走完这个函数.
BTW:论坛上看到过几位牛人讨论无KEY脱exec,再出来注册框之前,所有东西都解码完毕了.
我想一般的壳填充IAT都是最后一步,于是我就去看看代码段是否解码完了.果然全部代码都解出来了.
step3.修复stolen code
再次感谢shoooo,forgot的指点.
因为IAT已经填充完,而且没有加密.根据VC的启动代码都会call GetVersion,所以根据IAT反查出Call GetVersion的地址:
00529265 - E9 E4ED5E0A jmp 0AB1804E 0052926A 8BC2 mov eax, edx 0052926C 5A pop edx 0052926D - E9 8EDD5B0A jmp 0AAE7000 00529272 C1FC 56 sar esp, 56 00529275 BE 948B56E8 mov esi, E8568B94 0052927A 50 push eax 0052927B 64:8925 0000000>mov dword ptr fs:[0], esp 00529282 83EC 58 sub esp, 58 00529285 53 push ebx 00529286 56 push esi 00529287 57 push edi 00529288 8965 E8 mov dword ptr ss:[ebp-18], esp 0052928B FF15 34FDAD0A call dword ptr ds:[AADFD34] ; kernel32.GetVersion //See?See! 00529291 33D2 xor edx, edx 00529293 8AD4 mov dl, ah
根据VC的OEP的特称,可以断定00529265是OEP. 但是被stolen了5行 应该是 push ebp mov ebp,esp push -1 push imm32 push imm32 ...........
关键就是这两个imm32是多少.如果有KEY可以让程序跑起来断在后在,通过堆栈的值来修复这两个数.但问题是,我们没有KEY,程序无法运行.
我请教了forgot,问这两个imm32有没有办法找出来.他说这是VC的机制,是个xxx表.由于我愚钝,似懂非懂.后来遇上了shoooo.shoooo说这就是VC封装的SEH.想弄清楚就自己写个
__try,__except来看看.
于是豁然开朗~
我大体说一下怎么找这两imm32(为什么这样找?自己写个__try,__except看看就明白了,还有就是看看Crt.c或者crt0.c的源码.)
[1] [2] 下一页 |