Python3 print()与Python2打印

7_R*_*R3X 11 python stdout bytestring

在处理缓冲区溢出攻击时,我发现了一些非常奇怪的东西.我已经成功地发现我需要提供32个字符,然后才能跳转到正确的地址,并且正确的地址是0x08048a37.当我执行

python -c "print '-'*32+'\x37\x8a\x04\x08'" | ./MyExecutable
Run Code Online (Sandbox Code Playgroud)

该漏洞利用取得了成功.但是,当我尝试时:

python3 -c "print('-'*32+'\x37\x8a\x04\x08')" | ./MyExecutable
Run Code Online (Sandbox Code Playgroud)

它没有.可执行文件只会导致分段错误,而不会跳转到所需的地址.实际上,执行

python -c "print '-'*32+'\x37\x8a\x04\x08'"
Run Code Online (Sandbox Code Playgroud)

python3 -c "print('-'*32+'\x37\x8a\x04\x08')" 
Run Code Online (Sandbox Code Playgroud)

在控制台上产生两个不同的输出.当然,这些角色不可读,但它们在视觉上是不同的.

我想知道为什么会这样?

Mar*_*ers 19

Python 2代码写入字节,Python 3代码写入文本,然后编码为字节.因此后者不会写相同的输出; 它取决于为管道配置的编解码器.

在Python 3中,将字节写入sys.stdout.buffer对象:

python3 -c "import sys; sys.stdout.buffer.write(b'-'*32+b'\x37\x8a\x04\x08')"
Run Code Online (Sandbox Code Playgroud)

您可能希望手动添加要添加的\n换行符print.

sys.stdout是一个io.TextIOBase对象,将写入其中的数据编码到给定的编解码器(通常基于您的语言环境,但在使用管道时,通常默认为ASCII),然后将其传递给底层缓冲区对象.该TextIOBase.buffer属性使您可以直接访问基础BufferedIOBase对象.