Skip to content

Commit c711c28

Browse files
author
Requiem
committed
firmware checks for SSDT acpi tables and FACP PM_Profile
1 parent 13ca60a commit c711c28

2 files changed

Lines changed: 109 additions & 21 deletions

File tree

docs/documentation.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -515,13 +515,13 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
515515
| `VM::ANYRUN_DIRECTORY` | Check for any.run directory and handle the status code | 🪟 | 35% | | | | Removed from the lib, only available in the CLI | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/cli.cpp#L713) |
516516
| `VM::DRIVER_NAMES` | Check for VM-specific names for drivers | 🪟 | 100% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L7426) |
517517
| `VM::DISK_SERIAL` | Check for serial numbers of virtual disks | 🪟 | 100% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L7581) |
518-
| `VM::PORT_CONNECTORS` | Check for physical connection ports | 🪟 | 25% | | | | This technique is known to false flag on devices like Surface Pro | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L7700) |
518+
| `VM::PORT_CONNECTORS` | Check for physical connection ports | 🪟 | 25% | | | | This technique is known to false flag on devices like Surface Pro, disabled by default | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L7700) |
519519
| `VM::GPU_CAPABILITIES` | Check for GPU capabilities related to VMs | 🪟 | 100% | Admin | | | Admin only needed for some heuristics | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L7785) |
520520
| `VM::GPU_VM_STRINGS` | Check for specific GPU string signatures related to VMs | 🪟 | 100% | | | | If GPU_CAPABILITIES also flags, the score will have 50 added instead of 100 | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L7730) |
521521
| `VM::VM_DEVICES` | Check for VM-specific devices | 🪟 | 50% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L7848) |
522522
| `VM::PROCESSOR_NUMBER` | Check for number of processors | 🪟 | 50% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L7999) |
523523
| `VM::NUMBER_OF_CORES` | Check for number of cores | 🪟 | 50% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L8024) |
524-
| `VM::ACPI_TEMPERATURE` | Check for device's temperature | 🪟 | 25% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L8057) |
524+
| `VM::ACPI_TEMPERATURE` | Check for device's temperature | 🪟 | 25% | | | | Disabled by default | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L8057) |
525525
| `VM::SYS_QEMU` | Check for existence of "qemu_fw_cfg" directories within /sys/module and /sys/firmware | 🐧 | 70% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L8330) |
526526
| `VM::LSHW_QEMU` | Check for QEMU string instances with lshw command | 🐧 | 80% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L8364) |
527527
| `VM::VIRTUAL_PROCESSORS` | Check if the number of virtual and logical processors are reported correctly by the system | 🪟 | 50% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L8411) |
@@ -531,7 +531,7 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
531531
| `VM::AMD_THREAD_MISMATCH` | Check for AMD CPU thread count database if it matches the system's thread count | 🐧🪟🍏 | 95% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L8871) |
532532
| `VM::NATIVE_VHD` | Check for OS being booted from a VHD container | 🪟 | 100% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L9482) |
533533
| `VM::VIRTUAL_REGISTRY` | Check for particular object directory which is present in Sandboxie virtual environment but not in usual host systems | 🪟 | 65% | | | | Admin only needed for Linux | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L9505) |
534-
| `VM::FIRMWARE` | Check for VM signatures and patched strings by hardeners in firmware, while ensuring the BIOS serial is valid | 🐧🪟 | 100% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L9601) |
534+
| `VM::FIRMWARE` | Check for VM signatures and patched strings by hardeners in firmware | 🐧🪟 | 100% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L9601) |
535535
| `VM::FILE_ACCESS_HISTORY` | Check if the number of accessed files are too low for a human-managed environment | 🐧 | 15% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L9950) |
536536
| `VM::AUDIO` | Check if any waveform-audio output devices are present in the system | 🪟 | 25% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L9980) |
537537
| `VM::UNKNOWN_MANUFACTURER` | Check if the CPU manufacturer is not known | 🐧🪟🍏 | 50% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L10016) |

src/vmaware.hpp

Lines changed: 106 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9241,7 +9241,6 @@ struct VM {
92419241
#endif
92429242
}
92439243

9244-
92459244
/**
92469245
* @brief Checks for VM signatures in firmware
92479246
* @category Windows
@@ -9382,7 +9381,7 @@ struct VM {
93829381
}
93839382
free(info);
93849383
return false;
9385-
};
9384+
};
93869385

93879386
// Check RSMB table
93889387
if (check_firmware_table(RSMB_SIG, 0UL))
@@ -9399,55 +9398,144 @@ struct VM {
93999398
(PSYSTEM_FIRMWARE_TABLE_INFORMATION)malloc(sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION));
94009399
if (!acpiEnum)
94019400
return false;
9402-
acpiEnum->ProviderSignature = ACPI_SIG;
9401+
9402+
acpiEnum->ProviderSignature = ACPI_SIG; // 'ACPI'
94039403
acpiEnum->Action = 0;
94049404
acpiEnum->TableID = 0;
94059405
acpiEnum->TableBufferLength = 0;
9406+
94069407
ULONG retLen = 0;
9407-
NTSTATUS status = ntqsi(SystemFirmwareTableInformation,
9408+
NTSTATUS status = ntqsi(
9409+
SystemFirmwareTableInformation,
94089410
acpiEnum,
94099411
sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION),
9410-
&retLen);
9412+
&retLen
9413+
);
9414+
94119415
if (status == STATUS_BUFFER_TOO_SMALL)
94129416
{
94139417
free(acpiEnum);
94149418
acpiEnum = (PSYSTEM_FIRMWARE_TABLE_INFORMATION)malloc(retLen);
94159419
if (!acpiEnum)
94169420
return false;
9421+
94179422
acpiEnum->ProviderSignature = ACPI_SIG;
94189423
acpiEnum->Action = 0;
94199424
acpiEnum->TableID = 0;
94209425
acpiEnum->TableBufferLength = retLen - sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION);
9421-
status = ntqsi(SystemFirmwareTableInformation,
9426+
9427+
status = ntqsi(
9428+
SystemFirmwareTableInformation,
94229429
acpiEnum,
94239430
retLen,
9424-
&retLen);
9431+
&retLen
9432+
);
94259433

9426-
const PDWORD table_names = (PDWORD)calloc(0x1000, 1);
9427-
if (!table_names) {
9434+
if (NT_SUCCESS(status))
9435+
{
9436+
const DWORD* tables = (const DWORD*)acpiEnum->TableBuffer;
9437+
ULONG tableCount = acpiEnum->TableBufferLength / sizeof(DWORD);
9438+
9439+
for (ULONG i = 0; i < tableCount; ++i)
9440+
{
9441+
if (tables[i] == 'FACP')
9442+
{
9443+
PSYSTEM_FIRMWARE_TABLE_INFORMATION fadtEnum =
9444+
(PSYSTEM_FIRMWARE_TABLE_INFORMATION)malloc(sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION));
9445+
if (!fadtEnum)
9446+
break;
9447+
9448+
fadtEnum->ProviderSignature = ACPI_SIG;
9449+
fadtEnum->Action = 0;
9450+
fadtEnum->TableID = tables[i];
9451+
fadtEnum->TableBufferLength = 0;
9452+
9453+
ULONG fadtLen = 0;
9454+
NTSTATUS st2 = ntqsi(
9455+
SystemFirmwareTableInformation,
9456+
fadtEnum,
9457+
sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION),
9458+
&fadtLen
9459+
);
9460+
9461+
if (st2 == STATUS_BUFFER_TOO_SMALL)
9462+
{
9463+
free(fadtEnum);
9464+
fadtEnum = (PSYSTEM_FIRMWARE_TABLE_INFORMATION)malloc(fadtLen);
9465+
if (fadtEnum)
9466+
{
9467+
fadtEnum->ProviderSignature = ACPI_SIG;
9468+
fadtEnum->Action = 0;
9469+
fadtEnum->TableID = tables[i];
9470+
fadtEnum->TableBufferLength = fadtLen - sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION);
9471+
9472+
if (NT_SUCCESS(ntqsi(
9473+
SystemFirmwareTableInformation,
9474+
fadtEnum,
9475+
fadtLen,
9476+
&fadtLen
9477+
)))
9478+
{
9479+
// https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/05_ACPI_Software_Programming_Model/ACPI_Software_Programming_Model.html#preferred-pm-profile-system-types
9480+
BYTE* fadtBuf = (BYTE*)fadtEnum->TableBuffer;
9481+
if (fadtBuf[45] == 0) {
9482+
debug("FIRMWARE: Preferred_PM_Profile == 0 (Unspecified)");
9483+
free(fadtEnum);
9484+
free(acpiEnum);
9485+
return true;
9486+
}
9487+
}
9488+
}
9489+
}
9490+
9491+
if (fadtEnum) free(fadtEnum);
9492+
break;
9493+
}
9494+
}
9495+
}
9496+
9497+
const PDWORD tableNames = (PDWORD)calloc(0x1000, 1);
9498+
if (!tableNames) {
94289499
free(acpiEnum);
94299500
return false;
94309501
}
94319502
const DWORD sig = 'ACPI';
9432-
const DWORD table_size = EnumSystemFirmwareTables(sig, table_names, 0x1000);
9433-
if (table_size < 4) { // Check made by dmfrpro
9503+
const DWORD bytes = EnumSystemFirmwareTables(sig, tableNames, 0x1000);
9504+
const ULONG tCount = bytes / sizeof(DWORD);
9505+
9506+
const DWORD ssdtSig = 'SSDT';
9507+
ULONG ssdtCount = 0;
9508+
for (ULONG i = 0; i < tCount; ++i) {
9509+
if (tableNames[i] == ssdtSig) ++ssdtCount;
9510+
}
9511+
if (ssdtCount == 1) {
9512+
debug("FIRMWARE: Only one SSDT table found");
9513+
free(tableNames);
9514+
free(acpiEnum);
9515+
return true;
9516+
}
9517+
9518+
// RSDT/XSDT, FADT, DSDT and RSDP (this one since it’s required as a pointer althought not being a true table)
9519+
if (tCount < 4) { // by dmfrpro
94349520
debug("FIRMWARE: not enough ACPI tables found");
9435-
free(table_names);
9521+
free(tableNames);
94369522
free(acpiEnum);
94379523
return true;
94389524
}
9525+
94399526
if (NT_SUCCESS(status)) {
9440-
const DWORD* tables = reinterpret_cast<const DWORD*>(acpiEnum->TableBuffer);
9441-
ULONG tableCount = acpiEnum->TableBufferLength / sizeof(DWORD);
9442-
for (ULONG t = 0; t < tableCount; ++t) {
9443-
if (check_firmware_table(ACPI_SIG, tables[t])) {
9444-
free(table_names);
9527+
const DWORD* tables2 = reinterpret_cast<const DWORD*>(acpiEnum->TableBuffer);
9528+
ULONG bufTableCnt = acpiEnum->TableBufferLength / sizeof(DWORD);
9529+
for (ULONG t = 0; t < bufTableCnt; ++t) {
9530+
if (check_firmware_table(ACPI_SIG, tables2[t])) {
9531+
free(tableNames);
94459532
free(acpiEnum);
94469533
return true;
94479534
}
94489535
}
94499536
}
9450-
free(table_names);
9537+
9538+
free(tableNames);
94519539
}
94529540
free(acpiEnum);
94539541

0 commit comments

Comments
 (0)