使用工具:Ollydbg,PEID,ImportREC,LoadPE,IDA,Universal Import Fixer,OllySubScript html
此篇是加密殼的第二篇,更詳細的步驟和思考,請查看第一篇:手工脫殼之 未知加密殼 【IAT加密+混淆+花指令】 函數
PESpin殼: 工具
嘗試ESP定律,但硬件斷點未斷下。 加密
(緣由實際上是殼作了反調試,後面部分介紹) spa
API下斷: 調試
殼導入了LoadLibrary 和 GetProAddress,能夠從API下手。 code
按照經驗來講,跟蹤GDI32.dll的基地址。由於其它DLL,如kernel32.dll取出的函數,殼有可能用於本身的代碼而非修復IAT。 htm
跟蹤GDI32的基地址。多觀察寄存器窗口和堆棧窗口。 blog
DLL導出表: ip
DLL INT:
DLL IAT:
DLL 序號表:
經過RVA取得函數名:
跟蹤字符串,接下來可能有字符串循環。
函數名 首個字節跟0x53比。0x53 == ' S '。
並且每次的值都不同。可見是取對應字母開頭的函數名。
查看首個H開頭的函數名,下條件斷點。
字符串在減小,疑似於計算哈希值,
預判:根據上一篇加密殼的經驗,這樣的循環可能跟哈希加密,IAT加密有關。
預操做:記錄從DLL IAT取出函數地址的 指令地址 和 存放進exe IAT 指令的地址。
肯定循環的判斷臨界點,跳出循環,跟蹤最後的結果。
目標1:尋取出DLL IAT的函數地址。
字符串循環條件臨界點:
跳出循環,疑似哈希值。
交換寄存器。
的確是進行哈希值比較。
在條件成立的下一條指令下斷點。
跟蹤哈希值,獲得取函數地址的指令地址。
取DLL IAT函數地址的指令地址 :
記錄下一條指令地址:0x438F9F
目標2:尋 把DLL IAT函數地址 存放進 exe IAT 的指令地址。
此處還不知道exe IAT的位置,因此只能跟蹤函數地址EAX了。
多觀察帶方括號 MOV [xxx], xxx 之類的指令。
代碼中作了大量的混淆和花指令,以下,純粹無心義的指令,干擾分析。
(混淆和花指令具體見後面部分)
記錄PESpin殼特徵:
記錄殼的一些操做:
取API函數前部分字節,並判斷。
對取出的字節 作一些操做。
最終拷貝進指定地址,數據窗口跟隨反彙編看出點端倪。
推測殼是在 IAT引用 與 真正API調用 之間增長代碼屏障,仍是帶混淆的屏障。
這樣作順即可以對IAT進行加密,阻止ImportREC解析。
流程:偷取函數前部分字節,申請空間,製造混淆代碼塊。
CALL(IAT引用) ->> 內存代碼(混淆) -->> API
如下跟蹤證實推測正確:
再逐步取出字節。
構造混淆,IAT引用CALL進來就是這個樣子。
觀察內存空間首地址0x200000。推測可能準備填入exe IAT。
由於混淆和花指令,不少仔細分析都會作無用功,不知哪條真那條假。因此要肯定目標,定點分析。
存進IAT指令:
存進exe IAT 指令的地址:
記錄下一條指令地址:0x43918C
如今,存在IAT的位置的是 申請出來的內存地址,內存的地址 –>> API的地址。
查看數據窗口,仔細一看你會發現,IAT被重定向了。
API的地址用0隔開,這明顯不是IAT結構,是殼本身創建的IAT,ImportREC沒法解析。
接下來就是跳出修復IAT的循環,找到OEP了。
多注意 比較指令 和 遠跳。
找OEP的過程,感受就是在"花"海里遨遊~~.....
跨區段遠跳,通常是跳到OEP。
OEP:
記錄OEP地址:0x409486
查看調用模塊:
IAT引用,有些加密,有些未加密。
可見在殼修復IAT時,有些函數地址並無作相關加密處理,直接放回去了。
這就意味着在存進exe IAT 的循環中,多了一條分支,這像是有意擾亂分析者的腳步。
找一塊地址密集的地方,在首部,下硬件斷點,跟蹤分析出分支位置。
此處存進exe IAT的指令地址跟上一處的不一樣,地址正好能夠作爲分支的條件判斷。
記錄分支指令:
跳過call下一條指令地址: 0x439101
特徵碼搜索:
在殼解密TEXT段後,能夠按各個版本的編譯器的OEP特徵碼,進行逐個搜索。
如:
VC++的OEP特徵碼:
55 8B EC 6A FF
若是作了OEP特徵偷取,能夠針對某一條OEP相關指令,對內存進行暴力搜索。
殼操做:利用SEH異常鏈清理硬件斷點,進行反調試。
不少狀況下,要麼就硬件斷點斷不下,要麼就斷下的位置不正確。
懷疑硬件斷點被清除了。
按經驗,首先推測在異常處理裏進行反調試。
OD取消忽略異常。
Shift+F9 忽略異常運行,總共觸發9處異常,列出首幾處。
第三處和第四處斷在了同一個地方,但異常處理函數不一樣。
方案:經過在後方異常點 設置硬件斷點,來判斷前方異常點的異常處理 是否作了反調試。
逐個排查,肯定是第3個異常點,清理了硬件斷點。
查看異常處理函數,能夠在反調試函數前下硬件執行斷點。
這裏爲了進行更好的分析,在此處Dump下來,採用IDA分析。
的確是對Dr一、二、三、4清理爲零了,而且對Dr六、7進行了操做。
反反調試:編寫OD腳本時,下硬件斷點在此函數,並去掉反調試指令。
記錄地址:0x43AF59,NOP掉字節0x1A。
//清除全部硬件斷點 BPHWC //清除全部軟件斷點 BC //清除全部內存斷點 BPMC //IAT地址 VAR IATAddress //OEP斷點 BPHWS 409486,"x" //取IAT指令 BPHWS 438F9F,"x" //存IAT指令 BPHWS 43918C,"x" //硬件反調試代碼 BPHWS 43AF59,"x" _LOOP: RUN //去掉硬件反調試代碼 cmp eip,43AF59 JNZ _Sign1 fill 43AF59,1A,90 //清除反調試硬件斷點 BPHWC 43AF59 _Sign1: //取IAT判斷 CMP eip,438F9F JNZ _Sign2 MOV IATAddress,eax _Sign2: //分支判斷 CMP eip,439101 JNZ _Sign3 //不做操做 BPHWS 43AF59,"x" _Sign3: //存IAT的地方 CMP eip,43918C JNZ _Sign4 MOV [edi],IATAddress _Sign4: //OEP CMP eip,409486 JNZ _LOOP MSG "到達OEP"
OD腳本修復加密:
使用Universal Import Fixer 重定向修復IAT表:
從上面的殼代碼的運行地址能夠看出,殼的代碼是運行在最後一個區段的,能夠推斷最後一個區段是殼的區段。
當Dump下來的時候,最後一個區段就沒用了,因此能夠重定向到此區段。
再用ODDump,ImportREC新建導入表:
分析經驗:
混淆:無心義的垃圾指令,干擾分析,干擾反彙編引擎,使指令產生多種解釋。
花指令:無心義的大量跳轉,干擾分析。
花指令塊:無心義跳轉。
跳轉指令被截斷。
混淆讓反彙編出錯。
下硬件讀寫斷點,會難肯定上一條是什麼指令。
混淆使一樣意思的指令被肢解成多條。
一個混淆和花指令結合的循環,就是上面的字符串處理循環。
經過STC設置進位標誌 和 CMC進位標誌求補 控制跳轉,花指令。
我的總結:
附件:
KID