Virtual machine 如何以编程方式检测我正在哪个环(-1,0,1,2,3)中运行?

Virtual machine 如何以编程方式检测我正在哪个环(-1,0,1,2,3)中运行?,virtual-machine,Virtual Machine,如何以编程方式检测我在哪个环(-1,0,1,2,3)中运行?除非您是设备驱动程序,否则您将始终在环3中运行(对于本身具有“环”的系统)。最简单的方法是只运行(x86)命令并捕获相应的错误 例如(SEH、Windows、内核模式) bool ring\u lower\u 0=false; __试一试 { __asm{}; 环低0=真; } __EXCEPTION(GetExceptionCode()=异常专用指令) { 环低0=假; } 注: cmd,是一个汇编程序命令。有关命令及其各自的环级别

如何以编程方式检测我在哪个环(-1,0,1,2,3)中运行?

除非您是设备驱动程序,否则您将始终在环3中运行(对于本身具有“环”的系统)。

最简单的方法是只运行(x86)命令并捕获相应的错误

例如(SEH、Windows、内核模式)

bool ring\u lower\u 0=false;
__试一试
{
__asm{};
环低0=真;
}
__EXCEPTION(GetExceptionCode()=异常专用指令)
{
环低0=假;
}
注:

cmd,是一个汇编程序命令。有关命令及其各自的环级别的列表,请参阅《英特尔体系结构参考手册》

Linux有一个稍微不同的概念

但是请记住,驻留在较低级别的VM可能通过模拟调用来掩盖结果

(注意:VM的任务是将无效指令转换为有意义的调用)



如果您真的想检查您的应用程序是否已虚拟化,并希望因此停止执行,您应该阅读有关“红色药丸”的内容。

通常我会写您应该阅读有关“保护模式编程”的内容。有一篇文章介绍如何使用windows XP SP2与环0交互。请注意,对于其他windows版本和其他操作系统,它将发生更改

例如,如果您只想检测您是否在虚拟机内运行,以避免人们调试您的应用程序,您可以在此处进行检查:


环是64位x86体系结构中代码段选择器(CS)寄存器的下两位

您可以这样提取它:()

在demo-2中,我有一个Linux内核模块,它将执行相同的代码,但在环1的内核中:

:

您不能从内核驱动程序对控制台执行printf。相反,您需要将设备作为文件打开并从中读取:

cat /dev/lkm_example

我建议您循序渐进,这样您就可以看到它正在运行:)

WTF是环-1吗?我记得早期OS/2和受保护模式Windows时代的其他版本,但是-1在我身上是一个新版本。它是虚拟机监控程序,用于OSs的硬件虚拟化,已经在使用环0。好吧,我想这是有意义的。在我们开发操作系统时,没有虚拟机监控程序。谢谢,@one-by-one.ring-negative-one@Andrew:你想做什么?是这样吗?如果我是运行托管虚拟机监控程序的操作系统的设备驱动程序呢?我是否会与主机系统和虚拟机监控程序一起运行在环1中?deamons是在另一个帐户下运行的用户模式程序。root也是另一个帐户。”真正的“驱动程序”在内核模式下运行(大部分是环0,因为现在很少使用环1+2)。@Andrew:粗鲁,粗鲁。是的,就是这样。谢谢。这是一个很好的解决方案。我可以从这里开始工作。掩盖结果:我知道。我只是需要一些开始。
#include <stdint.h>
#include <stdio.h>

int main(void) {
    uint64_t rcs = 0;
    int ring;

    asm ("mov %%cs, %0" : "=r" (rcs));
    ring = (int) (rcs & 3);
    printf("Hello, world. This program is running on ring %d!\n", ring);
    return 0;
}
cd demo-1
. c-build.sh
...

#define EXAMPLE_MSG "Hello, World. This is executed in ring: _ \n"

...

uint64_t rcs = 0;
asm ("mov %%cs, %0" : "=r" (rcs));
msg_buffer[MSG_BUFFER_LEN - 3] = (int) (rcs & 3) + '0';
cat /dev/lkm_example