mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-11 16:46:16 +00:00
Move more logging into callbacks
This commit is contained in:
@@ -2,7 +2,11 @@
|
||||
|
||||
#include "analysis.hpp"
|
||||
#include "windows_emulator.hpp"
|
||||
#include "utils/lazy_object.hpp"
|
||||
#include <utils/lazy_object.hpp>
|
||||
|
||||
#ifdef OS_EMSCRIPTEN
|
||||
#include <event_handler.hpp>
|
||||
#endif
|
||||
|
||||
#define STR_VIEW_VA(str) static_cast<int>((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<uint32_t>(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);
|
||||
}
|
||||
|
||||
@@ -8,10 +8,6 @@
|
||||
#include "snapshot.hpp"
|
||||
#include "analysis.hpp"
|
||||
|
||||
#ifdef OS_EMSCRIPTEN
|
||||
#include <event_handler.hpp>
|
||||
#endif
|
||||
|
||||
#include <utils/interupt_handler.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
@@ -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);
|
||||
|
||||
@@ -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<uint32_t>(c.io_control_code),
|
||||
static_cast<uint32_t>(request));
|
||||
|
||||
switch (request)
|
||||
{
|
||||
case AFD_BIND:
|
||||
|
||||
@@ -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<uint32_t>(c.io_control_code));
|
||||
|
||||
if (c.io_control_code != 0x390400)
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
|
||||
@@ -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<io_device> 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);
|
||||
}
|
||||
|
||||
@@ -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 <typename T = io_device>
|
||||
requires(std::is_base_of_v<io_device, T> || std::is_same_v<io_device, T>)
|
||||
|
||||
@@ -34,7 +34,7 @@ struct process_context
|
||||
{
|
||||
utils::optional_function<void(handle h, emulator_thread& thr)> on_create_thread{};
|
||||
utils::optional_function<void(handle h, emulator_thread& thr)> on_thread_terminated{};
|
||||
utils::optional_function<void()> on_thread_switch{};
|
||||
utils::optional_function<void(emulator_thread& current_thread, emulator_thread& new_thread)> on_thread_switch{};
|
||||
};
|
||||
|
||||
struct atom_entry
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
{
|
||||
|
||||
@@ -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<UNICODE_STRING<EmulatorTraits<Emu64>>>{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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace syscalls
|
||||
{
|
||||
name = read_unicode_string(
|
||||
c.emu, emulator_object<UNICODE_STRING<EmulatorTraits<Emu64>>>{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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace syscalls
|
||||
const emulator_object<ULONG> 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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<continuation(uint32_t syscall_id, std::string_view syscall_name)> on_syscall{};
|
||||
utils::optional_function<void(std::string_view data)> on_stdout{};
|
||||
utils::optional_function<void(std::string_view type, std::u16string_view name)> on_generic_access{};
|
||||
utils::optional_function<void(std::string_view description)> on_generic_activity{};
|
||||
utils::optional_function<void(std::string_view description)> on_suspicious_activity{};
|
||||
utils::optional_function<void(uint64_t address)> on_instruction{};
|
||||
utils::optional_function<void(io_device& device, std::u16string_view device_name, ULONG code)> on_ioctrl{};
|
||||
};
|
||||
|
||||
struct application_settings
|
||||
|
||||
Reference in New Issue
Block a user