使用bar()与bar(void)的安全威胁:构造攻击遇阻求助
利用bar()与bar(void)差异的攻击构造方案
你的代码失效原因
- 64位调用约定不压栈:64位系统默认用寄存器传递前6个参数,参数不会存入栈中,因此
gdb info frame无法看到参数。 - 编译器优化把变量放寄存器:默认优化级别下,局部变量
a会被分配到寄存器而非栈上,栈参数无法覆盖它。 - 传入的是字符串指针而非内容:你传入的字符串字面量,压栈的是它在数据段的地址,不是字符本身,无法达到覆盖栈变量的效果。
- 栈保护机制拦截溢出:编译器默认开启栈保护,在栈帧中插入canary值,阻止非法覆盖操作。
成功构造攻击的步骤
1. 编译参数(必须配置)
用32位编译,关闭优化和栈保护:
gcc -m32 -O0 -fno-stack-protector attack.c -o attack
-m32:生成32位程序,采用cdecl调用约定,所有参数压栈。-O0:关闭所有优化,强制局部变量分配在栈上。-fno-stack-protector:关闭栈保护,允许栈溢出操作。
2. 攻击代码示例
#include <stdio.h> // K&R风格声明:编译器不检查调用时的参数数量和类型 void bar() { char buf[4]; // 4字节缓冲区,与局部变量a相邻 int a = 0x12345678; // 初始值,用于验证覆盖效果 printf("a的初始值: 0x%x\n", a); } int main() { // 传入8字节字符串,溢出buf覆盖相邻的a变量 bar("12345678"); return 0; }
3. 运行效果
执行程序后,a的初始值0x12345678会被覆盖为0x38373635(字符串"5678"的ASCII码,小端序存储)。
关键差异验证
如果把bar()改成bar(void),编译时会直接报错:
error: too many arguments to function ‘bar’
这就是bar()(允许任意参数)和bar(void)(严格无参数)的核心差异——前者能绕过编译器的参数检查,传入超长参数触发栈溢出,后者则会直接拦截非法调用。
内容的提问来源于stack exchange,提问作者sadcat_1
相关产品推荐
相关产品推荐

