概述
脫殼是一項(xiàng)綜合技術(shù),結(jié)合PE文件格式、匯編指令的分析,調(diào)試加密的程序并將其還原的一個(gè)過(guò)程。
殼一般分為兩種,加密殼和壓縮殼,里面所使用的技術(shù)有,壓縮算法、對(duì)代碼加密、對(duì)IAT加密、對(duì)資源加密。
我們從簡(jiǎn)單入手-壓縮殼。
脫殼三步法
1尋址OEP
2dump內(nèi)存到文件
3修復(fù)文件
脫殼三步法-尋址OEP技巧
1堆棧平衡法(ESP定律)
殼代碼就像一個(gè)函數(shù),進(jìn)入時(shí)會(huì)開(kāi)辟堆棧、保存寄存器環(huán)境,退出時(shí)會(huì)恢復(fù)堆棧、恢復(fù)寄存器。所以應(yīng)該是堆棧平衡的,那我們可以在殼代碼操作了堆棧后對(duì)堆棧設(shè)置訪問(wèn)或?qū)懭霐帱c(diǎn),然后運(yùn)行程序,當(dāng)斷點(diǎn)命中的時(shí)候,應(yīng)該就是退出殼代碼的時(shí)候。在其附近單步幾次,應(yīng)該就能到達(dá)程序的原始OEP。
2特征定位法
在我們熟悉的程序中,我們可以使用特征來(lái)定位程序原始OEP。特征有幾種:
① 二進(jìn)制特征
比如release版的VS2013是:
E8????????E9 call jmp
② API特征
比如vc6.0的第一個(gè)API調(diào)用是:
GetVersion
比如Delphi程序第一個(gè)API調(diào)用是:
GetModuleHandleA
3單步跟蹤法
這種方法一般使用在分析自己加殼的程序或者是練習(xí)分析殼時(shí)。
脫殼-0.aspack.exe
1尋址OEP
ESP定律
2dump內(nèi)存

3修復(fù)文件

注意:如果程序有隨機(jī)基址,脫殼后需要把隨機(jī)基址標(biāo)志位置0.
殼代碼的基本流程
① 保存寄存器環(huán)境
② 加載一些必要的API
③ 解密代碼和數(shù)據(jù)
④ 修復(fù)重定位
⑤ 填充IAT
⑥ 恢復(fù)寄存器環(huán)境
=========================
分析殼代碼-0.aspack.exe
① 殼OEP

② 加載必要API

③ 解密解壓縮代碼

④ 修復(fù)重定位

⑤ 修復(fù)IAT
001D726F 03F2 ADD ESI,EDX ; esi=導(dǎo)入表結(jié)構(gòu)
001D7271 8B46 0C MOV EAX,DWORD PTR DS:[ESI+0xC] ; 獲取模塊DLL名稱RVA
001D7274 85C0 TEST EAX,EAX
001D7276 0F84 0D010000 JE 00_aspac.001D7389
001D727C 03C2 ADD EAX,EDX ; 加上基地址,字符串VA
001D727E 8BD8 MOV EBX,EAX
001D7280 50 PUSH EAX
001D7281 FF95 A90F0000 CALL DWORD PTR SS:[EBP+0xFA9] ; 獲取模塊基地址
001D7287 85C0 TEST EAX,EAX
001D7289 75 07 JNZ SHORT 00_aspac.001D7292
001D728B 53 PUSH EBX
001D728C FF95 AD0F0000 CALL DWORD PTR SS:[EBP+0xFAD]
001D7292 8985 A9050000 MOV DWORD PTR SS:[EBP+0x5A9],EAX ; 保存模塊基地址
001D7298 C785 AD050000>MOV DWORD PTR SS:[EBP+0x5AD],0x0
001D72A2 8B95 88040000 MOV EDX,DWORD PTR SS:[EBP+0x488] ; 獲取基地址
001D72A8 8B06 MOV EAX,DWORD PTR DS:[ESI] ; 獲取指向OrignalFirstThunk RVA
001D72AA 85C0 TEST EAX,EAX
001D72AC 75 03 JNZ SHORT 00_aspac.001D72B1
001D72AE 8B46 10 MOV EAX,DWORD PTR DS:[ESI+0x10]
001D72B1 03C2 ADD EAX,EDX ; 計(jì)算得出 OrignalFirstThunk VA
001D72B3 0385 AD050000 ADD EAX,DWORD PTR SS:[EBP+0x5AD] ; 0
001D72B9 8B18 MOV EBX,DWORD PTR DS:[EAX] ; 獲取INT中的數(shù)據(jù),即指向函數(shù)名稱的 RVA
001D72BB 8B7E 10 MOV EDI,DWORD PTR DS:[ESI+0x10] ; 獲取 FirstThunk
001D72BE 03FA ADD EDI,EDX ; 計(jì)算得出 IAT 地址
001D72C0 03BD AD050000 ADD EDI,DWORD PTR SS:[EBP+0x5AD] ; 0
001D72C6 85DB TEST EBX,EBX ; 判斷結(jié)束
001D72C8 0F84 A5000000 JE 00_aspac.001D7373
001D72CE F7C3 00000080 TEST EBX,0x80000000 ; 判斷是否是序號(hào)
001D72D4 75 04 JNZ SHORT 00_aspac.001D72DA
001D72D6 03DA ADD EBX,EDX ; 指向函數(shù)字符串結(jié)構(gòu)=INT[i]+模塊基地址
001D72D8 43 INC EBX ; 減去2,跳過(guò)字符串結(jié)構(gòu)的序號(hào)
001D72D9 43 INC EBX
001D72DA 53 PUSH EBX ; 保存寄存器環(huán)境
001D72DB 81E3 FFFFFF7F AND EBX,0x7FFFFFFF ;去掉序號(hào)
001D72E1 53 PUSH EBX ; 壓入字符串或是序號(hào)
001D72E2 FFB5 A9050000 PUSH DWORD PTR SS:[EBP+0x5A9]
001D72E8 FF95 A50F0000 CALL DWORD PTR SS:[EBP+0xFA5] ; 獲取函數(shù)地址
001D72EE 85C0 TEST EAX,EAX
001D72F0 5B POP EBX ; 恢復(fù)寄存器環(huán)境
⑤ 修改屬性,跳轉(zhuǎn)原始OEP
