Skip to content

Commit df0b228

Browse files
authored
Merge pull request #341 from kernelwernel/revert-340-vm_processes
Revert "Refactoring & Looking Glass detection"
2 parents 78718ee + 944263f commit df0b228

File tree

4 files changed

+256
-141
lines changed

4 files changed

+256
-141
lines changed

docs/documentation.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@ 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% | | | | |
468469
| `VM::VPC_INVALID` | Check for official VPC method | Windows | 75% | | | 32-bit | |
469470
| `VM::SIDT` | Check for sidt instruction method | Windows | 25% | | | | |
470471
| `VM::SGDT` | Check for sgdt instruction method | Windows | 30% | | | 32-bit | |

src/cli.cpp

Lines changed: 2 additions & 1 deletion
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:
356355
case VM::VBOX_DEFAULT:
357356
case VM::LINUX_USER_HOST:
358357
case VM::BOCHS_CPU:
358+
case VM::QEMU_GA:
359359
case VM::SIDT:
360360
case VM::VMWARE_IOMEM:
361361
case VM::VMWARE_IOPORTS:
@@ -907,6 +907,7 @@ 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");
910911
checker(VM::QEMU_DIR, "QEMU directories");
911912
checker(VM::VPC_INVALID, "VPC invalid instructions");
912913
checker(VM::SIDT, "SIDT");

src/vmaware.hpp

Lines changed: 124 additions & 67 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 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
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
3838
*
3939
*
4040
* ============================== EXAMPLE ===================================
@@ -368,7 +368,6 @@
368368
#include <mmsystem.h>
369369
#include <dxgi.h>
370370
#include <d3d9.h>
371-
#include <tlhelp32.h>
372371

373372
#pragma comment(lib, "dxgi.lib")
374373
#pragma comment(lib, "d3d9.lib")
@@ -590,6 +589,7 @@ struct VM {
590589
IOREG_GREP,
591590
MAC_SIP,
592591
HKLM_REGISTRIES,
592+
QEMU_GA,
593593
VPC_INVALID,
594594
SIDT,
595595
SGDT,
@@ -1769,28 +1769,31 @@ struct VM {
17691769
}
17701770

17711771
// Checks if a process is running
1772-
[[nodiscard]] static bool is_proc_running(const char* executable, size_t len) {
1772+
[[nodiscard]] static bool is_proc_running(const char* executable) {
17731773
#if (WINDOWS)
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);
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);
17841788
return true;
17851789
}
1786-
} while (Process32Next(hSnapshot, &processEntry));
1790+
}
1791+
CloseHandle(process);
17871792
}
1788-
1789-
CloseHandle(hSnapshot);
17901793
}
17911794

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

18001803
const std::string filename = entry.path().filename().string();
18011804
#else
1805+
//DIR* dir = opendir("/proc/");
18021806
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir("/proc"), closedir);
18031807
if (!dir) {
18041808
debug("util::is_proc_running: ", "failed to open /proc directory");
@@ -1830,10 +1834,14 @@ struct VM {
18301834
continue;
18311835
}
18321836

1837+
//std::cout << "\n\nLINE = " << line << "\n";
18331838
if (line.find(executable) == std::string::npos) {
1839+
//std::cout << "skipped\n";
18341840
continue;
18351841
}
18361842

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+
18371845
const std::size_t slash_index = line.find_last_of('/');
18381846

18391847
if (slash_index == std::string::npos) {
@@ -1851,11 +1859,43 @@ struct VM {
18511859
if (line != executable) {
18521860
continue;
18531861
}
1854-
1862+
//#if (CPP < 17)
1863+
// closedir(dir);
1864+
// free(dir);
1865+
//#endif
18551866
return true;
18561867
}
1857-
#endif
1868+
1869+
return false;
1870+
#else
18581871
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+
}
1884+
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+
}
1896+
}
1897+
#endif
1898+
return processNames;
18591899
}
18601900

18611901
// Retrieves the computer name
@@ -3615,58 +3655,52 @@ struct VM {
36153655
* @implements VM::VM_PROCESSES
36163656
*/
36173657
[[nodiscard]] static bool vm_processes() {
3618-
bool res = false;
3619-
3620-
#if (WINDOWS)
3621-
struct VMProcess {
3622-
const char* name;
3623-
const char* brand;
3624-
const size_t len;
3625-
};
3626-
3627-
constexpr std::array<VMProcess, 19> vm_processes_names = { {
3628-
{ "joeboxserver.exe", brands::JOEBOX, 16 },
3629-
{ "joeboxcontrol.exe", brands::JOEBOX, 17 },
3658+
#if (!WINDOWS)
3659+
return false;
3660+
#else
3661+
const auto runningProcesses = util::get_running_process_names();
36303662

3631-
{ "prl_cc.exe", brands::PARALLELS, 10 },
3632-
{ "prl_tools.exe", brands::PARALLELS, 13 },
3663+
if (runningProcesses.count("joeboxserver.exe") || runningProcesses.count("joeboxcontrol.exe")) {
3664+
debug("VM_PROCESSES: Detected JoeBox process.");
3665+
return core::add(brands::JOEBOX);
3666+
}
36333667

3634-
{ "vboxservice.exe", brands::VBOX, 15 },
3635-
{ "vboxtray.exe", brands::VBOX, 12 },
3636-
{ "VBoxControl.exe", brands::VBOX, 15 },
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+
}
36373672

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 },
3673+
if (runningProcesses.count("vboxservice.exe") || runningProcesses.count("vboxtray.exe")) {
3674+
debug("VM_PROCESSES: Detected VBox process.");
3675+
return core::add(brands::VBOX);
3676+
}
36433677

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 },
3678+
if (runningProcesses.count("vmsrvc.exe") || runningProcesses.count("vmusrvc.exe")) {
3679+
debug("VM_PROCESSES: Detected VPC process.");
3680+
return core::add(brands::VPC);
3681+
}
36523682

3653-
{ "VDDSysTray.exe", brands::NULL_BRAND, 14 },
3654-
} };
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+
}
36553687

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-
}
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);
36613693
}
36623694

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

36723706

@@ -4297,6 +4331,27 @@ struct VM {
42974331
#endif
42984332
}
42994333

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+
43004355
/**
43014356
* @brief Check for official VPC method
43024357
* @category Windows, x86
@@ -11235,6 +11290,7 @@ struct VM {
1123511290
case IOREG_GREP: return "IOREG_GREP";
1123611291
case MAC_SIP: return "MAC_SIP";
1123711292
case HKLM_REGISTRIES: return "HKLM_REGISTRIES";
11293+
case QEMU_GA: return "QEMU_GA";
1123811294
case VPC_INVALID: return "VPC_INVALID";
1123911295
case SIDT: return "SIDT";
1124011296
case SGDT: return "SGDT";
@@ -11794,6 +11850,7 @@ std::pair<VM::enum_flags, VM::core::technique> VM::core::technique_list[] = {
1179411850
std::make_pair(VM::IOREG_GREP, VM::core::technique(100, VM::ioreg_grep)),
1179511851
std::make_pair(VM::MAC_SIP, VM::core::technique(40, VM::mac_sip)),
1179611852
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)),
1179711854
std::make_pair(VM::VPC_INVALID, VM::core::technique(75, VM::vpc_invalid)),
1179811855
std::make_pair(VM::SIDT, VM::core::technique(25, VM::sidt)),
1179911856
std::make_pair(VM::SGDT, VM::core::technique(30, VM::sgdt)),

0 commit comments

Comments
 (0)