Ich laufe Linux auf i386: x86_64.Ich habe ein Stück c-Code geschrieben und ich habe es zerlegt sowie die Register gelesen, um zu verstehen, wie das Programm in Assembly funktioniert. Unten ist mein c Programm, das ich geschrieben habe.Warum hat diese Speicheradresse einen zufälligen Wert?
#include <unistd.h>
#include <string.h>
#include <stdio.h>
char *string_in = "Did not work";
int test(char *this){
char sum_buf[6];
strncpy(sum_buf,this,32);
return 0;
}
int hello(){
printf("hello man");
string_in = "If this triggered, it means our shell code is working\n";
while(1){
printf("Worked!");
}
return 0;
}
int main(int argc, void **argv){
test("\x28\x28\x28\x28\x28\x28\x28\x28\x28\x28\x28\x28\x28\x28\x28\x28\x28\x28\x28\x28\x28\x28\x28\x28\x06\x06\x40\x00\x00\x00\x00\x00");//6f 73
printf("My string is %s",string_in);
return 0;
}
Das Stück meines Codes, das ich untersucht habe, ist die Testfunktion. Wenn ich die Ausgabe meiner Testfunktion zerlegen ich ...
0x00000000004005b4 <+0>: push %rbp
0x00000000004005b5 <+1>: mov %rsp,%rbp
0x00000000004005b8 <+4>: sub $0x20,%rsp
0x00000000004005bc <+8>: mov %rdi,-0x18(%rbp)
0x00000000004005c0 <+12>: mov %fs:0x28,%rax
=> 0x00000000004005c9 <+21>: mov %rax,-0x8(%rbp)
0x00000000004005cd <+25>: xor %eax,%eax
0x00000000004005cf <+27>: mov -0x18(%rbp),%rcx
0x00000000004005d3 <+31>: lea -0x10(%rbp),%rax
0x00000000004005d7 <+35>: mov $0x20,%edx
0x00000000004005dc <+40>: mov %rcx,%rsi
0x00000000004005df <+43>: mov %rax,%rdi
0x00000000004005e2 <+46>: callq 0x400490 <[email protected]>
0x00000000004005e7 <+51>: mov $0x0,%eax
0x00000000004005ec <+56>: mov -0x8(%rbp),%rdx
0x00000000004005f0 <+60>: xor %fs:0x28,%rdx
0x00000000004005f9 <+69>: je 0x400600 <test+76>
0x00000000004005fb <+71>: callq 0x4004a0 <[email protected]>
0x0000000000400600 <+76>: leaveq
0x0000000000400601 <+77>: retq
Jetzt liegt mein Interesse an der Linie < 12>. Aus meinem Verständnis heraus erklärt dieser Befehl dem Computer, die ersten 28 Bits des Segmentregisters %fs
zu nehmen und in %rax
meinen Akkumulator zu legen. Was mich stört, ist, dass vor und nach der Ausführung dieser Zeile das Register %fs
über p/x $fs
gelesen wird, das einen Wert von Null (sogar während des gesamten Programms) anzeigt und somit %rax
Null sein muss. Jedoch zeigt %rax
keine Null nach der Ausführung der Anweisung. Tatsächlich ergibt sich eine Zufallszahl. Diese Zufallszahl wird dann 8 Bytes vor %rbp
platziert (da es Little Endian ist) und dann erneut überprüft, falls es einen Puffer über den Fluss gibt, der diesen Speicherplatz überschrieben hat.
Was ich gerne wissen würde ist, was mov %fs:0x28,%rax
wirklich macht. Habe ich es richtig verstanden? Warum lese ich Null für %fs
wenn in p/x $fs
und wie lese ich den richtigen Wert?
Ok, das macht Sinn. Wie kann ich diese Adresse und den Wert mit gdb lesen? –
Der einfachste Weg ist, den Inhalt des RAX-Registers direkt nach dem MOV-Vorgang zu betrachten. – Jason