菜鳥脫殼之脫殼的基礎(chǔ)知識:DUMP的原理
當(dāng)外殼的執(zhí)行完畢后,會跳到原來的程序的入口點,即Entry Point,也可以稱作OEP!當(dāng)一般加密強度不是很大的殼,會在殼的末尾有一個大的跨段,跳向OEP,類似一個殼與程序入口點的“分界線!當(dāng)我們到達了程序的OEP,我們就需要進行DUMP程序了,那么什么時候去DUMP一個程序呢?這里我引用了fly的一句話!
“手動脫殼理想的最佳dump時機是指殼已經(jīng)把程序代碼包括資源等數(shù)據(jù)全部解密、輸入表等數(shù)據(jù)還原但還未填充系統(tǒng)函數(shù)地址、DLL則還未重定位,此時dump出來的文件只需修正OEP、ImportTableRVA等信息即可正常運行完成脫殼。”
并不是所有的程序都要到達OEP才能進行脫殼的,只要把壓縮的全部的代碼數(shù)據(jù)釋放到內(nèi)存中,初始化一些必需的項目,我們就可以選擇合適的DUMP點了!
那么何為DUMP呢?DUMP用中文翻譯過來,就是轉(zhuǎn)存,也就是抓取內(nèi)存鏡像,就是把內(nèi)存指定地址的映像文件讀取出來,然后用文件等形式保存下來!
我們比較常用的DUMP軟件有LordPE、PETools等工具。這些工具基本都是利用Module32Next來獲取將要唄Dump進程的信息,我們打開MSDN來查看下這個函數(shù)的原型:
BOOL WINAPI Module32Next( HANDLE hSnapshot, LPMODULEENTRY32 lpme );
我們再來看看他的參數(shù):
Parameters
hSnapshot
Handle to the snapshot returned from a previous call to the CreateToolhelp32Snapshot function. //由前面的CreateToolhelp32Snapshot 函數(shù)返回的快照
lpme
Pointer to a MODULEENTRY32 structure. //是指向MODULEENTRY32 的指針
我們再在MSDN上面看看MODULEENTRY32的結(jié)構(gòu)是什么樣子的:
typedef struct tagMODULEENTRY32 {
DWORD dwSize; // 這個結(jié)構(gòu)的大小
DWORD th32ModuleID;
DWORD th32ProcessID; // 進程的標(biāo)識符
DWORD GlblcntUsage;
DWORD ProccntUsage;
BYTE * modBaseAddr; // 進程的映像基址
DWORD modBaseSize; // 進程的影響大小
HMODULE hModule; // 進程的句柄
char szModule[MAX_MODULE_NAME32 + 1];
char szExePath[MAX_PATH]; } MODULEENTRY32;
typedef MODULEENTRY32 * PMODULEENTRY32; typedef MODULEENTRY32 * LPMODULEENTRY32;
LordPE就是利用這個結(jié)構(gòu)中的modBaseSize和modBaseAddr 得到進程的映像大小和基址,然后調(diào)用ReadProcessMemory來讀取進程內(nèi)所保存的數(shù)據(jù),LordPE不用進程的文件頭,直接讀取原始的文件的文件頭來用,讀取內(nèi)存數(shù)據(jù)后,再把進程中的數(shù)據(jù)保存到硬盤文件里。
OllyDbg的一個插件OllyDump,也支持DUMP功能,使用起來也比較簡單方便,但是不方便DUMP取DLL文件的鏡像!