Skip to content

Commit b9da209

Browse files
authored
Merge pull request #712 from NotRequiem/main
Windows CLI fixes and other improvements
2 parents a2e12df + 9bdffe6 commit b9da209

5 files changed

Lines changed: 393 additions & 644 deletions

File tree

src/cli/globals.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ enum arg_enum : u8 {
4141
DETECTED_ONLY,
4242
JSON,
4343
RICH,
44+
EXPERIMENTAL,
4445
NULL_ARG,
4546
};
4647

@@ -59,6 +60,6 @@ extern std::string tag_no_perms;
5960
extern std::string tag_notes;
6061

6162
// increment this each time a new argument is introduced
62-
constexpr std::size_t arg_count = 34;
63+
constexpr std::size_t arg_count = 35;
6364

6465
using arg_table = std::array<std::pair<const char*, arg_enum>, arg_count>;

src/cli/main.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@
3535
#include "wagner_fischer.hpp"
3636

3737
#if (CLI_WINDOWS)
38-
#include "windows_tui.hpp"
39-
#include <windows.h>
40-
#include <shellapi.h>
38+
#include "windows_tui.hpp"
39+
#include <windows.h>
40+
#include <shellapi.h>
4141
#endif
4242

4343
constexpr const char* ver = "2.7.0";
@@ -68,6 +68,7 @@ R"(Usage:
6868
--high-threshold a higher threshold bar for a VM detection will be applied (2x higher)
6969
--no-ansi removes color and ansi escape codes from the output
7070
--dynamic allow the conclusion message to be dynamic (8 possibilities instead of only 2)
71+
--experimental disable experimental techniques
7172
--verbose add more information to the output
7273
--enums display the technique enum name used by the lib
7374
--detected-only only display the techniques that were detected
@@ -178,7 +179,17 @@ int main(int argc, char* argv[]) {
178179
}
179180
}
180181

181-
if (rich_requested) {
182+
bool already_spawned = false;
183+
char env_buf[16];
184+
if (GetEnvironmentVariableA("VMAWARE_SPAWNED", env_buf, sizeof(env_buf)) > 0) {
185+
if (std::strcmp(env_buf, "1") == 0) {
186+
already_spawned = true;
187+
}
188+
}
189+
190+
if (rich_requested && !already_spawned) {
191+
SetEnvironmentVariableA("VMAWARE_SPAWNED", "1");
192+
182193
char exePath[MAX_PATH];
183194
GetModuleFileNameA(NULL, exePath, MAX_PATH);
184195

@@ -187,9 +198,6 @@ int main(int argc, char* argv[]) {
187198

188199
std::string args = "\"" + std::string(exePath) + "\"";
189200
for (int i = 1; i < argc; ++i) {
190-
if (std::strcmp(argv[i], "--rich") == 0) {
191-
continue;
192-
}
193201
args += " \"";
194202
args += argv[i];
195203
args += "\"";
@@ -249,6 +257,7 @@ int main(int argc, char* argv[]) {
249257
{ "--disable-notes", NOTES },
250258
{ "--high-threshold", HIGH_THRESHOLD },
251259
{ "--dynamic", DYNAMIC },
260+
{ "--experimental", EXPERIMENTAL },
252261
{ "--verbose", VERBOSE },
253262
{ "--enums", ENUMS },
254263
{ "--no-ansi", NO_ANSI },

src/cli/output.cpp

Lines changed: 17 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "output.hpp"
33
#include "windows_tui.hpp"
44
#include "globals.hpp"
5+
#include "sha256.hpp"
56

67
#include <chrono>
78
#include <iomanip>
@@ -218,60 +219,6 @@ const char* get_vm_description(const std::string& vm_brand) {
218219
return "";
219220
}
220221

221-
#if (CLI_WINDOWS)
222-
// Run a single technique in a worker thread and wait up to TECHNIQUE_TIMEOUT_MS.
223-
// Returns {result, timed_out}. On timeout the flag is pushed to
224-
// VM::disabled_techniques so the VM::vmaware constructor won't re-run it.
225-
static constexpr DWORD TECHNIQUE_TIMEOUT_MS = 3000;
226-
227-
struct win_run_result { bool result; bool timed_out; };
228-
229-
static win_run_result win_run_technique(const VM::enum_flags flag) {
230-
struct runner_t {
231-
VM::enum_flags flag;
232-
bool result = false;
233-
static DWORD WINAPI run(LPVOID lp) noexcept {
234-
auto* self = static_cast<runner_t*>(lp);
235-
self->result = VM::check(self->flag);
236-
return 0;
237-
}
238-
};
239-
240-
runner_t runner {
241-
flag,
242-
false
243-
};
244-
245-
HANDLE h = CreateThread(nullptr, 0, runner_t::run, &runner, 0, nullptr);
246-
if (!h) {
247-
return {
248-
VM::check(flag),
249-
false
250-
};
251-
}
252-
253-
if (WaitForSingleObject(h, TECHNIQUE_TIMEOUT_MS) == WAIT_TIMEOUT) {
254-
TerminateThread(h, 0);
255-
CloseHandle(h);
256-
VM::disabled_techniques.push_back(flag);
257-
std::cerr << "[TIMEOUT] VM::" << VM::flag_to_string(flag)
258-
<< " did not finish within " << (TECHNIQUE_TIMEOUT_MS / 1000)
259-
<< "s, skipping\n" << std::flush;
260-
261-
return {
262-
false,
263-
true
264-
};
265-
}
266-
267-
CloseHandle(h);
268-
return {
269-
runner.result,
270-
false
271-
};
272-
}
273-
#endif
274-
275222
static void checker(const VM::enum_flags flag, const char* message) {
276223
std::string enum_name;
277224

@@ -298,13 +245,7 @@ static void checker(const VM::enum_flags flag, const char* message) {
298245

299246
auto start_time = std::chrono::high_resolution_clock::now();
300247

301-
#if (CLI_WINDOWS)
302-
const win_run_result wres = win_run_technique(flag);
303-
if (wres.timed_out) { return; }
304-
const bool result = wres.result;
305-
#else
306248
const bool result = VM::check(flag);
307-
#endif
308249

309250
auto end_time = std::chrono::high_resolution_clock::now();
310251

@@ -380,19 +321,6 @@ bool parse_disable_token(const char* token) {
380321
}
381322

382323
void generate_json(const char* output) {
383-
#if (CLI_WINDOWS)
384-
// Warm the memo cache with per-technique timeouts before constructing
385-
// VM::vmaware, so that any technique that hangs (e.g. CPU_HEURISTIC on
386-
// Azure Hyper-V) is aborted and disabled rather than blocking indefinitely.
387-
for (u8 i = VM::technique_begin; i < static_cast<u8>(VM::technique_end); ++i) {
388-
const VM::enum_flags flag = static_cast<VM::enum_flags>(i);
389-
if (is_disabled(flag) || is_unsupported(flag)) {
390-
continue;
391-
}
392-
win_run_technique(flag);
393-
}
394-
#endif
395-
396324
const VM::vmaware vm(VM::MULTIPLE);
397325

398326
std::vector<std::string> json;
@@ -617,7 +545,6 @@ void general(bool high_threshold, bool all, bool dynamic, const char* output_fil
617545
checker(VM::CUCKOO_PIPE, "Cuckoo pipe");
618546
checker(VM::AZURE, "Azure Hyper-V");
619547
checker(VM::DISPLAY, "display");
620-
checker(VM::DEVICE_STRING, "bogus device string");
621548
checker(VM::BLUESTACKS_FOLDERS, "BlueStacks folders");
622549
checker(VM::CPUID_SIGNATURE, "CPUID signatures");
623550
checker(VM::KGT_SIGNATURE, "Intel KGT signature");
@@ -653,7 +580,6 @@ void general(bool high_threshold, bool all, bool dynamic, const char* output_fil
653580
checker(VM::MAC_SYS, "system profiler");
654581
checker(VM::KERNEL_OBJECTS, "kernel objects");
655582
checker(VM::NVRAM, "NVRAM");
656-
checker(VM::EDID, "EDID");
657583
checker(VM::CLOCK, "system timers");
658584
checker(VM::MSR, "model specific registers");
659585
checker(VM::CPU_HEURISTIC, "instruction capabilities");
@@ -671,6 +597,10 @@ void general(bool high_threshold, bool all, bool dynamic, const char* output_fil
671597
const VM::vmaware vm(VM::MULTIPLE, high_thresh_arg, all_arg, dynamic_arg);
672598
std::vector<std::string> summary;
673599

600+
#if defined(__VMAWARE_DEBUG__)
601+
std::cout << grey << "SHA-256: " << white << compute_self_sha256() << ansi_exit << "\n";
602+
#endif
603+
674604
const std::string brand = vm.brand;
675605
const bool is_red = ((brand == VM::brands::NULL_BRAND) || (brand == VM::brands::HYPERV_ROOT));
676606
summary.push_back(bold + "\nVM brand: " + ansi_exit + (is_red ? red : green) + brand + ansi_exit);
@@ -844,13 +774,25 @@ void general(bool high_threshold, bool all, bool dynamic, const char* output_fil
844774
std::cout << l << "\n";
845775
}
846776
}
777+
778+
#if defined(__VMAWARE_DEBUG__)
779+
std::cout << grey << "SHA-256: " << white << compute_self_sha256() << ansi_exit << "\n";
780+
#endif
781+
847782
#else
783+
848784
for (const auto& line : summary) {
849785
std::cout << line << "\n";
850786
}
851787

788+
#if defined(__VMAWARE_DEBUG__)
789+
std::cout << grey << "SHA-256: " << white << compute_self_sha256() << ansi_exit << "\n";
790+
#endif
791+
852792
if (original_cout_buf) {
853793
std::cout.rdbuf(original_cout_buf);
854794
}
795+
855796
#endif
797+
856798
}

0 commit comments

Comments
 (0)