32位x86缓冲区溢出CTF挑战:绕过字符限制读取文件
缓冲区溢出绕过字符限制的技术提示
你的核心思路没问题:通过缓冲区溢出控制返回地址执行自定义代码是正确的利用路径,当前的卡点是绕过0x00、0x80、0x89、0xe1这些禁止字符(注意代码里的forbidden数组重复了0x89,实际禁止的是四个唯一值)。下面是具体的绕过方案:
核心绕过方向
1. 替换被禁的系统调用触发指令
Linux 32位环境中,除了int 0x80(Opcode含0x80被禁),还可以用sysenter指令(Opcode为0x0f 0x34)触发系统调用,这两个字节不在禁止列表内。需要注意sysenter的调用约定和int 0x80不同:
eax存储系统调用号edx存储返回地址ecx存储第一个参数- 后续参数按顺序压入栈中
你可以基于这个指令重新编写读取文件的shellcode,比如依次调用open->read->write系统调用,全程避免使用任何被禁字节。
2. 编码shellcode并在运行时解码
如果原始功能必须用到被禁字符,可先对shellcode进行编码(例如XOR、加法/减法编码),注入时只传入编码后的字节,在shellcode开头添加解码逻辑,将编码后的字节还原为可执行的原始shellcode。解码逻辑必须确保不含被禁字符:
- 示例XOR解码:选择一个不在禁止列表里的密钥(如0x11),对原始shellcode逐字节XOR;解码时用
lodsb(Opcode0xac)读取编码字节,xor al, 0x11还原,再用stosb(Opcode0xaa)写入目标地址,循环处理所有字节。 - 示例加法编码:将原始shellcode每个字节加0x01,解码时用
dec al(Opcode0x48)还原,同样避免被禁指令。
3. 构造ROP链替代shellcode
完全避免注入shellcode,利用程序或libc中的现有代码片段(gadgets)构造ROP链,调用libc函数实现读取文件:
- 第一步:利用程序中的
printf函数泄露libc基地址(例如打印puts的GOT表项),通过泄露的地址计算system函数和/bin/sh字符串的地址。 - 第二步:查找可用的gadgets(用
ROPgadget工具),比如pop ebx; ret、pop ecx; pop edx; ret等,确保这些gadget的指令字节不含被禁字符。 - 第三步:拼接ROP链:
pop ebx; ret+/bin/sh地址 +system地址,执行后即可触发shell,进而读取目标文件。
内容的提问来源于stack exchange,提问作者E Epsylon
相关产品推荐
相关产品推荐

