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 ===================================
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