Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
kernelwernel committed Dec 6, 2023
2 parents 0363cb1 + 8534c6c commit f23f62d
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 18 deletions.
12 changes: 10 additions & 2 deletions docs/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ int main() {


# `VM::brand()`
This will essentially return the VM brand as a `std::string`. The possible brand string return values are:
This will essentially return the VM brand as a `std::string`. The brand string return values are:
- `VMware`
- `VirtualBox`
- `KVM`
Expand All @@ -60,6 +60,11 @@ This will essentially return the VM brand as a `std::string`. The possible brand
- `Wine`
- `Virtual Apple`
- `Virtual PC`
- `Anubis`
- `JoeBox`
- `Thread Expert`
- `CW Sandbox`

If none were detected, it will return `Unknown`. It's often not going to produce a satisfying result due to technical difficulties with accomplishing this, on top of being highly dependant on what mechanisms detected a VM. Don't rely on this function too much.

```cpp
Expand Down Expand Up @@ -129,7 +134,7 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
| `VM::SUNBELT` | Detect for Sunbelt technology | Windows | 10% | |
| `VM::WINE_CHECK` | Find for a Wine-specific file | Windows | 85% | |
| `VM::BOOT` | Analyse the OS uptime | Yes | 5% | |
| `VM::VM_FILES` | Find if any VM-specific files exists | Windows | 80% | |
| `VM::VM_FILES` | Find if any VM-specific files exists | Windows | 20% | |
| `VM::HWMODEL` | Check if the sysctl for the hwmodel does not contain the "Mac" string | MacOS | 75% | |
| `VM::DISK_SIZE` | Check if disk size is under or equal to 50GB | Linux | 60% | |
| `VM::VBOX_DEFAULT` | Check for default RAM and DISK sizes set by VirtualBox | Linux and Windows | 55% | Yes |
Expand All @@ -138,6 +143,9 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
| `VM::MEMORY` | Check if memory space is far too low for a physical machine | Windows | 35% | |
| `VM::VM_PROCESSES` | Check for any VM processes that are active | Windows | 30% | |
| `VM::LINUX_USER_HOST` | Check for default VM username and hostname for linux | Linux | 35% | |
| `VM::VBOX_WINDOW_CLASS` | Check for the window class for VirtualBox | 10% | |
| `VM::WINDOWS_NUMBER` | Check top-level default window level | 20% | |
| `VM::GAMARUE` | Check for Gamarue ransomeware technique which compares VM-specific Window product IDs | 40% | |

# Non-technique flags
| Flag | Description |
Expand Down
191 changes: 175 additions & 16 deletions src/vmaware.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
#endif
#if (CPP >= 17)
#include <bit>
#include <optional>
#endif
#ifdef __VMAWARE_DEBUG__
#include <iomanip>
Expand Down Expand Up @@ -213,7 +214,10 @@ struct VM {
static constexpr const char* VPC = "Virtual PC";
static constexpr const char* ANUBIS = "Anubis";
static constexpr const char* JOEBOX = "JoeBox";

static constexpr const char* THREADEXPERT = "Thread Expert";
static constexpr const char* CWSANDBOX = "CW Sandbox";
static constexpr const char* UNKNOWN = "Unknown";

// VM scoreboard table specifically for VM::brand()
#if (MSVC)
static std::map<const char*, int> scoreboard;
Expand Down Expand Up @@ -445,6 +449,7 @@ struct VM {

// memoize the value from VM::detect() in case it's ran again
static std::map<bool, std::pair<bool, const char*>> memo;
// ^ VM?

// cpuid check value
static bool cpuid_supported;
Expand Down Expand Up @@ -519,6 +524,9 @@ struct VM {
MEMORY = 1ULL << 35,
VM_PROCESSES = 1ULL << 36,
LINUX_USER_HOST = 1ULL << 37,
WINDOWS_NUMBER = 1ULL << 38,
VBOX_WINDOW_CLASS = 1ULL << 39,
GAMARUE = 1ULL << 40,

// settings
NO_MEMO = 1ULL << 63,
Expand Down Expand Up @@ -1707,7 +1715,7 @@ struct VM {

/**
* @brief checks for default usernames, often a sign of a VM
* @author: Some guy in a russian underground forum from a screenshot I saw, idk I don't speak russian ¯\_(ツ)_/¯
* @author: some guy in a russian underground forum from a screenshot i saw, idk who he is but ty ¯\_(ツ)_/¯
* @category Windows
*/
[[nodiscard]] static bool user_check() try {
Expand All @@ -1730,8 +1738,11 @@ struct VM {
debug("USER: ", "output = ", u);
#endif

if (u == "username") {
return add(THREADEXPERT);
}

return (
(u == "username") || // ThreadExpert
(u == "USER") || // Sandbox
(u == "user") || // Sandbox 2
(u == "currentuser") // Normal
Expand Down Expand Up @@ -2053,7 +2064,7 @@ struct VM {
L"C:\\windows\\System32\\Drivers\\VMToolsHook.dll",
L"C:\\windows\\System32\\Drivers\\vmGuestLib.dll",
L"C:\\windows\\System32\\Drivers\\vmhgfs.dll",
L"C:\\windows\\System32\\Drivers\\vmhgfs.dll", // Note: there's a typo in the original code

// VBox
L"C:\\windows\\System32\\Drivers\\VBoxMouse.sys",
L"C:\\windows\\System32\\Drivers\\VBoxGuest.sys",
Expand Down Expand Up @@ -2626,6 +2637,142 @@ struct VM {
}


/**
* @brief default vbox window class
* @category Windows
* @author Al-Khaser Project
*/
[[nodiscard]] static bool vbox_window_class() try {
if (disabled(VBOX_WINDOW_CLASS)) {
return false;
}

#if (!MSVC)
return false;
#else
HWND hClass = FindWindow(_T("VBoxTrayToolWndClass"), NULL);
HWND hWindow = FindWindow(NULL, _T("VBoxTrayToolWnd"));

if (hClass || hWindow) {
return add(VBOX);
}

return false;
#endif
} catch (...) {
#ifdef __VMAWARE_DEBUG__
debug("VBOX_WINDOW_CLASS: catched error, returned false");
#endif
return false;
}


/**
* @brief get top-level default window level
* @category Windows
*/
[[nodiscard]] static bool windows_number() try {
return false; // TODO: FIX THIS SHIT
/*
if (disabled(WINDOWS_NUMBER)) {
return false;
}
#if (!MSVC)
return false;
#else
// this definitely doesn't fucking work
auto enumProc = [](HWND, LPARAM lParam) -> bool
{
if (LPDWORD pCnt = reinterpret_cast<LPDWORD>(lParam))
*pCnt++;
return true;
};
DWORD winCnt = 0;
if (!EnumWindows(enumProc,LPARAM(&winCnt))) {
#ifdef __VMAWARE_DEBUG__
debug("WINDOWS_NUMBER: EnumWindows() failed");
#endif
return false;
}
return (winCnt < 10);
#endif
*/
} catch (...) {
#ifdef __VMAWARE_DEBUG__
debug("WINDOWS_NUMBER: catched error, returned false");
#endif
return false;
}


/**
* @brief Gamarue ransomware check
* @category Windows
*/
[[nodiscard]] static bool gamarue() try {
if (disabled(GAMARUE)) {
return false;
}

#if (!MSVC)
return false;
#else
HKEY hOpen;
char *szBuff;
int iBuffSize;
HANDLE hMod;
LONG nRes;

szBuff = (char*)calloc(512, sizeof(char));

hMod = GetModuleHandle("SbieDll.dll"); // Sandboxie
if (hMod != 0) {
free(szBuff);
return add(SANDBOXIE);
}

hMod = GetModuleHandle("dbghelp.dll"); // Thread Expert
if (hMod != 0) {
free(szBuff);
return add(THREADEXPERT);
}

nRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", 0L, KEY_QUERY_VALUE, &hOpen);
if (nRes == ERROR_SUCCESS) {
iBuffSize = sizeof(szBuff);
nRes = RegQueryValueEx(hOpen, "ProductId", NULL, NULL, (unsigned char*)szBuff, reinterpret_cast<LPDWORD>(&iBuffSize));
if (nRes == ERROR_SUCCESS) {
if (strcmp(szBuff, "55274-640-2673064-23950") == 0) { // joebox
free(szBuff);
return add(JOEBOX);
} else if (strcmp(szBuff, "76487-644-3177037-23510") == 0) {
free(szBuff);
return add(CWSANDBOX); // CW Sandbox
} else if (strcmp(szBuff, "76487-337-8429955-22614") == 0) { // anubis
free(szBuff);
return add(ANUBIS);
} else {
free(szBuff);
return false;
}
}
RegCloseKey(hOpen);
}
free(szBuff);
return false;
#endif
} catch (...) {
#ifdef __VMAWARE_DEBUG__
debug("GAMARUE: catched error, returned false");
#endif
return false;
}


// __LABEL (ignore this, it's just a label so I can easily teleport to this line on my IDE with CTRL+F)


Expand Down Expand Up @@ -2715,7 +2862,7 @@ struct VM {

// check if no VM was detected
if (memo[true].first == false) {
return "Unknown";
return UNKNOWN;
}

return (std::string(memo[true].second));
Expand Down Expand Up @@ -2753,6 +2900,7 @@ struct VM {
debug("cpuid: is supported? : ", VM::cpuid_supported);
#endif

// invoke every technique in the table and add points for techniques detecting a VM
for (auto it = table.cbegin(); it != table.cend(); ++it) {
const technique &pair = it->second;
if (pair.ptr()) { // equivalent to std::invoke, not used bc of C++11 compatibility
Expand All @@ -2765,34 +2913,31 @@ struct VM {

const char* current_brand = "";

#ifdef __VMAWARE_DEBUG__
for (const auto p : scoreboard) {
debug("scoreboard: ", (int)p.second, " : ", p.first);
}
#endif

// fetch the brand with the most points in the scoreboard
#if (CPP >= 20)
// get the highest score from the scoreboard
auto it = std::ranges::max_element(scoreboard, {},
[](const auto &pair) {
return pair.second;
}
);

// find potential VM brand
if (it != scoreboard.end()) {
if (
// if all of the scores are 0
std::none_of(scoreboard.cbegin(), scoreboard.cend(),
[](const auto &pair) {
return pair.second;
}
)
) {
current_brand = "Unknown";
current_brand = UNKNOWN;
} else {
current_brand = it->first;
}
} else {
current_brand = "Unknown";
current_brand = UNKNOWN;
}
#else
#if (MSVC)
Expand All @@ -2809,7 +2954,13 @@ struct VM {
}

if (max == 0) {
current_brand = "Unknown";
current_brand = UNKNOWN;
}
#endif

#ifdef __VMAWARE_DEBUG__
for (const auto p : scoreboard) {
debug("scoreboard: ", (int)p.second, " : ", p.first);
}
#endif

Expand Down Expand Up @@ -2851,7 +3002,12 @@ struct VM {
{ VM::VAPPLE, 0 },
{ VM::VPC, 0 },
{ VM::ANUBIS, 0 },
{ VM::JOEBOX, 0 }
{ VM::JOEBOX, 0 },
{ VM::VPC, 0 },
{ VM::ANUBIS, 0 },
{ VM::JOEBOX, 0 },
{ VM::THREADEXPERT, 0 },
{ VM::CWSANDBOX, 0 }
};


Expand Down Expand Up @@ -2921,7 +3077,10 @@ const std::map<VM::u64, VM::technique> VM::table = {
{ VM::HOSTNAME, { 25, VM::hostname_match }},
{ VM::MEMORY, { 35, VM::low_memory_space }},
{ VM::VM_PROCESSES, { 30, VM::vm_processes }},
{ VM::LINUX_USER_HOST, { 35, VM::linux_user_host }}
{ VM::LINUX_USER_HOST, { 35, VM::linux_user_host }},
{ VM::VBOX_WINDOW_CLASS, { 10, VM::vbox_window_class }},
{ VM::WINDOWS_NUMBER, { 20, VM::windows_number }},
{ VM::GAMARUE, { 40, VM::gamarue }}

// { VM::, { , }}
// ^ line template for personal use
Expand Down

0 comments on commit f23f62d

Please sign in to comment.