From a9e31dd58fa18881ff07c49da901144a88a1d062 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sun, 20 Oct 2024 20:47:36 +0200 Subject: [PATCH] Quick & dirty support for delay execution --- src/windows-emulator/process_context.hpp | 1 + src/windows-emulator/syscalls.cpp | 65 ++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 0bd0e6e9..ec5e8f74 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -219,6 +219,7 @@ public: std::optional exit_status{}; std::optional await_object{}; + std::optional await_time{}; std::optional gs_segment; std::optional> teb; diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 5b53edf0..d590c79b 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -117,7 +117,7 @@ namespace void write_status(const syscall_context& c, const NTSTATUS status, const uint64_t initial_ip) { - if (c.write_status) + if (c.write_status && !c.retrigger_syscall) { c.emu.reg(x64_register::rax, static_cast(status)); } @@ -204,9 +204,40 @@ namespace break; } } + throw std::runtime_error("Bad object"); } + std::chrono::steady_clock::time_point convert_delay_interval_to_time_point(const LARGE_INTEGER delay_interval) + { + constexpr auto HUNDRED_NANOSECONDS_IN_ONE_SECOND = 10000000LL; + constexpr auto EPOCH_DIFFERENCE_1601_TO_1970_SECONDS = 11644473600LL; + + if (delay_interval.QuadPart < 0) + { + const auto relative_ticks_in_ns = (-delay_interval.QuadPart) * 100; + const auto relative_duration = std::chrono::nanoseconds(relative_ticks_in_ns); + + return std::chrono::steady_clock::now() + relative_duration; + } + + const auto delay_seconds_since_1601 = delay_interval.QuadPart / HUNDRED_NANOSECONDS_IN_ONE_SECOND; + const auto delay_fraction_microseconds = (delay_interval.QuadPart % HUNDRED_NANOSECONDS_IN_ONE_SECOND) / 10; + + const auto delay_seconds_since_1970 = delay_seconds_since_1601 - EPOCH_DIFFERENCE_1601_TO_1970_SECONDS; + + const auto target_time = + std::chrono::system_clock::from_time_t(delay_seconds_since_1970) + + std::chrono::microseconds(delay_fraction_microseconds); + + const auto now_system = std::chrono::system_clock::now(); + + const auto duration_until_target = std::chrono::duration_cast< + std::chrono::microseconds>(target_time - now_system); + + return std::chrono::steady_clock::now() + duration_until_target; + } + NTSTATUS handle_NtQueryPerformanceCounter(const syscall_context&, const emulator_object performance_counter, const emulator_object performance_frequency) @@ -2066,7 +2097,6 @@ namespace return STATUS_WAIT_0; } - c.write_status = false; c.retrigger_syscall = true; c.win_emu.current_thread().await_object = h; @@ -2076,7 +2106,7 @@ namespace return STATUS_SUCCESS; } - NTSTATUS handle_NtTerminateThread(const syscall_context& c, uint64_t thread_handle, + NTSTATUS handle_NtTerminateThread(const syscall_context& c, const uint64_t thread_handle, const NTSTATUS exit_status) { auto* thread = !thread_handle @@ -2097,6 +2127,34 @@ namespace return STATUS_SUCCESS; } + + NTSTATUS handle_NtDelayExecution(const syscall_context& c, const BOOLEAN alertable, + const emulator_object delay_interval) + { + if (alertable) + { + puts("Alertable NtDelayExecution not supported yet!"); + return STATUS_NOT_SUPPORTED; + } + + auto& t = c.win_emu.current_thread(); + + if (!t.await_time.has_value()) + { + t.await_time = convert_delay_interval_to_time_point(delay_interval.read()); + } + else if (*t.await_time > std::chrono::steady_clock::now()) + { + t.await_time = {}; + return STATUS_SUCCESS; + } + + c.retrigger_syscall = true; + c.win_emu.switch_thread = true; + c.emu.stop(); + + return STATUS_SUCCESS; + } } void syscall_dispatcher::setup(const exported_symbols& ntdll_exports, const exported_symbols& win32u_exports) @@ -2199,6 +2257,7 @@ void syscall_dispatcher::add_handlers() add_handler(NtQueryDebugFilterState); add_handler(NtWaitForSingleObject); add_handler(NtTerminateThread); + add_handler(NtDelayExecution); #undef add_handler