OEP尋蹤

1)搜索JMP或者CALL指令的機(jī)器碼(即一步直達(dá)法,只適用于少數(shù)殼,包括UPX,ASPACK)

? 對(duì)于一些簡單的殼可以用這種方式來定位OEP,但是對(duì)于像AsProtect這類強(qiáng)殼(PS:AsProtect在04年算是強(qiáng)殼了,嘿嘿)就不適用了,我們可以直接搜索長跳轉(zhuǎn)JMP(0E9)或者CALL(0E8)這類長轉(zhuǎn)移的機(jī)器碼,一般情況下(理想情況)殼在解密完原程序各個(gè)區(qū)段以后,需要一個(gè)長JMP或者CALL跳轉(zhuǎn)到原程序代碼段中的OEP處開始執(zhí)行原程序代碼。

下面我們將上一章中加了UPX殼的那個(gè)CrueHead的CrackMe加載到OD中:

這里我們按CTRL+B組合鍵搜索一下JMP的機(jī)器碼E9,看看有沒有這樣一個(gè)JMP跳轉(zhuǎn)到原程序的代碼段。

這個(gè)JMP是跳轉(zhuǎn)到第一個(gè)區(qū)段的,我們在這條指令處設(shè)置一個(gè)斷點(diǎn),斷在這里時(shí),我們按F7鍵就可以單步跳轉(zhuǎn)到OEP處。

除了搜索JMP指令的機(jī)器碼以外,大家還可以嘗試搜索CALL EAX,CALL EBX,JMP EAX等指令的機(jī)器碼,因?yàn)楹芏鄽な菍EP的值存放在寄存器中,然后通過CALL 某寄存器或者JMP 某寄存器來跳往OEP的。OllyBbg提供了搜索ALL COMMANDS的功能,我們可以通過單擊鼠標(biāo)右鍵選擇-Search for-All Commands來搜索,然后各個(gè)指令處依次設(shè)置斷點(diǎn),下面我們來看個(gè)例子。

2)堆棧平衡法(ESP定律法)

? 這種方法適用于一些古老的殼。這些殼首先會(huì)使用PUSHAD指令保存寄存器環(huán)境,在解密各個(gè)區(qū)段完畢,跳往OEP之前,會(huì)使用POPAD指令恢復(fù)寄存器環(huán)境。

這里我們來看看CRACKME UPX。

我們可以看到第一條指令就是PUAHAD,有的情況下保存寄存器環(huán)境可能不是第一條指令,但也在附近了,還有些情況下,有些殼不使用PUSHAD,而是逐一PUSH各個(gè)寄存器(例如:PUSH EAX,PUSH EBX等等),總而言之,在解密完區(qū)段,跳往OEP之前會(huì)恢復(fù)寄存器環(huán)境。

這里我們按F7鍵執(zhí)行PUSHAD:

可以看到各個(gè)寄存器的初始值被壓入到堆棧中了,這里我們可以對(duì)這些初始值設(shè)置內(nèi)存或者硬件訪問斷點(diǎn),當(dāng)解密例程讀取這些初始值的時(shí)候就會(huì)斷下來,斷下來處基本上就在OEP附近了。

這里我們可以通過在ESP寄存器值上面單擊鼠標(biāo)右鍵選擇-Follow in dump在數(shù)據(jù)窗口中定位到這些寄存器的初始值。

數(shù)據(jù)窗口中顯示的堆棧內(nèi)容如下:


這里我們可以對(duì)這些初始值的第一個(gè)字節(jié)或者前4個(gè)字節(jié)設(shè)置硬件訪問斷點(diǎn)。

選擇字節(jié),字,雙字都可以,只要解密例程在讀取這些值的時(shí)候斷下來就OK,運(yùn)行起來。

我們可以斷在了POPAD指令的下一行,當(dāng)殼的解密例程讀取該值的時(shí)候斷了下來,緊接著下面就是跳往OEP處,說明這個(gè)方法起作用了。


3)VB應(yīng)用程序定位OEP(Native 或者 P-CODE)

定位VB程序的OEP比較容易,因?yàn)閂B應(yīng)用程序都有一個(gè)特點(diǎn)-開始都是一個(gè)PUSH指令,緊接著一個(gè)CALL指令調(diào)用一個(gè)VB API函數(shù)。我們可以使用Patch過的OD,首先定位到VB的動(dòng)態(tài)庫,接著給該動(dòng)態(tài)庫的代碼段設(shè)置內(nèi)存訪問斷點(diǎn),

當(dāng)殼的解密例程解密完原程序各個(gè)區(qū)段,接著就會(huì)斷在VB DLL的第一條指令處,接著我們可以在堆棧中定位到返回地址,就可以來到OEP的下一條指令處。這里我們也可以使用前面介紹的方法-跟逐一給各個(gè)區(qū)段設(shè)置內(nèi)存訪問斷點(diǎn)(使用Patch過的OD),但是很多殼會(huì)檢測這種方法,所以大家可能根據(jù)需要不同的情況來嘗試這不同的方法。這種方法很容易理解,我就不舉例子了,以后大家如果遇到了VB程序可以試試這種方法。

4)?最后一次異常法

? 如果我們在脫殼的過程中發(fā)現(xiàn)目標(biāo)程序產(chǎn)生大量異常的話,就可以使用最后一次異常法,我們來看一個(gè)例子,名字叫做”bitarts_evaluations.c”。

我們還是使用Patch過的OD來加載它,并且配置好反反調(diào)試插件。

然后將EXCEPTIONS菜單項(xiàng)中的忽略各個(gè)異常的選項(xiàng)都勾選上,運(yùn)行起來。

我們可以看到程序運(yùn)行起來了,我們單擊工具欄中L按鈕打開日志窗口。

這里我們可以看到產(chǎn)生了好幾處異常,但是都不是位于第一個(gè)區(qū)段,說明這些異常不是在原程序運(yùn)行期間發(fā)生的,是在殼的解密例程執(zhí)行期間產(chǎn)生的異常,最后一次是46e88f處的這個(gè)異常。

好,現(xiàn)在我們重新啟動(dòng)OD,將EXCEPTIONS菜單項(xiàng)中忽略的異常選項(xiàng)的對(duì)勾都去掉,僅保留Ignore memory access violations in KERNEL32這個(gè)選項(xiàng)的對(duì)勾。


我們運(yùn)行起來,產(chǎn)生異常斷了下來,我們直接按SHIFT + F9忽略異常繼續(xù)運(yùn)行。直到停在了46E88F處為止。

這里不是,我們按SHIFT + F9忽略異常繼續(xù)運(yùn)行,我們知道最后一次異常是46E88F處的INT 3指令引發(fā)的。

這里是殼的解密例程執(zhí)行過程中產(chǎn)生的最后一次異常,接著就是執(zhí)行原程序的代碼了。

5)利用應(yīng)用程序調(diào)用的第一個(gè)API函數(shù)來定位OEP

這種方法就是直接給應(yīng)用程序調(diào)用的第一個(gè)API函數(shù)設(shè)置斷點(diǎn),比如說,很多程序(VC++)一開始會(huì)調(diào)用GetVersion,GetModuleHandleA,對(duì)于bitarts_evaluations.c來說我們可以斷GetVersion,對(duì)于CRACKME UPX來說我們可以斷GetModuleHandleA。這里是bitarts_evaluations.c,所以我們給GetVersion設(shè)置斷點(diǎn)。

運(yùn)行起來。

這里我們斷在了GetVersion的入口點(diǎn)處,從堆棧中我們可以看到返回地址位于第一個(gè)區(qū)段。我們直接在返回地址上面單擊鼠標(biāo)右鍵選擇-Follow in Disassembler。



里我們又定位到了OEP。以上就給大家演示的如何利用應(yīng)用程序調(diào)用的第一個(gè)API函數(shù)來定位OEP了。如果我們遇到有的殼檢測GetVersion入口處的INT 3斷點(diǎn)的話,我們可以嘗試在該API函數(shù)的返回指令RET處下斷。

其實(shí)還有很多適用于特定殼定位OEP的方法,這里就不給大家一一介紹了,基本上也是根據(jù)上面的這些基本方法變通來的,所以說大家掌握好上述這些基本的定位OEP的方法和原理就即可。

這里給大家留一個(gè)小程序練習(xí),名字叫做UnPackMe_tElock0.98。大家嘗試定位其OEP。這個(gè)殼專門采取了一些技巧來干擾利用上述方法定位OEP,所以說如果直接利用上述這些方法的話,就不能奏效了,大家可以好好琢磨一下這個(gè)殼。

大家記住,如果殼檢測INT 3斷點(diǎn)或者硬件斷點(diǎn)的話,你使用ESP定律給堆棧中的寄存器初始值設(shè)置硬件斷點(diǎn)也是不起作用的,只能換其他方法。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 完美的免殺方法到目前為止,要實(shí)現(xiàn)惡意軟件的“FUD”,加密惡意代碼被認(rèn)為是個(gè)不錯(cuò)的選擇,不過有幾點(diǎn)要注意:1.惡意...
    極客圈閱讀 1,193評(píng)論 0 2
  • 本文轉(zhuǎn)載自:http://www.freebuf.com/articles/others-articles/181...
    inspireboom閱讀 7,922評(píng)論 0 13
  • 每個(gè)人的成長經(jīng)歷都不一樣,但是在每個(gè)人的成長里都少不了喜、怒、哀、樂,世間萬物的生長,其實(shí)跟人的成長差不...
    生如夏花_380f閱讀 311評(píng)論 0 2
  • 當(dāng)你背叛了別人時(shí),你會(huì)為此感到不安并想救贖自己嗎? 當(dāng)你遭到別人的背叛時(shí),你會(huì)選擇寬恕和原諒,并一如既往地把那個(gè)...
    Kland閱讀 390評(píng)論 0 3

友情鏈接更多精彩內(nèi)容