diff --git a/docs/documentation.md b/docs/documentation.md
index 8e495dc..e986048 100644
--- a/docs/documentation.md
+++ b/docs/documentation.md
@@ -213,6 +213,8 @@ VMAware provides a convenient way to not only check for VMs, but also have the f
| `VM::HYPERV_WMI` | Check for Hyper-V wmi output | Windows | 80% | |
| `VM::HYPERV_REG` | Check for Hyper-V strings in registry | Windows | 80% | |
| `VM::BIOS_SERIAL` | Check if BIOS serial number is null | Windows | 60% | |
+| `VM::VBOX_FOLDERS` | Check for VirtualBox-specific string for shared folder ID | Windows | 45% | |
+| `VM::VBOX_MSSMBIOS` | Check VirtualBox MSSMBIOS registry for VM-specific strings | Windows | 75% | |
diff --git a/src/cli.cpp b/src/cli.cpp
index 7e02f84..b50b402 100644
--- a/src/cli.cpp
+++ b/src/cli.cpp
@@ -116,6 +116,8 @@ int main(int argc, char* argv[]) {
checker(VM::BIOS_SERIAL, "BIOS serial number");
checker(VM::HYPERV_REG, "Hyper-V registry");
checker(VM::HYPERV_WMI, "Hyper-V WMI output");
+ checker(VM::VBOX_FOLDERS, "VirtualBox shared folders");
+ checker(VM::VBOX_MSSMBIOS, "VirtualBox MSSMBIOS");
std::printf("\n");
std::cout << "VM brand: " << (std::string(VM::brand()) == "Unknown" ? red : green) << VM::brand() << ansi_exit << "\n";
diff --git a/src/vmaware.hpp b/src/vmaware.hpp
index c1ebc00..e338710 100644
--- a/src/vmaware.hpp
+++ b/src/vmaware.hpp
@@ -868,6 +868,7 @@ struct VM {
HYPERV_REG = 1ULL << 50,
BIOS_SERIAL = 1ULL << 51,
VBOX_FOLDERS = 1ULL << 52,
+ VBOX_MSSMBIOS = 1ULL << 53,
// __UNIQUE_LABEL, ADD YOUR UNIQUE FUNCTION FLAG VALUE ABOVE HERE
@@ -3895,6 +3896,115 @@ struct VM {
}
+ /**
+ * @brief Check VirtualBox MSSMBIOS registry for VM-specific strings
+ * @category Windows
+ * @note slightly modified from original code
+ * @author @waleedassar
+ * @link https://pastebin.com/fPY4MiYq
+ */
+ [[nodiscard]] static bool vbox_mssmbios() try {
+ if (disabled(VBOX_MSSMBIOS)) {
+ return false;
+ }
+
+ #if (!MSVC)
+ return false;
+ #else
+ HKEY hk = 0;
+ int ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\mssmbios\\data", 0, KEY_ALL_ACCESS, &hk);
+ if (ret != ERROR_SUCCESS) {
+ return false;
+ }
+
+ bool is_vm = false;
+ unsigned long type = 0;
+ unsigned long length = 0;
+ ret = RegQueryValueEx(hk, "SMBiosData", 0, &type, 0, &length);
+
+ if (ret != ERROR_SUCCESS) {
+ RegCloseKey(hk);
+ return false;
+ }
+
+ if (length == 0) {
+ RegCloseKey(hk);
+ return false;
+ }
+
+ char* p = static_cast(LocalAlloc(LMEM_ZEROINIT, length));
+
+ if (p == nullptr) {
+ RegCloseKey(hk);
+ return false;
+ }
+
+ ret = RegQueryValueEx(hk, "SMBiosData", 0, &type, (unsigned char*)p, &length);
+
+ if (ret != ERROR_SUCCESS) {
+ LocalFree(p);
+ RegCloseKey(hk);
+ return false;
+ }
+
+ auto ScanDataForString = [](unsigned char* data, unsigned long data_length, unsigned char* string2) -> unsigned char* {
+ std::size_t string_length = strlen(reinterpret_cast(string2));
+
+ for (std::size_t i = 0; i <= (data_length-string_length); i++) {
+ if (strncmp(reinterpret_cast(&data[i]), reinterpret_cast(string2), string_length) == 0) {
+ return &data[i];
+ }
+ }
+ return 0;
+ };
+
+ auto AllToUpper = [](char* str, std::size_t len) -> void {
+ std::transform(str, str + len, str, [](unsigned char c) -> char {
+ return static_cast(std::toupper(c));
+ });
+ };
+
+ AllToUpper(p, length);
+
+ // cleaner and better shortcut than typing reinterpret_cast a million times
+ auto cast = [](char* p) -> unsigned char* {
+ return reinterpret_cast(p);
+ };
+
+ unsigned char* x1 = ScanDataForString(cast(p), length, (unsigned char*)("INNOTEK GMBH"));
+ unsigned char* x2 = ScanDataForString(cast(p), length, (unsigned char*)("VIRTUALBOX"));
+ unsigned char* x3 = ScanDataForString(cast(p), length, (unsigned char*)("SUN MICROSYSTEMS"));
+ unsigned char* x4 = ScanDataForString(cast(p), length, (unsigned char*)("VIRTUAL MACHINE"));
+ unsigned char* x5 = ScanDataForString(cast(p), length, (unsigned char*)("VBOXVER"));
+
+ if (x1 || x2 || x3 || x4 || x5) {
+ is_vm = true;
+ #ifdef __VMAWARE_DEBUG__
+ if (x1) { debug("VBOX_MSSMBIOS: x1 = ", x1); }
+ if (x2) { debug("VBOX_MSSMBIOS: x2 = ", x2); }
+ if (x3) { debug("VBOX_MSSMBIOS: x3 = ", x3); }
+ if (x4) { debug("VBOX_MSSMBIOS: x4 = ", x4); }
+ if (x5) { debug("VBOX_MSSMBIOS: x5 = ", x5); }
+ #endif
+ }
+
+ LocalFree(p);
+ RegCloseKey(hk);
+
+ if (is_vm) {
+ return add(VBOX);
+ }
+
+ return false;
+ #endif
+ } catch (...) {
+ #ifdef __VMAWARE_DEBUG__
+ debug("VBOX_MSSMBIOS: ", "catched error, returned false");
+ #endif
+ return false;
+ }
+
+
// __TECHNIQUE_LABEL, label for adding techniques above this point
@@ -4290,6 +4400,7 @@ const std::map VM::table = {
{ VM::HYPERV_REG, { 80, VM::hyperv_registry }},
{ VM::BIOS_SERIAL, { 60, VM::bios_serial }},
{ VM::VBOX_FOLDERS, { 45, VM::vbox_shared_folders }},
+ { VM::VBOX_MSSMBIOS, { 75, VM::vbox_mssmbios }}
// __TABLE_LABEL, add your technique above
// { VM::YOUR_FUNCTION, { POINTS, FUNCTION POINTER }}