Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,6 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
| `VM::IOREG_GREP` | Check for VM-strings in ioreg commands for MacOS | MacOS | 100% | | | | |
| `VM::MAC_SIP` | Check if System Integrity Protection is disabled (likely a VM if it is) | MacOS | 40% | | | | |
| `VM::HKLM_REGISTRIES` | Check HKLM registries for specific VM strings | Windows | 25% | | | | |
| `VM::QEMU_GA` | Check for "qemu-ga" process | Linux | 10% | | | | |
| `VM::VPC_INVALID` | Check for official VPC method | Windows | 75% | | | 32-bit | |
| `VM::SIDT` | Check for sidt instruction method | Windows | 25% | | | | |
| `VM::SGDT` | Check for sgdt instruction method | Windows | 30% | | | 32-bit | |
Expand Down
3 changes: 1 addition & 2 deletions src/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,10 +352,10 @@ bool is_unsupported(VM::enum_flags flag) {
case VM::HWMON:
case VM::SIDT5:
case VM::DISK_SIZE:
case VM::VM_PROCESSES:
case VM::VBOX_DEFAULT:
case VM::LINUX_USER_HOST:
case VM::BOCHS_CPU:
case VM::QEMU_GA:
case VM::SIDT:
case VM::VMWARE_IOMEM:
case VM::VMWARE_IOPORTS:
Expand Down Expand Up @@ -907,7 +907,6 @@ void general() {
checker(VM::KVM_DIRS, "KVM directories");
checker(VM::HKLM_REGISTRIES, "registry values");
checker(VM::AUDIO, "audio device");
checker(VM::QEMU_GA, "qemu-ga process");
checker(VM::QEMU_DIR, "QEMU directories");
checker(VM::VPC_INVALID, "VPC invalid instructions");
checker(VM::SIDT, "SIDT");
Expand Down
191 changes: 67 additions & 124 deletions src/vmaware.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@
*
* ============================== SECTIONS ==================================
* - enums for publicly accessible techniques => line 551
* - struct for internal cpu operations => line 742
* - struct for internal memoization => line 1213
* - struct for internal utility functions => line 1337
* - struct for internal core components => line 10067
* - start of VM detection technique list => line 2363
* - start of public VM detection functions => line 10731
* - start of externally defined variables => line 11677
* - struct for internal cpu operations => line 741
* - struct for internal memoization => line 1212
* - struct for internal utility functions => line 1336
* - struct for internal core components => line 10018
* - start of VM detection technique list => line 2322
* - start of public VM detection functions => line 10682
* - start of externally defined variables => line 11627
*
*
* ============================== EXAMPLE ===================================
Expand Down Expand Up @@ -368,6 +368,7 @@
#include <mmsystem.h>
#include <dxgi.h>
#include <d3d9.h>
#include <tlhelp32.h>

#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3d9.lib")
Expand Down Expand Up @@ -589,7 +590,6 @@ struct VM {
IOREG_GREP,
MAC_SIP,
HKLM_REGISTRIES,
QEMU_GA,
VPC_INVALID,
SIDT,
SGDT,
Expand Down Expand Up @@ -1769,31 +1769,28 @@ struct VM {
}

// Checks if a process is running
[[nodiscard]] static bool is_proc_running(const char* executable) {
[[nodiscard]] static bool is_proc_running(const char* executable, size_t len) {
#if (WINDOWS)
DWORD processes[1024], bytesReturned;

if (!K32EnumProcesses(processes, sizeof(processes), &bytesReturned))
return false;

DWORD numProcesses = bytesReturned / sizeof(DWORD);

for (DWORD i = 0; i < numProcesses; ++i) {
const HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processes[i]);
if (process != nullptr) {
char processName[MAX_PATH] = { 0 };
if (K32GetModuleBaseNameA(process, nullptr, processName, sizeof(processName))) {
if (_stricmp(processName, executable) == 0) {
CloseHandle(process);
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

if (hSnapshot != INVALID_HANDLE_VALUE) {
PROCESSENTRY32 processEntry;
processEntry.dwSize = sizeof(PROCESSENTRY32);

if (Process32First(hSnapshot, &processEntry)) {
do {
if (strncmp(processEntry.szExeFile, executable, len) == 0) {
CloseHandle(hSnapshot);
return true;
}
}
CloseHandle(process);
} while (Process32Next(hSnapshot, &processEntry));
}

CloseHandle(hSnapshot);
}

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

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

//std::cout << "\n\nLINE = " << line << "\n";
if (line.find(executable) == std::string::npos) {
//std::cout << "skipped\n";
continue;
}

//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";

const std::size_t slash_index = line.find_last_of('/');

if (slash_index == std::string::npos) {
Expand All @@ -1859,43 +1851,11 @@ struct VM {
if (line != executable) {
continue;
}
//#if (CPP < 17)
// closedir(dir);
// free(dir);
//#endif
return true;
}

return false;
#else
return false;
#endif
}

// Returns a list of running process names
[[nodiscard]] static std::unordered_set<std::string> get_running_process_names() {
std::unordered_set<std::string> processNames;
#if (WINDOWS)
DWORD processes[1024], bytesReturned;

if (!K32EnumProcesses(processes, sizeof(processes), &bytesReturned)) {
return processNames;
}

DWORD numProcesses = bytesReturned / sizeof(DWORD);
char processName[MAX_PATH];

for (DWORD i = 0; i < numProcesses; ++i) {
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processes[i]);
if (hProcess != nullptr) {
if (K32GetModuleBaseNameA(hProcess, nullptr, processName, sizeof(processName))) {
processNames.insert(processName);
}
CloseHandle(hProcess);
}
return true;
}
#endif
return processNames;
return false;
}

// Retrieves the computer name
Expand Down Expand Up @@ -3655,52 +3615,58 @@ struct VM {
* @implements VM::VM_PROCESSES
*/
[[nodiscard]] static bool vm_processes() {
#if (!WINDOWS)
return false;
#else
const auto runningProcesses = util::get_running_process_names();
bool res = false;

if (runningProcesses.count("joeboxserver.exe") || runningProcesses.count("joeboxcontrol.exe")) {
debug("VM_PROCESSES: Detected JoeBox process.");
return core::add(brands::JOEBOX);
}
#if (WINDOWS)
struct VMProcess {
const char* name;
const char* brand;
const size_t len;
};

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

if (runningProcesses.count("vboxservice.exe") || runningProcesses.count("vboxtray.exe")) {
debug("VM_PROCESSES: Detected VBox process.");
return core::add(brands::VBOX);
}
{ "prl_cc.exe", brands::PARALLELS, 10 },
{ "prl_tools.exe", brands::PARALLELS, 13 },

if (runningProcesses.count("vmsrvc.exe") || runningProcesses.count("vmusrvc.exe")) {
debug("VM_PROCESSES: Detected VPC process.");
return core::add(brands::VPC);
}
{ "vboxservice.exe", brands::VBOX, 15 },
{ "vboxtray.exe", brands::VBOX, 12 },
{ "VBoxControl.exe", brands::VBOX, 15 },

if (runningProcesses.count("xenservice.exe") || runningProcesses.count("xsvc_depriv.exe")) {
debug("VM_PROCESSES: Detected Xen process.");
return core::add(brands::XEN);
}
{ "vmsrvc.exe", brands::VPC, 10 },
{ "vmusrvc.exe", brands::VPC, 11 },

{ "xenservice.exe", brands::XEN, 14 },
{ "xsvc_depriv.exe", brands::XEN, 15 },

if (runningProcesses.count("vm3dservice.exe") ||
runningProcesses.count("VGAuthService.exe") ||
runningProcesses.count("vmtoolsd.exe")) {
debug("VM_PROCESSES: Detected VMware process.");
return core::add(brands::VMWARE);
{ "vm3dservice.exe", brands::VMWARE, 15 },
{ "VGAuthService.exe", brands::VMWARE, 17 },
{ "vmtoolsd.exe", brands::VMWARE, 12 },

{ "vdagent.exe", brands::QEMU, 11 },
{ "vdservice.exe", brands::QEMU, 13 },
{ "qemuwmi.exe", brands::QEMU, 11 },
{ "looking-glass-host.exe", brands::QEMU, 22 },

{ "VDDSysTray.exe", brands::NULL_BRAND, 14 },
} };

for (auto vm_process : vm_processes_names) {
if (util::is_proc_running(vm_process.name, vm_process.len)) {
debug("VM_PROCESSES: Detected process ", vm_process.name);
res = true;
}
}

if (runningProcesses.count("vdagent.exe") ||
runningProcesses.count("vdservice.exe") ||
runningProcesses.count("qemuwmi.exe")) {
debug("VM_PROCESSES: Detected QEMU process.");
#elif (LINUX)
if (util::is_proc_running("qemu_ga", 7)) {
debug("VM_PROCESSES: Detected QEMU guest agent process.");
return core::add(brands::QEMU);
}

return false;
#endif
#endif
return res;
}


Expand Down Expand Up @@ -4331,27 +4297,6 @@ struct VM {
#endif
}


/**
* @brief Check for "qemu-ga" process
* @category Linux
* @implements VM::QEMU_GA
*/
[[nodiscard]] static bool qemu_ga() {
#if (!LINUX)
return false;
#else
constexpr const char* process = "qemu-ga";

if (util::is_proc_running(process)) {
return core::add(brands::QEMU);
}

return false;
#endif
}


/**
* @brief Check for official VPC method
* @category Windows, x86
Expand Down Expand Up @@ -11290,7 +11235,6 @@ struct VM {
case IOREG_GREP: return "IOREG_GREP";
case MAC_SIP: return "MAC_SIP";
case HKLM_REGISTRIES: return "HKLM_REGISTRIES";
case QEMU_GA: return "QEMU_GA";
case VPC_INVALID: return "VPC_INVALID";
case SIDT: return "SIDT";
case SGDT: return "SGDT";
Expand Down Expand Up @@ -11850,7 +11794,6 @@ std::pair<VM::enum_flags, VM::core::technique> VM::core::technique_list[] = {
std::make_pair(VM::IOREG_GREP, VM::core::technique(100, VM::ioreg_grep)),
std::make_pair(VM::MAC_SIP, VM::core::technique(40, VM::mac_sip)),
std::make_pair(VM::HKLM_REGISTRIES, VM::core::technique(25, VM::hklm_registries)),
std::make_pair(VM::QEMU_GA, VM::core::technique(10, VM::qemu_ga)),
std::make_pair(VM::VPC_INVALID, VM::core::technique(75, VM::vpc_invalid)),
std::make_pair(VM::SIDT, VM::core::technique(25, VM::sidt)),
std::make_pair(VM::SGDT, VM::core::technique(30, VM::sgdt)),
Expand Down
Loading