mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-19 11:43:56 +00:00
Support win32k syscalls
This commit is contained in:
@@ -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, [&]
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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{};
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user