Quick Notes: Printing in Python3

Author: Jake Backer

Python3 has some quirks that can make binary exploitation more difficult.

Issue: ``print()` isn’t printing out the correct characters

If print is printing out characters with \x, this is a problem with the way the python3 print function works.

>>> a = "\xaa\xbb\x90\xff"
>>> a
'ª»\x90ÿ'
>  python -c "print('\xaa\xbb\x90\xff')"|xxd
00000000: c2aa c2bb c290 c3bf 0a                   .........
> python2.7 -c "print('\xaa\xbb\x90\xff')"|xxd
00000000: aabb 90ff 0a

By default, print tries to print the characters as UTF-8, but some characters like \x90 do not have valid UTF-8 characters. There’s a few ways to work around this.

  • Using sys.stdout.buffer.write() (you have to import sys first!). Instead of a string, this function takes a bytes-like object.
  • Specify the encoding as “latin-1” (ISO 8859-1).
>>> import sys b = b'\xaa\xbb\x90\xff' sys.stdout.buffer.write(b)
    4 
> python -c "import sys;sys.stdout.buffer.write(b'\xaa\xbb\x90\xff')" | xxd
00000000: aabb 90ff 

IssueL My pwntools code works in python2 but not python3

Many of the pwntools functions return bytes-like objects in python3. They work closer to an array of bytes rather than a string. The main differences is that you cannot concatenate bytes and strings. (Note: In python2, bytes and str are aliases for the same type. In python3, they are separate!)

>>> from pwn import *
>>> "A"*10 + p64(0xdeadbeef)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "bytes") to str
>>> b"A"*10 + p64(0xdeadbeef)
b'AAAAAAAAAA\xef\xbe\xad\xde\x00\x00\x00\x00'

Issue: All \x00 bytes are removed from my string

The codecs library seems to remove these bytes. Try manipulating your string without the codecs library. This can also happen when using bash command substitution (backtick notation) sometimes (specifically when using command substitution in radare2)