本文示例程式及upx加殼工具
一、基本概念的了解
殼的脫殼:如果我們将一個應用程式比喻成一個雞蛋,程式中對我們有用的程式代碼為雞蛋清,而我們需要擷取雞蛋清的時候,就必須打破雞蛋外面的雞蛋殼,也就是進行脫殼的處理。
脫殼的方式:不同的殼對應的脫殼方式會不一樣,甚至相同的殼但是不同的版本,脫殼的方式也會可能不同。
二、示例程式示範
示例程式為win7自帶的notepad.exe ,該程式原本沒有加殼
對該應用程式notepad-UPX.exe進行UPX加殼
壓縮之後查殼
進行upx加殼前後對比
三、脫UPX殼
1、脫殼的基本過程
手動跟蹤到程式的OEP(程式原始入口點),将程式和資料dump下來,然後再進行IAT的相關修複即可。
2、如可查找OEP
(1)需要熟悉各種編譯器生成的程式的入口點的指令。例如vs 程式的入口點一般為:
push ebp
mov ebp,esp
(2)殼進行解壓縮的代碼通常在一個自己的區段裡面運作,解壓縮完成後通常會跳轉到原始程式入口點進行運作,此時跳轉到OEP往往需要一個JMP或CALL,保證EIP指針指向了原始的OEP位址。注:原始的OEP與解壓縮的代碼通常不在一個區段内,是以JMP與CALL往往實作的是跨區段的跳轉。
3、手動的跟蹤脫UPX殼
OD載入程式後,先運作的是殼的解壓縮代碼,逐漸F8往下跟蹤,跟蹤完解壓縮代碼後,跳轉到OEP。
(1)UPX殼所用到的API:LoadLibraryA和GetProcAddress,這兩個API将進行對原始程式的導入函數進行還原。LoadLibraryA進行加載導入函數相關的動态連結庫,GetProcAddress在動态連結庫裡面擷取導入函數的位址進行還原。
LoadLibraryA
GetProcAddress
(2)注意相關的邏輯循環,使用F4運作到指定位置,跳出循環(注意:如果碰到nop的指令,F4定到下一條語句,否則程式會跑飛)。UPX在完成解壓縮之後,會進行跳轉到原始程式入口點,這是跨區段的跳轉,在F8與F4往下運作的同時,注意跨區段的JMP
位址 0x0055B9D4與0x004E53C2,位址之間相差巨大,此時往往為跨區段的跳轉。該條指令就是跳轉到原始程式的入口點,F8自動步入到OEP
(3)打開LoadPE,選中該應用程式程序,右鍵先“修正鏡像大小”,再“完整轉存”,将OD跟進到OEP的程式轉儲下來。
此時轉儲下來的dumped.exe程式無法運作,因為導入表還沒有進行修複
接下來我們進行導入表的修複
(4)計算出OEP的RVA值,也可以在我們跟進的OEP處,右鍵選中Dump Process插件(注:不同的OD的名稱有細微的差别),擷取目前EIP作為OEP的RVA值(Get EIP as OEP)
擷取到OEP的值為 0x000E53C2
(5)使用ImpREC進行對導入表的修複
填寫我們的OEP值,然後點選“自動查找IAT”,再點選“擷取輸入表”,最後進行轉儲到檔案,進行修複dump下來的導入表(無效的指針在脫UPX殼中可以不用删除)
修正後的可執行檔案dumped_.exe
dumped_.exe就是可以正常運作的程式了,我們最後再來查殼看看該程式,此時沒有殼
脫upx殼小技巧:通過脫殼發現,upx殼的解壓縮完成後跳轉到OEP的jmp指令後面為nop指令,通常隻需要滑鼠往下滾動,發現很多nop指令時,就能找到該jmp指令。
四、脫殼找IAT小技巧
我們在進行跟進到OEP後,有可能殼的解壓縮程式并沒有完全的幫我們恢複IAT(例如:FSG殼),而ImpREC并不能幫我們完整的修複,此時就需要我們手動進行修複,如何查找到IAT?
調用系統的API的call指令的二進制指令代碼為 FF 15,是以我們隻需要在OD中,查找FF 15二進制指令就能找到某個導入函數的位址,然後再資料視窗中跳轉到該位址就能到IAT的位置,再進行上下滾動就能查找了。
基本步驟:
1、Ctrl+B或在OD中右鍵->查找->二進制子串
輸入FF 15,點選确定就能查找到某一個導入函數的位址
2、此時查找到的API為kernel32裡面的GetCommandLineA,它在記憶體中的位址為0x53230C,我們在資料視窗中Ctrl+G,輸入該導入函數的位址跳轉到0x53230C(注:資料視窗中需要右鍵->長型->位址才能檢視到API的名稱)
此時查找到IAT,就可以進行一些相關恢複。
upx殼的解壓縮代碼已經進行了完全的恢複,是以此處并不需要進行相關修複。
本文難免有所錯誤,如有問題歡迎留言