在Linux上检测VMM [英] Detecting VMM on linux

查看:157
本文介绍了在Linux上检测VMM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想检测我是否在虚拟环境中运行(VMware的,VirtualBox的,等等)结果
在Windows上我有几个使用ASM但我不能在Linux中使用它们,主要是因为code可能会被编译并在32位或64位运行Linux。

I'm trying to detect whether I am running on a virtual environment (vmware, virtualbox, etc)
On Windows I've use several ASM but I can't use them in Linux, mainly because the code might be compiled and run on either 32 or 64 bit Linux.

以下code适用于Windows 32和64都和VMWare的,VirtualBox和其他虚拟机进行了测试:

The following code works on both Windows 32 and 64 and was tested on VMWare, virtualbox and other virtual machines:

#include <stdio.h> 

int idtCheck () 
{ 
    unsigned char m[2]; 
    __asm sidt m; 
    printf("IDTR: %2.2x %2.2x\n", m[0], m[1]); 
    return (m[1]>0xd0) ? 1 : 0; 
} 

int gdtCheck() 
{ 
    unsigned char m[2]; 
    __asm sgdt m; 
    printf("GDTR: %2.2x %2.2x\n", m[0], m[1]);
    return (m[1]>0xd0) ? 1 : 0; 
} 

int ldtCheck() 
{ 
    unsigned char m[2]; 
    __asm sldt m; 
    printf("LDTR: %2.2x %2.2x\n", m[0], m[1]); 
    return (m[0] != 0x00 && m[1] != 0x00) ? 1 : 0; 
} 

int main(int argc, char * argv[]) 
{ 
    idtCheck(); 
    gdtCheck(); 

    if (ldtCheck()) 
        printf("Virtual Machine detected.\n"); 
    else 
        printf("Native machine detected.\n"); 

    return 0; 
}

现在,海湾合作委员会抱怨的所有功能的__asm​​。我试着用ASM()的 ASM 的等形式,我在过去但没有工作使用。任何想法?

now, GCC complains about the __asm on all the functions. I tried with asm(), asm and other forms that I used in the past but none work. Any ideas?

推荐答案

好了,我还没有拆开机器code在那里,但这里使用GCC内联汇编版本:

Well, I haven't disassembled the machine code in there, but here's a version using GCC inline assembler:

int redpill()
{
        unsigned char idt_addr[(sizeof(long)==8)?10:6];
        __asm__("SIDT (%[ptr])"
                        : "=m" (idt_addr)
                        : [ptr] "r" (&idt_addr));
        // examine high order byte
        return idt_addr[(sizeof(long)==8)?9:5] > 0xd0;
}

此的的甚至是64位的'工作',但我没有测试它。

This should 'work' even for 64-bit, but I've not tested it there.

但!这并不能保证给你想要的结果,所有的。首先,它不会与硬件虚拟化工作,因为你无法看到真实的IDT。其次,它依靠的VMWare和Virtual PC的实现细节,这也许可以很容易地改变。如果你的操作系统决定把它的IDT在一个较高的地址,甚至可能会揭开序幕误报。所以我根本不推荐这种方法。

HOWEVER! This isn't guaranteed to give the result you want, at all. First, it won't work with hardware virtualization, as you can't see the true IDT. Second, it relies on an implementation detail of VMWare and Virtual PC, which could probably be changed quite easily. It might even kick off false alarms if your OS decides to put its IDT at a high address. So I don't recommend this approach at all.

有关使用VMX硬件支持的虚拟机,可能是你最好的选择将是做一些应该是快速的硬件,但需要在虚拟机陷阱,并检查计时。像 CPUID 的东西将是一个不错的选择;基准它在一个虚拟机,并​​在真实的硬件(针对虚拟环路,做一个ADD或东西来处理不同的时钟速率相比),看试机更加匹配的配置文件。由于每个 CPUID 将不得不退出VM要求主机内核就是了present哪些功能,它会占用大量的时间比实际硬件。

For virtual machines using the VMX hardware support, probably your best bet would be to do something which should be fast in hardware but require a trap in a virtual machine, and check the timing. Something like CPUID would be a good bet; benchmark it in a VM and on real hardware (compared against a dummy loop that does an ADD or something to deal with differing clock rates), and see which profile the test machine more closely matches. Since each CPUID will have to exit the VM to ask the host kernel what capabilities it wants to present, it will take a LOT longer than on real hardware.

对于其他类型的虚拟机,你可以简单地通过加载控制寄存器或调试寄存器做一个类似的定时检查 - 虚拟机将捕获它,或者用仿真code替换它。如果你的东西像VMware,它可能会取代一些模拟code中的陷阱 - 在这种情况下,你可能能够通过定时,以确定它的修改的包含code中的控制寄存器或调试寄存器的操作。这将迫使VM无效的缓存code,因此需要昂贵的陷阱虚拟机,这将显示在您的基准。

For other kinds of virtual machines, you could do a similar timing check simply by loading a control register or debug register - the VM will have to trap it, or replace it with emulated code. If you're on something like VMware, it might replace the trap with some emulated code - in this case, you might be able to identify it by timing modifying the code containing the control register or debug register operation. This will force the VM to invalidate its cached code, necessitating an expensive trap to the VM, which will show up on your benchmark.

请注意,这两种方法都需要从操作系统内核的帮助 - 这将是的非常的难以确定,如果你在一个虚拟机是,如果你不具备模拟控制内核至少。如果虚拟机是真正成熟的,它可能假定时,同时,在这点事情变得很困难的 - 但是这往往杀性能,并导致时钟漂移(容易辨认,如果你可以连接到互联网,查询时间服务器的地方!),所以大部分的商业虚拟机没有做到这一点。

Note that both of these approaches will require help from the OS kernel - it is going to be very hard to determine if you're in a VM if you don't have control of the emulated kernel at least. And if the VM is really sophisticated, it might fake timing as well, at which point things get really difficult - but this tends to kill performance, and result in clock drift (easy to identify if you can connect to the internet and query a time server somewhere!), so most commercial VMs don't do it.

这篇关于在Linux上检测VMM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆