From adf632c64ea3a9138baeb348147254c166451a28 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 10 Feb 2025 16:14:37 +0100 Subject: [PATCH] Remove getters --- src/analyzer/main.cpp | 18 +-- src/analyzer/object_watching.hpp | 4 +- src/fuzzer/main.cpp | 8 +- src/windows-emulator-test/emulation_test.cpp | 8 +- .../emulation_test_utils.hpp | 22 ++-- src/windows-emulator/devices/afd_endpoint.cpp | 4 +- src/windows-emulator/syscall_dispatcher.cpp | 12 +- src/windows-emulator/syscalls.cpp | 47 ++++--- src/windows-emulator/windows_emulator.cpp | 122 +++++++++--------- src/windows-emulator/windows_emulator.hpp | 77 ++--------- .../win_x64_gdb_stub_handler.hpp | 4 +- 11 files changed, 136 insertions(+), 190 deletions(-) diff --git a/src/analyzer/main.cpp b/src/analyzer/main.cpp index 97fe3162..37063aaf 100644 --- a/src/analyzer/main.cpp +++ b/src/analyzer/main.cpp @@ -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{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; } diff --git a/src/analyzer/object_watching.hpp b/src/analyzer/object_watching.hpp index 57bef027..a7dc3e61 100644 --- a/src/analyzer/object_watching.hpp +++ b/src/analyzer/object_watching.hpp @@ -13,8 +13,8 @@ emulator_hook* watch_object(windows_emulator& emu, const std::setname); + 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) { diff --git a/src/fuzzer/main.cpp b/src/fuzzer/main.cpp index e2769fef..a76980c0 100644 --- a/src/fuzzer/main.cpp +++ b/src/fuzzer/main.cpp @@ -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(1))), memory_permission::read_write); + const auto memory = emu.memory.allocate_memory(page_align_up(std::max(data.size(), static_cast(1))), + memory_permission::read_write); emu.emu().write_memory(memory, data.data(), data.size()); emu.emu().reg(x64_register::rcx, memory); diff --git a/src/windows-emulator-test/emulation_test.cpp b/src/windows-emulator-test/emulation_test.cpp index 9c6acd57..3a8eec32 100644 --- a/src/windows-emulator-test/emulation_test.cpp +++ b/src/windows-emulator-test/emulation_test.cpp @@ -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); } } diff --git a/src/windows-emulator-test/emulation_test_utils.hpp b/src/windows-emulator-test/emulation_test_utils.hpp index a5e1673d..c65eeba7 100644 --- a/src/windows-emulator-test/emulation_test_utils.hpp +++ b/src/windows-emulator-test/emulation_test_utils.hpp @@ -4,17 +4,17 @@ #include #include -#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)); } } diff --git a/src/windows-emulator/devices/afd_endpoint.cpp b/src/windows-emulator/devices/afd_endpoint.cpp index 46b83939..e3d38399 100644 --- a/src/windows-emulator/devices/afd_endpoint.cpp +++ b/src/windows-emulator/devices/afd_endpoint.cpp @@ -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 resolve_endpoints(windows_emulator& win_emu, const std::span handles) { - auto& proc = win_emu.process(); + auto& proc = win_emu.process; std::vector endpoints{}; endpoints.reserve(handles.size()); diff --git a/src/windows-emulator/syscall_dispatcher.cpp b/src/windows-emulator/syscall_dispatcher.cpp index 810268ce..f0c0343a 100644 --- a/src/windows-emulator/syscall_dispatcher.cpp +++ b/src/windows-emulator/syscall_dispatcher.cpp @@ -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(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() : "", - entry->second.name); + win_emu.callbacks.inline_syscall(syscall_id, address, mod ? mod->name.c_str() : "", + 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() : ""); @@ -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() : "", - entry->second.name, context.previous_ip, - previous_mod ? previous_mod->name.c_str() : ""); + win_emu.callbacks.outofline_syscall(syscall_id, address, mod ? mod->name.c_str() : "", + entry->second.name, context.previous_ip, + previous_mod ? previous_mod->name.c_str() : ""); win_emu.log.print(color::blue, "Crafted out-of-line syscall: %s (0x%X) at 0x%" PRIx64 " (%s) via 0x%" PRIx64 diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 86af4125..5fdf1aca 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -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 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 /*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) diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 1966a211..3666fa32 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -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 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 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([this] { - return memory_manager_wrapper{this->memory()}; // + return memory_manager_wrapper{this->memory}; // }); buffer.register_factory([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_; } diff --git a/src/windows-emulator/windows_emulator.hpp b/src/windows-emulator/windows_emulator.hpp index 1ef43195..3f6b3653 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -57,7 +57,17 @@ enum class apiset_location : uint8_t class windows_emulator { + std::unique_ptr 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 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 emu_{}; std::vector syscall_hooks_{}; std::unordered_map port_mappings_{}; - memory_manager memory_manager_; - std::set> modules_{}; - - process_context process_; - syscall_dispatcher dispatcher_; - std::vector process_snapshot_{}; // std::optional process_snapshot_{}; diff --git a/src/windows-gdb-stub/win_x64_gdb_stub_handler.hpp b/src/windows-gdb-stub/win_x64_gdb_stub_handler.hpp index e3855b6c..a9d00147 100644 --- a/src/windows-gdb-stub/win_x64_gdb_stub_handler.hpp +++ b/src/windows-gdb-stub/win_x64_gdb_stub_handler.hpp @@ -47,7 +47,7 @@ class win_x64_gdb_stub_handler : public x64_gdb_stub_handler std::vector get_thread_ids() override { - const auto& threads = this->win_emu_->process().threads; + const auto& threads = this->win_emu_->process.threads; std::vector ids{}; ids.reserve(threads.size()); @@ -70,7 +70,7 @@ class win_x64_gdb_stub_handler : public x64_gdb_stub_handler std::optional 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;