From 9f437657adb25febf683204c724cb07ed2122e02 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 7 Sep 2024 21:41:00 +0200 Subject: [PATCH] Prepare handle cleanup --- src/windows_emulator/main.cpp | 7 ++- src/windows_emulator/syscalls.cpp | 74 ++++++++++++++------------ src/windows_emulator/syscalls.hpp | 88 ++++++++++++++++++++++++++----- 3 files changed, 116 insertions(+), 53 deletions(-) diff --git a/src/windows_emulator/main.cpp b/src/windows_emulator/main.cpp index e080172..0d22f0a 100644 --- a/src/windows_emulator/main.cpp +++ b/src/windows_emulator/main.cpp @@ -344,9 +344,9 @@ namespace proc_params.Length = sizeof(proc_params); proc_params.Flags = 0x6001 | 0x80000000; // Prevent CsrClientConnectToServer - proc_params.ConsoleHandle = reinterpret_cast(CONSOLE_HANDLE); - proc_params.StandardOutput = reinterpret_cast(STDOUT_HANDLE); - proc_params.StandardInput = reinterpret_cast(STDIN_HANDLE); + proc_params.ConsoleHandle = CONSOLE_HANDLE.h; + proc_params.StandardOutput = STDOUT_HANDLE.h; + proc_params.StandardInput = STDIN_HANDLE.h; proc_params.StandardError = proc_params.StandardOutput; gs.make_unicode_string(proc_params.CurrentDirectory.DosPath, L"C:\\Users\\mauri\\Desktop"); @@ -714,7 +714,6 @@ namespace const auto allocation_size = combined_size + mach_frame_size; - const auto initial_sp = emu.reg(x64_register::rsp); const auto new_sp = align_down(initial_sp - allocation_size, 0x100); diff --git a/src/windows_emulator/syscalls.cpp b/src/windows_emulator/syscalls.cpp index a1d8d9f..820721f 100644 --- a/src/windows_emulator/syscalls.cpp +++ b/src/windows_emulator/syscalls.cpp @@ -224,36 +224,38 @@ namespace NTSTATUS handle_NtSetEvent(const syscall_context& c, const uint64_t handle, const emulator_object previous_state) { - if (handle & EVENT_BIT) + const auto value = get_handle_value(handle); + if (value.type != handle_types::event) { - const auto event_index = static_cast(handle & ~EVENT_BIT); - const auto entry = c.proc.events.find(event_index); - if (entry != c.proc.events.end()) - { - if (previous_state.value()) - { - previous_state.write(entry->second.signaled ? 1ULL : 0ULL); - } + return STATUS_INVALID_HANDLE; + } - entry->second.signaled = true; - return STATUS_SUCCESS; - } + const auto entry = c.proc.events.find(value.id); + if (entry == c.proc.events.end()) + { + return STATUS_INVALID_HANDLE; } - return STATUS_INVALID_HANDLE; + if (previous_state.value()) + { + previous_state.write(entry->second.signaled ? 1ULL : 0ULL); + } + + entry->second.signaled = true; + return STATUS_SUCCESS; } NTSTATUS handle_NtClose(const syscall_context& c, const uint64_t handle) { - if (handle & PSEUDO_BIT) + const auto value = get_handle_value(handle); + if (value.is_pseudo) { return STATUS_SUCCESS; } - if (handle & EVENT_BIT) + if (value.type == handle_types::event) { - const auto event_index = static_cast(handle & ~EVENT_BIT); - const auto entry = c.proc.events.find(event_index); + const auto entry = c.proc.events.find(value.id); if (entry != c.proc.events.end()) { c.proc.events.erase(entry); @@ -261,10 +263,9 @@ namespace } } - if (handle & FILE_BIT) + if (value.type == handle_types::file) { - const auto event_index = static_cast(handle & ~FILE_BIT); - const auto entry = c.proc.files.find(event_index); + const auto entry = c.proc.files.find(value.id); if (entry != c.proc.files.end()) { c.proc.files.erase(entry); @@ -305,7 +306,8 @@ namespace } } - event_handle.write(index | EVENT_BIT); + const auto h = make_handle(index, handle_types::event, false); + event_handle.write(h.bits); c.proc.events.try_emplace(index, initial_state != FALSE, event_type); @@ -354,7 +356,8 @@ namespace } } - file_handle.write(index | FILE_BIT); + const auto h = make_handle(index, handle_types::file, false); + file_handle.write(h.bits); auto status = STATUS_SUCCESS; object_attributes.access([&](const OBJECT_ATTRIBUTES& attributes) @@ -384,7 +387,7 @@ namespace if (filename == L"\\Windows\\SharedSection") { - section_handle.write(SHARED_SECTION); + section_handle.write(SHARED_SECTION.bits); return STATUS_SUCCESS; } @@ -395,7 +398,6 @@ namespace return STATUS_NOT_SUPPORTED; } - if (filename.starts_with(L"api-ms-")) { filename = L"C:\\WINDOWS\\System32\\downlevel\\" + filename; @@ -419,7 +421,8 @@ namespace } } - section_handle.write(index | FILE_BIT); + const auto h = make_handle(index, handle_types::file, false); + section_handle.write(h.bits); c.proc.files.try_emplace(index, std::move(filename)); @@ -438,13 +441,13 @@ namespace return STATUS_INVALID_HANDLE; } - if (!(section_handle & FILE_BIT)) + const auto value = get_handle_value(section_handle); + if (value.type != handle_types::file) { return STATUS_INVALID_HANDLE; } - const auto section_index = static_cast(section_handle & ~FILE_BIT); - const auto section_entry = c.proc.files.find(section_index); + const auto section_entry = c.proc.files.find(value.id); if (section_entry == c.proc.files.end()) { return STATUS_INVALID_HANDLE; @@ -870,7 +873,7 @@ namespace if (object_name == L"\\KnownDlls") { - directory_handle.write(KNOWN_DLLS_DIRECTORY); + directory_handle.write(KNOWN_DLLS_DIRECTORY.bits); return STATUS_SUCCESS; } @@ -886,7 +889,7 @@ namespace if (object_name == L"KnownDllPath") { - link_handle.write(KNOWN_DLLS_SYMLINK); + link_handle.write(KNOWN_DLLS_SYMLINK.bits); return STATUS_SUCCESS; } @@ -1023,7 +1026,7 @@ namespace puts("NtCreateSection not supported"); c.emu.stop(); - section_handle.write(SHARED_SECTION); + section_handle.write(SHARED_SECTION.bits); /* maximum_size.access([](LARGE_INTEGER& large_int) { @@ -1139,14 +1142,15 @@ namespace if (filename == L"\\Device\\ConDrv\\Server") { - file_handle.write(CONSOLE_SERVER); + file_handle.write(CONSOLE_SERVER.bits); return STATUS_SUCCESS; } - const auto root_handle = reinterpret_cast(attributes.RootDirectory); - if ((root_handle & PSEUDO_BIT) && (filename == L"\\Reference" || filename == L"\\Connect")) + handle root_handle{}; + root_handle.bits = reinterpret_cast(attributes.RootDirectory); + if (root_handle.value.is_pseudo && (filename == L"\\Reference" || filename == L"\\Connect")) { - file_handle.write(root_handle); + file_handle.write(root_handle.bits); return STATUS_SUCCESS; } diff --git a/src/windows_emulator/syscalls.hpp b/src/windows_emulator/syscalls.hpp index e66a2c0..f58f38c 100644 --- a/src/windows_emulator/syscalls.hpp +++ b/src/windows_emulator/syscalls.hpp @@ -3,20 +3,80 @@ #include #include "process_context.hpp" -constexpr uint64_t PSEUDO_BIT = 1ULL << 63ULL; -constexpr uint64_t EVENT_BIT = 1ULL << 62ULL; -constexpr uint64_t DIRECTORY_BIT = 1ULL << 61ULL; -constexpr uint64_t SYMLINK_BIT = 1ULL << 60ULL; -constexpr uint64_t FILE_BIT = 1ULL << 59ULL; - -constexpr uint64_t KNOWN_DLLS_DIRECTORY = DIRECTORY_BIT | PSEUDO_BIT | 0x1337; -constexpr uint64_t KNOWN_DLLS_SYMLINK = SYMLINK_BIT | PSEUDO_BIT | 0x1337; -constexpr uint64_t SHARED_SECTION = FILE_BIT | PSEUDO_BIT | 0x1337; -constexpr uint64_t CONSOLE_SERVER = FILE_BIT | PSEUDO_BIT | 0x1338; - -constexpr uint64_t CONSOLE_HANDLE = FILE_BIT | PSEUDO_BIT | 0x01; -constexpr uint64_t STDOUT_HANDLE = FILE_BIT | PSEUDO_BIT | 0x02; -constexpr uint64_t STDIN_HANDLE = FILE_BIT | PSEUDO_BIT | 0x03; +struct handle_types +{ + enum type : uint16_t + { + file, + event, + section, + symlink, + directory, + }; +}; + +#pragma pack(push) +#pragma pack(1) +struct handle_value +{ + uint64_t id : 32; + uint64_t type : 16; + uint64_t padding : 15; + uint64_t is_pseudo : 1; +}; +#pragma pack(pop) + +static_assert(sizeof(handle_value) == 8); + +union handle +{ + handle_value value; + uint64_t bits; + HANDLE h; +}; + +inline bool operator==(const handle& h1, const handle& h2) +{ + return h1.bits == h2.bits; +} + +inline bool operator==(const handle& h1, const uint64_t& h2) +{ + return h1.bits == h2; +} + +inline handle_value get_handle_value(const uint64_t h) +{ + handle hh{}; + hh.bits = h; + return hh.value; +} + +constexpr handle make_handle(const uint32_t id, const handle_types::type type, const bool is_pseudo) +{ + handle_value value{}; + + value.padding = 0; + value.id = id; + value.type = type; + value.is_pseudo = is_pseudo; + + return {value}; +} + +constexpr handle make_pseudo_handle(const uint32_t id, const handle_types::type type) +{ + return make_handle(id, type, true); +} + +constexpr auto KNOWN_DLLS_DIRECTORY = make_pseudo_handle(0x1337, handle_types::directory); +constexpr auto KNOWN_DLLS_SYMLINK = make_pseudo_handle(0x1337, handle_types::symlink); +constexpr auto SHARED_SECTION = make_pseudo_handle(0x1337, handle_types::section); +constexpr auto CONSOLE_SERVER = make_pseudo_handle(0x1337, handle_types::section); + +constexpr auto CONSOLE_HANDLE = make_pseudo_handle(0x1, handle_types::file); +constexpr auto STDOUT_HANDLE = make_pseudo_handle(0x2, handle_types::file); +constexpr auto STDIN_HANDLE = make_pseudo_handle(0x3, handle_types::file); struct syscall_context; using syscall_handler = void(*)(const syscall_context& c);