Remove getters

This commit is contained in:
momo5502
2025-02-10 16:14:37 +01:00
parent a28be3049b
commit adf632c64e
11 changed files with 136 additions and 190 deletions

View File

@@ -27,17 +27,17 @@ namespace
#ifdef OS_WINDOWS
watch_object(win_emu, modules, *win_emu.current_thread().teb, cache_logging);
watch_object(win_emu, modules, win_emu.process().peb, cache_logging);
watch_object(win_emu, modules, win_emu.process.peb, cache_logging);
watch_object(win_emu, modules, emulator_object<KUSER_SHARED_DATA64>{win_emu.emu(), kusd_mmio::address()},
cache_logging);
auto* params_hook = watch_object(win_emu, modules, win_emu.process().process_params, cache_logging);
auto* params_hook = watch_object(win_emu, modules, win_emu.process.process_params, cache_logging);
win_emu.emu().hook_memory_write(
win_emu.process().peb.value() + offsetof(PEB64, ProcessParameters), 0x8,
win_emu.process.peb.value() + offsetof(PEB64, ProcessParameters), 0x8,
[&win_emu, cache_logging, params_hook, modules](const uint64_t address, size_t,
const uint64_t value) mutable {
const auto target_address = win_emu.process().peb.value() + offsetof(PEB64, ProcessParameters);
const auto target_address = win_emu.process.peb.value() + offsetof(PEB64, ProcessParameters);
if (address == target_address)
{
@@ -80,7 +80,7 @@ namespace
throw;
}
const auto exit_status = win_emu.process().exit_status;
const auto exit_status = win_emu.process.exit_status;
if (!exit_status.has_value())
{
win_emu.log.print(color::red, "Emulation terminated without status!\n");
@@ -136,12 +136,12 @@ namespace
if (options.silent)
{
win_emu.buffer_stdout = false;
win_emu.callbacks().stdout_callback = [](const std::string_view data) {
win_emu.callbacks.stdout_callback = [](const std::string_view data) {
(void)fwrite(data.data(), 1, data.size(), stdout);
};
}
const auto& exe = *win_emu.process().executable;
const auto& exe = *win_emu.process.executable;
const auto concise_logging = options.concise_logging;
@@ -154,7 +154,7 @@ namespace
auto read_handler = [&, section, concise_logging](const uint64_t address, size_t, uint64_t) {
const auto rip = win_emu.emu().read_instruction_pointer();
if (win_emu.process().mod_manager.find_by_address(rip) != win_emu.process().executable)
if (win_emu.process.mod_manager.find_by_address(rip) != win_emu.process.executable)
{
return;
}
@@ -174,7 +174,7 @@ namespace
const auto write_handler = [&, section, concise_logging](const uint64_t address, size_t, uint64_t) {
const auto rip = win_emu.emu().read_instruction_pointer();
if (win_emu.process().mod_manager.find_by_address(rip) != win_emu.process().executable)
if (win_emu.process.mod_manager.find_by_address(rip) != win_emu.process.executable)
{
return;
}

View File

@@ -13,8 +13,8 @@ emulator_hook* watch_object(windows_emulator& emu, const std::set<std::string, s
object.value(), object.size(),
[i = std::move(info), object, &emu, cache_logging, modules](const uint64_t address, size_t, uint64_t) {
const auto rip = emu.emu().read_instruction_pointer();
const auto* mod = emu.process().mod_manager.find_by_address(rip);
const auto is_main_access = mod == emu.process().executable || modules.contains(mod->name);
const auto* mod = emu.process.mod_manager.find_by_address(rip);
const auto is_main_access = mod == emu.process.executable || modules.contains(mod->name);
if (!emu.verbose_calls && !is_main_access)
{

View File

@@ -16,7 +16,7 @@ namespace
win_emu.log.disable_output(true);
win_emu.start();
if (win_emu.process().exception_rip.has_value())
if (win_emu.process.exception_rip.has_value())
{
throw std::runtime_error("Exception!");
}
@@ -34,7 +34,7 @@ namespace
void forward_emulator(windows_emulator& win_emu)
{
const auto target = win_emu.process().executable->find_export("vulnerable");
const auto target = win_emu.process.executable->find_export("vulnerable");
win_emu.emu().hook_memory_execution(target, 1, [&](uint64_t, size_t, uint64_t) { win_emu.emu().stop(); });
run_emulation(win_emu);
@@ -83,8 +83,8 @@ namespace
restore_emulator();
const auto memory = emu.memory().allocate_memory(
page_align_up(std::max(data.size(), static_cast<size_t>(1))), memory_permission::read_write);
const auto memory = emu.memory.allocate_memory(page_align_up(std::max(data.size(), static_cast<size_t>(1))),
memory_permission::read_write);
emu.emu().write_memory(memory, data.data(), data.size());
emu.emu().reg(x64_register::rcx, memory);

View File

@@ -17,7 +17,7 @@ namespace test
auto emu = create_sample_emulator();
emu.start({}, count);
ASSERT_EQ(emu.process().executed_instructions, count);
ASSERT_EQ(emu.process.executed_instructions, count);
}
TEST(EmulationTest, CountedEmulationIsAccurate)
@@ -27,7 +27,7 @@ namespace test
ASSERT_TERMINATED_SUCCESSFULLY(emu);
const auto executedInstructions = emu.process().executed_instructions;
const auto executedInstructions = emu.process.executed_instructions;
auto new_emu = create_sample_emulator();
@@ -36,12 +36,12 @@ namespace test
new_emu.start({}, instructionsToExecute);
ASSERT_EQ(new_emu.process().executed_instructions, instructionsToExecute);
ASSERT_EQ(new_emu.process.executed_instructions, instructionsToExecute);
ASSERT_NOT_TERMINATED(new_emu);
new_emu.start({}, offset);
ASSERT_TERMINATED_SUCCESSFULLY(new_emu);
ASSERT_EQ(new_emu.process().executed_instructions, executedInstructions);
ASSERT_EQ(new_emu.process.executed_instructions, executedInstructions);
}
}

View File

@@ -4,17 +4,17 @@
#include <gtest/gtest.h>
#include <windows_emulator.hpp>
#define ASSERT_NOT_TERMINATED(win_emu) \
do \
{ \
ASSERT_FALSE((win_emu).process().exit_status.has_value()); \
#define ASSERT_NOT_TERMINATED(win_emu) \
do \
{ \
ASSERT_FALSE((win_emu).process.exit_status.has_value()); \
} while (false)
#define ASSERT_TERMINATED_WITH_STATUS(win_emu, status) \
do \
{ \
ASSERT_TRUE((win_emu).process().exit_status.has_value()); \
ASSERT_EQ(*(win_emu).process().exit_status, status); \
#define ASSERT_TERMINATED_WITH_STATUS(win_emu, status) \
do \
{ \
ASSERT_TRUE((win_emu).process.exit_status.has_value()); \
ASSERT_EQ(*(win_emu).process.exit_status, status); \
} while (false)
#define ASSERT_TERMINATED_SUCCESSFULLY(win_emu) ASSERT_TERMINATED_WITH_STATUS(win_emu, STATUS_SUCCESS)
@@ -101,7 +101,7 @@ namespace test
emu.serialize(start_state);
emu.start();
const auto limit = emu.process().executed_instructions;
const auto limit = emu.process.executed_instructions;
const auto reset_emulator = [&] {
utils::buffer_deserializer deserializer{start_state.get_buffer()};
@@ -152,6 +152,6 @@ namespace test
const auto rip = emu.emu().read_instruction_pointer();
printf("Diff detected after 0x%" PRIx64 " instructions at 0x%" PRIx64 " (%s)\n", lower_bound, rip,
emu.process().mod_manager.find_name(rip));
emu.process.mod_manager.find_name(rip));
}
}

View File

@@ -465,7 +465,7 @@ namespace
write_io_status(this->delayed_ioctl_->io_status_block, STATUS_TIMEOUT);
}
auto* e = win_emu.process().events.get(this->delayed_ioctl_->event);
auto* e = win_emu.process.events.get(this->delayed_ioctl_->event);
if (e)
{
e->signaled = true;
@@ -547,7 +547,7 @@ namespace
static std::vector<SOCKET> resolve_endpoints(windows_emulator& win_emu,
const std::span<const AFD_POLL_HANDLE_INFO64> handles)
{
auto& proc = win_emu.process();
auto& proc = win_emu.process;
std::vector<SOCKET> endpoints{};
endpoints.reserve(handles.size());

View File

@@ -62,7 +62,7 @@ void syscall_dispatcher::add_handlers()
void syscall_dispatcher::dispatch(windows_emulator& win_emu)
{
auto& emu = win_emu.emu();
auto& context = win_emu.process();
auto& context = win_emu.process;
const auto address = emu.read_instruction_pointer();
const auto syscall_id = emu.reg<uint32_t>(x64_register::eax);
@@ -91,8 +91,8 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
const auto* mod = context.mod_manager.find_by_address(address);
if (mod != context.ntdll && mod != context.win32u)
{
win_emu.callbacks().inline_syscall(syscall_id, address, mod ? mod->name.c_str() : "<N/A>",
entry->second.name);
win_emu.callbacks.inline_syscall(syscall_id, address, mod ? mod->name.c_str() : "<N/A>",
entry->second.name);
win_emu.log.print(color::blue, "Executing inline syscall: %s (0x%X) at 0x%" PRIx64 " (%s)\n",
entry->second.name.c_str(), syscall_id, address, mod ? mod->name.c_str() : "<N/A>");
@@ -116,9 +116,9 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
{
const auto* previous_mod = context.mod_manager.find_by_address(context.previous_ip);
win_emu.callbacks().outofline_syscall(syscall_id, address, mod ? mod->name.c_str() : "<N/A>",
entry->second.name, context.previous_ip,
previous_mod ? previous_mod->name.c_str() : "<N/A>");
win_emu.callbacks.outofline_syscall(syscall_id, address, mod ? mod->name.c_str() : "<N/A>",
entry->second.name, context.previous_ip,
previous_mod ? previous_mod->name.c_str() : "<N/A>");
win_emu.log.print(color::blue,
"Crafted out-of-line syscall: %s (0x%X) at 0x%" PRIx64 " (%s) via 0x%" PRIx64

View File

@@ -704,8 +704,8 @@ namespace
{
constexpr auto shared_section_size = 0x10000;
const auto address = c.win_emu.memory().find_free_allocation_base(shared_section_size);
c.win_emu.memory().allocate_memory(address, shared_section_size, memory_permission::read_write);
const auto address = c.win_emu.memory.find_free_allocation_base(shared_section_size);
c.win_emu.memory.allocate_memory(address, shared_section_size, memory_permission::read_write);
const std::u16string_view windows_dir = c.proc.kusd.get().NtSystemRoot.arr;
const auto windows_dir_size = windows_dir.size() * 2;
@@ -789,7 +789,7 @@ namespace
}
const auto protection = map_nt_to_emulator_protection(section_entry->section_page_protection);
const auto address = c.win_emu.memory().allocate_memory(size, protection);
const auto address = c.win_emu.memory.allocate_memory(size, protection);
if (!file_data.empty())
{
@@ -850,7 +850,7 @@ namespace
const emulator_object<EMU_MEMORY_BASIC_INFORMATION64> info{c.emu, memory_information};
info.access([&](EMU_MEMORY_BASIC_INFORMATION64& image_info) {
const auto region_info = c.win_emu.memory().get_region_info(base_address);
const auto region_info = c.win_emu.memory.get_region_info(base_address);
assert(!region_info.is_committed || region_info.is_reserved);
@@ -910,7 +910,7 @@ namespace
return STATUS_BUFFER_OVERFLOW;
}
const auto region_info = c.win_emu.memory().get_region_info(base_address);
const auto region_info = c.win_emu.memory.get_region_info(base_address);
if (!region_info.is_reserved)
{
return STATUS_INVALID_ADDRESS;
@@ -1655,7 +1655,7 @@ namespace
if (!f->enumeration_state || query_flags & SL_RESTART_SCAN)
{
f->enumeration_state.emplace(file_enumeration_state{});
f->enumeration_state->files = scan_directory(c.win_emu.file_sys().translate(f->name));
f->enumeration_state->files = scan_directory(c.win_emu.file_sys.translate(f->name));
}
auto& enum_state = *f->enumeration_state;
@@ -2015,8 +2015,7 @@ namespace
try
{
c.win_emu.memory().protect_memory(aligned_start, aligned_length, requested_protection,
&old_protection_value);
c.win_emu.memory.protect_memory(aligned_start, aligned_length, requested_protection, &old_protection_value);
}
catch (...)
{
@@ -2118,7 +2117,7 @@ namespace
auto potential_base = base_address.read();
if (!potential_base)
{
potential_base = c.win_emu.memory().find_free_allocation_base(allocation_bytes);
potential_base = c.win_emu.memory.find_free_allocation_base(allocation_bytes);
}
if (!potential_base)
@@ -2138,7 +2137,7 @@ namespace
throw std::runtime_error("Unsupported allocation type!");
}
if (commit && !reserve && c.win_emu.memory().commit_memory(potential_base, allocation_bytes, protection))
if (commit && !reserve && c.win_emu.memory.commit_memory(potential_base, allocation_bytes, protection))
{
c.win_emu.log.print(color::dark_gray, "--> Committed 0x%" PRIx64 " - 0x%" PRIx64 "\n", potential_base,
potential_base + allocation_bytes);
@@ -2149,7 +2148,7 @@ namespace
c.win_emu.log.print(color::dark_gray, "--> Allocated 0x%" PRIx64 " - 0x%" PRIx64 "\n", potential_base,
potential_base + allocation_bytes);
return c.win_emu.memory().allocate_memory(potential_base, allocation_bytes, protection, !commit)
return c.win_emu.memory.allocate_memory(potential_base, allocation_bytes, protection, !commit)
? STATUS_SUCCESS
: STATUS_MEMORY_NOT_ALLOCATED;
}
@@ -2177,14 +2176,14 @@ namespace
if (free_type & MEM_RELEASE)
{
return c.win_emu.memory().release_memory(allocation_base, allocation_size) ? STATUS_SUCCESS
: STATUS_MEMORY_NOT_ALLOCATED;
return c.win_emu.memory.release_memory(allocation_base, allocation_size) ? STATUS_SUCCESS
: STATUS_MEMORY_NOT_ALLOCATED;
}
if (free_type & MEM_DECOMMIT)
{
return c.win_emu.memory().decommit_memory(allocation_base, allocation_size) ? STATUS_SUCCESS
: STATUS_MEMORY_NOT_ALLOCATED;
return c.win_emu.memory.decommit_memory(allocation_base, allocation_size) ? STATUS_SUCCESS
: STATUS_MEMORY_NOT_ALLOCATED;
}
throw std::runtime_error("Bad free type");
@@ -2261,7 +2260,7 @@ namespace
}
client_shared_memory.access([&](PORT_VIEW64& view) {
p.view_base = c.win_emu.memory().allocate_memory(view.ViewSize, memory_permission::read_write);
p.view_base = c.win_emu.memory.allocate_memory(view.ViewSize, memory_permission::read_write);
view.ViewBase = p.view_base;
view.ViewRemoteBase = view.ViewBase;
});
@@ -2746,14 +2745,14 @@ namespace
const emulator_object<LARGE_INTEGER> /*default_casing_table_size*/)
{
const auto locale_file =
utils::io::read_file(c.win_emu.file_sys().translate(R"(C:\Windows\System32\locale.nls)"));
utils::io::read_file(c.win_emu.file_sys.translate(R"(C:\Windows\System32\locale.nls)"));
if (locale_file.empty())
{
return STATUS_FILE_INVALID;
}
const auto size = page_align_up(locale_file.size());
const auto base = c.win_emu.memory().allocate_memory(size, memory_permission::read);
const auto base = c.win_emu.memory.allocate_memory(size, memory_permission::read);
c.emu.write_memory(base, locale_file.data(), locale_file.size());
base_address.write(base);
@@ -2879,7 +2878,7 @@ namespace
io_status_block.write(block);
}
c.win_emu.callbacks().stdout_callback(temp_buffer);
c.win_emu.callbacks.stdout_callback(temp_buffer);
if (!temp_buffer.ends_with("\n"))
{
@@ -3048,14 +3047,14 @@ namespace
if (create_disposition & FILE_CREATE)
{
std::error_code ec{};
create_directory(c.win_emu.file_sys().translate(f.name), ec);
create_directory(c.win_emu.file_sys.translate(f.name), ec);
if (ec)
{
return STATUS_ACCESS_DENIED;
}
}
else if (!std::filesystem::is_directory(c.win_emu.file_sys().translate(f.name)))
else if (!std::filesystem::is_directory(c.win_emu.file_sys.translate(f.name)))
{
return STATUS_OBJECT_NAME_NOT_FOUND;
}
@@ -3078,7 +3077,7 @@ namespace
FILE* file{};
const auto error = open_unicode(&file, c.win_emu.file_sys().translate(path), mode);
const auto error = open_unicode(&file, c.win_emu.file_sys.translate(path), mode);
if (!file)
{
@@ -3123,7 +3122,7 @@ namespace
c.win_emu.log.print(color::dark_gray, "--> Querying file attributes: %s\n", u16_to_u8(filename).c_str());
const auto local_filename = c.win_emu.file_sys().translate(filename).string();
const auto local_filename = c.win_emu.file_sys.translate(filename).string();
struct _stat64 file_stat{};
if (_stat64(local_filename.c_str(), &file_stat) != 0)
@@ -3446,7 +3445,7 @@ namespace
return STATUS_NOT_SUPPORTED;
}
const auto h = c.proc.create_thread(c.win_emu.memory(), start_routine, argument, stack_size);
const auto h = c.proc.create_thread(c.win_emu.memory, start_routine, argument, stack_size);
thread_handle.write(h);
if (!attribute_list)

View File

@@ -213,15 +213,14 @@ namespace
const emulator_settings& emu_settings)
{
auto& emu = win_emu.emu();
auto& context = win_emu.process();
auto& memory = win_emu.memory();
auto& context = win_emu.process;
auto& memory = win_emu.memory;
setup_gdt(emu, memory);
// TODO: Move that out
context.registry =
registry_manager(win_emu.get_emulation_root().empty() ? emu_settings.registry_directory
: win_emu.get_emulation_root() / "registry");
context.registry = registry_manager(win_emu.emulation_root.empty() ? emu_settings.registry_directory
: win_emu.emulation_root / "registry");
context.kusd.setup(emu_settings.use_relative_time);
@@ -285,7 +284,7 @@ namespace
apiset_location apiset_loc = apiset_location::file;
if (win_emu.get_emulation_root().empty())
if (win_emu.emulation_root.empty())
{
#ifdef OS_WINDOWS
apiset_loc = apiset_location::host;
@@ -297,7 +296,7 @@ namespace
context.peb.access([&](PEB64& peb) {
peb.ImageBaseAddress = nullptr;
peb.ProcessParameters = context.process_params.ptr();
peb.ApiSetMap = build_api_set_map(emu, allocator, apiset_loc, win_emu.get_emulation_root()).ptr();
peb.ApiSetMap = build_api_set_map(emu, allocator, apiset_loc, win_emu.emulation_root).ptr();
peb.ProcessHeap = nullptr;
peb.ProcessHeaps = nullptr;
@@ -320,7 +319,7 @@ namespace
void perform_context_switch_work(windows_emulator& win_emu)
{
auto& devices = win_emu.process().devices;
auto& devices = win_emu.process.devices;
// Crappy mechanism to prevent mutation while iterating.
const auto was_blocked = devices.block_mutation(true);
@@ -353,7 +352,7 @@ namespace
}
auto& emu = win_emu.emu();
auto& context = win_emu.process();
auto& context = win_emu.process;
const auto is_ready = thread.is_thread_ready(context);
@@ -385,7 +384,7 @@ namespace
bool switch_to_thread(windows_emulator& win_emu, const handle thread_handle)
{
auto* thread = win_emu.process().threads.get(thread_handle);
auto* thread = win_emu.process.threads.get(thread_handle);
if (!thread)
{
throw std::runtime_error("Bad thread handle");
@@ -398,7 +397,7 @@ namespace
{
perform_context_switch_work(win_emu);
auto& context = win_emu.process();
auto& context = win_emu.process;
bool next_thread = false;
@@ -445,7 +444,7 @@ windows_emulator::windows_emulator(application_settings app_settings, const emul
for (const auto& mapping : settings.path_mappings)
{
this->file_sys().map(mapping.first, mapping.second);
this->file_sys.map(mapping.first, mapping.second);
}
for (const auto& mapping : settings.port_mappings)
@@ -457,21 +456,22 @@ windows_emulator::windows_emulator(application_settings app_settings, const emul
this->silent_until_main_ = settings.silent_until_main && !settings.disable_logging;
this->use_relative_time_ = settings.use_relative_time;
this->log.disable_output(settings.disable_logging || this->silent_until_main_);
this->callbacks_ = std::move(callbacks);
this->callbacks = std::move(callbacks);
this->modules_ = settings.modules;
this->setup_process(app_settings, settings);
}
windows_emulator::windows_emulator(const std::filesystem::path& emulation_root, std::unique_ptr<x64_emulator> emu)
: emulation_root_{emulation_root.empty() ? emulation_root : absolute(emulation_root)},
file_sys_(emulation_root_.empty() ? emulation_root_ : emulation_root_ / "filesys"),
emu_(std::move(emu)),
memory_manager_(*this->emu_),
process_(*emu_, memory_manager_, file_sys_)
windows_emulator::windows_emulator(const std::filesystem::path& emulation_root_directory,
std::unique_ptr<x64_emulator> emu)
: emu_(std::move(emu)),
emulation_root{emulation_root_directory.empty() ? emulation_root_directory : absolute(emulation_root_directory)},
file_sys(emulation_root.empty() ? emulation_root : emulation_root / "filesys"),
memory(*this->emu_),
process(*this->emu_, memory, file_sys)
{
#ifndef OS_WINDOWS
if (this->get_emulation_root().empty())
if (this->emulation_root.empty())
{
throw std::runtime_error("Emulation root directory can not be empty!");
}
@@ -486,8 +486,8 @@ void windows_emulator::setup_process(const application_settings& app_settings, c
{
auto& emu = this->emu();
auto& context = this->process();
context.mod_manager = module_manager(this->memory(), this->file_sys()); // TODO: Cleanup module manager
auto& context = this->process;
context.mod_manager = module_manager(this->memory, this->file_sys); // TODO: Cleanup module manager
setup_context(*this, app_settings, emu_settings);
@@ -503,7 +503,7 @@ void windows_emulator::setup_process(const application_settings& app_settings, c
const auto ntdll_data = emu.read_memory(context.ntdll->image_base, context.ntdll->size_of_image);
const auto win32u_data = emu.read_memory(context.win32u->image_base, context.win32u->size_of_image);
this->dispatcher_.setup(context.ntdll->exports, ntdll_data, context.win32u->exports, win32u_data);
this->dispatcher.setup(context.ntdll->exports, ntdll_data, context.win32u->exports, win32u_data);
context.ldr_initialize_thunk = context.ntdll->find_export("LdrInitializeThunk");
context.rtl_user_thread_start = context.ntdll->find_export("RtlUserThreadStart");
@@ -511,7 +511,7 @@ void windows_emulator::setup_process(const application_settings& app_settings, c
context.default_register_set = emu.save_registers();
const auto main_thread_id = context.create_thread(this->memory(), context.executable->entry_point, 0, 0);
const auto main_thread_id = context.create_thread(this->memory, context.executable->entry_point, 0, 0);
switch_to_thread(*this, main_thread_id);
}
@@ -533,7 +533,7 @@ void windows_emulator::perform_thread_switch()
bool windows_emulator::activate_thread(const uint32_t id)
{
const auto thread = get_thread_by_id(this->process(), id);
const auto thread = get_thread_by_id(this->process, id);
if (!thread)
{
return false;
@@ -544,25 +544,24 @@ bool windows_emulator::activate_thread(const uint32_t id)
void windows_emulator::on_instruction_execution(const uint64_t address)
{
auto& process = this->process();
auto& thread = this->current_thread();
++process.executed_instructions;
++this->process.executed_instructions;
const auto thread_insts = ++thread.executed_instructions;
if (thread_insts % MAX_INSTRUCTIONS_PER_TIME_SLICE == 0)
{
this->yield_thread();
}
process.previous_ip = process.current_ip;
process.current_ip = this->emu().read_instruction_pointer();
this->process.previous_ip = this->process.current_ip;
this->process.current_ip = this->emu().read_instruction_pointer();
const auto binary = utils::make_lazy([&] {
return this->process().mod_manager.find_by_address(address); //
return this->process.mod_manager.find_by_address(address); //
});
const auto previous_binary = utils::make_lazy([&] {
return this->process().mod_manager.find_by_address(process.previous_ip); //
return this->process.mod_manager.find_by_address(this->process.previous_ip); //
});
const auto is_in_interesting_module = [&] {
@@ -575,9 +574,9 @@ void windows_emulator::on_instruction_execution(const uint64_t address)
(previous_binary && this->modules_.contains(previous_binary->name));
};
const auto is_main_exe = process.executable->is_within(address);
const auto is_interesting_call = process.executable->is_within(process.previous_ip) //
|| is_main_exe //
const auto is_main_exe = this->process.executable->is_within(address);
const auto is_interesting_call = process.executable->is_within(this->process.previous_ip) //
|| is_main_exe //
|| is_in_interesting_module();
if (this->silent_until_main_ && is_main_exe)
@@ -601,7 +600,7 @@ void windows_emulator::on_instruction_execution(const uint64_t address)
uint64_t return_address{};
this->emu().try_read_memory(rsp, &return_address, sizeof(return_address));
const auto* mod_name = this->process().mod_manager.find_name(return_address);
const auto* mod_name = this->process.mod_manager.find_name(return_address);
log.print(is_interesting_call ? color::yellow : color::dark_gray,
"Executing function: %s - %s (0x%" PRIx64 ") via (0x%" PRIx64 ") %s\n", binary->name.c_str(),
@@ -621,6 +620,7 @@ void windows_emulator::on_instruction_execution(const uint64_t address)
auto& emu = this->emu();
// TODO: Remove or cleanup
log.print(color::gray,
"Inst: %16" PRIx64 " - RAX: %16" PRIx64 " - RBX: %16" PRIx64 " - RCX: %16" PRIx64 " - RDX: %16" PRIx64
" - R8: %16" PRIx64 " - R9: %16" PRIx64 " - RDI: %16" PRIx64 " - RSI: %16" PRIx64 " - %s\n",
@@ -640,12 +640,12 @@ void windows_emulator::setup_hooks()
}
}
this->dispatcher_.dispatch(*this);
this->dispatcher.dispatch(*this);
return instruction_hook_continuation::skip_instruction;
});
this->emu().hook_instruction(x64_hookable_instructions::rdtsc, [&] {
const auto instructions = this->process().executed_instructions;
const auto instructions = this->process.executed_instructions;
this->emu().reg(x64_register::rax, instructions & 0xFFFFFFFF);
this->emu().reg(x64_register::rdx, (instructions >> 32) & 0xFFFFFFFF);
return instruction_hook_continuation::skip_instruction;
@@ -665,14 +665,14 @@ void windows_emulator::setup_hooks()
switch (interrupt)
{
case 0:
dispatch_integer_division_by_zero(this->emu(), this->process());
dispatch_integer_division_by_zero(this->emu(), this->process);
return;
case 1:
this->log.print(color::pink, "Singlestep: 0x%" PRIx64 "\n", rip);
dispatch_single_step(this->emu(), this->process());
dispatch_single_step(this->emu(), this->process);
return;
case 6:
dispatch_illegal_instruction_violation(this->emu(), this->process());
dispatch_illegal_instruction_violation(this->emu(), this->process);
return;
default:
break;
@@ -682,7 +682,7 @@ void windows_emulator::setup_hooks()
if (this->fuzzing || true) // TODO: Fix
{
this->process().exception_rip = rip;
this->process.exception_rip = rip;
this->emu().stop();
}
});
@@ -691,7 +691,7 @@ void windows_emulator::setup_hooks()
const memory_violation_type type) {
const auto permission = get_permission_string(operation);
const auto ip = this->emu().read_instruction_pointer();
const char* name = this->process().mod_manager.find_name(ip);
const char* name = this->process.mod_manager.find_name(ip);
if (type == memory_violation_type::protection)
{
@@ -706,12 +706,12 @@ void windows_emulator::setup_hooks()
if (this->fuzzing)
{
this->process().exception_rip = ip;
this->process.exception_rip = ip;
this->emu().stop();
return memory_violation_continuation::stop;
}
dispatch_access_violation(this->emu(), this->process(), address, operation);
dispatch_access_violation(this->emu(), this->process, address, operation);
return memory_violation_continuation::resume;
});
@@ -726,14 +726,14 @@ void windows_emulator::start(std::chrono::nanoseconds timeout, size_t count)
const auto use_timeout = timeout != std::chrono::nanoseconds{};
const auto start_time = std::chrono::high_resolution_clock::now();
const auto start_instructions = this->process().executed_instructions;
const auto start_instructions = this->process.executed_instructions;
const auto target_time = start_time + timeout;
const auto target_instructions = start_instructions + count;
while (true)
{
if (this->switch_thread_ || !this->current_thread().is_thread_ready(this->process()))
if (this->switch_thread_ || !this->current_thread().is_thread_ready(this->process))
{
this->perform_thread_switch();
}
@@ -759,7 +759,7 @@ void windows_emulator::start(std::chrono::nanoseconds timeout, size_t count)
if (use_count)
{
const auto current_instructions = this->process().executed_instructions;
const auto current_instructions = this->process.executed_instructions;
if (current_instructions >= target_instructions)
{
@@ -776,15 +776,15 @@ void windows_emulator::serialize(utils::buffer_serializer& buffer) const
buffer.write(this->switch_thread_);
buffer.write(this->use_relative_time_);
this->emu().serialize_state(buffer, false);
this->memory().serialize_memory_state(buffer, false);
this->process_.serialize(buffer);
this->dispatcher_.serialize(buffer);
this->memory.serialize_memory_state(buffer, false);
this->process.serialize(buffer);
this->dispatcher.serialize(buffer);
}
void windows_emulator::deserialize(utils::buffer_deserializer& buffer)
{
buffer.register_factory<memory_manager_wrapper>([this] {
return memory_manager_wrapper{this->memory()}; //
return memory_manager_wrapper{this->memory}; //
});
buffer.register_factory<x64_emulator_wrapper>([this] {
@@ -798,25 +798,25 @@ void windows_emulator::deserialize(utils::buffer_deserializer& buffer)
buffer.read(this->switch_thread_);
buffer.read(this->use_relative_time_);
this->memory().unmap_all_memory();
this->memory.unmap_all_memory();
this->emu().deserialize_state(buffer, false);
this->memory().deserialize_memory_state(buffer, false);
this->process_.deserialize(buffer);
this->dispatcher_.deserialize(buffer);
this->memory.deserialize_memory_state(buffer, false);
this->process.deserialize(buffer);
this->dispatcher.deserialize(buffer);
}
void windows_emulator::save_snapshot()
{
utils::buffer_serializer serializer{};
this->emu().serialize_state(serializer, true);
this->memory().serialize_memory_state(serializer, true);
this->process_.serialize(serializer);
this->memory.serialize_memory_state(serializer, true);
this->process.serialize(serializer);
this->process_snapshot_ = serializer.move_buffer();
// TODO: Make process copyable
// this->process_snapshot_ = this->process();
// this->process_snapshot_ = this->process;
}
void windows_emulator::restore_snapshot()
@@ -829,7 +829,7 @@ void windows_emulator::restore_snapshot()
utils::buffer_deserializer deserializer{this->process_snapshot_};
this->emu().deserialize_state(deserializer, true);
this->memory().deserialize_memory_state(deserializer, true);
this->process_.deserialize(deserializer);
// this->process_ = *this->process_snapshot_;
this->memory.deserialize_memory_state(deserializer, true);
this->process.deserialize(deserializer);
// this->process = *this->process_snapshot_;
}

View File

@@ -57,7 +57,17 @@ enum class apiset_location : uint8_t
class windows_emulator
{
std::unique_ptr<x64_emulator> emu_{};
public:
std::filesystem::path emulation_root{};
emulator_callbacks callbacks{};
logger log{};
file_system file_sys;
memory_manager memory;
process_context process;
syscall_dispatcher dispatcher;
windows_emulator(const std::filesystem::path& emulation_root,
std::unique_ptr<x64_emulator> emu = create_default_x64_emulator());
windows_emulator(application_settings app_settings, const emulator_settings& settings = {},
@@ -81,34 +91,14 @@ class windows_emulator
return *this->emu_;
}
process_context& process()
{
return this->process_;
}
const process_context& process() const
{
return this->process_;
}
syscall_dispatcher& dispatcher()
{
return this->dispatcher_;
}
const syscall_dispatcher& dispatcher() const
{
return this->dispatcher_;
}
emulator_thread& current_thread() const
{
if (!this->process_.active_thread)
if (!this->process.active_thread)
{
throw std::runtime_error("No active thread!");
}
return *this->process_.active_thread;
return *this->process.active_thread;
}
void start(std::chrono::nanoseconds timeout = {}, size_t count = 0);
@@ -163,7 +153,6 @@ class windows_emulator
}
}
logger log{};
bool verbose{false};
bool verbose_calls{false};
bool buffer_stdout{false};
@@ -178,57 +167,15 @@ class windows_emulator
return this->use_relative_time_;
}
emulator_callbacks& callbacks()
{
return this->callbacks_;
}
file_system& file_sys()
{
return this->file_sys_;
}
const file_system& file_sys() const
{
return this->file_sys_;
}
memory_manager& memory()
{
return this->memory_manager_;
}
const memory_manager& memory() const
{
return this->memory_manager_;
}
const std::filesystem::path& get_emulation_root()
{
return this->emulation_root_;
}
private:
std::filesystem::path emulation_root_{};
file_system file_sys_;
emulator_callbacks callbacks_{};
bool switch_thread_{false};
bool use_relative_time_{false};
bool silent_until_main_{false};
std::unique_ptr<x64_emulator> emu_{};
std::vector<instruction_hook_callback> syscall_hooks_{};
std::unordered_map<uint16_t, uint16_t> port_mappings_{};
memory_manager memory_manager_;
std::set<std::string, std::less<>> modules_{};
process_context process_;
syscall_dispatcher dispatcher_;
std::vector<std::byte> process_snapshot_{};
// std::optional<process_context> process_snapshot_{};

View File

@@ -47,7 +47,7 @@ class win_x64_gdb_stub_handler : public x64_gdb_stub_handler
std::vector<uint32_t> get_thread_ids() override
{
const auto& threads = this->win_emu_->process().threads;
const auto& threads = this->win_emu_->process.threads;
std::vector<uint32_t> ids{};
ids.reserve(threads.size());
@@ -70,7 +70,7 @@ class win_x64_gdb_stub_handler : public x64_gdb_stub_handler
std::optional<uint32_t> get_exit_code() override
{
const auto status = this->win_emu_->process().exit_status;
const auto status = this->win_emu_->process.exit_status;
if (!status)
{
return std::nullopt;