user177772
user177772

Reputation: 19

Modify the return address of a C function with buffer overflow vulnerability

I am trying to modify the following C program so that the main function will skip the printf("x is 1") line and only print "x is 0".

 void func(char *str) {
         char buffer[24];
         int *ret;

         ret = buffer + 28; // Supposed to set ret to the return address of func
         (*ret) += 32; // Add the offset needed so that func will skip over printf("x is 1")
         strcpy(buffer, str);
 }

 int main(int argc, char **argv) {
         int x;
         x = 0;
         func(argv[1]);
         x = 1;
         printf("x is 1");
         printf("x is 0");
         getchar();
 }

As the comments imply, the ret pointer needs to first be set to the return address of the function. I then need to add on an offset that will push it over the line I want to skip. I am running this code on a Linux system with 2 x Intel(R) Xeon(TM) CPU 3.20GHz. I am using gcc version 4.7.2 (Debian 4.7.2-5) to compile. I'm also trying to use example3.c from this (http://insecure.org/stf/smashstack.html) link for reference. Here is a disassembly of the main function using gdb:

 Dump of assembler code for function main:
    0x0000000000400641 <+0>:     push   %rbp
    0x0000000000400642 <+1>:     mov    %rsp,%rbp
    0x0000000000400645 <+4>:     sub    $0x20,%rsp
    0x0000000000400649 <+8>:     mov    %edi,-0x14(%rbp)
    0x000000000040064c <+11>:    mov    %rsi,-0x20(%rbp)
    0x0000000000400650 <+15>:    movl   $0x0,-0x4(%rbp)
    0x0000000000400657 <+22>:    mov    -0x20(%rbp),%rax
    0x000000000040065b <+26>:    add    $0x8,%rax
    0x000000000040065f <+30>:    mov    (%rax),%rax
    0x0000000000400662 <+33>:    mov    %rax,%rdi
    0x0000000000400665 <+36>:    callq  0x4005ac <func>
    0x000000000040066a <+41>:    movl   $0x1,-0x4(%rbp)
    0x0000000000400671 <+48>:    mov    $0x40075b,%edi
    0x0000000000400676 <+53>:    mov    $0x0,%eax
    0x000000000040067b <+58>:    callq  0x400470 <printf@plt>
    0x0000000000400680 <+63>:    mov    $0x400762,%edi
    0x0000000000400685 <+68>:    mov    $0x0,%eax
    0x000000000040068a <+73>:    callq  0x400470 <printf@plt>
    0x000000000040068f <+78>:    callq  0x400490 <getchar@plt>
    0x0000000000400694 <+83>:    leaveq
    0x0000000000400695 <+84>:    retq
 End of assembler dump.

Using what I've read from the example, my buffer is 24 bytes long and I should add an extra 4 bytes for the SFP size. This would mean I add 28 bytes to get to the return address of <+41>. It then looks like I want to jump to the last printf call at <+73>. This should be an offset of 32. However, when I execute the code, "x is 1" is still printed. I can't seem to find out why. Is there something wrong with my math or assumptions?

Upvotes: 1

Views: 118

Answers (1)

Gwyn Evans
Gwyn Evans

Reputation: 1521

This looks to be an ideal time to get experience with gdb and verify that your expectations regarding the stack and the function return address locations are correct!

I will, however suggest that your modified return address should probably be at <+63>, not <+73>, as you need to run the function setup code (to pass the argument, etc).

Upvotes: 0

Related Questions