Komisiches ergebniss bei GDB?

Hallo,
ich versuche mit einem 3.2.0er Kernel und GCC 4.6.3 diesen code zu analysieren.
Code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>

void geheim (void) {
    printf ("GEHEIM !!!\n");
    exit (0);
}

void oeffentlich (char *args) {
    char    buff[12];
    memset (buff, 'B', sizeof (buff));

    strcpy (buff,args);
    printf ("\nbuff: [%s] (%p)(%d)\n\n", &buff, buff, sizeof (buff));
}


int main (int argc, char *argv []) {

    int uid;
    uid =getuid ();

    if (uid == 0)
        geheim ();

    if (argc > 1) {
        
        printf ("\n\n\n\n");
        printf ("geheim() --> (%p)\n",geheim);
        printf ("oeffentlich() --> (%p)\n",oeffentlich);

        oeffentlich (argv[1]);
        
        printf ("geheim() --> (%p)\n", geheim);
        printf ("oeffentlich() --Y (%p)\n", oeffentlich);

    } else    
        printf ("Kein Argument\n");
    return 0;
}



wenn ich die stack-protecion ausmache und stack-exec klappt das exploiten, aber darum geht es hier nicht mir geht es um die beiden D*Word's bei folgender ausgabe:

Break ans ende der Funktion oeffentlichsetzen (line 16)

disas main
Code:
0x08048516 <+0>:    push   %ebp
   0x08048517 <+1>:    mov    %esp,%ebp
   0x08048519 <+3>:    and    $0xfffffff0,%esp
   0x0804851c <+6>:    sub    $0x20,%esp
   0x0804851f <+9>:    call   0x8048390 <getuid@plt>
   0x08048524 <+14>:    mov    %eax,0x1c(%esp)
   0x08048528 <+18>:    cmpl   $0x0,0x1c(%esp)
   0x0804852d <+23>:    jne    0x8048534 <main+30>
   0x0804852f <+25>:    call   0x80484a4 <geheim>
   0x08048534 <+30>:    cmpl   $0x1,0x8(%ebp)
   0x08048538 <+34>:    jle    0x80485ac <main+150>
   0x0804853a <+36>:    movl   $0x80486b2,(%esp)
   0x08048541 <+43>:    call   0x80483b0 <puts@plt>
   0x08048546 <+48>:    mov    $0x80486b6,%eax
   0x0804854b <+53>:    movl   $0x80484a4,0x4(%esp)
   0x08048553 <+61>:    mov    %eax,(%esp)
   0x08048556 <+64>:    call   0x8048380 <printf@plt>
   0x0804855b <+69>:    mov    $0x80486c9,%eax
   0x08048560 <+74>:    movl   $0x80484c2,0x4(%esp)
   0x08048568 <+82>:    mov    %eax,(%esp)
   0x0804856b <+85>:    call   0x8048380 <printf@plt>
   0x08048570 <+90>:    mov    0xc(%ebp),%eax
   0x08048573 <+93>:    add    $0x4,%eax
   0x08048576 <+96>:    mov    (%eax),%eax
   0x08048578 <+98>:    mov    %eax,(%esp)
   0x0804857b <+101>:    call   0x80484c2 <oeffentlich>
   0x08048580 <+106>:    mov    $0x80486b6,%eax
   0x08048585 <+111>:    movl   $0x80484a4,0x4(%esp)
   0x0804858d <+119>:    mov    %eax,(%esp)
   0x08048590 <+122>:    call   0x8048380 <printf@plt>
   0x08048595 <+127>:    mov    $0x80486e1,%eax
   0x0804859a <+132>:    movl   $0x80484c2,0x4(%esp)
   0x080485a2 <+140>:    mov    %eax,(%esp)
   0x080485a5 <+143>:    call   0x8048380 <printf@plt>
   0x080485aa <+148>:    jmp    0x80485b8 <main+162>
   0x080485ac <+150>:    movl   $0x80486f9,(%esp)
   0x080485b3 <+157>:    call   0x80483b0 <puts@plt>
   0x080485b8 <+162>:    mov    $0x0,%eax
   0x080485bd <+167>:    leave  
   0x080485be <+168>:    ret

x/20x buff

Code:
0xbffff344:    0x42420041    0x42424242    0x42424242   [COLOR=Red] 0x080486b6[/COLOR]
0xbffff354:    [COLOR=Red]0x00131918[/COLOR]    0xbffff388    0x08048580    0xbffff5b0
0xbffff364:    0x080484c2    0x002d3ff4

um die zwei roten geht es das zweite könnte das Canary sein aber wo kommt es her?
Bei dem ersten wundert mich die ausgabe

x/s 0x080486b6
Code:
0x80486b6:     "geheim() --> (%p)\n"

vielleicht kann mir hier jemand helfen
 
Bei dem ersten wundert mich die ausgabe

x/s 0x080486b6
Code:
0x80486b6:     "geheim() --> (%p)\n"
vielleicht kann mir hier jemand helfen
=> überbleibsel auf dem Stack. Du nutzt ja schließlich nur 12 Chars und reserviert werden deutlich mehr (wegen aligning und weil der Compiler gerade so lustig ist ;) -> einfach mal gcc blub.c -S (oder disas oeffentlich in gdb) und anschauen, wieviel Stack tatsächlich in der "oeffentlich" reserviert wird. Ich garantiere Dir, dass es deutlich mehr als 12 Bytes sind. Memset setzt aber brav nur die 12.

Canary:
Linux/arch/x86/include/asm/stackprotector.h - Linux Cross Reference - Free Electrons (erstbeste Seite, ansonsten im eigenen Source schauen ;) )
Code:
#ifdef CONFIG_X86_32
        asm([I]"mov %0, %%[COLOR=black]gs[/COLOR]"[/I] : : [I]"r"[/I] ([URL="http://lxr.free-electrons.com/ident?i=__KERNEL_STACK_CANARY"]__KERNEL_STACK_CANARY[/URL]) : [I]"memory"[/I]);
#endif
Also Disassembly anschauen, irgendwo wird direkt nach der Stackinitialisierung sowas stehen:
Code:
    movl    %gs:20, %eax 
    movl    %eax, -4(%ebp)
 
Code:
 0x080484c2 <+0>:    push   %ebp
   0x080484c3 <+1>:    mov    %esp,%ebp
   0x080484c5 <+3>:    sub    $0x28,%esp
   0x080484c8 <+6>:    lea    -0x14(%ebp),%eax
   0x080484cb <+9>:    movl   $0x42424242,(%eax)
   0x080484d1 <+15>:    movl   $0x42424242,0x4(%eax)
   0x080484d8 <+22>:    movl   $0x42424242,0x8(%eax)
   0x080484df <+29>:    mov    0x8(%ebp),%eax
   0x080484e2 <+32>:    mov    %eax,0x4(%esp)
   0x080484e6 <+36>:    lea    -0x14(%ebp),%eax
   0x080484e9 <+39>:    mov    %eax,(%esp)
   0x080484ec <+42>:    call   0x80483a0 <strcpy@plt>
   0x080484f1 <+47>:    mov    $0x804869b,%eax
   0x080484f6 <+52>:    movl   $0xc,0xc(%esp)
   0x080484fe <+60>:    lea    -0x14(%ebp),%edx
   0x08048501 <+63>:    mov    %edx,0x8(%esp)
   0x08048505 <+67>:    lea    -0x14(%ebp),%edx
   0x08048508 <+70>:    mov    %edx,0x4(%esp)
   0x0804850c <+74>:    mov    %eax,(%esp)
   0x0804850f <+77>:    call   0x8048380 <printf@plt>
=> 0x08048514 <+82>:    leave  
   0x08048515 <+83>:    ret


hmm verstehen tue ich es trozdem nicht, wieso sollte da n überbleibsel drin bleiben, da der SFP auf 0xbffff358 und der RIP auf 0xbffff362 liegt?? Dann auf 0xbffff344 mein buff und dazwischen der müll sein soll?
aligning is einfach nur padding?
wie kann ich das rausfinden?

0x080484c5 <+3>: sub $0x28,%esp
28?
weil 12 buff + 8 Padding + 4SFP +4 RIP ????

kann ich das padding ausschalten? von dem canary hab ich nix gesehen in dem asm code,hatte es ja auch ausgeschaltet
 
Zuletzt bearbeitet:
hmm verstehen tue ich es trozdem nicht, wieso sollte da n überbleibsel drin bleiben, da der SFP auf 0xbffff358 und der RIP auf 0xbffff362 liegt?? Dann auf 0xbffff344 mein buff und dazwischen der müll sein soll?
Vorheriges
Code:
printf ("oeffentlich() --> (%p)\n",oeffentlich);
legt ja auch die Parameter auf dem Stack ab.
der Funktionsaufruf legt RetAddr auf den Stack und weiter wird der Code der Funktion ausgefürht, schaut dann in etwa so aus:
Code:
100 Ret Addr
96  SFP
... blub
...
...
20 buffer_start
d.h alles was zwischen dem Ende des Buffers und SFP (bzw. was die Funktion in den Stack bei der Initialisierung sonst noch schreibt) ist uninitialisiert.

aligning is einfach nur padding?
Jep. Könnte man auch so nennen - der Sinn ist dabei, dass die Variablen eben an "runden" Adressen liegen.


von dem canary hab ich nix gesehen in dem asm code,hatte es ja auch ausgeschaltet
sorry, hatte es aus dem Kontext so interpretiert, dass zwar ohne Stackprotection ausprobiert wurde, aber dann wieder "default" kompilieroptienen angegeben wurden.

Padding ausschalten:k.a. Es gibt zwar -fpack-struct, aber das hat keinen Einfluss auf Bufferpadding, -mpreferred-stack-boundary=2 wäre auch eine Option [flame]Es ist nun mal ein Märchen, dass man bei C wirklich die totale Kontrolle hat ;) [/flame]
 
Das Canary hab ich endlich gefunden wenn ich richtig compilen tue.
Ich verstehe es langsam schon ein bisschen mehr.

Also sollte eine off by one methode nicht funktionieren oder besser nur mit glück wenn der compiler willig ist.
Das dachte ich mir eig. schon die ganze zeit wollt nur den beweis im gdb finden.
Wenn ich weitere fragen hab weis ich ja nu wo ich jemand finde.

thx

EDIT

deine compiler option -mpreferred-stack-boundary=2 hat es echt gemacht

Code:
0xbffff368:	0x42420041	0x42424242	0x42424242	0xbffff388
0xbffff378:	0x0804857b	0xbffff5af	0x080484c2	0x000003e8
 
Zuletzt bearbeitet:
Ich verstehe es langsam schon ein bisschen mehr.
Du kannst gerne weitere Fragen stellen - nur möglichst detailiert, weil man sonst raten müsste, welchen Kontext Du meinst und was unklar ist ;)
Bei spezifischen Code bzw. Assemblyfrage ist eine komplette bof.s Disassembly nicht schlecht, da sowas sehr compilerversionsabhängig ist und man nicht unbedingt für eine Frage extra Installation machen möchte ;)

Also sollte eine off by one methode nicht funktionieren oder besser nur mit glück wenn der compiler willig ist.
off by one ist imho einer der häufigsten Fehler schlechthin :rolleyes:
Oder auch allgemein Zugriff auf +1 Element
 
Wieder ne Frage hehe...

Code:
 0x08048404 <+0>:    push   %ebp
   0x08048405 <+1>:    mov    %esp,%ebp
   0x08048407 <+3>:    sub    $0x1000,%esp
   0x0804840d <+9>:    movl   $0x0,-0x4(%ebp)
   0x08048414 <+16>:    jmp    0x804842e <funktion+42>
=> 0x08048416 <+18>:    mov    -0x4(%ebp),%eax
   0x08048419 <+21>:    add    0x8(%ebp),%eax
   0x0804841c <+24>:    movzbl (%eax),%edx
   0x0804841f <+27>:    lea    -0x104(%ebp),%eax
   0x08048425 <+33>:    add    -0x4(%ebp),%eax
   0x08048428 <+36>:    mov    %dl,(%eax)
   0x0804842a <+38>:    addl   $0x1,-0x4(%ebp)
   0x0804842e <+42>:    cmpl   $0x100,-0x4(%ebp)
   0x08048435 <+49>:    jle    0x8048416 <funktion+18>
   0x08048437 <+51>:    leave  
   0x08048438 <+52>:    ret

Code:
static void funktion (char *args) {
4        char    buff[256];
5        int   i;
7        for (i = 0;i <= 256; i++)
8            buff[i] = args[i];
9    
10    }

Code:
(gdb) x/70x buff
0xbfffdef4:    0x00000041    0x00000000    0x00000000    0x00000000
0xbfffdf04:    0x00000000    0x00000000    0x00000000    0x00000000
0xbfffdf14:    0x00000000    0x00000000    0x00000000    0x00000000
0xbfffdf24:    0x00000000    0x00000000    0x00000000    0x00000000
0xbfffdf34:    0x00000000    0x00000000    0x00000000    0x00000000
0xbfffdf44:    0x00000000    0x00000000    0x00000000    0x00000000
0xbfffdf54:    0x00000000    0x00000000    0x00000000    0x00000000
0xbfffdf64:    0x00000000    0x00000000    0x00000000    0x00000000
0xbfffdf74:    0x00000000    0x00000000    0x00000000    0x00000000
0xbfffdf84:    0x00000000    0x00000000    0x00000000    0x00000000
0xbfffdf94:    0x00000000    0x00000000    0x00000000    0x00000000
0xbfffdfa4:    0x00000000    0x00000000    0x00000000    0x00000000
0xbfffdfb4:    0x00000000    0x00000000    0x00000000    0x00000000
0xbfffdfc4:    0x00000000    0x00000000    0x00000000    0x00000000
0xbfffdfd4:    0x00000000    0x00000000    0x00000000    0x00000000
0xbfffdfe4:    0x00000000    0x00000000    0x00000000    0x00000000
0xbfffdff4:    0x00000001    0xbffff278    0x08048476    0xbffff4a4
0xbfffe004:    0x00000000    0x00000000

so das ist nach dem ertsen schleifendurchlauf zu sehen an 0xbfffdff4.
Laut meinen Tut sollte i da gar nicht sein, jetzt verstehe ich aber nicht warum das in dem tut so ist?
Wenn ich buff und i in der zeile drehe sollte sie ja eigentlicht vor buff sein, es ändert sich aber nichts.

natürlich setz ich ein static int i davor geht es dann kommt sie ja in den .bss speicher.
 
Zurück
Oben