diff --git a/deps/phnt b/deps/phnt index 8ef22dcb..a218107e 160000 --- a/deps/phnt +++ b/deps/phnt @@ -1 +1 @@ -Subproject commit 8ef22dcb850d2c82de57115bcaf457472da3ab3f +Subproject commit a218107e7a0eb16052a2124219778b3722e3681c diff --git a/src/windows_emulator/emulator_utils.hpp b/src/windows_emulator/emulator_utils.hpp index 3e693a06..ec273141 100644 --- a/src/windows_emulator/emulator_utils.hpp +++ b/src/windows_emulator/emulator_utils.hpp @@ -9,6 +9,11 @@ public: emulator_object() = default; + emulator_object(emulator& emu, const void* address) + : emulator_object(emu, reinterpret_cast(address)) + { + } + emulator_object(emulator& emu, const uint64_t address) : emu_(&emu) , address_(address) diff --git a/src/windows_emulator/main.cpp b/src/windows_emulator/main.cpp index 898ecc8e..49726ff9 100644 --- a/src/windows_emulator/main.cpp +++ b/src/windows_emulator/main.cpp @@ -197,7 +197,9 @@ namespace context.process_params.access([&](RTL_USER_PROCESS_PARAMETERS& proc_params) { + proc_params.Length = sizeof(proc_params); proc_params.Flags = 0x6001; + gs.make_unicode_string(proc_params.CurrentDirectory.DosPath, L"C:\\Users\\mauri\\Desktop"); gs.make_unicode_string(proc_params.ImagePathName, L"C:\\Users\\mauri\\Desktop\\ConsoleApplication6.exe"); gs.make_unicode_string(proc_params.CommandLine, L"C:\\Users\\mauri\\Desktop\\ConsoleApplication6.exe"); }); @@ -273,7 +275,7 @@ namespace template void watch_object(x64_emulator& emu, emulator_object object) { - type_info info{}; + const type_info info{}; emu.hook_memory_read(object.value(), object.size(), [i = std::move(info), object](const uint64_t address, size_t) @@ -315,14 +317,9 @@ namespace { auto name = exp.second; emu->hook_memory_execution(exp.first, 0, - [&emu, n = std::move(name)](const uint64_t address, const size_t) + [n = std::move(name)](const uint64_t address, const size_t) { printf("Executing function: %s (%llX)\n", n.c_str(), address); - - if (n == "RtlImageNtHeaderEx") - { - printf("Base: %llX\n", emu->reg(x64_register::rdx)); - } }); } @@ -338,23 +335,17 @@ namespace emu->hook_memory_execution(0, std::numeric_limits::max(), [&](const uint64_t address, const size_t) { - static bool hit = false; - // if (address == 0x1800D3C80) - if (address == 0x1800D4420) + if (address == 0x1800D52F4) { - //hit = true; - //uc.stop(); + //emu->stop(); } - //if (hit) - { - printf( - "Inst: %16llX - RAX: %16llX - RBX: %16llX - RCX: %16llX - RDX: %16llX - R8: %16llX - R9: %16llX - RDI: %16llX - RSI: %16llX\n", - address, - emu->reg(x64_register::rax), emu->reg(x64_register::rbx), emu->reg(x64_register::rcx), - emu->reg(x64_register::rdx), emu->reg(x64_register::r8), emu->reg(x64_register::r9), - emu->reg(x64_register::rdi), emu->reg(x64_register::rsi)); - } + printf( + "Inst: %16llX - RAX: %16llX - RBX: %16llX - RCX: %16llX - RDX: %16llX - R8: %16llX - R9: %16llX - RDI: %16llX - RSI: %16llX\n", + address, + emu->reg(x64_register::rax), emu->reg(x64_register::rbx), emu->reg(x64_register::rcx), + emu->reg(x64_register::rdx), emu->reg(x64_register::r8), emu->reg(x64_register::r9), + emu->reg(x64_register::rdi), emu->reg(x64_register::rsi)); }); const auto execution_context = context.gs_segment.reserve(); diff --git a/src/windows_emulator/process_context.hpp b/src/windows_emulator/process_context.hpp index 7d0b1b4b..97481215 100644 --- a/src/windows_emulator/process_context.hpp +++ b/src/windows_emulator/process_context.hpp @@ -37,5 +37,6 @@ struct process_context mapped_binary ntdll{}; std::map events{}; + std::map os_handles{}; emulator_allocator gs_segment{}; }; diff --git a/src/windows_emulator/syscalls.cpp b/src/windows_emulator/syscalls.cpp index 80246c56..22dedf2e 100644 --- a/src/windows_emulator/syscalls.cpp +++ b/src/windows_emulator/syscalls.cpp @@ -9,7 +9,13 @@ namespace process_context& proc; }; - constexpr uint64_t EVENT_BIT = 1ULL << 63ULL; + 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 KNOWN_DLLS_DIRECTORY = DIRECTORY_BIT | PSEUDO_BIT | 0x1337; + constexpr uint64_t KNOWN_DLLS_SYMLINK = SYMLINK_BIT | PSEUDO_BIT | 0x1337; uint64_t get_syscall_argument(x64_emulator& emu, const size_t index) { @@ -28,6 +34,68 @@ namespace } } + uint32_t store_os_handle(process_context& proc, const HANDLE handle) + { + uint32_t index = 1; + for (;; ++index) + { + if (!proc.os_handles.contains(index)) + { + break; + } + } + + proc.os_handles[index] = handle; + return index; + } + + std::optional get_os_handle(process_context& proc, const uint32_t handle) + { + const auto entry = proc.os_handles.find(handle); + if (entry == proc.os_handles.end()) + { + return {}; + } + + return entry->second; + } + + std::optional remove_os_handle(process_context& proc, const uint32_t handle) + { + const auto entry = proc.os_handles.find(handle); + if (entry == proc.os_handles.end()) + { + return {}; + } + + const auto res = entry->second; + proc.os_handles.erase(entry); + + return res; + } + + std::wstring read_unicode_string(emulator& emu, const emulator_object uc_string) + { + static_assert(offsetof(UNICODE_STRING, Length) == 0); + static_assert(offsetof(UNICODE_STRING, MaximumLength) == 2); + static_assert(offsetof(UNICODE_STRING, Buffer) == 8); + static_assert(sizeof(UNICODE_STRING) == 16); + + const auto ucs = uc_string.read(); + + std::wstring result{}; + result.resize(ucs.Length / 2); + + emu.read_memory(reinterpret_cast(ucs.Buffer), result.data(), ucs.Length); + + return result; + } + + std::wstring read_unicode_string(emulator& emu, const PUNICODE_STRING uc_string) + { + return read_unicode_string(emu, emulator_object{emu, uc_string}); + } + template requires(std::is_integral_v || std::is_enum_v) T resolve_argument(x64_emulator& emu, const size_t index) @@ -139,6 +207,11 @@ namespace NTSTATUS handle_NtClose(const syscall_context& c, const uint64_t handle) { + if (handle & PSEUDO_BIT) + { + return STATUS_SUCCESS; + } + if (handle & EVENT_BIT) { const auto event_index = static_cast(handle & ~EVENT_BIT); @@ -212,7 +285,8 @@ namespace return STATUS_NOT_IMPLEMENTED; } - if (info_class == MemoryWorkingSetExInformation) + if (info_class == MemoryWorkingSetExInformation + || info_class == MemoryImageExtensionInformation) { return STATUS_NOT_IMPLEMENTED; } @@ -464,6 +538,72 @@ namespace return STATUS_SUCCESS; } + NTSTATUS handle_NtOpenDirectoryObject(const syscall_context& c, + const emulator_object directory_handle, + const ACCESS_MASK /*desired_access*/, + const emulator_object object_attributes) + { + const auto attributes = object_attributes.read(); + const auto object_name = read_unicode_string(c.emu, attributes.ObjectName); + + if (object_name == L"\\KnownDlls") + { + directory_handle.write(KNOWN_DLLS_DIRECTORY); + return STATUS_SUCCESS; + } + + return STATUS_NOT_SUPPORTED; + } + + NTSTATUS handle_NtOpenSymbolicLinkObject(const syscall_context& c, const emulator_object link_handle, + ACCESS_MASK /*desired_access*/, + const emulator_object object_attributes) + { + const auto attributes = object_attributes.read(); + const auto object_name = read_unicode_string(c.emu, attributes.ObjectName); + + if (object_name == L"KnownDllPath") + { + link_handle.write(KNOWN_DLLS_SYMLINK); + return STATUS_SUCCESS; + } + + return STATUS_NOT_SUPPORTED; + } + + NTSTATUS WINAPI handle_NtQuerySymbolicLinkObject(const syscall_context& c, const uint64_t link_handle, + const emulator_object link_target, + const emulator_object returned_length) + { + if (link_handle == KNOWN_DLLS_SYMLINK) + { + constexpr std::wstring_view system32 = L"C:\\WINDOWS\\System32"; + constexpr auto str_length = system32.size() * 2; + constexpr auto max_length = str_length + 2; + + returned_length.write(max_length); + + bool too_small = false; + link_target.access([&](UNICODE_STRING& str) + { + if (str.MaximumLength < max_length) + { + too_small = true; + return; + } + + str.Length = str_length; + c.emu.write_memory(reinterpret_cast(str.Buffer), system32.data(), max_length); + }); + + return too_small + ? STATUS_BUFFER_TOO_SMALL + : STATUS_SUCCESS; + } + + return STATUS_NOT_SUPPORTED; + } + NTSTATUS handle_NtAllocateVirtualMemoryEx(const syscall_context& c, const uint64_t process_handle, const emulator_object base_address, const emulator_object bytes_to_allocate, @@ -571,12 +711,15 @@ namespace handle(0x036, handle_NtQuerySystemInformation); handle(0x048, handle_NtCreateEvent); handle(0x050, handle_NtProtectVirtualMemory); + handle(0x058, handle_NtOpenDirectoryObject); handle(0x05E, handle_NtTraceEvent); handle(0x078, handle_NtAllocateVirtualMemoryEx); handle(0x0B2, handle_NtCreateIoCompletion); handle(0x0D2, handle_NtCreateWaitCompletionPacket); handle(0x0D5, handle_NtCreateWorkerFactory); handle(0x11A, handle_NtManageHotPatch); + handle(0x138, handle_NtOpenSymbolicLinkObject); + handle(0x16B, handle_NtQuerySymbolicLinkObject); handle(0x16E, handle_NtQuerySystemInformationEx); default: