Red Pill 检测虚拟化

问题描述 投票:0回答:4

我正在尝试检测我的 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 时发生访问冲突。 我做错了吗?

c++ c virtual-machine virtualization
4个回答
5
投票

显然,示例代码试图执行一系列机器指令,这些指令在某些虚拟机中的行为与在“某些”真实硬件上的行为不同。请注意,使用这种简单的方法可能无法检测到其他虚拟机。

代码无法执行的原因是在现代操作系统上无法执行数据部分。您需要专门将该代码段放入可执行部分,或将数据部分更改为可执行。

来自代码的实际编写者

Joanna Rutkowska

注意:该程序将在具有 PAX/X^W/grsecurity、保护(正如 Brad Spengler 指出的那样)的系统上失败,因为 rpill 变量未标记为可执行文件。为了使其在此类系统中运行,应使用 mprotect() 为 rpill 标记 PROT_EXEC 属性。另一种解决方案是仅使用 asm() 关键字而不是类似 shellcode 的缓冲区。然而,这个程序应该被视为构建到您自己的 shellcode 中的骨架,而不是独立的生产类工具;)我的目标是使其尽可能简单和可移植。这就是为什么我没有使用 asm() 或 mprotect(),因为它们依赖于系统或编译器。


1
投票
#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 上运行它。


0
投票
这是为 x86 手写的,不考虑 NX 堆栈,而 NX 堆栈是现代编译器中常见的强化机制。一个更可移植的代码,用于通过 SIDT 获取 IDTR,适用于 amd64:

#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; }
    

0
投票
@L29Ah

我从你的代码中得到的输出是: ffffffffffff0000 0

这是否意味着没有虚拟机管理程序/虚拟化?

© www.soinside.com 2019 - 2024. All rights reserved.