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

Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top