You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用bar()与bar(void)的安全威胁:构造攻击遇阻求助

利用bar()与bar(void)差异的攻击构造方案

你的代码失效原因

  1. 64位调用约定不压栈:64位系统默认用寄存器传递前6个参数,参数不会存入栈中,因此gdb info frame无法看到参数。
  2. 编译器优化把变量放寄存器:默认优化级别下,局部变量a会被分配到寄存器而非栈上,栈参数无法覆盖它。
  3. 传入的是字符串指针而非内容:你传入的字符串字面量,压栈的是它在数据段的地址,不是字符本身,无法达到覆盖栈变量的效果。
  4. 栈保护机制拦截溢出:编译器默认开启栈保护,在栈帧中插入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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 15:44:51