PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Komisches Verhalten von ret



nimrod
05.03.2007, 17:16
Moin
beim Durcharbeiten von diesem (http://tty64.org/doc/smackthestack.txt) Paper bin ich auf folgendes gestoszen, was ich mir nicht erklaeren kann:

Ausgegangen wird von folgendem Programm:

/*
* vuln.c, Standard strcpy() buffer overflow within a function
*/

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

int foobar(int x, char *str) {
char buf[256];
strcpy(buf, str);
return x;
}

int main(int argc, char **argv) {
foobar(64, argv[1]);
return 1;
}

Uebersetzt habe ich es mit gcc-3.4.6 (std. Paket von Gentoo). Kernel ist 2.6.18 (Gentoo gepatcht) und mein Prozessor n amd athlon thunderbird c.

Meine gdb Session (auf das Wichtigste gekuerzt):

(bho@phuq:~/foobar)% gdb vuln2_1
GNU gdb 6.6
[...]
This GDB was configured as "i686-pc-linux-gnu"...
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) disas foobar
Dump of assembler code for function foobar:
0x08048394 <foobar+0>: push %ebp
[...]
0x080483b5 <foobar+33>: leave
0x080483b6 <foobar+34>: ret
End of assembler dump.
(gdb) b *foobar+34
Breakpoint 1 at 0x80483b6
(gdb) set args abc
(gdb) r
Starting program: /home/bho/vortex/vuln2_1 abc
Failed to read a valid object file image from memory.

Breakpoint 1, 0x080483b6 in foobar ()
(gdb) disas __do_global_ctors_aux
Dump of assembler code for function __do_global_ctors_aux:
0x08048480 <__do_global_ctors_aux+0>: push %ebp
[...]
0x080484a0 <__do_global_ctors_aux+32>: pop %ebx
0x080484a1 <__do_global_ctors_aux+33>: pop %ebp
0x080484a2 <__do_global_ctors_aux+34>: ret
0x080484a3 <__do_global_ctors_aux+35>: nop
End of assembler dump.
(gdb) x/a $esp
0xbfcc763c: 0x80483eb <main+52>
(gdb) set *0xbfcc763c = __do_global_ctors_aux+33
(gdb) x/a $esp+4
0xbfcc7640: 0x40
(gdb) x/a $esp+8
0xbfcc7644: 0xbfcc93dd
(gdb) nexti
0x080484a1 in __do_global_ctors_aux ()
(gdb) nexti
Cannot access memory at address 0x44
(gdb) print (void *)$ebp
$1 = (void *) 0x40
(gdb) print (void *)$esp
$2 = (void *) 0xbfcc7644


So, was passiert da?
Ich setz den Top of Stack auf die Adresse __do_global_ctors_aux+33.
ret holt sich die jetzt vom Stack und setzt %eip drauf. %esp ist jetzt also %esp+4. Soweit alles wie erwartet.
Das pop %ebp sorgt dafuer, dass %ebp = 0x40 ist.

Und dann wird's komisch. Wenn mich nicht alles taeuscht, sollte sich das ret jetzt ganz brav (%esp) vom Stack holen und da hin Springen (gut, da steht jetzt abc (argv[1]), aber es koennte der Shellcode sein..).
Stattdessen kommt der Fehler 'Cannot access memory at address 0x44', was ich mir nur so erklaeren kann, dass er versucht nach %ebp+4 zu springen, was natuerlich totaler Schwachsinn ist. Oder?

Ich geh mal davon aus, dass ich irgendwo nen boesen Denkfehler habe. Waer nett, wenn mich jemand in die richtige Richtung stoszen koennte ;)

Grusz Bho

ps: Ich war mir mit dem Forum nicht sicher. Wenns besser nach 'Systemnahe Programmierung' passt bitte verschieben.

pps: Uebersetzt habe ich das Programm mit 'gcc -o vuln vuln.c'. Die Binary habe ich angehaengt (die .txt Endung darf ignoriert werden ;))

nait
05.03.2007, 18:03
Hab ich was übersehen oder rufst du dein Programm nur mit 'abc' als Parameter auf? Das sollte eigentlich gar keine Probleme machen, da der lokale Buffer buf 256 Byte groß ist.

nimrod
05.03.2007, 18:36
Das Parameter ist nur da, weil es sonst n segfault gibt (strcpy).
Das was ich eigentlich mit nem zum langen Puffer machen wuerde, hab ich jetzt von Hand gemacht (set *0xbfcc763c = __do_global_ctors_aux+33).

EDIT:
Zur Verdeutlichung:

(gdb) x/a $esp
0xbfcc763c: 0x80483eb <main+52>
(gdb) set *0xbfcc763c = __do_global_ctors_aux+33
(gdb) x/a $esp
0xbfcc763c: 0x80484a1 <__do_global_ctors_aux+33>

nait
05.03.2007, 19:11
Mal 'ne ganz dumme Frage, hast du mal stepi statt nexti verwendet? Vielleicht meint der GDB, dass das ret sowas wie 'n Funktionsaufruf ist und lässt den Code einfach laufen. Das hätte zur Folge, dass er deine Text "abc\0" als Code interpretiert und daraus folgende Befehlsfolge macht:


61 POPAD
6263 00 BOUND ESP,QWORD PTR DS:[EBX]

Und das könnte den Crash erklären...

nimrod
05.03.2007, 19:23
nexti und stepi macht keinen Unterschied. Bis zum "abc\0" kommt er gar nicht. Das wuerde er versuchen als code zu interpretieren, wenn das ret in __do_global_ctors_aux mache wuerde, was ich von ihm erwarte.

Auszerdem:

(gdb) set args foobar
(gdb) r
[...]
Breakpoint 1, 0x080483b6 in foobar ()
(gdb) x/a $esp
0xbfd74eec: 0x80483eb <main+52>
(gdb) set *0xbfd74eec = __do_global_ctors_aux+33
(gdb) x/a $esp
0xbfd74eec: 0x80484a1 <__do_global_ctors_aux+33>
(gdb) stepi
0x080484a1 in __do_global_ctors_aux ()
(gdb) disas __do_global_ctors_aux
[...]
0x080484a1 <__do_global_ctors_aux+33>: pop %ebp
0x080484a2 <__do_global_ctors_aux+34>: ret
0x080484a3 <__do_global_ctors_aux+35>: nop
End of assembler dump.
(gdb) stepi
Cannot access memory at address 0x44
(gdb) print (void *)$eip
$1 = (void *) 0x80484a2

blue
05.03.2007, 20:41
Deine Vorgehensweise funktioniert bei mir tadellos.
Aber was ist mit deinem GDB los?

Failed to read a valid object file image from memory.

blue

nimrod
05.03.2007, 22:47
Aber was ist mit deinem GDB los?Die Fehlermeldung hab ich gepflegt ignoriert, da sie mir bisher keine Probleme bereitet hat. War wohl n Fehler. Mit nem aktuellen Kernel hat sich die jetzt in Luft aufgeloest (klick (https://launchpad.net/ubuntu/+source/linux-source-2.6.20/+bug/74691)).

Danach kam an bekannter Stelle die gleiche Fehlermeldung, nur dass er nun von 0x40 statt 0x44 spricht. Was die bezwecken soll weisz nicht, ich kann aber einfach drueber stepi'en. Gesprungen wird richtig und der Code im Buffer wird ausgefuehrt.

Ob das vorher auch schon so war und ich es einfach nur verpeilt hab, weisz ich nicht. Vielleicht teste ich das morgen nochmal mit dem alten Kernel. Jetzt hab ich Kopfschmerzen und geh zu Bett ;)

Danke an euch beide fuer die Hilfe.