2

To understand the stack frame concept, I wrote a little program for my own. First I will show you the code, a little sketch about it and then I will present my question:

So, the program:

int check_pw(char *password){
    int valid = 0;
    char buffer[10]; 

    strcpy(buffer, password);

    if(strcmp(buffer, "a") == 0){
       valid = 1;
    }

    return valid;
}

int main(int argc, char *argv[]){
   if(check_pw(argv[1])){
        printf("OK\n");
   }
   else{
        printf("Wrong password\n");
   }
}

I give the password as a command-line argument. And if it is equal to 'a', then it is ok. So, I think it is clear.

Now the sketch how the stack frame of the function check_pw must look like:

               -------------------------         LOW
               |    buffer             |
               -------------------------
               |    valid              |
               -------------------------
               |    old EBP            |
               -------------------------
               |      RET              |
               -------------------------
               |      password         |
               -------------------------        HIGH

Now, my question:

  • I assume that the sketch is correct. So, then the first local variable "valid" must get a higher memory address than the second variable "buffer", right?

  • But when I use gdb as debugger(I use Ubuntu Lucid Lynx), set my breakpoints at the right places and type the following: x/x &valid and x/x &buffer then I get the address 0xbffff388 for "valid" and 0xbffff38c for "buffer" So, it is obvious that "buffer" has a higher address, but why?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
user3097712
  • 1,565
  • 6
  • 27
  • 49
  • 4
    The compiler can lay out the locals in a stack frame however it wants. – Jeffrey Bosboom Feb 07 '15 at 19:01
  • 1
    possible duplicate of [Order of local variable allocation on the stack](http://stackoverflow.com/questions/1102049/order-of-local-variable-allocation-on-the-stack) -- there seem to be other similar questions in the related sidebar on the right – Jeffrey Bosboom Feb 07 '15 at 19:02
  • Could it be also a protection mechanism against a vulnerability like "buffer overflow" or something like that ? Because then I would not have the opportunity to overflow the "valid" - variable. – user3097712 Feb 07 '15 at 19:06
  • I'm afraid that which order these are located in doesn't affect the ability of someone to overflow them (dependent on your code and how they are populated, of course) – David Hoelzer Feb 07 '15 at 19:45
  • using the layout of the sketch, you could overflow the valid variable....and of course RET and so on...but whatever. I get my answers...a) order of local variables on the stack depends on compiler b) search stackoverflow for similar question – user3097712 Feb 07 '15 at 19:52
  • It makes no sense at all to talk about overflowing a single `int` in this manner. – Crowman Feb 07 '15 at 19:54
  • I aggree, of course not. It was only a question. – user3097712 Feb 07 '15 at 20:08
  • Don't forget that some systems (but probably not Ubuntu) have the stack growing upwards. At the very least, you should not assume that the stack grows downwards, though it is a very common arrangement. – Jonathan Leffler Feb 07 '15 at 21:50

1 Answers1

3

In order to protect against buffer overflows (like the one which could be exploited through your strcpy use, for instance), there's this technique which consists on writing a pre-defined value at the end of all arrays allocated on stack. When the function returns, the value (usually called canary) is verified and the program aborts if the value is changed.

The address where the program has to jump back to after the function finishes is pushed on the stack. A common attack is to override that value making the program execute code injected by the atacker. If there's a canary the compromised buffer and the pointer, the attacker would have to guess the canary value in order to gain control of the program execution.

You can learn more about it on wikipedia: http://en.wikipedia.org/wiki/Buffer_overflow_protection#A_canary_example

You can disable that on gcc. If you compile your code like so (let's say your program filename is login.c):

gcc -g -fno-stack-protector login.c

You will notice that the variables are no longer rearranged.

Rafael Almeida
  • 2,377
  • 3
  • 22
  • 32