[2023]通过ACPI检测沙箱 huoji 沙箱,ACPI 2023-06-19 1111 次浏览 18 次点赞 ### 前言 最近 @Daax [公布](https://revers.engineering/evading-trivial-acpi-checks/ "公布")了一个关于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(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( reinterpret_cast(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(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检测什么: 1. 检测ACPI表内容,如果小于8那么可能是虚拟机 2. 检测ACPI是否有windows的WEATH,如果有则说明在windows的虚拟机中 3. 检测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 本文由 huoji 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。 点赞 18
还不快抢沙发