From e61d37c4d3b5058ab086fe29811fb2dddfd704ab Mon Sep 17 00:00:00 2001 From: kernel <77142078+kernelwernel@users.noreply.github.com> Date: Wed, 16 Oct 2024 00:08:51 +0100 Subject: [PATCH] slight changes for ci/cd --- docs/documentation.md | 17 ++++--- src/cli.cpp | 26 ++++++++++- src/vmaware.hpp | 100 +++++++++++++++++++++++------------------- 3 files changed, 92 insertions(+), 51 deletions(-) diff --git a/docs/documentation.md b/docs/documentation.md index 85353f4..32043a1 100644 --- a/docs/documentation.md +++ b/docs/documentation.md @@ -48,16 +48,16 @@ int main() { /** * There are roughly 1/3 of all techniques that are considered to be "spoofable", * meaning that anybody can potentially cause a false positive by exploiting the - * fact that the "spoofable" techniques checks for things that anybody can modify - * (file, registry, directories, etc...). This category of techniques are disabled + * fact that the spoofable techniques checks for things that anybody can modify + * (file data, registry, directories, etc...). This category of techniques are disabled * by default, but they can be enabled with the VM::SPOOFABLE flag. */ bool is_vm4 = VM::detect(VM::SPOOFABLE); /** - * All checks are performed including SPOOFABLE techniques - * and the cursor check, which waits 5 seconds for any human + * All checks are performed including spoofable techniques + * and a few techniques that are disabled by default, which waits 5 seconds for any human * mouse interaction to detect automated virtual environments. * If you're fine with having a 5 second delay, add VM::ALL */ @@ -123,9 +123,9 @@ int main() { if (percent == 100) { std::cout << "Definitely a VM!\n"; } else if (percent == 0) { - std::cout << "Definitely NOT a VM"; + std::cout << "Definitely NOT a VM\n"; } else { - std::cout << "Unsure if it's a VM"; + std::cout << "Unsure if it's a VM\n"; } // converted to std::uint32_t for console character encoding reasons @@ -343,6 +343,11 @@ This will return the "conclusion" message of what the overall result is as a `st
+## `VM::detected_count()` +This will fetch the number of techniques that have been detected as a `std::uint8_t`. Can't get any more simpler than that ¯\_(ツ)_/¯ + +
+ # vmaware struct If you prefer having an object to store all the relevant information about the program's environment instead of calling static member functions, you can use the `VM::vmaware` struct: diff --git a/src/cli.cpp b/src/cli.cpp index 1f756a5..49f53cf 100644 --- a/src/cli.cpp +++ b/src/cli.cpp @@ -26,7 +26,30 @@ #include #include #include +#include +#include +void checkXsetbvVmException() { + UINT64 xcr0 = _xgetbv(0); + + __try { + _xsetbv(0, xcr0 & ~1); + + std::cout << "No exception occurred. Likely running on bare metal.\n"; + + } + __except (EXCEPTION_EXECUTE_HANDLER) { + std::cout << "Exception caught! VM likely detected (GP fault triggered).\n"; + } +} + +int main() { + checkXsetbvVmException(); + + return 0; +} + +/* #if (defined(__GNUC__) || defined(__linux__)) #include #define LINUX 1 @@ -755,4 +778,5 @@ int main(int argc, char* argv[]) { // at this point, it's assumed that the user's intention is for the general summary to be ran general(); return 0; -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/src/vmaware.hpp b/src/vmaware.hpp index 7401967..856318f 100644 --- a/src/vmaware.hpp +++ b/src/vmaware.hpp @@ -570,6 +570,8 @@ struct VM { static constexpr const char* WSL = "WSL"; static constexpr const char* OPENVZ = "OpenVZ"; static constexpr const char* ANYRUN = "ANY.RUN"; + static constexpr const char* NULL_BRAND = ""; + static flagset global_flags; // for certain techniques where the flags MUST be accessible @@ -1150,6 +1152,7 @@ struct VM { static void store(const hyperx_state p_state) { state = p_state; + cached = true; } static bool is_cached() { @@ -1930,7 +1933,7 @@ struct VM { * the Hyper-X mechanism comes into play to distinguish between these two. * @author idea by Requiem (https://github.com/NotRequiem) * @returns boolean, true = Hyper-V artifact, false = Real Hyper-V VM - * @link graph to explain how this works: https://github.com/kernelwernel/VMAware/blob/main/assets/Hyper-X_version_3.png + * @link graph to explain how this works: https://github.com/kernelwernel/VMAware/blob/main/assets/hyper-x/v4/Hyper-X_version_4.drawio.png */ [[nodiscard]] static bool hyper_x() { #if (!MSVC) @@ -3956,40 +3959,35 @@ struct VM { /* GPL */ #if (!MSVC) /* GPL */ return false; /* GPL */ #else -/* GPL */ HMODULE hDll; -/* GPL */ -/* GPL */ constexpr std::array szDlls = {{ -/* GPL */ "avghookx.dll", // AVG -/* GPL */ "avghooka.dll", // AVG -/* GPL */ "snxhk.dll", // Avast -/* GPL */ "sbiedll.dll", // Sandboxie -/* GPL */ "dbghelp.dll", // WindBG -/* GPL */ "api_log.dll", // iDefense Lab -/* GPL */ "dir_watch.dll", // iDefense Lab -/* GPL */ "pstorec.dll", // SunBelt CWSandbox -/* GPL */ "vmcheck.dll", // Virtual PC -/* GPL */ "wpespy.dll", // WPE Pro -/* GPL */ "cmdvrt64.dll", // Comodo Container -/* GPL */ "cmdvrt32.dll" // Comodo Container -/* GPL */ }}; -/* GPL */ -/* GPL */ for (const auto& key : szDlls) { -/* GPL */ const char* dll = key; -/* GPL */ -/* GPL */ hDll = GetModuleHandleA(dll); // Use GetModuleHandleA for ANSI strings -/* GPL */ -/* GPL */ if (hDll != NULL && dll != NULL) { -/* GPL */ if (strcmp(dll, "sbiedll.dll") == 0) { return core::add(SANDBOXIE); } -/* GPL */ if (strcmp(dll, "pstorec.dll") == 0) { return core::add(CWSANDBOX); } -/* GPL */ if (strcmp(dll, "vmcheck.dll") == 0) { return core::add(VPC); } -/* GPL */ if (strcmp(dll, "cmdvrt32.dll") == 0) { return core::add(COMODO); } -/* GPL */ if (strcmp(dll, "cmdvrt64.dll") == 0) { return core::add(COMODO); } -/* GPL */ -/* GPL */ return true; -/* GPL */ } +/* GPL */ std::unordered_map dllMap = { +/* GPL */ { "sbiedll.dll", SANDBOXIE }, // Sandboxie +/* GPL */ { "pstorec.dll", CWSANDBOX }, // CWSandbox +/* GPL */ { "vmcheck.dll", VPC }, // VirtualPC +/* GPL */ { "cmdvrt32.dll", COMODO }, // Comodo +/* GPL */ { "cmdvrt64.dll", COMODO }, // Comodo +/* GPL */ { "dbghelp.dll", NULL_BRAND }, // WindBG +/* GPL */ { "avghookx.dll", NULL_BRAND }, // AVG +/* GPL */ { "avghooka.dll", NULL_BRAND }, // AVG +/* GPL */ { "snxhk.dll", NULL_BRAND }, // Avast +/* GPL */ { "api_log.dll", NULL_BRAND }, // iDefense Lab +/* GPL */ { "dir_watch.dll", NULL_BRAND }, // iDefense Lab +/* GPL */ { "pstorec.dll", NULL_BRAND }, // SunBelt CWSandbox +/* GPL */ { "vmcheck.dll", NULL_BRAND }, // Virtual PC +/* GPL */ { "wpespy.dll", NULL_BRAND } // WPE Pro /* GPL */ } -/* GPL */ -/* GPL */ return false; +/* GPL */ +/* GPL */ for (const auto& key : dllMap) { +/* GPL */ hDll = GetModuleHandleA(key); +/* GPL */ +/* GPL */ if (hDll != NULL) { +/* GPL */ auto it = dllMap.find(key); +/* GPL */ if (it != dllMap.end()) { +/* GPL */ return core::add(it->second); +/* GPL */ } +/* GPL */ } +/* GPL */ } +/* GPL */ +/* GPL */ return false; /* GPL */ #endif /* GPL */ } /* GPL */ catch (...) { @@ -5436,22 +5434,22 @@ struct VM { u32 idt_entry = 0; #if (MSVC) -#if (x86_32) +# if (x86_32) _asm sidt idtr -#elif (x86) -#pragma pack(1) +# elif (x86) +# pragma pack(1) struct IDTR { u16 limit; u64 base; }; -#pragma pack() +# pragma pack() IDTR idtrStruct; __sidt(&idtrStruct); std::memcpy(idtr, &idtrStruct, sizeof(IDTR)); -#else +# else return false; -#endif +# endif idt_entry = *reinterpret_cast(&idtr[2]); #elif (LINUX) @@ -9532,7 +9530,9 @@ struct VM { * @return bool * @link https://github.com/kernelwernel/VMAware/blob/main/docs/documentation.md#vmcheck */ - [[nodiscard]] static bool check(const enum_flags flag_bit + [[nodiscard]] static bool check( + const enum_flags flag_bit, + const enum_flags memo_arg = NULL_ARG // clang doesn't support std::source_location for some reason #if (CPP >= 20 && !CLANG) , const std::source_location& loc = std::source_location::current() @@ -9563,12 +9563,21 @@ struct VM { throw_error("Flag argument must be a technique flag and not a settings flag"); } + if ( + (memo_arg != NO_MEMO) && + (memo_arg != NULL_ARG) + ) { + throw_error("Flag argument for memoization must be either VM::NO_MEMO or left empty"); + } + + const bool is_memoized = (memo_arg != NO_MEMO); + #if (CPP >= 23) [[assume(flag_bit < technique_end)]]; #endif // if the technique is already cached, return the cached value instead - if (memo::is_cached(flag_bit)) { + if (memo::is_cached(flag_bit) && is_memoized) { const memo::data_t data = memo::cache_fetch(flag_bit); return data.result; } @@ -9592,7 +9601,9 @@ struct VM { #endif // store the technique result in the cache table - memo::cache_store(flag_bit, result, pair.points); + if (is_memoized) { + memo::cache_store(flag_bit, result, pair.points); + } return result; } @@ -10423,7 +10434,8 @@ std::map VM::core::brand_scoreboard{ { VM::PODMAN, 0 }, { VM::WSL, 0 }, { VM::OPENVZ, 0 }, - { VM::ANYRUN, 0 } + { VM::ANYRUN, 0 }, + { VM::NULL_BRAND, 0 } };