Fix thread serialization

This commit is contained in:
momo5502
2024-10-24 19:41:37 +02:00
parent ec3861f595
commit 8bac2ba407
4 changed files with 132 additions and 8 deletions

View File

@@ -6,6 +6,7 @@
#include <stdexcept>
#include <cstring>
#include <optional>
#include <functional>
namespace utils
{
@@ -162,6 +163,21 @@ namespace utils
}
}
template <typename T, typename F>
requires(std::is_invocable_r_v<T, F>)
void read_optional(std::optional<T>& val, const F& constructor)
{
if (this->read<bool>())
{
val.emplace(constructor());
this->read<T>(*val);
}
else
{
val = {};
}
}
template <typename T>
void read_vector(std::vector<T>& result)
{

View File

@@ -14,7 +14,7 @@ namespace
try
{
win_emu.logger.disable_output(true);
win_emu.emu().start_from_ip();
win_emu.start();
if (win_emu.process().exception_rip.has_value())
{

View File

@@ -4,6 +4,7 @@ struct handle_types
{
enum type : uint16_t
{
invalid = 0,
file,
event,
section,
@@ -35,6 +36,16 @@ union handle
HANDLE h;
};
inline void serialize(utils::buffer_serializer& buffer, const handle& h)
{
buffer.write(h.bits);
}
inline void deserialize(utils::buffer_deserializer& buffer, handle& h)
{
buffer.read(h.bits);
}
inline bool operator==(const handle& h1, const handle& h2)
{
return h1.bits == h2.bits;
@@ -88,7 +99,8 @@ template <handle_types::type Type, typename T>
class handle_store
{
public:
using value_map = std::map<uint32_t, T>;
using index_type = uint32_t;
using value_map = std::map<index_type, T>;
handle store(T value)
{
@@ -98,7 +110,7 @@ public:
return make_handle(index);
}
handle make_handle(const uint32_t index)
handle make_handle(const index_type index) const
{
handle h{};
h.bits = 0;
@@ -109,6 +121,11 @@ public:
return h;
}
T* get_by_index(const uint32_t index)
{
return this->get(this->make_handle(index));
}
T* get(const handle_value h)
{
const auto entry = this->get_iterator(h);
@@ -220,6 +237,27 @@ public:
return i;
}
handle find_handle(const T& value) const
{
const auto entry = this->find(value);
if (entry == this->end())
{
return {};
}
return this->make_handle(entry->first);
}
handle find_handle(const T* value) const
{
if (!value)
{
return {};
}
return this->find_handle(*value);
}
typename value_map::iterator begin()
{
return this->store_.begin();

View File

@@ -23,6 +23,20 @@
#define GDT_LIMIT 0x1000
#define GDT_ENTRY_SIZE 0x8
inline void serialize(utils::buffer_serializer& buffer, const std::chrono::steady_clock::time_point& tp)
{
buffer.write(tp.time_since_epoch().count());
}
inline void deserialize(utils::buffer_deserializer& buffer, std::chrono::steady_clock::time_point& tp)
{
using time_point = std::chrono::steady_clock::time_point;
using duration = time_point::duration;
const auto count = buffer.read<duration::rep>();
tp = time_point{duration{count}};
}
struct ref_counted_object
{
uint32_t ref_count{1};
@@ -269,14 +283,54 @@ public:
}
}
void serialize(utils::buffer_serializer&) const
void serialize(utils::buffer_serializer& buffer) const
{
// TODO
buffer.write(this->stack_base);
buffer.write(this->stack_size);
buffer.write(this->start_address);
buffer.write(this->argument);
buffer.write(this->executed_instructions);
buffer.write(this->id);
buffer.write_string(this->name);
buffer.write_optional(this->exit_status);
buffer.write_optional(this->await_object);
buffer.write(this->waiting_for_alert);
buffer.write(this->alerted);
buffer.write_optional(this->await_time);
buffer.write_optional(this->pending_status);
buffer.write_optional(this->gs_segment);
buffer.write_optional(this->teb);
buffer.write_vector(this->last_registers);
}
void deserialize(utils::buffer_deserializer&)
void deserialize(utils::buffer_deserializer& buffer)
{
// TODO
buffer.read(this->stack_base);
buffer.read(this->stack_size);
buffer.read(this->start_address);
buffer.read(this->argument);
buffer.read(this->executed_instructions);
buffer.read(this->id);
buffer.read_string(this->name);
buffer.read_optional(this->exit_status);
buffer.read_optional(this->await_object);
buffer.read(this->waiting_for_alert);
buffer.read(this->alerted);
buffer.read_optional(this->await_time);
buffer.read_optional(this->pending_status);
buffer.read_optional(this->gs_segment, [this] { return emulator_allocator(*this->emu_ptr); });
buffer.read_optional(this->teb, [this] { return emulator_object<TEB>(*this->emu_ptr); });
buffer.read_vector(this->last_registers);
}
private:
@@ -336,6 +390,7 @@ struct process_context
buffer.write(this->current_ip);
buffer.write(this->previous_ip);
buffer.write_optional(this->exception_rip);
buffer.write(this->base_allocator);
buffer.write(this->peb);
buffer.write(this->process_params);
buffer.write(this->kusd);
@@ -345,6 +400,8 @@ struct process_context
buffer.write(this->ntdll->image_base);
buffer.write(this->win32u->image_base);
buffer.write(this->ldr_initialize_thunk);
buffer.write(this->rtl_user_thread_start);
buffer.write(this->ki_user_exception_dispatcher);
buffer.write(this->shared_section_size);
@@ -354,7 +411,11 @@ struct process_context
buffer.write(this->ports);
buffer.write_map(this->atoms);
// TODO: Serialize/deserialize threads
buffer.write_vector(this->default_register_set);
buffer.write(this->current_thread_id);
buffer.write(this->threads);
buffer.write(this->threads.find_handle(this->active_thread).bits);
}
void deserialize(utils::buffer_deserializer& buffer)
@@ -363,6 +424,7 @@ struct process_context
buffer.read(this->current_ip);
buffer.read(this->previous_ip);
buffer.read_optional(this->exception_rip);
buffer.read(this->base_allocator);
buffer.read(this->peb);
buffer.read(this->process_params);
buffer.read(this->kusd);
@@ -376,6 +438,8 @@ struct process_context
this->ntdll = this->module_manager.find_by_address(ntdll_base);
this->win32u = this->module_manager.find_by_address(win32u_base);
buffer.read(this->ldr_initialize_thunk);
buffer.read(this->rtl_user_thread_start);
buffer.read(this->ki_user_exception_dispatcher);
buffer.read(this->shared_section_size);
@@ -384,6 +448,12 @@ struct process_context
buffer.read(this->semaphores);
buffer.read(this->ports);
buffer.read_map(this->atoms);
buffer.read_vector(this->default_register_set);
buffer.read(this->current_thread_id);
buffer.read(this->threads);
this->active_thread = this->threads.get(buffer.read<uint64_t>());
}
handle create_thread(x64_emulator& emu, const uint64_t start_address, const uint64_t argument,