Support more syscalls

This commit is contained in:
momo5502
2025-03-22 19:38:23 +01:00
parent f26fc7f03f
commit 53fb2f9116
8 changed files with 75 additions and 12 deletions

View File

@@ -2,6 +2,10 @@
// NOLINTBEGIN(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
#ifndef OS_WINDOWS
#define CREATE_SUSPENDED 0x00000004
#endif
#define CONTEXT_X86_MAIN 0x00010000
#define CONTEXT_AMD64_MAIN 0x100000
#define CONTEXT_CONTROL_32 (CONTEXT_X86_MAIN | 0x1L)

View File

@@ -43,6 +43,7 @@ using NTSTATUS = std::uint32_t;
#define STATUS_INVALID_ADDRESS ((NTSTATUS)0xC0000141L)
#define STATUS_NOT_FOUND ((NTSTATUS)0xC0000225L)
#define STATUS_CONNECTION_REFUSED ((NTSTATUS)0xC0000236L)
#define STATUS_TIMER_RESOLUTION_NOT_SET ((NTSTATUS)0xC0000245L)
#define STATUS_ADDRESS_ALREADY_ASSOCIATED ((NTSTATUS)0xC0000328L)
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)

View File

@@ -96,12 +96,14 @@ 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 uint32_t id)
const uint64_t argument, const uint64_t stack_size, const bool suspended,
const uint32_t id)
: 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),
last_registers(context.default_register_set)
{
this->stack_base = memory.allocate_memory(this->stack_size, memory_permission::read_write);
@@ -151,7 +153,7 @@ bool emulator_thread::is_terminated() const
bool emulator_thread::is_thread_ready(process_context& process, utils::clock& clock)
{
if (this->is_terminated())
if (this->is_terminated() || this->suspended > 0)
{
return false;
}

View File

@@ -22,7 +22,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, uint32_t id);
uint64_t stack_size, bool suspended, uint32_t id);
emulator_thread(const emulator_thread&) = delete;
emulator_thread& operator=(const emulator_thread&) = delete;
@@ -54,6 +54,7 @@ class emulator_thread : public ref_counted_object
bool await_any{false};
bool waiting_for_alert{false};
bool alerted{false};
uint32_t suspended{0};
std::optional<std::chrono::steady_clock::time_point> await_time{};
std::optional<NTSTATUS> pending_status{};
@@ -123,6 +124,8 @@ class emulator_thread : public ref_counted_object
buffer.write(this->waiting_for_alert);
buffer.write(this->alerted);
buffer.write(this->suspended);
buffer.write_optional(this->await_time);
buffer.write_optional(this->pending_status);
buffer.write_optional(this->gs_segment);
@@ -156,6 +159,8 @@ class emulator_thread : public ref_counted_object
buffer.read(this->waiting_for_alert);
buffer.read(this->alerted);
buffer.read(this->suspended);
buffer.read_optional(this->await_time);
buffer.read_optional(this->pending_status);
buffer.read_optional(this->gs_segment, [this] { return emulator_allocator(*this->memory_ptr); });

View File

@@ -198,9 +198,9 @@ void process_context::deserialize(utils::buffer_deserializer& buffer)
}
handle process_context::create_thread(memory_manager& memory, const uint64_t start_address, const uint64_t argument,
const uint64_t stack_size)
const uint64_t stack_size, const bool suspended)
{
emulator_thread t{memory, *this, start_address, argument, stack_size, ++this->spawned_thread_count};
emulator_thread t{memory, *this, start_address, argument, stack_size, suspended, ++this->spawned_thread_count};
auto [h, thr] = this->threads.store_and_get(std::move(t));
this->callbacks_->on_create_thread(h, *thr);
return h;

View File

@@ -50,7 +50,8 @@ struct process_context
void setup(x64_emulator& emu, memory_manager& memory, const application_settings& app_settings,
const mapped_module& executable, const mapped_module& ntdll, const apiset::container& apiset_container);
handle create_thread(memory_manager& memory, uint64_t start_address, uint64_t argument, uint64_t stack_size);
handle create_thread(memory_manager& memory, uint64_t start_address, uint64_t argument, uint64_t stack_size,
bool suspended);
void serialize(utils::buffer_serializer& buffer) const;
void deserialize(utils::buffer_deserializer& buffer);

View File

@@ -299,7 +299,7 @@ namespace
return STATUS_INVALID_HANDLE;
}
if (info_class == ThreadSchedulerSharedDataSlot)
if (info_class == ThreadSchedulerSharedDataSlot || info_class == ThreadBasePriority)
{
return STATUS_SUCCESS;
}
@@ -1169,7 +1169,8 @@ namespace
{
if (info_class == SystemFlushInformation || info_class == SystemFeatureConfigurationInformation ||
info_class == SystemSupportedProcessorArchitectures2 ||
info_class == SystemFeatureConfigurationSectionInformation)
info_class == SystemFeatureConfigurationSectionInformation ||
info_class == SystemLogicalProcessorInformation)
{
return STATUS_NOT_SUPPORTED;
}
@@ -1453,7 +1454,8 @@ namespace
return STATUS_SUCCESS;
}
if (info_class == ProcessEnclaveInformation || info_class == ProcessMitigationPolicy)
if (info_class == ProcessEnclaveInformation || info_class == ProcessMitigationPolicy ||
info_class == ProcessGroupInformation)
{
return STATUS_NOT_SUPPORTED;
}
@@ -2523,6 +2525,11 @@ namespace
0xD4, 0x04, 0x4B, 0x68, 0x42, 0x34, 0x23, 0xBE, 0x69, 0x4E, 0xE9, 0x03, 0x00, 0x00,
};
if (token_information_class == TokenAppContainerSid)
{
return STATUS_NOT_SUPPORTED;
}
if (token_information_class == TokenUser)
{
constexpr auto required_size = sizeof(sid) + 0x10;
@@ -3507,7 +3514,7 @@ namespace
const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>>
/*object_attributes*/,
const handle process_handle, const uint64_t start_routine, const uint64_t argument,
const ULONG /*create_flags*/, const EmulatorTraits<Emu64>::SIZE_T /*zero_bits*/,
const ULONG create_flags, const EmulatorTraits<Emu64>::SIZE_T /*zero_bits*/,
const EmulatorTraits<Emu64>::SIZE_T stack_size,
const EmulatorTraits<Emu64>::SIZE_T /*maximum_stack_size*/,
const emulator_object<PS_ATTRIBUTE_LIST<EmulatorTraits<Emu64>>> attribute_list)
@@ -3517,7 +3524,8 @@ namespace
return STATUS_NOT_SUPPORTED;
}
const auto h = c.proc.create_thread(c.win_emu.memory, start_routine, argument, stack_size);
const auto h = c.proc.create_thread(c.win_emu.memory, start_routine, argument, stack_size,
create_flags & CREATE_SUSPENDED);
thread_handle.write(h);
if (!attribute_list)
@@ -3878,6 +3886,22 @@ namespace
return STATUS_SUCCESS;
}
NTSTATUS handle_NtSetTimerResolution(const syscall_context&, const ULONG /*desired_resolution*/,
const BOOLEAN set_resolution, const emulator_object<ULONG> current_resolution)
{
if (current_resolution)
{
current_resolution.write(0x0002625a);
}
if (set_resolution)
{
return STATUS_TIMER_RESOLUTION_NOT_SET;
}
return STATUS_SUCCESS;
}
NTSTATUS handle_NtSetContextThread(const syscall_context& c, const handle thread_handle,
const emulator_object<CONTEXT64> thread_context)
{
@@ -3919,6 +3943,29 @@ namespace
c.win_emu.yield_thread();
return STATUS_SUCCESS;
}
NTSTATUS handle_NtResumeThread(const syscall_context& c, const handle thread_handle,
const emulator_object<ULONG> previous_suspend_count)
{
auto* thread = c.proc.threads.get(thread_handle);
if (!thread)
{
return STATUS_INVALID_HANDLE;
}
const auto old_count = thread->suspended;
if (previous_suspend_count)
{
previous_suspend_count.write(old_count);
}
if (old_count > 0)
{
thread->suspended -= 1;
}
return STATUS_SUCCESS;
}
}
void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& handler_mapping)
@@ -4051,6 +4098,8 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
add_handler(NtSystemDebugControl);
add_handler(NtRequestWaitReplyPort);
add_handler(NtQueryDefaultLocale);
add_handler(NtSetTimerResolution);
add_handler(NtResumeThread);
#undef add_handler
}

View File

@@ -281,7 +281,8 @@ 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, 0);
const auto main_thread_id =
context.create_thread(this->memory, this->mod_manager.executable->entry_point, 0, 0, false);
switch_to_thread(*this, main_thread_id);
}