c - 为什么 push 指令会改变 rsp 的值?
问题描述
我正在检查 Ericksons Hacking: The Art of Exploitation 中的这段代码片段:
void test_function(int a, int b, int c, int d) {
int flag;
char buffer[10];
flag = 31337;
buffer[0] = 'A';
}
int main() {
test_function(1, 2, 3, 4);
}
gcc -g stack_example.c
gdb -q ./a.out
gef➤list main
0x555555555192 <main+0> endbr64
0x555555555196 <main+4> push rbp
0x555555555197 <main+5> mov rbp, rsp
→ 0x55555555519a <main+8> mov ecx, 0x4
0x55555555519f <main+13> mov edx, 0x3
0x5555555551a4 <main+18> mov esi, 0x2
0x5555555551a9 <main+23> mov edi, 0x1
0x5555555551ae <main+28> call 0x555555555149 <test_function>
0x5555555551b3 <main+33> mov eax, 0x0
我在 main 和 test_function 处设置断点。当 break main 我得到以下输出:
gef➤ i r rsp rbp rip
rsp 0x7fffffffdfc8 0x7fffffffdfc8
rbp 0x0 0x0
rip 0x555555555192 0x555555555192 <main>
gef➤ x/8i $rip
0x555555555192 <main>: endbr64
0x555555555196 <main+4>: push rbp
0x555555555197 <main+5>: mov rbp,rsp
0x55555555519a <main+8>: mov ecx,0x4
0x55555555519f <main+13>: mov edx,0x3
0x5555555551a4 <main+18>: mov esi,0x2
0x5555555551a9 <main+23>: mov edi,0x1
0x5555555551ae <main+28>: call 0x555555555149 <test_function>
gef➤continue
现在,当我在 test_function 处中断时,寄存器包含:
gef➤ i r rsp rbp rip
**rsp 0x7fffffffdfc0 0x7fffffffdfc0**
**rbp 0x7fffffffdfc0 0x7fffffffdfc0**
rip 0x55555555519a 0x55555555519a <main+8>
我的问题是,为什么寄存器 rsp在这些指令之后会从0x7fffffffdfc8
变为?0x7fffffffdfc0
0x555555555196 <main+4> push rbp
0x555555555197 <main+5> mov rbp, rsp
解决方案
该指令push rbp
完成与 相同的操作sub rsp, 8; mov QWORD PTR[rsp], rbp;
。它首先将堆栈指针 ( rsp
) 向上移动 8 个字节(这是因为 x86-64 中寄存器的大小是 8 个字节,即 64 位),然后将寄存器的值移动到它指向的内存位置。因此,rsp
原来的 值0x7fffffffdfc8
变为0x7fffffffdfc0
,比以前小 8。
推荐阅读
- django - 文件:在 Django Rest Framework 中使用 Postman “上传有效图像”
- javascript - 在异步编程中停止 javascript 循环
- excel - 当它引用的工作表更新时,如何替换公式以保留在 vba 中的特定单元格上
- react-native - react-navigation v5(下一个):从不同父级的子屏幕导航到嵌套的子屏幕
- javascript - 如何通过 React JS 组件中的对象数组中的道具显示信息
- jquery - 需要帮助引导 3 按钮样式
- grails - 使用 Micronaut 声明式客户端从 Flowable 响应中获取标头
- swiftui - SwiftUI NavigationBarTitle 未更新
- javascript - jquery 元素可拖动但不可调整大小
- daemontools - 使用 envdir 设置运行进程中的环境变量