ACPI & ACPI table
ACPI 表示高级配置和电源管理接口(Advanced Configuration and Power Management Interface),对于Windows2000,ACPI定义了Windows2000、BIOS和系统硬件之间的新型工作接口。这些新接口包括允许Windows 2000控制电源管理和设备配置的机制。ACPI table 是填写这些配置的地方。
很好的是,ACPI可以通过R3的 NtQuerySystemInformation 拿得到
https://github.com/classic130/VMProtect-Source/blob/a8433f06ee84fa2546e40bef71183827dc230a3b/runtime/core.cc#L329 这是一个vmp3.x后读Firmware 拿配置。很早之前的技术。
我们本次介绍的是一个新技术,让我们编写代码,获取虚拟机与物理机之间的差异
#include <Windows.h>
#include <stdio.h>
#include <cstdint>
#include <iostream>
struct acpi_table_header {
uint32_t signature;
uint32_t length;
uint8_t revision;
uint8_t checksum;
char oem_id[6];
uint64_t oem_table_id;
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_revision;
};
struct hpet_acpi_data {
uint32_t hardware_block_id;
uint8_t space_id;
uint8_t bit_width;
uint8_t bit_offset;
uint8_t encoded_access_width;
uint64_t address;
uint8_t sequence_number;
uint16_t minimum_clock_ticks;
uint8_t flags;
};
static const auto FirmwareTableProviderSignature = 'ACPI';
auto main()->int{
printf("acpi sandbox detect by BOSS\n");
auto firmwareTableBufferSize=EnumSystemFirmwareTables(FirmwareTableProviderSignature,0,0);
char* firmwareTableBuffer = NULL;
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: %llX oem_table_xd: %llX
// \n",
// tid, oemid, tableHeader->oem_table_id,
// (tableHeader->oem_table_id & 0xFFFFFFFF));
if (memcmp(oemid, "WAET", 4) == 0) {
printf(
"[detected] Vmware detected by Windows ACPI Emulated"
"\n");
}
if (foundHpet == false && memcmp(oemid, "HPET", 4) == 0) {
foundHpet = true;
}
if ((tableHeader->oem_table_id & 0xFFFFFFFF) == 0) {
printf(
"[detected] Cuckoo sandbox detected by oem table id"
"\n");
}
index++;
}
if (index < 8) {
printf("[detected] vm-guest detected by table size \n");
}
if (foundHpet == false) {
printf("[detected] HPET not found,Cuckoo detected \n");
}
} while (false);
if (firmwareTableBuffer != nullptr) {
free(firmwareTableBuffer);
}
getchar();
return 0;
}
这个POC检测什么?
- 检测ACPI表内容,如果小于8那么可能是虚拟机
- 检测ACPI是否有windows的WEATH,如果有则说明windows在虚拟机中
- 检测ACPI表中是否没有HPET,如果没有,则说明可能在linux下的沙箱中
GitHub - huoji120/ACPI_SANDBOX_DETECT: 通过ACPI检测沙箱
https://download.microsoft.com/download/7/E/7/7E7662CF-CBEA-470B-A97E-CE7CE0D98DC2/WAET.docx