mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-11 16:46:16 +00:00
Move module manager into windows emulator
This commit is contained in:
@@ -154,7 +154,7 @@ namespace
|
|||||||
|
|
||||||
auto read_handler = [&, section, concise_logging](const uint64_t address, size_t, uint64_t) {
|
auto read_handler = [&, section, concise_logging](const uint64_t address, size_t, uint64_t) {
|
||||||
const auto rip = win_emu.emu().read_instruction_pointer();
|
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.mod_manager.find_by_address(rip) != win_emu.process.executable)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -174,7 +174,7 @@ namespace
|
|||||||
|
|
||||||
const auto write_handler = [&, section, concise_logging](const uint64_t address, size_t, uint64_t) {
|
const auto write_handler = [&, section, concise_logging](const uint64_t address, size_t, uint64_t) {
|
||||||
const auto rip = win_emu.emu().read_instruction_pointer();
|
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.mod_manager.find_by_address(rip) != win_emu.process.executable)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ emulator_hook* watch_object(windows_emulator& emu, const std::set<std::string, s
|
|||||||
object.value(), object.size(),
|
object.value(), object.size(),
|
||||||
[i = std::move(info), object, &emu, cache_logging, modules](const uint64_t address, size_t, uint64_t) {
|
[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 rip = emu.emu().read_instruction_pointer();
|
||||||
const auto* mod = emu.process.mod_manager.find_by_address(rip);
|
const auto* mod = emu.mod_manager.find_by_address(rip);
|
||||||
const auto is_main_access = mod == emu.process.executable || modules.contains(mod->name);
|
const auto is_main_access = mod == emu.process.executable || modules.contains(mod->name);
|
||||||
|
|
||||||
if (!emu.verbose_calls && !is_main_access)
|
if (!emu.verbose_calls && !is_main_access)
|
||||||
|
|||||||
@@ -152,6 +152,6 @@ namespace test
|
|||||||
const auto rip = emu.emu().read_instruction_pointer();
|
const auto rip = emu.emu().read_instruction_pointer();
|
||||||
|
|
||||||
printf("Diff detected after 0x%" PRIx64 " instructions at 0x%" PRIx64 " (%s)\n", lower_bound, rip,
|
printf("Diff detected after 0x%" PRIx64 " instructions at 0x%" PRIx64 " (%s)\n", lower_bound, rip,
|
||||||
emu.process.mod_manager.find_name(rip));
|
emu.mod_manager.find_name(rip));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,10 +40,12 @@ class object_wrapper
|
|||||||
};
|
};
|
||||||
|
|
||||||
class windows_emulator;
|
class windows_emulator;
|
||||||
|
class module_manager;
|
||||||
struct process_context;
|
struct process_context;
|
||||||
|
|
||||||
using x64_emulator_wrapper = object_wrapper<x64_emulator>;
|
using x64_emulator_wrapper = object_wrapper<x64_emulator>;
|
||||||
using memory_manager_wrapper = object_wrapper<memory_manager>;
|
using memory_manager_wrapper = object_wrapper<memory_manager>;
|
||||||
|
using module_manager_wrapper = object_wrapper<module_manager>;
|
||||||
using process_context_wrapper = object_wrapper<process_context>;
|
using process_context_wrapper = object_wrapper<process_context>;
|
||||||
using windows_emulator_wrapper = object_wrapper<windows_emulator>;
|
using windows_emulator_wrapper = object_wrapper<windows_emulator>;
|
||||||
|
|
||||||
|
|||||||
@@ -27,12 +27,11 @@
|
|||||||
|
|
||||||
struct process_context
|
struct process_context
|
||||||
{
|
{
|
||||||
process_context(x64_emulator& emu, memory_manager& memory, file_system& file_sys)
|
process_context(x64_emulator& emu, memory_manager& memory)
|
||||||
: base_allocator(emu),
|
: base_allocator(emu),
|
||||||
peb(emu),
|
peb(emu),
|
||||||
process_params(emu),
|
process_params(emu),
|
||||||
kusd(memory, *this),
|
kusd(memory, *this)
|
||||||
mod_manager(memory, file_sys)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,8 +48,7 @@ struct process_context
|
|||||||
emulator_object<RTL_USER_PROCESS_PARAMETERS64> process_params;
|
emulator_object<RTL_USER_PROCESS_PARAMETERS64> process_params;
|
||||||
kusd_mmio kusd;
|
kusd_mmio kusd;
|
||||||
|
|
||||||
module_manager mod_manager;
|
// TODO: Remove this
|
||||||
|
|
||||||
mapped_module* executable{};
|
mapped_module* executable{};
|
||||||
mapped_module* ntdll{};
|
mapped_module* ntdll{};
|
||||||
mapped_module* win32u{};
|
mapped_module* win32u{};
|
||||||
@@ -86,7 +84,6 @@ struct process_context
|
|||||||
buffer.write(this->peb);
|
buffer.write(this->peb);
|
||||||
buffer.write(this->process_params);
|
buffer.write(this->process_params);
|
||||||
buffer.write(this->kusd);
|
buffer.write(this->kusd);
|
||||||
buffer.write(this->mod_manager);
|
|
||||||
|
|
||||||
buffer.write(this->executable->image_base);
|
buffer.write(this->executable->image_base);
|
||||||
buffer.write(this->ntdll->image_base);
|
buffer.write(this->ntdll->image_base);
|
||||||
@@ -124,15 +121,16 @@ struct process_context
|
|||||||
buffer.read(this->peb);
|
buffer.read(this->peb);
|
||||||
buffer.read(this->process_params);
|
buffer.read(this->process_params);
|
||||||
buffer.read(this->kusd);
|
buffer.read(this->kusd);
|
||||||
buffer.read(this->mod_manager);
|
|
||||||
|
|
||||||
const auto executable_base = buffer.read<uint64_t>();
|
const auto executable_base = buffer.read<uint64_t>();
|
||||||
const auto ntdll_base = buffer.read<uint64_t>();
|
const auto ntdll_base = buffer.read<uint64_t>();
|
||||||
const auto win32u_base = buffer.read<uint64_t>();
|
const auto win32u_base = buffer.read<uint64_t>();
|
||||||
|
|
||||||
this->executable = this->mod_manager.find_by_address(executable_base);
|
auto& mod_manager = buffer.read<module_manager_wrapper>().get();
|
||||||
this->ntdll = this->mod_manager.find_by_address(ntdll_base);
|
|
||||||
this->win32u = this->mod_manager.find_by_address(win32u_base);
|
this->executable = mod_manager.find_by_address(executable_base);
|
||||||
|
this->ntdll = mod_manager.find_by_address(ntdll_base);
|
||||||
|
this->win32u = mod_manager.find_by_address(win32u_base);
|
||||||
|
|
||||||
buffer.read(this->ldr_initialize_thunk);
|
buffer.read(this->ldr_initialize_thunk);
|
||||||
buffer.read(this->rtl_user_thread_start);
|
buffer.read(this->rtl_user_thread_start);
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto* mod = context.mod_manager.find_by_address(address);
|
const auto* mod = win_emu.mod_manager.find_by_address(address);
|
||||||
if (mod != context.ntdll && mod != context.win32u)
|
if (mod != context.ntdll && mod != context.win32u)
|
||||||
{
|
{
|
||||||
win_emu.callbacks.inline_syscall(syscall_id, address, mod ? mod->name.c_str() : "<N/A>",
|
win_emu.callbacks.inline_syscall(syscall_id, address, mod ? mod->name.c_str() : "<N/A>",
|
||||||
@@ -106,7 +106,7 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
|
|||||||
uint64_t return_address{};
|
uint64_t return_address{};
|
||||||
c.emu.try_read_memory(rsp, &return_address, sizeof(return_address));
|
c.emu.try_read_memory(rsp, &return_address, sizeof(return_address));
|
||||||
|
|
||||||
const auto* mod_name = context.mod_manager.find_name(return_address);
|
const auto* mod_name = win_emu.mod_manager.find_name(return_address);
|
||||||
|
|
||||||
win_emu.log.print(color::dark_gray,
|
win_emu.log.print(color::dark_gray,
|
||||||
"Executing syscall: %s (0x%X) at 0x%" PRIx64 " via 0x%" PRIx64 " (%s)\n",
|
"Executing syscall: %s (0x%X) at 0x%" PRIx64 " via 0x%" PRIx64 " (%s)\n",
|
||||||
@@ -114,7 +114,7 @@ void syscall_dispatcher::dispatch(windows_emulator& win_emu)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const auto* previous_mod = context.mod_manager.find_by_address(context.previous_ip);
|
const auto* previous_mod = win_emu.mod_manager.find_by_address(context.previous_ip);
|
||||||
|
|
||||||
win_emu.callbacks.outofline_syscall(syscall_id, address, mod ? 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,
|
entry->second.name, context.previous_ip,
|
||||||
|
|||||||
@@ -756,7 +756,7 @@ namespace
|
|||||||
|
|
||||||
if (section_entry->is_image())
|
if (section_entry->is_image())
|
||||||
{
|
{
|
||||||
const auto binary = c.proc.mod_manager.map_module(section_entry->file_name, c.win_emu.log);
|
const auto binary = c.win_emu.mod_manager.map_module(section_entry->file_name, c.win_emu.log);
|
||||||
if (!binary)
|
if (!binary)
|
||||||
{
|
{
|
||||||
return STATUS_FILE_INVALID;
|
return STATUS_FILE_INVALID;
|
||||||
@@ -880,7 +880,7 @@ namespace
|
|||||||
return STATUS_BUFFER_OVERFLOW;
|
return STATUS_BUFFER_OVERFLOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto mod = c.proc.mod_manager.find_by_address(base_address);
|
const auto mod = c.win_emu.mod_manager.find_by_address(base_address);
|
||||||
if (!mod)
|
if (!mod)
|
||||||
{
|
{
|
||||||
c.win_emu.log.error("Bad address for memory image request: 0x%" PRIx64 "\n", base_address);
|
c.win_emu.log.error("Bad address for memory image request: 0x%" PRIx64 "\n", base_address);
|
||||||
@@ -3408,7 +3408,7 @@ namespace
|
|||||||
return STATUS_NOT_SUPPORTED;
|
return STATUS_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto* mod = c.proc.mod_manager.find_by_address(base_address);
|
const auto* mod = c.win_emu.mod_manager.find_by_address(base_address);
|
||||||
if (!mod)
|
if (!mod)
|
||||||
{
|
{
|
||||||
c.win_emu.log.error("Unmapping non-module section not supported!\n");
|
c.win_emu.log.error("Unmapping non-module section not supported!\n");
|
||||||
@@ -3416,7 +3416,7 @@ namespace
|
|||||||
return STATUS_NOT_SUPPORTED;
|
return STATUS_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.proc.mod_manager.unmap(base_address, c.win_emu.log))
|
if (c.win_emu.mod_manager.unmap(base_address, c.win_emu.log))
|
||||||
{
|
{
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -448,7 +448,8 @@ windows_emulator::windows_emulator(const emulator_settings& settings, std::uniqu
|
|||||||
file_sys(emulation_root.empty() ? emulation_root : emulation_root / "filesys"),
|
file_sys(emulation_root.empty() ? emulation_root : emulation_root / "filesys"),
|
||||||
memory(*this->emu_),
|
memory(*this->emu_),
|
||||||
registry(emulation_root.empty() ? settings.registry_directory : emulation_root / "registry"),
|
registry(emulation_root.empty() ? settings.registry_directory : emulation_root / "registry"),
|
||||||
process(*this->emu_, memory, file_sys)
|
mod_manager(memory, file_sys),
|
||||||
|
process(*this->emu_, memory)
|
||||||
{
|
{
|
||||||
#ifndef OS_WINDOWS
|
#ifndef OS_WINDOWS
|
||||||
if (this->emulation_root.empty())
|
if (this->emulation_root.empty())
|
||||||
@@ -483,18 +484,17 @@ void windows_emulator::setup_process(const application_settings& app_settings, c
|
|||||||
auto& emu = this->emu();
|
auto& emu = this->emu();
|
||||||
|
|
||||||
auto& context = this->process;
|
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);
|
setup_context(*this, app_settings, emu_settings);
|
||||||
|
|
||||||
context.executable = context.mod_manager.map_module(app_settings.application, this->log, true);
|
context.executable = this->mod_manager.map_module(app_settings.application, this->log, true);
|
||||||
|
|
||||||
context.peb.access([&](PEB64& peb) {
|
context.peb.access([&](PEB64& peb) {
|
||||||
peb.ImageBaseAddress = reinterpret_cast<std::uint64_t*>(context.executable->image_base); //
|
peb.ImageBaseAddress = reinterpret_cast<std::uint64_t*>(context.executable->image_base); //
|
||||||
});
|
});
|
||||||
|
|
||||||
context.ntdll = context.mod_manager.map_module(R"(C:\Windows\System32\ntdll.dll)", this->log, true);
|
context.ntdll = this->mod_manager.map_module(R"(C:\Windows\System32\ntdll.dll)", this->log, true);
|
||||||
context.win32u = context.mod_manager.map_module(R"(C:\Windows\System32\win32u.dll)", this->log, true);
|
context.win32u = this->mod_manager.map_module(R"(C:\Windows\System32\win32u.dll)", this->log, true);
|
||||||
|
|
||||||
const auto ntdll_data = emu.read_memory(context.ntdll->image_base, context.ntdll->size_of_image);
|
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);
|
const auto win32u_data = emu.read_memory(context.win32u->image_base, context.win32u->size_of_image);
|
||||||
@@ -553,11 +553,11 @@ void windows_emulator::on_instruction_execution(const uint64_t address)
|
|||||||
this->process.current_ip = this->emu().read_instruction_pointer();
|
this->process.current_ip = this->emu().read_instruction_pointer();
|
||||||
|
|
||||||
const auto binary = utils::make_lazy([&] {
|
const auto binary = utils::make_lazy([&] {
|
||||||
return this->process.mod_manager.find_by_address(address); //
|
return this->mod_manager.find_by_address(address); //
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto previous_binary = utils::make_lazy([&] {
|
const auto previous_binary = utils::make_lazy([&] {
|
||||||
return this->process.mod_manager.find_by_address(this->process.previous_ip); //
|
return this->mod_manager.find_by_address(this->process.previous_ip); //
|
||||||
});
|
});
|
||||||
|
|
||||||
const auto is_in_interesting_module = [&] {
|
const auto is_in_interesting_module = [&] {
|
||||||
@@ -596,7 +596,7 @@ void windows_emulator::on_instruction_execution(const uint64_t address)
|
|||||||
uint64_t return_address{};
|
uint64_t return_address{};
|
||||||
this->emu().try_read_memory(rsp, &return_address, sizeof(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->mod_manager.find_name(return_address);
|
||||||
|
|
||||||
log.print(is_interesting_call ? color::yellow : color::dark_gray,
|
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(),
|
"Executing function: %s - %s (0x%" PRIx64 ") via (0x%" PRIx64 ") %s\n", binary->name.c_str(),
|
||||||
@@ -687,7 +687,7 @@ void windows_emulator::setup_hooks()
|
|||||||
const memory_violation_type type) {
|
const memory_violation_type type) {
|
||||||
const auto permission = get_permission_string(operation);
|
const auto permission = get_permission_string(operation);
|
||||||
const auto ip = this->emu().read_instruction_pointer();
|
const auto ip = this->emu().read_instruction_pointer();
|
||||||
const char* name = this->process.mod_manager.find_name(ip);
|
const char* name = this->mod_manager.find_name(ip);
|
||||||
|
|
||||||
if (type == memory_violation_type::protection)
|
if (type == memory_violation_type::protection)
|
||||||
{
|
{
|
||||||
@@ -773,6 +773,7 @@ void windows_emulator::serialize(utils::buffer_serializer& buffer) const
|
|||||||
buffer.write(this->use_relative_time_);
|
buffer.write(this->use_relative_time_);
|
||||||
this->emu().serialize_state(buffer, false);
|
this->emu().serialize_state(buffer, false);
|
||||||
this->memory.serialize_memory_state(buffer, false);
|
this->memory.serialize_memory_state(buffer, false);
|
||||||
|
this->mod_manager.serialize(buffer);
|
||||||
this->process.serialize(buffer);
|
this->process.serialize(buffer);
|
||||||
this->dispatcher.serialize(buffer);
|
this->dispatcher.serialize(buffer);
|
||||||
}
|
}
|
||||||
@@ -783,6 +784,10 @@ void windows_emulator::deserialize(utils::buffer_deserializer& buffer)
|
|||||||
return memory_manager_wrapper{this->memory}; //
|
return memory_manager_wrapper{this->memory}; //
|
||||||
});
|
});
|
||||||
|
|
||||||
|
buffer.register_factory<module_manager_wrapper>([this] {
|
||||||
|
return module_manager_wrapper{this->mod_manager}; //
|
||||||
|
});
|
||||||
|
|
||||||
buffer.register_factory<x64_emulator_wrapper>([this] {
|
buffer.register_factory<x64_emulator_wrapper>([this] {
|
||||||
return x64_emulator_wrapper{this->emu()}; //
|
return x64_emulator_wrapper{this->emu()}; //
|
||||||
});
|
});
|
||||||
@@ -798,26 +803,30 @@ void windows_emulator::deserialize(utils::buffer_deserializer& buffer)
|
|||||||
|
|
||||||
this->emu().deserialize_state(buffer, false);
|
this->emu().deserialize_state(buffer, false);
|
||||||
this->memory.deserialize_memory_state(buffer, false);
|
this->memory.deserialize_memory_state(buffer, false);
|
||||||
|
this->mod_manager.deserialize(buffer);
|
||||||
this->process.deserialize(buffer);
|
this->process.deserialize(buffer);
|
||||||
this->dispatcher.deserialize(buffer);
|
this->dispatcher.deserialize(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void windows_emulator::save_snapshot()
|
void windows_emulator::save_snapshot()
|
||||||
{
|
{
|
||||||
utils::buffer_serializer serializer{};
|
throw std::runtime_error("Not supported");
|
||||||
|
/*utils::buffer_serializer serializer{};
|
||||||
this->emu().serialize_state(serializer, true);
|
this->emu().serialize_state(serializer, true);
|
||||||
this->memory.serialize_memory_state(serializer, true);
|
this->memory.serialize_memory_state(serializer, true);
|
||||||
|
this->mod_manager.serialize(serializer);
|
||||||
this->process.serialize(serializer);
|
this->process.serialize(serializer);
|
||||||
|
|
||||||
this->process_snapshot_ = serializer.move_buffer();
|
this->process_snapshot_ = serializer.move_buffer();
|
||||||
|
|
||||||
// TODO: Make process copyable
|
// TODO: Make process copyable
|
||||||
// this->process_snapshot_ = this->process;
|
// this->process_snapshot_ = this->process;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void windows_emulator::restore_snapshot()
|
void windows_emulator::restore_snapshot()
|
||||||
{
|
{
|
||||||
if (this->process_snapshot_.empty())
|
throw std::runtime_error("Not supported");
|
||||||
|
/*if (this->process_snapshot_.empty())
|
||||||
{
|
{
|
||||||
assert(false);
|
assert(false);
|
||||||
return;
|
return;
|
||||||
@@ -826,6 +835,7 @@ void windows_emulator::restore_snapshot()
|
|||||||
utils::buffer_deserializer deserializer{this->process_snapshot_};
|
utils::buffer_deserializer deserializer{this->process_snapshot_};
|
||||||
this->emu().deserialize_state(deserializer, true);
|
this->emu().deserialize_state(deserializer, true);
|
||||||
this->memory.deserialize_memory_state(deserializer, true);
|
this->memory.deserialize_memory_state(deserializer, true);
|
||||||
|
this->mod_manager.deserialize(deserializer);
|
||||||
this->process.deserialize(deserializer);
|
this->process.deserialize(deserializer);
|
||||||
// this->process = *this->process_snapshot_;
|
// this->process = *this->process_snapshot_;*/
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ class windows_emulator
|
|||||||
file_system file_sys;
|
file_system file_sys;
|
||||||
memory_manager memory;
|
memory_manager memory;
|
||||||
registry_manager registry{};
|
registry_manager registry{};
|
||||||
|
module_manager mod_manager;
|
||||||
process_context process;
|
process_context process;
|
||||||
syscall_dispatcher dispatcher;
|
syscall_dispatcher dispatcher;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user