Support win32k syscalls

This commit is contained in:
momo5502
2024-09-11 12:52:24 +02:00
parent 920bc9dec6
commit 46302df864
5 changed files with 77 additions and 25 deletions

View File

@@ -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, [&]
{

View File

@@ -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)
{

View File

@@ -48,6 +48,7 @@ struct process_context
mapped_module* executable{};
mapped_module* ntdll{};
mapped_module* win32u{};
handle_store<handle_types::event, event> events{};
handle_store<handle_types::file, file> files{};

View File

@@ -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<uint64_t, size_t> reference_count{};
std::map<uint64_t, std::string> 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<std::string>& syscalls, const std::string_view name)
uint64_t get_syscall_id(const std::vector<std::string>& ntdll_syscalls, const std::vector<std::string>& 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<ULONG> number_of_bytes_readed)
const emulator_object<ULONG> 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<uint8_t> 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<CONTEXT> 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);
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(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); \
#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
}

View File

@@ -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);