Better output

This commit is contained in:
momo5502
2024-09-20 15:17:43 +02:00
parent 92df2ffc28
commit 8130d12089
11 changed files with 126 additions and 57 deletions

View File

@@ -40,10 +40,11 @@ namespace
{
if (use_gdb)
{
puts("Launching gdb stub...");
const auto* address = "0.0.0.0:28960";
win_emu.logger.print(color::pink, "Waiting for GDB connection on %s...\n", address);
x64_gdb_stub_handler handler{win_emu.emu()};
run_gdb_stub(handler, "i386:x86-64", gdb_registers.size(), "0.0.0.0:28960");
run_gdb_stub(handler, "i386:x86-64", gdb_registers.size(), address);
}
else
{
@@ -52,11 +53,9 @@ namespace
}
catch (...)
{
printf("Emulation failed at: %llX\n", win_emu.emu().read_instruction_pointer());
printf("Emulation failed at: 0x%llX\n", win_emu.emu().read_instruction_pointer());
throw;
}
printf("Emulation done.\n");
}
void run(std::string_view application)
@@ -65,14 +64,14 @@ namespace
application, {}
};
watch_system_objects(win_emu);
//watch_system_objects(win_emu);
const auto& exe = *win_emu.process().executable;
const auto text_start = exe.image_base + 0x1000;
const auto text_end = exe.image_base + 0x52000;
const auto scan_size = 0x1000;
const auto scan_size = 0x100;
win_emu.emu().hook_memory_read(text_start, scan_size, [&](uint64_t address, size_t, uint64_t)
{

View File

@@ -13,7 +13,7 @@ emulator_hook* watch_object(windows_emulator& emu, emulator_object<T> object)
const auto rip = emu.emu().read_instruction_pointer();
const auto offset = address - object.value();
emu.logger.log("Object access: %s - %llX (%s) at %llX (%s)\n", i.get_type_name().c_str(),
emu.logger.log("Object access: %s - 0x%llX (%s) at 0x%llX (%s)\n", i.get_type_name().c_str(),
offset,
i.get_member_name(offset).c_str(), rip,
emu.process().module_manager.find_name(rip));

View File

@@ -32,6 +32,7 @@ namespace
case cyan: return COLOR(0xB, "\033[0;96m");
case pink: return COLOR(0xD, "\033[0;95m");
case white: return COLOR(0xF, "\033[0;97m");
case dark_gray: return COLOR(0x8, "\033[0;97m");
case gray:
default: return get_reset_color();
}

View File

@@ -11,6 +11,7 @@ enum class color
pink,
white,
gray,
dark_gray,
};
class logger

View File

@@ -22,4 +22,9 @@ struct mapped_module
exported_symbols exports{};
address_name_mapping address_names{};
bool is_within(const uint64_t address) const
{
return address >= this->image_base && address < (this->image_base + this->size_of_image);
}
};

View File

@@ -66,7 +66,7 @@ mapped_module* module_manager::map_module(const std::filesystem::path& file)
return nullptr;
}
printf("Mapped %s at %llX\n", mod->path.generic_string().c_str(), mod->image_base);
printf("Mapped %s at 0x%llX\n", mod->path.generic_string().c_str(), mod->image_base);
const auto image_base = mod->image_base;
const auto entry = this->modules_.try_emplace(image_base, std::move(*mod));

View File

@@ -1,4 +1,5 @@
#pragma once
#include "emulator_utils.hpp"
#include "handles.hpp"
@@ -119,6 +120,9 @@ struct process_context
}
uint64_t executed_instructions{0};
uint64_t current_ip{0};
uint64_t previous_ip{0};
emulator_object<TEB> teb;
emulator_object<PEB> peb;
emulator_object<RTL_USER_PROCESS_PARAMETERS> process_params;
@@ -144,6 +148,8 @@ struct process_context
void serialize(utils::buffer_serializer& buffer) const
{
buffer.write(this->executed_instructions);
buffer.write(this->current_ip);
buffer.write(this->previous_ip);
buffer.write(this->teb);
buffer.write(this->peb);
buffer.write(this->process_params);
@@ -168,6 +174,8 @@ struct process_context
void deserialize(utils::buffer_deserializer& buffer)
{
buffer.read(this->executed_instructions);
buffer.read(this->current_ip);
buffer.read(this->previous_ip);
buffer.read(this->teb);
buffer.read(this->peb);
buffer.read(this->process_params);

View File

@@ -5,11 +5,14 @@
#include "context_frame.hpp"
#include "emulator_utils.hpp"
#include "windows_emulator.hpp"
#include <utils/io.hpp>
struct syscall_context
{
windows_emulator& win_emu;
x64_emulator& emu;
process_context& proc;
mutable bool write_status;
@@ -71,10 +74,6 @@ namespace
{
syscalls.push_back(std::move(syscall.second));
}
else
{
printf("Skipping %s\n", syscall.second.c_str());
}
}
return syscalls;
@@ -334,8 +333,8 @@ namespace
}
NTSTATUS handle_NtOpenEvent(const syscall_context& c, const emulator_object<uint64_t> event_handle,
const ACCESS_MASK /*desired_access*/,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes)
const ACCESS_MASK /*desired_access*/,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes)
{
const auto attributes = object_attributes.read();
const auto name = read_unicode_string(c.emu, attributes.ObjectName);
@@ -420,7 +419,7 @@ namespace
const auto attributes = object_attributes.read();
auto filename = read_unicode_string(c.emu, attributes.ObjectName);
printf("Open section: %S\n", filename.c_str());
printf("Opening section: %S\n", filename.c_str());
if (filename == L"\\Windows\\SharedSection")
{
@@ -622,7 +621,7 @@ namespace
const auto mod = c.proc.module_manager.find_by_address(base_address);
if (!mod)
{
printf("Bad address for memory image request: %llX\n", base_address);
printf("Bad address for memory image request: 0x%llX\n", base_address);
return STATUS_INVALID_ADDRESS;
}
@@ -842,7 +841,7 @@ namespace
|| info_class == SystemFeatureConfigurationInformation
|| info_class == SystemFeatureConfigurationSectionInformation)
{
printf("Unsupported, but allowed system info class: %X\n", info_class);
//printf("Unsupported, but allowed system info class: %X\n", info_class);
return STATUS_NOT_SUPPORTED;
}
@@ -1030,6 +1029,40 @@ namespace
return STATUS_SUCCESS;
}
if (info_class == ProcessImageFileNameWin32)
{
const auto peb = c.proc.peb.read();
emulator_object<RTL_USER_PROCESS_PARAMETERS> proc_params{c.emu, peb.ProcessParameters};
const auto params = proc_params.read();
const auto length = params.ImagePathName.Length + sizeof(UNICODE_STRING) + 2;
if (return_length)
{
return_length.write(static_cast<uint32_t>(length));
}
if (process_information_length < length)
{
return STATUS_BUFFER_OVERFLOW;
}
const emulator_object<UNICODE_STRING> info{c.emu, process_information};
info.access([&](UNICODE_STRING& str)
{
const auto buffer_start = static_cast<uint64_t>(process_information) + sizeof(UNICODE_STRING);
const auto string = read_unicode_string(c.emu, params.ImagePathName);
c.emu.write_memory(buffer_start, string.c_str(), (string.size() + 1) * 2);
str.Length = params.ImagePathName.Length;
str.MaximumLength = str.Length;
str.Buffer = reinterpret_cast<wchar_t*>(buffer_start);
});
return STATUS_SUCCESS;
}
printf("Unsupported process info class: %X\n", info_class);
c.emu.stop();
@@ -1125,8 +1158,8 @@ namespace
const auto requested_protection = map_nt_to_emulator_protection(protection);
printf("Changing protection at %llX-%llX to %s\n", aligned_start, aligned_start + aligned_length,
get_permission_string(requested_protection).c_str());
c.win_emu.logger.print(color::dark_gray, "--> Changing protection at 0x%llX-0x%llX to %s\n", aligned_start,
aligned_start + aligned_length, get_permission_string(requested_protection).c_str());
memory_permission old_protection_value{};
c.emu.protect_memory(aligned_start, aligned_length, requested_protection, &old_protection_value);
@@ -1297,7 +1330,7 @@ namespace
const ULONG /*section_page_protection*/, const ULONG /*allocation_attributes*/,
const uint64_t /*file_handle*/)
{
puts("NtCreateSection not supported");
//puts("NtCreateSection not supported");
section_handle.write(SHARED_SECTION.bits);
maximum_size.access([&c](ULARGE_INTEGER& large_int)
@@ -1365,62 +1398,62 @@ namespace
NTSTATUS handle_NtDeviceIoControlFile()
{
puts("NtDeviceIoControlFile not supported");
//puts("NtDeviceIoControlFile not supported");
return STATUS_SUCCESS;
}
NTSTATUS handle_NtQueryWnfStateData()
{
puts("NtQueryWnfStateData not supported");
//puts("NtQueryWnfStateData not supported");
return STATUS_NOT_SUPPORTED;
}
NTSTATUS handle_NtQueryWnfStateNameInformation()
{
puts("NtQueryWnfStateNameInformation not supported");
//puts("NtQueryWnfStateNameInformation not supported");
//return STATUS_NOT_SUPPORTED;
return STATUS_SUCCESS;
}
NTSTATUS handle_NtOpenProcessToken()
{
puts("NtOpenProcessToken not supported");
//puts("NtOpenProcessToken not supported");
return STATUS_NOT_SUPPORTED;
}
NTSTATUS handle_NtQuerySecurityAttributesToken()
{
puts("NtQuerySecurityAttributesToken not supported");
//puts("NtQuerySecurityAttributesToken not supported");
return STATUS_NOT_SUPPORTED;
}
NTSTATUS handle_NtQueryLicenseValue()
{
puts("NtQueryLicenseValue not supported");
//puts("NtQueryLicenseValue not supported");
return STATUS_NOT_SUPPORTED;
}
NTSTATUS handle_NtTestAlert()
{
puts("NtTestAlert not supported");
//puts("NtTestAlert not supported");
return STATUS_NOT_SUPPORTED;
}
NTSTATUS handle_NtQueryInformationToken()
{
puts("NtQueryInformationToken not supported");
//puts("NtQueryInformationToken not supported");
return STATUS_NOT_SUPPORTED;
}
NTSTATUS handle_NtDxgkIsFeatureEnabled()
{
puts("NtDxgkIsFeatureEnabled not supported");
//puts("NtDxgkIsFeatureEnabled not supported");
return STATUS_NOT_SUPPORTED;
}
NTSTATUS handle_NtUserDisplayConfigGetDeviceInfo()
{
puts("NtUserDisplayConfigGetDeviceInfo not supported");
//puts("NtUserDisplayConfigGetDeviceInfo not supported");
return STATUS_NOT_SUPPORTED;
}
@@ -1439,7 +1472,7 @@ namespace
NTSTATUS handle_NtUserGetThreadState()
{
puts("NtUserGetThreadState not supported");
//puts("NtUserGetThreadState not supported");
return STATUS_NOT_SUPPORTED;
}
@@ -1538,13 +1571,12 @@ namespace
temp_buffer.resize(length);
c.emu.read_memory(buffer, temp_buffer.data(), temp_buffer.size());
(void)fwrite(temp_buffer.data(), 1, temp_buffer.size(), stdout);
(void)fflush(stdout);
c.win_emu.logger.info("%.*s", static_cast<int>(temp_buffer.size()), temp_buffer.data());
return STATUS_SUCCESS;
}
puts("NtWriteFile not supported");
//puts("NtWriteFile not supported");
c.emu.stop();
return STATUS_NOT_SUPPORTED;
}
@@ -1831,20 +1863,23 @@ void syscall_dispatcher::deserialize(utils::buffer_deserializer& buffer)
this->add_handlers();
}
void syscall_dispatcher::dispatch(x64_emulator& emu, process_context& context)
void syscall_dispatcher::dispatch(windows_emulator& win_emu)
{
auto& emu = win_emu.emu();
auto& context = win_emu.process();
const auto address = emu.read_instruction_pointer();
const auto syscall_id = emu.reg<uint32_t>(x64_register::eax);
const syscall_context c{emu, context, true};
const syscall_context c{win_emu, emu, context, true};
try
{
const auto entry = this->handlers_.find(syscall_id);
if (entry == this->handlers_.end())
{
printf("Unknown syscall: %X\n", syscall_id);
printf("Unknown syscall: 0x%X\n", syscall_id);
c.emu.reg<uint64_t>(x64_register::rax, STATUS_NOT_SUPPORTED);
c.emu.stop();
return;
@@ -1852,24 +1887,25 @@ void syscall_dispatcher::dispatch(x64_emulator& emu, process_context& context)
if (!entry->second.handler)
{
printf("Unimplemented syscall: %s - %X\n", entry->second.name.c_str(), syscall_id);
printf("Unimplemented syscall: %s - 0x%X\n", entry->second.name.c_str(), syscall_id);
c.emu.reg<uint64_t>(x64_register::rax, STATUS_NOT_SUPPORTED);
c.emu.stop();
return;
}
printf("Handling syscall: %s with id %X at %llX \n", entry->second.name.c_str(), syscall_id, address);
win_emu.logger.print(color::dark_gray, "Syscall: %s (0x%X) at 0x%llX\n", entry->second.name.c_str(), syscall_id,
address);
entry->second.handler(c);
}
catch (std::exception& e)
{
printf("Syscall threw an exception: %X (%llX) - %s\n", syscall_id, address, e.what());
printf("Syscall threw an exception: %X (0x%llX) - %s\n", syscall_id, address, e.what());
emu.reg<uint64_t>(x64_register::rax, STATUS_UNSUCCESSFUL);
emu.stop();
}
catch (...)
{
printf("Syscall threw an unknown exception: %X (%llX)\n", syscall_id, address);
printf("Syscall threw an unknown exception: %X (0x%llX)\n", syscall_id, address);
emu.reg<uint64_t>(x64_register::rax, STATUS_UNSUCCESSFUL);
emu.stop();
}

View File

@@ -13,13 +13,15 @@ struct syscall_handler_entry
std::string name{};
};
class windows_emulator;
class syscall_dispatcher
{
public:
syscall_dispatcher() = default;
syscall_dispatcher(const exported_symbols& ntdll_exports, const exported_symbols& win32u_exports);
void dispatch(x64_emulator& emu, process_context& context);
void dispatch(windows_emulator& win_emu);
void serialize(utils::buffer_serializer& buffer) const;
void deserialize(utils::buffer_deserializer& buffer);

View File

@@ -437,9 +437,6 @@ namespace
frame.cs = pointers.ContextRecord->SegCs;
frame.eflags = pointers.ContextRecord->EFlags;
});
printf("ContextRecord: %llX\n", context_record_obj.value());
printf("ExceptionRecord: %llX\n", exception_record_obj.value());
}
void dispatch_access_violation(x64_emulator& emu, const uint64_t dispatcher, const uint64_t address,
@@ -543,20 +540,20 @@ void windows_emulator::setup_hooks()
}
}
this->dispatcher_.dispatch(this->emu(), this->process());
this->dispatcher_.dispatch(*this);
return instruction_hook_continuation::skip_instruction;
});
this->emu().hook_instruction(x64_hookable_instructions::invalid, [&]
{
const auto ip = this->emu().read_instruction_pointer();
printf("Invalid instruction at: %llX\n", ip);
printf("Invalid instruction at: 0x%llX\n", ip);
return instruction_hook_continuation::skip_instruction;
});
this->emu().hook_interrupt([&](const int interrupt)
{
printf("Interrupt: %i %llX\n", interrupt, this->emu().read_instruction_pointer());
printf("Interrupt: %i 0x%llX\n", interrupt, this->emu().read_instruction_pointer());
});
this->emu().hook_memory_violation([&](const uint64_t address, const size_t size, const memory_operation operation,
@@ -568,11 +565,11 @@ void windows_emulator::setup_hooks()
if (type == memory_violation_type::protection)
{
printf("Protection violation: %llX (%zX) - %s at %llX (%s)\n", address, size, permission.c_str(), ip, name);
printf("Protection violation: 0x%llX (%zX) - %s at 0x%llX (%s)\n", address, size, permission.c_str(), ip, name);
}
else if (type == memory_violation_type::unmapped)
{
printf("Mapping violation: %llX (%zX) - %s at %llX (%s)\n", address, size, permission.c_str(), ip, name);
printf("Mapping violation: 0x%llX (%zX) - %s at 0x%llX (%s)\n", address, size, permission.c_str(), ip, name);
}
dispatch_access_violation(this->emu(), this->process().ki_user_exception_dispatcher, address, operation);
@@ -582,9 +579,17 @@ void windows_emulator::setup_hooks()
this->emu().hook_memory_execution(0, std::numeric_limits<size_t>::max(),
[&](const uint64_t address, const size_t, const uint64_t)
{
++this->process().executed_instructions;
auto& process = this->process();
if (address == 0x180038B65)
++process.executed_instructions;
process.previous_ip = process.current_ip;
process.current_ip = this->emu().read_instruction_pointer();
const auto is_interesting_call = process.executable->is_within(
process.previous_ip) || process.executable->is_within(address);
/*if (address == 0x180038B65)
{
puts("!!! DLL init failed");
}
@@ -593,7 +598,13 @@ void windows_emulator::setup_hooks()
const auto* name = this->process().module_manager.find_name(
this->emu().reg(x64_register::rcx));
printf("!!! DLL init: %s\n", name);
}*/
if (!this->verbose_ && !this->verbose_calls_ && !is_interesting_call)
{
return;
}
const auto* binary = this->process().module_manager.find_by_address(address);
if (binary)
@@ -601,13 +612,13 @@ void windows_emulator::setup_hooks()
const auto export_entry = binary->address_names.find(address);
if (export_entry != binary->address_names.end())
{
printf("Executing function: %s - %s (%llX)\n", binary->name.c_str(),
export_entry->second.c_str(), address);
logger.print(is_interesting_call ? color::yellow : color::gray, "Executing function: %s - %s (0x%llX)\n", binary->name.c_str(),
export_entry->second.c_str(), address);
}
else if (address == binary->entry_point)
{
printf("Executing entry point: %s (%llX)\n", binary->name.c_str(),
address);
logger.print(is_interesting_call ? color::yellow : color::gray, "Executing entry point: %s (0x%llX)\n", binary->name.c_str(),
address);
}
}

View File

@@ -60,6 +60,11 @@ public:
this->verbose_ = verbose;
}
void set_verbose_calls(const bool verbose)
{
this->verbose_calls_ = verbose;
}
void add_syscall_hook(instruction_hook_callback callback)
{
this->syscall_hooks_.push_back(std::move(callback));
@@ -69,6 +74,7 @@ public:
private:
bool verbose_{false};
bool verbose_calls_{false};
std::unique_ptr<x64_emulator> emu_{};
std::vector<instruction_hook_callback> syscall_hooks_{};