首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在linux上检测VMM

在linux上检测VMM
EN

Stack Overflow用户
提问于 2010-09-08 14:33:50
回答 1查看 1.6K关注 0票数 1

我正在尝试检测是否运行在虚拟环境(vmware、virtualbox等)上。

在Windows上,我使用了几个ASM,但我不能在Linux中使用它们,主要是因为代码可能在32位或64位Linux上编译和运行。

以下代码在Windows 32和64上运行,并在VMWare、virtualbox和其他虚拟机上进行了测试:

代码语言:javascript
复制
#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; 
}

现在,GCC抱怨__asm的所有功能。我尝试过使用asm()、asm和其他我在过去使用过的表单,但是没有一种有效。有什么想法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2010-09-08 15:18:09

嗯,我还没有拆解里面的机器代码,但是这里有一个使用GCC内联汇编程序的版本:

代码语言:javascript
复制
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位,但我还没有测试它。

不过!这并不能保证给出你想要的结果。首先,它不适用于硬件虚拟化,因为您无法看到真正的IDT。其次,它依赖于VMWare和Virtual的实现细节,这可能很容易更改。如果你的操作系统决定把它的IDT放在一个高地址上,它甚至可能会发出错误的警报。所以我根本不推荐这种方法。

对于使用VMX硬件支持的虚拟机,最好的选择可能是做一些在硬件上应该很快但需要在虚拟机中设置陷阱的事情,并检查时间。像CPUID这样的东西是个不错的选择;在VM和实际硬件上对其进行基准测试(与处理不同时钟速率的虚拟循环进行比较),并查看哪个配置文件与测试机器更接近匹配。由于每个CPUID都必须退出VM才能询问主机内核它想要提供什么功能,所以它将花费比实际硬件更长的时间。

对于其他类型的虚拟机,您可以简单地通过加载控制寄存器或调试寄存器来执行类似的定时检查-- VM将不得不捕获它,或者用模拟代码替换它。如果您所处的位置类似于VMware,它可能会用一些模拟代码替换陷阱--在本例中,您可以通过定时修改包含控制寄存器或调试寄存器操作的代码来识别它。这将迫使VM使其缓存的代码失效,这就需要对VM设置一个昂贵的陷阱,这将显示在您的基准测试中。

请注意,这两种方法都需要操作系统内核的帮助--如果您至少没有对模拟内核的控制,那么很难确定您是否在VM中。如果VM真的很复杂的话,它可能还会伪造时间,这时事情变得非常困难--但这往往会破坏性能,并导致时钟漂移(如果您可以连接到internet并在某个地方查询时间服务器,那么就很容易识别),所以大多数商业VM都不会这么做。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3668804

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档