Skip to content

Commit 78718ee

Browse files
authored
Merge pull request #340 from dmfrpro/vm_processes
Refactoring & Looking Glass detection
2 parents 146c905 + ae8021a commit 78718ee

4 files changed

Lines changed: 141 additions & 256 deletions

File tree

docs/documentation.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,6 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
465465
| `VM::IOREG_GREP` | Check for VM-strings in ioreg commands for MacOS | MacOS | 100% | | | | |
466466
| `VM::MAC_SIP` | Check if System Integrity Protection is disabled (likely a VM if it is) | MacOS | 40% | | | | |
467467
| `VM::HKLM_REGISTRIES` | Check HKLM registries for specific VM strings | Windows | 25% | | | | |
468-
| `VM::QEMU_GA` | Check for "qemu-ga" process | Linux | 10% | | | | |
469468
| `VM::VPC_INVALID` | Check for official VPC method | Windows | 75% | | | 32-bit | |
470469
| `VM::SIDT` | Check for sidt instruction method | Windows | 25% | | | | |
471470
| `VM::SGDT` | Check for sgdt instruction method | Windows | 30% | | | 32-bit | |

src/cli.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,10 +352,10 @@ bool is_unsupported(VM::enum_flags flag) {
352352
case VM::HWMON:
353353
case VM::SIDT5:
354354
case VM::DISK_SIZE:
355+
case VM::VM_PROCESSES:
355356
case VM::VBOX_DEFAULT:
356357
case VM::LINUX_USER_HOST:
357358
case VM::BOCHS_CPU:
358-
case VM::QEMU_GA:
359359
case VM::SIDT:
360360
case VM::VMWARE_IOMEM:
361361
case VM::VMWARE_IOPORTS:
@@ -907,7 +907,6 @@ void general() {
907907
checker(VM::KVM_DIRS, "KVM directories");
908908
checker(VM::HKLM_REGISTRIES, "registry values");
909909
checker(VM::AUDIO, "audio device");
910-
checker(VM::QEMU_GA, "qemu-ga process");
911910
checker(VM::QEMU_DIR, "QEMU directories");
912911
checker(VM::VPC_INVALID, "VPC invalid instructions");
913912
checker(VM::SIDT, "SIDT");

src/vmaware.hpp

Lines changed: 67 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@
2828
*
2929
* ============================== SECTIONS ==================================
3030
* - enums for publicly accessible techniques => line 551
31-
* - struct for internal cpu operations => line 742
32-
* - struct for internal memoization => line 1213
33-
* - struct for internal utility functions => line 1337
34-
* - struct for internal core components => line 10067
35-
* - start of VM detection technique list => line 2363
36-
* - start of public VM detection functions => line 10731
37-
* - start of externally defined variables => line 11677
31+
* - struct for internal cpu operations => line 741
32+
* - struct for internal memoization => line 1212
33+
* - struct for internal utility functions => line 1336
34+
* - struct for internal core components => line 10018
35+
* - start of VM detection technique list => line 2322
36+
* - start of public VM detection functions => line 10682
37+
* - start of externally defined variables => line 11627
3838
*
3939
*
4040
* ============================== EXAMPLE ===================================
@@ -368,6 +368,7 @@
368368
#include <mmsystem.h>
369369
#include <dxgi.h>
370370
#include <d3d9.h>
371+
#include <tlhelp32.h>
371372

372373
#pragma comment(lib, "dxgi.lib")
373374
#pragma comment(lib, "d3d9.lib")
@@ -589,7 +590,6 @@ struct VM {
589590
IOREG_GREP,
590591
MAC_SIP,
591592
HKLM_REGISTRIES,
592-
QEMU_GA,
593593
VPC_INVALID,
594594
SIDT,
595595
SGDT,
@@ -1769,31 +1769,28 @@ struct VM {
17691769
}
17701770

17711771
// Checks if a process is running
1772-
[[nodiscard]] static bool is_proc_running(const char* executable) {
1772+
[[nodiscard]] static bool is_proc_running(const char* executable, size_t len) {
17731773
#if (WINDOWS)
1774-
DWORD processes[1024], bytesReturned;
1775-
1776-
if (!K32EnumProcesses(processes, sizeof(processes), &bytesReturned))
1777-
return false;
1778-
1779-
DWORD numProcesses = bytesReturned / sizeof(DWORD);
1780-
1781-
for (DWORD i = 0; i < numProcesses; ++i) {
1782-
const HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processes[i]);
1783-
if (process != nullptr) {
1784-
char processName[MAX_PATH] = { 0 };
1785-
if (K32GetModuleBaseNameA(process, nullptr, processName, sizeof(processName))) {
1786-
if (_stricmp(processName, executable) == 0) {
1787-
CloseHandle(process);
1774+
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
1775+
1776+
if (hSnapshot != INVALID_HANDLE_VALUE) {
1777+
PROCESSENTRY32 processEntry;
1778+
processEntry.dwSize = sizeof(PROCESSENTRY32);
1779+
1780+
if (Process32First(hSnapshot, &processEntry)) {
1781+
do {
1782+
if (strncmp(processEntry.szExeFile, executable, len) == 0) {
1783+
CloseHandle(hSnapshot);
17881784
return true;
17891785
}
1790-
}
1791-
CloseHandle(process);
1786+
} while (Process32Next(hSnapshot, &processEntry));
17921787
}
1788+
1789+
CloseHandle(hSnapshot);
17931790
}
17941791

1795-
return false;
17961792
#elif (LINUX)
1793+
(void *)len;
17971794
#if (CPP >= 17)
17981795
for (const auto& entry : std::filesystem::directory_iterator("/proc")) {
17991796
if (!(entry.is_directory())) {
@@ -1802,7 +1799,6 @@ struct VM {
18021799

18031800
const std::string filename = entry.path().filename().string();
18041801
#else
1805-
//DIR* dir = opendir("/proc/");
18061802
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir("/proc"), closedir);
18071803
if (!dir) {
18081804
debug("util::is_proc_running: ", "failed to open /proc directory");
@@ -1834,14 +1830,10 @@ struct VM {
18341830
continue;
18351831
}
18361832

1837-
//std::cout << "\n\nLINE = " << line << "\n";
18381833
if (line.find(executable) == std::string::npos) {
1839-
//std::cout << "skipped\n";
18401834
continue;
18411835
}
18421836

1843-
//std::cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nNOT SKIPPED\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
1844-
18451837
const std::size_t slash_index = line.find_last_of('/');
18461838

18471839
if (slash_index == std::string::npos) {
@@ -1859,43 +1851,11 @@ struct VM {
18591851
if (line != executable) {
18601852
continue;
18611853
}
1862-
//#if (CPP < 17)
1863-
// closedir(dir);
1864-
// free(dir);
1865-
//#endif
1866-
return true;
1867-
}
1868-
1869-
return false;
1870-
#else
1871-
return false;
1872-
#endif
1873-
}
1874-
1875-
// Returns a list of running process names
1876-
[[nodiscard]] static std::unordered_set<std::string> get_running_process_names() {
1877-
std::unordered_set<std::string> processNames;
1878-
#if (WINDOWS)
1879-
DWORD processes[1024], bytesReturned;
1880-
1881-
if (!K32EnumProcesses(processes, sizeof(processes), &bytesReturned)) {
1882-
return processNames;
1883-
}
18841854

1885-
DWORD numProcesses = bytesReturned / sizeof(DWORD);
1886-
char processName[MAX_PATH];
1887-
1888-
for (DWORD i = 0; i < numProcesses; ++i) {
1889-
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processes[i]);
1890-
if (hProcess != nullptr) {
1891-
if (K32GetModuleBaseNameA(hProcess, nullptr, processName, sizeof(processName))) {
1892-
processNames.insert(processName);
1893-
}
1894-
CloseHandle(hProcess);
1895-
}
1855+
return true;
18961856
}
18971857
#endif
1898-
return processNames;
1858+
return false;
18991859
}
19001860

19011861
// Retrieves the computer name
@@ -3655,52 +3615,58 @@ struct VM {
36553615
* @implements VM::VM_PROCESSES
36563616
*/
36573617
[[nodiscard]] static bool vm_processes() {
3658-
#if (!WINDOWS)
3659-
return false;
3660-
#else
3661-
const auto runningProcesses = util::get_running_process_names();
3618+
bool res = false;
36623619

3663-
if (runningProcesses.count("joeboxserver.exe") || runningProcesses.count("joeboxcontrol.exe")) {
3664-
debug("VM_PROCESSES: Detected JoeBox process.");
3665-
return core::add(brands::JOEBOX);
3666-
}
3620+
#if (WINDOWS)
3621+
struct VMProcess {
3622+
const char* name;
3623+
const char* brand;
3624+
const size_t len;
3625+
};
36673626

3668-
if (runningProcesses.count("prl_cc.exe") || runningProcesses.count("prl_tools.exe")) {
3669-
debug("VM_PROCESSES: Detected Parallels process.");
3670-
return core::add(brands::PARALLELS);
3671-
}
3627+
constexpr std::array<VMProcess, 19> vm_processes_names = { {
3628+
{ "joeboxserver.exe", brands::JOEBOX, 16 },
3629+
{ "joeboxcontrol.exe", brands::JOEBOX, 17 },
36723630

3673-
if (runningProcesses.count("vboxservice.exe") || runningProcesses.count("vboxtray.exe")) {
3674-
debug("VM_PROCESSES: Detected VBox process.");
3675-
return core::add(brands::VBOX);
3676-
}
3631+
{ "prl_cc.exe", brands::PARALLELS, 10 },
3632+
{ "prl_tools.exe", brands::PARALLELS, 13 },
36773633

3678-
if (runningProcesses.count("vmsrvc.exe") || runningProcesses.count("vmusrvc.exe")) {
3679-
debug("VM_PROCESSES: Detected VPC process.");
3680-
return core::add(brands::VPC);
3681-
}
3634+
{ "vboxservice.exe", brands::VBOX, 15 },
3635+
{ "vboxtray.exe", brands::VBOX, 12 },
3636+
{ "VBoxControl.exe", brands::VBOX, 15 },
36823637

3683-
if (runningProcesses.count("xenservice.exe") || runningProcesses.count("xsvc_depriv.exe")) {
3684-
debug("VM_PROCESSES: Detected Xen process.");
3685-
return core::add(brands::XEN);
3686-
}
3638+
{ "vmsrvc.exe", brands::VPC, 10 },
3639+
{ "vmusrvc.exe", brands::VPC, 11 },
3640+
3641+
{ "xenservice.exe", brands::XEN, 14 },
3642+
{ "xsvc_depriv.exe", brands::XEN, 15 },
36873643

3688-
if (runningProcesses.count("vm3dservice.exe") ||
3689-
runningProcesses.count("VGAuthService.exe") ||
3690-
runningProcesses.count("vmtoolsd.exe")) {
3691-
debug("VM_PROCESSES: Detected VMware process.");
3692-
return core::add(brands::VMWARE);
3644+
{ "vm3dservice.exe", brands::VMWARE, 15 },
3645+
{ "VGAuthService.exe", brands::VMWARE, 17 },
3646+
{ "vmtoolsd.exe", brands::VMWARE, 12 },
3647+
3648+
{ "vdagent.exe", brands::QEMU, 11 },
3649+
{ "vdservice.exe", brands::QEMU, 13 },
3650+
{ "qemuwmi.exe", brands::QEMU, 11 },
3651+
{ "looking-glass-host.exe", brands::QEMU, 22 },
3652+
3653+
{ "VDDSysTray.exe", brands::NULL_BRAND, 14 },
3654+
} };
3655+
3656+
for (auto vm_process : vm_processes_names) {
3657+
if (util::is_proc_running(vm_process.name, vm_process.len)) {
3658+
debug("VM_PROCESSES: Detected process ", vm_process.name);
3659+
res = true;
3660+
}
36933661
}
36943662

3695-
if (runningProcesses.count("vdagent.exe") ||
3696-
runningProcesses.count("vdservice.exe") ||
3697-
runningProcesses.count("qemuwmi.exe")) {
3698-
debug("VM_PROCESSES: Detected QEMU process.");
3663+
#elif (LINUX)
3664+
if (util::is_proc_running("qemu_ga", 7)) {
3665+
debug("VM_PROCESSES: Detected QEMU guest agent process.");
36993666
return core::add(brands::QEMU);
37003667
}
3701-
3702-
return false;
3703-
#endif
3668+
#endif
3669+
return res;
37043670
}
37053671

37063672

@@ -4331,27 +4297,6 @@ struct VM {
43314297
#endif
43324298
}
43334299

4334-
4335-
/**
4336-
* @brief Check for "qemu-ga" process
4337-
* @category Linux
4338-
* @implements VM::QEMU_GA
4339-
*/
4340-
[[nodiscard]] static bool qemu_ga() {
4341-
#if (!LINUX)
4342-
return false;
4343-
#else
4344-
constexpr const char* process = "qemu-ga";
4345-
4346-
if (util::is_proc_running(process)) {
4347-
return core::add(brands::QEMU);
4348-
}
4349-
4350-
return false;
4351-
#endif
4352-
}
4353-
4354-
43554300
/**
43564301
* @brief Check for official VPC method
43574302
* @category Windows, x86
@@ -11290,7 +11235,6 @@ struct VM {
1129011235
case IOREG_GREP: return "IOREG_GREP";
1129111236
case MAC_SIP: return "MAC_SIP";
1129211237
case HKLM_REGISTRIES: return "HKLM_REGISTRIES";
11293-
case QEMU_GA: return "QEMU_GA";
1129411238
case VPC_INVALID: return "VPC_INVALID";
1129511239
case SIDT: return "SIDT";
1129611240
case SGDT: return "SGDT";
@@ -11850,7 +11794,6 @@ std::pair<VM::enum_flags, VM::core::technique> VM::core::technique_list[] = {
1185011794
std::make_pair(VM::IOREG_GREP, VM::core::technique(100, VM::ioreg_grep)),
1185111795
std::make_pair(VM::MAC_SIP, VM::core::technique(40, VM::mac_sip)),
1185211796
std::make_pair(VM::HKLM_REGISTRIES, VM::core::technique(25, VM::hklm_registries)),
11853-
std::make_pair(VM::QEMU_GA, VM::core::technique(10, VM::qemu_ga)),
1185411797
std::make_pair(VM::VPC_INVALID, VM::core::technique(75, VM::vpc_invalid)),
1185511798
std::make_pair(VM::SIDT, VM::core::technique(25, VM::sidt)),
1185611799
std::make_pair(VM::SGDT, VM::core::technique(30, VM::sgdt)),

0 commit comments

Comments
 (0)