Skip to content

Commit 4664aa1

Browse files
author
Requiem
committed
dsdt firmware scanning
1 parent bcd46e8 commit 4664aa1

File tree

1 file changed

+107
-110
lines changed

1 file changed

+107
-110
lines changed

src/vmaware.hpp

Lines changed: 107 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -8910,31 +8910,30 @@ struct VM {
89108910
*/
89118911
[[nodiscard]] static bool firmware_scan() {
89128912
#if (WINDOWS)
8913-
#pragma warning (disable: 4459)
8913+
#pragma warning(disable: 4459)
89148914
typedef enum _SYSTEM_INFORMATION_CLASS {
89158915
SystemFirmwareTableInformation = 76
89168916
} SYSTEM_INFORMATION_CLASS;
8917-
8918-
typedef enum _SYSTEM_FIRMWARE_TABLE_ACTION
8919-
{
8917+
typedef enum _SYSTEM_FIRMWARE_TABLE_ACTION {
89208918
SystemFirmwareTableEnumerate,
89218919
SystemFirmwareTableGet,
89228920
SystemFirmwareTableMax
89238921
} SYSTEM_FIRMWARE_TABLE_ACTION;
8924-
8925-
typedef struct _SYSTEM_FIRMWARE_TABLE_INFORMATION
8926-
{
8922+
typedef struct _SYSTEM_FIRMWARE_TABLE_INFORMATION {
89278923
ULONG ProviderSignature;
89288924
SYSTEM_FIRMWARE_TABLE_ACTION Action;
89298925
ULONG TableID;
89308926
ULONG TableBufferLength;
89318927
_Field_size_bytes_(TableBufferLength) UCHAR TableBuffer[1];
89328928
} SYSTEM_FIRMWARE_TABLE_INFORMATION, * PSYSTEM_FIRMWARE_TABLE_INFORMATION;
8933-
#pragma warning (default : 4459)
8929+
#pragma warning(default: 4459)
89348930

89358931
typedef NTSTATUS(__stdcall* PNtQuerySystemInformation)(ULONG, PVOID, ULONG, PULONG);
89368932
constexpr ULONG STATUS_BUFFER_TOO_SMALL = 0xC0000023;
89378933
constexpr DWORD ACPI_SIG = 'ACPI';
8934+
constexpr DWORD ssdtSig = 'TDSS';
8935+
constexpr DWORD facpSig = 'PCAF';
8936+
constexpr DWORD dsdtSig = 'DSDT';
89388937

89398938
const HMODULE hNtdll = GetModuleHandle(_T("ntdll.dll"));
89408939
if (!hNtdll) return false;
@@ -8945,76 +8944,94 @@ struct VM {
89458944
util::GetFunctionAddresses(hNtdll, functionNames, functionPointers, 1);
89468945

89478946
const auto ntqsi = reinterpret_cast<PNtQuerySystemInformation>(functionPointers[0]);
8948-
if (!ntqsi)
8949-
return false;
8947+
if (!ntqsi) return false;
89508948

8951-
constexpr const char* targets[] = {
8952-
"Parallels Software International", "Parallels(R)", "innotek",
8953-
"Oracle", "VirtualBox", "vbox", "VBOX", "VS2005R2", "VMware, Inc.",
8954-
"VMware", "VMWARE", "S3 Corp.", "Virtual Machine", "QEMU", "WAET",
8955-
"BOCHS", "BXPC"
8949+
const char* targets[] = {
8950+
"Parallels Software International","Parallels(R)","innotek",
8951+
"Oracle","VirtualBox","vbox","VBOX","VS2005R2",
8952+
"VMware, Inc.","VMware","VMWARE",
8953+
"S3 Corp.","Virtual Machine","QEMU","WAET","BOCHS","BXPC"
89568954
};
89578955

89588956
PBYTE qsiBuffer = nullptr;
89598957
ULONG qsiBufferSize = 0;
89608958

8959+
auto clear_buffer = [&]() {
8960+
if (qsiBuffer) {
8961+
free(qsiBuffer);
8962+
qsiBuffer = nullptr;
8963+
qsiBufferSize = 0;
8964+
}
8965+
};
8966+
89618967
auto ensure_buffer = [&](ULONG needed) -> bool {
89628968
if (qsiBufferSize < needed) {
8963-
free(qsiBuffer);
8964-
qsiBuffer = static_cast<PBYTE>(malloc(needed));
8965-
if (!qsiBuffer) {
8966-
qsiBufferSize = 0;
8969+
PBYTE newBuf = static_cast<PBYTE>(realloc(qsiBuffer, needed));
8970+
if (!newBuf) {
89678971
return false;
89688972
}
8973+
qsiBuffer = newBuf;
89698974
qsiBufferSize = needed;
89708975
}
89718976
return true;
89728977
};
89738978

8974-
auto query_table = [&](DWORD provider, DWORD tableID, PULONG outDataSize) -> PSYSTEM_FIRMWARE_TABLE_INFORMATION {
8975-
const ULONG header = sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION);
8976-
if (!ensure_buffer(header)) return nullptr;
8979+
auto query_table = [&](DWORD provider, DWORD tableID, PULONG outSize) -> PSYSTEM_FIRMWARE_TABLE_INFORMATION {
8980+
ULONG header = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
8981+
if (!ensure_buffer(header)) {
8982+
clear_buffer();
8983+
return nullptr;
8984+
}
89778985

89788986
auto hdr = reinterpret_cast<PSYSTEM_FIRMWARE_TABLE_INFORMATION>(qsiBuffer);
89798987
hdr->ProviderSignature = provider;
89808988
hdr->Action = SystemFirmwareTableEnumerate;
89818989
hdr->TableID = _byteswap_ulong(tableID);
89828990
hdr->TableBufferLength = 0;
89838991

8984-
NTSTATUS st = ntqsi(SystemFirmwareTableInformation, hdr, header, outDataSize);
8985-
if (st != STATUS_BUFFER_TOO_SMALL)
8992+
NTSTATUS st = ntqsi(SystemFirmwareTableInformation, hdr, header, outSize);
8993+
if (st != STATUS_BUFFER_TOO_SMALL) {
8994+
clear_buffer();
89868995
return nullptr;
8996+
}
89878997

8988-
ULONG fullSize = *outDataSize;
8989-
if (!ensure_buffer(fullSize)) return nullptr;
8998+
ULONG fullSize = *outSize;
8999+
if (!ensure_buffer(fullSize)) {
9000+
clear_buffer();
9001+
return nullptr;
9002+
}
89909003

89919004
hdr = reinterpret_cast<PSYSTEM_FIRMWARE_TABLE_INFORMATION>(qsiBuffer);
89929005
hdr->ProviderSignature = provider;
89939006
hdr->Action = SystemFirmwareTableEnumerate;
89949007
hdr->TableID = _byteswap_ulong(tableID);
89959008
hdr->TableBufferLength = fullSize - header;
89969009

8997-
st = ntqsi(SystemFirmwareTableInformation, hdr, fullSize, outDataSize);
8998-
if (!NT_SUCCESS(st))
9010+
st = ntqsi(SystemFirmwareTableInformation, hdr, fullSize, outSize);
9011+
if (!NT_SUCCESS(st)) {
9012+
clear_buffer();
89999013
return nullptr;
9014+
}
90009015

90019016
return hdr;
90029017
};
90039018

9004-
auto check_firmware_table = [&](DWORD signature, DWORD tableID) -> bool {
9019+
auto check_firmware_table = [&](DWORD sig, DWORD id) -> bool {
90059020
ULONG gotSize = 0;
9006-
auto info = query_table(signature, tableID, &gotSize);
9021+
auto info = query_table(sig, id, &gotSize);
90079022
if (!info) return false;
90089023

90099024
const UCHAR* buf = info->TableBuffer;
9010-
const size_t bufLen = info->TableBufferLength;
9025+
size_t len = info->TableBufferLength;
90119026

90129027
for (auto target : targets) {
9013-
size_t tlen = strlen(target);
9014-
if (tlen > bufLen) continue;
9015-
for (size_t i = 0; i <= bufLen - tlen; ++i) {
9028+
const size_t tlen = strlen(target);
9029+
if (tlen > len) continue;
9030+
9031+
for (size_t i = 0; i <= len - tlen; ++i) {
90169032
if (memcmp(buf + i, target, tlen) == 0) {
90179033
const char* brand = nullptr;
9034+
90189035
if (!strcmp(target, "Parallels Software International") || !strcmp(target, "Parallels(R)"))
90199036
brand = brands::PARALLELS;
90209037
else if (!strcmp(target, "innotek") || !strcmp(target, "VirtualBox") || !strcmp(target, "vbox") || !strcmp(target, "VBOX") || !strcmp(target, "Oracle"))
@@ -9025,127 +9042,107 @@ struct VM {
90259042
brand = brands::QEMU;
90269043
else if (!strcmp(target, "BOCHS") || !strcmp(target, "BXPC"))
90279044
brand = brands::BOCHS;
9028-
else
9045+
else {
9046+
clear_buffer();
90299047
return true;
9048+
}
90309049

9050+
clear_buffer();
90319051
return core::add(brand);
90329052
}
90339053
}
90349054
}
90359055

9036-
// to detect VMAware's Hardener Loader
9037-
if (bufLen >= 6) {
9038-
for (size_t i = 0; i <= bufLen - 6; ++i) {
9039-
if (buf[i] == '7' && buf[i + 1] == '7' && buf[i + 2] == '7' && buf[i + 3] == '7' && buf[i + 4] == '7' && buf[i + 5] == '7') {
9056+
const char marker[] = "777777";
9057+
if (len >= sizeof(marker) - 1) {
9058+
for (size_t i = 0; i <= len - (sizeof(marker) - 1); ++i) {
9059+
if (memcmp(buf + i, marker, sizeof(marker) - 1) == 0) {
9060+
clear_buffer();
90409061
return core::add(brands::VMWARE_HARD);
90419062
}
90429063
}
90439064
}
9065+
9066+
clear_buffer();
90449067
return false;
90459068
};
90469069

9047-
// ACPI enumeration
90489070
ULONG totalLen = 0;
9049-
auto listInfo = query_table(ACPI_SIG, 0UL, &totalLen);
9071+
auto listInfo = query_table(ACPI_SIG, 0, &totalLen);
90509072
if (!listInfo) {
9051-
free(qsiBuffer);
9073+
clear_buffer();
90529074
return false;
90539075
}
90549076

90559077
const DWORD* tables = reinterpret_cast<const DWORD*>(listInfo->TableBuffer);
9056-
ULONG tableCount = listInfo->TableBufferLength / sizeof(DWORD);
9057-
9058-
if (tableCount < 4) { // idea by dmfrpro
9059-
free(qsiBuffer);
9078+
const ULONG tableCount = listInfo->TableBufferLength / sizeof(DWORD);
9079+
if (tableCount < 4) {
9080+
clear_buffer();
90609081
return true;
90619082
}
90629083

9063-
// count SSDT
9064-
constexpr DWORD ssdtSig = 'TDSS';
90659084
ULONG ssdtCount = 0;
90669085
for (ULONG i = 0; i < tableCount; ++i) {
9067-
if (tables[i] == ssdtSig)
9068-
++ssdtCount;
9069-
if (ssdtCount == 2)
9070-
break;
9086+
if (tables[i] == ssdtSig) ++ssdtCount;
9087+
if (ssdtCount == 2) break;
90719088
}
90729089
if (ssdtCount < 2) {
9073-
free(qsiBuffer);
9090+
clear_buffer();
90749091
return true;
90759092
}
90769093

9077-
constexpr DWORD facpSig = 'PCAF';
90789094
for (ULONG i = 0; i < tableCount; ++i) {
9079-
ULONG sig = tables[i];
9080-
9081-
if (sig == facpSig) {
9095+
if (tables[i] == facpSig) {
90829096
ULONG fSize = 0;
9083-
auto fadt = query_table(ACPI_SIG, sig, &fSize);
9084-
if (!fadt) continue;
9085-
BYTE* buf = reinterpret_cast<BYTE*>(fadt->TableBuffer);
9086-
// https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/05_ACPI_Software_Programming_Model/ACPI_Software_Programming_Model.html#preferred-pm-profile-system-types
9087-
if (fSize >= 45 + 1 && buf[45] == 0) { // idea by dmfrpro
9088-
free(qsiBuffer);
9097+
auto fadt = query_table(ACPI_SIG, tables[i], &fSize);
9098+
if (fadt && fSize > 45 && fadt->TableBuffer[45] == 0) {
9099+
clear_buffer();
90899100
return true;
90909101
}
90919102
}
9092-
if (check_firmware_table(ACPI_SIG, sig)) {
9093-
free(qsiBuffer);
9103+
if (check_firmware_table(ACPI_SIG, tables[i])) {
9104+
clear_buffer();
90949105
return true;
90959106
}
90969107
}
90979108

9098-
constexpr DWORD dsdtSig = 'DSDT';
9099-
ULONG dsdtSize = 0;
9100-
auto dsdt = query_table(ACPI_SIG, dsdtSig, &dsdtSize);
9101-
if (dsdt) {
9102-
const char* tb = reinterpret_cast<const char*>(dsdt->TableBuffer);
9103-
bool foundCPU = false;
9104-
9105-
for (ULONG j = 0; j + 8 <= dsdtSize; ++j) {
9106-
if (memcmp(tb + j, "ACPI0007", 8) == 0) { // idea by dmfrpro
9107-
foundCPU = true;
9108-
break;
9109-
}
9110-
}
9109+
const ULONG dsdtSize = GetSystemFirmwareTable(ACPI_SIG, _byteswap_ulong(dsdtSig), nullptr, 0);
9110+
if (dsdtSize == 0) {
9111+
clear_buffer();
9112+
return false;
9113+
}
91119114

9112-
if (!foundCPU) {
9113-
free(qsiBuffer);
9114-
return true;
9115-
}
9115+
BYTE* dsdtData = static_cast<BYTE*>(malloc(dsdtSize));
9116+
if (!dsdtData) {
9117+
clear_buffer();
9118+
return false;
9119+
}
91169120

9117-
constexpr const char* osi_targets[] = {
9118-
"Windows 95", "Windows 98",
9119-
"Windows 2000", "Windows 2000.1",
9120-
"Windows ME: Millennium Edition",
9121-
"Windows ME: Millennium Edition", // some firmwares omit space
9122-
"Windows XP", "Windows 2001",
9123-
"Windows 2006", "Windows 2009",
9124-
"Windows 2012", "Windows 2015",
9125-
"Windows 2020", "Windows 2022",
9126-
};
9127-
constexpr size_t n_osi = sizeof(osi_targets) / sizeof(osi_targets[0]);
9128-
9129-
bool foundOSI = false;
9130-
for (size_t t = 0; t < n_osi && !foundOSI; ++t) {
9131-
const char* s = osi_targets[t];
9132-
size_t len = strlen(s);
9133-
for (ULONG j = 0; j + len <= dsdtSize; ++j) {
9134-
if (memcmp(tb + j, s, len) == 0) {
9135-
foundOSI = true;
9136-
break;
9137-
}
9138-
}
9139-
}
9121+
if (GetSystemFirmwareTable(ACPI_SIG, _byteswap_ulong(dsdtSig), dsdtData, dsdtSize) != dsdtSize) {
9122+
free(dsdtData);
9123+
clear_buffer();
9124+
return false;
9125+
}
91409126

9141-
if (!foundOSI) {
9142-
free(qsiBuffer);
9143-
return true;
9127+
const char* str = reinterpret_cast<const char*>(dsdtData);
9128+
const char* osi_targets[] = { "Windows 95", "Windows 98", "Windows 2000", "Windows XP", "Windows 2012" };
9129+
bool foundOSI = false;
9130+
9131+
for (auto s : osi_targets) {
9132+
const size_t slen = strlen(s);
9133+
for (ULONG j = 0; j + slen <= dsdtSize; ++j) {
9134+
if (memcmp(str + j, s, slen) == 0) {
9135+
foundOSI = true;
9136+
break;
9137+
}
91449138
}
9139+
if (foundOSI) break;
91459140
}
91469141

9147-
free(qsiBuffer);
9148-
return false;
9142+
free(dsdtData);
9143+
clear_buffer();
9144+
9145+
return !foundOSI;
91499146
#elif (LINUX)
91509147
// Author: dmfrpro
91519148
if (!util::is_admin()) {

0 commit comments

Comments
 (0)