红丸检测虚拟化

时间:2017-09-17 18:42:03

标签: c++ c virtual-machine virtualization

我正在尝试检测我的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。 我做错了吗?

2 个答案:

答案 0 :(得分:3)

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

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

来自Joanna Rutkowska代码的实际作者:

  

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

答案 1 :(得分:0)

#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上构建的文件。