I'm currently reading (for the second time) "Hacking : The Art of Exploitation" and have stumbled on something.
The book suggests two different ways to exploit these two similar programs : auth_overflow and auth_overflow2
In the first one, there is a password checking function layed out like this
int check_authentication(char *password) {
int auth_flag = 0;
char password_buffer[16];
strcpy(password_buffer, password);
...
}
Inputing more than 16 ASCII characters will change the value of auth_flag to something greater than 0, thus bypassing the check, as shown on this gdb output:
gdb$ x/12x $esp
0xbffff400: 0xffffffff 0x0000002f 0xb7e0fd24 0x41414141
0xbffff410: 0x41414141 0x41414141 0x41414141 0x00000001
0xbffff420: 0x00000002 0xbffff4f4 0xbffff448 0x08048556
password_buffer @ 0xbffff40c
auth_flag @ 0xbffff41c
The second program inverts the two variables :
int check_authentication(char *password) {
char password_buffer[16];
int auth_flag = 0;
strcpy(password_buffer, password);
...
}
The author then suggests than it's not possible to overflow into auth_flag, which I really believed. I then proceeded to overflow the buffer, and to my surprise, it still worked. The auth_flag variable was still sitting after the buffer, as you can see on this gdb output:
gdb$ x/12x $esp
0xbffff400: 0xffffffff 0x0000002f 0xb7e0fd24 0x41414141
0xbffff410: 0x41414141 0x41414141 0x41414141 0x00000001
0xbffff420: 0x00000002 0xbffff4f4 0xbffff448 0x08048556
password_buffer @ 0xbffff40c
auth_flag @ 0xbffff41c
I'm wondering if gcc is not reordering local variables for alignement/optimization purposes.
I tried to compile using -O0 flag, but the result is the same.
Does one of you knows why is this happening ?
Thanks in advance.
The compiler authors are completely free to implement any allocation scheme for local variables with automatic storage. auth_flag
could be set before or after password_buffer
on the stack, it could be in a register, it could be elided completely if proper analysis of the code allows it. There might not even be a stack... The only guarantee the Standard gives you is this:
strcpy(password_buffer, password);
invokes undefined behavior if the source string including its null terminator is longer than the destination array password_buffer
. Whether this undefined behavior fits your needs is completely outside of the language specification.
As a matter of fact, some implementors purposely complicate the task of would be hackers by randomizing the behavior in cases such as the posted code.
I had the same problem. In order to fix this, put the two variables in a struct. In a struct the fields are always located as defined in the struct. Be aware that the order is reversed.
struct myStruct {
int auth_flag;
char password_buffer[16];
};
I know thats an old question.
But in my case -fno-stack-protector flag did the trick. So if I compile with -fno-stack-protector, local variables ordered as excepted (at least for this simple program ).
I wonder, maybe reordering can be some sort of protection. Here I found link about that
User contributions licensed under CC BY-SA 3.0