GiTS 2014: fuzzy

tl;dr – fuzzy is a “super secure parsing engine”, that includes a histogram function. The histogram ascii text uses a buffer on the stack, but will increment
buckets past the end of the buffer if non ascii text is provided, allowing us to
rop.

Binary and exploit available here.

The program

fuzzy is a “super secure parsing engine”, that includes a histogram function:

As you can see, it computes a histogram of the input. This histogram
is constructed using a buffer that is on the stack, so if we send it
non-ascii text we can write to the stack. By modifying the saved ebp,
we can point the stack to a buffer we control.

Unfortunately, this is a bit challenging to figure out because all
the interesting functions are encrypted. Fortunately for us, the “encryption”
is just bitwise not. Using our favorite hex editor, we make a new binary with
the decrypted functions to reverse.

With control of the stack, we get control over rip and can ROP.
We will use the callFunction function, which decrypts a function
into an executable page and then runs it. Our goal will be to read encrypted shellcode
into a known location (there is a convenient buffer dontcollide in the data
section that is never used), then invoke callFunction to run our shellcode.
Unfortunately, since this is x64, we need to find a good gadget to be able to
control registers and call functions. Luckily, there is a good gadget in
__libc_csu_init:

This gadget allows us to control the first three registers we need an call
anything we have function pointer to. The program uses a large function pointer table to enable
the encrypted functions to call library functions, so we have pointers to many
library functions. Unfortunately, we do not have a pointer to readAll, so we
cannot use it with our gadget. Furthermore, our gadget only controls 3 arguments,
so we cannot easily use recv. Lastly, we cannot use the encrypted my_readAll
function (that we have a pointer to) because it reads its arguments out of a
buffer and we don’t have an easy way to call functions with a buffer we control
as an argument. Still, this gadget allows us to chain calls arbitrary function pointers
with 3 arguments:

Instead, we make a function pointer to readAll in the data section that we can use our
gadget.
We call memset 4 times, once for each distinct byte in
the the address of readAll, and make dontcollide a pointer to readAll.

We then can use our gadget to call readAll,
reading the encrypted shellcode into dontcollide, and then again to call
callFunction, executing our shellcode.

We grab some connect back shellcode
and get a shell:

Writeup by Alex Reece, see me on Google+ or my blog.

    • someone
    • February 10th, 2014

    Nice work but you work too hard :p

    The stack was executable. It was possible to adjust the return address to point to a ret with just a few increments. The next value on the stack was a pointer to the buffer used for the histogram. Then you just needed to add shellcode which avoided byte values that would increment stack locations you didn’t want incremented.

  1. No trackbacks yet.