简介
虚拟技术是云计算的基础,而针对当前的虚拟化环境的安全检测。而虽然说虚拟化,其实当前虚拟技术的实现的一个基本共识就是运行在虚拟环境中的系统并不知道自己位于虚拟环境。那么对于红方来说,如何判断自己是在虚拟环境还是物理设备主机,对于制定针对性的安全方案尤为重要。除此之外,当前反病毒引擎的一个重要思想沙箱也是基于虚拟环境检查病毒行为。而相应的,病毒如何判断自己在虚拟环境还是真实设备也显得重要(可以调整自己的行为,规避查杀)。
当前主流的虚拟化实现方案
-
##### 硬件虚拟化(VM)
- qemu
- kvm
- vmware
- miscrosoft
- oracle
- xen
- bochs
-
##### 容器
- chroot
- docker
- lxc
这里主要分析VM,主要是qemu和Vmware。
VMdetect
Vmtect是多年前,针对Vmware
虚拟机的检测。但是时间比较长远了,很多场合不再适用。
通过特权指令检测虚拟机
Vmware为宿主机和虚拟机间提供了相互沟通的方式,使用IN
指令读取特定端口的数据进行通讯,但是IN
本身属于特权指令,在出于保护模式的宿主机直接运行时会触发EXCEPTION_PRIV_INSTUCTION
异常(除非权限运行),而虚拟机不会发生异常。
利用IDT基址检测虚拟机
利用LDT和GDT检测虚拟机
基于STR检测
基于注册表检测
基于时间差检测
基于虚拟硬件指纹检测
这一部分泉哥在看雪上有一篇很详细虚拟机检测技术剖析
Command-Line
虚拟的一些设备和真实物理主机设备信息有些差异,可以通过一些特殊指令获得相关信息。
dmidecode(need root)
dmidecode指令可以获取系统硬件相关的一些信息,原理是将DMI数据库信息解码,输出的信息包括BIOS、系统、主板、处理器、内存、缓存等。
在VMware中
在qemu启动的虚拟机中
在真实的物理主机上
在某云主机上
systemd-detect-virt(不需要root权限)
即可以识别是否处于vm,还可以识别container, 官方描述
It identifies the virtualization technology and can distinguish full machine virtualization from container virtualization. systemd-detect-virt exits with a return value of 0 (success) if a virtualization technology is detected, and non-zero (error) otherwise. By default, any type of virtualization is detected, and the options --container and --vm can be used to limit what types of virtualization are detected.
在vmware主机
在qemu-kvm启动的虚拟机
在真实物理主机
在某云主机
What I Found
我最近复现qemu逃逸漏洞,于是就想到一个问题:如何在qemu启动的虚拟机确认qemu的具体版本号
最先想到的方式是通过附加qemu进程,搜索qemu version
相关字符串。
找到qemu_get_version
函数,交叉引用找到引用该函数的一些接口
简单分析了下,与scsi
相关,在处理INQUIRY
类型命令时会获取qemu版本信息。
case INQUIRY:
if (!scsi_target_emulate_inquiry(r)) {
goto illegal_request;
}
static bool scsi_target_emulate_inquiry(SCSITargetReq *r)
{
.... /* PAGE CODE == 0 */
r->len = MIN(r->req.cmd.xfer, SCSI_INQUIRY_LEN);
memset(r->buf, 0, r->len);
if (r->req.lun != 0) {
r->buf[0] = TYPE_NO_LUN;
} else {
r->buf[0] = TYPE_NOT_PRESENT | TYPE_INACTIVE;
r->buf[2] = 5; /* Version */
r->buf[3] = 2 | 0x10; /* HiSup, response data format */
r->buf[4] = r->len - 5; /* Additional Length = (Len - 1) - 4 */
r->buf[7] = 0x10 | (r->req.bus->info->tcq ? 0x02 : 0); /* Sync, TCQ. */
memcpy(&r->buf[8], "QEMU ", 8);
memcpy(&r->buf[16], "QEMU TARGET ", 16);
pstrcpy((char *) &r->buf[32], 4, qemu_get_version());
}
}
于是参照sg3_utils项目中的scsi_inquiry
想要触发这里(没成功,虽然成功完成了SCSI_COMMAND,但是在所有与scsi相关的函数下断,没能断下,很奇怪,望了解的师傅指点下)。但是后来发现一个更简单的方式。
直接在Linux主机运行命令cat /proc/scsi/scsi
或者lsscsi
查看
VMware主机
qemu 2.5.92 和 2.2 启动的虚拟机
真实物理主机
All In One
各种检测虚拟机的手段可以分为以下几类
- 搜索虚拟环境的进程、文件系统、注册表
- 搜索虚拟环境内存
- 搜索虚拟环境特定虚拟硬件
- 搜索虚拟环境的特定处理器指令和功能