Buffer Overflow攻击无法覆盖EIP问题求助
Buffer Overflow无法覆盖EIP寄存器的问题排查
问题现象
复现Buffer Overflow攻击时,无论输入多大Payload,程序崩溃时EIP始终停留在0x080491ac,未被预期的0x41414141覆盖。
使用代码
#include <stdio.h> #include <string.h> int main(int argc, char** argv){ char buffer[10]; strcpy(buffer, argv[1]); return 0; }
编译命令
gcc -o example2 -fno-stack-protector -no-pie -m32 -g -z execstack example2.c -w
GDB调试信息
断点在strcpy处的状态
Breakpoint 2, 0x08049196 in main (argc=2, argv=0xffffd434) at example.c:6 6 strcpy(buffer, argv[1]); (gdb) info reg eax 0x804bff4 134529012 ecx 0xffffd380 -11392 edx 0xffffd356 -11434 ebx 0x804bff4 134529012 esp 0xffffd340 0xffffd340 ebp 0xffffd368 0xffffd368 esi 0xffffd440 -11200 edi 0xf7ffcb60 -134231200 eip 0x8049196 0x8049196 <main+48> eflags 0x296 [ PF AF SF IF ] cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x0 0 gs 0x63 99 (gdb) x/20x $esp 0xffffd340: 0xffffd356 0xffffd676 0x00000000 0x0804917d 0xffffd350: 0xffffffff 0xf7d833d4 0xf7fc1380 0x00000000 0xffffd360: 0xffffd380 0xf7f95e2c 0x00000000 0xf7d96af9 0xffffd370: 0x00000000 0x00000000 0x080482e7 0xf7d96af9 0xffffd380: 0x00000002 0xffffd434 0xffffd440 0xffffd3a0
继续运行后的崩溃前状态
(gdb) c Continuing. Breakpoint 1, main ( argc=<error reading variable: Cannot access memory at address 0x41414141>, argv=<error reading variable: Cannot access memory at address 0x41414145>) at example.c:9 9 } (gdb) x/20x $esp 0xffffd350: 0xffffffff 0x414133d4 0x41414141 0x41414141 0xffffd360: 0x41414141 0x41414141 0x41414141 0x41414141 0xffffd370: 0x41414141 0x41414141 0x41414141 0x41414141 0xffffd380: 0x41414141 0x41414141 0x41414141 0x41414141 0xffffd390: 0x41414141 0x41414141 0x41414141 0xffff0041 (gdb) info reg eax 0x0 0 ecx 0x41414141 1094795585 edx 0xffffd390 -11376 ebx 0x41414141 1094795585 esp 0x4141413d 0x4141413d ebp 0x41414141 0x41414141 esi 0xffffd440 -11200 edi 0xf7ffcb60 -134231200 eip 0x80491ac 0x80491ac <main+70> eflags 0x10286 [ PF SF IF RF ] cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x0 0 gs 0x63 99
崩溃报错信息
Program received signal SIGSEGV, Segmentation fault. 0x080491ac in main ( argc=<error reading variable: Cannot access memory at address 0x41414141>, argv=<error reading variable: Cannot access memory at address 0x41414145>) at example.c:9 9 }
原因分析
从调试信息可以看出:
ebp已被覆盖为0x41414141,说明栈确实被溢出,但程序在执行到ret指令(加载返回地址到EIP)前就崩溃了。- 崩溃发生在
main函数的结尾(0x080491ac对应汇编指令leave,即mov esp, ebp; pop ebp):- 当执行
mov esp, ebp时,esp被设置为非法地址0x41414141,后续访问栈内存时触发SIGSEGV,导致程序提前崩溃,EIP还未执行到ret指令去读取被覆盖的返回地址。
- 当执行
- GDB读取被覆盖为
0x41414141的argc变量时,也会触发内存访问错误,但这不是导致EIP未被覆盖的核心原因。
解决步骤
计算准确偏移量:
在GDB中执行p &buffer获取buffer的起始地址,计算ebp - &buffer得到buffer到ebp的偏移量,再加上4字节(ebp到返回地址的距离),就是覆盖返回地址所需的总填充长度。
示例:若&buffer = 0xffffd35e,ebp = 0xffffd368,则偏移量为0xa(10字节),覆盖返回地址需要10 + 4 = 14字节的填充,之后再加上4字节的目标EIP值。调整Payload内容:
避免将ebp覆盖为非法地址,可暂时将ebp设置为原栈地址(如调试时的0xffffd368),确保leave指令能正常执行,直到ret指令加载返回地址到EIP。
示例Payload:python -c 'print("A"*10 + "\x68\xd3\xff\xff" + "\x41\x41\x41\x41")'(10字节填充+原ebp地址+目标EIP)关闭GDB的变量自动读取:
GDB在断点处自动读取argc/argv变量会触发提前崩溃,可通过set print elements 0或禁用变量自动显示来避免,但这只是辅助手段,核心还是调整Payload偏移。
内容的提问来源于stack exchange,提问作者r3k0j
相关产品推荐
相关产品推荐

