手动脱HTMLZip的壳(asprotect)
有幸认识了hying兄,结果hying兄教了我如下方法进行Asprotect1.1版本以上的脱壳。
hying兄要我成功后贴个贴子,我的文笔不好,只好迎着头皮上了。
软件: HTMLZip 1.0 Beta (下载地址为:)
工具: TRW2000
TRW2000装入程序,一直到下面的连续五个Call应该如何跟,还是等Hying兄的文章吧。
告诉大家一个偷懒的办法,如果前面跟了很久也没看到这5个call的典型地方,就按F12,
一次一次地按,直到按下F12后要等将近10秒甚至更多时间才回到trw时,就按F8,
这就到了。:)
(我的系统是WinMe,其他系统会有不同的xxxx:xxxxxxxx)
016F:01110684 PUSH EBP
016F:01110685 MOV EBP,ESP
016F:01110687 ADD ESP,BYTE -0C
016F:0111068A CALL 01102F7C
016F:0111068F JNZ NEAR 01103C58
016F:01110695 CALL 01104114
016F:0111069A CALL 01108894
016F:0111069F CALL 01109224
016F:011106A4 CALL 0110B584
016F:011106A9 CALL 01103C58 <-------- 这个Call进去。
016F:011106AE MOV ESP,EBP
016F:011106B0 POP EBP
进去后按F10跟,期间能够遇到2个Call,都用F10带过,当走过第二个RET后,
(懒人可按F12, F8, F12, F8)
代码会变成:
016F:0110F4CA MOV EAX,[ESP+0C]
016F:0110F4CE JMP SHORT 0110F4D1
016F:0110F4D1 ADD DWORD [EAX+B8],BYTE +02
016F:0110F4D8 JMP SHORT 0110F4F4
下面两行动态生成:
016F:0110F4F4 XOR EAX,EAX
016F:0110F4F6 RET <--------停,看stack窗口,会看到xxxxxxxx:BFFxxxxxx
016F:0110FC4F CALL 0110D304
016F:0110FC54 CMP DWORD [01112578],BYTE +00
然后下u命令翻页,在最近的地方设断点。
此时能看到如下代码:(110F4F4,110F4F6为动态生成,翻页后就不见了。)
016F:0110F51F PUSH DWORD 0110F600
016F:0110F524 PUSH DWORD 0110EF20
016F:0110F529 PUSH DWORD 0110EBC8
016F:0110F52E PUSH DWORD 0110E58C
016F:0110F533 PUSH DWORD 0110E118
016F:0110F538 PUSH DWORD 0110F27C
016F:0110F53D RET <------- 在这里下断点,然后G可到这里。
bd这个断点,再F8。以下用F10走,看见类似于
016F:0110F4CA MOV EAX,[ESP+0C]
016F:0110F4CE JMP SHORT 0110F4D1
016F:0110F4D1 ADD DWORD [EAX+B8],BYTE +02
016F:0110F4D8 JMP SHORT 0110F4F4
016F:0110F4F4 XOR EAX,EAX
016F:0110F4F6 RET <---------------停,看stack窗口,会看到xxxxxxxx:BFFxxxxxx
就翻页找最近的RET,重复下断点,F5, bd断点,F8继续。
如此大约我进行了7次。
======================以上就是hying兄教我的方法=============================
再接着往下说之前先讲个跟踪原则:
*************************************************
* xxxx:AAAAAAAA CALL BBBBBBBB
*
* 当跟踪时看到一个Call的时候,要看看 *
* BBBBBBBB是不是比AAAAAAAA大,如果是, *
* 用F8;如果不是,用F10带过。 *
*************************************************
(当然,原则会有例外,下面会讲到什么情况下原则不适用。)
现在开始,利用上面说的原则,用F8或者F10追吧。
到了这里需要注意了,下面这段代码细看和我们前面遇上的有些不同。
016F:0110F263 RET
016F:0110F264 MOV EAX,0111290C
016F:0110F269 MOV EDX,0A
016F:0110F26E CALL 0110B8D4 <------- 离110F26E很远
016F:0110F273 CALL 0110F0E4 <------- 离110F273很近,这个Call一定用F8进去,否则GameOver。
016F:0110F278 RET
*********************************************************
* 这就是原则例外(1). 当看见两个Call并在一起, *
* BBBBBBBB都<AAAAAAAA,但是第二个CALL的
*
* BBBBBBBB和AAAAAAAA相差不如第一个悬殊,用F8。 *
*********************************************************
很快会走到这里,看到USER32!MessageBoxA,标志着离终点不远了。
016F:0110F1EE PUSH BYTE +00
016F:0110F1F0 CALL `USER32!MessageBoxA` <--------
注意!!!!!!!!!!!!!!!!
016F:0110F1F5 CALL 01102CDC
016F:0110F1FA XOR EAX,EAX
016F:0110F1FC POP EDX
016F:0110F1FD POP ECX
016F:0110F1FE POP ECX
016F:0110F1FF MOV [FS:EAX],EDX
016F:0110F202 JMP SHORT 0110F20E
016F:0110F204 JMP 01102B70
往下慢慢走,继续遵循我们的原则,来到这里,这是1126C1执行以前的代码:
016F:01126C61 CALL 01126C7E <---- 观察下面代码,是不是很“乱”?
这里一定用F10带,F8就GameOver了。
016F:01126C66 NOP
016F:01126C67 MOV BH,86
016F:01126C69 MOV EDI,GS
016F:01126C6B CALL 1A22A1A4
016F:01126C70 DB FF
016F:01126C71 JNG 01126C3D
016F:01126C73 ROR DWORD [ECX+EDX],E2
016F:01126C77 HLT
016F:01126C78 MOV BH,1A
016F:01126C7A REPNE POP EDI
016F:01126C7C IDIV DWORD [EBX]
016F:01126C7E AND EAX,BYTE -68
*************************************************
* 这里是原则例外(2),
*
* 走过USER32!MessageBoxA以后, *
* 看到类似上面这个Call,下面代码很“乱” *
* 一定用F10带过。
*
*************************************************
这就是F10执行1126C1以后的代码:
016F:01126C61 CALL 01126C7E
016F:01126C66 POP EBX
016F:01126C67 POP EAX
016F:01126C68 ADD EAX,33371CB8
016F:01126C6D POP ESP
016F:01126C6E OR ECX,ECX
016F:01126C70 JZ 01126C55
016F:01126C72 MOV [ECX],EAX
016F:01126C74 ADD EAX,EBX
016F:01126C76 MOV [ESP+1C],EAX
016F:01126C7A POPA
016F:01126C7B JMP EAX <------- 终于到家了,注意Eax的值,这就是入口值。
以上这个原则其实是hying兄方法的复杂操作,但是有时遇上
xor eax, eax
ret
最近的ret只能断一次时,就有用了。比如PictureToExe这个东东的asprotect脱壳。
用上述原则,就能成功脱掉Asprotect。
想作练习的话,可以找Advanced System Agent,前面有人在论坛上要求脱壳的,虽然
可以用冲击波,不过练习一下纯手动脱壳也不失为一个好教材。