【转】虚拟机检测技术
前言
在当今信息安全领域,特别是恶意软件分析中,经常需要利用到虚拟机技术,以提高病毒分析过程的安全性以及硬件资源的节约性,因此它在恶意软件领域中是应用 越来越来广泛。这里我们所谓的虚拟机(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 edxpush ecxpush ebxmov 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 ebxpop ecxpop edx}}__except(EXCEPTION_EXECUTE_HANDLER) //如果未处于VMware中,则触发此异常{rc = 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的大小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
利用此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 ldtrldt_addr = *((unsigned short *)&ldtr);printf("LDT BaseAddr: 0x%x\n", ldt_addr);if(ldt_addr == 0x0000){printf("Native OS\n");}elseprintf("Inside VMware\n"); }void GDTDetect(void) {unsigned int gdt_addr = 0;unsigned char gdtr[4];_asm sgdt gdtrgdt_addr = *((unsigned int *)&gdtr[2]);printf("GDT BaseAddr:0x%x\n", gdt_addr);if((gdt_addr >> 24) == 0xff){printf("Inside VMware\n");}elseprintf("Native OS\n"); }int main(void) {LDTDetect();GDTDetect();return 0; }
测试结果如图3所示:
图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");elseprintf("\n Native OS!!\n");return 0; }
测试结果如图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 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:noneinclude windows.incinclude user32.incinclude kernel32.incinclude advapi32.incincludelib user32.libincludelib kernel32.libincludelib 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_SUCCESSinvoke MessageBox, NULL,addr szInside, addr szCaption, MB_OK.elseinvoke MessageBox, NULL,addr szOutside, addr szCaption, MB_OK.endifinvoke RegCloseKey,hKeyinvoke ExitProcess,NULL end start
测试结果如图5所示:
图5
方法六:基于时间差的检测方式
本方法通过运行一段特定代码,然后比较这段代码在虚拟机和真实主机之中的相对运行时间,以此来判断是否处于虚拟机之中。这段代码我们可以通过RDTSC指 令来实现,RDTSC指令是用于将计算机启动以来的CPU运行周期数存放到EDX:EAX里面,其中EDX是高位,而EAX是低位。下面我们以 xchg ecx, eax 一句指令的运行时间为例,这段指令在我的真实主机windows 7系统上的运行时间为0000001E,如图6所 示:
图6
而该指令在虚拟机WinXP下的运行时间为00000442,如图7所示:
图7
两者之间的运行时间明显差别很多,在虚拟机中的运行速度远不如真实主机的,一般情况下,当它的运行时间大于0xFF时,就可以确定它处于虚拟机之中了,因此不难写出检测程序,具体实现代码如下:
.586p .model flat, stdcall option casemap:noneinclude windows.inc include kernel32.inc include user32.incincludelib kernel32.lib includelib user32.lib.data szTitle db "VMDetect With RDTSC", 0h szInsideVM db "Inside VMware!", 0h szOutsideVM db "Native OS!", 0h.codestart:RDTSCxchg ecx, eaxRDTSC sub eax, ecxcmp eax, 0FFhjg Detectedinvoke MessageBox, 0, offset szOutsideVM, offset szTitle, 0retDetected:invoke MessageBox, 0, offset szInsideVM, offset szTitle, 0ret end start
测试结果如图8所示:
图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
但由于这些可经过修改配置文件来绕过检测。另外,还可通过检测特定的硬件控制器,BIOS,USB控制器,显卡,网卡等特征字符串进行检测,这些在前面使 用注册表检测方法中已有所涉及。另外之前在看雪论坛上也有朋友提到通过检测硬盘Model Number是否含有“vmware”或“virtual”等 字样来实现检测虚拟机的功能,网址见这(附源码):http://bbs.pediy.com/showthread.php?t=110046。
总结
国外SANS安全组织的研究人员总结出当前各种虚拟机检测手段不外乎以下四类:
● 搜索虚拟环境中的进程,文件系统,注册表;
● 搜索虚拟环境中的内存
● 搜索虚拟环境中的特定虚拟硬件
● 搜索虚拟环境中的特定处理器指令和功能
因为现代计算系统大多是由文件系统,内存,处理器及各种硬件组件构成的,上面提到的四种检测手段均包含了这些因素。纵观前面各种检测方法,也均在此四类当 中。除此之外,也有人提出通过网络来检测虚拟机,比如搜索ICMP和TCP数据通讯的时间差异,IP ID数据包差异以及数据包中的异常头信息等等。随着 技术研究的深入,相信会有更多的检测手段出现,与此同时,虚拟机厂商也会不断进化它们的产品,以增加anti-vmware的难度,这不也正是一场永无休 止的无烟战争!
文档下载:
虚拟机检测技术剖析.doc[谁下载?]
转载于:https://www.cnblogs.com/jack204/archive/2011/12/27/2303924.html
【转】虚拟机检测技术相关推荐
- [原创]虚拟机检测技术剖析
标题:[原创]虚拟机检测技术剖析 作者:riusksk (泉哥) 主页:http://riusksk.blogbus.com 前言 在当今信息安全领域,特别是恶意软件分析中,经常需要利用到虚拟机技术, ...
- 虚拟机检测技术刨析(一)
虚拟机检测技术刨析(一) 原文:https://blog.csdn.net/qq_32400847/article/details/52830990 恶意代码编写者经常使用反虚拟机技术逃避分析,这种技 ...
- 关于虚拟机检测技术的研究
平平无奇的搬砖日,突然想起来之前分析的一个病毒好像有某种反虚拟机的方法,当时没太研究明白,甚至都没研究明白是检测虚拟机的操作.现在想起来回过头去再研究一下,虚拟机的检测技术,在这个过程中借鉴了很多其他 ...
- [系统安全] 三十三.恶意代码检测(3)基于机器学习的恶意代码检测技术
您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...
- 基于VMM的Rootkit检测技术及模型分析
Linux通过其特有的虚拟文件系统(Virtual Filesystem)实现对多种文件系统的兼容.虚拟文件系统又称虚拟文件系统转换(Virtual Filesystem Switch vFs),是一 ...
- 对抗恶意程序的反虚拟化,百度安全提最新检测技术,具备三大特性
导读:近日百度安全发表的论文<Detecting Hardware-assisted Virtualization with Inconspicuous Features>入选国际TOP期 ...
- 信息安全-入侵检测技术原理与应用
一.入侵检测概述 1.1 入侵检测概念 入侵应与受害目标相关联,该受害目标可以是一个大的系统或单个对象 判断与目标相关的操作是否为入侵的依据:对目标的操作是否超出了目标的安全策略范围 入侵:指违背访问 ...
- 恶意代码检测技术的演化
from:http://www.4ucode.com/Study/Topic/1407760 在本文中我们讨论了识别恶意代码的各种方法,它们彼此间在功能上(以及时间上)的联系,它们的技术以及特点.从一 ...
- 恶意代码可视化检测技术研究综述
摘要 随着反检测技术的不断发展,产生了大量形态多样的恶意代码变种,传统检测技术已无法准确检测出该种未知恶意代码.由于数据可视化方法能将恶意代码的核心表现在图像特征中,因此可视化恶意代码检测方法受到越来 ...
- 苹果新算法已混进 iOS 14.3!CSAM 检测技术再遭网友争议
整理 | 禾木木.郑丽媛 出品 | AI科技大本营(ID:rgznai100) 苹果宣布即将推出 CSAM 检测系统时,遭到了 4000 多个组织及个人的公开反对,他们质疑苹果会破坏用户隐私和端到端加 ...
最新文章
- Mysql Cluster节点类型
- Leetcode 38.外观数列 (每日一题 20210702)
- Hyperledger Fabric MSP Identity Validity Rules——MSP身份验证规则
- 删数问题 山东理工oj2072(贪心)
- angular4与高德地图的结合
- android播放器录制视频,Android播放器的录制实践
- linux提取曲线数据软件,曲线图转数据工具软件(Engauge Digitizer)提取文献中的数据...
- Android ------ 开源的Modnet算法实现抠图和更换背景
- 右键添加cmd命令快捷键,右键cmd快捷键丢失
- Hook技术(1):Hook技术简介
- 【kali-漏洞扫描】(2.1)Nessus下载安装(上)
- lg5.6不用计算机怎么算,lg换算(lg如何计算)
- 计算机音乐吧粉刷匠,中班音乐歌曲《粉刷匠》
- 雷军和董明珠的10亿赌局 什么来历
- 自动控制系统实验总结
- Composure获取子层级图像:使用变换通道
- SpringCloud项目搭建(六) —elastic-job的使用,以及consul的配置使用(衔接上篇)
- 数据库原理 头歌实训 数据库常用对象
- Locally Differential for Frequency Estimation
- 【安全知识分享】PPTX|典型事故和应急救援案例分析(25页)(附下载)
热门文章
- java队列和栈实现原理_Java特性队列和栈的堵塞原理解析
- 软件各种系统架构图【转】
- sliverlight+WCF项目发布到IIS
- 麻省理工6.824 分布式课程 Raft选主实现笔记
- nginx 反向代理及负载均衡
- [20150803]触发器对dml的影响.txt
- MySQL报错: Access denied for user 'root'@'localhost'
- 【算法】排序_归并排序
- mysql使用存储过程循环修改数据
- c语言利用索引数组排序,根据C中的索引数组对数组排序C