mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-19 11:43:56 +00:00
Prepare thread support
This commit is contained in:
@@ -11,7 +11,7 @@ namespace
|
||||
{
|
||||
void watch_system_objects(windows_emulator& win_emu)
|
||||
{
|
||||
watch_object(win_emu, win_emu.process().teb);
|
||||
//watch_object(win_emu, *win_emu.current_thread().teb);
|
||||
watch_object(win_emu, win_emu.process().peb);
|
||||
watch_object(win_emu, win_emu.process().kusd);
|
||||
auto* params_hook = watch_object(win_emu, win_emu.process().process_params);
|
||||
@@ -86,43 +86,6 @@ namespace
|
||||
}
|
||||
});
|
||||
|
||||
win_emu.add_syscall_hook([&]
|
||||
{
|
||||
// Read syscall id and name
|
||||
|
||||
const auto syscall_id = win_emu.emu().reg(x64_register::eax);
|
||||
const auto syscall_name = win_emu.dispatcher().get_syscall_name(syscall_id);
|
||||
|
||||
|
||||
// Check if desired syscall
|
||||
|
||||
if (syscall_name != "NtQueryInformationProcess")
|
||||
{
|
||||
return instruction_hook_continuation::run_instruction;
|
||||
}
|
||||
|
||||
// Check if image file name is read
|
||||
|
||||
const auto info_class = win_emu.emu().reg(x64_register::rdx);
|
||||
if (info_class != ProcessImageFileNameWin32)
|
||||
{
|
||||
return instruction_hook_continuation::run_instruction;
|
||||
}
|
||||
|
||||
// Patch result and feed expected filename
|
||||
|
||||
win_emu.logger.print(color::pink, "Patching NtQueryInformationProcess...\n");
|
||||
|
||||
const auto data = win_emu.emu().reg(x64_register::r8);
|
||||
|
||||
emulator_allocator data_allocator{win_emu.emu(), data, 0x100};
|
||||
data_allocator.make_unicode_string(L"C:\\Users\\Maurice\\Desktop\\protected.exe");
|
||||
|
||||
win_emu.emu().reg(x64_register::rax, STATUS_SUCCESS);
|
||||
|
||||
return instruction_hook_continuation::skip_instruction;
|
||||
});
|
||||
|
||||
run_emulation(win_emu);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,6 +181,16 @@ public:
|
||||
buffer.read(this->active_address_);
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
if (this->emu_ && this->address_ && this->size_)
|
||||
{
|
||||
this->emu_->release_memory(this->address_, this->size_);
|
||||
this->address_ = 0;
|
||||
this->size_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
emulator* emu_{};
|
||||
uint64_t address_{};
|
||||
|
||||
@@ -11,6 +11,7 @@ struct handle_types
|
||||
directory,
|
||||
semaphore,
|
||||
port,
|
||||
thread,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -106,15 +106,141 @@ struct port
|
||||
}
|
||||
};
|
||||
|
||||
struct process_context;
|
||||
|
||||
class moved_marker
|
||||
{
|
||||
public:
|
||||
moved_marker() = default;
|
||||
|
||||
moved_marker(const moved_marker& copy) = default;
|
||||
moved_marker& operator=(const moved_marker&) = default;
|
||||
|
||||
moved_marker(moved_marker&& obj) noexcept
|
||||
: moved_marker()
|
||||
{
|
||||
this->operator=(std::move(obj));
|
||||
}
|
||||
|
||||
moved_marker& operator=(moved_marker&& obj) noexcept
|
||||
{
|
||||
if (this != &obj)
|
||||
{
|
||||
this->was_moved_ = obj.was_moved_;
|
||||
obj.was_moved_ = true;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~moved_marker() = default;
|
||||
|
||||
bool was_moved() const
|
||||
{
|
||||
return this->was_moved_;
|
||||
}
|
||||
|
||||
private:
|
||||
bool was_moved_{false};
|
||||
};
|
||||
|
||||
class emulator_thread
|
||||
{
|
||||
public:
|
||||
emulator_thread() = default;
|
||||
|
||||
emulator_thread(x64_emulator& emu, std::vector<std::byte> default_register_set, const uint64_t start_address,
|
||||
const uint64_t argument,
|
||||
const uint64_t stack_size)
|
||||
: emu_ptr(&emu)
|
||||
, stack_size(page_align_up(stack_size))
|
||||
, start_address(start_address)
|
||||
, argument(argument)
|
||||
, last_registers(std::move(default_register_set))
|
||||
{
|
||||
}
|
||||
|
||||
emulator_thread(const emulator_thread&) = delete;
|
||||
emulator_thread& operator=(const emulator_thread&) = delete;
|
||||
|
||||
emulator_thread(emulator_thread&& obj) noexcept = default;
|
||||
emulator_thread& operator=(emulator_thread&& obj) noexcept = default;
|
||||
|
||||
~emulator_thread()
|
||||
{
|
||||
if (marker.was_moved())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->stack_base)
|
||||
{
|
||||
this->emu_ptr->release_memory(this->stack_base, this->stack_size);
|
||||
}
|
||||
|
||||
if (this->gs_segment)
|
||||
{
|
||||
this->gs_segment->release();
|
||||
}
|
||||
}
|
||||
|
||||
moved_marker marker{};
|
||||
|
||||
x64_emulator* emu_ptr{};
|
||||
|
||||
uint32_t id{};
|
||||
|
||||
uint64_t stack_base{};
|
||||
uint64_t stack_size{};
|
||||
uint64_t start_address{};
|
||||
uint64_t argument{};
|
||||
uint64_t executed_instructions{0};
|
||||
|
||||
std::optional<emulator_allocator> gs_segment;
|
||||
std::optional<emulator_object<TEB>> teb;
|
||||
|
||||
std::vector<std::byte> last_registers{};
|
||||
|
||||
void save(x64_emulator& emu)
|
||||
{
|
||||
this->last_registers = emu.save_registers();
|
||||
}
|
||||
|
||||
void restore(x64_emulator& emu) const
|
||||
{
|
||||
emu.restore_registers(this->last_registers);
|
||||
}
|
||||
|
||||
void setup_if_necessary(x64_emulator& emu, const process_context& context)
|
||||
{
|
||||
if (!this->teb.has_value())
|
||||
{
|
||||
this->setup(emu, context);
|
||||
}
|
||||
}
|
||||
|
||||
void serialize(utils::buffer_serializer&) const
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void deserialize(utils::buffer_deserializer&)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
private:
|
||||
void setup(x64_emulator& emu, const process_context& context);
|
||||
};
|
||||
|
||||
struct process_context
|
||||
{
|
||||
process_context(x64_emulator& emu)
|
||||
: teb(emu)
|
||||
: base_allocator(emu)
|
||||
, peb(emu)
|
||||
, process_params(emu)
|
||||
, kusd(emu)
|
||||
, module_manager(emu)
|
||||
, gs_segment(emu)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -124,7 +250,8 @@ struct process_context
|
||||
|
||||
std::optional<uint64_t> exception_rip{};
|
||||
|
||||
emulator_object<TEB> teb;
|
||||
emulator_allocator base_allocator;
|
||||
|
||||
emulator_object<PEB> peb;
|
||||
emulator_object<RTL_USER_PROCESS_PARAMETERS> process_params;
|
||||
emulator_object<KUSER_SHARED_DATA> kusd;
|
||||
@@ -135,6 +262,8 @@ struct process_context
|
||||
mapped_module* ntdll{};
|
||||
mapped_module* win32u{};
|
||||
|
||||
uint64_t ldr_initialize_thunk{};
|
||||
uint64_t rtl_user_thread_start{};
|
||||
uint64_t ki_user_exception_dispatcher{};
|
||||
|
||||
uint64_t shared_section_size{};
|
||||
@@ -144,7 +273,11 @@ struct process_context
|
||||
handle_store<handle_types::semaphore, semaphore> semaphores{};
|
||||
handle_store<handle_types::port, port> ports{};
|
||||
std::map<uint16_t, std::wstring> atoms{};
|
||||
emulator_allocator gs_segment;
|
||||
|
||||
std::vector<std::byte> default_register_set{};
|
||||
|
||||
handle_store<handle_types::thread, emulator_thread> threads{};
|
||||
emulator_thread* active_thread{nullptr};
|
||||
|
||||
void serialize(utils::buffer_serializer& buffer) const
|
||||
{
|
||||
@@ -152,7 +285,6 @@ struct process_context
|
||||
buffer.write(this->current_ip);
|
||||
buffer.write(this->previous_ip);
|
||||
buffer.write_optional(this->exception_rip);
|
||||
buffer.write(this->teb);
|
||||
buffer.write(this->peb);
|
||||
buffer.write(this->process_params);
|
||||
buffer.write(this->kusd);
|
||||
@@ -170,7 +302,8 @@ struct process_context
|
||||
buffer.write(this->semaphores);
|
||||
buffer.write(this->ports);
|
||||
buffer.write_map(this->atoms);
|
||||
buffer.write(this->gs_segment);
|
||||
|
||||
// TODO: Serialize/deserialize threads
|
||||
}
|
||||
|
||||
void deserialize(utils::buffer_deserializer& buffer)
|
||||
@@ -179,7 +312,6 @@ struct process_context
|
||||
buffer.read(this->current_ip);
|
||||
buffer.read(this->previous_ip);
|
||||
buffer.read_optional(this->exception_rip);
|
||||
buffer.read(this->teb);
|
||||
buffer.read(this->peb);
|
||||
buffer.read(this->process_params);
|
||||
buffer.read(this->kusd);
|
||||
@@ -201,6 +333,16 @@ struct process_context
|
||||
buffer.read(this->semaphores);
|
||||
buffer.read(this->ports);
|
||||
buffer.read_map(this->atoms);
|
||||
buffer.read(this->gs_segment);
|
||||
}
|
||||
|
||||
handle create_thread(x64_emulator& emu, const uint64_t start_address, const uint64_t argument,
|
||||
const uint64_t stack_size)
|
||||
{
|
||||
emulator_thread t{emu, default_register_set, start_address, argument, stack_size};
|
||||
|
||||
const handle h = this->threads.store(std::move(t));
|
||||
this->threads.get(h)->id = h.value.id;
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -494,7 +494,7 @@ namespace
|
||||
const emulator_object<UNICODE_STRING> sysdir_obj{c.emu, obj_address + windir_obj.size()};
|
||||
sysdir_obj.access([&](UNICODE_STRING& ucs)
|
||||
{
|
||||
c.proc.gs_segment.make_unicode_string(ucs, L"C:\\WINDOWS\\System32");
|
||||
c.proc.base_allocator.make_unicode_string(ucs, L"C:\\WINDOWS\\System32");
|
||||
ucs.Buffer = reinterpret_cast<wchar_t*>(reinterpret_cast<uint64_t>(ucs.Buffer) - obj_address);
|
||||
});
|
||||
|
||||
@@ -1136,8 +1136,8 @@ namespace
|
||||
const emulator_object<THREAD_BASIC_INFORMATION> info{c.emu, thread_information};
|
||||
info.access([&](THREAD_BASIC_INFORMATION& i)
|
||||
{
|
||||
i.TebBaseAddress = c.proc.teb.ptr();
|
||||
i.ClientId = c.proc.teb.read().ClientId;
|
||||
i.TebBaseAddress = c.win_emu.current_thread().teb->ptr();
|
||||
i.ClientId = c.win_emu.current_thread().teb->read().ClientId;
|
||||
});
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
@@ -1556,7 +1556,7 @@ namespace
|
||||
{
|
||||
if (!peb.GdiSharedHandleTable)
|
||||
{
|
||||
peb.GdiSharedHandleTable = c.proc.gs_segment.reserve<GDI_SHARED_MEMORY>().ptr();
|
||||
peb.GdiSharedHandleTable = c.proc.base_allocator.reserve<GDI_SHARED_MEMORY>().ptr();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1881,8 +1881,8 @@ namespace
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtUnmapViewOfSection(const syscall_context& c, uint64_t process_handle, uint64_t base_address
|
||||
)
|
||||
NTSTATUS handle_NtUnmapViewOfSection(const syscall_context& c, const uint64_t process_handle,
|
||||
const uint64_t base_address)
|
||||
{
|
||||
if (process_handle != ~0ULL)
|
||||
{
|
||||
@@ -1902,6 +1902,23 @@ namespace
|
||||
c.emu.stop();
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtCreateThreadEx(const syscall_context& c, const emulator_object<uint64_t> thread_handle,
|
||||
const ACCESS_MASK /*desired_access*/,
|
||||
const emulator_object<OBJECT_ATTRIBUTES> object_attributes,
|
||||
const uint64_t process_handle, const uint64_t start_routine,
|
||||
const uint64_t argument, const ULONG create_flags, const SIZE_T zero_bits,
|
||||
const SIZE_T stack_size, const SIZE_T maximum_stack_size)
|
||||
{
|
||||
if (process_handle != ~0ULL)
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
const auto h = c.proc.create_thread(c.emu, start_routine, argument, stack_size);
|
||||
thread_handle.write(h.bits);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
void syscall_dispatcher::setup(const exported_symbols& ntdll_exports, const exported_symbols& win32u_exports)
|
||||
@@ -2000,6 +2017,7 @@ void syscall_dispatcher::add_handlers()
|
||||
add_handler(NtQueryInformationJobObject);
|
||||
add_handler(NtSetSystemInformation);
|
||||
add_handler(NtQueryInformationFile);
|
||||
add_handler(NtCreateThreadEx);
|
||||
|
||||
#undef add_handler
|
||||
|
||||
|
||||
@@ -4,13 +4,12 @@
|
||||
|
||||
#include <unicorn_x64_emulator.hpp>
|
||||
|
||||
#define GS_SEGMENT_ADDR 0x6000000ULL
|
||||
#define GS_SEGMENT_SIZE (20 << 20) // 20 MB
|
||||
#define PEB_SEGMENT_SIZE (1 << 20) // 1 MB
|
||||
|
||||
#define GS_SEGMENT_SIZE (1 << 20) // 1 MB
|
||||
|
||||
#define IA32_GS_BASE_MSR 0xC0000101
|
||||
|
||||
#define STACK_SIZE 0x40000
|
||||
#define STACK_ADDRESS (0x80000000000 - STACK_SIZE)
|
||||
#define KUSD_ADDRESS 0x7ffe0000
|
||||
|
||||
#define GDT_ADDR 0x30000
|
||||
@@ -37,15 +36,16 @@ namespace
|
||||
emu.reg(x64_register::rsp, sp);
|
||||
}
|
||||
|
||||
void setup_stack(x64_emulator& emu, const uint64_t stack_base, const size_t stack_size)
|
||||
uint64_t setup_stack(x64_emulator& emu, const size_t stack_size)
|
||||
{
|
||||
emu.allocate_memory(stack_base, stack_size, memory_permission::read_write);
|
||||
const auto stack_base = emu.allocate_memory(stack_size, memory_permission::read_write);
|
||||
|
||||
const uint64_t stack_end = stack_base + stack_size;
|
||||
emu.reg(x64_register::rsp, stack_end);
|
||||
return stack_base;
|
||||
}
|
||||
|
||||
emulator_allocator setup_gs_segment(x64_emulator& emu, const uint64_t segment_base, const uint64_t size)
|
||||
emulator_allocator setup_gs_segment(x64_emulator& emu, const uint64_t size)
|
||||
{
|
||||
struct msr_value
|
||||
{
|
||||
@@ -53,13 +53,14 @@ namespace
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
const auto segment_base = emu.allocate_memory(size, memory_permission::read_write);
|
||||
|
||||
const msr_value value{
|
||||
IA32_GS_BASE_MSR,
|
||||
segment_base
|
||||
};
|
||||
|
||||
emu.write_register(x64_register::msr, &value, sizeof(value));
|
||||
emu.allocate_memory(segment_base, size, memory_permission::read_write);
|
||||
|
||||
return {emu, segment_base, size};
|
||||
}
|
||||
@@ -174,8 +175,6 @@ namespace
|
||||
hash_entries_obj.write(hash_entry, i);
|
||||
}
|
||||
|
||||
//watch_object(emu, api_set_map_obj);
|
||||
|
||||
return api_set_map_obj;
|
||||
}
|
||||
|
||||
@@ -209,28 +208,14 @@ namespace
|
||||
void setup_context(process_context& context, x64_emulator& emu, const std::filesystem::path& file,
|
||||
const std::vector<std::wstring>& arguments)
|
||||
{
|
||||
setup_stack(emu, STACK_ADDRESS, STACK_SIZE);
|
||||
setup_gdt(emu);
|
||||
|
||||
context.kusd = setup_kusd(emu);
|
||||
context.gs_segment = setup_gs_segment(emu, GS_SEGMENT_ADDR, GS_SEGMENT_SIZE);
|
||||
|
||||
auto allocator = create_allocator(emu, 1 << 20);
|
||||
context.base_allocator = create_allocator(emu, PEB_SEGMENT_SIZE);
|
||||
auto& allocator = context.base_allocator;
|
||||
|
||||
auto& gs = context.gs_segment;
|
||||
|
||||
context.teb = gs.reserve<TEB>();
|
||||
context.peb = gs.reserve<PEB>();
|
||||
|
||||
context.teb.access([&](TEB& teb)
|
||||
{
|
||||
teb.ClientId.UniqueProcess = reinterpret_cast<HANDLE>(1);
|
||||
teb.ClientId.UniqueThread = reinterpret_cast<HANDLE>(2);
|
||||
teb.NtTib.StackLimit = reinterpret_cast<void*>(STACK_ADDRESS);
|
||||
teb.NtTib.StackBase = reinterpret_cast<void*>((STACK_ADDRESS + STACK_SIZE));
|
||||
teb.NtTib.Self = &context.teb.ptr()->NtTib;
|
||||
teb.ProcessEnvironmentBlock = context.peb.ptr();
|
||||
});
|
||||
context.peb = allocator.reserve<PEB>();
|
||||
|
||||
/* Values of the following fields must be
|
||||
* allocated relative to the process_params themselves.
|
||||
@@ -247,7 +232,7 @@ namespace
|
||||
* RedirectionDllName
|
||||
*/
|
||||
|
||||
context.process_params = gs.reserve<RTL_USER_PROCESS_PARAMETERS>();
|
||||
context.process_params = allocator.reserve<RTL_USER_PROCESS_PARAMETERS>();
|
||||
|
||||
context.process_params.access([&](RTL_USER_PROCESS_PARAMETERS& proc_params)
|
||||
{
|
||||
@@ -267,11 +252,11 @@ namespace
|
||||
command_line.append(arg);
|
||||
}
|
||||
|
||||
gs.make_unicode_string(proc_params.CommandLine, command_line);
|
||||
allocator.make_unicode_string(proc_params.CommandLine, command_line);
|
||||
//gs.make_unicode_string(proc_params.CurrentDirectory.DosPath, file.parent_path().wstring());
|
||||
gs.make_unicode_string(proc_params.ImagePathName, file.wstring());
|
||||
allocator.make_unicode_string(proc_params.ImagePathName, file.wstring());
|
||||
|
||||
const auto total_length = gs.get_next_address() - context.process_params.value();
|
||||
const auto total_length = allocator.get_next_address() - context.process_params.value();
|
||||
|
||||
proc_params.Length = static_cast<uint32_t>(std::max(sizeof(proc_params), total_length));
|
||||
proc_params.MaximumLength = proc_params.Length;
|
||||
@@ -449,6 +434,66 @@ namespace
|
||||
|
||||
dispatch_exception_pointers(emu, dispatcher, pointers);
|
||||
}
|
||||
|
||||
void switch_to_thread(x64_emulator& emu, process_context& context, emulator_thread& thread)
|
||||
{
|
||||
auto* active_thread = context.active_thread;
|
||||
if (active_thread)
|
||||
{
|
||||
active_thread->save(emu);
|
||||
}
|
||||
|
||||
context.active_thread = &thread;
|
||||
thread.restore(emu);
|
||||
thread.setup_if_necessary(emu, context);
|
||||
}
|
||||
|
||||
void switch_to_thread(x64_emulator& emu, process_context& context, const handle thread_handle)
|
||||
{
|
||||
auto* thread = context.threads.get(thread_handle);
|
||||
if (!thread)
|
||||
{
|
||||
throw std::runtime_error("Bad thread handle");
|
||||
}
|
||||
|
||||
switch_to_thread(emu, context, *thread);
|
||||
}
|
||||
}
|
||||
|
||||
void emulator_thread::setup(x64_emulator& emu, const process_context& context)
|
||||
{
|
||||
this->stack_base = setup_stack(emu, this->stack_size);
|
||||
this->gs_segment = setup_gs_segment(emu, GS_SEGMENT_SIZE);
|
||||
|
||||
this->teb = this->gs_segment->reserve<TEB>();
|
||||
|
||||
this->teb->access([&](TEB& teb_obj)
|
||||
{
|
||||
teb_obj.ClientId.UniqueProcess = reinterpret_cast<HANDLE>(1);
|
||||
teb_obj.ClientId.UniqueThread = reinterpret_cast<HANDLE>(static_cast<uint64_t>(this->id));
|
||||
teb_obj.NtTib.StackLimit = reinterpret_cast<void*>(this->stack_base);
|
||||
teb_obj.NtTib.StackBase = reinterpret_cast<void*>(this->stack_base + this->stack_size);
|
||||
teb_obj.NtTib.Self = &this->teb->ptr()->NtTib;
|
||||
teb_obj.ProcessEnvironmentBlock = context.peb.ptr();
|
||||
});
|
||||
|
||||
CONTEXT ctx{};
|
||||
ctx.ContextFlags = CONTEXT_ALL;
|
||||
|
||||
unalign_stack(emu);
|
||||
context_frame::save(emu, ctx);
|
||||
|
||||
ctx.Rip = context.rtl_user_thread_start;
|
||||
ctx.Rcx = this->start_address;
|
||||
|
||||
const auto ctx_obj = allocate_object_on_stack<CONTEXT>(emu);
|
||||
ctx_obj.write(ctx);
|
||||
|
||||
unalign_stack(emu);
|
||||
|
||||
emu.reg(x64_register::rcx, ctx_obj.value());
|
||||
emu.reg(x64_register::rdx, context.ntdll->image_base);
|
||||
emu.reg(x64_register::rip, context.ldr_initialize_thunk);
|
||||
}
|
||||
|
||||
std::unique_ptr<x64_emulator> create_default_x64_emulator()
|
||||
@@ -492,27 +537,14 @@ void windows_emulator::setup_process(const std::filesystem::path& application,
|
||||
|
||||
this->dispatcher_.setup(context.ntdll->exports, context.win32u->exports);
|
||||
|
||||
const auto ldr_initialize_thunk = context.ntdll->find_export("LdrInitializeThunk");
|
||||
const auto rtl_user_thread_start = context.ntdll->find_export("RtlUserThreadStart");
|
||||
context.ldr_initialize_thunk = context.ntdll->find_export("LdrInitializeThunk");
|
||||
context.rtl_user_thread_start = context.ntdll->find_export("RtlUserThreadStart");
|
||||
context.ki_user_exception_dispatcher = context.ntdll->find_export("KiUserExceptionDispatcher");
|
||||
|
||||
CONTEXT ctx{};
|
||||
ctx.ContextFlags = CONTEXT_ALL;
|
||||
context.default_register_set = emu.save_registers();
|
||||
|
||||
unalign_stack(emu);
|
||||
context_frame::save(emu, ctx);
|
||||
|
||||
ctx.Rip = rtl_user_thread_start;
|
||||
ctx.Rcx = context.executable->entry_point;
|
||||
|
||||
const auto ctx_obj = allocate_object_on_stack<CONTEXT>(emu);
|
||||
ctx_obj.write(ctx);
|
||||
|
||||
unalign_stack(emu);
|
||||
|
||||
emu.reg(x64_register::rcx, ctx_obj.value());
|
||||
emu.reg(x64_register::rdx, context.ntdll->image_base);
|
||||
emu.reg(x64_register::rip, ldr_initialize_thunk);
|
||||
const auto main_thread_id = context.create_thread(emu, context.executable->entry_point, 0, 0x4000);
|
||||
switch_to_thread(emu, context, main_thread_id);
|
||||
}
|
||||
|
||||
void windows_emulator::setup_hooks()
|
||||
|
||||
@@ -51,6 +51,16 @@ public:
|
||||
return this->dispatcher_;
|
||||
}
|
||||
|
||||
emulator_thread& current_thread() const
|
||||
{
|
||||
if (!this->process_.active_thread)
|
||||
{
|
||||
throw std::runtime_error("No active thread!");
|
||||
}
|
||||
|
||||
return *this->process_.active_thread;
|
||||
}
|
||||
|
||||
void serialize(utils::buffer_serializer& buffer) const;
|
||||
void deserialize(utils::buffer_deserializer& buffer);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user