Click here to Skip to main content
Email Password   helpLost your password?

Sample Image

Introduction

This article will demonstrate how an application can detect if it is being run from inside a virtual machine software.

The code in this article will detect two well known machine virtualization software:

Other virtual machine software such as Bochs or Plex86 are not covered in this article.

It is best that the readers have a general idea about the Intel x86 assembly language to better understand how the code works, however I will do my best to explain the techniques in layman's terms.

Please note that whenever I use the term "Virtual Machine Software", this means I am referring to a software such as Virtual PC or VMWare. When the term "Virtual Machine" is used, this means the emulated machine, usually running an operating system.

A little about virtual machine software

Virtual machine software are software that emulate a given machine's architecture using software (code) instead of relying on hardware, thus allowing a code to be executed in that virtual machine as if it is being run from a real machine.

Till today, these software are far from being perfect, and emulating a given real machine still poses many challenges due to complexities involved when trying to emulate every component of a given machine.

Both Virtual PC and VMWare allow you to install "add-in"s to accelerate emulation, allow drag-n-drop from your real desktop to your virtual desktop, and allow file sharing between your real machine and the virtual machine.

In order to accomplish this task, a communication mechanism between the virtual machine software and the virtual machine itself must exist.

This sort of interfacing is called a "backdoor interfacing", since, using a special/undocumented mechanism, certain commands can be carried and interpreted in a different manner (by the virtual machine software) unlike having them interpreted by the real machine.

Next, I'll be covering how you can tell whether your software is being executed using a real machine or a virtual machine software (covering both Virtual PC and VMWare).

How to detect Virtual PC

As you may already know, every machine has a defined set of instructions commonly referred to as Instruction Set Architecture (ISA).

When an invalid instruction (that is not present in the ISA) is encountered, the machine raises an exception of the type "Invalid Opcode". The software can either handle the exception (using the usual try/catch mechanism), let the operating system handle the exception, or crash the machine in worst cases.

Virtual PC uses a bunch of invalid instructions to allow the interfacing between the virtual machine and the Virtual PC software.

Here's what happens when Virtual PC's virtual machine wants to talk with Virtual PC:

  1. The program sets exception handlers (try/catch blocks).
  2. Set needed parameters before calling the VM software.
  3. Issue a special "Invalid Opcode" instruction.
  4. VM software will recognize this invalid opcode and act accordingly, causing no exception if VPC was present, and an exception if VPC isn't present.
  5. The program's "catch" block will handle the exception and examine the returned parameters for the presence/absence of VM software.

In short, Virtual PC uses the "Invalid Opcode" mechanism as a backdoor.

The following code shows how to detect Virtual PC's presence:

// IsInsideVPC's exception filter

DWORD __forceinline IsInsideVPC_exceptionFilter(LPEXCEPTION_POINTERS ep)
{
  PCONTEXT ctx = ep->ContextRecord;

  ctx->Ebx = -1; // Not running VPC

  ctx->Eip += 4; // skip past the "call VPC" opcodes

  return EXCEPTION_CONTINUE_EXECUTION;
  // we can safely resume execution since we skipped faulty instruction

}

// High level language friendly version of IsInsideVPC()

bool IsInsideVPC()
{
  bool rc = false;

  __try
  {
    _asm push ebx
    _asm mov  ebx, 0 // It will stay ZERO if VPC is running

    _asm mov  eax, 1 // VPC function number


    // call VPC 

    _asm __emit 0Fh
    _asm __emit 3Fh
    _asm __emit 07h
    _asm __emit 0Bh

    _asm test ebx, ebx
    _asm setz [rc]
    _asm pop ebx
  }
  // The except block shouldn't get triggered if VPC is running!!

  __except(IsInsideVPC_exceptionFilter(GetExceptionInformation()))
  {
  }

  return rc;
}

More details on the code:

  1. Install exception handlers.
  2. Prepare input registers "eax" and "ebx".
  3. Issue invalid instruction 0x0F 0x3F 0x07 0x0B. This invalid instruction is like a function designator, it tells Virtual PC what to do exactly. For other functionality, Virtual PC uses another invalid instruction.
  4. Inside the exception handler -> modify registers so to mark VPC's absence (EBX is set to -1 if exception is triggered -> VPC is absent).
  5. Return from exception and resume execution (only if VPC was absent).
  6. Inspect returned registers accordingly.

How to detect VMWare

The Intel x86 provides two instructions to allow you to carry I/O operations, these instructions are the "IN" and "OUT" instructions. These two instructions are privileged instructions and cannot be used in a user-mode (while in protected mode) process unless the necessary privileges are enabled, so using them in normal cases will cause an exception of the type: "EXCEPTION_PRIV_INSTRUCTION".

VMWare uses the "IN" instruction to read from a special port. This port does not effectively exist, however when VMWare is present, that port will be the interface between the virtual machine and VMWare.

Here's the code:

bool IsInsideVMWare()
{
  bool rc = true;

  __try
  {
    __asm
    {
      push   edx
      push   ecx
      push   ebx

      mov    eax, 'VMXh'
      mov    ebx, 0 // any value but not the MAGIC VALUE

      mov    ecx, 10 // get VMWare version

      mov    edx, 'VX' // port number


      in     eax, dx // read port

                     // on return EAX returns the VERSION

      cmp    ebx, 'VMXh' // is it a reply from VMWare?

      setz   [rc] // set return value


      pop    ebx
      pop    ecx
      pop    edx
    }
  }
  __except(EXCEPTION_EXECUTE_HANDLER)
  {
    rc = false;
  }

  return rc;
}
  1. The program sets exception handlers (in case VMWare isn't present, we just discard its presence).
  2. Set up into the EAX register the magic number 0x564D5868 (or 'VMXh').
  3. Set EBX register to any value but the magic number.
  4. Set ECX register to the "function number" value. The value 10 means Get VMWare version, other codes means other functionality.
  5. Set into DX the magic port number 0x5658 (or 'VX'), this special port number allows interfacing with VMWare when it is present.
  6. Read from that port into EAX.
    1. When VMWare is not present, an exception will occur and we discard VMWare's presence.
    2. Otherwise, the code flow continues.
  7. EBX should now read the magic number value.
  8. If so, then VMWare is present.

Using the code

This article comes with a sample GUI written in C#/VB.NET and VC++, allowing you to detect the presence of either VMWare or Virtual PC.

The C++ code uses "DetectVM.cpp/.h" which exports the following functions:

  bool IsInsideVPC();
  bool IsInsideVMWare();

The C#/VB.NET code uses the following read-only properties:

  System::Boolean IsInsideVPC
  System::Boolean IsInsideVMWare

Closing words

Hope you enjoyed and learned from reading this article and using the code. Thanks to CodeProject members for their continuous support and quality articles/code.

Special thanks goes to Mr. Ken Kato, for his work that enabled me to learn about VMWare's backdoor interface.

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
QuestionCan not run on Windows Server 2008 64Bit.
Member 4429983
17:38 4 Feb '10  
Can not run on Windows Server 2008 64Bit.
GeneralIs it possible to detect Parallels ( Virtual Machine under Mac)
tomasen
8:13 4 Jun '09  
Is it possible to detect Parallels ? ( Virtual Machine under Mac)

There are more and more people start using Parallels Workstation or Desktop Under Mac. I really hope there can be a way to detect them.~~
QuestionHow about late binding?
HStrix
8:09 24 Mar '09  
Is it possible to use the dll in late binding?
Currently the statement "If COM.Tools.VmDetect.IsInsideVMWare() Then" is used for detection. This means, the dll needs to be added as COM object to the project. My question is, how can this dll be accessed without being added as a COM object? In old VB6 this was done by using CreateObject, but I couldn't figure it out.
Thanks for any help.
GeneralFor Virtual PC, try this...
leandrobecker
3:27 28 Jan '09  
Hello

For Virtual PC detection, maybe this worth a try: http://blogs.msdn.com/virtual_pc_guy/archive/2005/01/24/359650.aspx[^]

Regards
GeneralHow about ESXI
Colin Maharaj
13:23 21 Nov '08  
Has anyone tried this under ESXI??

Or, if it does not work in ESXI how can we then do a detection?
Questionporting in RHEL (UNIX) [modified]
vikramaditya234
2:34 17 Nov '08  
This is good information.
I am trying to port the code to UNIX in C language. My program:
asm("push ebx");
asm("mov %ebx, 0");
asm("mov %eax, 1");

asm("__emit 0fh");
asm("__emit 03fh");
asm("__emit 07h");
asm("__emit 0bh");

asm("pop ebx");


So far unsuccessful Frown
It seems we cannot use __asm instead we have to use asm() function for each command. But after using that i am facing problem in the compilation of the code in UNIX. I am getting error from the assembler:

/tmp/ccNpl4q8.s: Assembler messages:
/tmp/ccNpl4q8.s:12: Error: invalid character '_' in mnemonic
/tmp/ccNpl4q8.s:13: Error: invalid character '_' in mnemonic
/tmp/ccNpl4q8.s:14: Error: invalid character '_' in mnemonic
/tmp/ccNpl4q8.s:15: Error: invalid character '_' in mnemonic


Also the command __try wont work.

Can anyone please point out what mistake I am doing
Also how can implement the __try and __except in UNIX

Regards,
Vikram

think because thats what matters

modified on Tuesday, November 18, 2008 9:05 AM

QuestionI need to know from API Windows if my appIication is running in a virtual machine or not.
piermario
0:24 1 Sep '08  
Hi my need is to knows if my appl (running on windows ) is inside a virtual machine or not.But not specifically calling a backdoors of a known virtual machine like vmware, virtualpc, virtual box, but generally in any virtual machine (probably calling API windows?) .
Is it possible? is there any sample in C/C++ to use (Im working on VC++)?
Thank you in advance for any help.

Piermario
GeneralNot popping registers when exception thrown
LeoMaheo
5:27 18 Jun '08  
Concerning IsInsideVMWare(),

Is it harmless that these registerst aren't popped from stack if the exception is thrown?
pop ebx
pop ecx
pop edx

(That code isn't run in that case, am I correct?)

Thanks, Magnus

GeneralVB6
bitpusher1010
9:30 22 Apr '08  
How can I interface with the supplied DLL within VB6? Using the 'Dependency Walker' on the supplied DLL shows nothing is exported. Thanks for all replies.
GeneralRe: VB6
lallous
3:39 23 Apr '08  
hi,

The provided DLL is a COM object, please refer to the C# sample on how to use it.

Good luck,
Elias
Generalanother approach...
NikoTanghe
5:42 17 Dec '07  
If you want the user to prevent running multiple instances of your application, and your application requires a network connection, maybe it's better to broadcast some TCP/IP messages and try to find your own program on the same intranet. You can even make it more trickier by failing to start if another instance is found, or when the application is blocked by a firewall.

So you know how many instances there are running and this is guaranteed to work with all virtual machine flavors.
<< Nearly all men can stand adversity, but if you want to test a man's character, give him power. >>

GeneralVS 2008 Project
great_scandinavian
11:52 16 Dec '07  
Hi there,

It would be great if you could provide a 2008 based solution zip file, as I am having problems using it under VS 2008.

I used it before under 2005 where it worked great.

Thank you for your great work,

LP
GeneralThis is not best practice approach at all
nbk33r1
18:53 24 Jun '07  
Having extensive knowledge in both development and design of virtual systems, I feel I should point out that having any code specific to virtualization is not good. It implies a number of issues are not being addressed in your code, including, 1) weak resource control, 2) poor develop methods, 3) lack of understanding of how to write effective and efficient code for its own sake.

So many programmers now write for speed and time to market, at the expense of quality. Microsoft included in the very development of its operating system is guilty of this as well.

The goal of software design is to be resource effective, and time efficient, as applicable to the application design, not just the environment it whch your software runs. I would suggest rather than writing virtual machine versus non-virtual machine code, you write good code that works regardless of where it is hosted.

In the long run good code saves time and money, and improves the relationship with your customers more than anything else, This is something that seems to have been forgotten relatively recently by various firms that do nothing but chase deadlines and release dates over quality of code.
GeneralRe: This is not best practice approach at all
Yogesh P. Dhakad
23:19 12 Oct '07  
Hi nbk33r1,

I normally do not erupt out in my responses on CP, but I was just wondering - why those people who did rate this article as 5 are keeping quite, and hence this response from me (since I have also voted the author a FULL FIVE!)

Now - what you have said is very much appreciated but if you look at the _NEED_ of people - detect whether my product is running inside a Virtaul Machine or not. Hopefully they (atleast I) want to _avoid_ customers to run the product inside a virtual machine. Now why we need this is very well justified - keep up our business not leaking resources and memory ($).

The author has definitely presented to us a solution that _works_. Atleast I could quickly check it on VMWare and it did detect the presence of Virtual Machine.

People have their own plans (and agenda) man and the comments from someone like you really puzzle us for a while. I have actually successfully integrated this check not only in my product code, but I would prohibit this happening in my installer itself. Is that not what I originally wanted to have? The author has done everything that would make .NET programmers happy. For me (a C++ person) I quickly took his two functions and wrapped them inside a Win32 DLL (so that it has no dependency on any NON-OS dlls) and then applied a trick to return a secret code as a return value to the DetectVM function. The installer code successfully calls this function from a Win32 DLL (the function obviously exported out properly from the DLL) and based on the return value decides whether or not to go ahead with the installation.

Since you have taken time to put down your thoughts in a very nice way, please enlighten us some more on whether you are suggesting another solution for us, or are you suggesting NOT using this very check at all. If you are suggesting the latter, then I hope you will end up having less number of followers. Thanks.

Best regards,
Yogesh Dhakad
GeneralRe: This is not best practice approach at all
cgurtler
10:29 10 Feb '09  
What a load of rubbish. Unfortunately I have a library from a third party supply that does not work properly under Virtual PC because the USB ports are not supported. I have no control over the supplier and I have to deactivate features when it runs under Virtual PC. The code here is wonderful for my application, I thank the author.
GeneralDetecting number of Virtual PC
Fergal Cassidy
2:16 29 Mar '07  
Is there any way of detecting the number of currently running virtual PC from within the Virtual PC or from the host PC.
GeneralRe: Detecting number of Virtual PC
lallous
2:31 29 Mar '07  
No idea.
Perhaps you can try a dirty hack by trying to enumerate VPC's windows (from the host) and checking how many windows are of the class type of the VPC guest instance.
QuestionVirtualPC asm version problem
J.B.
17:41 22 Aug '06  
Hi,

First of all, thanks for this great article. The detection methods work really well.
However, I am having problems using the asm version for VPC detection bool IsInsideVPC_asm(). In debug mode compilation, it works fine. In release mode tho, it would generate illegal instruction error upon the point of VPC calling:

// call VPC 
_asm __emit 0Fh
<---- 0xC000001D: Illegal Instruction
_asm __emit 3Fh
_asm __emit 07h
_asm __emit 0Bh
]

this exception is not caught by exception_handler

I am using VC 2005

Any ideas?
Thanks in advance,
J.B.
GeneralAnother wholly different way...
Antoine Leca
4:53 21 Dec '05  
Very nice stuff.

While reading it, I was wondering about the "other" emulators or virtual environments, and it seems to me a good way to do it is to measure the time elapsed for say several additions (should run at full emulation speed), then several calculated jumps (jmp to register contents), then compute the ratio.
The latter should fault under any emulator and so should show a very important speed degradation. While the branch predictions of the processors should OTOH give good throughputs, at least so I believe.

Translated to C-like programming languages, calculated jumps are written switch(some_quantity); of course you probably have to make it volatile to avoid compiler optimising.

Antoine
GeneralRe: Another wholly different way...
lallous
21:46 21 Dec '05  
Hello Antoine,

If I understand you well, you're alluding to the fact that one can detect a VM through speed degradation?

--
Elias
GeneralRe: Another wholly different way...
Antoine Leca
23:25 25 Dec '05  
Yes
GeneralDoesn't seem to work under VPC7.01
rssmsvc
10:41 25 Apr '05  
Crashes out and doesn't seem to work under VPC 7.01.

I am running .Net 2003 under virtual PC under OSX 10.3.9
GeneralRe: Doesn't seem to work under VPC7.01
rssmsvc
20:04 25 Apr '05  
Also, running XP PRO
Virtual PC 7.01
.Net 2003
GeneralRe: Doesn't seem to work under VPC7.01
rssmsvc
20:57 25 Apr '05  
Also, I rebuilt on a native XP machine and when pressing the 2 buttons both fail correctly. However under VPC 7.01 the VMWare comes back as not found but the Virtual PC button crashes the app.
GeneralOf course yes
Maxim Alekseikin
3:08 17 May '06  
it woun't work on NT/XP/2005+ systems. this code uses in instruction Smile
you need to create a kernel mode driver for it.

School Management System


Last Updated 5 Apr 2005 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010