Печать 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
.