IconEdit2 v2.3脫殼實錄

看雪資料發表於2010-08-13

IconEdit2 脫殼,Asprotect的脫殼高手們已經寫過很過了,我菜鳥也湊個
熱鬧,多少給和我一樣菜的同志們借鑑一下,也希望高手們多多指教。

IconEdit2(v2.3)的殼很有意思,用FI245查出是Asprotect1.3的,用FI249查
出是Asprotect1.21的,估計FI249可能會準確一點吧(可是我覺得FI249沒有
FI245好用,所以很少用,只有245查不到的時候才用,^_^)
IconEdit2(v2.4)的殼是Asprotect1.22的,大家都差不多,就那v2.3開刀吧。

因為以前跟過1.2的殼,這次碰到個1.3的(也不知道真的假的),也跟一跟,
我是從頭到尾一個勁的傻跟了一遍,沒設過API斷點(其實也不知具體該設什
麼),最後終於到達OEP,感覺和1.2版的殼差別不大。具體跟蹤細節我這裡
就不說了,高手們有很多文章了。而且這個程式是Delphi寫的,可以用快速
找OEP的方法快速脫殼。我來說說dump出來以後的事情。

從OEP處dump出iEditu.exe,由於Asprotect對import table做了破壞,所以
程式不能執行,必須修復IAT,ImportREC142是個好東東,可以很快很方便的
修復IAT,就用它來做。在Process下拉欄選擇執行的程式(執行脫殼前的程式)
然後在OEP欄輸入我們得到的OEP值(0x00491D80),注意不要加base,即491D80
接著就IAT Autosearch,提示說找到,跟著Get Imports,視窗裡看到了很多
找到的引入函式,用Show Invalid看到一些未解析到的,在其上面點滑鼠右鍵
選Trace Level1,哇,又解析出一大堆來,還剩10個左右,再用右鍵的Plugin
Tracer,嘿嘿,Congratulation! 全部解析成功。暗暗竊喜... 最後就是 Fix
Dump,當然最好選中Add new section。生成修復過的檔案iEditu_.exe

滿懷熱情的雙擊執行,咦,什麼反應都沒有?考,是不是滑鼠壞了,咚咚咚,
幫幫幫......還好沒真把我的滑鼠敲壞了。冷靜下來開始分析,好像記得哪位
大俠說過“一執行就退出,一看就是CRC”。唉,看來這回是遇到棘手的了,
沒辦法,跟一跟了。入口如下:

018F:00491D80  PUSH     EBP          <-- OEP
018F:00491D81  MOV      EBP,ESP
018F:00491D83  ADD      ESP,BYTE -0C
018F:00491D86  PUSH     EBX
018F:00491D87  PUSH     ESI
018F:00491D88  PUSH     EDI
018F:00491D89  MOV      EAX,00491B30
018F:00491D8E  CALL     00406AD4
018F:00491D93  XOR      EAX,EAX
018F:00491D95  PUSH     EBP
018F:00491D96  PUSH     DWORD 00491E14
018F:00491D9B  PUSH     DWORD [FS:EAX]
018F:00491D9E  MOV      [FS:EAX],ESP
018F:00491DA1  CALL     0048A390
018F:00491DA6  MOV      EAX,[004938C4]
018F:00491DAB  MOV      EAX,[EAX]
018F:00491DAD  CALL     00448FC8
018F:00491DB2  CALL     0048A410
018F:00491DB7  MOV      EAX,[004938C4]
018F:00491DBC  MOV      EAX,[EAX]
018F:00491DBE  MOV      EDX,00491E30
018F:00491DC3  CALL     00448BCC
018F:00491DC8  CALL     0048A438       <-- F10帶過就沒了(1)
018F:00491DCD  MOV      EAX,[004938C4]
018F:00491DD2  MOV      EAX,[EAX]
018F:00491DD4  ADD      EAX,BYTE +40
018F:00491DD7  MOV      EDX,00491E44
018F:00491DDC  CALL     00403B8C
018F:00491DE1  CALL     0048A480        <-- F10帶過也沒了(2)
018F:00491DE6  MOV      ECX,[00493714]
018F:00491DEC  MOV      EAX,[004938C4]
018F:00491DF1  MOV      EAX,[EAX]
018F:00491DF3  MOV      EDX,[0048BA8C]
018F:00491DF9  CALL     00448FE0        <-- F10帶過還是沒了(3)
018F:00491DFE  MOV      EAX,[004938C4]
018F:00491E03  MOV      EAX,[EAX]
018F:00491E05  CALL     00449060        <-- 這裡主程式開始執行
018F:00491E0A  XOR      EAX,EAX

F8進到第(1)個CALL看看,如下:

018F:0048A438  PUSH     EBP
018F:0048A439  MOV      EBP,ESP
018F:0048A43B  PUSH     ECX
018F:0048A43C  MOV      BYTE [EBP-01],00
018F:0048A440  MOV      EAX,[00493624]
018F:0048A445  CMP      BYTE [EAX],00
018F:0048A448  JNZ      0048A463
018F:0048A44A  PUSH     ESI
018F:0048A44B  MOV      ESI,[004944D8]     <--這裡取基址400000
018F:0048A451  MOV      EAX,[ESI+3C]
018F:0048A454  MOV      EAX,[ESI+EAX+28]   <--EAX為OEP
018F:0048A458  CMP      AX,1000            <--OEP不為1000就退出
018F:0048A45C  JZ       0048A462           <--改這裡強行跳走。
018F:0048A45E  OR       BYTE [EBP-01],01
018F:0048A462  POP      ESI
018F:0048A463  CMP      BYTE [EBP-01],00
018F:0048A467  JZ       0048A47C
018F:0048A469  XOR      ECX,ECX
018F:0048A46B  MOV      DL,01
018F:0048A46D  MOV      EAX,[00407B60]
018F:0048A472  CALL     0040BA4C
018F:0048A477  CALL     00403608
018F:0048A47C  POP      ECX
018F:0048A47D  POP      EBP
018F:0048A47E  RET    

再進到第(2)個CALL看看,如下:

018F:0048A480  PUSH     EBP
018F:0048A481  MOV      EBP,ESP
018F:0048A483  PUSH     ECX
018F:0048A484  PUSH     EBX
018F:0048A485  MOV      EAX,[00406C4A]
018F:0048A480  PUSH     EBP
018F:0048A481  MOV      EBP,ESP
018F:0048A483  PUSH     ECX
018F:0048A484  PUSH     EBX
018F:0048A485  MOV      EAX,[00406C4A]
018F:0048A48B  MOV      EBX,[EAX]
018F:0048A48D  PUSH     DWORD [EBX]   \ 這個push和pop沒什麼意義,
018F:0048A48F  MOV      [EBP-04],EBX  | 我估計也是用來檢查脫殼的,
018F:0048A492  POP      DWORD [EBX]   / 這時EBX=BFFxxxxx,異常。
018F:0048A494  MOV      EAX,[EBP-04]    把Push和Pop都NOP掉。
018F:0048A497  POP      EBX
018F:0048A498  POP      ECX
018F:0048A499  POP      EBP
018F:0048A49A  RET    

改了這兩個地方後,覺得該行了吧,沒想到到(3)的CALL又死悄悄了。真讓人
上火,它到底要設多少陷阱呀!這個CALL可是個很大的呀,用原版帶過也要
等一陣才過來的,進去以後簡直像進了一個無底洞,半天出不來,而且也看
不到什麼可疑的類似CRC的校驗地方。這可真是大海撈針呀!用脫殼後的程式
跟進去,一不留神就退出了,發現都是產生異常而退出的,基本排除有CRC校
驗的保護。

一籌莫展之際,dede反編譯,發現這個CALL似乎是來建立資源的,難道是資源
在脫殼中有什麼不測?然後用一些資源編譯器試著編輯一下,果然有很多異常
現象。初步認為是ASPR對資源做了特殊壓縮,這樣可麻煩了。用procdump查知
.rsrc段RVA是4A4000,size是7D000,載入原版在OEP中斷,看看資源段,一切
正常,乾脆把它都dump出來,隨即dump出個rsrc.bin準備替換脫殼版的.rsrc段
可是一看原來一模一樣,那還換個什麼勁呀。再載入脫殼後的程式停在入口,
看資源段,咦?發現只有4A4000到4A6000有東西,後面的都是????,難道是段
的size有問題,翻來覆去的查,可是什麼問題也看不出來。現在我還不知道那
些????????是怎麼回事,有知道的請教教我。

窮途末路了,還是用TRW跟吧,硬著頭皮一層層的跟,設了無數斷點,記錄了我
無數辛苦的腳步,最後總算把錯誤定位在了一條語句上。對比原版,發現好像
就是和上面的那些????????有關,可是那些????????我又搞不定,難道就這麼
宣告失敗了?

最後最後,我又想到是不是我當初dump出來的程式就有問題呀(是用Procdump),
我再用TRW直接pedump一次,然後一樣用ImportREC修復IAT,咦,這次居然有
10個函式沒有解析出來,真是見了鬼了。沒辦法,手動來吧,還好沒有太難的,
全部找出來,發現有兩個是空函式,想在import list中刪掉,可是一不小心
竟然連整個Trunk都給刪掉了,暈倒(是不是ImportREC沒有刪函式的功能呀?)
只好重新再來抓,哇,這回居然又全部解析成功了,真不知怎麼搞的。成功就
成功吧,剛才也不能白忙活呀,對比對比吧,發現和我手動找的基本一致,只
有一個函式不一樣,還有就是那兩個空函式都被FreeResource代替了。
“FreeResource”,看到這個字眼,我的眼睛突然一亮,我上面定位的出錯點
反推回去好像就是在一個CALL FreeResource 附近呀,還好斷點還在,馬上來
到這裡:

018F:00413305  PUSH     EAX
018F:00413306  PUSH     ESI
018F:00413307  CALL     `KERNEL32!FindResourceA`
018F:0041330C  MOV      EDI,EAX
018F:0041330E  MOV      [EBX+10],EDI
018F:00413311  TEST     EDI,EDI
018F:00413313  JNZ      0041331C
018F:00413315  PUSH     EBP
018F:00413316  CALL     00413280
018F:0041331B  POP      ECX
018F:0041331C  MOV      EAX,[EBX+10]
018F:0041331F  PUSH     EAX
018F:00413320  PUSH     ESI
018F:00413321  CALL     `KERNEL32!LoadResource`
018F:00413326  MOV      EDI,EAX
018F:00413328  MOV      [EBX+14],EDI
018F:0041332B  TEST     EDI,EDI
018F:0041332D  JNZ      00413336
018F:0041332F  PUSH     EBP
018F:00413330  CALL     00413280
018F:00413335  POP      ECX
018F:00413336  MOV      EAX,[EBX+10]
018F:00413339  PUSH     EAX
018F:0041333A  PUSH     ESI
018F:0041333B  CALL     `KERNEL32!SizeofResource`
018F:00413340  PUSH     EAX
018F:00413341  MOV      EAX,[EBX+14]       <-- EAX=0x4AF088(就是????)
018F:00413344  PUSH     EAX                    這個值很關鍵,後面有用
018F:00413345  CALL     `KERNEL32!FreeResource`
018F:0041334A  MOV      EDX,EAX            <-- 到這EAX=0,導致後面的
018F:0041334C  MOV      EAX,EBX                異常錯誤產生。
018F:0041334E  POP      ECX
018F:0041334F  CALL     00413058
018F:00413354  POP      EDI
018F:00413355  POP      ESI
018F:00413356  POP      EBX
018F:00413357  POP      ECX
018F:00413358  POP      EBP
018F:00413359  RET      04

看來這裡來一個FreeResource很不合適,既然原來是空函式,那就NOP掉它吧,
這樣保持EAX的值不變,至少後面的那個出錯點不會再有問題了,改過後F5跑,
有好多次都會來到這裡,全部跳過去後,程式畫面總算出來了,啊,老天有眼
可算是搞定了。既然有兩個空函式,找到另一個,也NOP掉,另外一個不一樣
的函式好像沒什麼影響,不管了吧。改完以後終於可以正常執行了,^_^

總結一下,這次脫殼成功,運氣成分不可少,要不是不留神將Trunk刪了,可能
還發現不了ImportREC自動解析的錯誤,那樣還不知道什麼時候才能搞定這個殼
呢。由此看出,ImportREC自動解析的引入函式也不能保證都正確,最好在使用
TraceLavel1後還剩餘的函式上留意一下,如有什麼問題可以在這裡找找原因,
嘿嘿,這是我得出的一點經驗,與大家分享。有不對的地方請幫我指出來。

最後說一下,IconEdit2(v2.4)脫殼後,只需要修正IAT,並改一下(1)(2)兩個
陷阱,即可正常執行,沒那麼麻煩了。

相關文章