Various fixes and changes (#450)

This commit is contained in:
Maurice Heumann
2025-08-17 08:09:47 +02:00
committed by GitHub
14 changed files with 90 additions and 35 deletions

View File

@@ -29,11 +29,43 @@ namespace
};
}
std::string get_instruction_string(const emulator& emu, const uint64_t address)
{
std::vector<uint8_t> 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 {};
}
const 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->current_thread().previous_ip);
}
void handle_debug_string(const analysis_context& c, const std::string_view details)
@@ -256,8 +288,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)
@@ -274,7 +307,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 = [&] {
@@ -310,8 +343,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() : "<N/A>");
binary->name.c_str(), address, previous_ip, previous_binary ? previous_binary->name.c_str() : "<N/A>");
if (is_interesting_call)
{
@@ -324,7 +356,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())
@@ -336,8 +368,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() : "<N/A>");
nearest_entry->second.c_str(), address - nearest_entry->first, binary->name.c_str(), address, previous_ip,
previous_binary ? previous_binary->name.c_str() : "<N/A>");
}
}
@@ -383,13 +415,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() : "<N/A>");
}
else if (mod->is_within(win_emu.process.previous_ip))
else if (mod->is_within(previous_ip))
{
const auto rsp = emu.read_stack_pointer();
@@ -403,11 +436,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() : "<N/A>",
win_emu.process.previous_ip, previous_mod ? previous_mod->name.c_str() : "<N/A>");
STR_VIEW_VA(syscall_name), syscall_id, address, mod ? mod->name.c_str() : "<N/A>", previous_ip,
previous_mod ? previous_mod->name.c_str() : "<N/A>");
}
return instruction_hook_continuation::run_instruction;

View File

@@ -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();
});
}

View File

@@ -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<NTSTATUS> 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);

View File

@@ -367,7 +367,7 @@ inline std::u16string read_unicode_string(emulator& emu, const uint64_t uc_strin
return read_unicode_string(emu, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>{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)
{

View File

@@ -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;

View File

@@ -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);
@@ -704,4 +703,4 @@ namespace minidump_loader
throw;
}
}
} // namespace minidump_loader
} // namespace minidump_loader

View File

@@ -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);

View File

@@ -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;
@@ -246,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);
@@ -285,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);

View File

@@ -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};

View File

@@ -3,7 +3,7 @@
#include "windows_emulator.hpp"
#include <ctime>
#include <platform/primitives.hpp>
#include "windows-emulator/devices/named_pipe.hpp"
#include "devices/named_pipe.hpp"
struct syscall_context
{

View File

@@ -180,6 +180,7 @@ namespace syscalls
/*receive_message_attributes*/,
emulator_object<LARGE_INTEGER> /*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<std::string, syscall_handler>& ha
add_handler(NtEnumerateKey);
add_handler(NtEnumerateValueKey);
add_handler(NtAlpcConnectPort);
add_handler(NtAlpcConnectPortEx);
add_handler(NtGetNextThread);
add_handler(NtSetInformationObject);
add_handler(NtUserGetCursorPos);

View File

@@ -94,4 +94,9 @@ namespace syscalls
{
return STATUS_NOT_SUPPORTED;
}
NTSTATUS handle_NtAlpcConnectPortEx()
{
return STATUS_NOT_SUPPORTED;
}
}

View File

@@ -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:

View File

@@ -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);
}