日期:2010-09-10 00:06:00 来源:本站整理
虚拟机检测技术解析[网络技术]
本文“虚拟机检测技术解析[网络技术]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
虚拟机检测技术解析
作者:riusksk (泉哥)
主页:http://riusksk.blogbus.com
前言
在当今信息安全范畴,分外是恶意软件解析中,常常需求操纵到虚拟机技术,以提高病毒解析历程的安全性以及硬件资源的节俭性,因此它在恶意软件范畴中是利用越来越来遍及.这里我们所谓的虚拟机(Virtual Machine)是指通过软件模拟的具有完好硬件系统功效的、运行在一个完好断绝环境中的完好计算机系统.通过虚拟机软件(比方VMware,Virtual PC ,VirtualBox),你可以在一台物理计算机上模拟出一台或多台虚拟的计算机,这些虚拟机完好就像真正的计算机那样举行工作,比方你可以安装操作系统、安装利用程序、拜候网络资源等等.攻击者为了提高恶意程序的躲藏性以及破坏真实主机的成功率,他们都在恶意程序中加入检测虚拟机的代码,以判断程序所处的运行环境.当发现程序处于虚拟机(分外是蜜罐系统)中时,它就会改变操作行为大概中止履行,以此提高反病毒人员解析恶意软件行为的难度.本文主要针对基于Intel CPU的虚拟环境VMware中的Windows XP SP3系统举行检测解析,并摆列出当前常见的几种虚拟机检测办法.
办法一:通过履行特权指令来检测虚拟机
Vmware为真主机与虚拟机之间供应了彼此沟通的通讯机制,它利用"IN"指令来读取特定端口的数据以举行两机通讯,但由于IN指令属于特权指令,在处于保护情势下的真机上履行此指令时,除非权限答应,不然将会触发范例为"EXCEPTION_PRIV_INSTRUCTION"的非常,而在虚拟机中并不会发生非常,在指定功效号0A(获得VMware版本)的情形下,它会在EBX中返回其版本号"VMXH";而当功效号为0x14时,可用于获得VMware内存大小,当大于0时则阐明处于虚拟机中.VMDetect恰是操纵前一种办法来检测VMware的存在,其检测代码解析以下:
代码:
bool IsInsideVMWare() { bool rc = true; __try { __asm { push edx push ecx push ebx mov eax, 'VMXh' mov ebx, 0 // 将ebx设置为非幻数’VMXH’的别的值 mov ecx, 10 // 指定功效号,用于获得VMWare版本,当它为0x14时用于获得VMware内存大小 mov edx, 'VX' // 端口号 in eax, dx // 从端口dx读取VMware版本到eax //若上面指定功效号为0x14时,可通过判断eax中的值能否大于0,若是则阐明处于虚拟机中 cmp ebx, 'VMXh' // 判断ebx中能否包含VMware版本’VMXh’,若是则在虚拟机中 setz [rc] // 设置返回值 pop ebx pop ecx pop edx } } __except(EXCEPTION_EXECUTE_HANDLER) //假如未处于VMware中,则触发此非常 { rc = false; } return rc; }测试后果:
1.jpg下载此附件需求损耗2Kx,下载中会自动扣除.
图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的大小 WORD LowIDTbase; // IDT的低位地址 WORD 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", *((unsigned*)&m[2])); //由于前2字节为IDT大小,因此从m[2]开始即为IDT地址 if (m[5]>0xd0) printf ("Inside Matrix!\n", m[5]); //当IDT基址大于0xd0xxxxxx时则阐明程序处于VMware中 else printf ("Not in Matrix.\n"); return 0; }测试后果如图2所示:
2.jpg下载此附件需求损耗2Kx,下载中会自动扣除.
图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时阐明处于虚拟机中,不然为真实主机.具体实现代码以下:
代码:
#include <stdio.h> void LDTDetect(void) { unsigned short ldt_addr = 0; unsigned char ldtr[2]; _asm sldt ldtr ldt_addr = *((unsigned short *)&ldtr); printf("LDT BaseAddr: 0x%x\n", ldt_addr); if(ldt_addr == 0x0000) { printf("Native OS\n"); } else printf("Inside VMware\n"); } void GDTDetect(void) { unsigned int gdt_addr = 0; unsigned char gdtr[4]; _asm sgdt gdtr gdt_addr = *((unsigned int *)&gdtr[2]); printf("GDT BaseAddr:0x%x\n", gdt_addr); if((gdt_addr >> 24) == 0xff) { printf("Inside VMware\n"); } else printf("Native OS\n"); } int main(void) { LDTDetect(); GDTDetect(); return 0; }测试后果如图3所示:
3.jpg下载此附件需求损耗2Kx,下载中会自动扣除.
图3
办法四:基于STR的检测办法
在保护情势下运行的全部程序在切换任务时,关于当前任务中指向TSS的段挑选器将会被存储在任务存放器中,TSS中包含有当前任务的可履行环境状况,包含通用存放器状况,段存放器状况,标志存放器状况,EIP存放器状况等等,当此项任务再次被履行时,处理器就会其原先保存的任务状况.每项任务均有其自己的TSS,而我们可以通过STR指令来获得指向当前任务中TSS的段挑选器.这里STR(Store task register)指令是用于将任务存放器 (TR) 中的段挑选器存储到目标操作数,目标操作数可以是通用存放器或内存位置,利用此指令存储的段挑选器指向当前正在运行的任务的任务状况段 (TSS).在虚拟机和真实主机之中,通过STR读取的地址是差别的,本地址等于0x0040xxxx时,阐明处于虚拟机中,不然为真实主机.实现代码以下:
代码:
#include <stdio.h> int main(void) { unsigned char mem[4] = {0}; int i; __asm str mem; printf (" STR base: 0x"); for (i=0; i<4; i++) { printf("%02x",mem[i]); } if ( (mem[0]==0x00) && (mem[1]==0x40)) printf("\n INSIDE MATRIX!!\n"); else printf("\n Native OS!!\n"); return 0; }测试后果如图4所示:
4.jpg下载此附件需求损耗2Kx,下载中会自动扣除.
图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 Id 0\Identifier
键值:VMware Virtual IDE Hard Drive
项名:HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\Scsi\Scsi Port 1\Scsi Bus 0\Target Id 0\Logical Unit Id 0\Identifier
键值:NECVMWar VMware IDE CDR10
项名:HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Installer\Products\C2A6F2EFE6910124C940B2B12CF170FE\ProductName
键值:VMware Tools
项名:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\C2A6F2EFE6910124C940B2B12CF170FE\InstallProperties\DisplayName
键值:VMware Tools
项名:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Reinstall\0002\DeviceDesc
键值:VMware SVGA II
项名:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards\2\Description
键值:VMware Accelerated AMD PCNet Adapter
项名:HKEY_LOCAL_MACHINE\SOFTWARE\VMware, Inc.\VMware Tools
项名:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4D36E968-E325-11CE-BFC1-08002BE10318}\0000\DriverDesc
键值:VMware SVGA II
项名: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
键值:VMware Accelerated AMD PCNet Adapter
项名:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Class\{4D36E97B-E325-11CE-BFC1-08002BE10318}\0000\DriverDesc
键值:VMware SCSI Controller
项名:HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Print\Monitors\ThinPrint Print Port Monitor for VMWare
除以上这些表项之外,还有很多地方可以检测,分外是虚拟机供应的虚拟化软硬件、服务之类,比方文件同享服务,VMware 物理磁盘助手服务,VMware Ethernet Adapter Driver,VMware SCSI Controller等等的这些信息都可作为检测虚拟机的手段.这里我们就以此中某表项为例编程举例一下,别的表项检测办法同理,具体代码以下:
代码:
.386 .model flat, stdcall option casemap:none include windows.inc include user32.inc include kernel32.inc include advapi32.inc includelib user32.lib includelib kernel32.lib includelib advapi32.lib .data szCaption db "VMware Detector ",0 szInside db "Inside VMware!",0 szOutside db "Native OS!",0 szSubKey db "software\VMWare, Inc.\VMware tools",0 hKey dd ? .code start: invoke RegOpenKeyEx, HKEY_LOCAL_MACHINE, addr szSubKey, 0, KEY_WRITE or KEY_READ, addr hKey .if eax == ERROR_SUCCESS invoke MessageBox, NULL,addr szInside, addr szCaption, MB_OK .else invoke MessageBox, NULL,addr szOutside, addr szCaption, MB_OK .endif invoke RegCloseKey,hKey invoke ExitProcess,NULL end start测试后果如图5所示:
5.jpg下载此附件需求损耗2Kx,下载中会自动扣除.
图5
办法六:基于时间差的检测方法
本办法通过运行一段特定代码,然后对比这段代码在虚拟机和真实主机之中的相对运行时间,以此来判断能否处于虚拟机之中.这段代码我们可以通过RDTSC指令来实现,RDTSC指令是用于将计算机启动以来的CPU运行周期数存放到EDX:EAX里面,此中EDX是高位,而EAX是低位.下面我们以xchg ecx, eax 一句指令的运行时间为例,这段指令在我的真实主机windows 7系统上的运行时间为0000001E,如图6所示:
6.jpg下载此附件需求损耗2Kx,下载中会自动扣除.
图6
而该指令在虚拟机WinXP下的运行时间为00000442,如图7所示:
7.jpg下载此附件需求损耗2Kx,下载中会自动扣除.
图7
二者之间的运行时间明显差别很多,在虚拟机中的运行速度远不如真实主机的,普通情形下,当它的运行时间大于0xFF时,便可以肯定它处于虚拟机之中了,因此不难写出检测程序,具体实现代码以下:
代码:
.586p .model flat, stdcall option casemap:none include windows.inc include kernel32.inc include user32.inc includelib kernel32.lib includelib user32.lib .data szTitle db "VMDetect With RDTSC", 0h szInsideVM db "Inside VMware!", 0h szOutsideVM db "Native OS!", 0h .code start: RDTSC xchg ecx, eax RDTSC sub eax, ecx cmp eax, 0FFh jg Detected invoke MessageBox, 0, offset szOutsideVM, offset szTitle, 0 ret Detected: invoke MessageBox, 0, offset szInsideVM, offset szTitle, 0 ret end start测试后果如图8所示:
8.jpg下载此附件需求损耗2Kx,下载中会自动扣除.
图8
办法七:操纵虚拟硬件指纹检测虚拟机
操纵虚拟硬件指纹也可用于检测虚拟机的存在,比方VMware默许的网卡MAC地址前缀为"00-05-69,00-0C-29大概00-50-56",这前3节是由VMware分配的唯一标识符OUI,以供它的虚拟化适配器利用.在我的VMWare WinXP下的MAC地址为00-0C-29-5B-D7-67,如图9所示:
9.jpg下载此附件需求损耗2Kx,下载中会自动扣除.
图9
但由于这些可经过改正配置文件来绕过检测.别的,还可通过检测特定的硬件掌握器,BIOS,USB掌握器,显卡,网卡等特点字符串举行检测,这些在前面利用注册表检测办法中已有所触及.别的之前在看雪论坛上也有朋友提到通过检测硬盘Model Number能否含有"vmware"或"virtual"等字样来实现检测虚拟机的功效,网址见这(附源码):http://bbs.pediy.com/showthread.php?t=110046.
总结
国外SANS安全组织的研究人员总结出当前各种虚拟机检测手段不外乎以下四类:
● 搜索虚拟环境中的进程,文件系统,注册表;
● 搜索虚拟环境中的内存
● 搜索虚拟环境中的特定虚拟硬件
● 搜索虚拟环境中的特定处理器指令和功效
因为现代计算系统大多是由文件系统,内存,处理器及各种硬件组件构成的,上面提到的四种检测手段均包含了这些因素.纵观前面各种检测办法,也均在此四类当中.除此之外,也有人提出通过网络来检测虚拟机,比方搜索ICMP和TCP数据通讯的时间差别,IP ID数据包差别以及数据包中的非常头信息等等.随着技术研究的深化,相信会有更多的检测手段呈现,与此同时,虚拟机厂商也会不断进化它们的产品,以增添anti-vmware的难度,这不也恰是一场永无停止的无烟战争!
以上是“虚拟机检测技术解析[网络技术]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |
评论内容只代表网友观点,与本站立场无关!
评论摘要(共 0 条,得分 0 分,平均 0 分)
查看完整评论