简体   繁体   English

试图理解 rsp 和 rbp 寄存器的奇怪行为

[英]Trying to understand odd behavior of rsp and rbp registers

While playing around with detours I noticed this behavior that goes against my understanding of how registers rsp and rbp work.在玩弯路时,我注意到这种行为与我对寄存器 rsp 和 rbp 工作原理的理解背道而驰。 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.玩弄这个,我注意到rsprbp的值(奇怪的是r15 )在我绕道而行的过程中发生了变化,而我却没有碰它们。 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.进一步测试,我的绕道包括我首先将所有寄存器的值(除了rsprbprip )和标志顺序转储到特定地址,推送和弹出所有寄存器和标志,然后再次转储所有寄存器和标志,最后是我的钩子在原始函数中覆盖的指令。

The x64 code of my detour is below:我绕道的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

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.然后,我从地址 0x1C122560000 读取转储的寄存器以及每个寄存器转储的相应偏移量,并将结果写出。 This result is shown below (suffix _1 marks value from the first dump, and _2 from the second dump):此结果如下所示(后缀_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

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).我很难理解寄存器rsprbpr15的值在转储之间是如何变化的,并且每次调用原始函数时都会重复相同的“模式”(所有三个寄存器每次都变化,其他每个寄存器都保持不变)。 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?我通过推送和弹出寄存器来保存和恢复挂钩函数的原始状态的方法是否有缺陷?

mov [rax+0x60], r15 mov [rax+0x68], rsp
 mov [rax+100], rcx

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).您正在覆盖 R15(+96 处)和 RSP(+104 处)的存储值,因为您在mov [rax+100], rcx中使用的偏移量为十进制(+100)。

Same thing happens in mov [rax+108], rcx , changing the stored value of RBP.同样的事情发生在mov [rax+108], rcx中,改变了 RBP 的存储值。 Solution use hexadecimal as was intended:解决方案按预期使用十六进制:

mov [rax+0x100], rcx
...
mov [rax+0x108], rcx

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么 rbp 和 rsp 被称为通用寄存器? - Why are rbp and rsp called general purpose registers? 可以在64位Intel处理器中直接寻址寄存器RSI,RDI,RSP和RBP的低字节吗? - Can the lower byte of the registers RSI, RDI, RSP and RBP be directly addressed in the 64-bit Intel processors? 无意义地尝试在整个呼叫中比较rsp而不使用寄存器 - Pointlessly trying to compare rsp across a call without using registers 使用 gdb 理解堆栈帧和 rbp 和 rsp - Understanding stack frames and rbp and rsp with gdb 为什么 clang 的尾声使用 add $N, %rsp 而不是 mov %rbp, %rsp 来恢复 %rsp? - Why does clang's epilogue use `add $N, %rsp` instead of `mov %rbp, %rsp` to restore `%rsp`? 这个汇编函数prologue / epilogue代码用rbp / rsp / leave做什么? - What is this assembly function prologue / epilogue code doing with rbp / rsp / leave? 布局堆栈变量的意义比 rbp 更接近 rsp - Significance of laying out stack variables starting nearer rsp than rbp 试图在上下文中理解此指令。 段寄存器 - trying to understand this instruction in context w. Segment registers 为什么在这个函数序言中没有“sub rsp”指令,为什么函数参数存储在负 rbp 偏移量处? - Why is there no "sub rsp" instruction in this function prologue and why are function parameters stored at negative rbp offsets? 在x86程序集中分配堆栈上的变量。 rbp和rsp vs esp和ebp - Allocating variables on the stack in x86 assembly. rbp and rsp vs esp and ebp
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM