虚拟机检测技术剖析Word下载.docx

上传人:b****6 文档编号:17976846 上传时间:2022-12-12 格式:DOCX 页数:14 大小:355.01KB
下载 相关 举报
虚拟机检测技术剖析Word下载.docx_第1页
第1页 / 共14页
虚拟机检测技术剖析Word下载.docx_第2页
第2页 / 共14页
虚拟机检测技术剖析Word下载.docx_第3页
第3页 / 共14页
虚拟机检测技术剖析Word下载.docx_第4页
第4页 / 共14页
虚拟机检测技术剖析Word下载.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

虚拟机检测技术剖析Word下载.docx

《虚拟机检测技术剖析Word下载.docx》由会员分享,可在线阅读,更多相关《虚拟机检测技术剖析Word下载.docx(14页珍藏版)》请在冰豆网上搜索。

虚拟机检测技术剖析Word下载.docx

true;

__try

__asm

push 

edx

ecx

ebx

mov 

eax, 

'

VMXh'

ebx, 

// 

将ebx设置为非幻数’VMXH’的其它值

ecx, 

10 

指定功能号,用于获取VMWare版本,当它为0x14时用于获取VMware内存大小

edx, 

VX'

端口号

in 

dx 

从端口dx读取VMware版本到eax

//若上面指定功能号为0x14时,可通过判断eax中的值是否大于0,若是则说明处于虚拟机中

cmp 

判断ebx中是否包含VMware版本’VMXh’,若是则在虚拟机中

setz 

[rc] 

设置返回值

pop 

}

__except(EXCEPTION_EXECUTE_HANDLER) 

//如果未处于VMware中,则触发此异常

false;

return 

rc;

测试结果:

图1

如图1所示,VMDetect成功检测出VMWare的存在。

方法二:

利用IDT基址检测虚拟机

利用IDT基址检测虚拟机的方法是一种通用方式,对VMware和Virtual 

PC均适用。

中断描述符表IDT(Interrupt 

Descriptor 

Table)用于查找处理中断时所用的软件函数,它是一个由256项组成的数据,其中每一中断对应一项函数。

为了读取IDT基址,我们需要通过SIDT指令来读取IDTR(中断描述符表寄存器,用于IDT在内存中的基址),SIDT指令是以如下格式来存储IDTR的内容:

typedef 

struct

WORD 

IDTLimit;

IDT的大小

LowIDTbase;

IDT的低位地址

HiIDTbase;

IDT的高位地址

IDTINFO;

由于只存在一个IDTR,但又存在两个操作系统,即虚拟机系统和真主机系统。

为了防止发生冲突,VMM(虚拟机监控器)必须更改虚拟机中的IDT地址,利用真主机与虚拟机环境中执行sidt指令的差异即可用于检测虚拟机是否存在。

著名的“红丸”(redpill)正是利用此原理来检测VMware的。

Redpill作者在VMware上发现虚拟机系统上的IDT地址通常位于0xFFXXXXXX,而Virtual 

PC通常位于0xE8XXXXXX,而在真实主机上正如图2所示都位于0x80xxxxxx。

Redpill仅仅是通过判断执行SIDT指令后返回的第一字节是否大于0xD0,若是则说明它处于虚拟机,否则处于真实主机中。

Redpill的源码甚是精简,源码分析如下:

#include 

<

stdio.h>

int 

main 

() 

unsigned 

char 

m[2+4], 

rpill[] 

"

\x0f\x01\x0d\x00\x00\x00\x00\xc3"

;

//相当于SIDT[adrr],其中addr用于保存IDT地址

*((unsigned*)&

rpill[3]) 

(unsigned)m;

//将sidt[addr]中的addr设为m的地址

((void(*)())&

rpill)();

//执行SIDT指令,并将读取后IDT地址保存在数组m中

printf 

("

idt 

base:

%#x\n"

 

m[2]));

//由于前2字节为IDT大小,因此从m[2]开始即为IDT地址

if 

(m[5]>

0xd0) 

Inside 

Matrix!

\n"

m[5]);

//当IDT基址大于0xd0xxxxxx时则说明程序处于VMware中

else 

Not 

Matrix.\n"

);

0;

测试结果如图2所示:

图2

利用此IDT检测的方法存在一个缺陷,由于IDT的值只针对处于正在运行的处理器而言,在单CPU中它是个常量,但当它处于多CPU时就可能会受到影响了,因为每个CPU都有其自己的IDT,这样问题就自然而然的产生了。

针对此问题,Offensive 

Computing组织成员提出了两种应对方法,其中一种方法就是利用Redpill反复地在系统上循环执行任务,以此构造出一张当前系统的IDT值变化统计图,但这会增加CPU负担;

另一种方法就是windows 

API函数SetThreadAffinityMask()将线程限制在单处理器上执行,当执行此测试时只能准确地将线程执行环境限制在本地处理器,而对于将线程限制在VM处理器上就可能行不通了,因为VM是计划在各处理器上运行的,VM线程在不同的处理器上执行时,IDT值将会发生变化,因此此方法也是很少被使用的。

为此,有人提出了使用LDT的检测方法,它在具有多个CPU的环境下检测虚拟机明显优于IDT检测方法,该方法具体内容参见下节内容。

方法三:

利用LDT和GDT的检测方法

在 

《Intel®

64 

and 

IA-32 

Architecture 

Software 

Developer’s 

Manual 

Volume 

3A:

System 

Programming 

Guide》第二章的Vol.3 

2-5 

一页(我的Intel开发手册是2008版的)中对于LDT和GDT的描述如下(以下内容为个人翻译):

在保护模式下,所有的内存访问都要通过全局描述符表(GDT)或者本地描述符表(LDT)才能进行。

这些表包含有段描述符的调用入口。

各个段描述符都包含有各段的基址,访问权限,类型和使用信息,而且每个段描述符都拥有一个与之相匹配的段选择子,各个段选择子都为软件程序提供一个GDT或LDT索引(与之相关联的段描述符偏移量),一个全局/本地标志(决定段选择子是指向GDT还是LDT),以及访问权限信息。

若想访问段中的某一字节,必须同时提供一个段选择子和一个偏移量。

段选择子为段提供可访问的段描述符地址(在GDT 

或者LDT 

中)。

通过段描述符,处理器从中获取段在线性地址空间里的基址,而偏移量用于确定字节地址相对基址的位置。

假定处理器在当前权限级别(CPL)可访问这个段,那么通过这种机制就可以访问在GDT 

或LDT 

中的各种有效代码、数据或者堆栈段,这里的CPL是指当前可执行代码段的保护级别。

……

GDT的线性基址被保存在GDT寄存器(GDTR)中,而LDT的线性基址被保存在LDT寄存器(LDTR)中。

由于虚拟机与真实主机中的GDT和LDT并不能相同,这与使用IDT的检测方法一样,因此虚拟机必须为它们提供一个“复制体”。

关于GDT和LDT的基址可通过SGDT和SLDT指令获取。

虚拟机检测工具Scoopy 

suite的作者Tobias 

Klein经测试发现,当LDT基址位于0x0000(只有两字节)时为真实主机,否则为虚拟机,而当GDT基址位于0xFFXXXXXX时说明处于虚拟机中,否则为真实主机。

具体实现代码如下:

void 

LDTDetect(void)

short 

ldt_addr 

ldtr[2];

_asm 

sldt 

ldtr

*((unsigned 

*)&

ldtr);

printf("

LDT 

BaseAddr:

0x%x\n"

ldt_addr);

if(ldt_addr 

== 

0x0000)

Native 

OS\n"

else

VMware\n"

GDTDetect(void)

gdt_addr 

gdtr[4];

sgdt 

gdtr

gdtr[2]);

GDT 

gdt_addr);

if((gdt_addr 

>

24) 

0xff)

main(void)

LDTDetect();

GDTDetect();

测试结果如图3所示:

图3

方法四:

基于STR的检测方法

在保护模式下运行的所有程序在切换任务时,对于当前任务中指向TSS的段选择器将会被存储在任务寄存器中,TSS中包含有当前任务的可执行环境状态,包括通用寄存器状态,段寄存器状态,标志寄存器状态,EIP寄存器状态等等,当此项任务再次被执行时,处理器就会其原先保存的任务状态。

每项任务均有其自己的TSS,而我们可以通过STR指令来获取指向当前任务中TSS的段选择器。

这里STR(Store 

task 

register)指令是用于将任务寄存器 

(TR) 

中的段选择器存储到目标操作数,目标操作数可以是通用寄存器或内存位置,使用此指令存储的段选择器指向当前正在运行的任务的任务状态段 

(TSS)。

在虚拟机和真实主机之中,通过STR读取的地址是不同的,当地址等于0x0040xxxx时,说明处于虚拟机中,否则为真实主机。

实现代码如下:

mem[4] 

{0};

i;

__asm 

str 

mem;

STR 

0x"

for 

(i=0;

i<

4;

i++)

%02x"

mem[i]);

( 

(mem[0]==0x00) 

&

(mem[1]==0x40))

\n 

INSIDE 

MATRIX!

!

OS!

测试结果如图4所示:

图4

方法五:

基于注册表检测虚拟机

在windows虚拟机中常常安装有VMware 

Tools以及其它的虚拟硬件(如网络适配器、虚拟打印机,USB集线器……),它们都会创建任何程序都可以读取的windows注册表项,因此我们可以通过检测注册表中的一些关键字符来判断程序是否处于虚拟机之中。

关于这些注册表的位置我们可以通过在注册表中搜索关键词“vmware”来获取,下面是我在VMware下的WinXP中找到的一些注册表项:

项名:

HKEY_CLASSES_ROOT\Applications\VMwareHostOpen.exe

HKEY_CLASSES_ROOT\Installer\Products\C2A6F2EFE6910124C940B2B12CF170FE\ProductName

键值“VMware 

Tools”

HKEY_CLASSES_ROOT\Installer\Products\C2A6F2EFE6910124C940B2B12CF170FE\SourceList\PackageName

键值:

VMware 

Tools.msi

HKEY_CURRENT_USER\Printers\DeviceOld

_#VMwareVirtualPrinter,winspool,TPVM:

HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\Scsi\Scsi 

Port 

0\Scsi 

Bus 

0\Target 

Id 

0\Logical 

Unit 

0\Identifier

Virtual 

IDE 

Hard 

Drive

1\Scsi 

NECVMWar 

CDR10

HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Products\C2A6F2EFE6910124C940B2B12CF170FE\ProductName

Tools

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\C2A6F2EFE6910124C940B2B12CF170FE\InstallProperties\DisplayName

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Reinstall\0002\DeviceDesc

SVGA 

II

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows 

NT\CurrentVersion\NetworkCards\2\Description

Accelerated 

AMD 

PCNet 

Adapter

HKEY_LOCAL_MACHINE\SOFTWARE\VMware, 

Inc.\VMware 

HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4D36E968-E325-11CE-BFC1-08002BE10318}\0000\DriverDesc

HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4D36E968-E325-11CE-BFC1-

08002BE10318}\0000\ProviderName

VMware, 

Inc.

HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}\0001\DriverDesc

HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4D36E97B-E325-11CE-BFC1-08002BE10318}\0000\DriverDesc

SCSI 

Controller

HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Print\Monitors\ThinPrint 

Print 

Monitor 

VMWare

除以上这些表项之外,还有很多地方可以检测,特别是虚拟机提供的虚拟化软硬件、服务之类,比如文件共享服务,VMware 

物理磁盘助手服务,VMware 

Ethernet 

Adapter 

Driver,VMware 

Controller等等的这些信息都可作为检测虚拟机的手段。

这里我们就以其中某表项为例编程举例一下,其它表项检测方法同理,具体代码如下:

.386

.model 

flat, 

stdcall

option 

casemap:

none

include 

windows.inc

user32.inc

kernel32.inc

advapi32.inc

includelib 

user32.lib

kernel32.lib

advapi32.lib

.data

szCaption 

db 

Detector 

0

szInside 

VMware!

szOutside 

szSubKey 

software\VMWare, 

tools"

hKey 

dd 

?

.code

start:

invoke 

RegOpenKeyEx, 

HKEY_LOCAL_MACHINE, 

addr 

szSubKey, 

0,\

KEY_WRITE 

or 

KEY_READ, 

hKey

.if 

eax 

ERROR_SUCCESS

MessageBox, 

NULL,addr 

szInside, 

szCaption, 

MB_OK

.else

szOutside, 

.endif

RegCloseKey,hKey

ExitProcess,NULL

end 

start

测试结果如图5所示:

图5

方法六:

基于时间差的检测方式

本方法通过运行一段特定代码,然后比较这段代码在虚拟机和真实主机之中的相对运行时间,以此来判断是否处于虚拟机之中。

这段代码我们可以通过RDTSC指令来实现,RDTSC指令是用于将计算机启动以来的CPU运行周期数存放到EDX:

EAX里面,其中EDX是高位,而EAX是低位。

下面我们以xchg 

一句指令的运行时间为例,这段指令在我的真实主机windows 

7系统上的运行时间为0000001E,如图6所示:

图6

而该指令在虚拟机WinXP下的运行时间为00000442,如图7所示:

图7

两者之间的运行时间明显差别很多,在虚拟机中的运行速度远不如真实主机的,一般情况下,当它的运行时间大于0xFF时,就可以确定它处于虚拟机之中了,因此不难写出检测程序,具体实现代码如下:

.586p

szTitle 

VMDetect 

With 

RDTSC"

0h

szInsideVM 

szOutsideVM 

RDTSC

xchg 

eax

RDTSC 

sub 

0FFh

jg 

Detected

0, 

offset 

szOutsideVM, 

szTitle, 

ret

Detected:

szInsideVM, 

r

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 小学教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1