Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I check if my Java program is running in a virtual machine? [duplicate]

I have a Java software that needs to be licensed to clients. I have created a licensing module that would only allow the software to be executed on a specific hardware on which it was activated.

However I don't want the client to activate the software inside a Virtual Machine which would mean that multiple copies of the software could be used with a single license.

How do I stop my software from being installed in a VM?

Note:

  1. I have done research on this and already found a solution. I'm posting it here so that it may be useful to other developers.
  2. It works only for VmWare and Virtual PC not on Parallels or VirtualBox
  3. I couldn't find a pure Java solution. It relies on native code.

If you know a better solution please post it as an answer.

like image 428
Kshitiz Sharma Avatar asked Aug 08 '13 09:08

Kshitiz Sharma


1 Answers

Some methods to check presence of a VM are -

  1. Looking for presence of VM artifacts like processes, files, registry entries made by VM Guest tools
  2. Using non-standard x86 instructions exposed by Virtualization software

If you would like to know more, there is a good presentation that discusses these topics here.

Since method 2 is the easiest and straightforward we'd be using it.

Following code snippet can be used to check if the code is running in VMware Virtual Machine -

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;
}

This is a part of code taken from a project published on Code Project. Being meant for demonstration it does not include code to check presence of Microsoft Virtual PC. You can visit the main site to get code for Virtual PC and a pre-compiled demo. A DLL is also provided on that site but ironically the functions are not exported which defeats the purpose of DLL as you cannot call it in a program. Thus I had to compile the above code myself and create a DLL.

__try and __catch are Microsoft specific C++ extensions. You'll need to compile this with Visual Studio on Windows as using gcc will not work.

Download and install following components -

  1. Visual Studio 2005 (or higher)
  2. Microsoft Platform SDK 2003

Create a new DLL project and paste the above code into the main CPP file.

Add this to your code in order to export your function. Without this your DLL would get compiled but function would not be callable from outside.

extern "C" __declspec(dllexport) 
bool IsInsideVMWare()
{
  //Code
}

Now compile the DLL by building the Visual Studio project. In case you get errors like windows.h not found or other errors consult these stackoverflow questions -

  • Cannot open Windows.h
  • Why doesn't Visual Studio give me an option to create a DLL?
  • Why doesn't GCC compile this code?

To check whether the function has been exported to DLL or not you can use DLL Export Viewer to see list of functions exported (i.e. exposed) by your DLL.

Now we have our component that checks for presence of VM. All we need to do is call it from Java.

Download the JNA library which is needed to invoke native code from Java. Create an Eclipse Project and add the DLL and JNA to classpath.

Create following files -

VmCheck.java

package in.ksharma;

import com.sun.jna.Library;

public interface VmCheck extends Library {
    boolean IsInsideVMWare();
    boolean IsInsideVPC();
}

Test.java

package in.ksharma;

import com.sun.jna.Native;

public class Test {
    public static void main(String[] args) {
        VmCheck lib = (VmCheck) Native.loadLibrary("VmDetect.dll", VmCheck.class);
        if(lib.IsInsideVMWare() || lib.IsInsideVPC())
            System.out.println("I'm trapped in the matrix.");
        else 
            System.out.println("I'm for real.");
    }
}

Here is a screenshot showing the final code running in a VM - enter image description here

like image 97
Kshitiz Sharma Avatar answered Oct 19 '22 10:10

Kshitiz Sharma