我正在尝试检测我的 Windows 是否在虚拟机上运行。我找到了这段 C 代码,它被称为 Joanna Rutkowska 的红色药丸:
int swallow_redpill ()
{
unsigned char m[2+4], rpill[] = "\x0f\x01\x0d\x00\x00\x00\x00\xc3";
*((unsigned*)&rpill[3]) = (unsigned)m;
((void(*)())&rpill)();
return (m[5]>0xd0) ? 1 : 0;
}
但是当我在 VC++ 项目中运行它时,它在线失败
((void(*)())&rpill)();
带有消息:执行位置 0x003AFCE8 时发生访问冲突。 我做错了吗?
显然,示例代码试图执行一系列机器指令,这些指令在某些虚拟机中的行为与在“某些”真实硬件上的行为不同。请注意,使用这种简单的方法可能无法检测到其他虚拟机。
代码无法执行的原因是在现代操作系统上无法执行数据部分。您需要专门将该代码段放入可执行部分,或将数据部分更改为可执行。来自代码的实际编写者
Joanna Rutkowska:
注意:该程序将在具有 PAX/X^W/grsecurity、保护(正如 Brad Spengler 指出的那样)的系统上失败,因为 rpill 变量未标记为可执行文件。为了使其在此类系统中运行,应使用 mprotect() 为 rpill 标记 PROT_EXEC 属性。另一种解决方案是仅使用 asm() 关键字而不是类似 shellcode 的缓冲区。然而,这个程序应该被视为构建到您自己的 shellcode 中的骨架,而不是独立的生产类工具;)我的目标是使其尽可能简单和可移植。这就是为什么我没有使用 asm() 或 mprotect(),因为它们依赖于系统或编译器。
#include <windows.h>
unsigned char m[2+4], rpill[] = "\x0f\x01\x0d\x00\x00\x00\x00\xc3";
int swallow_redpill ()
{
unsigned int old;
VirtualProtect(rpill, 8, PAGE_EXECUTE_READWRITE, &old);
*((unsigned*)&rpill[3]) = (unsigned)m;
((void(*)())&rpill)();
return (m[5]>0xd0) ? 1 : 0;
}
在 Windows 上应该可以解决问题。如果您有 x64 机器,请确保在 Win32 上运行它。
#include <stdio.h>
struct {
unsigned short limit;
unsigned long base;
} __attribute__((packed)) idtr;
int main() {
asm("sidt %0" : "=m" (idtr));
printf("%lx %x\n", idtr.base, idtr.limit);
return 0;
}
我从你的代码中得到的输出是: ffffffffffff0000 0
这是否意味着没有虚拟机管理程序/虚拟化?