Frage zu Bufferoverflow
-
Hallo ich hab ein einfach kleines Programm in C geschrieben welches für einen Buffer Overflow anfällig ist.
Das verwundbare Programm:
char name[10]; = 10 Hex = 16 Dezimal
int ret; = 4 Byte
20 Byte = Buffer Overflow
Ein Exploit dafür habe ich auch schon und es funktioniert ohne Probleme.
Nur ein verstehe ich nicht ganz wieso 20 Bytes ?
Muss ich nicht eigentlich nur den Puffer überschreiben ( char name[10]; )
Wieso muss ich noch 4 Bytes dazu rechnen damit der return Befehl der Funktion überschrieben wird ?
Hat da wer zufällig Ahnung von ?
Mein erklärung dafür:
LEA EAX,DWORD PTR SS:[EBP-10] <-- 16 Byte Puffer hier in der Funktion
CMP DWORD PTR SS:[EBP-4],0EBP - 16 Byte
EBP - 4 Byte
------------
20 ByteMit dieser Theorie hat es auch funktioniert wenn in der Funktion
z.b. so etwas standint ret;
int var;
char name[10];Also das vor dem Puffer nochmal 2 andere Variablen sind aber wieso müssen die auch überschrieben werden ?
#include <stdio.h> #include <string.h> int funktion(void) { int ret; char name[10]; printf("Name: "); fflush(stdout); gets(name); ret = strcmp(name, "abc"); if (ret == 0) { printf("ok message aus funktion\n"); return 1; } if (ret != 0) { printf("err message aus funktion\n"); // diese message wird bei dem buffer overflow exploit immer ausgeführt return 0; } } int main(int argc, char *argv[]) { int var; var = funktion(); if (var == 1) { printf("OK Message aus Hauptprogramm\n"); getch(); return 0; } printf("error Message aus Hauptprogramm\n"); getch(); return 0; }
So siehts im Olly Debugger aus:
00401210 funktion /$ 55 PUSH EBP 00401211 |. 8BEC MOV EBP,ESP 00401213 |. 83C4 F0 ADD ESP,-10 00401216 |. 68 A4B04000 PUSH vul.0040B0A4 ; /format = "Name: " 0040121B |. E8 243B0000 CALL vul.___org_printf ; \___org_printf 00401220 |. 59 POP ECX ; kernel32.7C817067 00401221 |. 68 90BC4000 PUSH vul.0040BC90 ; /stream = vul.0040BC90 00401226 |. E8 FD320000 CALL vul.___org_fflush ; \___org_fflush 0040122B |. 59 POP ECX ; kernel32.7C817067 0040122C |. 8D45 F0 LEA EAX,DWORD PTR SS:[EBP-10] 0040122F |. 50 PUSH EAX ; /s = NULL 00401230 |. E8 CF340000 CALL vul.___org_gets ; \___org_gets 00401235 |. 59 POP ECX ; kernel32.7C817067 00401236 |. 68 ABB04000 PUSH vul.0040B0AB ; /s2 = "abc" 0040123B |. 8D55 F0 LEA EDX,DWORD PTR SS:[EBP-10] ; | 0040123E |. 52 PUSH EDX ; |s1 = "Ã\xA4$" 0040123F |. E8 381C0000 CALL vul.___org_strcmp ; \___org_strcmp 00401244 |. 83C4 08 ADD ESP,8 00401247 |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX 0040124A |. 837D FC 00 CMP DWORD PTR SS:[EBP-4],0 0040124E |. 75 12 JNZ SHORT vul.00401262 00401250 |. 68 AFB04000 PUSH vul.0040B0AF ; /format = "ok message aus funktion\n" 00401255 |. E8 EA3A0000 CALL vul.___org_printf ; \___org_printf 0040125A |. 59 POP ECX ; kernel32.7C817067 0040125B |. B8 01000000 MOV EAX,1 00401260 |. EB 13 JMP SHORT vul.00401275 00401262 |> 837D FC 00 CMP DWORD PTR SS:[EBP-4],0 00401266 |. 74 0D JE SHORT vul.00401275 00401268 |. 68 C8B04000 PUSH vul.0040B0C8 ; /format = "err message aus funktion\n" 0040126D |. E8 D23A0000 CALL vul.___org_printf ; \___org_printf 00401272 |. 59 POP ECX ; kernel32.7C817067 00401273 |. 33C0 XOR EAX,EAX 00401275 |> 8BE5 MOV ESP,EBP 00401277 |. 5D POP EBP ; kernel32.7C817067 00401278 \. C3 RETN 00401279 main /. 55 PUSH EBP 0040127A |. 8BEC MOV EBP,ESP 0040127C |. 51 PUSH ECX 0040127D |. E8 8EFFFFFF CALL vul.funktion ; [vul.funktion 00401282 |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX 00401285 |. 837D FC 01 CMP DWORD PTR SS:[EBP-4],1 00401289 |. 75 15 JNZ SHORT vul.004012A0 0040128B |. 68 E2B04000 PUSH vul.0040B0E2 ; /format = "OK Message aus Hauptprogramm\n" 00401290 |. E8 AF3A0000 CALL vul.___org_printf ; \___org_printf 00401295 |. 59 POP ECX ; kernel32.7C817067 00401296 |. E8 8D190000 CALL vul.getch 0040129B |. 33C0 XOR EAX,EAX 0040129D |. 59 POP ECX ; kernel32.7C817067 0040129E |. 5D POP EBP ; kernel32.7C817067 0040129F |. C3 RETN 004012A0 |> 68 00B14000 PUSH vul.0040B100 ; /format = "error Message aus Hauptprogramm\n" 004012A5 |. E8 9A3A0000 CALL vul.___org_printf ; \___org_printf 004012AA |. 59 POP ECX ; kernel32.7C817067 004012AB |. E8 78190000 CALL vul.getch 004012B0 |. 33C0 XOR EAX,EAX 004012B2 |. 59 POP ECX ; kernel32.7C817067 004012B3 |. 5D POP EBP ; kernel32.7C817067 004012B4 \. C3 RETN
Hier mal die Funktion als Screenshot:
-
Oops ich hab da überall geschrieben Buffer Overflow aber das ist ja ein Stack Overflow sry mein Fehler. -.-
-
buf schrieb:
Wieso muss ich noch 4 Bytes dazu rechnen damit der return Befehl der Funktion überschrieben wird ?
Der alte stack frame des callers (EBP) wird unmittelbar nach dem Eintritt in die Funktion auf den Stack abgelegt (push ebp). Du musst also 16+4 Bytes überschreiben - weiter 4 Byte (insgesamt 24) überschreiben dann die Rücksprungaddr.
-
PUSB EBP ; <-- ESP - 4 Byte ok das hab ich verstanden
Aber dann kommt ja noch meine Variable int ret;
und deswegen dann nochmal - 4 Byte oder?
Also 16 + PUSH EBP (4 byte) + int ret; (4 byte) = 24 byte
So wäre es ja eine erklärung.
Aber die Frage ist ja warum muss ich die variable int ret; auch mit überschreiben ?
-
nun, die Variablen werden alle auf dem Stack angelegt. Dies geschieht in einem Schritt – "sub esp,x" oder "add esp,-(x)" oder "lea esp,[esp-x]".
x ist hierbei die Gesamtgröße aller Variablen. Wie viel Bytes du überschreiben musst, um an die Rücksprungaddr. zu gelangen,
hängt allerdings davon ab, wo der Buffer in Bereich x angesiedelt ist: [EBP-x+y]. In der Regel (sollte man sich aber nicht drauf verlassen da compiler abhänig) geht das nach der Reihenfolge in der sie deklariert sind: Der untersten Deklaration wird in der Regel auch die niedrigste Addr. zu gewiesen (y=0).
-
grad erst gesehen:
buf schrieb:
Also 16 + PUSH EBP (4 byte) + int ret; (4 byte) = 24 byte
so überschreibst du nur den stack frame des callers - 4 weitere bytes überschreiben die Rücksprungaddr.
-
char name[10]; // = 10 Hex = 16 Dezimal
sind 10 dez und 0x0A hex
ganz interessant:
http://controllingtheinter.net/BOFMSCPP.php
-
Ty das sieht ganz interssant aus ich werds mir mal durchlesen.