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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 16:35:20