关于虚拟化:如何识别您正在VM下运行?

关于虚拟化:如何识别您正在VM下运行?

How to identify that you're running under a VM?

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

我猜大概有一些简单的方法可以识别特定的VM系统,尤其是在VM已安装了提供程序的扩展名(例如VirtualBox或VMWare)的情况下。 但是,是否有一种通用方法可以确定您不是直接在CPU上运行?


关于此的大量研究致力于检测所谓的"蓝色药丸"攻击,即恶意的管理程序正在积极尝试逃避检测。

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

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


红帽有一个程序可以检测正在哪个虚拟化产品下运行(virt-what)。

从长远来看,使用这种第三方维护的工具比尝试使用自己的检测逻辑(例如,更多的眼睛(针对更多的虚拟化产品进行测试)等等)是一种更好的策略。


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


这取决于您所追求的:

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

  • 如果VM确实希望您为它做一些特殊的事情,它将有一些明显的挂钩,例如修改处理器的ID或添加一些您可以访问以检测它的特殊寄存器。或者在内存中一个已知的位置放置一个特殊的设备(假定您可以原始访问世界的物理内存空间)。注意,像IBM Power6和Sun UltraSparc T1 / T2这样的现代机器设计总是设计为运行虚拟机监控程序,而不是直接在原始硬件上运行。操作系统使用的"硬件"接口实际上是虚拟机管理程序软件层的接口,无法绕开它。在这种情况下,检测是微不足道的,因为它是恒定的"是"。对于所有负担得起的计算机系统来说,这是未来的可能方向,例如,以飞思卡尔QorIQ P4080芯片等最新设计的支持为例(www.freescale.com/qoriq)。

  • 如果虚拟机是有意试图隐藏的,而您正在追逐它的存在,那它是一种猫捉老鼠的游戏,其中,虚拟机的时序干扰和不同的性能特征几乎总是会把它丢掉。显然,这取决于VM的实现方式以及体系结构中有多少硬件支持(我认为zSeries大型机比常规的x86更好地隐藏了特定OS下的VM或VM堆栈的存在)例如,机器)。有关此主题的一些讨论,请参见http://jakob.engbloms.se/archives/97。可以尝试将其隐藏为VM,但是如果尝试足够努力,检测很可能总是会获胜。


这是一个(java + Windows)解决方案,用于识别基础计算机是物理的还是虚拟的。

虚拟机示例:

制造商

  • en
  • 微软公司
  • innotek GmbH
  • 红色的帽子
  • VMware,Inc.

模型

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    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());
    }
    }

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

物理机输出:

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

虚拟机输出:

BIOS序列号:0
硬件型号:Innotec GmBH
硬件制造商:虚拟盒子


我曾经遇到一个汇编代码片段,该片段告诉您您是否在VM中。...我用Google搜索,但找不到原始文章。

我确实发现了这一点:检测您的程序是否在虚拟机中运行。

希望能帮助到你。


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

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


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

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

这是完整的指南,用于检测Linux下VM的环境,而无需"喝药" :)


TrapKIT提供了ScoopyNG(一种用于VMware识别的工具),它试图解决规避技术,但不一定要针对VMware以外的任何虚拟化软件。源代码和二进制文件均可用。


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

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


一个很好的例子是,显然是在对主板制造商进行WMI查询,如果返回" Microsoft",则表示您在VM中。以为我相信这仅适用于VMWare。每种VM主机软件可能有不同的判断方法。

本文http://blogs.technet.com/jhoward/archive/2005/07/26/407958.aspx提供了一些不错的建议,并提供了一些链接来检测您是否在VM中(VMWare和VirtualPC位于最小)。


如果VM能够很好地完成工作,则客户端应该看不到它已被虚拟化。但是,可以看看其他线索。

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

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


推荐阅读