2011年8月5日星期五

PESpin 1.33全保護脫殼筆記

【文章作者】: Nerin
【加殼方式】: PESpin
【使用工具】: OllyIce PEID LordPE ImportRec
【操作平台】: Windows XP SP2
【作者聲明】: 只是感興趣,沒有其他目的。失誤之處敬請諸位大俠賜教!
-------------------------------------------------- ------------------------------
【詳細過程】
  PEID查殼,顯示為“PESpin 0.3x - 1.xx -> cyberbob”。雙擊文件運行,打開任務管理器發現有兩個進程,我們脫殼的第一步就是要去掉雙進程保護。用OllyIce載入文件,開始我們的脫殼之旅。
  單步F7幾次之後,發現了我們很熟悉的幾條指令:
  
代碼:
  0041C0D7 60 PUSHAD
  0041C0D8 E8 00000000 CALL UnPackMe.0041C0DD
  0041C0DD 8B1C24 MOV EBX,DWORD PTR SS:[ESP]
  0041C0E0 83C3 12 ADD EBX,12
  
  這裡我們使用ESP定律下一個硬件斷點,然後Ctrl+G輸入CreateMutexA,解除雙進程守護。我們在函數末尾的Retn 0C處下斷點,因為殼會判斷這個函數的頭部是否有斷點。運行之後我們Alt+F9返回,停在這裡:
  
  
代碼:
  0041FE1E 8985 6E6E4000 MOV DWORD PTR SS:[EBP+406E6E],EAX
  0041FE24 8D85 E2281F03 LEA EAX,DWORD PTR SS:[EBP+31F28E2]
  0041FE2A 2D FCCEDE02 SUB EAX,2DECEFC
  0041FE2F FF10 CALL DWORD PTR DS:[EAX]
  0041FE31 BB CA7DB9FE MOV EBX,FEB97DCA
  0041FE36 81EB 137DB9FE SUB EBX,FEB97D13
  0041FE3C 3BC3 CMP EAX,EBX
  0041FE3E 9C PUSHFD ★走到這裡將ZF標誌位改成1
  0041FE3F C12C24 06 SHR DWORD PTR SS:[ESP],6
  0041FE43 F71424 NOT DWORD PTR SS:[ESP]
  0041FE46 832424 01 AND DWORD PTR SS:[ESP],1
  0041FE4A 58 POP EAX
  0041FE4B 2BD2 SUB EDX,EDX
  0041FE4D BB BAE74D02 MOV EBX,24DE7BA
  0041FE52 81EB 86E74D02 SUB EBX,24DE786
  0041FE58 F7E3 MUL EBX
  0041FE5A 81CB FE12F40E OR EBX,0EF412FE
  0041FE60 8​​D8428 4E0E91ED LEA EAX,DWORD PTR DS:[EAX+EBP+ED910E4E]
  0041FE67 2D 179B50ED SUB EAX,ED509B17
  0041FE6C FFE0 JMP EAX ★父子進程的分水嶺
  
  經過0041FE6C處的跳轉指令之後,我們來到這裡:
  
代碼:
  0041FE85 F1 INT1
  0041FE86 E8 1C030000 CALL UnPackMe.004201A7
  0041FE8B 85C0 TEST EAX,EAX
  0041FE8D 75 23 JNZ SHORT UnPackMe.0041FEB2
  0041FE8F 8BC3 MOV EAX,EBX
  0041FE91 35 08001F0E XOR EAX,0E1F0008
  0041FE96 C3 RETN
  
  看堆棧顯示:
  
引用:
  0012FFA0 0041C51B RETURN to UnPackMe.0041C51B
  0012FFA4 7C930738 ntdll.7C930738
  
  我們直接到0041C51B新建EIP,同時注意修改ESP寄存器的值。
  
代碼:
  0041C51B B8 4AAC1C95 MOV EAX,951CAC4A ★此處新建EIP
  0041C520 2BC9 SUB ECX,ECX
  0041C522 83C9 15 OR ECX,15
  0041C525 0FA3C8 BT EAX,ECX
  0041C528 0F83 81000000 JNB UnPackMe.0041C5AF
  
  在這裡搜索二進製字符串“F1 87 DF”,找到這裡:
  
代碼:
  004207AD F1 INT1
  004207AE 87DF XCHG EDI,EBX
  004207B0 57 PUSH EDI
  004207B1 C3 RETN
  
  在004207AD這裡下一個斷點,shift+F9停下來,同樣看堆棧新建EIP,調整堆棧。
  
代碼:
  0041D6D4 /EB 04 JMP SHORT UnPackMe.0041D6DA ★新建EIP
  0041D6D6 |7A EB JPE SHORT UnPackMe.0041D6C3
  0041D6D8 |04 9A ADD AL,9A
  0041D6DA ^\EB FB JMP SHORT UnPackMe.0041D6D7
  0041D6DC FFF6 PUSH ESI
  
  到這裡我們就已經處理好了雙進程保護,下面開始處理API Redirection。 Ctrl+G輸入GetVersion,在函數頭部下一個硬件
  訪問斷點,然後F9找到對API進行重定向的地方。
  
代碼:
  0041CE25 F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
  0041CE27 8BC6 MOV EAX,ESI
  0041CE29 8BF7 MOV ESI,EDI
  0041CE2B 5F POP EDI
  
  走到這裡要注意了,快到關鍵的地方了,刪除硬件斷點,然後單步跟踪。
  
代碼:
  0041CD64 83FA 12 CMP EDX,12
  0041CD67 73 7B JNB SHORT UnPackMe.0041CDE4 ★直接跳過這裡的循環
  0041CD69 8B18 MOV EBX,DWORD PTR DS:[EAX]
  0041CD6B EB 07 JMP SHORT UnPackMe.0041CD74
  
  繼續F7往下走:
  
代碼:
  0041D08D /0F84 92000000 JE UnPackMe.0041D125 ★這裡的循環也直接跳
  0041D093 |47 INC EDI
  0041D094 |EB 01 JMP SHORT UnPackMe.0041D097
  
  來到這裡:
  
代碼:
  0041D1A0 8907 MOV DWORD PTR DS:[EDI],EAX ★這裡就是關鍵了,在這裡下一個硬件執行斷點
  0041D1A2 EB 02 JMP SHORT UnPackMe.0041D1A6
  0041D1A4 02F5 ADD DH,CH
  0041D1A6 F9 STC
  0041D1A7 72 08 JB SHORT UnPackMe.0041D1B1
  0041D1A9 73 0E JNB SHORT UnPackMe.0041D1B9
  0041D1AB - E9 83042417 JMP 1765D633
  0041D1B0 C3 RETN
  
  走到這裡我們看一下堆棧:
  
引用:
  $-34 > 7C8114BA kernel32.7C8114BA ★函數的地址
  $-30 > 0000000F ★被偷的opcode數量
  $-2C > 00000000
  $-28 > 00000007
  $-24 > 0041CDDC UnPackMe.0041CDDC
  $-20 > 0041E4AD UnPackMe.0041E4AD
  $-1C > 00407A81 UnPackMe.00407A81
  $-18 > 004076D8 UnPackMe.004076D8
  $-14 > 0012FF94
  $-10 > 0012FF94
  $-C > 00007060
  $-8 > 00D50180
  $-4 > 0041D07F UnPackMe.0041D07F
  $ ==> > 0041D8A8 UnPackMe.0041D8A8
  
  我們找一塊空的地方,打上我們的補丁代碼,這樣就繞過了殼的API重定向:
  
代碼:
  mov eax,dword ptr [esp-34]
  sub eax,dword ptr [esp-30]
  mov dword ptr [edi],eax
  jmp 0041D1A6
  
  API處理完之後,我們刪除那個硬件執行斷點,F9快速到達偽OEP處,單步跟踪來補上被偷的OEP代碼。
  
代碼:
  0041DCFA F7D2 NOT EDX ★來到這裡
  0041DCFC 39C2 CMP EDX,EAX
  0041DCFE F7C0 74E7F921 TEST EAX,21F9E774
  0041DD04 0FACC2 48 SHRD EDX,EAX,48 ; Shift constant out of range 1..31
  0041DD08 0FBDC8 BSR ECX,EAX
  0041DD0B C7C2 2431C7CD MOV EDX,CDC73124
  0041DD11 85C0 TEST EAX,EAX
  0041DD13 0FBAEA 31 BTS EDX,31
  0041DD17 F7D2 NOT EDX
  0041DD19 F7C1 25C4A65C TEST ECX,5CA6C425
  0041DD1F 3BD0 CMP EDX,EAX
  0041DD21 0FABC2 BTS EDX,EAX
  0041DD24 EB 01 JMP SHORT UnPackMe.0041DD27
  
  0041DD3C 55 PUSH EBP ★第一句被偷的代碼
  0041DD3D EB 01 JMP SHORT UnPackMe.0041DD40
  
  下面就單步跟踪,就不一一列舉過程了,大家可以自己動下手,這裡我就直接貼出來被偷的OEP代碼了:
  
引用:
  0041DD3C 55 PUSH EBP ; 1
  
  0041DD40 8BEC MOV EBP,ESP ; 2
  
  0041DD45 6A FF PUSH -1 ; 3
  
  push 00407190
  push 00403368
  
  0041DD62 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
  
  0041DD6B 50 PUSH EAX
  
  0041DD6F 64:8925 00000000 MOV DWORD PTR FS:[0],ESP
  
  0041DD79 83EC 58 SUB ESP,58
  
  0041DD7F 53 PUSH EBX
  
  0041DD83 56 PUSH ESI
  
  0041DD87 57 PUSH EDI ; ntdll.7C930738
  
  0041DD8B 8965 E8 MOV DWORD PTR SS:[EBP-18],ESP
  
  0041DD91 FF15 D20E4200 CALL DWORD PTR DS:[420ED2] ;GetVersion
  
  0041DD9A 33D2 XOR EDX,EDX
  
  0041DD9F 8AD4 MOV DL,AH
  
  0041DDA4 8915 34AD4000 MOV DWORD PTR DS:[40AD34],EDX
  
  0041DDAD 8BC8 MOV ECX,EAX
  
  0041DDB2 81E1 FF000000 AND ECX,0FF
  
  0041DDBB 890D 30AD4000 MOV DWORD PTR DS:[40AD30],ECX
  
  0041DDC4 C1E1 08 SHL ECX,8
  
  二進制opcode如下:
  
  55 8B EC 6A FF 68 90 71 40 0​​0 68 68 33 40 0​​0 64 A1 00 00 00 00 50 64 89 25 00 00 00 00 83 EC 58
  53 56 57 89 65 E8 FF 15 D2 0E 42 00 33 D2 8A D4 89 15 34 AD 40 0​​0 8B C8 81 E1 FF 00 00 00 89 0D
  30 AD 40 0​​0 C1 E1 08
  
  補上之後直接在00402598處新建EIP即可。下面我們開始處理Code Redirection,往下隨便找一句看看:
  
代碼:
  004026A0 - E9 9FDBFFFF JMP UnPackMe.00400244
  004026A5 90 NOP
  004026A6 90 NOP
  004026A7 8DC0 LEA EAX,EAX ; Illegal use of register
  
  00400244 833D 20AD4000 01 CMP DWORD PTR DS:[40AD20],1
  0040024B - E9 57240000 JMP UnPackMe.004026A7
  
  我們記下00400244處的代碼,然後再補回去就好了,但是這裡的工作量比較大,所以我就用網上的一個腳本來修復了。修
  复完畢之後,我們用LordPE抓取鏡像(★記得糾正鏡像大小),打開ImportRec,填入OEP:2598,在空白處右鍵,選擇高
  級命令->獲取API調用,然後剪切掉無效的指針就可以得到一份完整的API了,直接修復dump。下面就要修復nanomites了,
  這個我們可以直接用工具進行修復。修復完畢之後雙擊脫殼文件,沒有反應,⊙﹏⊙b 我們重新載入脫殼文件,單步跟踪
  發現問題出現在這裡:
  
代碼:
  0040264F |. E8 2D030000 CALL tuowen_.00402981
  
  00402981 $- E9 AAD9FFFF JMP tuowen_.00400330
  00402986 90 NOP
  00402987 90 NOP
  
  00400330 0000 ADD BYTE PTR DS:[EAX],AL ★這裡看來是腳本沒有修復好,我們手工修復一下好了
  
這裡是我修復的方案,大家可以參考一下:
  
代碼:
  00400330 833D C8B34000 0>CMP DWORD PTR DS:[40B3C8],0
  00400337 - E9 18230000 JMP dumped_1.00402654
  
  這裡修復完畢之後保存,雙擊已經可以看到界面了,但是點擊OK按鈕之後會崩潰,下面我們就來修復SDK保護吧。 O(∩_∩)O~
  用OD載入,F9跑起來,然後點擊OK按鈕之後,發現造成崩潰的地方在這裡。
  
代碼:
  00401160 $​​ 55 PUSH EBP ★我們要修復這裡的代碼
  00401161 . 8BEC MOV EBP,ESP
  00401163 . 81EC 60020000 SUB ESP,260
  00401169 . 53 PUSH EBX
  0040116A . 56 PUSH ESI
  0040116B . 57 PUSH EDI
  0040116C . FF15 8F124200 CALL DWORD PTR DS:[42128F]
  00401172 . B2 1E MOV DL,1E
  00401174 . 57 PUSH EDI
  00401175 . 6F OUTS DX,DWORD PTR ES:[EDI] ; I/O command
  00401176 . DBBF 81D54987 FSTP TBYTE PTR DS:[EDI+8749D581]
  0040117C C5 DB C5
  0040117D . C8 08118B ENTER 1108,8B
  00401181 . C3 RETN
  
  我們帶殼調試源文件,然後看看對應的代碼應該是什麼樣子,然後再補上去就可以恢復那個按鈕的功能了。由於這裡只有
  一處,所以比較簡單:
  
代碼:
  00401160 55 PUSH EBP
  00401161 8BEC MOV EBP,ESP
  00401163 81EC 60020000 SUB ESP,260
  00401169 53 PUSH EBX
  0040116A 56 PUSH ESI
  0040116B 57 PUSH EDI
  0040116C FF15 8F124200 CALL DWORD PTR DS:[42128F]
  
  此時DS:[0042128F]=00D30000,看來源文件是跑到殼臨時申請的空間裡面去直接代碼解碼了,我們跟進去之後,把代碼記
  下來,然後找個空白的地方把代碼補上即可,下面是我自己補的代碼,貼出來僅供大家參考下O(∩_∩)O~:
  
代碼:
  00401160 $​​ 55 PUSH EBP
  00401161 . 8BEC MOV EBP,ESP
  00401163 . 81EC 60020000 SUB ESP,260
  00401169 . 53 PUSH EBX
  0040116A . 56 PUSH ESI
  0040116B . 57 PUSH EDI
  0040116C . 90 NOP
  0040116D . E8 CC650000 CALL dumped_2.0040773E ★到空白的地方去解碼
  
  
  0040773E 9C PUSHFD
  0040773F 60 PUSHAD
  00407740 8B4424 24 MOV EAX,DWORD PTR SS:[ESP+24]
  00407744 8B08 MOV ECX,DWORD PTR DS:[EAX]
  00407746 8D78 04 LEA EDI,DWORD PTR DS:[EAX+4]
  00407749 897C24 24 MOV DWORD PTR SS:[ESP+24],EDI
  0040774D 81E9 BC1D576F SUB ECX,6F571DBC
  00407753 FC CLD
  00407754 8A07 MOV AL,BYTE PTR DS:[EDI]
  00407756 2C B2 SUB AL,0B2
  00407758 F9 STC
  00407759 32C1 XOR AL,CL
  0040775B F8 CLC
  0040775C 34 98 XOR AL,98
  0040775E C0C0 CE ROL AL,0CE ; Shift constant out of range 1..31
  00407761 34 41 XOR AL,41
  00407763 C0C8 06 ROR AL,6
  00407766 2AC1 SUB AL,CL
  00407768 34 EF XOR AL,0EF
  0040776A C0C8 9E ROR AL,9E ; Shift constant out of range 1..31
  0040776D 32C1 XOR AL,CL
  0040776F C0C8 8B ROR AL,8B ; Shift constant out of range 1..31
  00407772 02C1 ADD AL,CL
  00407774 04 F6 ADD AL,0F6
  00407776 04 6B ADD AL,6B
  00407778 AA STOS BYTE PTR ES:[EDI]
  00407779 49 DEC ECX
  0040777A ^ 75 D8 JNZ SHORT dumped_2.00407754
  0040777C 61 POPAD
  0040777D 9D POPFD
  0040777E C3 RETN
  
  補上這裡的代碼之後保存,再次打開發現OK按鈕的功能也正常了,PEID再掃描下,顯示“Microsoft Visual C++ 6.0”看
  來我們已經成功脫殼了( ⊙o⊙ )
  
-------------------------------------------------- ------------------------------
【經驗總結】
  脫這個殼的方法總得來說還是比較傳統的,如果能跟踪一下殼的流程,相信能學到不少東西。這篇文章是匆忙寫成的,有錯誤的地方希望大家能指正。另外我這裡修復SDK的方法還不能夠跨平台,如果有哪位大俠有更好的方法的話,希望能夠給出給我們學習學習。

没有评论:

发表评论