【问题标题】:How to identify that you're running under a VM?如何识别您在 VM 下运行?
【发布时间】:2008-09-02 13:39:47
【问题描述】:

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

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

【问题讨论】:

  • 您是在寻找理论答案(即论文或算法,需要实现,提供一种旨在防止不太可能发生的攻击的机制)还是实际答案(即旨在处理的工作代码非恶意的常见案例)?
  • 你做的事情是,你随身携带一件小东西,而且你不允许别人碰。如果感觉正确并且行为正确,那么您就没有在 VM 中运行。(无法抗拒。抱歉。)

标签: virtualization


【解决方案1】:

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

检测 VM 的经典技巧是填充 ITLB,运行 必须 虚拟化的指令(当它将控制权交给管理程序时必然会清除此类处理器状态),然后运行一些更多代码来检测 ITLB 是否仍被填充。第一篇论文位于here,来自researcher's blog 和替代Wayback Machine link to the blog article (images broken) 的一个相当丰富的解释。

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

【讨论】:

  • 我不确定给定的方法是否适用于使用 NPT/EPT 的主机。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 我的电脑 -> 属性 -> 硬件 -> 设备管理器看看显示适配器 - 你通常会看到 microsoft VM 或 VMWare 的东西...
    • 虚拟化系统可以并且确实可以模拟真实的硬件(即使它通常是旧的/过时的硬件;特别是对于视频驱动程序而言,Matrox 模拟很常见,虽然几乎再也没有在桌面上找到过——但它们的芯片组也用于具有 KVM 远程处理的服务器芯片组,因此它们也可能发生在非虚拟化情况下),或者甚至可以进行 PCI 直通以提供 VM 对真实显卡的完全控制。 (一些高端网卡有多个 PCI 端点,让虚拟机可以完全控制真实物理网卡的子集)。
    【解决方案4】:

    这取决于你追求什么:

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

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

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

    【讨论】:

      【解决方案5】:

      我曾经遇到过一个汇编代码 sn-p,它会告诉您您是否在虚拟机中....我用谷歌搜索但找不到原始文章。

      我确实找到了这个:Detect if your program is running inside a Virtual Machine

      希望对你有帮助。

      【讨论】:

      【解决方案6】:

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

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

      【讨论】:

        【解决方案7】:

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

        虚拟机示例:

        制造商

        • Xen
        • 微软公司
        • innotek GmbH
        • 红帽
        • VMware, Inc.

        型号

        • HVM domU
        • 虚拟机
        • 虚拟盒子
        • KVM
        • 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
        硬件制造商:戴尔公司。

        虚拟机输出:

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

        【讨论】:

        • 我也会为 linux 实现这个解决方案,但我需要一个最著名的虚拟系统的模型列表,你认为我可以在哪里找到它
        • 答案中的列表涵盖了最广泛使用的虚拟化软件。
        • @LukasOwen 查看虚拟机列表:en.wikipedia.org/wiki/…
        【解决方案8】:

        如果它的虚拟机能很好地完成这项工作,它应该对客户端来说是不可见的,它正在被虚拟化。不过,可以看看其他线索。

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

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

        【讨论】:

          【解决方案9】:

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

          这篇文章http://blogs.technet.com/jhoward/archive/2005/07/26/407958.aspx 提供了一些很好的建议和一些链接,可以用来检测您是否在虚拟机中(至少是 VMWare 和 VirtualPC)。

          【讨论】:

            【解决方案10】:

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

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

            【讨论】:

            • 此外,任何 VM 公司都可以随时注册新的 MAC 地址编号范围。 VMWare 目前有 4 个不同的 MAC 范围(根据在 ieee.org 中搜索分配的编号。)。
            【解决方案11】:

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

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

            Here's a full guide to detect VM's environent在Linux下不用“吃药”:)

            【讨论】:

              【解决方案12】:

              TrapKIT provides ScoopyNG, a tool for VMware identification -- 它试图绕过规避技术,但不一定针对除 VMware 之外的任何虚拟化软件。源代码和二进制文件都可用。

              【讨论】:

              • 那是……一个相当稀疏的答案,正如最初写的那样。
              猜你喜欢
              • 2018-05-16
              • 2022-12-11
              • 2018-04-17
              • 2021-11-28
              • 1970-01-01
              • 2014-11-03
              • 2021-04-09
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多