如何检查我的 Java 程序是不是在虚拟机中运行? [复制]

Posted

技术标签:

【中文标题】如何检查我的 Java 程序是不是在虚拟机中运行? [复制]【英文标题】:How do I check if my Java program is running in a virtual machine? [duplicate]如何检查我的 Java 程序是否在虚拟机中运行? [复制] 【发布时间】:2013-08-08 09:40:27 【问题描述】:

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

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

如何阻止我的软件安装在 VM 中?

注意:

    我已经对此进行了研究,并且已经找到了解决方案。我在这里发布它,以便它可能对 其他开发者。 它仅适用于VmWareVirtual PC 不适用于ParallelsVirtualBox 我找不到纯 Java 解决方案。它依赖于本机代码。

如果您知道更好的解决方案,请将其作为答案发布。

【问题讨论】:

从技术上讲当然是个有趣的问题,但是为什么让您的付费客户使用该软件比盗版的非付费用户更难使用这个 DRM 的盗版版本呢?或者,可能更重要的是,为什么要以此吓跑潜在客户?并增加支持成本以帮助用户运行他们的许可程序,因为一些损坏的 DRM 认为他们没有获得许可(请记住,每个程序都有错误,DRM 也不例外)。 @Thilo 我们产品的尺寸并不大。您不会在互联网上找到我们软件的盗版副本。我们的目标不是设计一种 100% 万无一失的方法,而是确保使用我们的软件不像复制粘贴那么简单。 而一个简单的许可证密钥解决方案不能达到同样的效果? @Thilo 如果他们使用的是现在每个人都在使用的虚拟机,则不会。我们要做的就是将我们的软件破解难度提高到客户不会打扰并支付许可费的水平,这也可以获得他们的支持。 AFAIK 这就是为什么即使像微软和 Adob​​e 这样的大牌也这样做的原因。 如果他们使用虚拟机并且有意识地决定违反您的许可,则不会。另一方面:如果现在每个人都在使用虚拟机,他们会很高兴你强迫他们不再这样做。 【参考方案1】:

检查虚拟机是否存在的一些方法是 -

    查找是否存在 VM 工件,例如由 VM Guest 工具生成的进程、文件、注册表项 使用虚拟化软件公开的非标准 x86 指令

如果您想了解更多信息,有一个很好的演示文稿讨论了这些主题here。

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

下面的代码sn -p可以用来检查代码是否在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 将不起作用。

下载并安装以下组件 -

    Visual Studio 2005(或更高版本) 微软平台 SDK 2003

创建一个新的 DLL 项目并将上述代码粘贴到主 CPP 文件中。

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

extern "C" __declspec(dllexport) 
bool IsInsideVMWare()

  //Code

现在通过构建 Visual Studio 项目来编译 DLL。如果您遇到windows.h not found 之类的错误或其他错误,请参阅这些 *** 问题 -

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

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

现在我们有了检查虚拟机是否存在的组件。我们需要做的就是从 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 中运行的最终代码的屏幕截图 -

【讨论】:

以上是关于如何检查我的 Java 程序是不是在虚拟机中运行? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Java为什么要在虚拟机中运行

java 后台线程自己断掉一般是啥由原因引起的?

如何解决虚拟机不能启动的问题

如何在虚拟机中运行 YOCTO LINUX 操作系统

java虚拟机中的对象的创建

Java虚拟机中获得Runtime实例的方法是什么?