为什么push指令会改变rsp的值呢?
Why does the push instruction change the value of rsp?
我正在检查 Ericksons Hacking 中的代码片段:剥削的艺术:
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。
我正在检查 Ericksons Hacking 中的代码片段:剥削的艺术:
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。