qemu-spoof: seed-driven per-VM hardware-identity anti-detection for pve-qemu
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
/* spoof-acpi.c — ACPI table header identity. OEM id / table id come from the
|
||||
* PLATFORM anchor (spoof-platform.c) so they cohere with the machine / BIOS /
|
||||
* baseboard. Only the creator id (the ASL compiler) is its own pool. */
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/misc/spoof.h"
|
||||
#include "hw/misc/spoof-core.h"
|
||||
|
||||
/* 4-byte creator id: real machines are overwhelmingly the Intel ASL compiler. */
|
||||
static const char *const CREATOR[] = { "INTL", "INTL", "INTL", "MSFT", "AMI ", "ACPI", "PTL " };
|
||||
|
||||
const char *spoof_acpi_oem_id(const char *def)
|
||||
{
|
||||
return spoof_on() ? spoof_plat_acpi_oem() : def;
|
||||
}
|
||||
const char *spoof_acpi_oem_table_id(const char *def)
|
||||
{
|
||||
return spoof_on() ? spoof_plat_acpi_table() : def;
|
||||
}
|
||||
const char *spoof_acpi_creator_id(const char *def)
|
||||
{
|
||||
return spoof_on() ? SPOOF_PICK("acpi.creator", CREATOR) : def;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/* spoof-audio.c — HDA codec identity (real machines = Realtek ALC, not a QEMU id). */
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/misc/spoof.h"
|
||||
#include "hw/misc/spoof-core.h"
|
||||
|
||||
/* 32-bit HDA codec vendor/device id (Realtek vendor 0x10EC). */
|
||||
static const uint32_t HDA_ID[] = {
|
||||
0x10EC0892, 0x10EC1220, 0x10EC0887, 0x10EC0255, 0x10EC0256, 0x10EC0897, 0x10EC0233,
|
||||
};
|
||||
static const char *const HDA_NAME[] = {
|
||||
"Realtek ALC892", "Realtek ALC1220", "Realtek ALC887", "Realtek ALC255",
|
||||
"Realtek ALC256", "Realtek ALC897", "Realtek ALC233",
|
||||
};
|
||||
|
||||
uint32_t spoof_hda_vendor_id(uint32_t def)
|
||||
{
|
||||
return spoof_on() ? HDA_ID[spoof_field("hda.id") % ARRAY_SIZE(HDA_ID)] : def;
|
||||
}
|
||||
const char *spoof_hda_name(const char *def)
|
||||
{
|
||||
return spoof_on() ? SPOOF_PICK("hda.name", HDA_NAME) : def;
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* spoof-core.c — seed/config acquisition + the deterministic derivation engine
|
||||
* + the policy knobs (hv mode / WAET / vmgenid). See spoof-core.h, spoof.h.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/cutils.h" /* pstrcpy */
|
||||
#include "hw/misc/spoof.h"
|
||||
#include "hw/misc/spoof-core.h"
|
||||
#include "hw/core/boards.h" /* current_machine */
|
||||
#include "qom/object.h"
|
||||
|
||||
const char SPOOF_A36[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
const char SPOOF_LET[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
const char SPOOF_DIG[] = "0123456789";
|
||||
|
||||
/* ---- config: machine property first, env var as a test fallback ----------- */
|
||||
static char g_seed[256];
|
||||
static bool g_ready, g_enabled;
|
||||
static char g_hv[16], g_waet[16], g_vgid[16], g_pvp[16];
|
||||
|
||||
static void read_prop(const char *prop, const char *env, char *out, size_t n)
|
||||
{
|
||||
out[0] = '\0';
|
||||
if (current_machine && object_property_find(OBJECT(current_machine), prop)) {
|
||||
char *v = object_property_get_str(OBJECT(current_machine), prop, NULL);
|
||||
if (v) { pstrcpy(out, n, v); g_free(v); }
|
||||
}
|
||||
if (!out[0]) {
|
||||
const char *e = getenv(env);
|
||||
if (e) { pstrcpy(out, n, e); }
|
||||
}
|
||||
}
|
||||
|
||||
static void config_load(void)
|
||||
{
|
||||
if (g_ready) {
|
||||
return;
|
||||
}
|
||||
read_prop("spoof-seed", "QEMU_SPOOF_SEED", g_seed, sizeof(g_seed));
|
||||
read_prop("spoof-hv", "QEMU_SPOOF_HV", g_hv, sizeof(g_hv));
|
||||
read_prop("spoof-waet", "QEMU_SPOOF_WAET", g_waet, sizeof(g_waet));
|
||||
read_prop("spoof-vmgenid", "QEMU_SPOOF_VMGENID", g_vgid, sizeof(g_vgid));
|
||||
read_prop("spoof-pvpanic", "QEMU_SPOOF_PVPANIC", g_pvp, sizeof(g_pvp));
|
||||
g_enabled = g_seed[0] != '\0';
|
||||
g_ready = true;
|
||||
}
|
||||
|
||||
bool spoof_on(void) { config_load(); return g_enabled; }
|
||||
bool spoof_enabled(void) { return spoof_on(); }
|
||||
|
||||
/* ---- deterministic derivation: fnv1a(seed|key) -> splitmix64 -------------- */
|
||||
static uint64_t fnv1a(const char *s)
|
||||
{
|
||||
uint64_t h = 1469598103934665603ULL;
|
||||
for (; *s; s++) { h ^= (uint8_t)*s; h *= 1099511628211ULL; }
|
||||
return h;
|
||||
}
|
||||
static uint64_t mix(uint64_t x)
|
||||
{
|
||||
x += 0x9E3779B97F4A7C15ULL;
|
||||
x = (x ^ (x >> 30)) * 0xBF58476D1CE4E5B9ULL;
|
||||
x = (x ^ (x >> 27)) * 0x94D049BB133111EBULL;
|
||||
return x ^ (x >> 31);
|
||||
}
|
||||
uint64_t spoof_field(const char *key)
|
||||
{
|
||||
config_load();
|
||||
return mix(fnv1a(g_seed) ^ (fnv1a(key) * 0x100000001B3ULL));
|
||||
}
|
||||
uint64_t spoof_field_n(const char *key, unsigned i)
|
||||
{
|
||||
char k[96];
|
||||
snprintf(k, sizeof(k), "%s#%u", key, i);
|
||||
return spoof_field(k);
|
||||
}
|
||||
const char *spoof_pick(const char *key, const char *const *arr, size_t n)
|
||||
{
|
||||
return arr[spoof_field(key) % n];
|
||||
}
|
||||
void spoof_gen(const char *key, const char *cs, int len, char *out)
|
||||
{
|
||||
size_t m = strlen(cs);
|
||||
for (int i = 0; i < len; i++) {
|
||||
out[i] = cs[spoof_field_n(key, (unsigned)i) % m];
|
||||
}
|
||||
out[len] = '\0';
|
||||
}
|
||||
/* one cpu-vendor draw anchors BOTH the CPU signature and the chipset/PCI vendor. */
|
||||
int spoof_anchor_vendor(void)
|
||||
{
|
||||
return (int)(spoof_field("anchor.cpu") & 1); /* 0 Intel, 1 AMD */
|
||||
}
|
||||
|
||||
/* ---- policy knobs --------------------------------------------------------- */
|
||||
SpoofHvMode spoof_hv_mode(void)
|
||||
{
|
||||
config_load();
|
||||
if (!strcmp(g_hv, "hidden")) return SPOOF_HV_HIDDEN;
|
||||
if (!strcmp(g_hv, "hyperv")) return SPOOF_HV_HYPERV;
|
||||
if (!strcmp(g_hv, "off")) return SPOOF_HV_OFF;
|
||||
return g_enabled ? SPOOF_HV_HYPERV : SPOOF_HV_OFF; /* seeded default = hyperv */
|
||||
}
|
||||
bool spoof_waet_drop(void)
|
||||
{
|
||||
config_load();
|
||||
if (!strcmp(g_waet, "on")) return true;
|
||||
if (!strcmp(g_waet, "off")) return false;
|
||||
return g_enabled; /* seeded default = drop */
|
||||
}
|
||||
bool spoof_pvpanic_hide(void)
|
||||
{
|
||||
config_load();
|
||||
if (!strcmp(g_pvp, "on")) return true;
|
||||
if (!strcmp(g_pvp, "off")) return false;
|
||||
return g_enabled; /* seeded default = hide pvpanic */
|
||||
}
|
||||
SpoofVgidPolicy spoof_vmgenid_policy(void)
|
||||
{
|
||||
config_load();
|
||||
if (!strcmp(g_vgid, "hide")) return SPOOF_VGID_HIDE;
|
||||
if (!strcmp(g_vgid, "mask")) return SPOOF_VGID_MASK;
|
||||
if (!strcmp(g_vgid, "keep")) return SPOOF_VGID_KEEP;
|
||||
switch (spoof_hv_mode()) { /* default tracks hv mode */
|
||||
case SPOOF_HV_HIDDEN: return SPOOF_VGID_HIDE;
|
||||
case SPOOF_HV_HYPERV: return SPOOF_VGID_MASK;
|
||||
default: return SPOOF_VGID_KEEP;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* spoof-core.h — the engine shared by every spoof-<aspect>.c (INTERNAL).
|
||||
*
|
||||
* Pure, seed-driven derivation: no entropy, no files, deterministic. Aspect
|
||||
* modules use these to pick from pools or generate format-correct values, and
|
||||
* cache their own result (lazily) for stable storage.
|
||||
*/
|
||||
#ifndef QEMU_SPOOF_CORE_H
|
||||
#define QEMU_SPOOF_CORE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#endif
|
||||
|
||||
bool spoof_on(void); /* seed present */
|
||||
uint64_t spoof_field(const char *key); /* stable 64-bit draw for a key */
|
||||
uint64_t spoof_field_n(const char *key, unsigned i); /* nth independent draw */
|
||||
const char *spoof_pick(const char *key, const char *const *arr, size_t n);
|
||||
void spoof_gen(const char *key, const char *cs, int len, char *out); /* len chars from cs */
|
||||
int spoof_anchor_vendor(void); /* 0=Intel, 1=AMD (stable per seed) */
|
||||
|
||||
/* platform anchor (spoof-platform.c): one coherent machine identity per seed. */
|
||||
const char *spoof_plat_acpi_oem(void); /* 6-byte ACPI OEM id */
|
||||
const char *spoof_plat_acpi_table(void); /* 8-byte ACPI OEM table id */
|
||||
const char *spoof_plat_machine_desc(void); /* board model (CPU-vendor matched) */
|
||||
const char *spoof_plat_socket(void); /* that board's CPU socket */
|
||||
const char *spoof_plat_bios_vendor(void);
|
||||
const char *spoof_plat_baseboard(void);
|
||||
const char *spoof_plat_oem_string(void); /* SMBIOS type11 */
|
||||
|
||||
extern const char SPOOF_A36[37]; /* "0-9A-Z" + NUL */
|
||||
extern const char SPOOF_LET[27]; /* "A-Z" + NUL */
|
||||
extern const char SPOOF_DIG[11]; /* "0-9" + NUL */
|
||||
|
||||
#define SPOOF_PICK(key, arr) spoof_pick((key), (arr), ARRAY_SIZE(arr))
|
||||
|
||||
#endif /* QEMU_SPOOF_CORE_H */
|
||||
@@ -0,0 +1,44 @@
|
||||
/* spoof-cpu.c — CPUID hypervisor signature, anchored to the CPU vendor. */
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/misc/spoof.h"
|
||||
#include "hw/misc/spoof-core.h"
|
||||
|
||||
/* index 0 = Intel, 1 = AMD (the anchor). The chipset/PCI vendor tracks this. */
|
||||
static const char *const KVM_SIG[] = { "GenuineIntel", "AuthenticAMD" };
|
||||
|
||||
const char *spoof_kvm_signature(const char *def)
|
||||
{
|
||||
return spoof_on() ? KVM_SIG[spoof_anchor_vendor()] : def;
|
||||
}
|
||||
|
||||
/* CPUID leaf 0x16 (Processor Frequency Information) — QEMU returns zeros; real
|
||||
* CPUs report base/max/bus MHz. Fill plausible, self-consistent values. */
|
||||
static const int BASE_MHZ[] = { 2400, 2900, 3000, 3200, 3400, 3600, 3700, 3800 };
|
||||
static const int TURBO_MHZ[] = { 400, 600, 800, 1000, 1200, 1400 };
|
||||
|
||||
int spoof_cpu_base_mhz(int def)
|
||||
{
|
||||
return spoof_on() ? BASE_MHZ[spoof_field("cpu.base") % ARRAY_SIZE(BASE_MHZ)] : def;
|
||||
}
|
||||
int spoof_cpu_max_mhz(int def)
|
||||
{
|
||||
if (!spoof_on()) return def;
|
||||
return spoof_cpu_base_mhz(0) + TURBO_MHZ[spoof_field("cpu.turbo") % ARRAY_SIZE(TURBO_MHZ)];
|
||||
}
|
||||
int spoof_cpu_bus_mhz(int def)
|
||||
{
|
||||
return spoof_on() ? 100 : def;
|
||||
}
|
||||
/* Microcode revision, returned already positioned for the MSR (IA32_UCODE_REV
|
||||
* 0x8B): Intel reports the revision in bits 63:32, AMD the patch level in 31:0.
|
||||
* Stock QEMU/KVM defaults (Intel 0x1_00000000, AMD 0x01000065) follow the same
|
||||
* layout, so the seeded value stays a drop-in. Anchored to the persona's CPU
|
||||
* vendor (the operator drives -cpu to match, as with the KVM signature). */
|
||||
uint64_t spoof_cpu_microcode(uint64_t def)
|
||||
{
|
||||
if (!spoof_on()) return def;
|
||||
if (spoof_anchor_vendor()) { /* AMD: patch level, low dword */
|
||||
return 0x0A201000ull | (uint64_t)(spoof_field("ucode") & 0xFFF);
|
||||
}
|
||||
return ((uint64_t)(0xC0u | (spoof_field("ucode") & 0x3F))) << 32; /* Intel: revision, hi dword */
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/* spoof-display.c — EDID: vendor + name from pools; product code / serial /
|
||||
* manufacture date GENERATED (real per-unit fields). */
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/misc/spoof.h"
|
||||
#include "hw/misc/spoof-core.h"
|
||||
|
||||
static const char *const EDID_VEND[] = {
|
||||
"DEL", "SAM", "AUS", "LEN", "HWP", "ACR", "BNQ", "GSM", "AOC", "MSI", "VSC", "PHL",
|
||||
"GBT", "IVM", "NEC", "EIZ", "SHP", "SNY", "AUO", "CMN", "LGD", "BOE", "HSD", "VIZ",
|
||||
};
|
||||
static const char *const EDID_NAME[] = {
|
||||
"DELL U2415", "DELL P2419H", "DELL S2721DGF", "SyncMaster", "S24F350", "Odyssey G5",
|
||||
"ASUS VG248", "VG279Q", "ProArt PA248", "LG 27GL850", "27GP850", "UltraGear",
|
||||
"BenQ GL2480", "HP 24mh", "HP X27q", "ThinkVision T24i", "Acer KG241", "Nitro VG240",
|
||||
"AOC 24G2", "ViewSonic VX2458", "Philips 245V", "iiyama PL2480H", "EIZO EV2456", "MSI G241",
|
||||
};
|
||||
|
||||
const char *spoof_edid_vendor(const char *def)
|
||||
{
|
||||
return spoof_on() ? SPOOF_PICK("edid.vend", EDID_VEND) : def;
|
||||
}
|
||||
const char *spoof_edid_name(const char *def)
|
||||
{
|
||||
return spoof_on() ? SPOOF_PICK("edid.name", EDID_NAME) : def;
|
||||
}
|
||||
uint16_t spoof_edid_model(uint16_t def)
|
||||
{
|
||||
return spoof_on() ? (uint16_t)(spoof_field("edid.model") % 0xFFFE) + 1 : def;
|
||||
}
|
||||
uint32_t spoof_edid_serial(uint32_t def)
|
||||
{
|
||||
return spoof_on() ? (uint32_t)spoof_field("edid.serial") : def;
|
||||
}
|
||||
int spoof_edid_year(int def)
|
||||
{
|
||||
return spoof_on() ? 2017 + (int)(spoof_field("edid.year") % 8) : def; /* 2017..2024 */
|
||||
}
|
||||
int spoof_edid_week(int def)
|
||||
{
|
||||
return spoof_on() ? 1 + (int)(spoof_field("edid.week") % 52) : def;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/* spoof-fwcfg.c — fw_cfg signatures + ACPI _HID (the "QEMU"/"QEMU CFG" tells). */
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/misc/spoof.h"
|
||||
#include "hw/misc/spoof-core.h"
|
||||
|
||||
static const char *const FWCFG_SIG[] = {
|
||||
"INTL", "ASUS", "DELL", "LENV", "HPQ ", "MSI ", "ACER", "GBT ", "ASRK", "SUPM", "BIOS", "SONY",
|
||||
};
|
||||
static const char *const FWCFG_DEVID[] = {
|
||||
"INTC0002", "PNP0C01", "PNP0C02", "ASUS0002", "DELL0002", "LEN0078", "HPQ0002",
|
||||
"MSFT0002", "ACPI0002", "INT33A0",
|
||||
};
|
||||
|
||||
const char *spoof_fwcfg_sig(const char *def)
|
||||
{
|
||||
return spoof_on() ? SPOOF_PICK("fwcfg.sig", FWCFG_SIG) : def;
|
||||
}
|
||||
const char *spoof_fwcfg_acpi_devid(const char *def)
|
||||
{
|
||||
return spoof_on() ? SPOOF_PICK("fwcfg.devid", FWCFG_DEVID) : def;
|
||||
}
|
||||
uint64_t spoof_fwcfg_dma_sig(uint64_t def)
|
||||
{
|
||||
if (!spoof_on()) {
|
||||
return def;
|
||||
}
|
||||
uint64_t v = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
v = (v << 8) | (uint8_t)SPOOF_A36[spoof_field_n("fwcfg.dma", (unsigned)i) % (sizeof(SPOOF_A36) - 1)];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* spoof-machine.c — the QEMU machine `desc` string. Comes from the PLATFORM
|
||||
* anchor (spoof-platform.c) so the model matches the ACPI OEM / BIOS / baseboard. */
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/misc/spoof.h"
|
||||
#include "hw/misc/spoof-core.h"
|
||||
|
||||
const char *spoof_machine_desc(const char *def)
|
||||
{
|
||||
return spoof_on() ? spoof_plat_machine_desc() : def;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/* spoof-pci.c — PCI identity: hide the Red Hat/virtio fingerprint, anchored to
|
||||
* the CPU vendor so the chipset matches the CPU (Intel CPU -> Intel chipset). */
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/misc/spoof.h"
|
||||
#include "hw/misc/spoof-core.h"
|
||||
|
||||
static const uint16_t PCI_VENDOR[] = { 0x8086 /* Intel */, 0x1022 /* AMD */ };
|
||||
|
||||
uint16_t spoof_pci_vendor(uint16_t def)
|
||||
{
|
||||
return spoof_on() ? PCI_VENDOR[spoof_anchor_vendor()] : def;
|
||||
}
|
||||
uint16_t spoof_pci_subvendor(uint16_t def)
|
||||
{
|
||||
return spoof_on() ? PCI_VENDOR[spoof_anchor_vendor()] : def;
|
||||
}
|
||||
uint16_t spoof_pci_device(const char *role, uint16_t def)
|
||||
{
|
||||
if (!spoof_on()) {
|
||||
return def;
|
||||
}
|
||||
/* TODO: curated real per-role device-id table. For now keep it stable per
|
||||
* role and in a plausible range (never the bogus device==vendor case). */
|
||||
char k[64];
|
||||
snprintf(k, sizeof(k), "pci.dev.%s", role ? role : "");
|
||||
return (uint16_t)(0x1500 + (spoof_field(k) % 0x0400));
|
||||
}
|
||||
/* Subsystem device id (the OEM/board sub-identity); subsystem vendor =
|
||||
* spoof_pci_subvendor. Gives QEMU-origin controllers an OEM-branded SSID. */
|
||||
uint16_t spoof_pci_subdevice(const char *role, uint16_t def)
|
||||
{
|
||||
if (!spoof_on()) {
|
||||
return def;
|
||||
}
|
||||
char k[64];
|
||||
snprintf(k, sizeof(k), "pci.ssid.%s", role ? role : "");
|
||||
return (uint16_t)(0x8000 | (spoof_field(k) & 0x7FFF));
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* spoof-platform.c — the PLATFORM anchor: one seed draw selects a coherent
|
||||
* machine identity (ACPI OEM id, ACPI table id, BIOS vendor, baseboard, the
|
||||
* board model AND its socket). The board list is split by CPU vendor and indexed
|
||||
* by the CPU anchor, so the board's chipset/socket always matches the CPU
|
||||
* (no "Intel H510 board + AMD CPU"). The board's own socket feeds SMBIOS type4.
|
||||
*
|
||||
* Two classes: OEM prebuilt (ACPI OEM = vendor code) and DIY/retail (AMI Aptio
|
||||
* firmware -> ACPI OEM "ALASKA"/"A M I"; the board brand is in the baseboard).
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/misc/spoof.h"
|
||||
#include "hw/misc/spoof-core.h"
|
||||
|
||||
typedef struct { const char *model, *socket; } Board;
|
||||
|
||||
/* --- OEM prebuilt: real Intel and (separate) AMD desktop SKUs --- */
|
||||
static const Board DELL_I[] = { {"OptiPlex 7090","LGA1200"}, {"OptiPlex 5090","LGA1200"},
|
||||
{"Precision 3650 Tower","LGA1200"}, {"OptiPlex 7000","LGA1700"} };
|
||||
static const Board DELL_A[] = { {"OptiPlex 5055","AM4"}, {"OptiPlex 7010 AMD","AM4"} };
|
||||
static const Board HP_I[] = { {"HP EliteDesk 800 G6","LGA1200"}, {"HP ProDesk 600 G6","LGA1200"},
|
||||
{"HP Z2 Tower G5","LGA1200"}, {"HP EliteDesk 800 G9","LGA1700"} };
|
||||
static const Board HP_A[] = { {"HP ProDesk 405 G6","AM4"}, {"HP ProDesk 485 G4","AM4"} };
|
||||
static const Board LEN_I[] = { {"ThinkCentre M720q","LGA1151"}, {"ThinkCentre M920t","LGA1151"},
|
||||
{"ThinkStation P340","LGA1200"}, {"ThinkCentre M70q Gen 3","LGA1700"} };
|
||||
static const Board LEN_A[] = { {"ThinkCentre M75q Gen 2","AM4"}, {"ThinkCentre M75s Gen 2","AM4"} };
|
||||
static const Board ACE_I[] = { {"Veriton M4660G","LGA1151"}, {"Aspire TC-895","LGA1200"},
|
||||
{"Aspire TC-1760","LGA1700"} };
|
||||
static const Board ACE_A[] = { {"Nitro N50-110","AM4"}, {"Aspire TC-380","AM4"} };
|
||||
|
||||
/* --- DIY/retail boards: the model unambiguously implies the socket --- */
|
||||
static const Board ASUS_I[] = { {"ROG STRIX Z590-E GAMING WIFI","LGA1200"}, {"PRIME B560M-A","LGA1200"},
|
||||
{"TUF GAMING Z690-PLUS WIFI","LGA1700"}, {"PRIME H610M-E D4","LGA1700"} };
|
||||
static const Board ASUS_A[] = { {"TUF GAMING B550M-PLUS","AM4"}, {"ROG STRIX X570-E GAMING","AM4"},
|
||||
{"PRIME B650M-A","AM5"}, {"ProArt X670E-CREATOR WIFI","AM5"} };
|
||||
static const Board GBT_I[] = { {"Z390 AORUS PRO","LGA1151"}, {"B660M DS3H DDR4","LGA1700"},
|
||||
{"Z690 AORUS ELITE AX","LGA1700"} };
|
||||
static const Board GBT_A[] = { {"X570 AORUS ELITE","AM4"}, {"B450 AORUS M","AM4"}, {"B650 AORUS ELITE AX","AM5"} };
|
||||
static const Board MSI_I[] = { {"MAG B560 TOMAHAWK","LGA1200"}, {"PRO B660M-A DDR4","LGA1700"},
|
||||
{"MPG Z690 CARBON WIFI","LGA1700"} };
|
||||
static const Board MSI_A[] = { {"MPG B550 GAMING PLUS","AM4"}, {"B450 TOMAHAWK MAX","AM4"},
|
||||
{"MAG B650 TOMAHAWK WIFI","AM5"} };
|
||||
static const Board ASR_I[] = { {"H510M-HVS","LGA1200"}, {"B660M Pro RS","LGA1700"},
|
||||
{"Z690 Steel Legend","LGA1700"} };
|
||||
static const Board ASR_A[] = { {"X570 Taichi","AM4"}, {"B450M Steel Legend","AM4"}, {"B650M PG Riptide","AM5"} };
|
||||
|
||||
typedef struct {
|
||||
const char *oem, *table, *bios, *board, *oemstr;
|
||||
const Board *intel; size_t ni;
|
||||
const Board *amd; size_t na;
|
||||
} Platform;
|
||||
|
||||
#define BL(a) (a), ARRAY_SIZE(a)
|
||||
static const Platform PLAT[] = {
|
||||
/* --- OEM prebuilt: ACPI OEM id = vendor code --- */
|
||||
{ "DELL ", "QA09 ", "Dell Inc.", "Dell Inc.", "Dell System", BL(DELL_I), BL(DELL_A) },
|
||||
{ "HPQOEM", "8054 ", "HP", "HP", "HP", BL(HP_I), BL(HP_A) },
|
||||
{ "LENOVO", "TP-N1Q ", "LENOVO", "LENOVO", "LENOVO", BL(LEN_I), BL(LEN_A) },
|
||||
{ "ACRSYS", "ACRSYS ", "Insyde Corp.", "Acer", "Acer System", BL(ACE_I), BL(ACE_A) },
|
||||
/* --- DIY/retail (AMI firmware): ACPI OEM id "ALASKA"; brand in baseboard --- */
|
||||
{ "ALASKA", "A M I ", "American Megatrends Inc.", "ASUSTeK COMPUTER INC.", "$ASUS$", BL(ASUS_I), BL(ASUS_A) },
|
||||
{ "ALASKA", "A M I ", "American Megatrends Inc.", "Gigabyte Technology Co., Ltd.", "GIGABYTE", BL(GBT_I), BL(GBT_A) },
|
||||
{ "ALASKA", "A M I ", "American Megatrends Inc.", "Micro-Star International Co., Ltd.", "MSI", BL(MSI_I), BL(MSI_A) },
|
||||
{ "ALASKA", "A M I ", "American Megatrends Inc.", "ASRock", "ASRock", BL(ASR_I), BL(ASR_A) },
|
||||
};
|
||||
|
||||
static const Platform *plat(void)
|
||||
{
|
||||
return &PLAT[spoof_field("anchor.platform") % ARRAY_SIZE(PLAT)];
|
||||
}
|
||||
/* the chosen board for THIS platform under the CPU-vendor anchor (Intel/AMD). */
|
||||
static const Board *chosen_board(void)
|
||||
{
|
||||
const Platform *p = plat();
|
||||
const Board *list = spoof_anchor_vendor() ? p->amd : p->intel;
|
||||
size_t n = spoof_anchor_vendor() ? p->na : p->ni;
|
||||
return &list[spoof_field("mach.board") % n];
|
||||
}
|
||||
|
||||
const char *spoof_plat_acpi_oem(void) { return plat()->oem; }
|
||||
const char *spoof_plat_acpi_table(void) { return plat()->table; }
|
||||
const char *spoof_plat_bios_vendor(void) { return plat()->bios; }
|
||||
const char *spoof_plat_baseboard(void) { return plat()->board; }
|
||||
const char *spoof_plat_machine_desc(void) { return chosen_board()->model; }
|
||||
const char *spoof_plat_socket(void) { return chosen_board()->socket; }
|
||||
const char *spoof_plat_oem_string(void) { return plat()->oemstr; }
|
||||
|
||||
const char *spoof_bios_vendor(const char *def)
|
||||
{
|
||||
return spoof_on() ? spoof_plat_bios_vendor() : def;
|
||||
}
|
||||
const char *spoof_baseboard_manufacturer(const char *def)
|
||||
{
|
||||
return spoof_on() ? spoof_plat_baseboard() : def;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/* spoof-smbios.c — SMBIOS: clear the type0 "VM" bit, fill type17 (memory) and
|
||||
* type4 (processor). CPU manufacturer + socket are anchored to the CPU vendor. */
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/misc/spoof.h"
|
||||
#include "hw/misc/spoof-core.h"
|
||||
|
||||
static const char *const MEM_MFR[] = {
|
||||
"Samsung", "SK Hynix", "Micron Technology", "Crucial", "Corsair",
|
||||
"G.Skill", "Kingston", "ADATA", "Patriot", "Team Group",
|
||||
};
|
||||
static const char *const CPU_MFR[] = { "Intel(R) Corporation", "Advanced Micro Devices, Inc." };
|
||||
|
||||
static const char *mem_prefix(const char *mfr)
|
||||
{
|
||||
if (!strncmp(mfr, "Samsung", 7)) return "M";
|
||||
if (!strncmp(mfr, "SK", 2)) return "HMA";
|
||||
if (!strncmp(mfr, "Micron", 6)) return "MTA";
|
||||
if (!strncmp(mfr, "Crucial", 7)) return "CT";
|
||||
if (!strncmp(mfr, "Corsair", 7)) return "CM";
|
||||
if (!strncmp(mfr, "G.Skill", 7)) return "F4-";
|
||||
if (!strncmp(mfr, "Kingston", 8)) return "K";
|
||||
return "AD";
|
||||
}
|
||||
|
||||
static struct {
|
||||
const char *mfr, *part_pre;
|
||||
char part[24], serial[12];
|
||||
bool done;
|
||||
} m;
|
||||
|
||||
static void m_init(void)
|
||||
{
|
||||
if (m.done) {
|
||||
return;
|
||||
}
|
||||
m.mfr = SPOOF_PICK("mem.mfr", MEM_MFR);
|
||||
char tail[16];
|
||||
spoof_gen("mem.part", SPOOF_A36, 12, tail);
|
||||
snprintf(m.part, sizeof(m.part), "%s%s", mem_prefix(m.mfr), tail);
|
||||
spoof_gen("mem.serial", SPOOF_A36, 8, m.serial);
|
||||
m.done = true;
|
||||
}
|
||||
|
||||
bool spoof_smbios_hide_vm(void) { return spoof_on(); }
|
||||
|
||||
const char *spoof_smbios_mem_manufacturer(const char *def)
|
||||
{
|
||||
if (!spoof_on()) return def;
|
||||
m_init(); return m.mfr;
|
||||
}
|
||||
const char *spoof_smbios_mem_part(const char *def)
|
||||
{
|
||||
if (!spoof_on()) return def;
|
||||
m_init(); return m.part;
|
||||
}
|
||||
const char *spoof_smbios_mem_serial(const char *def)
|
||||
{
|
||||
if (!spoof_on()) return def;
|
||||
m_init(); return m.serial;
|
||||
}
|
||||
const char *spoof_smbios_cpu_manufacturer(const char *def)
|
||||
{
|
||||
return spoof_on() ? CPU_MFR[spoof_anchor_vendor()] : def;
|
||||
}
|
||||
const char *spoof_smbios_cpu_socket(const char *def)
|
||||
{
|
||||
/* the socket of the platform's chosen board -> matches the model + CPU vendor. */
|
||||
return spoof_on() ? spoof_plat_socket() : def;
|
||||
}
|
||||
const char *spoof_smbios_oem_string(const char *def) /* type11 */
|
||||
{
|
||||
return spoof_on() ? spoof_plat_oem_string() : def;
|
||||
}
|
||||
int spoof_smbios_chassis_type(int def) /* type3: 3=Desktop, 10=Notebook */
|
||||
{
|
||||
if (!spoof_on()) return def;
|
||||
const char *m = spoof_plat_machine_desc();
|
||||
if (strstr(m, "ThinkPad") || strstr(m, "Latitude") || strstr(m, "EliteBook")) {
|
||||
return 10;
|
||||
}
|
||||
return 3; /* all current models are desktops */
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/* spoof-storage.c — disks/NVMe/CD-ROM. Model = pool; per-unit serial / WWN /
|
||||
* firmware / EUI64 / NGUID = GENERATED to brand-correct format. */
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/cutils.h" /* pstrcpy */
|
||||
#include "hw/misc/spoof.h"
|
||||
#include "hw/misc/spoof-core.h"
|
||||
|
||||
/* rpm: 1 = SSD (non-rotational), else the spinning rate — stored, not guessed. */
|
||||
typedef struct { const char *model; int rpm; } DiskModel;
|
||||
static const DiskModel DISK_MODEL[] = {
|
||||
{ "Samsung SSD 870 EVO 500GB", 1 }, { "Samsung SSD 860 EVO 1TB", 1 }, { "Samsung SSD 870 QVO 2TB", 1 },
|
||||
{ "WDC WD10EZEX-08WN4A0", 7200 }, { "WDC WD20EZBX-00AYRA0", 5400 }, { "WDC WDS500G2B0A-00SM50", 1 },
|
||||
{ "ST1000DM010-2EP102", 7200 }, { "ST2000DM008-2FR102", 7200 }, { "ST500DM002-1BD142", 7200 },
|
||||
{ "CT500MX500SSD1", 1 }, { "CT1000BX500SSD1", 1 }, { "KINGSTON SA400S37480G", 1 }, { "KINGSTON SKC600512G", 1 },
|
||||
{ "Crucial_CT525MX300SSD1", 1 }, { "TOSHIBA DT01ACA100", 7200 }, { "SanDisk SDSSDA240G", 1 },
|
||||
{ "INTEL SSDSC2KW256G8", 1 }, { "HGST HUS726T4TALA6L4", 7200 }, { "ADATA SU800", 1 }, { "PNY CS900 240GB", 1 },
|
||||
};
|
||||
static const char *const NVME_MODEL[] = {
|
||||
"Samsung SSD 980 1TB", "Samsung SSD 970 EVO Plus 1TB", "Samsung SSD 990 PRO 2TB",
|
||||
"WD_BLACK SN770 1TB", "WD Blue SN570 1TB", "KXG60ZNV512G TOSHIBA",
|
||||
"CT1000P3SSD8", "CT500P5SSD8", "Sabrent Rocket 4.0", "KINGSTON SNV2S1000G",
|
||||
"ADATA SX8200PNP", "Seagate FireCuda 520", "Corsair MP600", "PNY CS3030",
|
||||
"INTEL SSDPEKNW010T8", "SKHynix_HFS512GD9TNG", "Micron 2210 MTFDHBA512QFD", "GIGABYTE GP-GSM2NE3",
|
||||
};
|
||||
static const char *const CDROM_MODEL[] = {
|
||||
"HL-DT-ST DVD-RAM GH24NSD1", "ASUS DRW-24D5MT", "TSSTcorp CDDVDW SH-224",
|
||||
"PLDS DVD+-RW DH-16AES", "HL-DT-ST DVDRWBD CH12NS30",
|
||||
};
|
||||
|
||||
/* Disk serial in the format the model's brand actually uses. */
|
||||
static void gen_disk_serial(const char *model, char *out, size_t n)
|
||||
{
|
||||
char b[24];
|
||||
if (!strncmp(model, "Samsung", 7)) { /* S<3L>N<d>0<6 alnum> */
|
||||
b[0] = 'S';
|
||||
for (int i = 0; i < 3; i++) b[1 + i] = SPOOF_LET[spoof_field_n("dsk.sa.l", i) % 26];
|
||||
b[4] = 'N'; b[5] = SPOOF_DIG[spoof_field_n("dsk.sa.d", 0) % 10]; b[6] = '0';
|
||||
for (int i = 0; i < 6; i++) b[7 + i] = SPOOF_A36[spoof_field_n("dsk.sa.t", i) % 36];
|
||||
b[13] = '\0';
|
||||
} else if (!strncmp(model, "WDC", 3) || !strncmp(model, "WD", 2)) { /* WD-WCC<7> */
|
||||
memcpy(b, "WD-WCC", 6);
|
||||
for (int i = 0; i < 7; i++) b[6 + i] = SPOOF_A36[spoof_field_n("dsk.wd", i) % 36];
|
||||
b[13] = '\0';
|
||||
} else if (!strncmp(model, "ST", 2)) { /* Seagate: Z<7 base36> */
|
||||
b[0] = 'Z';
|
||||
for (int i = 0; i < 7; i++) b[1 + i] = SPOOF_A36[spoof_field_n("dsk.st", i) % 36];
|
||||
b[8] = '\0';
|
||||
} else if (!strncmp(model, "CT", 2) || !strncmp(model, "Crucial", 7)) { /* 4d+12 */
|
||||
for (int i = 0; i < 4; i++) b[i] = SPOOF_DIG[spoof_field_n("dsk.ct.a", i) % 10];
|
||||
for (int i = 0; i < 12; i++) b[4 + i] = SPOOF_A36[spoof_field_n("dsk.ct.b", i) % 36];
|
||||
b[16] = '\0';
|
||||
} else { /* generic 16 alnum */
|
||||
for (int i = 0; i < 16; i++) b[i] = SPOOF_A36[spoof_field_n("dsk.g", i) % 36];
|
||||
b[16] = '\0';
|
||||
}
|
||||
pstrcpy(out, n, b);
|
||||
}
|
||||
static void gen_nvme_serial(const char *model, char *out, size_t n)
|
||||
{
|
||||
char b[24];
|
||||
if (!strncmp(model, "Samsung", 7)) {
|
||||
b[0] = 'S';
|
||||
for (int i = 0; i < 3; i++) b[1 + i] = SPOOF_LET[spoof_field_n("nvm.sa.l", i) % 26];
|
||||
memcpy(b + 4, "NX0", 3);
|
||||
for (int i = 0; i < 7; i++) b[7 + i] = SPOOF_A36[spoof_field_n("nvm.sa.t", i) % 36];
|
||||
b[14] = '\0';
|
||||
} else {
|
||||
for (int i = 0; i < 20; i++) b[i] = SPOOF_A36[spoof_field_n("nvm.g", i) % 36];
|
||||
b[20] = '\0';
|
||||
}
|
||||
pstrcpy(out, n, b);
|
||||
}
|
||||
/* WWN: NAA-5 + a brand-matched 24-bit OUI + 36-bit vendor-specific. */
|
||||
static uint64_t brand_oui(const char *m)
|
||||
{
|
||||
if (!strncmp(m, "Samsung", 7)) return 0x002538;
|
||||
if (!strncmp(m, "WD", 2)) return 0x0014EE;
|
||||
if (!strncmp(m, "ST", 2)) return 0x000C50;
|
||||
if (!strncmp(m, "CT", 2) || !strncmp(m, "Crucial", 7)) return 0x00A075; /* Micron */
|
||||
return 0x0024E9;
|
||||
}
|
||||
|
||||
static struct {
|
||||
const char *model; char serial[24], fw[12]; uint64_t wwn; int rpm;
|
||||
bool done;
|
||||
} d;
|
||||
static struct {
|
||||
const char *model; char serial[24], fw[12]; uint64_t eui64;
|
||||
bool done;
|
||||
} v;
|
||||
|
||||
static void d_init(void)
|
||||
{
|
||||
if (d.done) return;
|
||||
const DiskModel *dm = &DISK_MODEL[spoof_field("disk.model") % ARRAY_SIZE(DISK_MODEL)];
|
||||
d.model = dm->model;
|
||||
d.rpm = dm->rpm;
|
||||
gen_disk_serial(d.model, d.serial, sizeof(d.serial));
|
||||
spoof_gen("disk.fw", SPOOF_A36, 8, d.fw);
|
||||
d.wwn = (0x5ULL << 60) | (brand_oui(d.model) << 36) | (spoof_field("disk.wwn") & 0xFFFFFFFFFULL);
|
||||
d.done = true;
|
||||
}
|
||||
static void v_init(void)
|
||||
{
|
||||
if (v.done) return;
|
||||
v.model = SPOOF_PICK("nvme.model", NVME_MODEL);
|
||||
gen_nvme_serial(v.model, v.serial, sizeof(v.serial));
|
||||
spoof_gen("nvme.fw", SPOOF_A36, 8, v.fw);
|
||||
v.eui64 = (brand_oui(v.model) << 40) | (spoof_field("nvme.eui") & 0xFFFFFFFFFFULL);
|
||||
v.done = true;
|
||||
}
|
||||
|
||||
const char *spoof_disk_model(const char *def) { if (!spoof_on()) return def; d_init(); return d.model; }
|
||||
const char *spoof_disk_serial(const char *def) { if (!spoof_on()) return def; d_init(); return d.serial; }
|
||||
const char *spoof_disk_fw(const char *def) { if (!spoof_on()) return def; d_init(); return d.fw; }
|
||||
uint64_t spoof_disk_wwn(uint64_t def) { if (!spoof_on()) return def; d_init(); return d.wwn; }
|
||||
|
||||
const char *spoof_nvme_model(const char *def) { if (!spoof_on()) return def; v_init(); return v.model; }
|
||||
const char *spoof_nvme_serial(const char *def) { if (!spoof_on()) return def; v_init(); return v.serial; }
|
||||
const char *spoof_nvme_fw(const char *def) { if (!spoof_on()) return def; v_init(); return v.fw; }
|
||||
uint64_t spoof_nvme_eui64(uint64_t def) { if (!spoof_on()) return def; v_init(); return v.eui64; }
|
||||
|
||||
void spoof_nvme_nguid(uint8_t out[16])
|
||||
{
|
||||
if (!spoof_on()) return;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
out[i] = (uint8_t)spoof_field_n("nvme.nguid", (unsigned)i);
|
||||
}
|
||||
}
|
||||
const char *spoof_cdrom_model(const char *def)
|
||||
{
|
||||
return spoof_on() ? SPOOF_PICK("cdrom.model", CDROM_MODEL) : def;
|
||||
}
|
||||
/* ATA rotation rate: 1 = non-rotational (SSD), else RPM — matched to the model
|
||||
* so an "SSD 870 EVO" reports SSD and an "ST1000DM" reports a spinning rate. */
|
||||
int spoof_disk_rotation(int def)
|
||||
{
|
||||
if (!spoof_on()) return def;
|
||||
d_init();
|
||||
return d.rpm; /* 1 = SSD, else RPM (from the pool) */
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* qemu-spoof — seed-driven, per-VM hardware identity for anti-detection.
|
||||
*
|
||||
* PUBLIC header: this is what QEMU call sites include. Every getter takes the
|
||||
* STOCK default and returns it verbatim when spoofing is disabled (no seed) — so
|
||||
* an un-seeded VM behaves exactly like stock QEMU (safe fallback). With a seed,
|
||||
* each value is derived deterministically: same seed -> same coherent persona,
|
||||
* different seed -> different one (kills fleet correlation).
|
||||
*
|
||||
* Implementation is decomposed by aspect (spoof-core.c + spoof-<aspect>.c).
|
||||
*
|
||||
* Inputs (env var = test fallback for the machine property):
|
||||
* spoof-seed / QEMU_SPOOF_SEED persona seed (empty => everything stock)
|
||||
* spoof-hv / QEMU_SPOOF_HV hv mode: off|hyperv|hidden
|
||||
* spoof-waet / QEMU_SPOOF_WAET drop the WAET ACPI table: on|off
|
||||
* spoof-vmgenid/ QEMU_SPOOF_VMGENID vmgenid: keep|mask|hide
|
||||
* Config (the machine property) ALWAYS overrides the seed-implied default.
|
||||
*/
|
||||
#ifndef QEMU_SPOOF_H
|
||||
#define QEMU_SPOOF_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
bool spoof_enabled(void); /* a seed was supplied */
|
||||
|
||||
/* ---- policy knobs (config-overridable; not part of the random persona) ----- */
|
||||
typedef enum { SPOOF_HV_OFF = 0, SPOOF_HV_HYPERV, SPOOF_HV_HIDDEN } SpoofHvMode;
|
||||
SpoofHvMode spoof_hv_mode(void); /* seeded default = HYPERV, else OFF */
|
||||
typedef enum { SPOOF_VGID_KEEP = 0, SPOOF_VGID_MASK, SPOOF_VGID_HIDE } SpoofVgidPolicy;
|
||||
SpoofVgidPolicy spoof_vmgenid_policy(void); /* HIDDEN->HIDE, HYPERV->MASK, OFF->KEEP */
|
||||
bool spoof_waet_drop(void); /* drop the WAET (emulated-devices) table */
|
||||
bool spoof_pvpanic_hide(void); /* drop the pvpanic device (_HID QEMU0001) */
|
||||
|
||||
/* ---- platform (spoof-platform.c) — one coherent firmware/board identity ----
|
||||
* The ACPI OEM id, machine desc, BIOS vendor and baseboard all come from a single
|
||||
* per-seed platform pick (OEM-prebuilt vendor code, or "ALASKA"/AMI for DIY). */
|
||||
const char *spoof_bios_vendor(const char *def); /* SMBIOS type0 */
|
||||
const char *spoof_baseboard_manufacturer(const char *def); /* SMBIOS type2 */
|
||||
|
||||
/* ---- ACPI (spoof-acpi.c; hw/acpi, hw/i386/acpi-build) --------------------- */
|
||||
const char *spoof_acpi_oem_id(const char *def); /* 6 bytes (platform-anchored) */
|
||||
const char *spoof_acpi_oem_table_id(const char *def); /* 8 bytes (platform-anchored) */
|
||||
const char *spoof_acpi_creator_id(const char *def); /* 4 bytes (ASL compiler) */
|
||||
|
||||
/* ---- CPU (spoof-cpu.c; target/i386) --------------------------------------- */
|
||||
const char *spoof_kvm_signature(const char *def); /* 12 bytes; vendor-anchored */
|
||||
int spoof_cpu_base_mhz(int def); /* CPUID leaf 0x16 base freq */
|
||||
int spoof_cpu_max_mhz(int def); /* CPUID leaf 0x16 max freq */
|
||||
int spoof_cpu_bus_mhz(int def); /* CPUID leaf 0x16 bus freq */
|
||||
uint64_t spoof_cpu_microcode(uint64_t def); /* IA32_UCODE_REV, vendor-positioned */
|
||||
|
||||
/* ---- PCI (spoof-pci.c) ---------------------------------------------------- */
|
||||
uint16_t spoof_pci_vendor(uint16_t def); /* anchored to the CPU vendor */
|
||||
uint16_t spoof_pci_subvendor(uint16_t def);
|
||||
uint16_t spoof_pci_device(const char *role, uint16_t def);
|
||||
uint16_t spoof_pci_subdevice(const char *role, uint16_t def); /* OEM-branded SSID */
|
||||
|
||||
/* ---- fw_cfg (spoof-fwcfg.c; hw/nvram/fw_cfg, standard-headers) ------------- */
|
||||
const char *spoof_fwcfg_sig(const char *def); /* 4-byte selector signature */
|
||||
uint64_t spoof_fwcfg_dma_sig(uint64_t def); /* 8-byte DMA signature */
|
||||
const char *spoof_fwcfg_acpi_devid(const char *def); /* fw_cfg device _HID */
|
||||
|
||||
/* ---- SMBIOS (spoof-smbios.c; hw/smbios) ----------------------------------- */
|
||||
bool spoof_smbios_hide_vm(void); /* clear type0 "VM" char. bit */
|
||||
const char *spoof_smbios_mem_manufacturer(const char *def); /* type17 */
|
||||
const char *spoof_smbios_mem_part(const char *def);
|
||||
const char *spoof_smbios_mem_serial(const char *def);
|
||||
const char *spoof_smbios_cpu_manufacturer(const char *def); /* type4 */
|
||||
const char *spoof_smbios_cpu_socket(const char *def);
|
||||
const char *spoof_smbios_oem_string(const char *def); /* type11 */
|
||||
int spoof_smbios_chassis_type(int def); /* type3: 3=Desktop, 10=Notebook */
|
||||
|
||||
/* ---- display / EDID (spoof-display.c; hw/display/edid-generate) ------------ */
|
||||
const char *spoof_edid_vendor(const char *def); /* 3-char PNP (pool) */
|
||||
const char *spoof_edid_name(const char *def); /* model name (pool) */
|
||||
uint16_t spoof_edid_model(uint16_t def); /* product code (generated) */
|
||||
uint32_t spoof_edid_serial(uint32_t def); /* serial (generated) */
|
||||
int spoof_edid_year(int def); /* year of manufacture */
|
||||
int spoof_edid_week(int def); /* week of manufacture */
|
||||
|
||||
/* ---- storage (spoof-storage.c; hw/ide, hw/scsi, hw/nvme) ------------------ */
|
||||
/* model = pool (finite real set); per-unit serial/WWN/EUI64/FW = GENERATED. */
|
||||
const char *spoof_disk_model(const char *def);
|
||||
const char *spoof_disk_serial(const char *def); /* brand-matched format */
|
||||
uint64_t spoof_disk_wwn(uint64_t def); /* NAA-5 + brand OUI */
|
||||
const char *spoof_disk_fw(const char *def); /* ATA firmware revision */
|
||||
const char *spoof_nvme_model(const char *def);
|
||||
const char *spoof_nvme_serial(const char *def);
|
||||
const char *spoof_nvme_fw(const char *def); /* 8-char rev (fixes FR leak) */
|
||||
uint64_t spoof_nvme_eui64(uint64_t def); /* OUI + vendor */
|
||||
void spoof_nvme_nguid(uint8_t out[16]); /* filled iff enabled */
|
||||
const char *spoof_cdrom_model(const char *def);
|
||||
int spoof_disk_rotation(int def); /* 1=SSD, else RPM (matches model) */
|
||||
|
||||
/* ---- audio (spoof-audio.c; hw/audio/hda-codec) ---------------------------- */
|
||||
uint32_t spoof_hda_vendor_id(uint32_t def); /* HDA codec vendor/device id */
|
||||
const char *spoof_hda_name(const char *def);
|
||||
|
||||
/* ---- machine (spoof-machine.c; hw/i386/pc_*) ------------------------------ */
|
||||
const char *spoof_machine_desc(const char *def);
|
||||
|
||||
#endif /* QEMU_SPOOF_H */
|
||||
Reference in New Issue
Block a user