Home > Enterprise >  Changing the sequence of memory variables doesn't change the memory layout of the stack
Changing the sequence of memory variables doesn't change the memory layout of the stack

Time:11-06

Here's a sequence:

 int auth_flag = 0;
 char password_buffer[16];

According to my understanding, these are local variables and are supposedly stored on the stack, which is a LIFO structure, grows upwards towards lower memory addresses(towards the heap) and variables are placed in reverse order on it. So password_buffer will go first and auth_flag will go next. I examined their memory addresses with gdb and here are the results:

Thread 1 hit Breakpoint 1, check_authentication (password=0xd01760 'A' <repeats 30 times>) at main.c:10
10          strcpy(password_buffer, password);
(gdb) x/s password_buffer
0x61fdd0:       "P\026@"
(gdb) p/d 0x61fdd0
$1 = 6421968
(gdb) x/s auth_flag
0x0:    <error: Cannot access memory at address 0x0>
(gdb) x/s &auth_flag
0x61fdec:       ""
(gdb) p/d 0x61fdec
$2 = 6421996
(gdb) print 0x61fdec - 0x61fdd0
$3 = 28

auth_flag is located 28 bytes past the start of password_buffer. This sequence places the auth_flag ahead of password_buffer and renders it vulnerable to an overflow(by which I mean overwriting the return address of auth_flag).

So far so good. I was able to overwrite the return address and got access.

Then I reversed the declarations, namely:

char password_buffer[16];
int auth_flag = 0;

Now, in theory the auth_flag should be placed before password_buffer leaving me unable to use the return address as a exploit. I checked the memory addresses and these were the results:

(gdb) x/s password_buffer
0x61fdd0:       "P\026@"
(gdb) p/d 0x61fdd0
$1 = 6421968
(gdb) x/s &auth_flag
0x61fdec:       ""
(gdb) p/d 0x61fdec
$2 = 6421996
(gdb) print 0x61fdec - 0x61fdd0
$5 = 28

The memory addresses were still the same and I was able to overwrite the return address and gained access anyhow. Am I missing something here? Could anyone explain why the memory addresses remained the same regardless of the fact that I changed the sequence?

CodePudding user response:

The compiler does not have to place variables in the memory in a particular order, it does not even have to put them there.

If you want to have data in a particular order and make sure that object will have memory representation you need to declare it as struct and use references to it. You can also use volatile or compiler-specific attributes or pragmas to disable possible optimizations.

int main(void)
{
    struct
    {
        char password_buffer[16];
        int auth_flag;
    }x;
    struct
    {
        int auth_flag;
        char password_buffer[16];
    }y;

    printf("x: %p %p\n", (void *)&x.password_buffer, (void *)&x.auth_flag);
    printf("x: %p %p\n", (void *)&y.password_buffer, (void *)&y.auth_flag);
}

CodePudding user response:

The stack is LIFO. The compiler does not necessarily put objects on the stack in the order they are declared. Modern compilers perform sophisticated processing. They may analyze an entire block of code or function or more before deciding where to put objects. Where objects are put may be influenced by their alignment requirements and sizes, by where the compiler happened to insert them into its internal database (e.g., ordered by name or hash result, as examples) during analysis, or other factors.

  • Related