1

I'm reading Jon Erickson's art of exploitation and have a general idea about memory allocation on the stack. But the book is for 32 bit systems and I own a 64 bit system. I know that stack grows along lower memory addresses so if you initialize a certain variable var_one before var_two in a function, var_one in theory, should have a larger value of memory address than var_two. However, when I'm trying some of the exploitation techniques on my 64 bit system, its not quite making sense to me. In one of the programs I initialized an int type variable after I initialized a char buffer but still the int variable was at a higher memory address than the buffer. I tried 3 things:

int pass_check(char *password) {
    char pass_buffer[10];
    int auth = 0;
    strcpy(pass_buffer, password);

Once like the one shown above, once with auth variable initialized before pass_buffer (initialized first) and one auth variable initialized after the strcpy() line. When examining with gdb, I'm getting the same memory address of auth variable every time for each variation of the code. I'm sure I did not make any silly error, made 3 different binaries for the 3 variants, disabled ASLR and even disabled gcc code optimizer. So why am I getting a result like this?

Rachid K.
  • 4,490
  • 3
  • 11
  • 30

2 Answers2

4

The C compiler is not obligated to put variables in memory in the order that you initialized them in the function. In fact, it intentionally doesn't do so. A lot of modern compilers will actually put buffers after local variables when possible so that you can't overflow from a buffer into a local variable.

Aplet123
  • 33,825
  • 1
  • 29
  • 55
0

Concerning your comment:

I know that stack grows along lower memory addresses

Although most of the platforms have a stack growing downward, some platform do not. For example, the manual of clone() system call says that:

stacks grow downward on all processors that run Linux (except the HP PA processors)

So, for a maximum portability, it is not advised to make any assumption on the way the stack grows.

Concerning the order of the local variables, if you really need to have a deterministic order, an interesting comment on StackExchange says:

wrapping your local variables in a structure should be enough to prevent GCC reordering them.

#include <stdio.h>

struct local_vars{
  int var1;
  char buffer[40];
  int var2;
};

int main(void)
{
  struct local_vars locals;

  printf("@var1=%p, @buffer=%p, @var2=%p\n", &(locals.var1), &(locals.buffer), &(locals.var2));

}
$ gcc p.c -o p
$ ./p
@var1=0x7ffef59b23e0, @buffer=0x7ffef59b23e4, @var2=0x7ffef59b240c
Rachid K.
  • 4,490
  • 3
  • 11
  • 30
  • OP's actual problem is not about the direction the stack grows (since there are no independent growths at all in the program, only a single call frame) but about how the compiler lays out the call frame. But for what it's worth, in 2020 there are no remaining viable archs where stack grows upward. For the most part you can't observe the difference anyway without UB (exception: `uintptr_t` cast) though. – R.. GitHub STOP HELPING ICE Nov 14 '20 at 16:35
  • @R..GitHubSTOPHELPINGICE: In the question of the OP, there is a reference to the stack growing direction. That is why I spoke about it. But after, I speak about the way the locals are ordered... – Rachid K. Nov 14 '20 at 16:41