diff --git a/src/analyzer/analysis.cpp b/src/analyzer/analysis.cpp index 7c00b0ad..0e2b8f33 100644 --- a/src/analyzer/analysis.cpp +++ b/src/analyzer/analysis.cpp @@ -2,7 +2,11 @@ #include "analysis.hpp" #include "windows_emulator.hpp" -#include "utils/lazy_object.hpp" +#include + +#ifdef OS_EMSCRIPTEN +#include +#endif #define STR_VIEW_VA(str) static_cast((str).size()), (str).data() @@ -31,6 +35,34 @@ namespace c.win_emu->log.print(color::pink, "Suspicious: %.*s (0x%" PRIx64 ")\n", STR_VIEW_VA(details), rip); } + void handle_generic_activity(const analysis_context& c, const std::string_view details) + { + c.win_emu->log.print(color::dark_gray, "%.*s\n", STR_VIEW_VA(details)); + } + + void handle_generic_access(const analysis_context& c, const std::string_view type, const std::u16string_view name) + { + c.win_emu->log.print(color::dark_gray, "--> %.*s: %s\n", STR_VIEW_VA(type), u16_to_u8(name).c_str()); // + } + + void handle_ioctrl(const analysis_context& c, const io_device&, const std::u16string_view device_name, + const ULONG code) + { + c.win_emu->log.print(color::dark_gray, "--> %s: 0x%X\n", u16_to_u8(device_name).c_str(), + static_cast(code)); + } + + void handle_thread_switch(const analysis_context& c, const emulator_thread& current_thread, + const emulator_thread& new_thread) + { + c.win_emu->log.print(color::dark_gray, "Performing thread switch: %X -> %X\n", current_thread.id, + new_thread.id); + +#ifdef OS_EMSCRIPTEN + debugger::event_context ec{.win_emu = *c.win_emu}; + debugger::handle_events(ec); +#endif + } void handle_instruction(analysis_context& c, const uint64_t address) { auto& win_emu = *c.win_emu; @@ -167,6 +199,10 @@ void register_analysis_callbacks(analysis_context& c) cb.on_stdout = make_callback(c, handle_stdout); cb.on_syscall = make_callback(c, handle_syscall); + cb.on_ioctrl = make_callback(c, handle_ioctrl); cb.on_instruction = make_callback(c, handle_instruction); + cb.on_thread_switch = make_callback(c, handle_thread_switch); + cb.on_generic_access = make_callback(c, handle_generic_access); + cb.on_generic_activity = make_callback(c, handle_generic_activity); cb.on_suspicious_activity = make_callback(c, handle_suspicious_activity); } diff --git a/src/analyzer/main.cpp b/src/analyzer/main.cpp index 3e8de362..88b3b08d 100644 --- a/src/analyzer/main.cpp +++ b/src/analyzer/main.cpp @@ -8,10 +8,6 @@ #include "snapshot.hpp" #include "analysis.hpp" -#ifdef OS_EMSCRIPTEN -#include -#endif - #include #include @@ -268,14 +264,6 @@ namespace win_emu->log.disable_output(options.concise_logging || options.silent); context.win_emu = win_emu.get(); - // TODO: Move to analysis -#ifdef OS_EMSCRIPTEN - win_emu->callbacks.on_thread_switch = [&] { - debugger::event_context c{.win_emu = *win_emu}; - debugger::handle_events(c); // - }; -#endif - win_emu->log.log("Using emulator: %s\n", win_emu->emu().get_name().c_str()); register_analysis_callbacks(context); diff --git a/src/windows-emulator/devices/afd_endpoint.cpp b/src/windows-emulator/devices/afd_endpoint.cpp index d067eb1a..72adae17 100644 --- a/src/windows-emulator/devices/afd_endpoint.cpp +++ b/src/windows-emulator/devices/afd_endpoint.cpp @@ -525,9 +525,6 @@ namespace const auto request = _AFD_REQUEST(c.io_control_code); - win_emu.log.print(color::dark_gray, "--> AFD IOCTL: 0x%X (%u)\n", static_cast(c.io_control_code), - static_cast(request)); - switch (request) { case AFD_BIND: diff --git a/src/windows-emulator/devices/security_support_provider.cpp b/src/windows-emulator/devices/security_support_provider.cpp index f3de5cb5..58b2a9f6 100644 --- a/src/windows-emulator/devices/security_support_provider.cpp +++ b/src/windows-emulator/devices/security_support_provider.cpp @@ -26,8 +26,6 @@ namespace NTSTATUS io_control(windows_emulator& win_emu, const io_device_context& c) override { - win_emu.log.print(color::dark_gray, "--> KSEC IOCTL: 0x%X\n", static_cast(c.io_control_code)); - if (c.io_control_code != 0x390400) { return STATUS_NOT_SUPPORTED; diff --git a/src/windows-emulator/io_device.cpp b/src/windows-emulator/io_device.cpp index b1803824..cefc0a15 100644 --- a/src/windows-emulator/io_device.cpp +++ b/src/windows-emulator/io_device.cpp @@ -1,5 +1,6 @@ #include "std_include.hpp" #include "io_device.hpp" +#include "windows_emulator.hpp" #include "devices/afd_endpoint.hpp" #include "devices/mount_point_manager.hpp" #include "devices/security_support_provider.hpp" @@ -49,3 +50,31 @@ std::unique_ptr create_device(const std::u16string_view device) throw std::runtime_error("Unsupported device: " + u16_to_u8(device)); } + +NTSTATUS io_device_container::io_control(windows_emulator& win_emu, const io_device_context& context) +{ + this->assert_validity(); + win_emu.callbacks.on_ioctrl(*this->device_, this->device_name_, context.io_control_code); + return this->device_->io_control(win_emu, context); +} + +void io_device_container::work(windows_emulator& win_emu) +{ + this->assert_validity(); + this->device_->work(win_emu); +} + +void io_device_container::serialize_object(utils::buffer_serializer& buffer) const +{ + this->assert_validity(); + + buffer.write_string(this->device_name_); + this->device_->serialize(buffer); +} + +void io_device_container::deserialize_object(utils::buffer_deserializer& buffer) +{ + buffer.read_string(this->device_name_); + this->setup(); + this->device_->deserialize(buffer); +} diff --git a/src/windows-emulator/io_device.hpp b/src/windows-emulator/io_device.hpp index 970b5053..c55ca84d 100644 --- a/src/windows-emulator/io_device.hpp +++ b/src/windows-emulator/io_device.hpp @@ -146,32 +146,11 @@ class io_device_container : public io_device this->device_->create(win_emu, data); } - NTSTATUS io_control(windows_emulator& win_emu, const io_device_context& context) override - { - this->assert_validity(); - return this->device_->io_control(win_emu, context); - } + void work(windows_emulator& win_emu) override; + NTSTATUS io_control(windows_emulator& win_emu, const io_device_context& context) override; - void work(windows_emulator& win_emu) override - { - this->assert_validity(); - this->device_->work(win_emu); - } - - void serialize_object(utils::buffer_serializer& buffer) const override - { - this->assert_validity(); - - buffer.write_string(this->device_name_); - this->device_->serialize(buffer); - } - - void deserialize_object(utils::buffer_deserializer& buffer) override - { - buffer.read_string(this->device_name_); - this->setup(); - this->device_->deserialize(buffer); - } + void serialize_object(utils::buffer_serializer& buffer) const override; + void deserialize_object(utils::buffer_deserializer& buffer) override; template requires(std::is_base_of_v || std::is_same_v) diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 6fad5508..2a718257 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -34,7 +34,7 @@ struct process_context { utils::optional_function on_create_thread{}; utils::optional_function on_thread_terminated{}; - utils::optional_function on_thread_switch{}; + utils::optional_function on_thread_switch{}; }; struct atom_entry diff --git a/src/windows-emulator/registry/registry_manager.hpp b/src/windows-emulator/registry/registry_manager.hpp index 809713aa..81e0cb79 100644 --- a/src/windows-emulator/registry/registry_manager.hpp +++ b/src/windows-emulator/registry/registry_manager.hpp @@ -40,6 +40,11 @@ struct registry_key : ref_counted_object buffer.read(this->hive); buffer.read(this->path); } + + std::u16string to_string() const + { + return this->hive.get().u16string() + u"\\" + this->path.get().u16string(); + } }; struct registry_value diff --git a/src/windows-emulator/syscalls/event.cpp b/src/windows-emulator/syscalls/event.cpp index b53c0910..40b7a8a7 100644 --- a/src/windows-emulator/syscalls/event.cpp +++ b/src/windows-emulator/syscalls/event.cpp @@ -63,7 +63,7 @@ namespace syscalls if (attributes.ObjectName) { name = read_unicode_string(c.emu, attributes.ObjectName); - c.win_emu.log.print(color::dark_gray, "--> Event name: %s\n", u16_to_u8(name).c_str()); + c.win_emu.callbacks.on_generic_access("Opening event", name); } } @@ -100,7 +100,7 @@ namespace syscalls { const auto attributes = object_attributes.read(); const auto name = read_unicode_string(c.emu, attributes.ObjectName); - c.win_emu.log.print(color::dark_gray, "--> Event name: %s\n", u16_to_u8(name).c_str()); + c.win_emu.callbacks.on_generic_access("Opening event", name); if (name == u"\\KernelObjects\\SystemErrorPortReady") { diff --git a/src/windows-emulator/syscalls/file.cpp b/src/windows-emulator/syscalls/file.cpp index a44fdff7..0d9abfd2 100644 --- a/src/windows-emulator/syscalls/file.cpp +++ b/src/windows-emulator/syscalls/file.cpp @@ -236,16 +236,7 @@ namespace syscalls if (!f->enumeration_state || query_flags & SL_RESTART_SCAN) { const auto mask = file_mask ? read_unicode_string(c.emu, file_mask) : u""; - - if (!mask.empty()) - { - c.win_emu.log.print(color::dark_gray, "--> Enumerating directory: %s (Mask: \"%s\")\n", - u16_to_u8(f->name).c_str(), u16_to_u8(mask).c_str()); - } - else - { - c.win_emu.log.print(color::dark_gray, "--> Enumerating directory: %s\n", u16_to_u8(f->name).c_str()); - } + c.win_emu.callbacks.on_generic_access("Enumerating directory", f->name); f->enumeration_state.emplace(file_enumeration_state{}); f->enumeration_state->files = scan_directory(c.win_emu.file_sys, f->name, mask); @@ -565,7 +556,7 @@ namespace syscalls const auto attributes = object_attributes.read(); auto filename = read_unicode_string(c.emu, attributes.ObjectName); - c.win_emu.log.print(color::dark_gray, "--> Query file info: %s\n", u16_to_u8(filename).c_str()); // + c.win_emu.callbacks.on_generic_access("Query file info", filename); const auto ret = [&](const NTSTATUS status) { block.Status = status; @@ -798,7 +789,7 @@ namespace syscalls auto filename = read_unicode_string(c.emu, attributes.ObjectName); auto printer = utils::finally([&] { - c.win_emu.log.print(color::dark_gray, "--> Opening file: %s\n", u16_to_u8(filename).c_str()); // + c.win_emu.callbacks.on_generic_access("Opening file", filename); // }); const auto io_device_name = get_io_device_name(filename); @@ -849,7 +840,7 @@ namespace syscalls if (is_directory || create_options & FILE_DIRECTORY_FILE) { - c.win_emu.log.print(color::dark_gray, "--> Opening folder: %s\n", u16_to_u8(f.name).c_str()); + c.win_emu.callbacks.on_generic_access("Opening folder", f.name); if (create_disposition & FILE_CREATE) { @@ -871,7 +862,7 @@ namespace syscalls return STATUS_SUCCESS; } - c.win_emu.log.print(color::dark_gray, "--> Opening file: %s\n", u16_to_u8(f.name).c_str()); + c.win_emu.callbacks.on_generic_access("Opening file", f.name); std::u16string mode = map_mode(desired_access, create_disposition); @@ -924,7 +915,7 @@ namespace syscalls filename = root->name + (has_separator ? u"" : u"\\") + filename; } - c.win_emu.log.print(color::dark_gray, "--> Querying file attributes: %s\n", u16_to_u8(filename).c_str()); + c.win_emu.callbacks.on_generic_access("Querying file attributes", filename); const auto local_filename = c.win_emu.file_sys.translate(filename).u8string(); @@ -965,7 +956,7 @@ namespace syscalls const auto filename = read_unicode_string( c.emu, emulator_object>>{c.emu, attributes.ObjectName}); - c.win_emu.log.print(color::dark_gray, "--> Querying file attributes: %s\n", u16_to_u8(filename).c_str()); + c.win_emu.callbacks.on_generic_access("Querying file attributes", filename); const auto local_filename = c.win_emu.file_sys.translate(filename).u8string(); diff --git a/src/windows-emulator/syscalls/memory.cpp b/src/windows-emulator/syscalls/memory.cpp index be5af2fb..5df89aef 100644 --- a/src/windows-emulator/syscalls/memory.cpp +++ b/src/windows-emulator/syscalls/memory.cpp @@ -192,8 +192,6 @@ namespace syscalls if (!potential_base) { - c.win_emu.log.print(color::dark_gray, "--> Not allocated\n"); - return STATUS_MEMORY_NOT_ALLOCATED; } diff --git a/src/windows-emulator/syscalls/mutant.cpp b/src/windows-emulator/syscalls/mutant.cpp index 1adb21d2..306c3474 100644 --- a/src/windows-emulator/syscalls/mutant.cpp +++ b/src/windows-emulator/syscalls/mutant.cpp @@ -44,7 +44,7 @@ namespace syscalls { name = read_unicode_string( c.emu, emulator_object>>{c.emu, attributes.ObjectName}); - c.win_emu.log.print(color::dark_gray, "--> Mutant name: %s\n", u16_to_u8(name).c_str()); + c.win_emu.callbacks.on_generic_access("Opening mutant", name); } } @@ -78,7 +78,7 @@ namespace syscalls if (attributes.ObjectName) { name = read_unicode_string(c.emu, attributes.ObjectName); - c.win_emu.log.print(color::dark_gray, "--> Mutant name: %s\n", u16_to_u8(name).c_str()); + c.win_emu.callbacks.on_generic_access("Opening mutant", name); } } diff --git a/src/windows-emulator/syscalls/port.cpp b/src/windows-emulator/syscalls/port.cpp index 50072d50..46fa7a03 100644 --- a/src/windows-emulator/syscalls/port.cpp +++ b/src/windows-emulator/syscalls/port.cpp @@ -14,7 +14,7 @@ namespace syscalls const emulator_object connection_info_length) { auto port_name = read_unicode_string(c.emu, server_port_name); - c.win_emu.log.print(color::dark_gray, "NtConnectPort: %s\n", u16_to_u8(port_name).c_str()); + c.win_emu.callbacks.on_generic_access("Connecting port", port_name); port p{}; p.name = std::move(port_name); diff --git a/src/windows-emulator/syscalls/registry.cpp b/src/windows-emulator/syscalls/registry.cpp index 96017a30..7ec1c034 100644 --- a/src/windows-emulator/syscalls/registry.cpp +++ b/src/windows-emulator/syscalls/registry.cpp @@ -25,7 +25,7 @@ namespace syscalls key = full_path.u16string(); } - c.win_emu.log.print(color::dark_gray, "--> Registry key: %s\n", u16_to_u8(key).c_str()); + c.win_emu.callbacks.on_generic_access("Registry key", key); auto entry = c.win_emu.registry.get_key({key}); if (!entry.has_value()) @@ -129,8 +129,12 @@ namespace syscalls } const auto query_name = read_unicode_string(c.emu, value_name); - c.win_emu.log.print(color::dark_gray, "--> Query value key: %s (%s\\%s)\n", u16_to_u8(query_name).c_str(), - key->hive.get().string().c_str(), key->path.get().string().c_str()); + + if (c.win_emu.callbacks.on_generic_access) + { + // TODO: Find a better way to log this + c.win_emu.callbacks.on_generic_access("Querying value key", query_name + u" (" + key->to_string() + u")"); + } const auto value = c.win_emu.registry.get_value(*key, u16_to_u8(query_name)); if (!value) diff --git a/src/windows-emulator/syscalls/section.cpp b/src/windows-emulator/syscalls/section.cpp index 27f3cb2e..47ba9633 100644 --- a/src/windows-emulator/syscalls/section.cpp +++ b/src/windows-emulator/syscalls/section.cpp @@ -20,7 +20,7 @@ namespace syscalls const auto* file = c.proc.files.get(file_handle); if (file) { - c.win_emu.log.print(color::dark_gray, "--> Section for file %s\n", u16_to_u8(file->name).c_str()); + c.win_emu.callbacks.on_generic_access("Section for file", file->name); s.file_name = file->name; } @@ -30,7 +30,7 @@ namespace syscalls if (attributes.ObjectName) { auto name = read_unicode_string(c.emu, attributes.ObjectName); - c.win_emu.log.print(color::dark_gray, "--> Section with name %s\n", u16_to_u8(name).c_str()); + c.win_emu.callbacks.on_generic_access("Section with name", name); s.name = std::move(name); } } @@ -60,7 +60,7 @@ namespace syscalls const auto attributes = object_attributes.read(); auto filename = read_unicode_string(c.emu, attributes.ObjectName); - c.win_emu.log.print(color::dark_gray, "--> Opening section: %s\n", u16_to_u8(filename).c_str()); + c.win_emu.callbacks.on_generic_access("Opening section", filename); if (filename == u"\\Windows\\SharedSection") { diff --git a/src/windows-emulator/syscalls/timer.cpp b/src/windows-emulator/syscalls/timer.cpp index a154e27f..cc320fa1 100644 --- a/src/windows-emulator/syscalls/timer.cpp +++ b/src/windows-emulator/syscalls/timer.cpp @@ -43,7 +43,7 @@ namespace syscalls if (attributes.ObjectName) { name = read_unicode_string(c.emu, attributes.ObjectName); - c.win_emu.log.print(color::dark_gray, "--> Timer name: %s\n", u16_to_u8(name).c_str()); + c.win_emu.callbacks.on_generic_access("Opening timer", name); } } diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 79cc0664..9c43e9ce 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -107,7 +107,7 @@ namespace return; } - win_emu.log.print(color::dark_gray, "Dispatching APC...\n"); + win_emu.callbacks.on_generic_activity("APC Dispatch"); const auto next_apx = apcs.front(); apcs.erase(apcs.begin()); @@ -165,8 +165,7 @@ namespace { if (active_thread) { - win_emu.log.print(color::dark_gray, "Performing thread switch: %X -> %X\n", active_thread->id, - thread.id); + win_emu.callbacks.on_thread_switch(*active_thread, thread); active_thread->save(emu); } @@ -184,7 +183,6 @@ namespace } thread.apc_alertable = false; - win_emu.callbacks.on_thread_switch(); return true; } diff --git a/src/windows-emulator/windows_emulator.hpp b/src/windows-emulator/windows_emulator.hpp index 50141ad7..d7373d40 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -13,14 +13,19 @@ #include "module/module_manager.hpp" #include "network/socket_factory.hpp" +struct io_device; + struct emulator_callbacks : module_manager::callbacks, process_context::callbacks { using continuation = instruction_hook_continuation; utils::optional_function on_syscall{}; utils::optional_function on_stdout{}; + utils::optional_function on_generic_access{}; + utils::optional_function on_generic_activity{}; utils::optional_function on_suspicious_activity{}; utils::optional_function on_instruction{}; + utils::optional_function on_ioctrl{}; }; struct application_settings