Den Stapel example3.c durcheinander bringen

9

Artikel kann hier gefunden werden.

Ich lese gerade den Stack auf und habe festgestellt, dass ich auf example3.c stecken bleibe.

%Vor%

Der Autor gibt an, dass wir von 0x80004a8 nach 0x80004b2 überspringen wollen und dass dieser Sprung 8 Bytes ist; Wie hat der Autor festgestellt, dass dies 8 Bytes ist? Ich habe den Code neu erstellt und über objdump gesendet und festgestellt, dass es keine 8 Bytes sind (ich bin auf einer 64-Bit-Maschine, aber ich habe dafür gesorgt, dass ich mit 32 Bit kompiliere):

%Vor%

Der Autor sagte auch " Wie konnten wir wissen, dass wir 8 zur Absenderadresse hinzufügen mussten? Wir haben a Testwert zuerst (z. B. 1) "Wo hat er diesen Testwert bei verwendet?

    
user1529891 22.10.2012, 06:25
quelle

3 Antworten

-1

Nach viel Zeit und Nachdenken habe ich das Problem endlich gelöst. Die Ressource, die mir geholfen hat, dies zu lösen, ist Stack smashing code funktioniert nicht auf Linux Kernel 2.6.38.7 ... Bitte helfen Sie

Die größte Änderung, die mir dabei geholfen hat, war die Verwendung von disassembly-flavor intel für gdb .

Zerlegter Code (als Referenz):

%Vor%

Es gab zwei Probleme mit meinem Verständnis:

A) Mein erstes Problem bestand darin, die Anzahl der Bytes zu finden, die ret in function überlaufen sollte. Nochmal; Ich tat dies, indem ich die Intel-Syntax für die Disassemblierung verwendete und folgendes fand:

Um ret auf den korrekten Speicherplatz im Speicher zu setzen, muss ret beim Aufruf der Funktion auf EIP gesetzt werden. Der Adressraum bei 8048412 verschiebt den Stapel 0x9 nach unten. Weil dies 32-Bit-Code ist; Um zu ret zu kommen, fügen wir dann ein zusätzliches 0x4 bytes für die Wortgröße hinzu. Um zu ret zu gelangen, bedeutet das, dass ret auf 0x9 + 0x4 gesetzt ist, was 13 in Dezimal ist.

Dies löst das erste Problem von ret .

B) Das zweite Problem besteht darin, den Speicherplatz 0x8048457 zu überspringen. Dies geschieht durch Hinzufügen von 7 Bytes zu (*ret) , wodurch das Programm übersprungen und ausgeführt wird bei 0x804845e , was 00 ( NUL ) ist. Das ist einfach ineffizient; Also habe ich das zusätzliche Byte hinzugefügt und 8 Bytes im Stapel ausgeführt. Daraus ergibt sich x = 0 ;

Ich fand die genaue Anzahl der Bytes 8 ( c7 44 24 1c 01 00 00 ist 7 Bytes) und 00 ist ein Byte. Das hat mein letztes Problem gelöst.

Mein modifizierter C-Code:

%Vor%     
user1529891 23.10.2012, 05:25
quelle
3

So interpretiere ich den Artikel nicht. So wie ich es verstehe, möchte er die Rückgabeadresse so ändern, dass die x = 1; -Zuweisung übersprungen wird, d. H. Er möchte, dass function dorthin zurückkehrt, wo die printf ausgeführt würde.

Wie Sie in Ihrer Disassemblierung sehen können, ist die Zuweisung 8 Byte ( c7 44 24 1c 01 00 00 00 ). Wenn Sie also die Rücksprungadresse um 8 Byte vorwärts bewegen, wird sie an dieser Anweisung vorbeibewegt. Wie für den "Wir haben einen Testwert zuerst" Kommentar .. vielleicht bedeutet er nur, dass er auf den Code in einem Disassembler sah, um herauszufinden, die Länge, oder dass er mit verschiedenen Offsets (?) Experimentiert.

    
Michael 22.10.2012 08:24
quelle
1

Die Verschiebung in dem Artikel ist falsch, es sollte 10 bytes sein. Wenn eine Funktion aufgerufen wird (oder ein Sprung ausgeführt wird), wird die Rücksprungadresse gleich dem Befehlszeiger + der aktuellen Befehlsgröße gesetzt:

%Vor%

Wenn also der Aufruf der Funktion zurückkehrt, sollte der Befehlszeiger gleich 0x80004a8 ( 0x80004a3 + die Größe der Aufrufanweisung) sein:

%Vor%

Wenn Sie den Anweisungszeiger jedoch stattdessen auf 0x80004b2 setzen möchten, um die Zuweisung zu überspringen, müssen Sie zwangsläufig auch eine andere Anweisung (addl (0x80004b2-0x80004a8)xc,%esp) überspringen, um dorthin zu gelangen oder in andere Wörter müssen Sie addl bytes oder 10 Bytes zum Anweisungszeiger hinzufügen, um diese beiden Anweisungen zu überspringen:

%Vor%

Die tatsächliche Befehlsgröße hängt von den Operanden, dem Maschinentyp usw. ab. In diesem Beispiel ist movl jedoch 3 Byte lang und %code% ist 7 Byte lang. Sie können die Referenz zum x86-Befehlssatz auf die genaue Befehlsgröße überprüfen, oder Sie könnten kompilieren und disassemblieren Sie diesen Code, Sie werden sehen, dass diese beiden Anweisungen 10 Bytes lang sind:

%Vor%

gdb:

%Vor%

Es gibt auch eine Diskussion hier und hier zu genau demselben Thema in Beispiel 3.

    
iabdalkader 22.10.2012 09:59
quelle