Reputation: 954
I'm trying to make buffer overflow and here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int check_authentication(char *password) {
char password_buffer[16];
int auth_flag = 0;
strcpy(password_buffer, password);
if(strcmp(password_buffer, "brillig") == 0)
auth_flag = 1;
if(strcmp(password_buffer, "outgrabe") == 0)
auth_flag = 1;
return auth_flag;
}
int main(int argc, char *argv[]) {
if(argc < 2) {
printf("Usage: %s <password>\n", argv[0]);
exit(0);
}
if(check_authentication(argv[1])) {
printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
printf(" Access Granted.\n");
printf("-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
}
else {
printf("\nAccess Denied.\n");
}
}
The provided password from command line will be compared to "brilling" and "outgrabe" if user input matches any of these, access will be granted, if not it will be denied. As I know if provided password will be greater than 16 return address will be overwritten but when I input "A" 17 it is not overwritten. Instead of that auth_flag is overwritten and is 65(0x41 in hex which is A). I can't figure out why the variable is overwritten instead of return address. I'm compiling with this
gcc -fno-stack-protector -z execstack -g -o test test.c
Hope you guys can help. Thanks.
Upvotes: 4
Views: 886
Reputation: 2576
As Sourav Ghosh said, your program invokes undefined behavior.
In practice, this means you need to dive into the generated code to see how the stack is used.
As this relies heavily on your environment (machine, OS, compiler version, etc.), there is little we can do to debug it for you.
In my environment, the authenticated
flag is stored at ebp-12, while the buffer is stored at ebp-28. ebp-28 is passed to strcmp, meaning that overflow will result in authenticated
being overwritten.
A longer string will eventually smash the return address : "1234567890123456000000000000" triggers a segfault in my place.
A recommended starting point could be compiling to assembly:
gcc -fno-stack-protector -z execstack -g -S test.c
generates test.s which will show you how your stack look.
You can also look at the binary using de-assemblers (objdump
and ida pro
come to mind), if compiling from source is not a facility you can afford ;-).
EDIT: From your pastebin, here is what I gather:
There clearly appears to be some form of stack protection:
movl %gs:20, %eax
[...]
movl -12(%ebp), %edx
xorl %gs:20, %edx
je .L5
call __stack_chk_fail
The __stack_chk_fail
is called if the place at -12(%ebp) is not %gs:20 anymore (eg your stack has been corrupted).
As a side note, if a real attacker who wants to bypass authentication can control the value of your "authenticated" flag, they won't even bother to try and erase the return address for the beauty of it.
Upvotes: 3
Reputation: 134286
Once the input (password
) string contains more than 15
(not 16
, need terminating null) charcater, using strcpy()
will invoke undefined behaviour.
So, after your program shows UB, you cannot expect it to behave in a desired way. It can do anything and everyting expected or unexpected. Whether it overwrites auth_flag
or not, cannot be determined.
Maybe, it's worthy to mention that the allocation of memory for variables does not necessarily take place in any particular order (of appearance). Your compiler is free to allocate memory in any order it sees fit.
Upvotes: 0