windows 32位以及64位的inline hook


Tips : 這篇文章的主題是x86及x64 windows系統下的inline hook實現部分。

 

32位inline hook

對於系統API的hook,windows 系統為了達成hotpatch的目的,每個API函數的最前5個字節均為:

8bff   move edi,edi

55     push ebp

8bec  mov ebp,esp

其中move edi,edi這條指令是為了專門用於hotpatch而插入的,微軟通過將這條指令跳轉到一個short jmp,然后一個long jmp可以跳轉到任意4G范圍內的代碼(http://blogs.msdn.com/b/oldnewthing/archive/2011/09/21/10214405.aspx),達到運行中替換dll的目的。

假設我們要求把0x12345678這個地址的函數hook,使其跳轉到0x12345690,我們可以將這5個字節替換為:0xe9 (0x12345690-0x12345678-5) ,以達到跳轉到0x12345690這個地址的目的(此處,注意大小端系統的區別),這條指令是相對跳轉。

64位inline hook

64位系統沒有了上面這樣的方便之處,因此必須有一種新的策略。

64位的跳轉,可用兩種方法,下面兩個方法都是絕對跳轉指令,第一個影響rax寄存器,可能需要先保存原來的rax的值:

1,

48 b8 ef cd ab 89 67 45 23 01   mov rax, 0x0123456789abcdef
ff e0                           jmp rax

2,

0xff25 [0x00000000]

0xef cd ab 89 67 45 23 01  

這里用第二種方法,將一個old_func_address的前x個字節修改為跳轉到我們的new_func_address,步驟:

1,反匯編old_func_address處的指令,累加其長度,依次反匯編下去,直到長度大於12,例如為15;

2,復制這15個字節的指令,將old_func_address的前12個字節修改為:0xff25 0x00000000 new_func_address(8個字節);

3,跳轉完成之后將其前15個字節還原。

這個方法要求函數長度大於15個字節,所以有一個方法用於適用於小於15字節長度的函數:

通過一個0xe9 tmp_address跳轉到我們申請的空間(該空間地址與old_func_address的間隔在4G范圍內,通過VirsualAlloc函數達成),在tmp_address處再long jmp(0xff25 …)。

 

這里貼一個得到指令長度的網址:http://bbs.pediy.com/showthread.php?t=147401,附件上傳到網盤:http://pan.baidu.com/s/1o6yh1Rc

上述是我工作中用過的方法,可行。如有錯誤或建議,請留言,謝謝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM