Skip to content

Commit

Permalink
Quick & dirty support for delay execution
Browse files Browse the repository at this point in the history
  • Loading branch information
momo5502 committed Oct 20, 2024
1 parent 17bfe72 commit a9e31dd
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/windows-emulator/process_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ class emulator_thread : ref_counted_object

std::optional<uint32_t> exit_status{};
std::optional<handle> await_object{};
std::optional<std::chrono::steady_clock::time_point> await_time{};

std::optional<emulator_allocator> gs_segment;
std::optional<emulator_object<TEB>> teb;
Expand Down
65 changes: 62 additions & 3 deletions src/windows-emulator/syscalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint64_t>(x64_register::rax, static_cast<uint64_t>(status));
}
Expand Down Expand Up @@ -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<LARGE_INTEGER> performance_counter,
const emulator_object<LARGE_INTEGER> performance_frequency)
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -2097,6 +2127,34 @@ namespace

return STATUS_SUCCESS;
}

NTSTATUS handle_NtDelayExecution(const syscall_context& c, const BOOLEAN alertable,
const emulator_object<LARGE_INTEGER> 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)
Expand Down Expand Up @@ -2199,6 +2257,7 @@ void syscall_dispatcher::add_handlers()
add_handler(NtQueryDebugFilterState);
add_handler(NtWaitForSingleObject);
add_handler(NtTerminateThread);
add_handler(NtDelayExecution);

#undef add_handler

Expand Down

0 comments on commit a9e31dd

Please sign in to comment.