In-Memory fuzzing with Pin

In my previous blog post,
I talked about the taint analysis and the pattern matching with Pin. In this short post, I will always talk
about Pin, but this time about the In-Memory fuzzing.

1 - In-Memory fuzzing

1.1 - Little introduction

In-Memory fuzzing is a technique which consists to target and test a specific basic block, function or portion of a program. To
be honest, this technique is not really satisfactory over a large portion of code, this is mainly used for a quick analysis. However
it's really straightforward to implement it.

For that, we just need to :

Choose a targeted piece of code.

Set a breakpoint before and after our targeted area.

Save the execution context when the first breakpoint occurs.

Restore the execution context when the second breakpoint occurs.

Catch the SIGSEGV signal.

Repeat the operation 3 and 4 until the crash occurs.

1.2 - Little example

For a little example, see the following graph. Now, imagine that the user can control the first argument,
that means he can control the rdi register in the first basic block and [rbp+var_4] in this stack frame. In this case,
we are interested to test the orange basic block. As you can see below, in the orange basic block we have a "mov eax, [rbp+var_4]",
that means we can control the eax register. So, we will apply the In-Memory fuzzing technique in this basic block between the
"cdqe" and "mov eax, 0" instructions and we will fuzz the eax register.

Use the Pin API

The Pin API provides all what we need to apply the In-Memory fuzzing technique. To catch the signals, we use the
PIN_InterceptSignal()
function. This function takes the type of signal and a callback. So, to catch the SIGSEGV signal, in our main function we have something like
that:

PIN_InterceptSignal(SIGSEGV,catchSignal,0);

Our call back catchSignal, displays just the current context when the signal occurs.

Then, because Pin is a DBI framework (Dynamic Binary Instrumentation), we can't set a breakpoint, but that's not really important. With a DBI framework we
can control each instruction before and after their execution. So, we will use
the PIN_SaveContext()
and PIN_ExecuteAt()
functions when the first and last targeted instruction occurs.

A CONTEXT
in Pin, is just the registers state of the processor. That means, when you call PIN_SaveContext(), you save only the state of registers, not the memory. So,
to monitor the STORE access, we use the INS_MemoryOperandIsWritten()
function. When a STORE occurs, we save the original value and we restore it when the context is restored.

In-Memory fuzzing Pin tool

This Pin tool requires three arguments and can take three optional arguments.

Required
--------
-start <address> The start address of the fuzzing area
-end <address> The end address of the fuzzing area
-reg <register> The register which will be fuzzed
Optional
--------
-startValue <value> The start value
-maxValue <value> The end value
-fuzzingType <"inc" | "random"> Type of fuzzing: incremental or random

If we take the above example and that we want to fuzz the orange basic block, we have something like that:

I used the "time" command to show you how Pin is efficient - I've also redirected stdout in a file called 'dump'
because of the output log size (5.5M). At the end of this dump, you can see the context when the SIGSEGV occurs -
Current RIP = 0x4005a5 "movzx eax, byte ptr [rax]" with RAX = 0x2420.