试图了解RSP和RBP寄存器的奇怪行为
在四处弯腰时,我注意到这种行为与我对注册RSP和RBP的工作方式的理解有关。 我正在吸引另一个功能,我的目标是保留寄存器和标志的状态,以返回原始功能。在此操作时,我注意到rsp
和rbp
的值(奇怪的r15
)在我的绕行过程中正在发生变化,而无需我触摸它们。进一步测试这一点,我的弯路由我组成,首先倾倒所有寄存器的值(rsp
,rbp
和rip
),并顺序标记到一个特定的地址,推动并弹出所有寄存器和标志,然后再次倾倒所有寄存器和标志,最后我的钩子覆盖在原始功能中的指令。
我的弯路的X64代码如下:
;dump registers
mov rax, 0x1C122560000
mov [rax], rcx
mov [rax+0x8], rdx
mov [rax+0x10], rbx
mov [rax+0x18], rdi
mov [rax+0x20], rsi
mov [rax+0x28], r8
mov [rax+0x30], r9
mov [rax+0x38], r10
mov [rax+0x40], r11
mov [rax+0x48], r12
mov [rax+0x50], r13
mov [rax+0x58], r14
mov [rax+0x60], r15
mov [rax+0x68], rsp
mov [rax+0x70], rbp
;dump flags
push rcx
pushfq
pop rcx
mov [rax+100], rcx
pop rcx
pushfq
push rcx
push rdx
push rbx
push rdi
push rsi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
;this is where my actual detour instructions would happen, but it is currently empty
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rsi
pop rdi
pop rbx
pop rdx
pop rcx
popfq
;dump registers
mov rax, 0x1C122560000
mov [rax+0x78], rcx
mov [rax+0x80], rdx
mov [rax+0x88], rbx
mov [rax+0x90], rdi
mov [rax+0x98], rsi
mov [rax+0xA0], r8
mov [rax+0xA8], r9
mov [rax+0xB0], r10
mov [rax+0xB8], r11
mov [rax+0xC0], r12
mov [rax+0xC8], r13
mov [rax+0xD0], r14
mov [rax+0xD8], r15
mov [rax+0xF0], rsp
mov [rax+0xF8], rbp
;dump flags
push rcx
pushfq
pop rcx
mov [rax+108], rcx
pop rcx
;original instructions (omitted)
...
...
...
ret
然后,我从地址0x1C122560000中读取倾倒寄存器,并带有每个寄存器被倾倒的相应偏移,并将结果写出。该结果如下所示(后缀_1
从第一个转储中标记值,_2
在第二个转储中):
rcx_1: 23E5A6FEE00
rdx_1: 0
rbx_1: 3FFFAB921FE0
rdi_1: 3FF636D38F00
rsi_1: 23E5A6FEE00
r8_1: 0
r9_1: 3FFFAB921FE0
r10_1: 2C7
r11_1: 9E057FFA78
r12_1: 1
r13_1: 0
r14_1: 0
r15_1: 24600000000
rsp_1: 24600000000
rbp_1: 9E00000000
flags_1: 0
rcx_2: 23E5A6FEE00
rdx_2: 0
rbx_2: 3FFFAB921FE0
rdi_2: 3FF636D38F00
rsi_2: 23E5A6FEE00
r8_2: 0
r9_2: 3FFFAB921FE0
r10_2: 2C7
r11_2: 9E057FFA78
r12_2: 1
r13_2: 0
r14_2: 0
r15_2: 0
rsp_2: 9E057FF750
rbp_2: 9E057FF860
flags_2: 0
我很难了解寄存器的值> RSP
,rbp
和r15
在转储之间发生变化,每次调用原始函数时,相同的“模式”重复(所有三个寄存器都会更改每个寄存器时间,其他每个寄存器都保持不变)。据我了解,相同数量的推动和弹出量应返回堆栈框架以指向相同的地址。我是否错过了这些寄存器的工作方式非常明显的东西?我是否通过推动和弹出寄存器有缺陷来保存和恢复连锁功能的原始状态的方法?
While playing around with detours I noticed this behavior that goes against my understanding of how registers rsp and rbp work.
I am hooking another function, and my goal is to retain the state of the registers and flags for when I return back to the original function. Playing around with this, I noticed that the values of rsp
and rbp
(and weirdly enough r15
) are changing during my detour without me touching them. Testing this further, my detour consists of me first dumping the values of all the registers (except rsp
, rbp
, and rip
) and flags sequentially to a specific address, pushing and popping all registers and flags, then dumping all the registers and flags again, and finally the instructions that my hook overwrote in the original function.
The x64 code of my detour is below:
;dump registers
mov rax, 0x1C122560000
mov [rax], rcx
mov [rax+0x8], rdx
mov [rax+0x10], rbx
mov [rax+0x18], rdi
mov [rax+0x20], rsi
mov [rax+0x28], r8
mov [rax+0x30], r9
mov [rax+0x38], r10
mov [rax+0x40], r11
mov [rax+0x48], r12
mov [rax+0x50], r13
mov [rax+0x58], r14
mov [rax+0x60], r15
mov [rax+0x68], rsp
mov [rax+0x70], rbp
;dump flags
push rcx
pushfq
pop rcx
mov [rax+100], rcx
pop rcx
pushfq
push rcx
push rdx
push rbx
push rdi
push rsi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
;this is where my actual detour instructions would happen, but it is currently empty
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rsi
pop rdi
pop rbx
pop rdx
pop rcx
popfq
;dump registers
mov rax, 0x1C122560000
mov [rax+0x78], rcx
mov [rax+0x80], rdx
mov [rax+0x88], rbx
mov [rax+0x90], rdi
mov [rax+0x98], rsi
mov [rax+0xA0], r8
mov [rax+0xA8], r9
mov [rax+0xB0], r10
mov [rax+0xB8], r11
mov [rax+0xC0], r12
mov [rax+0xC8], r13
mov [rax+0xD0], r14
mov [rax+0xD8], r15
mov [rax+0xF0], rsp
mov [rax+0xF8], rbp
;dump flags
push rcx
pushfq
pop rcx
mov [rax+108], rcx
pop rcx
;original instructions (omitted)
...
...
...
ret
I am then reading the dumped registers from the address 0x1C122560000 with the corresponding offsets that each register was dumped with, and writing the results out. This result is shown below (suffix _1
marks value from the first dump, and _2
from the second dump):
rcx_1: 23E5A6FEE00
rdx_1: 0
rbx_1: 3FFFAB921FE0
rdi_1: 3FF636D38F00
rsi_1: 23E5A6FEE00
r8_1: 0
r9_1: 3FFFAB921FE0
r10_1: 2C7
r11_1: 9E057FFA78
r12_1: 1
r13_1: 0
r14_1: 0
r15_1: 24600000000
rsp_1: 24600000000
rbp_1: 9E00000000
flags_1: 0
rcx_2: 23E5A6FEE00
rdx_2: 0
rbx_2: 3FFFAB921FE0
rdi_2: 3FF636D38F00
rsi_2: 23E5A6FEE00
r8_2: 0
r9_2: 3FFFAB921FE0
r10_2: 2C7
r11_2: 9E057FFA78
r12_2: 1
r13_2: 0
r14_2: 0
r15_2: 0
rsp_2: 9E057FF750
rbp_2: 9E057FF860
flags_2: 0
I struggle to understand how the value of the registers rsp
, rbp
, and r15
are changing between the dumps, and the same "pattern" repeats every time the original function is called (all three registers change every time, every other register stays the same). To my understanding, the equal amount of pushes and pops should return the stack frame to point to the same address. Am I missing something very obvious about how these registers work? Is my approach to saving and restoring the original state of the hooked function by pushing and popping the registers flawed?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您正在覆盖R15(+96)和RSP(+104)的存储值,因为您在
mov [rax +100]中使用的偏移量,rcx
in DECIMAL中/strong>(+100)。同样的事情发生在
mov [Rax+108],RCX
中,更改RBP的存储值。解决方案使用预期的十六进制:
You are overwriting the stored values of R15 (at +96) and RSP (at +104), since the offset that you use in
mov [rax+100], rcx
is in decimal (+100).Same thing happens in
mov [rax+108], rcx
, changing the stored value of RBP.Solution use hexadecimal as was intended: