Печать Python3() Vs Python2 print

Во время работы над эксплойтом переполнения буфера я нашел что-то действительно странное. Я успешно обнаружил, что мне нужно предоставить 32 символа перед правильным адресом, на который я хочу перейти, и что правильный адрес 0x08048a37. Когда я выполнил

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

эксплойт привел к успеху. Но когда я попытался:

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

это не так. Исполняемый файл просто привел к ошибке сегментации без перехода на нужный адрес. Фактически выполнение

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

и

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

выводит на консоль два разных выхода. Символы, конечно, не читаемы, но они визуально отличаются.

Интересно, почему это происходит?

Ответ 1

Код Python 2 записывает байты, код Python 3 записывает текст, который затем кодируется в байты. Таким образом, последний не будет писать тот же вывод; это зависит от кодека, настроенного для вашего канала.

В Python 3 вместо этого напишите байты в sys.stdout.buffer:

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

Вы можете вручную добавить новую строку \n, добавленную print.

sys.stdout представляет собой объект io.TextIOBase, данные кодирования, записанные на него, в данный кодек (обычно на основе вашего языка, но когда используя трубку, часто по умолчанию использующую ASCII), прежде чем передать ее базовому буферному объекту. Атрибут TextIOBase.buffer дает вам прямой доступ к базовому объекту BufferedIOBase.