From 46302df8646cdddca9f517dd58436eb2b9e1905a Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 11 Sep 2024 12:52:24 +0200 Subject: [PATCH] Support win32k syscalls --- src/windows_emulator/main.cpp | 3 +- .../module/module_manager.cpp | 8 ++ src/windows_emulator/process_context.hpp | 1 + src/windows_emulator/syscalls.cpp | 90 ++++++++++++++----- src/windows_emulator/syscalls.hpp | 2 +- 5 files changed, 78 insertions(+), 26 deletions(-) diff --git a/src/windows_emulator/main.cpp b/src/windows_emulator/main.cpp index ba2cfc3..75c5865 100644 --- a/src/windows_emulator/main.cpp +++ b/src/windows_emulator/main.cpp @@ -532,13 +532,14 @@ namespace }); context.ntdll = context.module_manager.map_module(R"(C:\Windows\System32\ntdll.dll)"); + context.win32u = context.module_manager.map_module(R"(C:\Windows\System32\win32u.dll)"); const auto ldr_initialize_thunk = find_exported_function(context.ntdll->exports, "LdrInitializeThunk"); const auto rtl_user_thread_start = find_exported_function(context.ntdll->exports, "RtlUserThreadStart"); const auto ki_user_exception_dispatcher = find_exported_function( context.ntdll->exports, "KiUserExceptionDispatcher"); - syscall_dispatcher dispatcher{context.ntdll->exports}; + syscall_dispatcher dispatcher{context.ntdll->exports, context.win32u->exports}; emu->hook_instruction(x64_hookable_instructions::syscall, [&] { diff --git a/src/windows_emulator/module/module_manager.cpp b/src/windows_emulator/module/module_manager.cpp index 689f212..4dde2fa 100644 --- a/src/windows_emulator/module/module_manager.cpp +++ b/src/windows_emulator/module/module_manager.cpp @@ -9,6 +9,14 @@ module_manager::module_manager(emulator& emu) mapped_module* module_manager::map_module(const std::filesystem::path& file) { + for (auto& mod : this->modules_) + { + if (mod.second.path == file) + { + return &mod.second; + } + } + auto mod = map_module_from_file(*this->emu_, file); if (!mod) { diff --git a/src/windows_emulator/process_context.hpp b/src/windows_emulator/process_context.hpp index d370a77..b9b157f 100644 --- a/src/windows_emulator/process_context.hpp +++ b/src/windows_emulator/process_context.hpp @@ -48,6 +48,7 @@ struct process_context mapped_module* executable{}; mapped_module* ntdll{}; + mapped_module* win32u{}; handle_store events{}; handle_store files{}; diff --git a/src/windows_emulator/syscalls.cpp b/src/windows_emulator/syscalls.cpp index 66ea30a..4114c3a 100644 --- a/src/windows_emulator/syscalls.cpp +++ b/src/windows_emulator/syscalls.cpp @@ -44,12 +44,14 @@ namespace // is equal to the order of syscall IDs. // So first Nt* function is the first syscall with ID 0 + std::map reference_count{}; std::map ordered_syscalls{}; for (const auto& symbol : exports) { if (is_syscall(symbol.name)) { + ++reference_count[symbol.address]; ordered_syscalls[symbol.address] = symbol.name; } } @@ -59,22 +61,37 @@ namespace for (auto& syscall : ordered_syscalls) { - syscalls.push_back(std::move(syscall.second)); + if (reference_count[syscall.first] == 1) + { + syscalls.push_back(std::move(syscall.second)); + } + else + { + printf("Skipping %s\n", syscall.second.c_str()); + } } return syscalls; } - uint64_t get_syscall_id(const std::vector& syscalls, const std::string_view name) + uint64_t get_syscall_id(const std::vector& ntdll_syscalls, const std::vector& win32u_syscalls, const std::string_view name) { - for (size_t i = 0; i < syscalls.size(); ++i) + for (size_t i = 0; i < ntdll_syscalls.size(); ++i) { - if (syscalls[i] == name) + if (ntdll_syscalls[i] == name) { return i; } } + for (size_t i = 0; i < win32u_syscalls.size(); ++i) + { + if (win32u_syscalls[i] == name) + { + return i + 0x1000; + } + } + throw std::runtime_error("Unable to determine syscall id: " + std::string(name)); } @@ -1056,16 +1073,25 @@ namespace NTSTATUS handle_NtReadVirtualMemory(const syscall_context& c, uint64_t process_handle, uint64_t base_address, uint64_t buffer, ULONG number_of_bytes_to_read, - const emulator_object number_of_bytes_readed) + const emulator_object number_of_bytes_read) { - puts("NtReadVirtualMemory not supported"); - //c.emu.stop(); + number_of_bytes_read.write(0); if (process_handle != ~0ULL) { return STATUS_NOT_SUPPORTED; } + std::vector memory{}; + memory.resize(number_of_bytes_read); + + if (!c.emu.try_read_memory(base_address, memory.data(), memory.size())) + { + return STATUS_INVALID_ADDRESS; + } + + c.emu.write_memory(buffer, memory.data(), memory.size()); + number_of_bytes_read.write(number_of_bytes_to_read); return STATUS_SUCCESS; } @@ -1105,6 +1131,18 @@ namespace return STATUS_NOT_SUPPORTED; } + NTSTATUS handle_NtQueryInformationToken() + { + puts("NtQueryInformationToken not supported"); + return STATUS_NOT_SUPPORTED; + } + + NTSTATUS handle_NtDxgkIsFeatureEnabled() + { + puts("NtDxgkIsFeatureEnabled not supported"); + return STATUS_NOT_SUPPORTED; + } + NTSTATUS handle_NtContinue(const syscall_context& c, const emulator_object thread_context, const BOOLEAN /*raise_alert*/) { @@ -1179,7 +1217,8 @@ namespace return STATUS_SUCCESS; } - throw std::runtime_error("Unsupported file"); + printf("Unsupported file: %S\n", filename.c_str()); + return STATUS_NOT_SUPPORTED; } NTSTATUS handle_NtRaiseHardError(const syscall_context& c, const NTSTATUS error_status, @@ -1224,23 +1263,24 @@ namespace } } -syscall_dispatcher::syscall_dispatcher(const exported_symbols& ntdll_exports) +syscall_dispatcher::syscall_dispatcher(const exported_symbols& ntdll_exports, const exported_symbols& win32u_exports) { - const auto syscalls = find_syscalls(ntdll_exports); - -#define add_handler(syscall) do \ - { \ - std::string name = #syscall; \ - const auto id = get_syscall_id(syscalls, name); \ - auto handler = +[](const syscall_context& c) \ - { \ - forward(c, handle_ ## syscall); \ - }; \ - \ - syscall_handler_entry entry{}; \ - entry.handler = handler; \ - entry.name = std::move(name); \ - this->handlers_[id] = std::move(entry); \ + const auto ntdll_syscalls = find_syscalls(ntdll_exports); + const auto win32u_syscalls = find_syscalls(win32u_exports); + +#define add_handler(syscall) do \ + { \ + std::string name = #syscall; \ + const auto id = get_syscall_id(ntdll_syscalls, win32u_syscalls, name); \ + auto handler = +[](const syscall_context& c) \ + { \ + forward(c, handle_ ## syscall); \ + }; \ + \ + syscall_handler_entry entry{}; \ + entry.handler = handler; \ + entry.name = std::move(name); \ + this->handlers_[id] = std::move(entry); \ } while(0) add_handler(NtSetInformationThread); @@ -1287,6 +1327,8 @@ syscall_dispatcher::syscall_dispatcher(const exported_symbols& ntdll_exports) add_handler(NtRaiseHardError); add_handler(NtCreateSemaphore); add_handler(NtReadVirtualMemory); + add_handler(NtQueryInformationToken); + add_handler(NtDxgkIsFeatureEnabled); #undef add_handler } diff --git a/src/windows_emulator/syscalls.hpp b/src/windows_emulator/syscalls.hpp index daf0fff..543703f 100644 --- a/src/windows_emulator/syscalls.hpp +++ b/src/windows_emulator/syscalls.hpp @@ -16,7 +16,7 @@ struct syscall_handler_entry class syscall_dispatcher { public: - syscall_dispatcher(const exported_symbols& ntdll_exports); + syscall_dispatcher(const exported_symbols& ntdll_exports, const exported_symbols& win32u_exports); void dispatch(x64_emulator& emu, process_context& context);