手動脫掉Asprotect的殼,(給初學者的) (9千字)

看雪資料發表於2002-01-24

已經好久沒有寫東西了,呵呵,人懶沒辦法啊,不過我現在在學脫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,所以破解起來很難,唉~~也許此次脫殼唯一得到
的就是你可以反彙編它了:(

相關文章