28
28
*
29
29
* ============================== SECTIONS ==================================
30
30
* - 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
38
38
*
39
39
*
40
40
* ============================== EXAMPLE ===================================
368
368
#include < mmsystem.h>
369
369
#include < dxgi.h>
370
370
#include < d3d9.h>
371
- #include < tlhelp32.h>
372
371
373
372
#pragma comment(lib, "dxgi.lib")
374
373
#pragma comment(lib, "d3d9.lib")
@@ -590,6 +589,7 @@ struct VM {
590
589
IOREG_GREP,
591
590
MAC_SIP,
592
591
HKLM_REGISTRIES,
592
+ QEMU_GA,
593
593
VPC_INVALID,
594
594
SIDT,
595
595
SGDT,
@@ -1769,28 +1769,31 @@ struct VM {
1769
1769
}
1770
1770
1771
1771
// 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) {
1773
1773
#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);
1784
1788
return true ;
1785
1789
}
1786
- } while (Process32Next (hSnapshot, &processEntry));
1790
+ }
1791
+ CloseHandle (process);
1787
1792
}
1788
-
1789
- CloseHandle (hSnapshot);
1790
1793
}
1791
1794
1795
+ return false ;
1792
1796
#elif (LINUX)
1793
- (void *)len;
1794
1797
#if (CPP >= 17)
1795
1798
for (const auto & entry : std::filesystem::directory_iterator (" /proc" )) {
1796
1799
if (!(entry.is_directory ())) {
@@ -1799,6 +1802,7 @@ struct VM {
1799
1802
1800
1803
const std::string filename = entry.path ().filename ().string ();
1801
1804
#else
1805
+ // DIR* dir = opendir("/proc/");
1802
1806
std::unique_ptr<DIR, decltype (&closedir)> dir (opendir (" /proc" ), closedir);
1803
1807
if (!dir) {
1804
1808
debug (" util::is_proc_running: " , " failed to open /proc directory" );
@@ -1830,10 +1834,14 @@ struct VM {
1830
1834
continue ;
1831
1835
}
1832
1836
1837
+ // std::cout << "\n\nLINE = " << line << "\n";
1833
1838
if (line.find (executable) == std::string::npos) {
1839
+ // std::cout << "skipped\n";
1834
1840
continue ;
1835
1841
}
1836
1842
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
+
1837
1845
const std::size_t slash_index = line.find_last_of (' /' );
1838
1846
1839
1847
if (slash_index == std::string::npos) {
@@ -1851,11 +1859,43 @@ struct VM {
1851
1859
if (line != executable) {
1852
1860
continue ;
1853
1861
}
1854
-
1862
+ // #if (CPP < 17)
1863
+ // closedir(dir);
1864
+ // free(dir);
1865
+ // #endif
1855
1866
return true ;
1856
1867
}
1857
- #endif
1868
+
1869
+ return false ;
1870
+ #else
1858
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
+ }
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;
1859
1899
}
1860
1900
1861
1901
// Retrieves the computer name
@@ -3615,58 +3655,52 @@ struct VM {
3615
3655
* @implements VM::VM_PROCESSES
3616
3656
*/
3617
3657
[[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 ();
3630
3662
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
+ }
3633
3667
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
+ }
3637
3672
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
+ }
3643
3677
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
+ }
3652
3682
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
+ }
3655
3687
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);
3661
3693
}
3662
3694
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." );
3666
3699
return core::add (brands::QEMU);
3667
3700
}
3668
- #endif
3669
- return res;
3701
+
3702
+ return false ;
3703
+ #endif
3670
3704
}
3671
3705
3672
3706
@@ -4297,6 +4331,27 @@ struct VM {
4297
4331
#endif
4298
4332
}
4299
4333
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
+
4300
4355
/* *
4301
4356
* @brief Check for official VPC method
4302
4357
* @category Windows, x86
@@ -11235,6 +11290,7 @@ struct VM {
11235
11290
case IOREG_GREP: return " IOREG_GREP" ;
11236
11291
case MAC_SIP: return " MAC_SIP" ;
11237
11292
case HKLM_REGISTRIES: return " HKLM_REGISTRIES" ;
11293
+ case QEMU_GA: return " QEMU_GA" ;
11238
11294
case VPC_INVALID: return " VPC_INVALID" ;
11239
11295
case SIDT: return " SIDT" ;
11240
11296
case SGDT: return " SGDT" ;
@@ -11794,6 +11850,7 @@ std::pair<VM::enum_flags, VM::core::technique> VM::core::technique_list[] = {
11794
11850
std::make_pair (VM::IOREG_GREP, VM::core::technique (100 , VM::ioreg_grep)),
11795
11851
std::make_pair (VM::MAC_SIP, VM::core::technique (40 , VM::mac_sip)),
11796
11852
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)),
11797
11854
std::make_pair (VM::VPC_INVALID, VM::core::technique (75 , VM::vpc_invalid)),
11798
11855
std::make_pair (VM::SIDT, VM::core::technique (25 , VM::sidt)),
11799
11856
std::make_pair (VM::SGDT, VM::core::technique (30 , VM::sgdt)),
0 commit comments