• 标 题:手动脱掉Asprotect的壳,(给初学者的) (9千字)
  • 作 者:TAE!
  • 时 间:2002-1-24 15:40:54
  • 链 接:http://bbs.pediy.com

已经好久没有写东西了,呵呵,人懒没办法啊,不过我现在在学脱asprotect得壳,研究了几天,
对付些简单得已经没问题了,所以这里写篇文章给初学脱asprotect这冬冬得cracker.
感谢zombieys,blowfish,小球对我的帮助!
目标软件是个叫做icon catcher 3得软件,是抓图标用的

用trw载入软件,然后load,来到了这里:
0167:00401000 6801604D00      PUSH    DWORD 004D6001
0167:00401005 E801000000      CALL    0040100B
0167:0004100A C3              RET
上面的那个call是可以用f10带过去的,再按一次f10就来到了上面的ret,然后返回到了下面这个地方:
0167:004D6001 60              PUSHA 
0167:004D6002 E803000000      CALL    004D600A
0167:004D6007 E9EB045D45      JMP      45AA64F7
上面的这个call 004d600a是一定要进入的,因为大客们说过这个call相当于是jmp,瞧,call 004d600a
这个地址(004d600a)是不是离此指令的地址(004d6002)很近呢?以后看到这样的地址都要用f8进入,建
议以后跟踪的时候用f8键.
以后跟踪要主意的地方就是,看到程序向上跳的时候,就在跳转指令的下面一行按f9设置断点,返回f5继
续运行,这样一般都能跳过循环
0167:004D60C4 BEE70FD372      MOV      ESI,72D30FE7
0167:004D60C9 5E              POP      ESI
0167:004D60CA 81C32903B24D    ADD      EBX,4DB20329
0167:004D60D0 80D6DF          ADC      DH,DF
0167:004D60D3 8919            MOV      [ECX],EBX
0167:004D60D5 80CA71          OR      DL,71
0167:004D60D8 83E901          SUB      ECX,BYTE +01
0167:004D60DB 49              DEC      ECX
0167:004D60DC 49              DEC      ECX
0167:004D60DD 49              DEC      ECX
0167:004D60DE 81E801000000    SUB      EAX,01
0167:004D60E4 0F859EFFFFFF    JNZ      NEAR 004D6088            (JUMP)这个会向"上"跳
0167:004D60EA 68EBFDE75C      PUSH    DWORD 5CE7FDEB
那个jnz near 004d6008会向上面跳转,所以这时你就应该在他的下面一行,也就是push dword 5ce7fdeb
这里设置一个断点,然后按f5,之后程序就会被中断到这里了.

但是还有下面这种情况要主意!
0167:004D6242 58              POP      EAX
0167:004D6243 81EA4EBACE4B    SUB      EDX,4BCEBA4E
0167:004D6249 0FBFF6          MOVSX    ESI,SI
0167:004D624C 81C24ABACE4B    ADD      EDX,4BCEBA4A
0167:004D6252 8BF7            MOV      ESI,EDI
0167:004D6254 81FAACF9FFFF    CMP      EDX,FFFFF9AC
0167:004D625A 0F8516000000    JNZ      NEAR 004D6276            (JUMP)
0167:004D6260 6880C8D167      PUSH    DWORD 67D1C880
0167:004D6265 6681C7755D      ADD      DI,5D75
0167:004D626A 5E              POP      ESI
0167:004D626B E921000000      JMP      004D6291
0167:004D6270 D6              SALC   
虽然jnz near 004d6276是向"下"跳转的,但是当你跳到那里的时候你会发现那里又会有个jmp xxxxx
而且跳转的方向是向上面的,然后你就又会回到上面那段代码,所以这时候你应该在jmp 004d6291那行
设置一个断点,然后f5让程序运行,此时程序又会被中断了:)而且你跳过了那讨厌的循环了,后面像这样
的情况还非常多,一定要注意!
0167:004D6604 8B31            MOV      ESI,[ECX]
0167:004D6606 03F2            ADD      ESI,EDX
0167:004D6608 E82F000000      CALL    004D663C
0167:004D660D BFA75125B7      MOV      EDI,B72551A7
0167:004D6612 3BC7            CMP      EAX,EDI
0167:004D6614 7405            JZ      004D661B        //瞧这个,刚开始的时候这里是不跳的
0167:004D6616 83C104          ADD      ECX,BYTE +04
0167:004D6619 EBE9            JMP      SHORT 004D6604  //又是个循环!
0167:004D661B XXXX            XXXXXXXXXXXXXXXXXXXXXX    //所以在这里设置断点,
后面几乎每个call都要用f8进入,但是如果碰到下面这样的call,你就可以放心大胆的用f10带过去了!
0167:004D64CB FF9560020000    CALL    NEAR [EBP+0260]  //f10带过!
0167:004D64D1 898575010000    MOV      [EBP+0175],EAX
0167:004D64D7 8B9D6C020000    MOV      EBX,[EBP+026C]
如果你已经跟踪到上面这段代码的话,就可以按f12直接结束这段代码,然后返回到这里:
0167:00C77001 60              PUSHA 
0167:00C77002 E840060000      CALL    00C77647
0167:00C77007 EB44            JMP      SHORT 00C7704D

这时你也可以再按一次f12,然后到了这里:
0167:00C77388 8BB575294400    MOV      ESI,[EBP+00442975]
0167:00C7738E 33DB            XOR      EBX,EBX
0167:00C77390 0BC9            OR      ECX,ECX
0167:00C77392 741C            JZ      00C773B0
0167:00C77394 781A            JS      00C773B0
0167:00C77396 AC              LODSB 
0167:00C77397 3CE8            CMP      AL,E8
0167:00C77399 7408            JZ      00C773A3
0167:00C7739B 3CE9            CMP      AL,E9
0167:00C7739D 7404            JZ      00C773A3
0167:00C7739F 43              INC      EBX
0167:00C773A0 49              DEC      ECX
0167:00C773A1 EBED            JMP      SHORT 00C77390
上面这段代码好像在哪里见过?对了,aspack有相同的一段代码,原来这里就是程序解压缩自身的地方,
相信应该难不到你吧:)如果你很懒,那么就直接f12跳过这里吧!可能要等上几秒中哦~然后就来到了一
个asprotect壳的一个标志性的地方:
0167:00C71044 55              PUSH    EBP
0167:00C71045 8BEC            MOV      EBP,ESP
0167:00C71047 83C4F4          ADD      ESP,BYTE -0C
0167:00C7104A E8E120FFFF      CALL    00C63130
0167:00C7104F 0F85F72DFFFF    JNZ      NEAR 00C63E4C
0167:00C71055 E8AE32FFFF      CALL    00C64308
0167:00C7105A E8697AFFFF      CALL    00C68AC8
0167:00C7105F E8F883FFFF      CALL    00C6945C
0167:00C71064 E827AFFFFF      CALL    00C6BF90
0167:00C71069 E8DE2DFFFF      CALL    00C63E4C
0167:00C7106E 8BE5            MOV      ESP,EBP
0167:00C71070 5D              POP      EBP
0167:00C71071 C20C00          RET      0C
其实要想快速定位到这个地方,还是有捷径的:)这样:
设置一个断点getversionexa,然后运行程序,这时程序会被中断,但是前面两次中断全是在系统中,第三次
中断时就是在程序内部了,这时要用f10慢慢走,几个ret返回后你就到了0167:00C7106E    MOV  ESP,EBP
这样你就直接在00c71069那一行设置断点吧,是不是很方便?嘿嘿~~~记住最后一个call一定要用f8进入!
进去后一直按f10直到一个ret返回,那时你会看见有很多连续的call,大概是七八个吧.(不知为啥,俺用trw
不能抓取这段代码?)进入最后一个!就到了这儿,
0167:00C6FB80 B8BC39C700      MOV      EAX,00C739BC
0167:00C6FB85 BA0A000000      MOV      EDX,0A
0167:00C6FB8A E889C7FFFF      CALL    00C6C318
0167:00C6FB8F E82CFEFFFF      CALL    00C6F9C0
0167:00C6FB94 C3              RET   
还是进入最后一个call,一直按f10,直到再次出现两个连续的call,像这样:
0167:00C6FB0D BA04000000      MOV      EDX,04
0167:00C6FB12 E859C9FFFF      CALL    00C6C470
0167:00C6FB17 E815000000      CALL    00C6FB31
同样还是要进入最后一个call(很有规律是吧:)0167:00C6FB60 FF75FC          PUSH    DWORD [EBP-04]
0167:00C6FB63 FF75F8          PUSH    DWORD [EBP-08]
0167:00C6FB66 8B45F4          MOV      EAX,[EBP-0C]
0167:00C6FB69 833800          CMP      DWORD [EAX],BYTE +00
0167:00C6FB6C 7402            JZ      00C6FB70
0167:00C6FB6E FF30            PUSH    DWORD [EAX]
0167:00C6FB70 FF75F0          PUSH    DWORD [EBP-10]
0167:00C6FB73 FF65EC          JMP      NEAR [EBP-14]    //^_^大客们都说看到这个就快到oep了!
0167:00C6FB76 5F              POP      EDI
但是,如果你想手动跟踪到oep的话还是挺麻烦的,其实用softice加icedump好像就可以直接定位到oep了,不过
俺没试过,呵呵,俺都是跟踪到oep的.因为只有这样才能熟习壳的状况,否则哪天icedump不灵了,就傻了?所以
还是跟我来吧!
0167:00C8321E 5B              POP      EBX
0167:00C8321F 58              POP      EAX
0167:00C83220 0561098106      ADD      EAX,06810961
0167:00C83225 5C              POP      ESP
0167:00C83226 03C3            ADD      EAX,EBX
0167:00C83228 8944241C        MOV      [ESP+1C],EAX
0167:00C8322C 61              POPA                  //入口点地址
0167:00C8322D FFE0            JMP      EAX          //跳到程序入口点(OEP)

我这里的入口点是4a0ac4,一定要记住哦,这时在4a0ac4这一行,下命令pedump c:\icdump.exe
然后下命令suspend,运行Imprec1.4,在Attach to an Active Process这个下拉菜单中选择ic.exe
在oep中输入0a0ac4(4a0ac4-400000),点iat autosearch,最后点get imports,然后再autotrace,
然后show invalid,这时发现有五个函数没有被修复,就是zombieys大哥常说的那五个,
1    000A51CC    ?    0000    00C6C94C
2    000A52E8    ?    0000    00C6C954
3    000A5324    ?    0000    00C6C914
4    000A536C    ?    0000    00C6C944
5    000A5374    ?    0000    00C6C960
这时ctrl+n输入u 00c6c94c(因为此时你的ic处于挂起状态,所以可以直接看,否则你得先进入程序凌空!),这时看到的内容如下,
0167:00C6C94C A14036C700      MOV      EAX,[00C73640]//**注意这个!
0167:00C6C951 C3              RET
此时用ctrl+pageup向上翻几页可以看到如下代码:
   
0167:00C6C7BA 8BC0            MOV      EAX,EAX
0167:00C6C7BC 6A00            PUSH    BYTE +00
0167:00C6C7BE E8897CFFFF      CALL    `KERNEL32!GetModuleHandleA`
0167:00C6C7C3 A34C36C700      MOV      [00C7364C],EAX
0167:00C6C7C8 E8977CFFFF      CALL    `KERNEL32!GetVersion`
0167:00C6C7CD A34436C700      MOV      [00C73644],EAX
0167:00C6C7D2 68AC35C700      PUSH    DWORD 00C735AC
0167:00C6C7D7 E8907CFFFF      CALL    `KERNEL32!GetVersionExA`
0167:00C6C7DC E83B7CFFFF      CALL    `KERNEL32!GetCurrentProcess`
0167:00C6C7E1 A34836C700      MOV      [00C73648],EAX
0167:00C6C7E6 E8397CFFFF      CALL    `KERNEL32!GetCurrentProcessId`
0167:00C6C7EB A35036C700      MOV      [00C73650],EAX
0167:00C6C7F0 E81F7CFFFF      CALL    `KERNEL32!GetCommandLineA`
0167:00C6C7F5 A34036C700      MOV      [00C73640],EAX      //**呵呵,和上面一样得哟~~
0167:00C6C7FA C3              RET   
这些是asprotect壳运行时调用程序将要使用得函数然后将其保存在内存中,这样就使得imprec
不能正确识别这些函数了.
所以呢,第一个未知函数应该是getcommandlinea,
blowfish大哥说第二个应该是lockresource
第三个是getversion
第四个是GetCurrentProcessId
第五个是freeresource(我也不知道为什么?)
最后将这些一一对应得填入imprec中选择fixdump,即可,程序可以运行了,脱壳完毕!
虽然脱壳已经完成,但是我仍然没有能力破解它,听zombieys哥说,这样的程序都是用
注册码来给自身解密的,也就是smc,所以破解起来很难,唉~~也许此次脱壳唯一得到
的就是你可以反汇编它了:(