Skip to content

Commit

Permalink
added windows support for sys_result and vmid improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
kernelwernel committed Dec 6, 2023
1 parent 3353638 commit 70fbcab
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 38 deletions.
1 change: 1 addition & 0 deletions docs/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
| `VM::VBOX_WINDOW_CLASS` | Check for the window class for VirtualBox | Windows | 10% | |
| `VM::WINDOWS_NUMBER` | Check top-level default window level | Windows | 20% | |
| `VM::GAMARUE` | Check for Gamarue ransomeware technique which compares VM-specific Window product IDs | Windows | 40% | |
| `VM::VMID_0X4` | Check if the CPU manufacturer ID matches that of a VM brand with leaf 0x40000000 | Yes | 100% | |

# Non-technique flags
| Flag | Description |
Expand Down
165 changes: 127 additions & 38 deletions src/vmaware.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,28 +143,92 @@ struct VM {
};

// Basically std::system but it runs in the background with no output
[[nodiscard]] static std::unique_ptr<std::string> sys_result(const char *cmd) {
[[nodiscard]] static std::unique_ptr<std::string> sys_result(const char *cmd) try {
#if (CPP < 14)
std::unique_ptr<std::string> tmp(nullptr);
return tmp;
#else
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);
#if (LINUX)
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose);

if (!pipe) {
return nullptr;
}
if (!pipe) {
return nullptr;
}

std::string result{};
std::array<char, 128> buffer{};
std::string result{};
std::array<char, 128> buffer{};

while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
result += buffer.data();
}
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
result += buffer.data();
}

result.pop_back();

return std::make_unique<std::string>(result);
#elif (MSVC)
// Set up the structures for creating the process
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);

// Create a pipe to capture the command output
HANDLE hReadPipe, hWritePipe;
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;

if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) {
#if __VMAWARE_DEBUG__
debug("sys_result: ", "error creating pipe");
#endif
return nullptr;
}

// Set up the startup information with the write end of the pipe as the standard output
si.hStdError = hWritePipe;
si.hStdOutput = hWritePipe;
si.dwFlags |= STARTF_USESTDHANDLES;

// Create the process
if (!CreateProcess(NULL, const_cast<char*>(command), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
#if __VMAWARE_DEBUG__
debug("sys_result: ", "error creating process");
#endif
CloseHandle(hReadPipe);
CloseHandle(hWritePipe);
return nullptr;
}

// Close the write end of the pipe as it's not needed in this process
CloseHandle(hWritePipe);

result.pop_back();
// Read the output from the pipe
char buffer[4096];
DWORD bytesRead;
std::string result;

while (ReadFile(hReadPipe, buffer, sizeof(buffer), &bytesRead, NULL) && bytesRead > 0) {
result.append(buffer, bytesRead);
}

return std::make_unique<std::string>(result);
// Close handles
CloseHandle(hReadPipe);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

// Return the result as a unique_ptr<string>
return std::make_unique<std::string>(result);
#endif
#endif
} catch (...) {
#if __VMAWARE_DEBUG__
debug("sys_result: ", "catched error, returning nullptr");
#endif
std::unique_ptr<std::string> tmp(nullptr);
return tmp;
}
#endif

Expand Down Expand Up @@ -525,6 +589,7 @@ struct VM {
VBOX_WINDOW_CLASS = 1ULL << 38,
GAMARUE = 1ULL << 39,
WINDOWS_NUMBER = 1ULL << 40,
VMID_0X4 = 1ULL << 41,

// settings
NO_MEMO = 1ULL << 63,
Expand All @@ -535,24 +600,7 @@ struct VM {
ALL = ~(NO_MEMO & std::numeric_limits<u64>::max());
#endif

private:
static constexpr u64 DEFAULT = (~(CURSOR) & ALL);

/**
* @brief Check CPUID output of manufacturer ID for known VMs/hypervisors
* @category x86
*/
[[nodiscard]] static bool vmid() try {
#if (!x86)
return false;
#else
if (!cpuid_supported || disabled(VMID)) {
#ifdef __VMAWARE_DEBUG__
debug("VMID: precondition return called");
#endif
return false;
}

[[nodiscard]] static bool vmid_template(const u32 leaf, const char* technique_name) {
#if (CPP >= 17)
constexpr sv
#else
Expand Down Expand Up @@ -596,16 +644,12 @@ struct VM {
};

std::string brand = "";

u32 sig_reg[3] = {0};

if (!cpuid_thingy(0, sig_reg, 1)) {
if (!cpuid_thingy(leaf, sig_reg, 1)) {
return false;
}

u32 features;
cpuid_thingy(1, &features, 2, 3);

auto strconvert = [](u64 n) -> std::string {
const std::string &str(reinterpret_cast<char*>(&n));
return str;
Expand All @@ -619,7 +663,7 @@ struct VM {
brand = ss.str();

#ifdef __VMAWARE_DEBUG__
debug("VMID: ", brand);
debug(technique_name, brand);
#endif

const bool found = (std::find(std::begin(IDs), std::end(IDs), brand) != std::end(IDs));
Expand All @@ -641,6 +685,27 @@ struct VM {
}

return false;
}

private:
static constexpr u64 DEFAULT = (~(CURSOR) & ALL);

/**
* @brief Check CPUID output of manufacturer ID for known VMs/hypervisors
* @category x86
*/
[[nodiscard]] static bool vmid() try {
if (!cpuid_supported || disabled(VMID)) {
#ifdef __VMAWARE_DEBUG__
debug("VMID: ", "precondition return called");
#endif
return false;
}

#if (!x86)
return false;
#else
return vmid_template(0, "VMID: ");
#endif
} catch (...) {
#ifdef __VMAWARE_DEBUG__
Expand All @@ -650,6 +715,30 @@ struct VM {
}


/**
* @brief Check CPUID output of manufacturer ID for known VMs/hypervisors with leaf value 0x40000000
* @category x86
*/
[[nodiscard]] static bool vmid_0x4() try {
if (!cpuid_supported || disabled(VMID_0X4)) {
#ifdef __VMAWARE_DEBUG__
debug("VMID_0X4: ", "precondition return called");
#endif
return false;
}

#if (!x86)
return false;
#else
return vmid_template(0x40000000, "VMID_0x4: ");
#endif
} catch (...) {
#ifdef __VMAWARE_DEBUG__
debug("VMID_0x4: catched error, returned false");
#endif
return false;
}

/**
* @brief Check if CPU brand is a VM brand
* @category x86
Expand Down Expand Up @@ -2767,7 +2856,6 @@ struct VM {
#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 @@ -3070,7 +3158,8 @@ const std::map<VM::u64, VM::technique> VM::table = {
{ VM::LINUX_USER_HOST, { 35, VM::linux_user_host }},
{ VM::VBOX_WINDOW_CLASS, { 10, VM::vbox_window_class }},
{ VM::GAMARUE, { 40, VM::gamarue }},
{ VM::WINDOWS_NUMBER, { 20, VM::windows_number }}
{ VM::WINDOWS_NUMBER, { 20, VM::windows_number }},
{ VM::VMID_0X4, { 90, VM::vmid_0x4 }}

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

0 comments on commit 70fbcab

Please sign in to comment.