《逆向工程核心原理》第33章原始碼分析(上)

2021-10-02 15:00:46 字數 3964 閱讀 2134

用於注入dll

bool injectallprocess

(int nmode, lpctstr szdllpath)

while

(process32next

(hsnapshot,

&pe));

closehandle

(hsnapshot)

;return true;

}

首先呼叫createtoolhelp32snapshot返回系統所有程序的控制代碼

bool injectdll

(dword dwpid, lpctstr szdllpath)

premotebuf =

virtualallocex

(hprocess,

null

, dwbufsize,

mem_commit, page_readwrite)

;writeprocessmemory

(hprocess, premotebuf,

(lpvoid)szdllpath, dwbufsize,

null);

pthreadproc =

(lpthread_start_routine)

getprocaddress

(getmodulehandle

(l"kernel32.dll"),

"loadlibraryw");

hthread =

createremotethread

(hprocess,

null,0

, pthreadproc, premotebuf,0,

null);

waitforsingleobject

(hthread, infinite)

;virtualfreeex

(hprocess, premotebuf,

0, mem_release)

;closehandle

(hthread)

;closehandle

(hprocess)

;return true;

}

openprocess根據傳入的pid得到特定程序的控制代碼,並且獲得了all_access許可權。

virtualallocex在程序中分配一定大小的空間,此大小是路徑名字串所佔空間大小。返回值是分配空間的首位址。

writeprocessmemory傳入程序控制代碼、分配空間首位址、路徑字串首位址,路徑長度,在分配空間中傳入了路徑字串。

getprocaccess傳入kernel32.dll控制代碼和loadlibraryw字串,返回loadlibraryw入口位址,強制轉換為lpthread_start_routine用來當做createremotethread的傳入引數。

createremotethread傳入程序控制代碼、loadlibraryw位址和目標程序字串首位址,在目標程序中注入函式。

waitforsingleobject等待訊號量,變為已通知狀態時執行執行緒。

用於api鉤取

結構很簡單,dllmain呼叫hook_by_code呼叫newzwquerysysteminformation。

// global variable (in sharing memory)

#pragma comment(linker, "/section:.share,rws")

#pragma data_seg(".share")

tchar g_szprocname[max_path]=;

#pragma data_seg()

//export function

#ifdef __cplusplus

extern

"c"#ifdef __cplusplus

}#endif

#pragma comment(linker, 「/section:.share,rws」)讓聯結器知道有乙個share共享資料段,同時具有read,write,share屬性。

#pragma data_seg(".share")建立了乙個share的共享資料段,下一行在此資料段中定義了g_szprocname[max_path]陣列。

#pragma data_seg()表示宣告的結束

#ifdef __cplusplus

extern 「c」

;char

*p =

null

;// #1. 若當前程序為hideproc.exe則終止,不進行鉤取操作

getmodulefilenamea

(null

, szcurproc, max_path)

; p =

strrchr

(szcurproc,

'\\');

if((p !=

null)&&

!_stricmp

(p+1

,"hideproc.exe"))

return true;

switch

( fdwreason )

//呼叫原因

return true;

}

bool hook_by_code

(lpcstr szdllname, lpcstr szfuncname, proc pfnnew, pbyte porgbytes)

; pbyte pbyte;

//獲取要鉤取的api位址

pfnorg =

(farproc)

getprocaddress

(getmodulehandlea

(szdllname)

, szfuncname)

; pbyte =

(pbyte)pfnorg;

//若已被鉤取,則結束

if( pbyte[0]

==0xe9

)return false;

//向記憶體的五個位元組新增寫屬性

virtualprotect

((lpvoid)pfnorg,

5, page_execute_readwrite,

&dwoldprotect)

;//備份原有**

memcpy

(porgbytes, pfnorg,5)

;//計算jmp位址

// => ***x = pfnnew - pfnorg - 5

dwaddress =

(dword)pfnnew -

(dword)pfnorg -5;

memcpy

(&pbuf[1]

,&dwaddress,4)

;//hook:修改五個位元組

memcpy

(pfnorg, pbuf,5)

;// 恢復記憶體屬性

virtualprotect

((lpvoid)pfnorg,

5, dwoldprotect,

&dwoldprotect)

;return true;

}

為什麼pbyte[0] == 0xe9就代表被鉤取了呢?

因為hook後,pfnorg最初的五個位元組被修改為e9 ******xx,e9代表彙編指令jmp。

然後就是要計算******xx(下面用x代替)等於多少了。

jmp指令轉換為機器碼時,需要計算當前eip和目標位址的差,但是jmp指令佔五個位元組,jmp還沒執行時,當前eip的值是jmp指令首位址+5個位元組。

因為當前eip+5+x = 目標位址

所以x =目標位址 - 當前eip -5

把e9 ******xx寫入pbuf,再寫入pfnorg,就完成了hook操作。

最後恢復記憶體屬性。

逆向工程核心原理 第二章

首先我們跟隨書本,寫乙個帶有彈窗的程式 源 是這樣的 首先我們跟隨程式整體看一遍 看到有乙個0x401005,和我們的0x401000很近的乙個位址,我們懷疑他就是main函式,所以我們進入看看 看到裡面不僅有我們輸入的字串,而且還有乙個messagbox的函式,所以我們可以確定這就是main函式 ...

逆向工程核心原理 第十五章

第十五章的15.3介紹了upx殼的四個迴圈及其作用,接下來我們乙個乙個的看一下 迴圈1 通過 我們能知道,ecx為迴圈次數,迴圈的內容是從edx中讀取乙個位元組放入edi中,這個位元組就是節區 upx0 0042d6fd 8a02 mov al,byte ptr ds edx 將edx放入al 00...

逆向工程核心原理 第六章

第六章是分析乙個crackme檔案 首先還是看看這個檔案,開啟之後是什麼樣子的 開啟後是兩個彈窗 點了確定之後就沒有了。根據書本的步驟,我們要通過修改關鍵跳,破解。首先我們看到這個程式 所以我們將關鍵跳的命令修改為 可以看到我們把指令由原來的 je 改為了現在的 jmp 因為 je 是需要滿足條件才...