The answer to your question about the fs segment appears to be the stack canary. I found a blog that seems to explain it pretty well, along with its comments:
http://xorl.wordpress.com/2010/10/14/linux-glibc-stack-canary-values/
Question
I have a C function written here ( It does have a buffer overflow vulnerability )
void func(char *str)
{
char buffer[12];
int a=9;
strcpy(buffer,str);
}
Its assembly in gdb translates to
|0x4005b4 <func> push %rbp
|0x4005b5 <func+1> mov %rsp,%rbp
|0x4005b8 <func+4> sub $0x40,%rsp
|0x4005bc <func+8> mov %rdi,-0x38(%rbp)
|0x4005c0 <func+12> mov %fs:0x28,%rax
|0x4005c9 <func+21> mov %rax,-0x8(%rbp)
|0x4005cd <func+25> xor %eax,%eax
|0x4005cf <func+27> movl $0x9,-0x24(%rbp)
|0x4005d6 <func+34> mov -0x38(%rbp),%rdx
|0x4005da <func+38> lea -0x20(%rbp),%rax
|0x4005de <func+42> mov %rdx,%rsi
|0x4005e1 <func+45> mov %rax,%rdi
|0x4005e4 <func+48> callq 0x400490 <strcpy@plt>
|0x4005e9 <func+53> mov -0x8(%rbp),%rax
|0x4005ed <func+57> xor %fs:0x28,%rax
|0x4005f6 <func+66> je 0x4005fd <func+73>
|0x4005f8 <func+68> callq 0x4004a0 <__stack_chk_fail@plt>
|0x4005fd <func+73> leaveq
|0x4005fe <func+74> retq
rdi
contains the address of the original character array passed to the function.
1.In func+8
, is moving this rdi value to -0x38(rbp) to save the value in local variable str of the function or does it have any other implications?
2.What does the instruction at func+8
accomplish? Is there anyway in gdb or in linux to view the contents of the fs segment
?
3.What do the instructions func+12
to func+25
do?
EDIT: I compiled this in gcc 4.6.3 with -O0
Solution
The answer to your question about the fs segment appears to be the stack canary. I found a blog that seems to explain it pretty well, along with its comments:
http://xorl.wordpress.com/2010/10/14/linux-glibc-stack-canary-values/
OTHER TIPS
func+8
is storing the parameter value in a temporary variable since %rdi
is going to get clobbered at func+45
. The compiler could have handled it differently but I guess that's what it chose for this situation.
I do not remember off hand how to inspect the contents of the fs
segment but I suspect it is reading some known canary value to put on the stack. I'm not exactly sure but func+12
to func+25
looks like it is setting up some stack protection given that the value is checked later and an error handler is called if it is not the same:
|0x4005e9 <func+53> mov -0x8(%rbp),%rax <-- loads the value on the stack
|0x4005ed <func+57> xor %fs:0x28,%rax <-- compare with original
|0x4005f6 <func+66> je 0x4005fd <func+73> <-- if they are different
|0x4005f8 <func+68> callq 0x4004a0 <__stack_chk_fail@plt> <-- call this
This just answers a small part of question #3 up there, but xor %eax %eax
clears eax.
I don't do much with x86, so I can't tell you exactly what the preamble is doing there, but objdump usually gives nicer disassembly than gdb:
$ objdump -dS func.o
Disassembly of section .text:
0000000000000000 <func>:
#include <string.h>
void func(char *str)
{
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 20 sub $0x20,%rsp
8: 48 89 7d e8 mov %rdi,-0x18(%rbp)
char buffer[12];
int a=9;
c: c7 45 fc 09 00 00 00 movl $0x9,-0x4(%rbp)
strcpy(buffer, str);
13: 48 8b 55 e8 mov -0x18(%rbp),%rdx
17: 48 8d 45 f0 lea -0x10(%rbp),%rax
1b: 48 89 d6 mov %rdx,%rsi
1e: 48 89 c7 mov %rax,%rdi
21: e8 00 00 00 00 callq 26 <func+0x26>
}
26: c9 leaveq
27: c3 retq
That should at least tell you what the compiler thinks it's doing.