Python中传递含0x87的Shellcode payload至CTF程序的问题
Pwnable.tw "start"挑战:正确传递含不可打印字符的Payload
我在完成pwnable.tw平台上的入门CTF挑战——"start"挑战时,逆向分析二进制文件后发现存在缓冲区溢出漏洞。为了泄露栈地址,需要将返回地址覆盖为特定地址0x08048087,为此构造了如下Payload代码:
from pwn import * shellcode = b'A' * 20 shellcode += pack(0x08048087, 32) print(shellcode)
我原本计划将输出通过管道作为标准输入传入漏洞程序,但print输出的是字节字面量:
b'AAAAAAAAAAAAAAAAAAAA\x87\x80\x04\x08'
这种输出无法被程序按预期解析。尝试将其解码为UTF-8、ASCII字符串或直接用str转换时,还出现了以下错误:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x87 in position 20: invalid start byte
由于0x87字节没有对应可解码字符,我需要知道如何正确传递该Shellcode(尤其是十六进制地址部分),让程序将溢出缓冲区的该部分解析为预期地址,而非错误的字符串化十六进制值。
解决方案
问题核心在于print()函数会将字节对象转换为字符串表示,而非直接输出原始二进制字节。以下两种方法可以解决这个问题:
方法1:直接写入二进制标准输出
使用sys.stdout.buffer.write()直接向标准输出写入原始字节流,绕过Python的字符串处理逻辑:
from pwn import * import sys shellcode = b'A' * 20 shellcode += pack(0x08048087, 32) sys.stdout.buffer.write(shellcode)
方法2:使用pwntools直接与程序交互(推荐)
CTF场景下更常用的方式是用pwntools的process模块直接和目标程序建立管道,通过send()方法发送字节流,完全不需要处理编码问题:
from pwn import * # 替换为你的目标程序路径 p = process('./start') shellcode = b'A' * 20 shellcode += pack(0x08048087, 32) p.send(shellcode) # 进入交互模式接收程序输出 p.interactive()
原因说明
print()处理字节对象时,会调用其__repr__()方法,输出的是字节对象的字符串表示形式(包含b''包裹和转义字符),而非你需要的原始二进制字节,导致目标程序收到错误的数据。sys.stdout.buffer.write()直接操作二进制标准输出流,将原始字节写入stdout,管道另一端的程序能直接读取到正确的二进制数据。- pwntools的
process模块专为二进制程序交互设计,send()方法直接发送字节流,是CTF中处理此类问题的标准方式。
内容的提问来源于stack exchange,提问作者leatherprofitable
相关产品推荐
相关产品推荐

