From fea27338bb882e059386a0bfa0749a650e430472 Mon Sep 17 00:00:00 2001 From: ssvine <79405160+ssvine@users.noreply.github.com> Date: Tue, 30 Dec 2025 13:44:21 +0300 Subject: [PATCH] Support SameTebFlags.InitialThread This flag is needed to suport emulation of .net executables that don't have an entry point set in PE header. This applies to both PE32 and PE64 executables. If InitialThread is set the loader substitutes an entry point of the .net executable with mscoree.dll!_CorExeMain. --- src/windows-emulator/emulator_thread.cpp | 6 +++++- src/windows-emulator/emulator_thread.hpp | 2 +- src/windows-emulator/process_context.cpp | 4 ++-- src/windows-emulator/process_context.hpp | 3 ++- src/windows-emulator/windows_emulator.cpp | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/windows-emulator/emulator_thread.cpp b/src/windows-emulator/emulator_thread.cpp index 7e578c05..16320137 100644 --- a/src/windows-emulator/emulator_thread.cpp +++ b/src/windows-emulator/emulator_thread.cpp @@ -116,7 +116,8 @@ namespace } emulator_thread::emulator_thread(memory_manager& memory, const process_context& context, const uint64_t start_address, - const uint64_t argument, const uint64_t stack_size, const bool suspended, const uint32_t id) + const uint64_t argument, const uint64_t stack_size, const bool suspended, const uint32_t id, + const bool initial_thread) : memory_ptr(&memory), // stack_size(page_align_up(std::max(stack_size, static_cast(STACK_SIZE)))), start_address(start_address), @@ -152,6 +153,7 @@ emulator_thread::emulator_thread(memory_manager& memory, const process_context& teb_obj.NtTib.Self = this->teb64->value(); teb_obj.CurrentLocale = 0x409; teb_obj.ProcessEnvironmentBlock = context.peb64.value(); + teb_obj.SameTebFlags.InitialThread = initial_thread; }); return; @@ -209,6 +211,7 @@ emulator_thread::emulator_thread(memory_manager& memory, const process_context& teb_obj.CurrentLocale = 0x409; teb_obj.ProcessEnvironmentBlock = context.peb64.value(); + teb_obj.SameTebFlags.InitialThread = initial_thread; teb_obj.StaticUnicodeString.MaximumLength = sizeof(teb_obj.StaticUnicodeBuffer); teb_obj.StaticUnicodeString.Buffer = this->teb64->value() + offsetof(TEB64, StaticUnicodeBuffer); @@ -264,6 +267,7 @@ emulator_thread::emulator_thread(memory_manager& memory, const process_context& } teb32_obj.WowTebOffset = -0x2000; + teb32_obj.InitialThread = initial_thread; // Note: CurrentLocale and other fields will be initialized by WOW64 runtime }); diff --git a/src/windows-emulator/emulator_thread.hpp b/src/windows-emulator/emulator_thread.hpp index 4f14aa7a..95124a0c 100644 --- a/src/windows-emulator/emulator_thread.hpp +++ b/src/windows-emulator/emulator_thread.hpp @@ -49,7 +49,7 @@ class emulator_thread : public ref_counted_object } emulator_thread(memory_manager& memory, const process_context& context, uint64_t start_address, uint64_t argument, uint64_t stack_size, - bool suspended, uint32_t id); + bool suspended, uint32_t id, bool initial_thread); emulator_thread(const emulator_thread&) = delete; emulator_thread& operator=(const emulator_thread&) = delete; diff --git a/src/windows-emulator/process_context.cpp b/src/windows-emulator/process_context.cpp index c48c155c..f9e2fdef 100644 --- a/src/windows-emulator/process_context.cpp +++ b/src/windows-emulator/process_context.cpp @@ -525,9 +525,9 @@ generic_handle_store* process_context::get_handle_store(const handle handle) } handle process_context::create_thread(memory_manager& memory, const uint64_t start_address, const uint64_t argument, - const uint64_t stack_size, const bool suspended) + const uint64_t stack_size, const bool suspended, const bool initial_thread) { - emulator_thread t{memory, *this, start_address, argument, stack_size, suspended, ++this->spawned_thread_count}; + emulator_thread t{memory, *this, start_address, argument, stack_size, suspended, ++this->spawned_thread_count, initial_thread}; auto [h, thr] = this->threads.store_and_get(std::move(t)); this->callbacks_->on_thread_create(h, *thr); return h; diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 634fe3c4..91ffb417 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -74,7 +74,8 @@ struct process_context const mapped_module& executable, const mapped_module& ntdll, const apiset::container& apiset_container, const mapped_module* ntdll32 = nullptr); - handle create_thread(memory_manager& memory, uint64_t start_address, uint64_t argument, uint64_t stack_size, bool suspended); + handle create_thread(memory_manager& memory, uint64_t start_address, uint64_t argument, uint64_t stack_size, bool suspended, + bool initial_thread = false); std::optional find_atom(std::u16string_view name); uint16_t add_or_find_atom(std::u16string name); diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 2598b5ed..e751dcbf 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -371,7 +371,7 @@ void windows_emulator::setup_process(const application_settings& app_settings) this->dispatcher.setup(ntdll->exports, ntdll_data, win32u->exports, win32u_data); const auto main_thread_id = context.create_thread(this->memory, this->mod_manager.executable->entry_point, 0, - this->mod_manager.executable->size_of_stack_commit, false); + this->mod_manager.executable->size_of_stack_commit, false, true); switch_to_thread(*this, main_thread_id); }