如何检查我的Java程序是否在虚拟机中运行?

时间:2013-08-08 09:40:28

标签: java c++ virtual-machine jna

我有一个需要获得客户许可的Java软件。我创建了一个许可模块,它只允许软件在激活它的特定硬件上执行。

但是,我不希望客户端激活虚拟机内的软件,这意味着可以使用单个许可证来使用该软件的多个副本。

如何阻止我的软件安装在虚拟机中?

注意:

  1. 我已经对此进行了研究,并且已经找到了解决方案。我在这里发帖,以便它可能有用 其他开发者。
  2. 仅适用于VmWareVirtual PC不适用于ParallelsVirtualBox
  3. 我无法找到纯Java解决方案。它依赖于本机代码。
  4. 如果您知道更好的解决方案,请将其作为答案发布。

1 个答案:

答案 0 :(得分:8)

检查VM存在的一些方法是 -

  1. 查找虚拟机工件(如虚拟机访客工具
  2. 所生成的虚拟机工件,如进程,文件,注册表项)
  3. 使用虚拟化软件公开的非标准x86指令
  4. 如果您想了解更多信息,可以参考here讨论这些主题。

    由于方法2是最简单直接的,我们将使用它。

    以下代码段可用于检查代码是否在VMware虚拟机中运行 -

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

    这是从Code Project发布的项目中获取的代码的一部分。用于演示它不包括检查Microsoft Virtual PC的存在的代码。您可以访问主站点以获取Virtual PC的代码和预编译的演示。该网站上还提供了一个DLL,但具有讽刺意味的是,这些函数不会被导出,这会破坏DLL的目的,因为您无法在程序中调用它。因此,我必须自己编译上面的代码并创建一个DLL。

    __try__catch是Microsoft特定的C ++扩展。您需要在Windows上使用Visual Studio进行编译,因为使用gcc将无效。

    下载并安装以下组件 -

    1. Visual Studio 2005(或更高版本)
    2. Microsoft Platform SDK 2003
    3. 创建一个新的DLL项目并将上述代码粘贴到主CPP文件中。

      将此添加到您的代码中以导出您的功能。如果没有这个,您的DLL将被编译,但函数将无法从外部调用。

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

      现在通过构建Visual Studio项目来编译DLL。如果您收到windows.h未找到的错误或其他错误,请参阅这些stackoverflow问题 -

      要检查函数是否已导出到DLL,您可以使用DLL Export Viewer查看DLL导出(即公开)的函数列表。

      现在我们有了检查VM存在的组件。我们需要做的就是从Java中调用它。

      下载从Java调用本机代码所需的JNA库。 创建Eclipse项目并将DLLJNA添加到类路径。

      创建以下文件 -

      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.");
          }
      }
      

      以下是显示在VM中运行的最终代码的屏幕截图 - enter image description here