2012-03-30 17 views
2

Ich habe verschiedene Arten von Pufferüberlauf wurde die Überprüfung und lief in ein Problem kann ich mich nicht erinnern, warum es auftritt. Der Code ist wie folgt: das Programm, das ich versucht bin einen Pufferüberlauf führen an:Linux Pufferüberlauf Umgebungsvariablen

#include <stdio.h> 

void func(char *buff){ 
    char buffer[5]; 
    strcpy(buffer, buff); 
    printf("%s\n", buffer); 
} 

int main(int argc, char *argv[]){ 
    func(argv[1]); 
    printf("I'm done!\n"); 
    return 0; 
} 

Das Kernkonzept des Programms ist sehr einfach, ich überläuft gerade den Puffer, um die Absenderadresse von func() zu überschreiben. Das alles funktioniert gut, wenn ich ihm eine Adresse wie 0x0804850c gebe, die die <_fini> des Programms ist. Das Endergebnis, wenn ich den Überlauf mit dieser Adresse implementiere, ist das Programm beendet "würdevoll", ohne I'm done! zu drucken. Das Problem, auf das ich jetzt stoße, ist, wenn ich versuche, die Rückkehradresse zu etwas zu sagen, das eine Umgebungsvariable sagt, die bei 0xbfffd89 gelegen ist.

Der Code Shell in diesem speziellen Umgebungsvariable befindet sich einfach das Programm, nachdem sie gesagt hello beenden sollte. Das passiert jedoch nicht, das Programm segelt einfach Fehler und das war's. Es wurde bereits bestätigt, dass der Shell-Code in dem vorherigen Programm funktioniert, das ich zum Testen von Shell-Code geschrieben habe. Jeder hat irgendwelche Ideen, warum das nicht funktioniert. Thx

+1

Führen Sie es unter Gdb aus, um zu sehen, was den Segfault auslöst. Meine Vermutung: Die Umgebungsvariable lebt in einem Speicherbereich, der zwar lesbar aber nicht ausführbar [email protected] EugeneMayevski'EldoSCorp: Ich nehme an, dass "Shell-Code" hier Jargon für Maschinencode ist, der eine Shell und einige externe Befehle ausführt, was Exploits normalerweise tun wollen. Obwohl es in diesem Fall klingt, als ob keine tatsächliche Shell ausgeführt wird. – Celada

+0

@Celada Irgendwelche Vorschläge, wie ich mit GDB überprüfen kann, ob die Umgebungsvariablen READ-ONLY sind. Auch Sie haben den Shell-Code korrekt. – Blackninja543

+0

@ EugeneMayevski'EldoSCorp Shell-Code allgemein definiert ist der Byte-Code einer Binärdatei. In diesem Fall habe ich den Shell-Code erzeugt, indem ich geschrieben habe, was ich in x86 ASM raus wollte. Wenn ich die Rücksprungadresse der Funktion umadressiere, leite ich sie zu einem Bereich des Gedächtnisses, das eine neue Reihe Anweisungen enthält. – Blackninja543

Antwort

2

Umgebungsvariablen werden in einem Speicherbereich befindet, die & Schreibberechtigung gelesen hat aber keine Berechtigung ausführen. Ich wiedergegeben leicht dies wie folgt:

#include <stdio.h> 
#include <stdlib.h> 

int 
main(int argc, char **argv) 
{ 
void (*function)(void); 

     function = (void (*)(void))getenv("PATH"); 
     function(); 
     return 0; 
} 

unter gdb Rennen, habe ich dies:

Program received signal SIGSEGV, Segmentation fault. 
0x00007fffffffeb51 in ??() 
(gdb) 

ich dann 0x00007fffffffeb51 wenn /proc/PID/maps die Adresse nachgeschlagen und fand eine Zeile wie diese:

7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0       [stack] 

Es gibt eine wo das x (Ausführen) Bit normalerweise gefunden würde.

+0

OK also nehmen wir an, ich kann die Berechtigungen der Umgebungsvariablen nicht ändern, welche anderen Möglichkeiten gibt es für die Ausführung meines Shell-Codes außerhalb der Umgebungsvariablen. – Blackninja543

+1

Plausables Szenario für ein gefährliches Programm: Eine Umgebungsvariable wird in den Heap kopiert. Vielleicht benennt die Umgebungsvariable ein Verzeichnis und es wird mit einem Dateinamen verkettet, um einen vollständigen Pfadnamen in 'malloc()' ed Speicher zu bilden. Jetzt kann Ihr Pufferüberlauf zu dieser Adresse auf dem Heap springen. Es wird ausführbar sein. Aber du musst raten, was diese Heap-Adresse ist ... viel Glück damit :-) – Celada

0

Können Sie bestätigen die Adresse der Variablen zwischen den Läufen? Wenn Ihr System etwas wie ASLR verwendet, kann es bei jedem Lauf anders sein. Die Adresse des argv [1] kann jedoch über ein Register angegeben werden, wenn Sie also die Rücksprungadresse mit der Adresse der indirekten Anweisung über dieses Register angeben (Sie finden diese Anweisung wahrscheinlich unter Verwendung von objdump -d in Ihrem Programm), Es wird Ihren Code unter der Adresse ausführen, die er auch haben wird - vorausgesetzt, diese Adresse befindet sich auf der ausführbaren Seite. Und Register werden in Ihrem ABI verwendet, um Parameter zu übergeben. Es kann weitere Probleme jedoch sein ...

Wenn Sie weitere Informationen zur Verfügung stellen (möglicherweise, insluding Demontage des Programms), vielleicht könnte es speziell beantwortet werden.

+0

Ich werde den disassemblierten Code hinzufügen, wenn ich eine Chance bekomme. Soweit Adressraum Randomisierung, habe ich das in meiner Testumgebung ausgeschaltet. Wie Celada gezeigt hat und ich auf meine eigene Umgebung überprüft habe, sind meine Umgebungsvariablen nicht nicht ausführbar. Haben Sie irgendwelche Gedanken darüber, wie ich meinen Code-Shell-Code einfügen kann, um es ausführbar zu machen? Die einzige Möglichkeit, an die ich zu diesem Zeitpunkt denken kann, ist die Verwendung der Umgebungsvariablen. – Blackninja543

2

Moderne Linux-Distributionen sind gegen diese Art von Angriff gehärtet. Das NX-Bit ist beispielsweise für Stapelseiten auf x86-64 festgelegt. Und Mapping-Adressen sind randomisiert, um die Fähigkeit zu vermeiden, von außerhalb des Prozesses zu erraten. Siehe die folgenden:

http://en.wikipedia.org/wiki/Executable_space_protection http://en.wikipedia.org/wiki/Address_space_layout_randomization

Grundsätzlich, wenn Sie ein Exploit für ein modernes System schreiben wollen Sie gehen zu müssen, etwas mehr Arbeit zu tun.

+1

Korrigieren. Was in diesem speziellen Fall nicht offensichtlich ist, ist, dass Umgebungsvariablen sich tatsächlich in der gleichen Speicherzuordnungsregion wie der Stapel befinden. Das wusste ich bis jetzt nicht! – Celada

+0

@Celada: Tatsächlich werden alle von "argc", "argv", "envp" und "auxv" und die entsprechenden Zeiger auf sie zu jedem Prozess auf dem Stapel übertragen. – ninjalj

+0

@ninjalj Ich wusste, dass "argv", "envp" und "auxv" alle zusammen in einer Speicherregion waren, die als "Benutzerbereich" bekannt ist, aber ich wusste nicht, dass es der gleiche Bereich wie der Stapel war. Aber ich war auf Solaris zurück, als ich das vor einigen alarmierenden Zahlen erfuhr, und die Dinge könnten sich geändert haben. Danke für die Klarstellung! – Celada