Communicating with VMWare when you're running inside it is fairly straight forward... basically you just set up a few registers with certain parameters and then call a port.
This backdoor port acts as a bridge between the virtual machine and the host machine, allowing them to talk to each other. And this is what VMWare Tools does, allowing you to do such things as copy files to and from the virtual machine and host machine. Without this backdoor port such features wouldn't be possible.
Saying hello to VMWare is easy. For example, to retrieve the VMWare version number you set the following registers:
EAX = &h564D5868 ("VMXh") ;'Magic number' used by VM to identify calls made to it
CX = &h000A ;Command number (&hA = Get Version)
DX = &h5658 ;Port number
CX is used to specify the command. EAX and DX are constants. The return values are stored in eax, and ebx/ecx/edx as needed. That's basically all there is to it!
If you try to make such a call when you're NOT running from within VMWare your program will crash because of the call to privileged port instruction "in", so we simply need to set up a Structured Exception Handler first.
So while the virtual machine is isolated from the host machine this backdoor port shows that it's not completely isolated ...
For example, this demo when run from within a virtual machine will show you the current clipboard text of the HOST machine even though it is supposedly isolated. You could for example write a program that runs inside VMWare that sits in a loop, checking the contents of the host machines clipboard every second and logging it ... something of an 'intra-machine clipboard logger'. You can also SET the clipboard text on the host from within the virtual machine, although i haven't included code for that.
This demo also shows other things such as memory size, CPU speed, screen dimensions, and a few others. Some are related to the virtual machine, some to the host, and some to both (such as getting clipboard text).
You can also use the backdoor port to copy files from the host to the virtual machine and back, but I haven't included any code for that here.
You can find more information about the VMWare backdoor port at http://chitchat.at.infoseek.co.jp/vmware/backdoor.html, it's what I used to help write this.
This backdoor port acts as a bridge between the virtual machine and the host machine, allowing them to talk to each other. And this is what VMWare Tools does, allowing you to do such things as copy files to and from the virtual machine and host machine. Without this backdoor port such features wouldn't be possible.
Saying hello to VMWare is easy. For example, to retrieve the VMWare version number you set the following registers:
EAX = &h564D5868 ("VMXh") ;'Magic number' used by VM to identify calls made to it
CX = &h000A ;Command number (&hA = Get Version)
DX = &h5658 ;Port number
CX is used to specify the command. EAX and DX are constants. The return values are stored in eax, and ebx/ecx/edx as needed. That's basically all there is to it!
If you try to make such a call when you're NOT running from within VMWare your program will crash because of the call to privileged port instruction "in", so we simply need to set up a Structured Exception Handler first.
So while the virtual machine is isolated from the host machine this backdoor port shows that it's not completely isolated ...

For example, this demo when run from within a virtual machine will show you the current clipboard text of the HOST machine even though it is supposedly isolated. You could for example write a program that runs inside VMWare that sits in a loop, checking the contents of the host machines clipboard every second and logging it ... something of an 'intra-machine clipboard logger'. You can also SET the clipboard text on the host from within the virtual machine, although i haven't included code for that.
This demo also shows other things such as memory size, CPU speed, screen dimensions, and a few others. Some are related to the virtual machine, some to the host, and some to both (such as getting clipboard text).
You can also use the backdoor port to copy files from the host to the virtual machine and back, but I haven't included any code for that here.
You can find more information about the VMWare backdoor port at http://chitchat.at.infoseek.co.jp/vmware/backdoor.html, it's what I used to help write this.
Code:
#COMPILE EXE #REGISTER NONE #INCLUDE "WIN32API.INC" TYPE SEH dwPrevLink AS DWORD dwCurrentHandler AS DWORD dwSafeOffset AS DWORD dwPrevEsp AS DWORD dwPrevEbp AS DWORD END TYPE TYPE VMWareReply eax AS DWORD ebx AS DWORD ecx AS DWORD edx AS DWORD END TYPE FUNCTION SEH_Handler CDECL( ptExcept AS EXCEPTION_RECORD PTR, ptFrame AS SEH PTR, ptContext AS CONTEXT PTR, BYVAL pdwDispatch AS DWORD) AS LONG @ptContext.regEip = @ptFrame.dwSafeOffset END FUNCTION FUNCTION VMWareCall (VMReply AS VMWareReply, BYVAL vmebx AS DWORD, BYVAL vmecx AS DWORD, BYVAL vmedx AS DWORD) AS LONG #REGISTER NONE LOCAL lEbp AS LONG, lEsp AS LONG, tSeh AS SEH, ptrReply AS DWORD ptrReply = VARPTR(VMReply) ! push dword fs:[0] tSeh.dwCurrentHandler = CODEPTR(SEH_HANDLER) tSeh.dwSafeOffset = CODEPTR(Except) ! lea esi, tSeh ! mov fs:[0], esi ! mov lEsp, esp ! mov lEbp, ebp tSeh.dwPrevEsp = lEsp tSeh.dwPrevEbp = lEbp ! mov eax, "VMXh" ! mov ebx, vmebx ! mov ecx, vmecx ! mov edx, vmedx ! in eax, dx ! push esi ! mov esi, ptrReply ! mov [esi], eax ! mov [esi+4], ebx ! mov [esi+8], ecx ! mov [esi+12], edx ! pop esi FUNCTION = 1 Except: ! pop dword fs:[0] END FUNCTION '### VMWARE CALLS ###################################################################### FUNCTION GetVMVersion() AS STRING '// Returns VMWare version and product type LOCAL VMReply AS VMWareReply, sVer AS STRING IF VMWareCall(VMReply, BYVAL 0, BYVAL &h0000000A, BYVAL &h00005658) <> 1 THEN FUNCTION = "Error": EXIT FUNCTION ELSE SELECT CASE VMReply.ecx CASE 1: sVer = "Express" CASE 2: sVer = "ESX Server" CASE 3: sVer = "GSX Server" CASE 4: sVer = "Workstation" END SELECT sVer = sVer & " (Version: " & HEX$(VMReply.eax) & ")" FUNCTION = sVer END IF END FUNCTION FUNCTION GetVMHardwareVersion() AS STRING '// Returns virtual machine hardware version LOCAL VMReply AS VMWareReply IF VMWareCall(VMReply, BYVAL 0, BYVAL &h00000011, BYVAL &h00005658) <> 1 THEN FUNCTION = "Error": EXIT FUNCTION ELSE SELECT CASE VMReply.eax CASE 1, 2: FUNCTION = TRIM$(STR$(VMReply.eax)) & " - WS3.x/GSX2.x" CASE 3: FUNCTION = "3 - WS4.x, ESX2.x, GSX3.x, ACE1.x, and with WS5.x" CASE 4: FUNCTION = "4 - WS5.x" CASE ELSE: FUNCTION = TRIM$(STR$(VMReply.eax)) & " - Unknown" END SELECT END IF END FUNCTION FUNCTION GetVMCPUSpeed() AS STRING '// Returns host CPU speed in MHz LOCAL VMReply AS VMWareReply IF VMWareCall(VMReply, BYVAL 0, BYVAL &h00000001, BYVAL &h00005658) <> 1 THEN FUNCTION = "Error": EXIT FUNCTION ELSE FUNCTION = TRIM$(STR$(VMReply.eax)) & "MHz" END IF END FUNCTION FUNCTION GetVMCursorPos() AS STRING '// Returns current cursor position LOCAL VMReply AS VMWareReply IF VMWareCall(VMReply, BYVAL 0, BYVAL &h00000004, BYVAL &h00005658) <> 1 THEN FUNCTION = "Error": EXIT FUNCTION ELSE FUNCTION = "X=" & TRIM$(STR$(LOWRD(VMReply.eax))) & " Y=" & TRIM$(STR$(HIWRD(VMReply.eax))) END IF END FUNCTION FUNCTION GetVMHostScreenSize() AS STRING '// Returns dimensions of the host screen size LOCAL VMReply AS VMWareReply IF VMWareCall(VMReply, BYVAL 0, BYVAL &h0000000F, BYVAL &h00005658) <> 1 THEN FUNCTION = "Error": EXIT FUNCTION ELSE FUNCTION = TRIM$(STR$(LOWRD(VMReply.eax))) & " x " & TRIM$(STR$(HIWRD(VMReply.eax))) END IF END FUNCTION FUNCTION GetVMClipboardTextLen() AS DWORD '// Returns length of text in clipboard LOCAL VMReply AS VMWareReply, sBuf AS STRING IF VMWareCall(VMReply, BYVAL 0, BYVAL &h00000006, BYVAL &h00005658) <> 1 THEN EXIT FUNCTION ELSE FUNCTION = VMReply.eax END IF END FUNCTION FUNCTION GetVMMemorySize() AS STRING '// Returns amount of memory assigned to the virtual machine LOCAL VMReply AS VMWareReply IF VMWareCall(VMReply, BYVAL 0, BYVAL &h00000014, BYVAL &h00005658) <> 1 THEN EXIT FUNCTION ELSE FUNCTION = TRIM$(STR$(VMReply.eax)) & " MBs" END IF END FUNCTION FUNCTION GetVMHostSystemTime() AS STRING '// Returns hosts current system time (GMT) LOCAL VMReply AS VMWareReply, sTime AS STRING IF VMWareCall(VMReply, BYVAL 0, BYVAL &h00000017, BYVAL &h00005658) <> 1 THEN EXIT FUNCTION ELSE sTime = HEX$(VMReply.eax,8) & " (Timezone: " & TRIM$(STR$(VMReply.edx)) & ")" FUNCTION = sTime END IF END FUNCTION FUNCTION GetVMClipboardText() AS STRING '// Returns text from clipboard LOCAL VMReply AS VMWareReply, sBuf AS STRING, txtLen AS LONG, dwPtr AS DWORD PTR txtLen = GetVMClipboardTextLen IF txtLen <= 0 THEN FUNCTION = "{Empty}": EXIT FUNCTION END IF sBuf = STRING$(txtLen+4,0) dwPtr = STRPTR(sBuf) DO IF VMWareCall(VMReply, BYVAL 0, BYVAL &h00000007, BYVAL &h00005658) <> 1 THEN FUNCTION = "Error": EXIT FUNCTION ELSE IF VMReply.eax = 0 THEN EXIT DO @dwPtr = VMReply.eax dwPtr = dwPtr + 4 END IF LOOP FUNCTION = LEFT$(sBuf, txtLen) END FUNCTION FUNCTION InsideVMWare() AS LONG '// Returns 1 if we're running inside VMWare LOCAL VMReply AS VMWareReply FUNCTION = VMWareCall(VMReply, BYVAL 0, BYVAL &h0000000A, BYVAL &h00005658) END FUNCTION FUNCTION PBMAIN() AS LONG IF InsideVMWare <> 1 THEN STDOUT "Not running in VMWare." WAITKEY$: EXIT FUNCTION END IF STDOUT "Type/Version: " & GetVMVersion STDOUT "CPU Speed: " & GetVMCPUSpeed STDOUT "Cursor: " & GetVMCursorPos STDOUT "Host Screen Size: " & GetVMHostScreenSize STDOUT "Clipboard Text: " & GetVMClipboardText STDOUT "Virtual Hardware Version: " & GetVMHardwareVersion STDOUT "Memory: " & GetVMMemorySize STDOUT "Host System Time (unix-style timestamp): " & GetVMHostSystemTime STDOUT "Done." WAITKEY$ END FUNCTION
Comment