Skip to content

Commit

Permalink
Support more syscalls
Browse files Browse the repository at this point in the history
  • Loading branch information
momo5502 committed Dec 21, 2024
1 parent 98d3077 commit ce6cb01
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 8 deletions.
6 changes: 6 additions & 0 deletions src/emulator/memory_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ class memory_manager
this->write_memory(address, &value, sizeof(value));
}

template <typename T>
void write_memory(void* address, const T& value)
{
this->write_memory(reinterpret_cast<uint64_t>(address), &value, sizeof(value));
}

void write_memory(void* address, const void* data, const size_t size)
{
this->write_memory(reinterpret_cast<uint64_t>(address), data, size);
Expand Down
9 changes: 6 additions & 3 deletions src/windows-emulator/process_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,8 @@ class emulator_thread : ref_counted_object
std::wstring name{};

std::optional<NTSTATUS> exit_status{};
std::optional<handle> await_object{};
std::vector<handle> await_objects{};
bool await_any{false};
bool waiting_for_alert{false};
bool alerted{false};
std::optional<std::chrono::steady_clock::time_point> await_time{};
Expand Down Expand Up @@ -317,7 +318,8 @@ class emulator_thread : ref_counted_object
buffer.write_string(this->name);

buffer.write_optional(this->exit_status);
buffer.write_optional(this->await_object);
buffer.write_vector(this->await_objects);
buffer.write(this->await_any);

buffer.write(this->waiting_for_alert);
buffer.write(this->alerted);
Expand Down Expand Up @@ -349,7 +351,8 @@ class emulator_thread : ref_counted_object
buffer.read_string(this->name);

buffer.read_optional(this->exit_status);
buffer.read_optional(this->await_object);
buffer.read_vector(this->await_objects);
buffer.read(this->await_any);

buffer.read(this->waiting_for_alert);
buffer.read(this->alerted);
Expand Down
57 changes: 56 additions & 1 deletion src/windows-emulator/syscalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,11 @@ namespace
return STATUS_NO_TOKEN;
}

NTSTATUS handle_NtOpenThreadTokenEx()
{
return STATUS_NO_TOKEN;
}

NTSTATUS handle_NtCreateEvent(const syscall_context& c, const emulator_object<handle> event_handle,
const ACCESS_MASK /*desired_access*/,
const emulator_object<OBJECT_ATTRIBUTES> object_attributes,
Expand Down Expand Up @@ -1764,6 +1769,12 @@ namespace
return STATUS_NOT_SUPPORTED;
}

NTSTATUS handle_NtOpenProcessTokenEx()
{
//puts("NtOpenProcessToken not supported");
return STATUS_NOT_SUPPORTED;
}

NTSTATUS handle_NtQuerySecurityAttributesToken()
{
//puts("NtQuerySecurityAttributesToken not supported");
Expand Down Expand Up @@ -2554,6 +2565,46 @@ namespace
return FALSE;
}

NTSTATUS handle_NtWaitForMultipleObjects(const syscall_context& c, const ULONG count,
const emulator_object<handle> handles, const WAIT_TYPE wait_type,
const BOOLEAN alertable, const emulator_object<LARGE_INTEGER> timeout)
{
if (alertable)
{
c.win_emu.logger.print(color::gray, "Alertable NtWaitForMultipleObjects not supported yet!\n");
}

if (wait_type != WaitAny && wait_type != WaitAll)
{
puts("Wait type not supported!");
c.emu.stop();
return STATUS_NOT_SUPPORTED;
}

auto& t = c.win_emu.current_thread();
t.await_objects.clear();
t.await_any = wait_type == WaitAny;

for (ULONG i = 0; i < count; ++i)
{
const auto h = handles.read(i);

if (h.value.type != handle_types::thread && h.value.type != handle_types::event)
{
c.win_emu.logger.print(color::gray, "Unsupported handle type for NtWaitForMultipleObjects!\n");
return STATUS_NOT_SUPPORTED;
}
}

if (timeout.value() && !t.await_time.has_value())
{
t.await_time = convert_delay_interval_to_time_point(timeout.read());
}

c.win_emu.yield_thread();
return STATUS_SUCCESS;
}

NTSTATUS handle_NtWaitForSingleObject(const syscall_context& c, const handle h,
const BOOLEAN alertable,
const emulator_object<LARGE_INTEGER> timeout)
Expand All @@ -2570,7 +2621,8 @@ namespace
}

auto& t = c.win_emu.current_thread();
t.await_object = h;
t.await_objects = {h};
t.await_any = false;

if (timeout.value() && !t.await_time.has_value())
{
Expand Down Expand Up @@ -2690,6 +2742,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
add_handler(NtFreeVirtualMemory);
add_handler(NtQueryVirtualMemory);
add_handler(NtOpenThreadToken);
add_handler(NtOpenThreadTokenEx);
add_handler(NtQueryPerformanceCounter);
add_handler(NtQuerySystemInformation);
add_handler(NtCreateEvent);
Expand All @@ -2715,6 +2768,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
add_handler(NtDeviceIoControlFile);
add_handler(NtQueryWnfStateData);
add_handler(NtOpenProcessToken);
add_handler(NtOpenProcessTokenEx);
add_handler(NtQuerySecurityAttributesToken);
add_handler(NtQueryLicenseValue);
add_handler(NtTestAlert);
Expand Down Expand Up @@ -2766,6 +2820,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
add_handler(NtGetCurrentProcessorNumberEx);
add_handler(NtQueryObject);
add_handler(NtQueryAttributesFile);
add_handler(NtWaitForMultipleObjects);

#undef add_handler
}
23 changes: 19 additions & 4 deletions src/windows-emulator/windows_emulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ void emulator_thread::mark_as_ready(const NTSTATUS status)
{
this->pending_status = status;
this->await_time = {};
this->await_object = {};
this->await_objects = {};

// TODO: Find out if this is correct
if (this->waiting_for_alert)
Expand Down Expand Up @@ -625,11 +625,26 @@ bool emulator_thread::is_thread_ready(windows_emulator& win_emu)
return false;
}

if (this->await_object.has_value())
if (!this->await_objects.empty())
{
if (is_object_signaled(win_emu.process(), *this->await_object))
bool all_signaled = true;
for (uint32_t i = 0; i < this->await_objects.size(); ++i)
{
this->mark_as_ready(STATUS_WAIT_0);
const auto& obj = this->await_objects[i];

const auto signaled = is_object_signaled(win_emu.process(), obj);
all_signaled &= signaled;

if (signaled && this->await_any)
{
this->mark_as_ready(STATUS_WAIT_0 + i);
return true;
}
}

if (!this->await_any && all_signaled)
{
this->mark_as_ready(STATUS_SUCCESS);
return true;
}

Expand Down

0 comments on commit ce6cb01

Please sign in to comment.