From 24e37e7bf51b3e6f906ac211c99cf24531b71415 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 25 Dec 2024 10:33:20 +0100 Subject: [PATCH 01/10] Add directory I/O test --- src/test-sample/test.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/test-sample/test.cpp b/src/test-sample/test.cpp index a0ff5167..07d09516 100644 --- a/src/test-sample/test.cpp +++ b/src/test-sample/test.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -153,6 +154,18 @@ bool test_io() return text == buffer; } +bool test_dir_io() +{ + size_t count = 0; + + for(auto i : std::filesystem::directory_iterator(R"(C:\Windows\System32\)")) + { + ++count; + } + + return count > 30; +} + std::optional read_registry_string(const HKEY root, const char* path, const char* value) { HKEY key{}; @@ -263,6 +276,7 @@ int main(int argc, const char* argv[]) bool valid = true; RUN_TEST(test_io, "I/O") + RUN_TEST(test_dir_io, "Dir I/O") RUN_TEST(test_registry, "Registry") RUN_TEST(test_threads, "Threads") RUN_TEST(test_env, "Environment") From 6f8f87010383a8b6d29a5ee269749389105f8f3a Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 25 Dec 2024 12:41:43 +0100 Subject: [PATCH 02/10] Directory enumertion --- src/windows-emulator/emulator_utils.hpp | 5 + src/windows-emulator/process_context.hpp | 48 +++++++++- src/windows-emulator/syscalls.cpp | 115 ++++++++++++++++++++++- 3 files changed, 166 insertions(+), 2 deletions(-) diff --git a/src/windows-emulator/emulator_utils.hpp b/src/windows-emulator/emulator_utils.hpp index 805f1a3c..bfa448a3 100644 --- a/src/windows-emulator/emulator_utils.hpp +++ b/src/windows-emulator/emulator_utils.hpp @@ -130,6 +130,11 @@ public: buffer.read(this->address_); } + void set_address(const uint64_t address) + { + this->address_ = address; + } + private: emulator* emu_{}; uint64_t address_{}; diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 97269c94..e850f703 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -140,20 +140,66 @@ struct mutant : ref_counted_object } }; +struct file_entry +{ + std::filesystem::path file_path{}; + + void serialize(utils::buffer_serializer& buffer) const + { + buffer.write(this->file_path); + } + + void deserialize(utils::buffer_deserializer& buffer) + { + buffer.read(this->file_path); + } +}; + +struct file_enumeration_state +{ + size_t current_index{0}; + std::vector files{}; + + void serialize(utils::buffer_serializer& buffer) const + { + buffer.write(this->current_index); + buffer.write_vector(this->files); + } + + void deserialize(utils::buffer_deserializer& buffer) + { + buffer.read(this->current_index); + buffer.read_vector(this->files); + } +}; + struct file { utils::file_handle handle{}; std::wstring name{}; + std::optional enumeration_state{}; + + bool is_file() const + { + return this->handle; + } + + bool is_directory() const + { + return !this->is_file(); + } void serialize(utils::buffer_serializer& buffer) const { - buffer.write(this->name); // TODO: Serialize handle + buffer.write(this->name); + buffer.write_optional(this->enumeration_state); } void deserialize(utils::buffer_deserializer& buffer) { buffer.read(this->name); + buffer.read_optional(this->enumeration_state); this->handle = {}; } }; diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 7d8e9075..c821ff34 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -1420,6 +1420,118 @@ namespace return STATUS_NOT_SUPPORTED; } + std::vector scan_directory(const std::filesystem::path& dir) + { + std::vector files{}; + + for (const auto& file : std::filesystem::directory_iterator(dir)) + { + files.emplace_back(file.path()); + } + + return files; + } + + NTSTATUS handle_NtQueryDirectoryFileEx(const syscall_context& c, const handle file_handle, + const handle /*event_handle*/, + const emulator_pointer /*PIO_APC_ROUTINE*/ /*apc_routine*/, + const emulator_pointer /*apc_context*/, + const emulator_object io_status_block, + const uint64_t file_information, const uint32_t length, + const uint32_t info_class, const ULONG query_flags, + const emulator_object /*file_name*/) + { + auto* f = c.proc.files.get(file_handle); + if (!f || !f->is_directory()) + { + return STATUS_INVALID_HANDLE; + } + + if (!f->enumeration_state || query_flags & SL_RESTART_SCAN) + { + f->enumeration_state.emplace(file_enumeration_state{}); + f->enumeration_state->files = scan_directory(f->name); + } + + auto& enum_state = *f->enumeration_state; + + if (info_class == FileFullDirectoryInformation) + { + size_t current_offset{0}; + emulator_object object{c.emu}; + + size_t current_index = enum_state.current_index; + + do + { + if (current_index >= enum_state.files.size()) + { + break; + } + + const auto new_offset = align_up(current_offset, 8); + const auto& current_file = enum_state.files[current_index]; + const auto file_name = current_file.file_path.u16string(); + const auto required_size = sizeof(FILE_FULL_DIR_INFORMATION) + (file_name.size() * 2) - 2; + const auto end_offset = new_offset + required_size; + + if (end_offset > length) + { + if (current_offset == 0) + { + IO_STATUS_BLOCK block{}; + block.Information = end_offset; + io_status_block.write(block); + + return STATUS_BUFFER_OVERFLOW; + } + + break; + } + + if (object) + { + object.access([&](FILE_FULL_DIR_INFORMATION& dir_info) + { + dir_info.NextEntryOffset = static_cast(new_offset); + }); + } + + FILE_FULL_DIR_INFORMATION info{}; + info.NextEntryOffset = 0; + info.FileIndex = static_cast(current_index); + info.FileAttributes = FILE_ATTRIBUTE_NORMAL; + info.FileNameLength = static_cast(file_name.size() * 2); + + object.set_address(file_information + new_offset); + object.write(info); + + c.emu.write_memory(object.value() + offsetof(FILE_FULL_DIR_INFORMATION, FileName), file_name.data(), + info.FileNameLength); + + ++current_index; + current_offset = end_offset; + } + while ((query_flags & SL_RETURN_SINGLE_ENTRY) == 0); + + if ((query_flags & SL_NO_CURSOR_UPDATE) == 0) + { + f->enumeration_state->current_index = current_index; + } + + IO_STATUS_BLOCK block{}; + block.Information = current_offset; + io_status_block.write(block); + + return current_index < enum_state.files.size() ? STATUS_SUCCESS : STATUS_NO_MORE_FILES; + } + + printf("Unsupported query directory file info class: %X\n", info_class); + c.emu.stop(); + + return STATUS_NOT_SUPPORTED; + } + NTSTATUS handle_NtQueryInformationFile(const syscall_context& c, const handle file_handle, const emulator_object io_status_block, const uint64_t file_information, const uint32_t length, @@ -1473,7 +1585,7 @@ namespace const emulator_object info{c.emu, file_information}; FILE_STANDARD_INFORMATION i{}; - i.Directory = f->handle ? FALSE : TRUE; + i.Directory = f->is_directory() ? TRUE : FALSE; if (f->handle) { @@ -3279,6 +3391,7 @@ void syscall_dispatcher::add_handlers(std::map& ha add_handler(NtQueryTimerResolution); add_handler(NtSetInformationKey); add_handler(NtUserGetKeyboardLayout); + add_handler(NtQueryDirectoryFileEx); #undef add_handler } From fcf8fc001ec663bf99bfadc9d49a1c514a4fea16 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 25 Dec 2024 14:43:40 +0100 Subject: [PATCH 03/10] Add new syscall --- src/windows-emulator/syscalls.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index c821ff34..73df1642 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -3056,6 +3056,12 @@ namespace return STATUS_INVALID_PARAMETER; } + NTSTATUS handle_NtUnmapViewOfSectionEx(const syscall_context& c, const handle process_handle, + const uint64_t base_address, const ULONG /*flags*/) + { + return handle_NtUnmapViewOfSection(c, process_handle, base_address); + } + NTSTATUS handle_NtCreateThreadEx(const syscall_context& c, const emulator_object thread_handle, const ACCESS_MASK /*desired_access*/, const emulator_object /*object_attributes*/, @@ -3347,6 +3353,7 @@ void syscall_dispatcher::add_handlers(std::map& ha add_handler(NtAddAtomEx); add_handler(NtInitializeNlsFiles); add_handler(NtUnmapViewOfSection); + add_handler(NtUnmapViewOfSectionEx); add_handler(NtDuplicateObject); add_handler(NtQueryInformationThread); add_handler(NtQueryWnfStateNameInformation); From b5ca800e7d72a24b7d60534c98a714abe5e29dda Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 25 Dec 2024 14:43:49 +0100 Subject: [PATCH 04/10] Disable broken code --- src/windows-emulator/syscalls.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 73df1642..104f500e 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -2487,12 +2487,12 @@ namespace return STATUS_NOT_SUPPORTED; } - const emulator_object data{c.emu, receive_message.value() + 0x48}; + /*const emulator_object data{c.emu, receive_message.value() + 0x48}; const auto dest = data.read(); const auto base = reinterpret_cast(dest.Base); const auto value = base + 0x10; - c.emu.write_memory(base + 8, &value, sizeof(value)); + c.emu.write_memory(base + 8, &value, sizeof(value));*/ return STATUS_SUCCESS; } From 62de7c0564e0efe7c9a19075c175c0e585402edd Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 25 Dec 2024 14:44:05 +0100 Subject: [PATCH 05/10] Add token handler --- src/windows-emulator/syscalls.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 104f500e..8fd84937 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -2343,6 +2343,21 @@ namespace return STATUS_SUCCESS; } + if (token_information_class == TokenStatistics) + { + constexpr auto required_size = sizeof(TOKEN_STATISTICS); + return_length.write(required_size); + + if (required_size > token_information_length) + { + return STATUS_BUFFER_TOO_SMALL; + } + + c.emu.write_memory(token_information, TOKEN_STATISTICS{}); + + return STATUS_SUCCESS; + } + if (token_information_class == TokenSecurityAttributes) { constexpr auto required_size = sizeof(TOKEN_SECURITY_ATTRIBUTES_INFORMATION); From 5b5db035219f598284cf6560e9e503322865b144 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 25 Dec 2024 14:44:13 +0100 Subject: [PATCH 06/10] Accurate file enumeration --- src/windows-emulator/syscalls.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 8fd84937..f6bad741 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -1422,11 +1422,14 @@ namespace std::vector scan_directory(const std::filesystem::path& dir) { - std::vector files{}; + std::vector files{ + {"."}, + {".."}, + }; for (const auto& file : std::filesystem::directory_iterator(dir)) { - files.emplace_back(file.path()); + files.emplace_back(file.path().filename()); } return files; From 68d5a0532f15a18b524efef923b96cb18d3f8a4b Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 25 Dec 2024 14:58:15 +0100 Subject: [PATCH 07/10] Check if logger output is disabled --- src/windows-emulator/logger.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/windows-emulator/logger.hpp b/src/windows-emulator/logger.hpp index be4ffe91..139d0a1d 100644 --- a/src/windows-emulator/logger.hpp +++ b/src/windows-emulator/logger.hpp @@ -54,6 +54,11 @@ public: this->disable_output_ = value; } + bool is_output_disabled() const + { + return this->disable_output_; + } + private: bool disable_output_{false}; }; From df812fd24d77904e2387ed2b4ff3c9e74324fd22 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 25 Dec 2024 15:06:07 +0100 Subject: [PATCH 08/10] Fix offsets --- src/windows-emulator/syscalls.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index f6bad741..6f2859b5 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -1494,9 +1494,11 @@ namespace if (object) { + const auto object_offset = object.value() - file_information; + object.access([&](FILE_FULL_DIR_INFORMATION& dir_info) { - dir_info.NextEntryOffset = static_cast(new_offset); + dir_info.NextEntryOffset = static_cast(new_offset - object_offset); }); } From cb88ebe480286678a8473f7d0f8d842ed639c486 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 25 Dec 2024 15:32:21 +0100 Subject: [PATCH 09/10] Fix warning --- src/windows-emulator/syscalls.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 6f2859b5..bbedf287 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -2489,7 +2489,7 @@ namespace const emulator_object /*send_message_attributes*/ , - const emulator_object receive_message, + const emulator_object /*receive_message*/, const emulator_object /*buffer_length*/, const emulator_object /*receive_message_attributes*/, From 724446620c2f393335dd5ba63c6648a6eef17ac1 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Thu, 26 Dec 2024 09:37:10 +0100 Subject: [PATCH 10/10] Small fixes --- src/test-sample/test.cpp | 6 +++++- src/windows-emulator/syscalls.cpp | 8 +++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/test-sample/test.cpp b/src/test-sample/test.cpp index 07d09516..4d146e56 100644 --- a/src/test-sample/test.cpp +++ b/src/test-sample/test.cpp @@ -158,9 +158,13 @@ bool test_dir_io() { size_t count = 0; - for(auto i : std::filesystem::directory_iterator(R"(C:\Windows\System32\)")) + for (auto i : std::filesystem::directory_iterator(R"(C:\Windows\System32\)")) { ++count; + if (count > 30) + { + return true; + } } return count > 30; diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index bbedf287..9fa1a028 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -2489,7 +2489,7 @@ namespace const emulator_object /*send_message_attributes*/ , - const emulator_object /*receive_message*/, + const emulator_object receive_message, const emulator_object /*buffer_length*/, const emulator_object /*receive_message_attributes*/, @@ -2507,12 +2507,14 @@ namespace return STATUS_NOT_SUPPORTED; } - /*const emulator_object data{c.emu, receive_message.value() + 0x48}; + // TODO: Fix this. This is broken and wrong. + + const emulator_object data{c.emu, receive_message.value() + 0x48}; const auto dest = data.read(); const auto base = reinterpret_cast(dest.Base); const auto value = base + 0x10; - c.emu.write_memory(base + 8, &value, sizeof(value));*/ + c.emu.write_memory(base + 8, &value, sizeof(value)); return STATUS_SUCCESS; }