I cannot get this buffer overflow exploit to work for the life of me. The source code is here. It is from the book, Hacking the Art of Exploitation. The subject here is the below struct:
struct user {
int uid;
int credits;
int highscore;
char name[100];
int (*current_game) ();
};
The idea is to overflow name[100] such that the address provided after the 100 letter A's will overwrite the address of the function pointer, entitled current_game.
However, please see the below gdb readout:
[Name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA��048e2c]
56 printf("[You have %u credits] -> ", player.credits);
(gdb) x/40x player.name
0x804c08c <player+12>: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c09c <player+28>: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c0ac <player+44>: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c0bc <player+60>: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c0cc <player+76>: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c0dc <player+92>: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c0ec <player+108>: 0x41414141 0x080490bb 0x65383430 0x00006332
0x804c0fc: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c10c: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c11c: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) x/5x player.current_game
0x80490bb <pick_a_number>: 0x83e58955 0xec8318ec 0x9d2e680c 0xa2e80804
0x80490cb <pick_a_number+16>: 0x83fffff4
(gdb) print 6*16
$2 = 96
I've placed the address of another function into player.name as noted by the [Name: A*100 ...
line. Below this, you can see the memory layout, how there are indeed 100 A's in memory. However, after the final A, we see that the next memory spot is 0x080490bb
and has not been overwritten, even though we see that the player.name buffer does indeed contain an overflow just prior. I've shown a printout of player.current_game afterwards to display that it is indeed at address 0x80490bb
which is what we see in the dump directly after the last 0x41414141. I am baffled here.
What I've Tried:
- Disabled ASLR on my Fedora 25 by setting
/proc/sys/kernel/randomize_va_space
to 0. - Enabled executable stack in gcc.
- Turned off the stack protection in gcc.
- Turned off PIE
- You can confirm with this command that I used to make the binary:
gcc -z execstack game_of_chance.c -fno-stack-protector -no-pie -m32 -o goc
- I've tried writing the address in as \x2c\x8e\x04\08 AND just straight 0x08048e2c, neither work. This is the address of the function I'm trying to run.
- Observed that paddr and vaddr are the same throughout multiple executions of the program.
Debugged in both gdb as you see, as well as Radare2. You can see my rabin2 printout for the file below:
havecode true pic false canary false nx false crypto false va true intrp /lib/ld-linux.so.2 bintype elf class ELF32 lang c arch x86 bits 32 machine Intel 80386 os linux minopsz 1 maxopsz 16 pcalign 0 subsys linux endian little stripped false static false linenum true lsyms true relocs true rpath NONE binsz 20471
Thanks.
Update
I am able to successfully cause a segmentation fault with the chars (such as 'A' or 'B'), however, when I do the A*100 followed by 08048e2c memory address which I am trying to jump execution to, the segfault happens, but the player.current_game function pointer address (which is right after the player.name buffer as shown above) is oddly [DEBUG] current_game pointer @ 0x34303830
rather than the address 08048e2c, which causes the segmentation fault since it can't execute 0x34303830. Additionally, I placed read/write watches on 0x804c0ec to see if I could find anything writing but was not successful in finding anything else.