7_R3X
7_R3X

Reputation: 4370

Python3 print() Vs Python2 print

While working on a buffer overflow exploit I found something really strange. I have successfully found that I need to provide 32 characters before the proper address I want to jump to and that the proper address is 0x08048a37. When I executed

python -c "print '-'*32+'\x37\x8a\x04\x08'" | ./MyExecutable

the exploit resulted in a success. But, when I tried:

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

it didn't. The executable simply resulted in a Segmentation Fault without jumping to the desired address. In fact, executing

python -c "print '-'*32+'\x37\x8a\x04\x08'"

and

python3 -c "print('-'*32+'\x37\x8a\x04\x08')" 

results in two different output on the console. The characters are, of course, not readable but they're visually different.

I wonder why is this happening?

Upvotes: 12

Views: 2437

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1122022

The Python 2 code writes bytes, the Python 3 code writes text that is then encoded to bytes. The latter will thus not write the same output; it depends on the codec configured for your pipe.

In Python 3, write bytes to the sys.stdout.buffer object instead:

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

You may want to manually add the \n newline that print would add.

sys.stdout is a io.TextIOBase object, encoding data written to it to a given codec (usually based on your locale, but when using a pipe, often defaulting to ASCII), before passing it on to the underlying buffer object. The TextIOBase.buffer attribute gives you direct access to the underlying BufferedIOBase object.

Upvotes: 20

Related Questions