From 9c29f266479b83d729909475e69bfdf3411938aa Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 17 Aug 2025 07:26:11 +0200 Subject: [PATCH 1/4] Small fixes --- src/analyzer/analysis.cpp | 37 ++++++++++++++++++- src/windows-emulator/emulator_thread.cpp | 1 + src/windows-emulator/emulator_utils.hpp | 2 +- .../module/module_manager.hpp | 13 +++++++ src/windows-emulator/syscall_utils.hpp | 2 +- src/windows-emulator/syscalls.cpp | 2 + src/windows-emulator/syscalls/port.cpp | 5 +++ 7 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/analyzer/analysis.cpp b/src/analyzer/analysis.cpp index b05ce8f0..444e61a6 100644 --- a/src/analyzer/analysis.cpp +++ b/src/analyzer/analysis.cpp @@ -29,11 +29,44 @@ namespace }; } + std::string get_instruction_string(const emulator& emu, const uint64_t address) + { + std::vector instruction_bytes(15, 0); + const auto result = emu.try_read_memory(address, instruction_bytes.data(), instruction_bytes.size()); + if (!result) + { + return {}; + } + + disassembler disasm{}; + const auto instructions = disasm.disassemble(instruction_bytes, 1); + if (instructions.empty()) + { + return {}; + } + + auto& inst = instructions[0]; + + return std::string(inst.mnemonic) + (strlen(inst.op_str) ? " "s + inst.op_str : ""); + } + void handle_suspicious_activity(const analysis_context& c, const std::string_view details) { + std::string addition{}; const auto rip = c.win_emu->emu().read_instruction_pointer(); - c.win_emu->log.print(color::pink, "Suspicious: %.*s at 0x%" PRIx64 " (via 0x%" PRIx64 ")\n", STR_VIEW_VA(details), rip, - c.win_emu->process.previous_ip); + + // TODO: Pass enum? + if (details == "Illegal instruction") + { + const auto inst = get_instruction_string(c.win_emu->emu(), rip); + if (!inst.empty()) + { + addition = " (" + inst + ")"; + } + } + + c.win_emu->log.print(color::pink, "Suspicious: %.*s%.*s at 0x%" PRIx64 " (via 0x%" PRIx64 ")\n", STR_VIEW_VA(details), + STR_VIEW_VA(addition), rip, c.win_emu->process.previous_ip); } void handle_debug_string(const analysis_context& c, const std::string_view details) diff --git a/src/windows-emulator/emulator_thread.cpp b/src/windows-emulator/emulator_thread.cpp index 86e73e32..19af1b48 100644 --- a/src/windows-emulator/emulator_thread.cpp +++ b/src/windows-emulator/emulator_thread.cpp @@ -117,6 +117,7 @@ emulator_thread::emulator_thread(memory_manager& memory, const process_context& teb_obj.NtTib.StackLimit = this->stack_base; teb_obj.NtTib.StackBase = this->stack_base + this->stack_size; teb_obj.NtTib.Self = this->teb->value(); + teb_obj.CurrentLocale = 0x409; teb_obj.ProcessEnvironmentBlock = context.peb.value(); }); } diff --git a/src/windows-emulator/emulator_utils.hpp b/src/windows-emulator/emulator_utils.hpp index 53d82995..97c07605 100644 --- a/src/windows-emulator/emulator_utils.hpp +++ b/src/windows-emulator/emulator_utils.hpp @@ -367,7 +367,7 @@ inline std::u16string read_unicode_string(emulator& emu, const uint64_t uc_strin return read_unicode_string(emu, emulator_object>>{emu, uc_string}); } -inline uint64_t get_function_argument(x86_64_emulator& emu, const size_t index, bool is_syscall = false) +inline uint64_t get_function_argument(x86_64_emulator& emu, const size_t index, const bool is_syscall = false) { switch (index) { diff --git a/src/windows-emulator/module/module_manager.hpp b/src/windows-emulator/module/module_manager.hpp index 25acdf40..897cc777 100644 --- a/src/windows-emulator/module/module_manager.hpp +++ b/src/windows-emulator/module/module_manager.hpp @@ -39,6 +39,19 @@ class module_manager return nullptr; } + mapped_module* find_by_name(const std::string_view name) + { + for (auto& mod : this->modules_ | std::views::values) + { + if (mod.name == name) + { + return &mod; + } + } + + return nullptr; + } + const char* find_name(const uint64_t address) { const auto* mod = this->find_by_address(address); diff --git a/src/windows-emulator/syscall_utils.hpp b/src/windows-emulator/syscall_utils.hpp index 27b9d3d5..0fe55849 100644 --- a/src/windows-emulator/syscall_utils.hpp +++ b/src/windows-emulator/syscall_utils.hpp @@ -3,7 +3,7 @@ #include "windows_emulator.hpp" #include #include -#include "windows-emulator/devices/named_pipe.hpp" +#include "devices/named_pipe.hpp" struct syscall_context { diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 1b1698da..72238d38 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -180,6 +180,7 @@ namespace syscalls /*receive_message_attributes*/, emulator_object /*timeout*/); NTSTATUS handle_NtAlpcConnectPort(); + NTSTATUS handle_NtAlpcConnectPortEx(); // syscalls/process.cpp: NTSTATUS handle_NtQueryInformationProcess(const syscall_context& c, handle process_handle, uint32_t info_class, @@ -1050,6 +1051,7 @@ void syscall_dispatcher::add_handlers(std::map& ha add_handler(NtEnumerateKey); add_handler(NtEnumerateValueKey); add_handler(NtAlpcConnectPort); + add_handler(NtAlpcConnectPortEx); add_handler(NtGetNextThread); add_handler(NtSetInformationObject); add_handler(NtUserGetCursorPos); diff --git a/src/windows-emulator/syscalls/port.cpp b/src/windows-emulator/syscalls/port.cpp index 64363c77..fcaf7319 100644 --- a/src/windows-emulator/syscalls/port.cpp +++ b/src/windows-emulator/syscalls/port.cpp @@ -94,4 +94,9 @@ namespace syscalls { return STATUS_NOT_SUPPORTED; } + + NTSTATUS handle_NtAlpcConnectPortEx() + { + return STATUS_NOT_SUPPORTED; + } } From b2eef2bf46725914db1b7e739bd389e6f48a6555 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 17 Aug 2025 07:31:37 +0200 Subject: [PATCH 2/4] Align processor counts --- src/windows-emulator/kusd_mmio.cpp | 14 +++++++------- src/windows-emulator/minidump_loader.cpp | 2 +- src/windows-emulator/process_context.cpp | 2 ++ src/windows-emulator/syscalls/system.cpp | 4 ++-- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/windows-emulator/kusd_mmio.cpp b/src/windows-emulator/kusd_mmio.cpp index 95eadfa5..512c3408 100644 --- a/src/windows-emulator/kusd_mmio.cpp +++ b/src/windows-emulator/kusd_mmio.cpp @@ -27,16 +27,16 @@ namespace kusd.TimeZoneBias.High2Time = -17; kusd.TimeZoneId = 0x00000002; kusd.LargePageMinimum = 0x00200000; - kusd.RNGSeedVersion = 0x0000000000000013; + kusd.RNGSeedVersion = 0; kusd.TimeZoneBiasStamp = 0x00000004; - kusd.NtBuildNumber = 0x00006c51; + kusd.NtBuildNumber = 19045; kusd.NtProductType = NtProductWinNt; kusd.ProductTypeIsValid = 0x01; kusd.NativeProcessorArchitecture = 0x0009; kusd.NtMajorVersion = 0x0000000a; - kusd.BootId = 0x0000000b; - kusd.SystemExpirationDate.QuadPart = 0x01dc26860a9ff300; - kusd.SuiteMask = 0x00000110; + kusd.BootId = 0; + kusd.SystemExpirationDate.QuadPart = 0; + kusd.SuiteMask = 0; kusd.MitigationPolicies.MitigationPolicies = 0x0a; kusd.MitigationPolicies.NXSupportPolicy = 0x02; kusd.MitigationPolicies.SEHValidationPolicy = 0x02; @@ -48,7 +48,7 @@ namespace kusd.FullNumberOfPhysicalPages = 0x0000000000bf0958; kusd.TickCount.TickCount.LowPart = 0x001f7f05; kusd.TickCount.TickCountQuad = 0x00000000001f7f05; - kusd.Cookie = 0x1c3471da; + kusd.Cookie = 0; kusd.ConsoleSessionForegroundProcessId = 0x00000000000028f4; kusd.TimeUpdateLock = 0x0000000002b28586; kusd.BaselineSystemTimeQpc = 0x0000004b17cd596c; @@ -61,7 +61,7 @@ namespace kusd.TelemetryCoverageRound = 0x00000001; kusd.LangGenerationCount = 0x00000003; kusd.InterruptTimeBias = 0x00000015a5d56406; - kusd.ActiveProcessorCount = 0x0000000c; + kusd.ActiveProcessorCount = 0x00000004; kusd.ActiveGroupCount = 0x01; kusd.TimeZoneBiasEffectiveStart.QuadPart = 0x01db276e654cb2ff; kusd.TimeZoneBiasEffectiveEnd.QuadPart = 0x01db280b8c3b2800; diff --git a/src/windows-emulator/minidump_loader.cpp b/src/windows-emulator/minidump_loader.cpp index e78f6ebd..998a17e2 100644 --- a/src/windows-emulator/minidump_loader.cpp +++ b/src/windows-emulator/minidump_loader.cpp @@ -704,4 +704,4 @@ namespace minidump_loader throw; } } -} // namespace minidump_loader \ No newline at end of file +} // namespace minidump_loader diff --git a/src/windows-emulator/process_context.cpp b/src/windows-emulator/process_context.cpp index 29bde03a..99c87926 100644 --- a/src/windows-emulator/process_context.cpp +++ b/src/windows-emulator/process_context.cpp @@ -225,6 +225,8 @@ void process_context::setup(x86_64_emulator& emu, memory_manager& memory, regist p.HeapDeCommitFreeBlockThreshold = 0x0000000000001000; p.NumberOfHeaps = 0x00000000; p.MaximumNumberOfHeaps = 0x00000010; + p.NumberOfProcessors = 4; + p.ImageSubsystemMajorVersion = 6; p.OSPlatformId = 2; p.OSMajorVersion = 0x0000000a; diff --git a/src/windows-emulator/syscalls/system.cpp b/src/windows-emulator/syscalls/system.cpp index cb0b8705..5af6418b 100644 --- a/src/windows-emulator/syscalls/system.cpp +++ b/src/windows-emulator/syscalls/system.cpp @@ -267,8 +267,8 @@ namespace syscalls basic_info.AllocationGranularity = ALLOCATION_GRANULARITY; basic_info.MinimumUserModeAddress = MIN_ALLOCATION_ADDRESS; basic_info.MaximumUserModeAddress = MAX_ALLOCATION_ADDRESS; - basic_info.ActiveProcessorsAffinityMask = 0x0000000000000fff; - basic_info.NumberOfProcessors = 1; + basic_info.ActiveProcessorsAffinityMask = 0x0000000000000f; + basic_info.NumberOfProcessors = 4; }); default: From 584b770def7b17b4ff97027a75e88a78a7867bd5 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 17 Aug 2025 07:32:26 +0200 Subject: [PATCH 3/4] Store previous IP per thread --- src/analyzer/analysis.cpp | 25 ++++++++++++----------- src/windows-emulator/emulator_thread.hpp | 7 +++++++ src/windows-emulator/minidump_loader.cpp | 1 - src/windows-emulator/process_context.cpp | 4 ---- src/windows-emulator/process_context.hpp | 3 --- src/windows-emulator/windows_emulator.cpp | 4 ++-- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/analyzer/analysis.cpp b/src/analyzer/analysis.cpp index 444e61a6..81288895 100644 --- a/src/analyzer/analysis.cpp +++ b/src/analyzer/analysis.cpp @@ -66,7 +66,7 @@ namespace } c.win_emu->log.print(color::pink, "Suspicious: %.*s%.*s at 0x%" PRIx64 " (via 0x%" PRIx64 ")\n", STR_VIEW_VA(details), - STR_VIEW_VA(addition), rip, c.win_emu->process.previous_ip); + STR_VIEW_VA(addition), rip, c.win_emu->current_thread().previous_ip); } void handle_debug_string(const analysis_context& c, const std::string_view details) @@ -289,8 +289,9 @@ namespace } #endif + const auto previous_ip = c.win_emu->current_thread().previous_ip; const auto is_main_exe = win_emu.mod_manager.executable->is_within(address); - const auto is_previous_main_exe = win_emu.mod_manager.executable->is_within(c.win_emu->process.previous_ip); + const auto is_previous_main_exe = win_emu.mod_manager.executable->is_within(previous_ip); const auto binary = utils::make_lazy([&] { if (is_main_exe) @@ -307,7 +308,7 @@ namespace return win_emu.mod_manager.executable; } - return win_emu.mod_manager.find_by_address(win_emu.process.previous_ip); // + return win_emu.mod_manager.find_by_address(previous_ip); // }); const auto is_in_interesting_module = [&] { @@ -343,8 +344,7 @@ namespace { win_emu.log.print(is_interesting_call ? color::yellow : color::dark_gray, "Executing function: %s (%s) (0x%" PRIx64 ") via (0x%" PRIx64 ") %s\n", export_entry->second.c_str(), - binary->name.c_str(), address, win_emu.process.previous_ip, - previous_binary ? previous_binary->name.c_str() : ""); + binary->name.c_str(), address, previous_ip, previous_binary ? previous_binary->name.c_str() : ""); if (is_interesting_call) { @@ -357,7 +357,7 @@ namespace win_emu.log.print(is_interesting_call ? color::yellow : color::gray, "Executing entry point: %s (0x%" PRIx64 ")\n", binary->name.c_str(), address); } - else if (is_previous_main_exe && binary != previous_binary && !is_return(c.win_emu->emu(), win_emu.process.previous_ip)) + else if (is_previous_main_exe && binary != previous_binary && !is_return(c.win_emu->emu(), previous_ip)) { auto nearest_entry = binary->address_names.upper_bound(address); if (nearest_entry == binary->address_names.begin()) @@ -369,8 +369,8 @@ namespace win_emu.log.print(is_interesting_call ? color::yellow : color::dark_gray, "Transition to foreign code: %s+0x%" PRIx64 " (%s) (0x%" PRIx64 ") via (0x%" PRIx64 ") %s\n", - nearest_entry->second.c_str(), address - nearest_entry->first, binary->name.c_str(), address, - win_emu.process.previous_ip, previous_binary ? previous_binary->name.c_str() : ""); + nearest_entry->second.c_str(), address - nearest_entry->first, binary->name.c_str(), address, previous_ip, + previous_binary ? previous_binary->name.c_str() : ""); } } @@ -416,13 +416,14 @@ namespace const auto address = emu.read_instruction_pointer(); const auto* mod = win_emu.mod_manager.find_by_address(address); const auto is_sus_module = mod != win_emu.mod_manager.ntdll && mod != win_emu.mod_manager.win32u; + const auto previous_ip = win_emu.current_thread().previous_ip; if (is_sus_module) { win_emu.log.print(color::blue, "Executing inline syscall: %.*s (0x%X) at 0x%" PRIx64 " (%s)\n", STR_VIEW_VA(syscall_name), syscall_id, address, mod ? mod->name.c_str() : ""); } - else if (mod->is_within(win_emu.process.previous_ip)) + else if (mod->is_within(previous_ip)) { const auto rsp = emu.read_stack_pointer(); @@ -436,11 +437,11 @@ namespace } else { - const auto* previous_mod = win_emu.mod_manager.find_by_address(win_emu.process.previous_ip); + const auto* previous_mod = win_emu.mod_manager.find_by_address(previous_ip); win_emu.log.print(color::blue, "Crafted out-of-line syscall: %.*s (0x%X) at 0x%" PRIx64 " (%s) via 0x%" PRIx64 " (%s)\n", - STR_VIEW_VA(syscall_name), syscall_id, address, mod ? mod->name.c_str() : "", - win_emu.process.previous_ip, previous_mod ? previous_mod->name.c_str() : ""); + STR_VIEW_VA(syscall_name), syscall_id, address, mod ? mod->name.c_str() : "", previous_ip, + previous_mod ? previous_mod->name.c_str() : ""); } return instruction_hook_continuation::run_instruction; diff --git a/src/windows-emulator/emulator_thread.hpp b/src/windows-emulator/emulator_thread.hpp index bd0d5075..1b2edef5 100644 --- a/src/windows-emulator/emulator_thread.hpp +++ b/src/windows-emulator/emulator_thread.hpp @@ -74,6 +74,9 @@ class emulator_thread : public ref_counted_object uint32_t id{}; + uint64_t current_ip{0}; + uint64_t previous_ip{0}; + std::u16string name{}; std::optional exit_status{}; @@ -144,6 +147,8 @@ class emulator_thread : public ref_counted_object buffer.write(this->argument); buffer.write(this->executed_instructions); buffer.write(this->id); + buffer.write(this->current_ip); + buffer.write(this->previous_ip); buffer.write_string(this->name); @@ -182,6 +187,8 @@ class emulator_thread : public ref_counted_object buffer.read(this->argument); buffer.read(this->executed_instructions); buffer.read(this->id); + buffer.read(this->current_ip); + buffer.read(this->previous_ip); buffer.read_string(this->name); diff --git a/src/windows-emulator/minidump_loader.cpp b/src/windows-emulator/minidump_loader.cpp index 998a17e2..f650fafc 100644 --- a/src/windows-emulator/minidump_loader.cpp +++ b/src/windows-emulator/minidump_loader.cpp @@ -654,7 +654,6 @@ namespace minidump_loader return; } - win_emu.process.current_ip = exception_info->exception_record.exception_address; win_emu.log.info("Exception context: address=0x%" PRIx64 ", code=0x%08X, thread=%u\n", exception_info->exception_record.exception_address, exception_info->exception_record.exception_code, exception_info->thread_id); diff --git a/src/windows-emulator/process_context.cpp b/src/windows-emulator/process_context.cpp index 99c87926..c383febc 100644 --- a/src/windows-emulator/process_context.cpp +++ b/src/windows-emulator/process_context.cpp @@ -248,8 +248,6 @@ void process_context::setup(x86_64_emulator& emu, memory_manager& memory, regist void process_context::serialize(utils::buffer_serializer& buffer) const { - buffer.write(this->current_ip); - buffer.write(this->previous_ip); buffer.write(this->shared_section_address); buffer.write(this->shared_section_size); buffer.write(this->dbwin_buffer); @@ -287,8 +285,6 @@ void process_context::serialize(utils::buffer_serializer& buffer) const void process_context::deserialize(utils::buffer_deserializer& buffer) { - buffer.read(this->current_ip); - buffer.read(this->previous_ip); buffer.read(this->shared_section_address); buffer.read(this->shared_section_size); buffer.read(this->dbwin_buffer); diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 1fd26ac5..66b21342 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -83,9 +83,6 @@ struct process_context callbacks* callbacks_{}; - uint64_t current_ip{0}; - uint64_t previous_ip{0}; - uint64_t shared_section_address{0}; uint64_t shared_section_size{0}; uint64_t dbwin_buffer{0}; diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 17796646..091e7ddd 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -420,8 +420,8 @@ void windows_emulator::on_instruction_execution(const uint64_t address) this->yield_thread(); } - this->process.previous_ip = this->process.current_ip; - this->process.current_ip = this->emu().read_instruction_pointer(); + thread.previous_ip = thread.current_ip; + thread.current_ip = this->emu().read_instruction_pointer(); this->callbacks.on_instruction(address); } From 9ca18dd1411b35e9b364cc4dd5918bf0a4e03d8d Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 17 Aug 2025 07:52:45 +0200 Subject: [PATCH 4/4] Fix linter warning --- src/analyzer/analysis.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/analyzer/analysis.cpp b/src/analyzer/analysis.cpp index 81288895..23f50bfc 100644 --- a/src/analyzer/analysis.cpp +++ b/src/analyzer/analysis.cpp @@ -45,8 +45,7 @@ namespace return {}; } - auto& inst = instructions[0]; - + const auto& inst = instructions[0]; return std::string(inst.mnemonic) + (strlen(inst.op_str) ? " "s + inst.op_str : ""); }