前言
最近 @Daax 公布了一个关于ACPI检测虚拟机的方法,我对此比较感兴趣,于是研究了一下
ACPI & ACPI table
ACPI表示高级配置和电源管理接口(Advanced Configuration and Power Management Interface)。对于Windows2000,ACPI定义了Windows 2000、BIOS和系统硬件之间的新型工作接口。这些新接口包括允许Windows 2000控制电源管理和设备配置的机制。
ACPI table是填写这些配置的地方
很好的是,ACPI可以通过R3的NtQuerySystemInformation拿得到
通过FirmwareTablesView.exe我们能很轻易的看到:
虚拟机 vs 物理机
well..在此声明,在我第一眼看 @Daax 的介绍时候,我第一印象就是这不就是vmp3.x后读 Firmware 拿配置嘛,烂大街了,这项技术很早之前就有了,并不神秘:
https://github.com/classic130/VMProtect-Source/blob/a8433f06ee84fa2546e40bef71183827dc230a3b/runtime/core.cc#L329
不不不,今天不会介绍那么古老的技术,而是介绍一些"新"的.
让我们编写代码,获取虚拟机与物理机之间的差异,这是一个简单的快速实现:
static const auto FirmwareTableProviderSignature = 'ACPI';
auto main() -> int {
printf("acpi sandbox detect by huoji 2023.6.19 \n");
auto firmwareTableBufferSize =
EnumSystemFirmwareTables(FirmwareTableProviderSignature, 0, 0);
char* firmwareTableBuffer = nullptr;
do {
if (firmwareTableBufferSize == 0) {
break;
}
firmwareTableBuffer =
reinterpret_cast<char*>(malloc(firmwareTableBufferSize));
if (firmwareTableBuffer == nullptr) {
break;
}
firmwareTableBufferSize = EnumSystemFirmwareTables(
FirmwareTableProviderSignature, firmwareTableBuffer,
firmwareTableBufferSize);
if (firmwareTableBufferSize == 0) {
break;
}
bool foundHpet = false;
auto index = 0;
for (size_t i = 0; i < firmwareTableBufferSize / 4; i++) {
const auto tableHeader = reinterpret_cast<acpi_table_header*>(
reinterpret_cast<uint64_t>(firmwareTableBuffer) + i);
const auto tableID = *firmwareTableBuffer;
char tid[6] = {0};
char oemid[7] = {0};
memcpy(tid, &tableHeader->signature, sizeof(unsigned long));
memcpy(oemid, reinterpret_cast<char*>(tableHeader->oem_id),
sizeof(tableHeader->oem_id));
printf("tid: %s oemid: %s oem_table_id: %08X \n", tid, oemid,
tableHeader->oem_table_id);
index++;
}
if (index < 7) {
printf("[detected] table size \n");
}
if (foundHpet == false) {
printf("[detected] HPET not found,Cuckoo detected \n");
}
} while (false);
if (firmwareTableBuffer != nullptr) {
free(firmwareTableBuffer);
}
getchar();
return 0;
}
这是物理机的:
这是在Vmware虚拟机里面的:
这是在布谷鸟沙箱里面的:
看看我们发现了什么:
在windows的虚拟机中,会存在'WAETH'这个OEM_ID
在Vbox/KVM/XEN等非linux hypervisor中,则没有WAETH,只有OEMID(而且OEMID配置不当导致出现问题)
此外这个table的表也存在问题,在虚拟机里面的比在外面的少.
因此我们可以很快的实现一个检测是否在沙箱中的POC
POC
这个POC检测什么:
检测ACPI表内容,如果小于8那么可能是虚拟机
检测ACPI是否有windows的WEATH,如果有则说明在windows的虚拟机中
检测ACPI表中是否没有HPET,如果没有,则说明可能在linux下的沙箱中
here we go:
https://github.com/huoji120/ACPI_SANDBOX_DETECT
vmware:
Cuckoo:
扩展: WEATH是什么
https://download.microsoft.com/download/7/E/7/7E7662CF-CBEA-470B-A97E-CE7CE0D98DC2/WAET.docx
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)