5

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.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Kshitiz Sharma
  • 17,947
  • 26
  • 98
  • 169
  • Interesting question technically of course, but why make it harder for your paying customers to use the software than the non-paying users of the pirated version that has this DRM stripped out? Or, probably even more important, why scare away potential customers with this? And increase the support cost to help users get their licensed program to run because of some broken DRM that thinks they are not licensed (remember, every program has bugs, and DRM is no exception). – Thilo Aug 08 '13 at 09:50
  • @Thilo The size of our Product is not that large. You wouldn't find pirated copy of our software on the internet. Our aim is not to devise a 100% foolproof method, but ensure that using our software isn't as simple as copy paste. – Kshitiz Sharma Aug 08 '13 at 09:54
  • And a simple license key solution won't achieve the same thing? – Thilo Aug 08 '13 at 09:55
  • @Thilo Not if they're using a VM which everyone does these days. All we want to do is to make cracking our software hard upto that level at which client just won't bother and pay the license fee, which also gets them the support. AFAIK that's why even the big names like Microsoft and Adobe do it. – Kshitiz Sharma Aug 08 '13 at 09:55
  • 2
    Not if they are using a VM *and make the conscious decision to violate your license*. And on the other side of the coin: If everyone these days is using a VM, they will be really happy that you force them to not do that anymore. – Thilo Aug 08 '13 at 09:57

1 Answers1

9

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 -

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

Community
  • 1
  • 1
Kshitiz Sharma
  • 17,947
  • 26
  • 98
  • 169