Safengine Shielden v2.40 IAT修復及指令碼編寫(x64dbg)
前言
首先感謝 L4nce 前輩寫的“ 淺談 Safengine 系列脫殼 ”,給了我很大幫助,讓我開始入門脫加密殼。
L4nce 的這篇文章已經算是“巨人的肩膀”了,但我覺得仍有一些東西可以細寫。由於是自己第一次研究脫殼寫指令碼,沒有人指點,錯誤紕漏處還請指正包涵。

我的奇妙之旅
到這裡,我就假設大家已經看完 L4nce 的文章了。接下來我想談一些他文章中沒有寫到或者寫全的東西,以及一些我的“奇妙旅途”。
關於研究脫殼寫指令碼,我是先從簡單程式(只有幾個 API 呼叫的彙編程式)入手,分析呼叫 iat 的程式碼有什麼特徵和功能,然後寫個簡易指令碼,測試脫殼成功了。再用相對複雜程式(易語言靜態編譯程式)測試指令碼並完善修改。
這個方法在我看來或許比較耗時,但可以逐步解決難關,避免在莫名其妙的問題上“卡關”。
再來談談 SE 的 IAT 加密。。。剛開始按照 L4nce 的思路寫指令碼,最後測試脫殼什麼的都成功了。。。直到我√上了“使用雜湊API函式名稱”再測試脫殼,就失效了。
分析看了一下,不再走獲得API地址的 add edi,eax 這條路了。這樣就只能另闢蹊徑獲得 API 地址
這逼的我重新分析兩種情況下 call sedata_section 的流程,以圖尋找共同點和突破點。
一般來說,為了程式的速度,殼對原程式的 iat 呼叫的加密不會多厲害,最多是在第一次跑的時候跑的久一點,之後呼叫都是馬上取得目標地址,呼叫 API 或者對暫存器賦值API地址。這一點,我認為不僅適用於 se ,也適用於其他加密殼,照著這個想法找下去,總能找到希望。
最終我找到了一個點: push xxxxxx
se在虛擬機器中獲取到目標(API)地址後會將其修改成push 目標地址
由此我修改了指令碼流程:
1.找 call sedata_section
2.步進跟蹤找 push xxxxxx 和 cmp dword ptr ss:[esp+0x4],0
3.對 push 的立即數下硬體寫入斷點,以此來獲得目標( API )地址
4.判斷呼叫IAT的型別,做出修復
在第4點上, L4nce 說了大部分情況,但有些特殊情況沒有細說了。我在此把相關情況列一下:
常見:
1.call dword ptr [iat]
2.jmp dword ptr [iat]
3.mov reg,dword ptr [iat]
call reg
少見:
4.call @ jmp dword ptr [iat]
jmp dword ptr [iat]
第4種情況的 call ,在加殼的時候有時候會加密,有時候不會(但其呼叫的 jmp dword ptr [iat] 是一定會加密的)。既然這樣,就一律按加密的情況來考慮。

判斷呼叫IAT的型別
在L4nce方法的基礎上,我做了一些較大的變動。方法如下:
1.分別對 call sedata_section+5和 call sedata_section+6 這兩處可能的返回地址下單位元組斷點( int3 )
2.判斷獲取到的目標( API )地址所處地址是否大於殼區段,以此判斷是否是 Mov_Reg 型別或者其他 IAT 呼叫型別
其他 IAT 呼叫型別
( shadow 已破)
3.1如果是 Mov_Reg型別,直接 run ,停在返回地址後,依次判斷哪個暫存器參與了呼叫。
3.2如果是其他 IAT 呼叫的型別,先對其 API 地址下硬體執行斷點再 r un ,此時 EIP 停在 API 領空,判斷 [esp] 是否與 call sedata_section+5 或者 call sedata_section+6 相等,或者都不相等。
4.1 如果與 call sedata_section+6 相等,則是 call dword ptr [iat]
4.2 如果與 call sedata_section+5 相等,則是
call @ jmp dword ptr [iat]
jmp dword ptr [iat] 中的 call
4.3 如果都不相等,則是 jmp dword ptr [iat]
至此, IAT 的呼叫型別就判斷完了,然後按照各自情況修復就可以了,可以直接參考指令碼。
(特殊 API 如 CreateThread 不會填充 push xxxxxx ,手動修復即可)

寫指令碼的奇妙旅途
寫 x64dbg 指令碼,還真是發生了不少“奇妙事件”。有些解決了,有些只能迴避掉。
1. 單步步入( sti )無效:
在把 EIP 設定到 call 上後,第一次 sti 有一定機率停在原地不動
2. 跑指令碼時奇奇怪怪的異常崩潰:
也是把 EIP 設定到 call 上後,步進追蹤可能崩潰,可能出現異常訪問(偏偏手動單步執行指令碼就不會出現,換個系統也有可能不會再出現)。遇到這種情況,只能把地址加入 ignore 表,到時候手動修復。所幸這都是少數,一般就3個左右
3. 跑指令碼跑得 x64dbg 崩潰:
這個還好,跑指令碼前把 GUI 更新關閉,堆疊更新關閉,日誌更新關閉即可。出現特殊情況了,再解開 GUI 更新,分析情況。
4. call 壓入錯誤返回地址
這個是最奇妙的。把 EIP 設定到 call 上後,第一次步進,,有機率出現壓入錯誤的返回地址的現象!只能重新把 EIP 設定在 call 上,把之前的返回地址清0,再步進跟蹤一次,就不會再出現了。

尾聲
L4nce 在他的文中寫到還有“被抽取的程式碼”,不過我脫殼時都沒遇見到,不知道什麼情況。
脫殼時建議選擇 win7 環境( xp 貌似用不了 x64dbg ), win10 下脫出來的易語言靜態編譯程式 (其他語言程式沒問題) ,在其他平臺執行不了。只有 win7 脫下來的正常執行在其他平臺(暫時只測試了 xp,win7,win10 )
指令碼我寫了比較多的註釋,放上來供大家參考。至於特殊情況的判斷和修復,相信對有心學習的人來說不是難事,對伸手黨倒是難事。
- End -

看雪ID: Lixinist
https://bbs.pediy.com/thread-251066.htm
本文由看雪論壇 Lixinist 原創
轉載請註明來自看雪社群
熱門圖書推薦
戳 立即購買!
公眾號ID:ikanxue
官方微博:看雪安全
商務合作:[email protected]
↙ 點選下方“閱讀原文”,檢視更多幹貨