脫殼實踐之尋找OEP——兩次記憶體斷點法

來源:互聯網
上載者:User

標籤:roc   情況   內容   實現   目的   構造   重定位   通過   OLE   

  0x00 前言

  對於加殼程式第一件事就是要找到OEP(oringinal Entry point),由於加殼的緣故,當PE檔案載入OD或者其他調試軟體時進入的的往往是殼程式的入口地址。所以要進行逆向分析第一步就必須找到PE程式的原始進入點。

  0x01 殼的載入過程

  殼和病毒在某些方面比較類似,都需要比原程式更早獲得控制權。殼修改了原程式的的執行檔案的組織圖,從而比原程式更早獲得控制權,並且並不會影響原程式的正常運行。瞭解的殼的載入過程對於脫殼加殼異常重要。殼的載入過程如下:

1)儲存入口參數

  加殼程式初始化時儲存各個寄存器的值,外殼執行完畢,再恢複各個寄存器內容,最後再跳到來源程式的入口處執行。通常,用pushad/popad,pushfd/popfd指令來儲存的和恢複現場環境。

2)擷取殼自己所需的API函數

  一般的殼輸入表只有GetProAddress,GetMoudleHanle,LoadLibrary這幾個API函數,甚至只有Kernel32.DLL以及GetProAddress。如果需要其他的API函數,可以通過LoadLibraryA(W)或者LoadLibraryExa(W)將DLL檔案映像映射到調用進程的地址空間,函數返回的HINSTANCE值用於標識檔案映像到虛擬記憶體地址。

LoadLibrary函數的原型如下:

HINSTANCE LoadLibrary{

LPCTSTR lpLibFileName   //DLL檔案名稱地址

}

傳回值:成功時返回模組控制代碼,失敗返回NULL。

當DLL檔案已經被映射到調用進程的地址空間裡,可以調用GetModuleHanleA(W)函數獲得DLL模組的控制代碼,函數的地址原型如下:

HMODULE GetModuleHandle{

LPCTSTR lpModuleName   //DLL檔案地址

}

一旦模組被載入,線程就可以調用GetProcAddress函數擷取輸入函數地址。函數的原型如下:

FARPROC GetProcAddress{

HMODULE hModlue  //DLL模組控制代碼

LPCSTR  lpProName //函數名

}

 這三個函數異常重要,對於程式加殼協助很大。後面幾篇將會詳細介紹用法,這裡暫且羅列出來。

3)解密原程式的各個區塊的資料

  殼出於保護原程式碼和資料的目的,一般都會加密原程式檔案的各個區塊,在程式時外殼將會對這些資料解密,以讓程式能夠正常運行。殼一般都是按區塊加密的,那麼在解密時也是按區塊解密的,並且把解密的區塊資料按照區塊的定義放在合適的記憶體位置。

4)ITA的初始化

ITA填寫,本來應該由PE載入器實現。但是由於加殼時,自己構造了一個輸入表,並且讓PE檔案頭輸入表指標指向了自建的輸入表。所以PE裝載器就對自建的輸入表進行填寫。那麼原來PE輸入表只能由外殼程式來填寫了。外殼所要做的就是將這個新輸入表結構從頭到尾掃描一遍,對每一個DLL引入的所有函數重新擷取地址,並填寫在ITA表中。

5)重定位處理

  檔案執行時將被映像到指定的記憶體位址中,這個初始地址稱為基址。對於EXE檔案,windows系統會盡量使用EXE問價所指定的記憶體位址,比如某EXE問價的基址為40000h,而運行時Windows系統提供給程式使用的基地址也是40000h。這種情況就不需要重定位了。對於DLL檔案,windows沒辦法每一次提供DLL運行時提供相同的基址。對於這種情況,重定位是必須的。此時殼程式也需要提供PE檔案的重定位功能。所以加殼DLL檔案比加殼EXE檔案多一個重定位表。

6)HOOK-API

 程式檔案中輸入表的作用是讓windows系統在程式運行時提供API的實際地址給程式使用。在程式的第一行代碼執行前,windows系統就完成了這項工作。

  殼程式一般都修改了原程式的輸入表,然後自己模仿windows系統的工作來填充輸入表的中相關資料。在填充過程中,外殼程式可填充HOOK-API的代碼地址,這樣就可間接的擷取程式的控制權。

7)跳轉到程式進入點(OEP)

經曆過以上步驟後,外殼程式的功能就完成了,隨後他會把控制權交給原程式,一般的殼這裡會有一個明顯的“分界線”。當然現在越來越多的加密殼將OEP一段代碼搬到外殼的地址空間裡,然後將這段代碼清除掉。這種方式稱為StolenBytes。這樣,OEP與外殼就沒有明顯的分界線了,這增加了脫殼的難度。

  0x02 利用兩次記憶體斷點法手動找到OEP

  兩次記憶體法的原理就是利用了殼載入過程第三步時需要對各個區段進行解密並將解密後的區段寫入各個區段,完畢之後會跳轉至原程式的OEP處。當然,如果我們能判斷出殼何時跳轉至OEP處最好,但是一般這並不容易。但是我們可以先對.data區塊下斷後再運行程式(因為區段.code比.data先解壓,運行到這個斷點時.code以及解密完成),隨後再對.code(有的編譯器是.text)段下斷在運行,這樣程式就會停在OEP處(因為解密完成後殼程式一定再次返回到OEP處,將控制權交給原程式)。這個方法就是兩次記憶體法。

  0x03 執行個體介紹兩次斷點法找OEP過程

 1)將檔案拖入od,alt+m進入記憶體模板,隨後對.data區塊按F2下斷,如:

  2)點擊F9運行,此時程式停在了下來,如:

 這裡其實馬上就要對.data區塊進行解密讀寫操作了,此時再alt+m進入記憶體模組,對.text(這個就是.code區塊,由於編譯器不同,有的顯示.text區塊)區塊下斷。

 3)點擊F9運行,此時程式停止,如:

 其實這裡就是原程式的OEP地址了,由於od對PE檔案進行了分析,所以顯示如,我們可以右鍵,刪除模組分析即可得到:

 

標紅框的地方就是OEP地址了。

  0x04  總結

  兩次記憶體斷點法雖然簡單,但是我們還是要弄清楚其中的原理。它其實就是利用殼載入過程需要對區段進行解密然後返回原程式OEP這一特性。

 

脫殼實踐之尋找OEP——兩次記憶體斷點法

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.