spoof: spoof-mode master fork (none/hyperv/vbs/physical) + microsoft-vm persona
Phase 0. Replace the spoof-hv knob with spoof-mode, a first-class selector modeled as two axes (persona x presence) exposed as 4 presets: - none: stock (spoof_on now requires mode != none, killing half-spoof states) - hyperv: Microsoft Virtual Machine persona + Hyper-V presence (honest child VM) - vbs (seeded default): real-OEM persona + Hyper-V presence (mimic physical Win11+VBS) - physical: real-OEM persona + bare metal Engine: spoof_mode()/spoof_persona_msvm()/spoof_presence_hyperv() in spoof-core; the hv/waet/pvpanic/vmgenid policies now derive from the mode. microsoft-vm persona wired across platform (ACPI OEM VRTUAL/MICROSFT, Microsoft Corporation), system type1 (Virtual Machine), storage (Virtual HD / Msft Virtual DVD-ROM) and EDID (MSF/Hyper-V). New getters spoof_system_manufacturer/product (type1, real-OEM or Hyper-V). Patches: 0002 registers spoof-mode; 0024 now also forces type1 system identity. spoof-hv kept as a back-compat alias. Inert without a seed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -38,6 +38,21 @@ QEMU_SPOOF_SEED=<string> # env fallback (testing)
|
|||||||
Same seed → same persona. Mix in a host secret so personas are not guessable from
|
Same seed → same persona. Mix in a host secret so personas are not guessable from
|
||||||
the vmid. Proxmox: add `spoof-seed=` through the VM `args:` line.
|
the vmid. Proxmox: add `spoof-seed=` through the VM `args:` line.
|
||||||
|
|
||||||
|
### Modes
|
||||||
|
|
||||||
|
`-machine ...,spoof-mode=` selects the identity strategy (two axes — hardware
|
||||||
|
persona × hypervisor presence — as presets):
|
||||||
|
|
||||||
|
| mode | persona | presence | looks like |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `none` | stock | KVM | a plain VM (no spoof) |
|
||||||
|
| `hyperv` | Microsoft "Virtual Machine" | Hyper-V | an honest Hyper-V guest |
|
||||||
|
| `vbs` (default when seeded) | real OEM | Hyper-V | a physical Win11 box with VBS on |
|
||||||
|
| `physical` | real OEM | bare metal | a physical machine (no hypervisor) |
|
||||||
|
|
||||||
|
The presence axis (clearing the hypervisor bit / Hyper-V enlightenments) is partly
|
||||||
|
the CPU model configuration (`cpu: host,hidden=1` + `hv-*`); set it to match the mode.
|
||||||
|
|
||||||
## Layout
|
## Layout
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
qemu-spoof: register per-VM anti-detect machine properties
|
qemu-spoof: register per-VM anti-detect machine properties
|
||||||
|
|
||||||
Adds string machine properties spoof-seed / spoof-hv / spoof-waet /
|
Adds string machine properties spoof-seed / spoof-mode / spoof-hv / spoof-waet /
|
||||||
spoof-vmgenid / spoof-pvpanic on the x86 machine, backed by X86MachineState
|
spoof-vmgenid / spoof-pvpanic on the x86 machine, backed by X86MachineState fields.
|
||||||
fields. The qemu-spoof module (hw/misc/spoof*) reads them via
|
The qemu-spoof module (hw/misc/spoof*) reads them via
|
||||||
object_property_get_str(current_machine, "spoof-*"). Inert unless set.
|
object_property_get_str(current_machine, "spoof-*"). spoof-mode (none|hyperv|vbs|
|
||||||
|
physical) is the master fork; spoof-hv is the legacy knob. Inert unless set.
|
||||||
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
|
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
|
||||||
index 01872cb..66400fe 100644
|
index 01872cb..702b327 100644
|
||||||
--- a/hw/i386/x86.c
|
--- a/hw/i386/x86.c
|
||||||
+++ b/hw/i386/x86.c
|
+++ b/hw/i386/x86.c
|
||||||
@@ -372,6 +372,26 @@ static void x86_machine_initfn(Object *obj)
|
@@ -372,6 +372,27 @@ static void x86_machine_initfn(Object *obj)
|
||||||
x86ms->above_4g_mem_start = 4 * GiB;
|
x86ms->above_4g_mem_start = 4 * GiB;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,6 +28,7 @@ index 01872cb..66400fe 100644
|
|||||||
+ x86ms->field = g_strdup(value); \
|
+ x86ms->field = g_strdup(value); \
|
||||||
+ }
|
+ }
|
||||||
+X86_SPOOF_PROP(spoof_seed)
|
+X86_SPOOF_PROP(spoof_seed)
|
||||||
|
+X86_SPOOF_PROP(spoof_mode)
|
||||||
+X86_SPOOF_PROP(spoof_hv)
|
+X86_SPOOF_PROP(spoof_hv)
|
||||||
+X86_SPOOF_PROP(spoof_waet)
|
+X86_SPOOF_PROP(spoof_waet)
|
||||||
+X86_SPOOF_PROP(spoof_vmgenid)
|
+X86_SPOOF_PROP(spoof_vmgenid)
|
||||||
@@ -35,7 +37,7 @@ index 01872cb..66400fe 100644
|
|||||||
static void x86_machine_class_init(ObjectClass *oc, const void *data)
|
static void x86_machine_class_init(ObjectClass *oc, const void *data)
|
||||||
{
|
{
|
||||||
MachineClass *mc = MACHINE_CLASS(oc);
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
@@ -426,6 +446,27 @@ static void x86_machine_class_init(ObjectClass *oc, const void *data)
|
@@ -426,6 +447,31 @@ static void x86_machine_class_init(ObjectClass *oc, const void *data)
|
||||||
"in ACPI table header."
|
"in ACPI table header."
|
||||||
"The string may be up to 8 bytes in size");
|
"The string may be up to 8 bytes in size");
|
||||||
|
|
||||||
@@ -43,10 +45,14 @@ index 01872cb..66400fe 100644
|
|||||||
+ x86_machine_get_spoof_seed, x86_machine_set_spoof_seed);
|
+ x86_machine_get_spoof_seed, x86_machine_set_spoof_seed);
|
||||||
+ object_class_property_set_description(oc, "spoof-seed",
|
+ object_class_property_set_description(oc, "spoof-seed",
|
||||||
+ "qemu-spoof: per-VM persona seed (empty = stock QEMU)");
|
+ "qemu-spoof: per-VM persona seed (empty = stock QEMU)");
|
||||||
|
+ object_class_property_add_str(oc, "spoof-mode",
|
||||||
|
+ x86_machine_get_spoof_mode, x86_machine_set_spoof_mode);
|
||||||
|
+ object_class_property_set_description(oc, "spoof-mode",
|
||||||
|
+ "qemu-spoof: identity mode (none|hyperv|vbs|physical)");
|
||||||
+ object_class_property_add_str(oc, "spoof-hv",
|
+ object_class_property_add_str(oc, "spoof-hv",
|
||||||
+ x86_machine_get_spoof_hv, x86_machine_set_spoof_hv);
|
+ x86_machine_get_spoof_hv, x86_machine_set_spoof_hv);
|
||||||
+ object_class_property_set_description(oc, "spoof-hv",
|
+ object_class_property_set_description(oc, "spoof-hv",
|
||||||
+ "qemu-spoof: hypervisor mode (off|hyperv|hidden)");
|
+ "qemu-spoof: legacy hv knob (off|hyperv|hidden); prefer spoof-mode");
|
||||||
+ object_class_property_add_str(oc, "spoof-waet",
|
+ object_class_property_add_str(oc, "spoof-waet",
|
||||||
+ x86_machine_get_spoof_waet, x86_machine_set_spoof_waet);
|
+ x86_machine_get_spoof_waet, x86_machine_set_spoof_waet);
|
||||||
+ object_class_property_set_description(oc, "spoof-waet",
|
+ object_class_property_set_description(oc, "spoof-waet",
|
||||||
@@ -64,7 +70,7 @@ index 01872cb..66400fe 100644
|
|||||||
x86_machine_get_bus_lock_ratelimit,
|
x86_machine_get_bus_lock_ratelimit,
|
||||||
x86_machine_set_bus_lock_ratelimit, NULL, NULL);
|
x86_machine_set_bus_lock_ratelimit, NULL, NULL);
|
||||||
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
|
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
|
||||||
index 71fe6b5..a80700f 100644
|
index 71fe6b5..c1f5f7e 100644
|
||||||
--- a/include/hw/i386/x86.h
|
--- a/include/hw/i386/x86.h
|
||||||
+++ b/include/hw/i386/x86.h
|
+++ b/include/hw/i386/x86.h
|
||||||
@@ -79,6 +79,9 @@ struct X86MachineState {
|
@@ -79,6 +79,9 @@ struct X86MachineState {
|
||||||
@@ -73,7 +79,7 @@ index 71fe6b5..a80700f 100644
|
|||||||
char *oem_table_id;
|
char *oem_table_id;
|
||||||
+
|
+
|
||||||
+ /* qemu-spoof: per-VM anti-detect config, read by hw/misc/spoof*.c */
|
+ /* qemu-spoof: per-VM anti-detect config, read by hw/misc/spoof*.c */
|
||||||
+ char *spoof_seed, *spoof_hv, *spoof_waet, *spoof_vmgenid, *spoof_pvpanic;
|
+ char *spoof_seed, *spoof_mode, *spoof_hv, *spoof_waet, *spoof_vmgenid, *spoof_pvpanic;
|
||||||
/*
|
/*
|
||||||
* Address space used by IOAPIC device. All IOAPIC interrupts
|
* Address space used by IOAPIC device. All IOAPIC interrupts
|
||||||
* will be translated to MSI messages in the address space.
|
* will be translated to MSI messages in the address space.
|
||||||
|
|||||||
@@ -1,25 +1,29 @@
|
|||||||
qemu-spoof: SMBIOS type0 BIOS vendor / version / date
|
qemu-spoof: SMBIOS type0 BIOS + type1 system identity
|
||||||
|
|
||||||
Stock QEMU leaves type0 vendor/version/date unset, so the guest reads an empty or
|
Stock QEMU leaves type0 vendor/version/date unset (guest reads an empty/firmware-
|
||||||
firmware-default ("SeaBIOS") BIOS identity via WMI Win32_BIOS / dmidecode -- a tell.
|
default "SeaBIOS" BIOS via WMI/dmidecode) and type1 system manufacturer/product fall
|
||||||
Force a real, platform-anchored OEM BIOS identity (vendor coheres with the board;
|
back to the bare machine values. Force the persona identity through smbios_set_defaults:
|
||||||
version uses the vendor's real format) through smbios_set_defaults, so an explicit
|
- real-OEM persona: vendor-formatted BIOS + board-brand system manufacturer/product;
|
||||||
-smbios type=0 still wins and an un-seeded VM stays stock. (spoof.h include added by
|
- hyperv persona: Microsoft "Virtual Machine".
|
||||||
|
Config (-smbios) still wins; an un-seeded VM stays stock. (spoof.h include added by
|
||||||
0015-smbios-vm-bit.)
|
0015-smbios-vm-bit.)
|
||||||
diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
|
diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
|
||||||
index 7d71418..13ffa93 100644
|
index 7d71418..8321f10 100644
|
||||||
--- a/hw/smbios/smbios.c
|
--- a/hw/smbios/smbios.c
|
||||||
+++ b/hw/smbios/smbios.c
|
+++ b/hw/smbios/smbios.c
|
||||||
@@ -1027,6 +1027,12 @@ void smbios_set_defaults(const char *manufacturer, const char *product,
|
@@ -1027,6 +1027,15 @@ void smbios_set_defaults(const char *manufacturer, const char *product,
|
||||||
{
|
{
|
||||||
smbios_have_defaults = true;
|
smbios_have_defaults = true;
|
||||||
|
|
||||||
+ /* qemu-spoof: a real OEM BIOS identity (type0). Stock leaves vendor/version/date
|
+ /* qemu-spoof: a real OEM (or Hyper-V) BIOS + system identity. Stock leaves type0
|
||||||
+ * unset, so the guest reads an empty / firmware-default ("SeaBIOS") BIOS — a tell.
|
+ * vendor/version/date unset (guest reads empty/"SeaBIOS") and type1 falls back to
|
||||||
+ * Platform-anchored so the BIOS vendor coheres with the board. Inert without a seed. */
|
+ * the bare machine manufacturer/product; force the persona's values. Platform-
|
||||||
|
+ * anchored; config (-smbios) still wins; inert without a seed. */
|
||||||
+ SMBIOS_SET_DEFAULT(smbios_type0.vendor, spoof_bios_vendor(NULL));
|
+ SMBIOS_SET_DEFAULT(smbios_type0.vendor, spoof_bios_vendor(NULL));
|
||||||
+ SMBIOS_SET_DEFAULT(smbios_type0.version, spoof_bios_version(NULL));
|
+ SMBIOS_SET_DEFAULT(smbios_type0.version, spoof_bios_version(NULL));
|
||||||
+ SMBIOS_SET_DEFAULT(smbios_type0.date, spoof_bios_date(NULL));
|
+ SMBIOS_SET_DEFAULT(smbios_type0.date, spoof_bios_date(NULL));
|
||||||
|
+ SMBIOS_SET_DEFAULT(smbios_type1.manufacturer, spoof_system_manufacturer(NULL));
|
||||||
|
+ SMBIOS_SET_DEFAULT(smbios_type1.product, spoof_system_product(NULL));
|
||||||
SMBIOS_SET_DEFAULT(smbios_type1.manufacturer, manufacturer);
|
SMBIOS_SET_DEFAULT(smbios_type1.manufacturer, manufacturer);
|
||||||
SMBIOS_SET_DEFAULT(smbios_type1.product, product);
|
SMBIOS_SET_DEFAULT(smbios_type1.product, product);
|
||||||
SMBIOS_SET_DEFAULT(smbios_type1.version, version);
|
SMBIOS_SET_DEFAULT(smbios_type1.version, version);
|
||||||
|
|||||||
+2
-2
@@ -11,7 +11,7 @@ match exactly. Naming: `0002` = infra, `0010+` = one aspect each.
|
|||||||
|
|
||||||
| patch | covers |
|
| patch | covers |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 0002-x86-machine-spoof-properties | register `spoof-seed` / `spoof-hv` / `spoof-waet` / `spoof-vmgenid` / `spoof-pvpanic` machine props |
|
| 0002-x86-machine-spoof-properties | register `spoof-seed` / `spoof-mode` / `spoof-hv` / `spoof-waet` / `spoof-vmgenid` / `spoof-pvpanic` machine props |
|
||||||
| 0010-acpi-table-header | ACPI OEM id / table id / creator + FADT hypervisor-vendor |
|
| 0010-acpi-table-header | ACPI OEM id / table id / creator + FADT hypervisor-vendor |
|
||||||
| 0011-acpi-policy-waet-vmgenid | drop the WAET table; skip the vmgenid SSDT when policy = hide |
|
| 0011-acpi-policy-waet-vmgenid | drop the WAET table; skip the vmgenid SSDT when policy = hide |
|
||||||
| 0012-acpi-device-hids | vmgenid `_HID` (mask), pvpanic `_HID` (hide), fw_cfg `_HID` |
|
| 0012-acpi-device-hids | vmgenid `_HID` (mask), pvpanic `_HID` (hide), fw_cfg `_HID` |
|
||||||
@@ -25,7 +25,7 @@ match exactly. Naming: `0002` = infra, `0010+` = one aspect each.
|
|||||||
| 0021-smbios-identity | SMBIOS type3 chassis / type4 socket + cpu-mfr / type11 OEM / type17 memory |
|
| 0021-smbios-identity | SMBIOS type3 chassis / type4 socket + cpu-mfr / type11 OEM / type17 memory |
|
||||||
| 0022-storage-extra | IDE WWN + rotation rate; NVMe EUI-64 + NGUID |
|
| 0022-storage-extra | IDE WWN + rotation rate; NVMe EUI-64 + NGUID |
|
||||||
| 0023-cpu-microcode | CPU microcode revision (IA32_UCODE_REV), vendor-positioned |
|
| 0023-cpu-microcode | CPU microcode revision (IA32_UCODE_REV), vendor-positioned |
|
||||||
| 0024-smbios-bios-type0 | SMBIOS type0 BIOS vendor / version / date (platform-anchored OEM firmware) |
|
| 0024-smbios-bios-type0 | SMBIOS type0 BIOS vendor/version/date + type1 system manufacturer/product (real-OEM or Hyper-V persona) |
|
||||||
|
|
||||||
## The PCI-id problem (why 0018 is careful)
|
## The PCI-id problem (why 0018 is careful)
|
||||||
|
|
||||||
|
|||||||
+33
-11
@@ -15,8 +15,8 @@ const char SPOOF_DIG[] = "0123456789";
|
|||||||
|
|
||||||
/* ---- config: machine property first, env var as a test fallback ----------- */
|
/* ---- config: machine property first, env var as a test fallback ----------- */
|
||||||
static char g_seed[256];
|
static char g_seed[256];
|
||||||
static bool g_ready, g_enabled;
|
static bool g_ready;
|
||||||
static char g_hv[16], g_waet[16], g_vgid[16], g_pvp[16];
|
static char g_mode[16], 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)
|
static void read_prop(const char *prop, const char *env, char *out, size_t n)
|
||||||
{
|
{
|
||||||
@@ -37,17 +37,38 @@ static void config_load(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
read_prop("spoof-seed", "QEMU_SPOOF_SEED", g_seed, sizeof(g_seed));
|
read_prop("spoof-seed", "QEMU_SPOOF_SEED", g_seed, sizeof(g_seed));
|
||||||
|
read_prop("spoof-mode", "QEMU_SPOOF_MODE", g_mode, sizeof(g_mode));
|
||||||
read_prop("spoof-hv", "QEMU_SPOOF_HV", g_hv, sizeof(g_hv));
|
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-waet", "QEMU_SPOOF_WAET", g_waet, sizeof(g_waet));
|
||||||
read_prop("spoof-vmgenid", "QEMU_SPOOF_VMGENID", g_vgid, sizeof(g_vgid));
|
read_prop("spoof-vmgenid", "QEMU_SPOOF_VMGENID", g_vgid, sizeof(g_vgid));
|
||||||
read_prop("spoof-pvpanic", "QEMU_SPOOF_PVPANIC", g_pvp, sizeof(g_pvp));
|
read_prop("spoof-pvpanic", "QEMU_SPOOF_PVPANIC", g_pvp, sizeof(g_pvp));
|
||||||
g_enabled = g_seed[0] != '\0';
|
|
||||||
g_ready = true;
|
g_ready = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool spoof_on(void) { config_load(); return g_enabled; }
|
bool spoof_on(void) { return spoof_mode() != SPOOF_MODE_NONE; }
|
||||||
bool spoof_enabled(void) { return spoof_on(); }
|
bool spoof_enabled(void) { return spoof_on(); }
|
||||||
|
|
||||||
|
SpoofMode spoof_mode(void)
|
||||||
|
{
|
||||||
|
config_load();
|
||||||
|
if (!g_seed[0]) return SPOOF_MODE_NONE;
|
||||||
|
if (!strcmp(g_mode, "none")) return SPOOF_MODE_NONE;
|
||||||
|
if (!strcmp(g_mode, "hyperv")) return SPOOF_MODE_HYPERV;
|
||||||
|
if (!strcmp(g_mode, "vbs")) return SPOOF_MODE_VBS;
|
||||||
|
if (!strcmp(g_mode, "physical")) return SPOOF_MODE_PHYSICAL;
|
||||||
|
/* back-compat with the old spoof-hv knob (real-OEM persona either way) */
|
||||||
|
if (!strcmp(g_hv, "hidden")) return SPOOF_MODE_PHYSICAL;
|
||||||
|
if (!strcmp(g_hv, "hyperv")) return SPOOF_MODE_VBS;
|
||||||
|
if (!strcmp(g_hv, "off")) return SPOOF_MODE_NONE;
|
||||||
|
return SPOOF_MODE_VBS; /* seeded default = VBS (real-OEM + Hyper-V) */
|
||||||
|
}
|
||||||
|
bool spoof_persona_msvm(void) { return spoof_mode() == SPOOF_MODE_HYPERV; }
|
||||||
|
bool spoof_presence_hyperv(void)
|
||||||
|
{
|
||||||
|
SpoofMode m = spoof_mode();
|
||||||
|
return m == SPOOF_MODE_HYPERV || m == SPOOF_MODE_VBS;
|
||||||
|
}
|
||||||
|
|
||||||
/* ---- deterministic derivation: fnv1a(seed|key) -> splitmix64 -------------- */
|
/* ---- deterministic derivation: fnv1a(seed|key) -> splitmix64 -------------- */
|
||||||
static uint64_t fnv1a(const char *s)
|
static uint64_t fnv1a(const char *s)
|
||||||
{
|
{
|
||||||
@@ -94,25 +115,26 @@ int spoof_anchor_vendor(void)
|
|||||||
/* ---- policy knobs --------------------------------------------------------- */
|
/* ---- policy knobs --------------------------------------------------------- */
|
||||||
SpoofHvMode spoof_hv_mode(void)
|
SpoofHvMode spoof_hv_mode(void)
|
||||||
{
|
{
|
||||||
config_load();
|
switch (spoof_mode()) { /* derived from the mode preset */
|
||||||
if (!strcmp(g_hv, "hidden")) return SPOOF_HV_HIDDEN;
|
case SPOOF_MODE_HYPERV:
|
||||||
if (!strcmp(g_hv, "hyperv")) return SPOOF_HV_HYPERV;
|
case SPOOF_MODE_VBS: return SPOOF_HV_HYPERV; /* present Hyper-V */
|
||||||
if (!strcmp(g_hv, "off")) return SPOOF_HV_OFF;
|
case SPOOF_MODE_PHYSICAL: return SPOOF_HV_HIDDEN; /* bare metal */
|
||||||
return g_enabled ? SPOOF_HV_HYPERV : SPOOF_HV_OFF; /* seeded default = hyperv */
|
default: return SPOOF_HV_OFF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bool spoof_waet_drop(void)
|
bool spoof_waet_drop(void)
|
||||||
{
|
{
|
||||||
config_load();
|
config_load();
|
||||||
if (!strcmp(g_waet, "on")) return true;
|
if (!strcmp(g_waet, "on")) return true;
|
||||||
if (!strcmp(g_waet, "off")) return false;
|
if (!strcmp(g_waet, "off")) return false;
|
||||||
return g_enabled; /* seeded default = drop */
|
return spoof_on(); /* any spoof mode drops WAET */
|
||||||
}
|
}
|
||||||
bool spoof_pvpanic_hide(void)
|
bool spoof_pvpanic_hide(void)
|
||||||
{
|
{
|
||||||
config_load();
|
config_load();
|
||||||
if (!strcmp(g_pvp, "on")) return true;
|
if (!strcmp(g_pvp, "on")) return true;
|
||||||
if (!strcmp(g_pvp, "off")) return false;
|
if (!strcmp(g_pvp, "off")) return false;
|
||||||
return g_enabled; /* seeded default = hide pvpanic */
|
return spoof_on(); /* QEMU pvpanic isn't a Hyper-V/real device */
|
||||||
}
|
}
|
||||||
SpoofVgidPolicy spoof_vmgenid_policy(void)
|
SpoofVgidPolicy spoof_vmgenid_policy(void)
|
||||||
{
|
{
|
||||||
|
|||||||
+14
-1
@@ -16,7 +16,20 @@
|
|||||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool spoof_on(void); /* seed present */
|
bool spoof_on(void); /* a persona is active (seed set + mode != none) */
|
||||||
|
|
||||||
|
/* The master config fork. Two axes (persona x presence) as named presets:
|
||||||
|
* none stock persona + stock-kvm presence (no spoof)
|
||||||
|
* hyperv microsoft-vm persona + hyperv presence (honest Hyper-V child VM)
|
||||||
|
* vbs real-OEM persona + hyperv presence (mimic physical Win11 + VBS)
|
||||||
|
* physical real-OEM persona + bare-metal presence (VBS-off machine) */
|
||||||
|
typedef enum {
|
||||||
|
SPOOF_MODE_NONE = 0, SPOOF_MODE_HYPERV, SPOOF_MODE_VBS, SPOOF_MODE_PHYSICAL
|
||||||
|
} SpoofMode;
|
||||||
|
SpoofMode spoof_mode(void);
|
||||||
|
bool spoof_persona_msvm(void); /* hardware persona = Microsoft "Virtual Machine" */
|
||||||
|
bool spoof_presence_hyperv(void);/* present Hyper-V enlightenments (hyperv|vbs) */
|
||||||
|
|
||||||
uint64_t spoof_field(const char *key); /* stable 64-bit draw for a key */
|
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 */
|
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);
|
const char *spoof_pick(const char *key, const char *const *arr, size_t n);
|
||||||
|
|||||||
+6
-2
@@ -17,11 +17,15 @@ static const char *const EDID_NAME[] = {
|
|||||||
|
|
||||||
const char *spoof_edid_vendor(const char *def)
|
const char *spoof_edid_vendor(const char *def)
|
||||||
{
|
{
|
||||||
return spoof_on() ? SPOOF_PICK("edid.vend", EDID_VEND) : def;
|
if (!spoof_on()) return def;
|
||||||
|
if (spoof_persona_msvm()) return "MSF"; /* Microsoft synthetic display */
|
||||||
|
return SPOOF_PICK("edid.vend", EDID_VEND);
|
||||||
}
|
}
|
||||||
const char *spoof_edid_name(const char *def)
|
const char *spoof_edid_name(const char *def)
|
||||||
{
|
{
|
||||||
return spoof_on() ? SPOOF_PICK("edid.name", EDID_NAME) : def;
|
if (!spoof_on()) return def;
|
||||||
|
if (spoof_persona_msvm()) return "Hyper-V Monitor";
|
||||||
|
return SPOOF_PICK("edid.name", EDID_NAME);
|
||||||
}
|
}
|
||||||
uint16_t spoof_edid_model(uint16_t def)
|
uint16_t spoof_edid_model(uint16_t def)
|
||||||
{
|
{
|
||||||
|
|||||||
+24
-7
@@ -77,13 +77,15 @@ static const Board *chosen_board(void)
|
|||||||
return &list[spoof_field("mach.board") % n];
|
return &list[spoof_field("mach.board") % n];
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *spoof_plat_acpi_oem(void) { return plat()->oem; }
|
/* In hyperv mode the hardware persona is an honest Hyper-V "Virtual Machine"
|
||||||
const char *spoof_plat_acpi_table(void) { return plat()->table; }
|
* (real Hyper-V ACPI OEM = VRTUAL/MICROSFT, vendor = Microsoft Corporation). */
|
||||||
const char *spoof_plat_bios_vendor(void) { return plat()->bios; }
|
const char *spoof_plat_acpi_oem(void) { return spoof_persona_msvm() ? "VRTUAL" : plat()->oem; }
|
||||||
const char *spoof_plat_baseboard(void) { return plat()->board; }
|
const char *spoof_plat_acpi_table(void) { return spoof_persona_msvm() ? "MICROSFT" : plat()->table; }
|
||||||
const char *spoof_plat_machine_desc(void) { return chosen_board()->model; }
|
const char *spoof_plat_bios_vendor(void) { return spoof_persona_msvm() ? "Microsoft Corporation" : plat()->bios; }
|
||||||
const char *spoof_plat_socket(void) { return chosen_board()->socket; }
|
const char *spoof_plat_baseboard(void) { return spoof_persona_msvm() ? "Microsoft Corporation" : plat()->board; }
|
||||||
const char *spoof_plat_oem_string(void) { return plat()->oemstr; }
|
const char *spoof_plat_machine_desc(void) { return spoof_persona_msvm() ? "Virtual Machine" : chosen_board()->model; }
|
||||||
|
const char *spoof_plat_socket(void) { return spoof_persona_msvm() ? "None" : chosen_board()->socket; }
|
||||||
|
const char *spoof_plat_oem_string(void) { return spoof_persona_msvm() ? "Hyper-V" : plat()->oemstr; }
|
||||||
|
|
||||||
const char *spoof_bios_vendor(const char *def)
|
const char *spoof_bios_vendor(const char *def)
|
||||||
{
|
{
|
||||||
@@ -96,6 +98,9 @@ const char *spoof_bios_version(const char *def)
|
|||||||
if (!spoof_on()) {
|
if (!spoof_on()) {
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
if (spoof_persona_msvm()) {
|
||||||
|
return "Hyper-V UEFI Release v4.1";
|
||||||
|
}
|
||||||
static char v[32];
|
static char v[32];
|
||||||
const char *b = spoof_plat_bios_vendor();
|
const char *b = spoof_plat_bios_vendor();
|
||||||
if (strstr(b, "Megatrends")) { /* AMI Aptio */
|
if (strstr(b, "Megatrends")) { /* AMI Aptio */
|
||||||
@@ -136,3 +141,15 @@ const char *spoof_baseboard_manufacturer(const char *def)
|
|||||||
{
|
{
|
||||||
return spoof_on() ? spoof_plat_baseboard() : def;
|
return spoof_on() ? spoof_plat_baseboard() : def;
|
||||||
}
|
}
|
||||||
|
/* SMBIOS type1 (system) — the most guest-visible identity (Win32_ComputerSystem).
|
||||||
|
* hyperv: Microsoft "Virtual Machine"; real-OEM: the board brand + model. */
|
||||||
|
const char *spoof_system_manufacturer(const char *def)
|
||||||
|
{
|
||||||
|
if (!spoof_on()) return def;
|
||||||
|
return spoof_persona_msvm() ? "Microsoft Corporation" : spoof_plat_baseboard();
|
||||||
|
}
|
||||||
|
const char *spoof_system_product(const char *def)
|
||||||
|
{
|
||||||
|
if (!spoof_on()) return def;
|
||||||
|
return spoof_persona_msvm() ? "Virtual Machine" : spoof_plat_machine_desc();
|
||||||
|
}
|
||||||
|
|||||||
+4
-2
@@ -124,7 +124,7 @@ static void v_init(void)
|
|||||||
v.done = true;
|
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_model(const char *def) { if (!spoof_on()) return def; if (spoof_persona_msvm()) return "Virtual HD ATA Device"; 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_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; }
|
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; }
|
uint64_t spoof_disk_wwn(uint64_t def) { if (!spoof_on()) return def; d_init(); return d.wwn; }
|
||||||
@@ -155,7 +155,9 @@ void spoof_nvme_nguid(uint8_t out[16])
|
|||||||
}
|
}
|
||||||
const char *spoof_cdrom_model(const char *def)
|
const char *spoof_cdrom_model(const char *def)
|
||||||
{
|
{
|
||||||
return spoof_on() ? SPOOF_PICK("cdrom.model", CDROM_MODEL) : def;
|
if (!spoof_on()) return def;
|
||||||
|
if (spoof_persona_msvm()) return "Msft Virtual DVD-ROM";
|
||||||
|
return SPOOF_PICK("cdrom.model", CDROM_MODEL);
|
||||||
}
|
}
|
||||||
/* ATA rotation rate: 1 = non-rotational (SSD), else RPM — matched to the model
|
/* 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. */
|
* so an "SSD 870 EVO" reports SSD and an "ST1000DM" reports a spinning rate. */
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ bool spoof_pvpanic_hide(void); /* drop the pvpanic device (_HID QEMU000
|
|||||||
const char *spoof_bios_vendor(const char *def); /* SMBIOS type0 */
|
const char *spoof_bios_vendor(const char *def); /* SMBIOS type0 */
|
||||||
const char *spoof_bios_version(const char *def); /* SMBIOS type0 (vendor-format) */
|
const char *spoof_bios_version(const char *def); /* SMBIOS type0 (vendor-format) */
|
||||||
const char *spoof_bios_date(const char *def); /* SMBIOS type0 (MM/DD/YYYY) */
|
const char *spoof_bios_date(const char *def); /* SMBIOS type0 (MM/DD/YYYY) */
|
||||||
|
const char *spoof_system_manufacturer(const char *def); /* SMBIOS type1 */
|
||||||
|
const char *spoof_system_product(const char *def); /* SMBIOS type1 */
|
||||||
const char *spoof_baseboard_manufacturer(const char *def); /* SMBIOS type2 */
|
const char *spoof_baseboard_manufacturer(const char *def); /* SMBIOS type2 */
|
||||||
|
|
||||||
/* ---- ACPI (spoof-acpi.c; hw/acpi, hw/i386/acpi-build) --------------------- */
|
/* ---- ACPI (spoof-acpi.c; hw/acpi, hw/i386/acpi-build) --------------------- */
|
||||||
|
|||||||
Reference in New Issue
Block a user