Reputation: 41
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.
Upvotes: 2
Views: 325
Reputation: 41
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 :-)
Upvotes: 1
Reputation: 13690
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.
Upvotes: 1
Reputation: 901
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.
Upvotes: 0