Fix creating suspended thread and parse create_flags

This commit is contained in:
ssvine
2025-12-30 15:18:55 +03:00
parent 0370da327b
commit 57ad277158
7 changed files with 29 additions and 8 deletions

View File

@@ -971,6 +971,13 @@ union TEB_CROSS_TEB_FLAGS_UNION
USHORT SpareCrossTebBits : 16;
};
constexpr auto THREAD_CREATE_FLAGS_CREATE_SUSPENDED = 0x1;
constexpr auto THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH = 0x2;
constexpr auto THREAD_CREATE_FLAGS_HIDE_FROM_DEBUGGER = 0x4;
constexpr auto THREAD_CREATE_FLAGS_LOADER_WORKER = 0x10;
constexpr auto THREAD_CREATE_FLAGS_SKIP_LOADER_INIT = 0x20;
constexpr auto THREAD_CREATE_FLAGS_BYPASS_PROCESS_FREEZE = 0x40;
union TEB_SAME_TEB_FLAGS_UNION
{
USHORT SameTebFlags;

View File

@@ -116,16 +116,18 @@ 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 uint32_t create_flags, const uint32_t id,
const bool initial_thread)
: memory_ptr(&memory),
// stack_size(page_align_up(std::max(stack_size, static_cast<uint64_t>(STACK_SIZE)))),
start_address(start_address),
argument(argument),
id(id),
suspended(suspended),
create_flags(create_flags),
last_registers(context.default_register_set)
{
this->suspended = create_flags & THREAD_CREATE_FLAGS_CREATE_SUSPENDED;
// native 64-bit
if (!context.is_wow64_process)
{
@@ -154,6 +156,9 @@ 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.SameTebFlags.SkipThreadAttach = (create_flags & THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH) ? 1 : 0;
teb_obj.SameTebFlags.LoaderWorker = (create_flags & THREAD_CREATE_FLAGS_LOADER_WORKER) ? 1 : 0;
teb_obj.SameTebFlags.SkipLoaderInit = (create_flags & THREAD_CREATE_FLAGS_SKIP_LOADER_INIT) ? 1 : 0;
});
return;
@@ -212,6 +217,9 @@ emulator_thread::emulator_thread(memory_manager& memory, const process_context&
teb_obj.ProcessEnvironmentBlock = context.peb64.value();
teb_obj.SameTebFlags.InitialThread = initial_thread;
teb_obj.SameTebFlags.SkipThreadAttach = (create_flags & THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH) ? 1 : 0;
teb_obj.SameTebFlags.LoaderWorker = (create_flags & THREAD_CREATE_FLAGS_LOADER_WORKER) ? 1 : 0;
teb_obj.SameTebFlags.SkipLoaderInit = (create_flags & THREAD_CREATE_FLAGS_SKIP_LOADER_INIT) ? 1 : 0;
teb_obj.StaticUnicodeString.MaximumLength = sizeof(teb_obj.StaticUnicodeBuffer);
teb_obj.StaticUnicodeString.Buffer = this->teb64->value() + offsetof(TEB64, StaticUnicodeBuffer);
@@ -268,6 +276,9 @@ emulator_thread::emulator_thread(memory_manager& memory, const process_context&
teb32_obj.WowTebOffset = -0x2000;
teb32_obj.InitialThread = initial_thread;
teb32_obj.SkipThreadAttach = (create_flags & THREAD_CREATE_FLAGS_SKIP_THREAD_ATTACH) ? 1 : 0;
teb32_obj.LoaderWorker = (create_flags & THREAD_CREATE_FLAGS_LOADER_WORKER) ? 1 : 0;
teb32_obj.SkipLoaderInit = (create_flags & THREAD_CREATE_FLAGS_SKIP_LOADER_INIT) ? 1 : 0;
// Note: CurrentLocale and other fields will be initialized by WOW64 runtime
});

View File

@@ -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 initial_thread);
uint32_t create_flags, uint32_t id, bool initial_thread);
emulator_thread(const emulator_thread&) = delete;
emulator_thread& operator=(const emulator_thread&) = delete;
@@ -86,6 +86,7 @@ class emulator_thread : public ref_counted_object
bool await_any{false};
bool waiting_for_alert{false};
bool alerted{false};
uint32_t create_flags{0};
uint32_t suspended{0};
std::optional<std::chrono::steady_clock::time_point> await_time{};
@@ -164,6 +165,7 @@ class emulator_thread : public ref_counted_object
buffer.write(this->waiting_for_alert);
buffer.write(this->alerted);
buffer.write(this->create_flags);
buffer.write(this->suspended);
buffer.write_optional(this->await_time);
@@ -209,6 +211,7 @@ class emulator_thread : public ref_counted_object
buffer.read(this->waiting_for_alert);
buffer.read(this->alerted);
buffer.read(this->create_flags);
buffer.read(this->suspended);
buffer.read_optional(this->await_time);

View File

@@ -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 bool initial_thread)
const uint64_t stack_size, const uint32_t create_flags, const bool initial_thread)
{
emulator_thread t{memory, *this, start_address, argument, stack_size, suspended, ++this->spawned_thread_count, initial_thread};
emulator_thread t{memory, *this, start_address, argument, stack_size, create_flags, ++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;

View File

@@ -74,7 +74,7 @@ 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, uint32_t create_flags,
bool initial_thread = false);
std::optional<uint16_t> find_atom(std::u16string_view name);

View File

@@ -625,7 +625,7 @@ namespace syscalls
return STATUS_NOT_SUPPORTED;
}
const auto h = c.proc.create_thread(c.win_emu.memory, start_routine, argument, stack_size, create_flags & CREATE_SUSPENDED);
const auto h = c.proc.create_thread(c.win_emu.memory, start_routine, argument, stack_size, create_flags);
thread_handle.write(h);
if (!attribute_list)

View File

@@ -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, true);
this->mod_manager.executable->size_of_stack_commit, 0, true);
switch_to_thread(*this, main_thread_id);
}