2017-10-22 11 views
11

Während ich an einem Pufferüberlauf-Exploit arbeitete, fand ich etwas wirklich seltsames. Ich habe erfolgreich gefunden, dass ich 32 Zeichen vor der richtigen Adresse bereitstellen muss, zu der ich springen möchte und dass die richtige Adresse 0x08048a37 ist. Wenn ich ausgeführtPython3 print() Vs Python2 print

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

die Exploit führte zu einem Erfolg. Aber, als ich versuchte:

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

es tat es nicht. Die ausführbare Datei führte einfach zu einer Segmentierungsfehler, ohne zu der gewünschten Adresse zu springen. In der Tat, die Ausführung

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

und

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

Ergebnisse in zwei unterschiedlichen Ausgängen auf der Konsole. Die Charaktere sind natürlich nicht lesbar, aber sie sind visuell unterschiedlich.

Ich frage mich, warum passiert das?

Antwort

19

Der Python 2-Code schreibt Bytes, der Python 3 Code schreibt Text, die dann an Bytes codiert ist. Letzteres wird also nicht die gleiche Ausgabe schreiben; Es hängt von dem für Ihre Pipe konfigurierten Codec ab.

In Python 3, schreiben Bytes an den sys.stdout.buffer Objekt statt:

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

Sie können das \n Newline manuell hinzufügen, dass print hinzufügen würde.

sys.stdout ist ein io.TextIOBase object, codieren Daten in einen bestimmten Codec geschrieben (in der Regel basierend auf Ihrem Gebietsschema, aber bei Verwendung einer Pipe, oft Standard auf ASCII), bevor es an das zugrunde liegende Pufferobjekt übergeben. Die TextIOBase.buffer attribute gibt Ihnen direkten Zugriff auf die zugrunde liegende BufferedIOBase object.