Search code examples
cstack-overflow

Which return address am I corrupting?


I have a pretty simple program for learning stack overflow.

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv) {

  char buf[128];

  if(argc < 2) return 1;

  strcpy(buf, argv[1]);

  printf("Hello\n");

  return 0;
}

The strategy is to supply large string in argv[1] to overflow buf and overwrite the return address. But which return address? i thought it is the address saved before I entered strcpy, so when we return normally from strcpy, we will execute printf.

However, after I overflow the buffer with a shell code payload to change this return address to my shellcode. I see the printf is still executed. Even if I added a few more printf, they will all be executed. Apparently, the return address I change only affects the main function return, otherwise I should not even see the printfs being executed.

Why would this happen? Isn't that when I overrun the buffer to change the return address to my shellcode, the main program will jump to my shellcode directly without executing the next printf?


Solution

  • On your typical PC, the stack grows downward. That means the memory layout of the stack will look like this while calling strcpy:

    // ^^^ higher addresses ^^^
    [stuff]
    [return address of main]
    [buf[127]]
    [buf[126]]
    ...
    [buf[1]]
    [buf[0]]
    [argument 2 (pointer to argv[1])]
    [argument 1 (pointer to buf)]
    [return address of strcpy (points into main)]
    [local variables in strcpy]
    // vvv lower addresses vvv
    

    By overflowing buf (writing to buf[128], buf[129], etc.), you write over main's call frame (most importantly, main's return address). You can't affect strcpy's call frame because it lives before buf in memory.