Please take a moment to read http://bit.ly/demandglobalchange, to help share the message and support the initiative to tell our leaders to focus on addressing the global world problems, instead of complaining about the effects of their lack of leadership. Be a leader yourself, and share this with as many people as possible. #demandglobalchange // https://www.facebook.com/demandglobalchange

Please consider donating: https://www.corelan.be/index.php/donate/


13,329 views | This page as PDF

In Memory Fuzzing

Introduction

In memory fuzzing is a technique that allows the analyst to bypass parsers; network-related limitations such as max connections, buit-in IDS or flooding protection; encrypted or unknown (poorly documented) protocol in order to fuzz the actual underlying assembly routines that are potentially vulnerable.

Prior to the development of my fuzzing toolset, I was unsatisfied (for now) with all the publicly available in memory fuzzers, because most of them are just too basic and require too much prep time in advance — flow analysis, reverse code engineering, etc — which obviously has a high learning curve and time consuming tasks, and most people would rather just stick with traditional fuzzers (which usually can accomplish the exact same thing).  Yes, you DO need some reversing skills to make in memory fuzzing useful, but honestly it doesn’t really have to be all that difficult to start fuzzing and find bugs… as long as you have the right approach.

One of the approaches we do here is by tracing user input automatically at real time, and log all the important functions that process that input, and then fuzz them.  A proof of concept (Tracer.py and InMemoryFuzzer.py) is also available to download:

http://redmine.corelan.be/projects/inmemoryfuzzing

Special thanks to:

  • Peter Van Eeckhoutte, and members of Corelan Security
  • Offensive Security Exploit Database
  • dookie2000ca for all the feedback

Requirements/Setup:

In order to use these tools, you should have:

Pydbg is probably the trickiest to install so we’ll go throughly the steps briefly:

  1. Install Python 2.5. The one I tested was Python 2.5 (r25:51908, Sep 19 2006)
  2. Download Pydasm (for Python 2.5) from the URL above.
  3. Download Paimei. Extract the package, go to the "installers" folder, and run the installer.
  4. Remove C:\Python25\Lib\site-packages\pydbg\pydasm.pyd
  5. Now you’re ready to test out Pydbg. Open command prompt, and type the following. If you no errors after importing Pydbg, that means your system now supports Pydbg:

import_pydbg

Tracer.py: How It Works

As I previously mentioned, in order to deploy an in memory fuzzer, you must go through a good amount of analysis to identify all the functions that process your input, and log the function entry address, RETN addresses, and the argument you want to fuzz.  This makes fuzzing very time consuming, simply not something that can be done in minutes. The purpose of Tracer.py is to ease off this process, allowing the user to track the control flow and user input at real time.

This is done by first searching all the function addresses in the application, put a hook point in every one of them, and then start monitoring.  If a hooked function is detected, we log the function and the argument, and keep monitoring.  Since this happens at real time, even with the most basic tool like this can still see some kind of pattern in the log, which gives us an idea where to fuzz.

The following example shows how to recognize this pattern in Tracer.py:

tracer_screenshot

Tracer.py: How To

First, open IDA.  If you’re using IDA 4.9 ( see image):

  1. Click on the Functions tab
  2. Select all the functions (click the first function -> hold [shift] -> select last function)
  3. Right click -> copy -> paste on notepad.  Save it as "functions.txt" under the same directory as the script.

ida49_functions_enum

If you’re using IDA Pro 5.5 or higher, the Functions table should be on the left of the the pretty graph.  You can do the same thing (right click -> copy and paste) to obtain all your functions that way.

Second, open the application you want to fuzz.  You must do this before running the script because it needs to attach to the process first.

Third, now that you have a function list (functions.txt).  Go to command prompt, and type of the following (assuming you saved Tracer.py in C:\):

C:>C:\Python25\python.exe Tracer.py

Fourth, the script should find the function list file without problems.  Give it a pattern (user input) to look for, select the process you want to monitor, and the fun begins.  Note that a file named "new_functions_addrs.txt" will be created — this file contains the same function addresses, and the correct RETN addresses.  You can use this as a reference later for InMemoryFuzzer.py.

Fifth, now Tracer.py should be monitoring.  Go back to the application, feed it the same pattern, and then you’ll see which functions get triggered.  Press [CTRL]+[C] to terminate the script.

InMemoryFuzzer.py: How It Works

The idea of how the fuzzer works is simple.  Say you have a vulnerable routine at entry 0x1001BEEF (aka snapshot point), which takes the user input as [ESP+4] at the beginning of the prologue, and that function ends at address 0x1001BFEA (restore point).  We can put a breakpoint at 0x1001BEEF, another at 0x1001BFEA, and let the application run, as the following diagram demonstrates:

flow_1

Wehen the execution flow hits our first breakpoint (entry) for the first time, we take a snapshot of the state (threads, stack, registers, flags, etc), modify the user input in [ESP+4], and resume execution to let the function to process our data, and hope something crashes.  If an exception is thrown somewhere in the code, we log that, restore the function state, and redirect the execution flow back to the entry (0x1001BEEF), and fuzz again with a new input, like this diagram:

flow_2

Or, no exception is triggered, we end up hitting the second breakpoint, then all we have to do is restore the state, rewind, and fuzz again:

flow_3

InMemoryFuzzer.py: How To

Before you use the fuzzer, you should already know the following:

  • Which process/dll to fuzz
  • The function entry address(s) (aka your snapshot points)
  • The restore point(s) (typically a RETN address)
  • Which function argument(s) to fuzz

First thing, open the application you want to fuzz again.  And if needed, change how many times you want to fuzz by editing the "maxFuzzCount" global variable in the source code.  Please note that InMemoryFuzzer.py has two modes for fuzzing:  Single routine, or multiple. Single routine mode allows the user to put every required information (function entry, restore point, argument) in one line:

C:>C:\python25\python.exe InMemoryFuzzer.py <Snapshot point> <Restore point> <Argument>

So if we were to reuse the same example in the "How it works" section, we would be feeding the fuzzer with the following:

C:>C:\python25\python.exe InMemoryFuzzer.py 0x1001BEEF 0x1001BFEA ESP+4

Multiple-Routine mode, which is my favorite mode, does not have to called from the command line.  All you must do is prepare breakpoints.txt, which contains information such as the snapshot point/restore point/argument with the same format: <snapshot point> <restore point> <argument>.  Example:

breakpoints_file

Once you have breakpoints.txt, double click on  InMemoryFuzzer.py, you’ll be asked which process to attach, trigger the vulnerable routine by feeding some user input again (does not have to be the same pattern as you did for Tracer.py) and then it’ll start fuzzing once the execution flow hits our first breakpoint. When the fuzzer is complete, there should be a newly created folder named "crashbin" under the same directory as the fuzzer.  Crash Bin is a place where InMemoryFuzzer.py stores all the crashes (htm files), and the inputs that caused them.  Here’s an example of a crash dump:

dump

Each crash dump contains information including:

  • Function entry (snapshot point) address
  • Argument
  • Argument length to crash the application
  • Registers (and what data they’re pointing to)
  • Disassembled instruction
  • SEH chains and offsets
  • Input that caused the crash

After an exception is found, the rest leaves for the user to analyze.  This is where IDA Pro, or Immunity Debugger becomes handy again.

Demonstration

In Memory Fuzzer demonstration

The above video demonstration shows you how to use in memory fuzzing from vulnerability to exploitation. You can view the video here as well : http://www.youtube.com/watch?v=YhyFuAfD7C4

  Copyright secured by Digiprove © 2010 Peter Van Eeckhoutte

© 2010 – 2015, Corelan Team (sinn3r). All rights reserved.

Related Posts:

17 Responses to In Memory Fuzzing

  • Boken says:

    Hi,

    First of all, congratulations for your development and to release the code.

    In my blog (Spanish, sorry), I released a script similar to InMemoryFuzzer.py:
    http://boken00.blogspot.com/2008/12/desarrollo-de-un-fuzzer-genrico-para.html

    The way to improve this work is your script Trace.py. Great job!

    But I don’t know why you don’t automatize the extraction of functions list and start-end address of each function with IDAPython invoked from Trace.py, using IDA command-line options and a little IDAPython script. Probably was for incompatibility with an IDA 4.9 and IDAPython?

    In the source code of my blog, you can view an example of this.

    Congratulations!
    Greets!

  • nombre says:

    Hello sinn3r,

    Just to clarify my thoughts, how do you select the dll that you get the functions from in step 1 of Tracer.py How to?

    Thanks,
    nombre

  • Pingback: Week 42 in Review – 2010 | Infosec Events

  • moigai says:

    Hi,

    I would like to thank you for writing such a nice article. I really want to try it out, but I cannot download the two files(Tracer.py and InMemoryFuzzer.py) from the link that was provided above. Is there any other way that I could download them?

    Thank you.

    • moigai says:

      Hi there again,

      I am sorry for this post. After a few more attempts, the link came back alive and I was able to download the files. Once again, thank you for this nice article!

      Thank you.

  • learner101 says:

    Hi, thanks very much for your time and the valuable information. Unfortunately, I could not access to two of the download links that you provided, any pointers are greatly appreciated.

    Pydasm: http://therning.org/magnus/archive/278

    https://redmine.corelan.be:3690/projects/inmemoryfuzzing <– this link requires credential that appears to be different than the one I'm using to access this blog.

    Best Regard

  • learner101 says:

    Peter, I’m able to download the files from the following link, thanks again for your help.

    http://redmine.corelan.be:8800/projects/inmemoryfuzzing/files?sort=size%2Cfilename

  • kewel says:

    Hi guys,

    I am not able yet to run tracer.py because of this error “ImportError: No module named MySQLdb”

    could somebody show me does he/she installed MySQLdb for python 2.5 on windows?

    Thank you,

  • Corelan Team (sinn3r) says:

    Regarding the “import MySQLdb” issue:

    The problem has been privately resolved thanks to kewel’s feedback. In case other users might have the same issue, this is due to a missing Try statement in module C:\Python25\Lib\site-packages\utils\code_coverage.py (part of Paimei). Please open this file with notepad, and modify the code like so:

    try: import MySQLdb
    except: pass

    Other similar problems (“No module named xx” error) may also be fixed with this approach.

  • kewel says:

    sinn3r,

    If you don’t mind I have one more Feedback.

    after that i executed the script very nice then i had to make Ctrl+C, when i came back to run the script again i got this error :s

    ==================================================
    C:\Fuzzer>Tracer.py
    _____
    |_ _| __ __ _ ___ ___ _ __
    | || ‘__/ _` |/ __/ _ \ ‘__|
    | || | | (_| | (_| __/ | by sinn3r
    |_||_| \__,_|\___\___|_| twitter.com/_sinn3r

    [*] Function list found
    [*] Enter a DWORD to track (eg: AAAA): AAAA
    Traceback (most recent call last):
    File “C:\Fuzzer\Tracer.py”, line 264, in
    main()
    File “C:\Fuzzer\Tracer.py”, line 246, in main
    functions = tracker.enumerateFunctions() #Grep all matching functions including RETNs
    File “C:\Fuzzer\Tracer.py”, line 106, in enumerateFunctions
    funcLength = lsplit[3] #Function block length
    IndexError: list index out of range
    ===================================================

    any reply will be appreciated.

    Thanks,

  • Oblivion86 says:

    This tutorial is out of date now I think. pydbg can’t be installed with the newer versions of python that come with immunity debugger. And the newest versions of Paimei doesn’t have pydbg installed by default, (at least there is no longer a file called pydbg.py). A updated fix for this that is newb friendly would be really cool of you guys, thanks.

Demand Global Change

The world needs your help !

Please take a few moments to read the "Demand Global Change Call For Action" document at
http://bit.ly/demandglobalchange
Read the full document at
http://bit.ly/demandglobalchange_full and share the message with as many people as possible.

Like the Facebook page, and SHARE it with everyone you know.



Donate

Want to support the Corelan Team community ? Click here to go to our donations page.

Want to donate BTC to Corelan Team?



Your donation will help funding server hosting.

Protected by Copyscape Web Plagiarism Tool

Corelan Team Merchandise

You can support Corelan Team by donating or purchasing items from the official Corelan Team merchandising store.

Corelan Live training

Since 2011, Corelan GCV has been teaching live win32 exploit dev classes at various security cons and private companies & organizations.

You can read more about the training and schedules here

Corelan on IRC

You can chat with us and our friends on #corelan (freenode IRC)

Categories