Declared variables stack

2019-07-15 14:07发布

问题:

I have 2 files name auth_overflow & auth_overflow2, the only difference is the sequence of the variable declaration. My question is, does declaration sequence affect their stack sequence according to FILO (first in last out)?

auth_overflow

bash-4.2$ gdb -q auth_overflow
Reading symbols from /home/reader/hacking/auth_overflow...done.
(gdb) list
5       int check_authetication (char *password) {
6               int auth_flag = 0;
7               char password_buffer[16];
8
9               strcpy(password_buffer, password);

(gdb) break 9
Breakpoint 1 at 0x804850d: file auth_overflow.c, line 9.
(gdb) run AAAAAAAAAAAA
Starting program: /home/reader/hacking/auth_overflow AAAAAAAAAAAA

Breakpoint 1, check_authetication (password=0xbffff7f3 'A' <repeats 12 times>) at auth_overflow.c:9
9               strcpy(password_buffer, password);
(gdb) x/x password_buffer
0xbffff52c:     0x08048330
(gdb) x/x &auth_flag
0xbffff53c:     0x00000000

auth_overflow2

bash-4.2$ gdb -q auth_overflow2
Reading symbols from /home/reader/hacking/auth_overflow2...done.
(gdb) list
5       int check_authetication (char *password) {
6               char password_buffer[16];
7               int auth_flag = 0;
8
9               strcpy(password_buffer, password);

(gdb) break 9
Breakpoint 1 at 0x804850d: file auth_overflow2.c, line 9.
(gdb) run AAAAAAAAAAAA
Starting program: /home/reader/hacking/auth_overflow2 AAAAAAAAAAAA

Breakpoint 1, check_authetication (password=0xbffff7f2 'A' <repeats 12 times>) at auth_overflow2.c:9
9               strcpy(password_buffer, password);
(gdb) x/x password_buffer
0xbffff52c:     0x08048330
(gdb) x/x &auth_flag
0xbffff53c:     0x00000000

Normal output:

(gdb) x/x password_buffer
0xbffff52c:     0x08048330
(gdb) x/x &auth_flag
0xbffff53c:     0x00000000

Expected output after variable swapped:

(gdb) x/x password_buffer
0xbffff53c:     0x08048330
(gdb) x/x &auth_flag
0xbffff52c:     0x00000000

I swapped between line 6 & 7 and I expect their corresponding addresses to be swapped too. Instead, their addresses remain the same despite the swap. Is there any explanation for this? Thank you.

回答1:

The order of the variable declaration is irrelevant since it's only a declaration.

When you define the variable as local variables (on the stack) the compiler can allocate any appropriate place on the stack, align the variables and "reorders" them. It's not really a reorder, since only the compiler chooses the order.

Example:

int foo(void)
{
    int a;
    int b;

    return a + b;
}

int bar(void)
{
    int b;
    int a;

    return a + b;
}

will be compiled by the GCC to this assembler code: [gcc -S --verbose-asm foo.c]

        .text
        .align  2
        .global foo
        .type   foo, %function
foo:
        @ Function supports interworking.
        @ args = 0, pretend = 0, frame = 8
        @ frame_needed = 1, uses_anonymous_args = 0
        @ link register save eliminated.
        str     fp, [sp, #-4]!  @,
        add     fp, sp, #0      @,,
        sub     sp, sp, #12     @,,
        ldr     r2, [fp, #-8]   @ tmp136, a
        ldr     r3, [fp, #-12]  @ tmp137, b
        rsb     r3, r3, r2      @ D.4069, tmp137, tmp136
        mov     r0, r3  @, <retval>
        add     sp, fp, #0      @,,
        ldmfd   sp!, {fp}
        bx      lr
        .size   foo, .-foo
        .align  2
        .global bar
        .type   bar, %function
bar:
        @ Function supports interworking.
        @ args = 0, pretend = 0, frame = 8
        @ frame_needed = 1, uses_anonymous_args = 0
        @ link register save eliminated.
        str     fp, [sp, #-4]!  @,
        add     fp, sp, #0      @,,
        sub     sp, sp, #12     @,,
        ldr     r2, [fp, #-8]   @ tmp136, a
        ldr     r3, [fp, #-12]  @ tmp137, b
        rsb     r3, r3, r2      @ D.4067, tmp137, tmp136
        mov     r0, r3  @, <retval>
        add     sp, fp, #0      @,,
        ldmfd   sp!, {fp}
        bx      lr
        .size   bar, .-bar

As you can see the variable a is always at the same address [fp-8]. My observation for GCC is that the variables are sorted alphabetically.



回答2:

According to the assembly output by @harper the compiler can freely reorder the stack of variables therefore in this case it's always char array before int variable. This makes the program vulnerable for stack-based buffer overflow.

In order to change the following:

(gdb) x/x password_buffer
0xbffff52c:     0x08048330
(gdb) x/x &auth_flag
0xbffff53c:     0x00000000

Into expected output as below:

(gdb) x/x password_buffer
0xbffff53c:     0x08048330
(gdb) x/x &auth_flag
0xbffff52c:     0x00000000

We simply add a -fstack-protector-all argument during compilation and the result will be as expected. To be vice-versa, perhaps you can use -O0 or -fno-stack-protector.

Thank you @harper and @tesseract for your contribution :-)



回答3:

on a 32bit machine the order of declaration affects where its placed in memory, not sure exactly how a 64bit machine handles it, but from memory it pushed variables into registers and then to the stack.

lets assume u use a 32bit machine in that case the memory locations must be swapped, are you sure you compiled your code after swapping?.

auth_overflow seems correct, auth_overflow2 should give the expected output in your question, not sure why this may be. the only reason I can think of is try recompile the code.