Я пытался решить pwnable с Python 3. Для этого мне нужно напечатать некоторые символы, которые не находятся в диапазоне ASCII.
Python 3 превращает эти символы в какой-то странный Unicode.
Например, если я печатаю "xff"
в Python 3, я получаю это:
root@kali:~# python3 -c 'print("xff")' | xxd
00000000: c3bf 0a ...
xff
преобразуется в xc3xbf
Но в Python 2 все работает как положено, вот так:
root@kali:~# python -c 'print("xff")' | xxd
00000000: ff0a ..
Так как же это напечатать в Python 3?
Всего 2 ответа
В Python 2 print 'xff'
записывает строку байтов непосредственно в терминал, поэтому вы получаете печатаемый байт.
В Python 3 print('xff')
кодирует символ Unicode U + 00FF для терминала, используя кодировку по умолчанию ... в вашем случае UTF-8.
Чтобы напрямую выводить байты на терминал в Python 3, вы не можете использовать print
, но вы можете использовать следующее, чтобы пропустить кодирование и написать строку байтов:
python3 -c "import sys; sys.stdout.buffer.write(b'xff')"
В Python 2 str
и bytes
были одним и тем же, поэтому когда вы написали 'xff'
, результат содержал реальный байт 0xFF
.
В Python 3 str
ближе к unicode
объекту Python 2 и не является псевдонимом для bytes
. xff
больше не является запросом на вставку байта, а скорее является запросом на вставку символа Unicode, код которого может быть представлен в 8 битах. Строка печатается с вашей кодировкой по умолчанию (возможно, UTF-8), в которой символ 0xFF кодируется как байты xc3xbf
. x
- это в основном однобайтовая версия u
когда она появляется в строке. Это все то же самое, что и раньше, когда оно появляется в bytes
.
Теперь для решения. Если вы просто хотите несколько байтов, сделайте
b'xff'
Это будет работать так же, как в Python 2. Вы можете записать эти байты в двоичный файл, но затем не сможете печатать напрямую, поскольку все, что вы печатаете, конвертируется в str
. Проблема печати заключается в том, что все кодируется в текстовом режиме. К счастью, sys.stdout
имеет атрибут buffer
который позволяет вам выводить bytes
напрямую:
sys.stdout.buffer.write(b'xff
')
Это будет работать, только если вы не замените sys.stdout
чем-то необычным, у которого нет buffer
.