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

Analyzing heap objects with mona.py

Introduction

Hi all,

While preparing for my Advanced exploit dev course at Derbycon, I’ve been playing with heap allocation primitives in IE. One of the things that causes some frustration (or, at least, tends to slow me down during the research) is the ability to quickly identify objects that may be useful. After all, I’m trying to find objects that contain arbitrary data, or pointers to arbitrary data, and it’s not always easy to do so because of the noise.

I decided to add a few new features to mona.py, that should allow you to find interesting objects in a faster way. The new features are only available under WinDBG.

To get the latest version of mona, simply run !py mona up. Since I also upgraded to the latest version of pykd, you may have to update pykd.pyd as well before you can run the latest version of mona. (You should see update instructions in the WinDBG log window when you try to run mona with an outdated version of pykd)

dumpobj (do)

The first new feature is "dumpobj". This mona.py command will dump the contents of an object and provide (hopefully) useful information about the contents. The command takes the following arguments:

As you can see in the output of !py mona help dumpobj above, we need to provide at least 2 arguments:

-a

: the start location (address of the object, but you can specifiy any location you want)

-s : the size of the object. If you don’t specify the -s argument, mona will attempt to determine the size of the object. If that is not possible, mona will dump 0x28 bytes of the object.

Additionally, you can tell mona to dump linked objects as well. Argument -l takes a number, which refers to the number of levels for the recursive dump. In order to somewhat limit the size of the output (and for performance reasons), only the first 0x28 bytes of the linked objects will be printed (unless you use argument -m to overrule this behavior).

Of course, it is quite trivial to dump the contents of an object in WinDBG. The dds or dc commands will print out objects and show some information about its contents. In some cases, the output of dds/dc is not sufficient and it would require some additional work to further analyze the object and optional objects that are linked inside this object.

Let’s look at an example. Let’s say we have a 0x78 byte object at 0x023a1bc0. Of course, we can dump the contents of the object using native WinDBG commands:

Apparently some of the values in the object point at strings (ASCII and Unicode), another point appears to link to another object (ADVAPI32!g_CodeLevelObjTable+0x4). This is a lot more useful than dds or dc. But we can make it even better. We can tell mona to automatically print out linked objects as well, up to any level deep. Let’s repeat the mona command, this time asking for linked objects up to one level deep:

As you can see in the output above, mona determined that the source object contained references to 2 linked objects, and decided to dump those linked object as well. It’s important to know that mona won’t consider strings (ASCII or Unicode) as objects, because mona already shows the strings, even if they are referenced inside the object. The output of the dumpobj command is written to a text file called "dumpobj.txt".

For your info, the output of !mona info -a

includes the output of mona dumpobj (without printing recursive objects). If you want to understand what exactly a given address is, you’ll get something like this:

dumplog (dl)

It is clear that the dumpobj command will make it easier to visualize important information inside an object. This is certainly helpful if you already know the starting object. What if you have been logging all Heap allocations and free operations in the application and storing the output in a log file? Even a few lines of javascript code can be quite noisy from a Heap perspective, making it less trivial to identify interesting objects.

To make our lives easier, I decided to implement "dumplog", which will parse a log file (based on a certain syntax) and perform a "dumpobj" on each object that has been allocated, but not freed. In the current version, dumplog will not dump linked objects, but I plan on adding this feature soon. (probably tomorrow)

Dumplog requires a proper setup. We need to tell WinDBG to create a log file that follows a specific convention, and we obviously must run mona dumplog in the same debug session (to make sure the logged allocations and free operations are still relevant).

The output of "!py mona help dumplog" shows this:

Usage of command 'dl' :
------------------------
Dump all objects recorded in an alloc/free log
Note: dumplog will only dump objects that have not been freed in the same logfile.
Expected syntax for log entries:
Alloc : 'alloc(size in hex) = address'
Free : 'free(address)'
Additional text after the alloc & free info is fine.
Just make sure the syntax matches exactly with the examples above.
Arguments:
-f <path/to/logfile> : Full path to the logfile

The idea is to log all Heap allocations and free operations to a log file. In WinDBG this can be achieved using the following steps:

Before running the process and triggering the alloc/free operations that you want to capture and analyze, tell WinDBG to write the output of the log window to a text file:

These 2 breakpoints will print a message to the WinDBG log window each time RtlAllocateHeap and RtlFreeHeap are called, printing out valuable information about the API call. It’s important to stick to this format, but you are free to add more text to the end of the message string. With these 2 breakpoints active, and WinDBG configured to start writing the output of the log window to a text file, we can run the application.

When you’re ready to do analysis, break WinDBG. Don’t close it at this point, but close the log file using the .logclose command.

We can now use mona to parse the log file, find the objects that have been allocated and not freed, and perform a mona dumpobj on each of those objects.

!py mona dl -f c:\allocs.txt

The output will be written to dump_alloc_free.txt

I hope you’ll enjoy these 2 new features.

Stay safe & take care

cheers

-corelanc0d3r

Update (Aug 17) – the "dumplog" feature now supports dumping linked objects (option -l). Linked objects will have a reference to the parent object. (This applies to dumpobj as well).