第四课 脱壳必备知识要点及方法
???????????????????????????? 第四課? 脫殼必備知識(shí)要點(diǎn)及方法
?
??? 今天所要講的是這高級(jí)篇中最為關(guān)鍵,最為重要的一課,希望大家能認(rèn)真學(xué)習(xí),反復(fù)推敲,舉一反三學(xué)習(xí)脫殼的各種方法,當(dāng)然有的時(shí)候可能需要幾種方法一起使用,今后我們也會(huì)一點(diǎn)一點(diǎn)接觸到,今天我們先學(xué)習(xí)大體的幾種脫殼法。
?
一:常見脫殼調(diào)試法
?
二:預(yù)備知識(shí)
???
??? OEP是Original Entry Point縮寫,即程序加殼前的真正的入口點(diǎn)。
??? 外殼初始化的現(xiàn)場(chǎng)環(huán)境(各寄存器值)與原程序的現(xiàn)場(chǎng)環(huán)境是相同的。加殼程序初始化時(shí)保存各寄存器的值,外殼執(zhí)行完畢,會(huì)恢復(fù)各寄存器內(nèi)容。其代碼形式一般如下:
?
??? PUSHFD???????? ; 將標(biāo)志寄存器入棧保存
??? PUSHAD???????? ; push eax, ecx, edx, ebx, esp, ebp, esi, edi
??? ……?????????? ; 外殼代碼部分
??? POPAD????????? ; pop edi, esi, ebp, esp, ebx, edx, ecx, eax
??? POPFD????????? ; 恢復(fù)標(biāo)志寄存器
??? JMP OEP??????? ; 大的跳轉(zhuǎn)
??? OEP: ……????? ; 解壓后的程序原代碼
?
??? PUSHAD (壓棧) 代表程序的入口點(diǎn),
??? POPAD? (出棧) 代表程序的出口點(diǎn),與PUSHAD想對(duì)應(yīng),一般找到這個(gè)OEP就在附近
?
三:脫殼方法之單步跟蹤找OEP
???
??? 1.用OD載入,如果有提示是否分析代碼,就點(diǎn)“ 不分析代碼!”
??? 2.F8單步向下跟蹤調(diào)試,沒有實(shí)現(xiàn)的向上的跳,向下的跳都可以步過,阻止實(shí)現(xiàn)的向上的跳。
??? 3.遇到會(huì)跑飛的CALL我們就F7步入。
???
Btw:遇到程序無法向下跟蹤調(diào)試的時(shí)候,在附近(上下均可)找一個(gè)大跳轉(zhuǎn)(像下的實(shí)現(xiàn)的,跳的大小看線的長(zhǎng)短)(如果找不到大的跳就找一個(gè)不跳的跳(沒有線),FSG2.0就是這樣),F4運(yùn)行到該跳處,然后右鍵→跟隨或者回車到達(dá)跟隨的地址按F2下斷點(diǎn),然后shift+F9(忽略異常運(yùn)行)運(yùn)行到跟隨的地址,然后再F2取消斷點(diǎn),接著就可以F8繼續(xù)單步調(diào)試了(對(duì)于FSG2.0的課可能直接就到oep了,另外老版的OD可能會(huì)出現(xiàn)要你分析代碼,解決辦法:右鍵-->分析-->從模塊刪除目標(biāo)文件)。另:在F8單步跟蹤的時(shí)候并不一定非要是在實(shí)現(xiàn)的向上的跳的下一句F4,如果是像:je,jne,ja,jna,等有條件的跳也可以繼續(xù)F8單步,因?yàn)槟愀h(huán)個(gè)次它的條件一般就會(huì)改變?nèi)缓笙蚝笞?#xff08;它本身變成了為實(shí)現(xiàn)的跳了)。但是如果是像jmp這樣非條件的跳,如果你還F8單步的話它會(huì)一直循環(huán),所以這種跳就必須F4。
?
清除OD的使用記錄:OD菜單-〉插件-〉文件清除-〉全部文件
退出OD,在OD目錄里有個(gè)UDD文件夾,把里面的東西刪除干凈,這樣就清除了OD的歷史記錄。
?
四:脫殼方法之根據(jù)堆棧平衡原理找OEP(ESP定律法)
???
??? 堆棧平衡原理找OEP,Lenus寫過一篇文章《尋找真正的入口(OEP)--廣義ESP定律》我會(huì)打包給大家,有興趣的可以自己看一下堆棧平衡原理,做免殺自己寫花指令也需要用到這個(gè)原理,所以這文章對(duì)大家相當(dāng)有幫助。
?
??? 1.F8單步跟蹤調(diào)試在關(guān)鍵句的下一句,在OD寄存器窗口ESP突顯為紅色
??? 2.在OD命令行下輸入(dd ESP突顯紅色的地址) 或者 (hr ESP突顯紅色的地址)
??? 3.下硬件訪問斷點(diǎn)
??? 4.F9運(yùn)行(然后刪除硬件斷點(diǎn)),繼續(xù)F8單步向下調(diào)試。
?
五:脫殼方法之內(nèi)存斷點(diǎn)法找OEP(內(nèi)存鏡像法)
?
??? 1.OD載入程序后,我們直接對(duì)code段下內(nèi)存訪問斷點(diǎn)
??? 2.Shift+F9運(yùn)行 (code段沒有解壓完畢,所以會(huì)不斷得中斷,連續(xù)按F9。當(dāng)然這種方法是不可取的)
?
正確的方法是:我們使用兩次斷點(diǎn)法。
假設(shè)我是程序作者,一個(gè)程序有code段,data段,rsrc段....依次排列在你的內(nèi)存空間中。那么我會(huì)怎么解碼呢?程序會(huì)先將code段解碼,然后再將data段解碼,接著是rsrc段....只要你在data段或者rsrc段下內(nèi)存訪問斷點(diǎn),那么中斷的時(shí)候code段就已經(jīng)解壓完畢了。這時(shí)我們?cè)賹?duì)code段下內(nèi)存訪問斷點(diǎn),不就可以直接到達(dá)OEP了嗎?
?
綜上正確的操作方法是:
1, 1.OD載入程序-->查看-->內(nèi)存-->在程序塊(屬主名和程序名一樣)的rsrc段F2-->Shift+F9(忽略異常運(yùn)行到該斷點(diǎn))-->然后再對(duì)code段(一般它的地址是:00401000)F2下斷-->Shift+F9(對(duì)于tElock直接就到OEP了,也不再F2-->Shift+9運(yùn)行到該處了,因?yàn)檫@里對(duì)應(yīng)的就是我們?cè)赾ode段設(shè)斷點(diǎn)的地方)。注:兩個(gè)斷點(diǎn)不用刪除
?
??? 總結(jié)一下:如果我們知道殼在什么地方對(duì)code段解壓完畢我們就可以使用內(nèi)存斷點(diǎn),找到OEP。如果不知道,那么我們就依靠2次內(nèi)存斷點(diǎn)去找,如果還不行就用多次內(nèi)存斷點(diǎn)。總之明白了原理再多次的內(nèi)存斷點(diǎn)其實(shí)都一樣。
?
??? 局限性:當(dāng)一個(gè)殼如果它在JMP到OEP前的一行代碼仍在對(duì)code段解壓,那么我們就不能再使用這種辦法了。更貼切得說,是我們沒必要使用這種方法。(如UPX,ASPACK)
?
六:脫殼方法之最后一次異常法
?
??? 1.OD載入程序后
??? 2.設(shè)置異常選項(xiàng):選項(xiàng)——調(diào)試設(shè)置——異常(一般情況我們忽略所有的異常選項(xiàng)(去掉所有的勾選),當(dāng)然后面根據(jù)猛殼的特點(diǎn)我們可以自己選擇設(shè)置異常選項(xiàng),注意:只有用這種方法是需要設(shè)置這里,其它方法一定要全部勾選上,不然不能跟蹤下去的)
??? 3.重載下OD(然后,插件-->隱藏od-->隱藏(不然OD會(huì)跑飛的),然后不用重載了),我們按SHIFT+F9,直到程序跑起來為止,我們把按的次數(shù)記住
??? 4.再次重載OD,再次按SHIFT+F9,我們按到程序跑起來的前一次。(第一次如果按了21下程序跑起來了,那么我們第二次就按20次,跑起來的前一次)
??? 5.在OD的右下角(堆棧窗口)看見一個(gè)"SE句柄",這時(shí)我們按CTRL+G,輸入SE句柄前的數(shù)值(注:不是地址)!?
??? 6.來到SE句柄的地方我們按F2下斷,F9運(yùn)行至斷點(diǎn)這,然后再F2取消斷點(diǎn)
??? 7.接著我們F8單步繼續(xù)向下調(diào)試
?
?
經(jīng)驗(yàn):popad
????? Jmp? XXXX
????? 看到這兩句就應(yīng)該引起我的注意,特別當(dāng)jmp 沒注明short時(shí),那么這里很可能就是殼的出口,也即OEP入口。
七:脫殼方法之其他方法
???
八:模擬跟蹤法
???
1.F9運(yùn)行程序,確定是否有暗樁。看程序能不能跑起來,如果程序能正常跑起來說明沒有暗樁(有暗樁才能用這種方法)
2,用“脫殼方法之最后一次異常法”(到6)(目的是把暗樁給過掉)
??? 2.打開內(nèi)存鏡像,找到包含有SFX,imports,relocations的區(qū)段
??? 3.命令行下輸入tc eip<區(qū)段地址(上面找到的包含有SFX,imports(輸入表),relocations(重定向)的區(qū)段的地址)。回車后會(huì)自動(dòng)跟蹤出OEP地址。
?
九:根據(jù)編譯語(yǔ)言特點(diǎn)找OEP
?
??? (一).delphi程序
??? 1.執(zhí)行程序。
??? 2.用LordPE脫殼。
??? 3.接著用16進(jìn)制編輯器(如Hex Workshop,winhex,UE等)打開脫殼程序。
??? 4.搜索文本“runtime”,搜到后,向前查找離“runtime”最近的十六進(jìn)制數(shù)字“55 8B EC”,
??? 數(shù)字所在的地址就是程序的OEP。
?
??? (二).Visual C程序
??? 利用Visual C啟動(dòng)部分的幾個(gè)函數(shù)GetCommandLineA(W)、GetVersion、GetModuleHandleA(W)、
??? GetStartupInfoA(W) 等來定位程序的OEP。
?
十. 一步到達(dá)OEP
???
??? 1.開始按ctrl+f,輸入:popad(適合少數(shù)殼,如UPX,ASPACK等)
??? 2.F2下斷,F9運(yùn)行到此斷點(diǎn)處,再F2取消斷點(diǎn)
??? 3.F8繼續(xù)向下調(diào)試
十一: “SFX”法
???
??? 1.設(shè)置OD,忽略所有異常(去掉所有勾選)
??? 2.切換到SFX選項(xiàng)卡,選擇“字節(jié)模式跟蹤實(shí)際入口(速度非常慢)”
3.重載程序(自動(dòng)走到OEP停下來)
(注:用完之后記得還原設(shè)置:停在解壓入口)
?
十二: 內(nèi)存另類斷點(diǎn)法
?
??? 1.OD載入程序
??? 2.在內(nèi)存鏡像中找到包含code/text(代碼)的區(qū)段,雙擊,然后在數(shù)據(jù)窗口第一個(gè)下內(nèi)存訪問斷點(diǎn)
3.不斷的按F9,直到從程序領(lǐng)空到系統(tǒng)領(lǐng)空,記錄下按了幾下(如:9次)(按得過程注意可能反應(yīng)比較慢,要按一下等一會(huì)兒,即到暫停狀態(tài)再按,(文件按鈕下顯示狀態(tài)))
??? 4.重載,繼續(xù)上面的操作,不同的是我們按8次F9 。
??? 5.然后繼續(xù)用單步跟蹤法調(diào)試
?
??? Btw:OEP可能會(huì)在我們到達(dá)的地方的上面,我們可以倒著走,向下跳轉(zhuǎn)不讓實(shí)現(xiàn),實(shí)現(xiàn)向上跳轉(zhuǎn)。也可以在程序跑起來的前兩次開始F8跟蹤,大家多多實(shí)驗(yàn)。
?
??? 好了,我們今天的課程就到這里,部分資料會(huì)打包給大家。大家有空好好復(fù)習(xí)下,今天給大家留下作業(yè)就是用多種方法找到課件中的FSG2.0和TELOCK的OEP。
轉(zhuǎn)載于:https://www.cnblogs.com/eldn/archive/2012/08/28/2660896.html
總結(jié)
以上是生活随笔為你收集整理的第四课 脱壳必备知识要点及方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ExtJS 4 Beta 2预览:Ext
- 下一篇: 幽默集锦