关于虚拟机检测技术的研究
平平无奇的搬砖日,突然想起来之前分析的一个病毒好像有某种反虚拟机的方法,当时没太研究明白,甚至都没研究明白是检测虚拟机的操作。现在想起来回过头去再研究一下,虚拟机的检测技术,在这个过程中借鉴了很多其他大神的经典文章(当然大多数都是人家的东西,我只不过是拾人牙慧)
相较而言,我们一般在分析病毒的时候,也会碰到一些反虚拟机反调试的操作。常见的反虚拟机的手段,无非就是遍历系统进程,检测特殊进程、检测特殊服务、检测注册表项等几种。国外SANS安全组织的研究人员总结出当前各种虚拟机检测手段不外乎以下四类:
● 搜索虚拟环境中的进程,文件系统,注册表;
● 搜索虚拟环境中的内存
● 搜索虚拟环境中的特定虚拟硬件
● 搜索虚拟环境中的特定处理器指令和功能
学习了几位大神早期分享的文章,并且根据里边的示例。自己做了一下测试,加了一些自己在测试过程中的理解。
这次主要针对虚拟环境的内存以及处理器指令的技术手段进行虚拟机环境的检测。
第一种:使用特权指令进行虚拟环境的检测:
Vmware为物理机与虚拟机之间提供了相互沟通的通讯机制,它使用“IN”指令来读取特定端口的数据以进行两机通讯,但由于IN指令属于特权指令,在处于保护模式下的真机上执行此指令时,除非权限允许,否则将会触发类型为“EXCEPTION_PRIV_INSTRUCTION”的异常,而在虚拟机中并不会发生异常,在指定功能号0A(获取VMware版本)的情况下,它会在EBX中返回其版本号“VMXH”;而当功能号为0x14时,可用于获取VMware内存大小,当大于0时则说明处于虚拟机中。
检测例程:
#include <stdio.h>
#include <Windows.h>
int main()
{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;}if (rc)printf("在虚拟机环境");elseprintf("不在虚拟机");getchar();return rc;
}
#include <stdio.h>
#include <Windows.h>
int main()
{bool rc = true;__asm{push edxpush ecxpush ebxmov eax, 'VMXh'mov ebx, 0 // 将ebx设置为非幻数’VMXH’的其它值mov ecx, 14h // 指定功能号,用于获取VMWare版本,当它为0x14时用于获取VMware内存大小mov edx, 'VX' // 端口号in eax, dx // 从端口dx读取VMware版本到eax//若上面指定功能号为0x14时,可通过判断eax中的值是否大于0,若是则说明处于虚拟机中cmp eax, 0 // 判断ebx中是否包含VMware版本’VMXh’,若是则在虚拟机中JBE Tablesetz [rc] // 设置返回值
Table:pop ebxpop ecxpop edx}if(!rc)printf("在虚拟机环境");
elseprintf("不在虚拟机");getchar();return rc;}
检测结果:
方法二:使用敏感指令进行虚拟环境监测:
VMM(Virtual Machine Monitor,虚拟机监视器)是一种可以在同一物理硬件上创建分离的多台(虚拟)机器的软件,如上所说,VMWare的VMM似乎只是作为一个应用程序运行在我们的操作系统里边,实际上,它可以运行在操作系统的底层,也就是我们常说的系统层,完全控制硬件。也就是说在这段时间里,物理机的虚拟内存和线性内存会被短暂的移除。
如上图所示,有几点需要注意:
1:虚拟机内存和物理机内存可以相互切换
2:操作系统完全控制物理机OS上下文
3:VMM完全控制虚拟机的上下文
4:每个上下文有自己的地址空间,中断描述符表,堆栈,执行上下文(也就是物理机和虚拟机都各自有自己的一套数据结构),从这里就可以着手去检测虚拟机的存在
接下来就是第二种检测虚拟机的方法:敏感指令检测虚拟机
利用IDT基址检测虚拟机的方法是一种通用方式,对VMware和Virtual PC均适用。中断描述符表IDT(Interrupt Descriptor Table)用于查找处理中断时所用的软件函数,它是一个由256项组成的数据,其中每一中断对应一项函数。中断描述符表IDT将每个异常或中断向量分别与它们的处理过程联系起来,IDT是由8字节长描述符组成的一个数组。IDT表可以驻留在线性地址空间的任何地方,处理器使用IDTR寄存器来定位IDT表的位置。我们可以使用敏感指令来获取需要的数据,以下敏感指令可以分别获取相应的寄存器的值。
- SGDT:存储GDT寄存器
- SIDT:存储IDT寄存器
- SLDT:存储LDT寄存器
- SMSW: 存储机器状态
LIDT和SIDT指令分别用于加载和保存IDTR寄存器的内容(中断描述符表寄存器,用于IDT在内存中的基址),LIDT指令用于把内存中的限长值和基地址操作数加载到IDTR寄存器中。该指令仅能由当前特权级CPL是0的代码执行,通常被用于创建IDT时的操作系统初始化代码中。SIDT指令用于把IDTR中的基地址和限长内容复制到内存中,该指令可在任何特权级上执行。
SIDT指令是以如下格式来存储IDTR的内容
typedef struct
{WORD IDTLimit; // IDT的大小WORD LowIDTbase; // IDT的低位地址WORD HiIDTbase; // IDT的高位地址
} IDTINFO;
由于在使用的时候IDTR是唯一存在的,不可能存在两个IDTR表同时起作用。但是存在两个操作系统,也就是我们的物理机操作系统和虚拟机操作系统。为了防止二者冲突所以VMM会修改虚拟机中的IDT地址,这也就造成了物理机和虚拟机IDT地址的差异,我们可以通过这个差异来进行虚拟机的检测。
使用一句话代码读取到IDT表的基址:
一句汇编读取到IDT的位置
_asm sidt idtr;
(我在实际测试过程中发现当当IDT基址小于0xd0xxxxxx时则说明程序处于VMware虚拟环境中,但是这个具体的实用性还有待检测,我在Win10 64位物理及检测的时候发现并不是很准确)
测试例程:
#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("Not in Matrix!%#x\n", m[5]); //当IDT基址大于0x80xxxxxx时则说明程序处于VMware中else printf ("in Matrix.%#x\n",m[5]);getchar();return 0;
}
测试结果:
以上是利用IDT基址的方式进行检测虚拟机的方式,同理可以使用LDT和GDT的方式进行虚拟机的检测。
(在操作系统中,全局描述符表GDT只有一张,一个处理器对应一个GDT,同理为了防止冲突,虚拟机的GDT和物理机的GDT必然有差别,我们可以根据这个数值的差别进行判断)
使用LGDT指令将GDT的入口地址装入寄存器GDTR,便于CPU在殉职的时候使用,我们可以通过SGDT指令来获取GDTR寄存器的数据;同理使用LLDT指令将选择子装在到LDTR寄存器里边,使用SLDT来获取LDTR寄存器的数值。
测试例程:
#include <stdio.h>
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) == 0x80){printf("Inside VMware\n");}elseprintf("Native OS\n");
}int main(void)
{GDTDetect();getchar();return 0;
}
测试结果:
基于STR机制的检测方式
在保护模式下运行的所有程序在切换任务时,对于当前任务中指向TSS的段选择器将会被存储在任务寄存器中,TSS中包含有当前任务的可执行环境状态,包括通用寄存器状态,段寄存器状态,标志寄存器状态,EIP寄存器状态等等,当此项任务再次被执行时,处理器就会其原先保存的任务状态。每项任务均有其自己的TSS,而我们可以通过STR指令来获取指向当前任务中TSS的段选择器。任务寄存器拥有当前任务的TSS的段选择符和段描述符,TSS描述符仅可能存放在GDT中,不能存放在LDT或IDT中。指令LTR(加载任务寄存器)和STR(保存任务寄存器)加载和保存任务寄存器的可见部分。LTR指令让任务寄存器加载TSS描述符的段选择符,该指令只能运行在特权级0,该指令通常用来系统初始化时初始化任务寄存器。指令STR可以将任务寄存器的可见部分保存到通用寄存器或内存中。该指令可以运行在任何特权级。
这里STR(Store task register)指令是用于将任务寄存器 (TR) 中的段选择器存储到目标操作数,目标操作数可以是通用寄存器或内存位置,使用此指令存储的段选择器指向当前正在运行的任务的任务状态段 (TSS)。在虚拟机和真实主机之中,通过STR读取的地址是不同的,当地址等于0x0040xxxx时,说明处于虚拟机中,否则为物理机。(在实际测试过程中发现,与之相反当STR地址等于0x40的时候说明处于物理机状态,反之则是在虚拟机之中)
测试代码:
}*/
#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] == 0x40)printf("\n Native OS!!\n");elseprintf("\n INSIDE MATRIX!!\n");getchar();return 0;
}
第三种方法:基于时间差的检测方式
顾名思义,就是通过特定的指令在虚拟机和真机运行的相对时间进行检测。可以通过RDTSC指令来实现,RDTSC指令是用于将计算机启动以来的CPU运行周期数存放到EDX:EAX里面,其中EDX是高位,而EAX是低位。
主要测试代码如下:
.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
对抗方法:
对于以上列出的几种检测虚拟机的方式,包括未列出的检测注册表项、检测特定进程、检测硬件指纹、检测特定服务的方法都有相应的对抗手段。
在开启虚拟化的情况下,以上的大部分检测方式均会失效。至于硬件指纹,VN的硬件特征有很多,比较常见的检测方式会检测VMWare的MAC地址,VMware默认的网卡MAC地址前缀为“00-05-69,00-0C-29或者00-50-56
。可以使用相应的工具修改特征来躲避检测。
总结:
在安全对抗愈演愈烈的现在,网络安全问题已然是一个不容忽视的重大问题,而虚拟机作为网络安全从业者必不可少的辅助工具,对于网络安全的贡献也是不容小觑的,之后必然也会是兵家必争之地,虚拟机的检测以及对抗也必然会成为攻城略地的重中之重,随着VMWare的不断更新升级以及Hacker的技术手段不断升级,相信会有越来越多的检测虚拟机的技术手段,同时兵来将挡水来土掩,也一定会有更多的反反虚拟机的技术手段产生,生生不息,安全至上。
参考链接:
https://bbs.pediy.com/thread-119969-1.htm
https://bbs.pediy.com/thread-228395.htm
https://bbs.pediy.com/thread-229571.htm
https://www.ibm.com/developerworks/cn/linux/l-cn-vt/index.html
关于虚拟机检测技术的研究相关推荐
- [原创]虚拟机检测技术剖析
标题:[原创]虚拟机检测技术剖析 作者:riusksk (泉哥) 主页:http://riusksk.blogbus.com 前言 在当今信息安全领域,特别是恶意软件分析中,经常需要利用到虚拟机技术, ...
- 虚拟机检测技术刨析(一)
虚拟机检测技术刨析(一) 原文:https://blog.csdn.net/qq_32400847/article/details/52830990 恶意代码编写者经常使用反虚拟机技术逃避分析,这种技 ...
- 图像检测技术的研究现状
图像检测技术的研究现状 技术检测 图像处理知识库 · 2016-01-08 19:59 图像检测技术的研究现状 所谓图像检测,就是通过图像对感兴趣的特征区域(检测目标)进行提取的过程,其中图像是承载检 ...
- 问题模型对计算机软件的需要,计算机软件安全检测技术方法研究讨论
高鑫帅 摘 要:做好计算机软件的安全检测工作可以保障计算机的安全运行.该文阐述了应用计算机软件安全检测技术时应注意的问题,并以此为切入点分析了计算机软件安全检测技术的具体应用方法,旨在为同行业的相关人 ...
- 无创血糖检测技术研究进展
[摘 要] 血糖检测是糖尿病诊断和病情控制的重要手段,目前,无创血糖检测是血糖检测的主要发展方向.本文将对无创血糖检测技术进行综述,总结无创血糖检测的发展现状,并探讨限制无创血糖检测技术发展的技术难点 ...
- [系统安全] 三十三.恶意代码检测(3)基于机器学习的恶意代码检测技术
您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...
- 计算机网络PIC和SDV,SRBSDV和RBSDV检测技术的建立
摘要: 南方水稻黑条矮缩病是威胁我国水稻生产的重要病毒病害之一,由南方水稻黑条矮缩病毒(Southern rice black-streaked dwarf virus, SRBSDV)引起.该病毒属 ...
- 基于图像处理的路面裂缝检测系统设计与研究
基于MATLAB的路面裂缝检测系统设计与研究 一.课题背景及研究目的 随着社会经济的不断发展,道路交通在国民经济和人民生活中起的作用愈发显著, 交通已成为人们日常出行和我国经济建设中重要的基础设施之一 ...
- 传感器检测技术及仪表笔记01第一章 绪论
第一章 绪论 1.1 检测技术及仪表的地位与作用 1.1.1 检测仪表的地位与作用 1.检测的定义 2.检测仪表的地位与作用 3.检测方法 1.2 传感器概述 1.2.1 传感器的基本概念 1.传感器 ...
最新文章
- [十九]JavaIO之PipedReader 和 PipedWriter
- 使用ffmpeg实现转码样例(代码实现)
- Response.ContentType所有类型例举
- [react] React中怎么操作虚拟DOM的Class属性
- 课程体系包括哪些要素_利润的构成要素包括哪些部分
- QT每日一练day10:设计一个登陆界面
- java编译sql存过_SQL SERVER 临时表导致存储过程重编译(recompile)的一些探讨
- Java调用存储过程返回数组
- Service GIS
- OrCAD设计原理图
- 七步法计算测量不确定度:第八步
- F28335第一篇——看门狗的开断
- 第26课:JSP Cookie 处理 读取和删除cookie(JSP教程 JSP入门实战教程 黄菊华Java网站开发系列教程)
- mongoDB可视化工具Robo 3T
- 腾讯小程序服务器忙,使用腾讯云助手小程序管理腾讯云服务器
- 微信可上线类型与封杀理由
- (FMD)辉芒MCU开发指南
- linux 文件唯一标识符,详解Linux中获取全球唯一标示符UUID的方法
- linux 下 POCO 安装
- “最敬业变脸”值得点赞
热门文章
- 云风Skynet——skynet非官方网站
- U盘中毒(一堆.scr扩展名的文件),文件不见了怎么办,怎么恢复隐藏文件
- 自信心、自制力。Java
- centos install fcitx
- bat文件快捷打开指定的程序、文件夹、文档或Internet资源
- 机场精细化管理_【青海机场公司召开“强化‘三基’固根本 精益管理促发展”主题交流会议】...
- 【CF 732E】Sockets(优先队列+贪心)
- 锻炼编程能力的10个游戏:通关既巅峰
- [NEXT] 时间管理实践
- Java内部类介绍 - 静态内部类和成员内部类