34

有没有办法从 VM 中识别您的代码在 VM 中运行?

我想有或多或少简单的方法来识别特定的 VM 系统,特别是如果 VM 安装了提供程序的扩展(例如 VirtualBox 或 VMWare)。但是有没有一种通用的方法来识别你没有直接在 CPU 上运行?

4

12 回答 12

26

很多这方面的研究都致力于检测所谓的“蓝色药丸”攻击,即积极试图逃避检测的恶意管理程序。

检测 VM 的经典技巧是填充 ITLB,运行必须虚拟化的指令(当它将控制权交给管理程序时,这必然会清除此类处理器状态),然后运行更多代码来检测 ITLB 是否仍然填充. 关于它的第一篇论文位于此处,研究人员的博客和替代Wayback Machine 链接到博客文章的一个相当丰富多彩的解释(图像损坏) 。

对此讨论的底线是,总有一种方法可以检测到恶意虚拟机管理程序,而且检测不试图隐藏的虚拟机管理程序要简单得多。

于 2008-09-02T14:13:47.250 回答
12

Red Hat 有一个程序可以检测它在哪个(如果有的话)虚拟化产品下运行:virt-what.

从长远来看,使用第三方维护的工具比尝试推出自己的检测逻辑更好:更多的眼睛(针对更多的虚拟化产品进行测试)等。

于 2008-09-20T15:34:49.670 回答
7

一种更具经验性的方法是检查已知的 VM 设备驱动程序。您可以编写 WMI 查询来定位 VMware 显示适配器、磁盘驱动器、网络适配器等。如果您知道您只需要担心环境中已知的 VM 主机类型,这将是合适的。这是在 Perl 中执行此操作的示例,可以将其移植到您选择的语言。

于 2008-09-02T13:53:12.900 回答
5

这取决于你追求的是什么:

  • 如果虚拟机不是故意隐藏的,你可以使用一些已知的钩子。比如寻找 VmWare 驱动程序或内存中是否存在某些字符串或某些其他迹象。

  • 如果虚拟机真的希望你为它做一些特殊的事情,它会有一些明显的钩子,比如修改处理器的 ID 或添加一些你可以访问的特殊寄存器来检测它。或者是内存中已知位置的特殊设备(假设您可以原始访问您的世界的物理内存空间)。请注意,IBM Power6 和 Sun UltraSparc T1/T2 等现代机器设计旨在始终运行虚拟机管理程序,而不是直接在原始硬件上运行。操作系统使用的“硬件”接口实际上是管理程序软件层的接口,无法绕过它。在这种情况下,检测是微不足道的,因为它是一个恒定的“是”。对于所有能够承受开销的计算机系统来说,这可能是未来的方向,

  • 如果 VM 故意试图隐藏,而您正在追逐它的存在,那么这就是一场猫捉老鼠的游戏,VM 的时间干扰和不同的性能配置文件几乎总是会泄露它。显然,这取决于 VM 是如何实现的,以及架构中有多少硬件支持(我认为 zSeries 大型机在隐藏特定操作系统下的 VM 或 VM 堆栈方面比常规 x86 更好)机器是,例如)。有关此主题的一些讨论,请参见http://jakob.engbloms.se/archives/97。可以尝试隐藏为 VM,但如果足够努力,检测很可能总是获胜。

于 2008-09-27T20:27:23.093 回答
3

在大多数情况下,您不应该尝试。您不应该关心是否有人在 VM 中运行您的代码,除非在少数特定情况下。

如果需要,在 Linux 中最常见的方法是查看/sys/devices/virtual/dmi/id/product_name,它将列出大多数真实系统上的笔记本电脑/主板的名称,以及大多数虚拟系统上的虚拟机管理程序。dmidecode | grep Product是另一种常用方法,但我认为这需要 root 访问权限。

于 2008-09-02T13:45:10.203 回答
3

我曾经遇到过一个汇编代码片段,它告诉你是否在虚拟机中……我用谷歌搜索但找不到原始文章。

我确实发现了这一点:Detect if your program is running inside a Virtual Machine

希望能帮助到你。

于 2008-09-02T13:54:44.050 回答
3

这是一个(java + windows)解决方案,用于识别底层机器是物理机还是虚拟机。

虚拟机示例:

制造商

  • 微软公司
  • 英诺特有限公司
  • 红色的帽子
  • VMware, Inc.

模型

  • HVM domU
  • 虚拟机
  • 虚拟盒子
  • 虚拟机
  • VMware 虚拟平台

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.List;
    
    public abstract class OSUtil {
    
    public static final List<String> readCmdOutput(String command) {
        List<String> result = new ArrayList<>();
    
        try {
            Process p=Runtime.getRuntime().exec("cmd /c " + command);
            p.waitFor();
            BufferedReader reader=new BufferedReader(
                    new InputStreamReader(p.getInputStream())
                    );
            String line;
            while((line = reader.readLine()) != null) {
                if(line != null && !line.trim().isEmpty()) {
                    result.add(line);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    
        return result;
    }
    
    public static final String readCmdOutput(String command, int lineNumber) {
        List<String> result = readCmdOutput(command);
        if(result.size() < lineNumber) {
            return null;
        }
    
        return result.get(lineNumber - 1);
    }
    
    public static final String getBiosSerial() {
        return readCmdOutput("WMIC BIOS GET SERIALNUMBER", 2);
    }
    
    public static final String getHardwareModel() {
        return readCmdOutput("WMIC COMPUTERSYSTEM GET MODEL", 2);
    }
    
    public static final String getHardwareManufacturer() {
        return readCmdOutput("WMIC COMPUTERSYSTEM GET MANUFACTURER", 2);
    }
    
    public static void main(String[] args) {
        System.out.println("BIOS Serial: " + getBiosSerial());
        System.out.println("Hardware Model: " + getHardwareModel());
        System.out.println("Hardware Manufacturer: " + getHardwareManufacturer());
    }
    }
    

您可以使用输出来确定它是虚拟机还是物理机:

物理机输出:

BIOS 序列号:2HC3J12
硬件型号:Inspiron 7570
硬件制造商:Dell Inc.

虚拟机输出:

BIOS 序列号:0
硬件型号:Innotec GmBH
硬件制造商:Virtual Box

于 2018-06-20T10:11:42.977 回答
0

如果它的虚拟机做得很好,它应该对客户端不可见,它正在被虚拟化。但是,可以查看其他线索。

我想寻找特定于 VM 环境的已知驱动程序或软件将是最好的方法。

例如,在运行 Windows 的 VMWare 客户端上,vmxnet.sys 将是网络驱动程序,显示为 VMware 加速 AMD PCNet 适配器。

于 2008-09-02T13:50:17.087 回答
0

一个很好的例子是,显然对主板制造商进行了 WMI 查询,如果它返回“Microsoft”,那么你就在 VM 中。以为我相信这仅适用于VMWare。对于每个 VM 主机软件,可能有不同的方法来判断。

这篇文章在这里http://blogs.technet.com/jhoward/archive/2005/07/26/407958.aspx有一些很好的建议和链接到几种方法来检测你是否在虚拟机中(VMWare 和 VirtualPC 在至少)。

于 2008-09-02T13:52:26.147 回答
0

您可以通过查看网络连接的 MAC 地址来确定您是否在虚拟机中。例如,Xen 通常建议使用特定范围的地址 00:16:3e:xx:xx:xx。

这不能保证,因为系统管理员可以指定他们喜欢的 MAC 地址。

于 2008-09-02T13:53:27.517 回答
0

TrapKIT 提供了 ScoopyNG,这是一种 VMware 识别工具——它试图绕过规避技术,但不一定针对 VMware 以外的任何虚拟化软件。源代码和二进制文件都可用。

于 2010-07-30T19:11:47.550 回答
0

在 Linux 系统中,您可以尝试在 /proc 上搜索常用文件。

例如,/proc/vz/ 的存在告诉你是一个 OpenVZ。

这是在 Linux 下检测 VM 环境的完整指南,无需“喝药”:)

于 2013-11-26T20:19:10.040 回答