Skip to content

Commit 4a5ead0

Browse files
authored
Merge pull request #351 from dmfrpro/phantom
Phantom
2 parents c94a723 + d7537e7 commit 4a5ead0

4 files changed

Lines changed: 92 additions & 24 deletions

File tree

docs/documentation.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
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) |
518518
| `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) |
519+
| `VM::IVSHMEM` | Check for IVSHMEM device absense | 🪟 | 100% | | | | |
519520
| `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) |
520521
| `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) |
521522
| `VM::VM_DEVICES` | Check for VM-specific devices | 🪟 | 50% | | | | | [link](https://github.com/kernelwernel/VMAware/blob/8cb2491b1c7d2cb7300d1d698b7c64c953b4ae75/src/vmaware.hpp#L7848) |
@@ -617,6 +618,7 @@ This is the table of all the brands the lib supports.
617618
| NoirVisor | `brands::NOIRVISOR` | Hypervisor (type 1) | |
618619
| Qihoo 360 Sandbox | `brands::QIHOO` | Sandbox | |
619620
| nsjail | `brands::NSJAIL` | Process isolator | |
621+
| Hypervisor-Phantom | `brands::HYPERVISOR_PHANTOM` | Sandbox | See the [repository](https://github.com/Scrut1ny/Hypervisor-Phantom) |
620622

621623
<br>
622624

src/cli.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ Neko Project II
276276
NoirVisor
277277
Qihoo 360 Sandbox
278278
nsjail
279+
Hypervisor-Phantom
279280
)";
280281

281282
std::exit(0);
@@ -449,6 +450,7 @@ bool is_unsupported(VM::enum_flags flag) {
449450
case VM::DRIVER_NAMES:
450451
case VM::DISK_SERIAL:
451452
case VM::PORT_CONNECTORS:
453+
case VM::IVSHMEM:
452454
case VM::GPU_VM_STRINGS:
453455
case VM::GPU_CAPABILITIES:
454456
case VM::PROCESSOR_NUMBER:
@@ -652,6 +654,7 @@ std::string vm_description(const std::string& vm_brand) {
652654
{ brands::NOIRVISOR, "NoirVisor is a hardware-accelerated hypervisor with support to complex functions and purposes. It is designed to support processors based on x86 architecture with hardware-accelerated virtualization feature. For example, Intel processors supporting Intel VT-x or AMD processors supporting AMD-V meet the requirement. It was made by Zero-Tang." },
653655
{ brands::QIHOO, "360 sandbox is a part of 360 Total Security. Similar to other sandbox software, it provides a virtualized environment where potentially malicious or untrusted programs can run without affecting the actual system. Qihoo 360 Sandbox is commonly used for testing unknown applications, analyzing malware behavior, and protecting users from zero-day threats." },
654656
{ brands::NSJAIL, "nsjail is a process isolation tool for Linux. It utilizes Linux namespace subsystem, resource limits, and the seccomp-bpf syscall filters of the Linux kernel. It can be used for isolating networking services, CTF challenges, and containing invasive syscall-level OS fuzzers." },
657+
{ brands::HYPERVISOR_PHANTOM, "Hypervisor-Phantom is an automated setup solution designed to evade detection from advanced malware, enabling thorough analysis. It employs a highly customized version of QEMU/KVM, EDK2, and the Linux Kernel. This also spoofs many unique hypervisor identifiers, effectively disguising the environment. This setup enhances the accuracy and reliability of malware analysis by minimizing the risk of detection." },
655658
{ brands::NULL_BRAND, "Indicates no detectable virtualization brand. This result may occur on bare-metal systems, unsupported/obscure hypervisors, or when anti-detection techniques (e.g., VM escaping) are employed by the guest environment." }
656659
};
657660

@@ -949,6 +952,7 @@ void general() {
949952
checker(VM::DRIVER_NAMES, "driver names");
950953
checker(VM::DISK_SERIAL, "disk serial number");
951954
checker(VM::PORT_CONNECTORS, "physical connection ports");
955+
checker(VM::IVSHMEM, "IVSHMEM device");
952956
checker(VM::GPU_CAPABILITIES, "GPU capabilities");
953957
checker(VM::GPU_VM_STRINGS, "GPU strings");
954958
checker(VM::PROCESSOR_NUMBER, "processor count");

src/vmaware.hpp

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,7 @@ namespace brands {
538538
static constexpr const char* NOIRVISOR = "NoirVisor";
539539
static constexpr const char* QIHOO = "Qihoo 360 Sandbox";
540540
static constexpr const char* NSJAIL = "nsjail";
541+
static constexpr const char* HYPERVISOR_PHANTOM = "Hypervisor-Phantom";
541542
}
542543

543544

@@ -637,6 +638,7 @@ struct VM {
637638
DRIVER_NAMES,
638639
DISK_SERIAL,
639640
PORT_CONNECTORS,
641+
IVSHMEM,
640642
GPU_VM_STRINGS,
641643
GPU_CAPABILITIES,
642644
VM_DEVICES,
@@ -1261,6 +1263,7 @@ struct VM {
12611263
return (
12621264
!cache_keys.test(VMWARE_DMESG) &&
12631265
!cache_keys.test(PORT_CONNECTORS) &&
1266+
!cache_keys.test(IVSHMEM) &&
12641267
!cache_keys.test(ACPI_TEMPERATURE)
12651268
);
12661269
}
@@ -3730,14 +3733,14 @@ struct VM {
37303733

37313734
if (runningProcesses.count("vdagent.exe") ||
37323735
runningProcesses.count("vdservice.exe") ||
3733-
runningProcesses.count("qemuwmi.exe") ||
3734-
runningProcesses.count("looking-glass-host.exe")) {
3736+
runningProcesses.count("qemuwmi.exe")) {
37353737
debug("VM_PROCESSES: Detected QEMU process.");
37363738
return core::add(brands::QEMU);
37373739
}
37383740

3739-
if (runningProcesses.count("VDDSysTray.exe")) {
3740-
return true;
3741+
if (runningProcesses.count("looking-glass-host.exe") ||
3742+
runningProcesses.count("VDDSysTray.exe")) {
3743+
return core::add(brands::HYPERVISOR_PHANTOM);
37413744
}
37423745

37433746
#elif (LINUX)
@@ -7399,6 +7402,33 @@ struct VM {
73997402
#endif
74007403
}
74017404

7405+
/**
7406+
* @brief Check for IVSHMEM device absense
7407+
* @category Windows
7408+
* @author dmfrpro (https://github.com/dmfrpro)
7409+
* @implements VM::IVSHMEM
7410+
*/
7411+
[[nodiscard]] static bool ivshmem() {
7412+
#if (!WINDOWS)
7413+
return false;
7414+
#else
7415+
const GUID GUID_IVSHMEM_IFACE =
7416+
{ 0xdf576976, 0x569d, 0x4672, {0x95, 0xa0, 0xf5, 0x7e, 0x4e, 0xa0, 0xb2, 0x10} };
7417+
7418+
HDEVINFO hDevInfo = SetupDiGetClassDevsW(&GUID_IVSHMEM_IFACE,
7419+
nullptr, nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
7420+
if (hDevInfo == INVALID_HANDLE_VALUE) {
7421+
return true;
7422+
}
7423+
7424+
SP_DEVINFO_DATA devInfoData = { sizeof(SP_DEVINFO_DATA) };
7425+
// Check first device only
7426+
const bool hasIvshmemData = SetupDiEnumDeviceInfo(hDevInfo, 0, &devInfoData);
7427+
7428+
SetupDiDestroyDeviceInfoList(hDevInfo);
7429+
return hasIvshmemData ? core::add(brands::HYPERVISOR_PHANTOM) : false;
7430+
#endif
7431+
}
74027432

74037433
/**
74047434
* @brief Check for specific GPU string signatures related to VMs
@@ -9285,8 +9315,8 @@ struct VM {
92859315
constexpr const char* targets[] = {
92869316
"Parallels Software International", "Parallels(R)", "innotek",
92879317
"Oracle", "VirtualBox", "vbox", "VBOX", "VS2005R2", "VMware, Inc.",
9288-
"VMware", "VMWARE", "S3 Corp.", "Virtual Machine", "QEMU", "FWCF",
9289-
"WAET", "BOCHS", "BXPC"
9318+
"VMware", "VMWARE", "S3 Corp.", "Virtual Machine", "QEMU", "WAET",
9319+
"BOCHS", "BXPC"
92909320
};
92919321

92929322
auto check_firmware_table = [&](DWORD signature, ULONG tableID) -> bool {
@@ -9347,8 +9377,7 @@ struct VM {
93479377
strcmp(target, "VMware") == 0 ||
93489378
strcmp(target, "VMWARE") == 0)
93499379
brand = brands::VMWARE;
9350-
else if (strcmp(target, "QEMU") == 0 ||
9351-
strcmp(target, "FWCF") == 0)
9380+
else if (strcmp(target, "QEMU") == 0)
93529381
brand = brands::QEMU;
93539382
else if (strcmp(target, "BOCHS") == 0 ||
93549383
strcmp(target, "BXPC") == 0)
@@ -9496,8 +9525,8 @@ struct VM {
94969525
constexpr const char* targets[] = {
94979526
"Parallels Software International", "Parallels(R)", "innotek",
94989527
"Oracle", "VirtualBox", "vbox", "VBOX", "VS2005R2", "VMware, Inc.",
9499-
"VMware", "VMWARE", "S3 Corp.", "Virtual Machine", "QEMU", "FWCF",
9500-
"BOCHS", "BXPC"
9528+
"VMware", "VMWARE", "S3 Corp.", "Virtual Machine", "QEMU", "BOCHS",
9529+
"BXPC"
95019530
};
95029531

95039532
struct dirent* entry;
@@ -9565,8 +9594,7 @@ struct VM {
95659594
strcmp(target, "VMWARE") == 0) {
95669595
brand = brands::VMWARE;
95679596
}
9568-
else if (strcmp(target, "QEMU") == 0 ||
9569-
strcmp(target, "FWCF") == 0) {
9597+
else if (strcmp(target, "QEMU")) {
95709598
brand = brands::QEMU;
95719599
}
95729600
else if (strcmp(target, "BOCHS") == 0 ||
@@ -11197,6 +11225,7 @@ struct VM {
1119711225
case DRIVER_NAMES: return "DRIVER_NAMES";
1119811226
case DISK_SERIAL: return "DISK_SERIAL";
1119911227
case PORT_CONNECTORS: return "PORT_CONNECTORS";
11228+
case IVSHMEM: return "IVSHMEM";
1120011229
case GPU_VM_STRINGS: return "GPU_STRINGS";
1120111230
case GPU_CAPABILITIES: return "GPU_CAPABILITIES";
1120211231
case VM_DEVICES: return "VM_DEVICES";
@@ -11382,6 +11411,7 @@ struct VM {
1138211411
{ brands::COMODO, "Sandbox" },
1138311412
{ brands::THREATEXPERT, "Sandbox" },
1138411413
{ brands::QIHOO, "Sandbox" },
11414+
{ brands::HYPERVISOR_PHANTOM, "Sandbox" },
1138511415

1138611416
// misc
1138711417
{ brands::BOCHS, "Emulator" },
@@ -11753,6 +11783,7 @@ std::pair<VM::enum_flags, VM::core::technique> VM::core::technique_list[] = {
1175311783
std::make_pair(VM::DRIVER_NAMES, VM::core::technique(100, VM::driver_names)),
1175411784
std::make_pair(VM::DISK_SERIAL, VM::core::technique(100, VM::disk_serial_number)),
1175511785
std::make_pair(VM::PORT_CONNECTORS, VM::core::technique(25, VM::port_connectors)),
11786+
std::make_pair(VM::IVSHMEM, VM::core::technique(100, VM::ivshmem)),
1175611787
std::make_pair(VM::GPU_VM_STRINGS, VM::core::technique(100, VM::gpu_vm_strings)),
1175711788
std::make_pair(VM::GPU_CAPABILITIES, VM::core::technique(100, VM::gpu_capabilities)),
1175811789
std::make_pair(VM::VM_DEVICES, VM::core::technique(50, VM::vm_devices)),

src/vmaware_MIT.hpp

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ namespace brands {
560560
static constexpr const char* NOIRVISOR = "NoirVisor";
561561
static constexpr const char* QIHOO = "Qihoo 360 Sandbox";
562562
static constexpr const char* NSJAIL = "nsjail";
563+
static constexpr const char* HYPERVISOR_PHANTOM = "Hypervisor-Phantom";
563564
}
564565

565566

@@ -652,6 +653,7 @@ struct VM {
652653
DRIVER_NAMES,
653654
DISK_SERIAL,
654655
PORT_CONNECTORS,
656+
IVSHMEM,
655657
GPU_VM_STRINGS,
656658
GPU_CAPABILITIES,
657659
VM_DEVICES,
@@ -3514,14 +3516,14 @@ struct VM {
35143516

35153517
if (runningProcesses.count("vdagent.exe") ||
35163518
runningProcesses.count("vdservice.exe") ||
3517-
runningProcesses.count("qemuwmi.exe") ||
3518-
runningProcesses.count("looking-glass-host.exe")) {
3519+
runningProcesses.count("qemuwmi.exe")) {
35193520
debug("VM_PROCESSES: Detected QEMU process.");
35203521
return core::add(brands::QEMU);
35213522
}
35223523

3523-
if (runningProcesses.count("VDDSysTray.exe")) {
3524-
return true;
3524+
if (runningProcesses.count("looking-glass-host.exe") ||
3525+
runningProcesses.count("VDDSysTray.exe")) {
3526+
return core::add(brands::HYPERVISOR_PHANTOM);
35253527
}
35263528

35273529
#elif (LINUX)
@@ -7183,6 +7185,34 @@ struct VM {
71837185
#endif
71847186
}
71857187

7188+
/**
7189+
* @brief Check for IVSHMEM device absense
7190+
* @category Windows
7191+
* @author dmfrpro (https://github.com/dmfrpro)
7192+
* @implements VM::IVSHMEM
7193+
*/
7194+
[[nodiscard]] static bool ivshmem() {
7195+
#if (!WINDOWS)
7196+
return false;
7197+
#else
7198+
const GUID GUID_IVSHMEM_IFACE =
7199+
{ 0xdf576976, 0x569d, 0x4672, {0x95, 0xa0, 0xf5, 0x7e, 0x4e, 0xa0, 0xb2, 0x10} };
7200+
7201+
HDEVINFO hDevInfo = SetupDiGetClassDevsW(&GUID_IVSHMEM_IFACE,
7202+
nullptr, nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
7203+
if (hDevInfo == INVALID_HANDLE_VALUE) {
7204+
return true;
7205+
}
7206+
7207+
SP_DEVINFO_DATA devInfoData = { sizeof(SP_DEVINFO_DATA) };
7208+
// Check first device only
7209+
const bool hasIvshmemData = SetupDiEnumDeviceInfo(hDevInfo, 0, &devInfoData);
7210+
7211+
SetupDiDestroyDeviceInfoList(hDevInfo);
7212+
return hasIvshmemData ? core::add(brands::HYPERVISOR_PHANTOM) : false;
7213+
#endif
7214+
}
7215+
71867216

71877217
/**
71887218
* @brief Check for specific GPU string signatures related to VMs
@@ -9069,8 +9099,8 @@ struct VM {
90699099
constexpr const char* targets[] = {
90709100
"Parallels Software International", "Parallels(R)", "innotek",
90719101
"Oracle", "VirtualBox", "vbox", "VBOX", "VS2005R2", "VMware, Inc.",
9072-
"VMware", "VMWARE", "S3 Corp.", "Virtual Machine", "QEMU", "FWCF",
9073-
"WAET", "BOCHS", "BXPC"
9102+
"VMware", "VMWARE", "S3 Corp.", "Virtual Machine", "QEMU", "WAET",
9103+
"BOCHS", "BXPC"
90749104
};
90759105

90769106
auto check_firmware_table = [&](DWORD signature, ULONG tableID) -> bool {
@@ -9131,8 +9161,7 @@ struct VM {
91319161
strcmp(target, "VMware") == 0 ||
91329162
strcmp(target, "VMWARE") == 0)
91339163
brand = brands::VMWARE;
9134-
else if (strcmp(target, "QEMU") == 0 ||
9135-
strcmp(target, "FWCF") == 0)
9164+
else if (strcmp(target, "QEMU") == 0)
91369165
brand = brands::QEMU;
91379166
else if (strcmp(target, "BOCHS") == 0 ||
91389167
strcmp(target, "BXPC") == 0)
@@ -9280,8 +9309,8 @@ struct VM {
92809309
constexpr const char* targets[] = {
92819310
"Parallels Software International", "Parallels(R)", "innotek",
92829311
"Oracle", "VirtualBox", "vbox", "VBOX", "VS2005R2", "VMware, Inc.",
9283-
"VMware", "VMWARE", "S3 Corp.", "Virtual Machine", "QEMU", "FWCF",
9284-
"BOCHS", "BXPC"
9312+
"VMware", "VMWARE", "S3 Corp.", "Virtual Machine", "QEMU","BOCHS",
9313+
"BXPC"
92859314
};
92869315

92879316
struct dirent* entry;
@@ -9349,8 +9378,7 @@ struct VM {
93499378
strcmp(target, "VMWARE") == 0) {
93509379
brand = brands::VMWARE;
93519380
}
9352-
else if (strcmp(target, "QEMU") == 0 ||
9353-
strcmp(target, "FWCF") == 0) {
9381+
else if (strcmp(target, "QEMU") == 0) {
93549382
brand = brands::QEMU;
93559383
}
93569384
else if (strcmp(target, "BOCHS") == 0 ||
@@ -10971,6 +10999,7 @@ struct VM {
1097110999
case DRIVER_NAMES: return "DRIVER_NAMES";
1097211000
case DISK_SERIAL: return "DISK_SERIAL";
1097311001
case PORT_CONNECTORS: return "PORT_CONNECTORS";
11002+
case IVSHMEM: return "IVSHMEM";
1097411003
case GPU_VM_STRINGS: return "GPU_STRINGS";
1097511004
case GPU_CAPABILITIES: return "GPU_CAPABILITIES";
1097611005
case VM_DEVICES: return "VM_DEVICES";
@@ -11155,6 +11184,7 @@ struct VM {
1115511184
{ brands::COMODO, "Sandbox" },
1115611185
{ brands::THREATEXPERT, "Sandbox" },
1115711186
{ brands::QIHOO, "Sandbox" },
11187+
{ brands::HYPERVISOR_PHANTOM, "Sandbox" },
1115811188

1115911189
// misc
1116011190
{ brands::BOCHS, "Emulator" },
@@ -11519,6 +11549,7 @@ std::pair<VM::enum_flags, VM::core::technique> VM::core::technique_list[] = {
1151911549
std::make_pair(VM::DRIVER_NAMES, VM::core::technique(100, VM::driver_names)),
1152011550
std::make_pair(VM::DISK_SERIAL, VM::core::technique(100, VM::disk_serial_number)),
1152111551
std::make_pair(VM::PORT_CONNECTORS, VM::core::technique(25, VM::port_connectors)),
11552+
std::make_pair(VM::IVSHMEM, VM::core::technique(100, VM::ivshmem)),
1152211553
std::make_pair(VM::GPU_VM_STRINGS, VM::core::technique(100, VM::gpu_vm_strings)),
1152311554
std::make_pair(VM::GPU_CAPABILITIES, VM::core::technique(100, VM::gpu_capabilities)),
1152411555
std::make_pair(VM::VM_DEVICES, VM::core::technique(50, VM::vm_devices)),

0 commit comments

Comments
 (0)