有没有办法从VM中识别您的代码在VM中运行?
我想有多种或多种简单的方法来识别特定的VM系统,特别是如果VM安装了提供程序的扩展(例如VirtualBox或VMWare)。但有没有一种通用的方法可以确定您没有直接在CPU上运行?
答案 0 :(得分:20)
许多关于此的研究致力于检测所谓的“蓝色药丸”攻击,即恶意的管理程序,它正在积极地试图逃避检测。
检测VM的经典技巧是填充ITLB,运行必须虚拟化的指令(当它控制管理程序时必须清除此类处理器状态),然后运行一些更多代码来检测ITLB是否仍然填充。关于它的第一篇论文位于here,而researcher's blog和替代Wayback Machine link to the blog article (images broken)的解释相当丰富。
讨论这个问题的最后一点是总有办法检测恶意虚拟机管理程序,并且检测一个不想隐藏的虚拟机管理程序要简单得多。
答案 1 :(得分:11)
Red Hat有一个程序可以检测它运行的虚拟化产品(如果有的话):virt-what
。
使用第三方维护的工具,这是一个比试图推出自己的检测逻辑更长远的策略:更多的眼睛(针对更多虚拟化产品进行测试)等。
答案 2 :(得分:6)
更经验的方法是检查已知的VM设备驱动程序。您可以编写WMI查询来查找VMware显示适配器,磁盘驱动器,网络适配器等。如果您知道只需要担心环境中已知的VM主机类型,那么这将是合适的。这是an example of doing this in Perl,可以移植到您选择的语言。
答案 3 :(得分:4)
这取决于你的目标:
如果VM没有故意隐藏您,您可以使用一些已知的挂钩。 LIke寻找VmWare驱动程序或在内存中存在某些字符串或某些其他告示标志。
如果VM真的希望你为它做特殊事情,它会有一些明显的钩子,比如修改处理器的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,但如果尝试足够努力,检测很可能总是会赢。
答案 4 :(得分:2)
我曾经遇到一个汇编代码片段,告诉你你是否在虚拟机中....我用Google搜索但找不到原始文章。
我确实找到了这个:Detect if your program is running inside a Virtual Machine。
希望它有所帮助。
答案 5 :(得分:1)
在大多数情况下,你不应该尝试。除了少数特定情况外,您不应该关心某人是否在VM中运行您的代码。
如果需要,在Linux中,最常见的方法是查看/sys/devices/virtual/dmi/id/product_name
,它将列出大多数实际系统上的笔记本电脑/主板的名称,以及大多数虚拟系统上的虚拟机管理程序。 dmidecode | grep Product
是另一种常用方法,但我认为这需要root访问权限。
答案 6 :(得分:1)
这是一种( java + windows )解决方案,用于识别基础计算机是物理计算机还是虚拟计算机。
虚拟机示例:
制造商
模型
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());
}
}
您可以使用输出来确定它是VM还是物理机:
物理机输出:
BIOS序列号:2HC3J12
硬件型号:Inspiron灵越7570
硬件制造商:Dell Inc.
虚拟机输出:
BIOS序列号:0
硬件型号:Innotec GmBH
硬件制造商:Virtual Box
答案 7 :(得分:0)
一个很好的例子就是显然是为主板制造商做了一个WMI查询,如果它返回“Microsoft”,你就在VM中。我以为我相信这只适用于VMWare。可能有不同的方法来判断每个VM主机软件。
这篇文章http://blogs.technet.com/jhoward/archive/2005/07/26/407958.aspx有一些很好的建议和链接,可以通过几种方法来检测你是否在虚拟机中(至少是VMWare和VirtualPC)。
答案 8 :(得分:0)
您可以通过查看网络连接的MAC地址来确定您是否在虚拟机中。例如,Xen通常建议使用特定范围的地址00:16:3e:xx:xx:xx。
这不能保证,因为由系统管理员来指定他们喜欢的MAC地址。
答案 9 :(得分:0)
TrapKIT provides ScoopyNG, a tool for VMware identification - 它试图解决逃避技术,但不一定针对VMware以外的任何虚拟化软件。源代码和二进制文件都可用。
答案 10 :(得分:0)
在Linux系统中,您可以尝试在/ proc。
上搜索公共文件例如,/ proc / vz /的existente告诉你是一个OpenVZ。
Linux下的答案 11 :(得分:-1)
如果VM能够很好地完成工作,那么客户端对它进行虚拟化应该是不可见的。但是,人们可以看一下其他线索。
我认为寻找特定于VM环境的已知驱动程序或软件将是最佳方式。
例如,在运行Windows的VMWare客户端上,vmxnet.sys将是网络驱动程序,显示为VMware加速AMD PCNet适配器。