Analyse C-Programm - Vergleich mit Speicherstelle

Hallo,
ein einfaches Testprogramm in C für "Hallo Welt", enthält einen anderen Wert im EIP-Register als angegeben.
Das Testprogramm:

int main()
{
int i;
for(i=0;i<10;i++)
{
printf ("Hallo Welt!\n");
}
return 0;
}

Ich arbeite in einer virtuellen 32bit Maschine Ubuntu 15.04 und teste das.
Warum habe ich dann beim Debuggen mit gdb -q
einen anderen Wert als hier?
Eigentlich sollte der Wert 0x8048393 sein, ich habe aber 0x8048435 ?
Es ist doch dieselbe print-Anweisung?
 
Eigentlich sollte der Wert 0x8048393 sein, ich habe aber 0x8048435 ?

Ich bin mir ziemlich sicher, dass in deiner Lektüre zum EIP auf genau dieses Phänomen hingewiesen wird.
 
Deine Antwort verstehe ich nicht

Hallo,
tut mir leid, bei der Analyse deiner Antwort komme ich nicht voran. Kannst Du mir eine kleine Hilfestellung geben, wie ich das zu verstehen habe?
Ich habe nochmal geblättert, aber keinen Hinweis gefunden.
Das die Speicheradresse nicht stimmt, leuchtet mir ja ein. Die kann immer unterschiedlich sein.
Der Inhalt der Speicheradresse sollte aber bei der selben For-Schleife gleich sein. Zumindest der Zähler einer For-Schleife von 1 bis 10. Nur weil es ein anderer Computer ist, zählt er nicht einmal von 1-10 und ein anderes Mal von 23-33.
Oder was verstehe ich nicht?
 
Zuletzt bearbeitet:
Der Inhalt der Speicheradresse sollte aber bei der selben For-Schleife gleich sein. Zumindest der Zähler einer For-Schleife von 1 bis 10. Nur weil es ein anderer Computer ist, zählt er nicht einmal von 1-10 und ein anderes Mal von 23-33. Oder was verstehe ich nicht?


Deine Session sieht vermutlich ähnlich aus?

Code:
(gdb) list
1       #include <stdio.h>
2       
3       int main()
4       {
5       int i;
6       for(i=0;i<10;i++)
7       {
8       printf ("Hallo Welt!\n");
9       }
10      return 0;
(gdb) break 8
Breakpoint 1 at 0x96a: file test.c, line 8.
(gdb) run
Starting program: /root/test 
Breakpoint 1 at 0x1458c96a: file test.c, line 8.

Breakpoint 1, main () at test.c:8
8       printf ("Hallo Welt!\n");
(gdb) info register eip
eip            [B]0x1458c96a       [/B]0x1458c96a
(gdb) run              
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/test 
Breakpoint 1 at [B]0x1884c96a[/B]: file test.c, line 8.

Breakpoint 1, main () at test.c:8
8       printf ("Hallo Welt!\n");
(gdb) info register eip
eip            [B]0x1884c96a       [/B]0x1884c96a
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/test 
Breakpoint 1 at 0x1ac9b96a: file test.c, line 8.

Breakpoint 1, main () at test.c:8
8       printf ("Hallo Welt!\n");
(gdb) info register eip
eip            [B]0x1ac9b96a       [/B]0x1ac9b96a
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/test 
Breakpoint 1 at 0x1bb0c96a: file test.c, line 8.

Breakpoint 1, main () at test.c:8
8       printf ("Hallo Welt!\n");
(gdb) info register eip
eip            0x1bb0c96a       0x1bb0c96a
(gdb)

Wie sieht's denn mit ESP und EBP aus? ;)
 
Speicherinhalt analysiert

Hallo,
nun habe ich den Speicher zumindest soweit verstanden, dass ich die Stringausgabe von "Hello, world!" verstanden habe. Das ist vollständig klar.
Bis ich erstmal über so Kleinigkeiten gestolpert bin, dass Next i nicht der nächste Schleifendurchlauf ist, sondern next instruction bedeutet. ;-) (Anfänger halt!)

Was ich jedoch nach allem Speicherdurchsuchen noch nicht gefunden habe, ist die Speicherstelle, die die Zaehlervariable hochzählt. Irgendwo muss doch eine Speicherstelle sein, in der von 1 bis 10 gezählt werden.
Wenn ich weiterhin nexti wiederhole, komme ich wieder zur Zeile der For-Schleife.
Das heisst der Zähler muss inkrementiert werden. Wo sehe, an welcher Speicherstelle oder in welchen Zähler das geschieht?
Das suche ich gerade.

Besten Dank für die schnelle Rückmeldung, dass hat wieder motiviert weiter zu machen und nicht direkt nach dem Anfang, (aller Anfang ist schwer) sofort wieder aufzugeben.
 
Was ich jedoch nach allem Speicherdurchsuchen noch nicht gefunden habe, ist die Speicherstelle, die die Zaehlervariable hochzählt. Irgendwo muss doch eine Speicherstelle sein, in der von 1 bis 10 gezählt werden.

Die Speicherstelle ist die _Adresse_ der Variabe "i" und der Zählerstand ist ihr _Wert_.

Im Gegensatz zum EIP kannst du Speicheradressen von Variablen direkt aus dem Programm heraus ausgeben:
printf("%p\n", &i);

Bevor du mit dem Debugger anfängst solltest du dir erstmal ein paar Grundlagen von C draufschaffen. Stichwort Zeiger und Adressoperatoren. Dann wird dir da einiges von selber klar. Was Fragen zur Funktionsweise der Register angeht, so ist "smashing the stack" noch immer gut um reinzukommen.

Das heisst der Zähler muss inkrementiert werden. Wo sehe, an welcher Speicherstelle oder in welchen Zähler das geschieht? Das suche ich gerade.

Dafür musst du dir wohl den Assemblercode reinziehen ;)

Code:
# gcc -S -o test.s test.c 
# cat test.s                                                                                                                                                 
        .file   "test.c"
        .section        .rodata
.LC0:
        .string "Hallo Welt!"
        .text
        .globl  main
        .type   main, @function
main:
        leal    4(%esp), %ecx
        andl    $-16, %esp
        pushl   -4(%ecx)
        pushl   %ebp
        movl    %esp, %ebp
        pushl   %ebx
        pushl   %ecx
        subl    $32, %esp
        call    __i686.get_pc_thunk.bx
        addl    $_GLOBAL_OFFSET_TABLE_, %ebx
        movl    $0, -16(%ebp)
        jmp     .L2
.L3:
        leal    .LC0@GOTOFF(%ebx), %eax
        movl    %eax, (%esp)
        call    puts@PLT
        addl    $1, -16(%ebp)
.L2:
        cmpl    $9, -16(%ebp)
        jle     .L3
        movl    $0, %eax
        addl    $32, %esp
        popl    %ecx
        popl    %ebx
        popl    %ebp
        leal    -4(%ecx), %esp
        ret
        .size   main, .-main
        .section        .gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits
        .globl  __i686.get_pc_thunk.bx
        .hidden __i686.get_pc_thunk.bx
        .type   __i686.get_pc_thunk.bx, @function
__i686.get_pc_thunk.bx:
        movl    (%esp), %ebx
        ret
#

Aber ab hier muss dir jetzt jemand anderes weiterhelfen ;)
 
Zurück
Oben