64位下的InlineHook


x64下手工HOOK的方法

關於64位程序.網上HOOK方法一大堆.這里也記錄一下. 了解跨平台HOOK的真相與本質.

一丶HOOK的幾種方法之遠跳

1. 遠跳 不影響寄存器 + 15字節方法

在64位下 HOOK有幾種方法. 一種是影響寄存器的值.另一種是不影響寄存器的值.各有優劣.

第一種: 不影響寄存器的值 硬編碼占用大小為15個字節.

原理: 利用push + ret的原理. 讓HOOK的位置跳轉為我們的地址.

push 函數低地址(8個字節)
mov qword ptr ss:[rsp + 4],函數高地址(8個字節,不過高4個字節一般都是0所以可以不用給)
ret

硬編碼:

68 XX XX XX XX							push LowAddress
48 C7 44 24 04 XX XX XX XX              mov qword ptr ss:[rsp + 4],HighAddress
C3	                                    ret

其中XX的地方可以換成我們的地址.

2.遠跳 影響寄存器 + 12字節方法

這一種方法則會影響寄存器的值.

原理: 利用 rax + jmp的方式進行跳轉.

mov rax,Address
Jmp rax

硬編碼

48 B8 XX XX XX XX XX XX XX XX FF E0 

截圖:

這里需要注意的是地址的大小尾模式. 填寫一定不要寫錯.

3.影響寄存器,恢復寄存器 進行跳轉.

這種方法其實是第二種方法的演變. 第二種我們會直接修改rax為我們的地址.其實我們可以利用堆棧進行保存.

原理: rax + jmp + push 進行恢復還原


push reg
mov reg,address
jmp reg
pop reg

reg代表的就是任意寄存器. 如果使用這個方法可以有效地保存寄存器進行HOOK.跳轉回來的時候進行還原即可.

這里的硬編碼不確定.因為 push reg 與 pop reg 跟你使用的寄存器有關.

4. 常用 jmp + rip方式跳轉 大小6個字節

在64位程序中. 可以使用rip寄存器了. 而32位不可以.32位下想要改變 eip的值. 無非就是 jmp + call才可以改變.64位可以使用

原理: jmp + rip 進行尋址. 進行跳轉

jmp qword ptr ds:[rip]
數據地址

這種方法就是 對rip + (指令長度)這個寄存器取內容 把里面的數據當做地址進行跳轉. 所以當使用這個方式的時候.我們的下方跟着八個字節數據即可. 這個數據就是你要跳轉的地址.

如下:

它會把下面八個字節數據當做地址進行跳轉.

這時候有人說了.你這不是6字節跳轉呀.下面要跟着8個字節. 所以這里說一下.
使用這種方法. 在rip的下面不一定要跟着就是數據. 我們可以修改偏移進行跳轉.
什么意思. 現在我們是 jmp qword ptr ds:[rip] ,代表了我們要在當前rip的下方取8個字節當做地址跳轉. 那么我們也可以寫成 jmp qword ptr ds:[rip + x];
x就是任意數. 把這個偏移下的8個字節去內容當做地址去跳轉.

關於偏移 計算公式其實還是一樣. 目的地址 - 源地址 - 指令長度.

如下:

比如我們從第一條指令 進行偏移跳轉. 把圖中紅框內容當做8個字節數據進行跳轉.

那么可以寫成如下:

目的地址(紅框地址,0x7FFF12A51228) - 源地址(7FFF12A511Dd) - 指令長度(6)

指令長度為什么是6.因為我們第一行指令是 jmp qword ptr ds:[rip] 只不過我們現在還沒寫. 我們得出的偏移放到第一行中的偏移..

現在得出的偏移為 0x45 這個45我們就可以填寫到偏移中.

現在 0x7FFF12A51228 紅框地址是我們的數據.只需要在這里寫入8個字節地址即可.

如下圖:

如上圖可以看到,第一個紅框 FF 25 45 00 00 00 這個45就是我們算的偏移.
意思就是在 rip + 45位置,讀取8個字節數據當做地址進行跳轉. 然后 228地址我們寫入了8個字節數據. 數據的地址 后綴為1EC的地址. 所以看上圖,我們的RIP已經跳轉過去了.

注意,因為 rip的尋址偏移只能是上下2GB 也就是你的偏移不要超過2G位置即可.

二丶Call的幾種方式.

1. CALL PUSH + RET 方式

這種方式跟上方的push + ret原理類似.

call Next
Next:
push lowAddress;
mov [rsp + 4],highAddress
ret

這種方式就是取得下一行指令, 下一行指令入棧. 然后繼續push + ret 進行跳轉.

2.正常call

這種call 沒有試過. 原理跟上面一樣. 硬編碼 E8 偏移 的方式調用


call youAddress

硬編碼為: E8 XX XX XX XX xx代表偏移. 偏移計算公式還是 目的 - 源 - 5(指令長度)

但是是上下2GB

其他待整理


免責聲明!

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



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