From c6c297cb97e9a0328e3d69cc3658cfd3799215e1 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 19 Aug 2024 21:13:50 +0200 Subject: [PATCH] More syscalls --- src/emulator/main.cpp | 2 +- src/emulator/memory_utils.hpp | 51 +++++++++++++----- src/emulator/syscalls.cpp | 97 +++++++++++++++++++++++++++++++++-- 3 files changed, 133 insertions(+), 17 deletions(-) diff --git a/src/emulator/main.cpp b/src/emulator/main.cpp index 185ca083..1539cbd6 100644 --- a/src/emulator/main.cpp +++ b/src/emulator/main.cpp @@ -132,7 +132,7 @@ namespace auto& export_directory_entry = optional_header.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; if (export_directory_entry.VirtualAddress == 0 || export_directory_entry.Size == 0) { - return {}; + return binary; } const auto* export_directory = reinterpret_cast(ptr + export_directory_entry. diff --git a/src/emulator/memory_utils.hpp b/src/emulator/memory_utils.hpp index 1c4970a8..09505800 100644 --- a/src/emulator/memory_utils.hpp +++ b/src/emulator/memory_utils.hpp @@ -32,26 +32,51 @@ inline uint64_t page_align_up(const uint64_t value) return align_up(value, 0x1000); } -inline uint32_t get_memory_protection(const unicorn& uc, uint64_t address) +template +T access_memory_regions(const unicorn& uc, const F& accessor) { uint32_t count{}; uc_mem_region* regions{}; e(uc_mem_regions(uc, ®ions, &count)); const auto _ = utils::finally([&] - { - uc_free(regions); - }); - - for (const auto& region : std::span(regions, count)) { - if (is_within_start_and_end(address, region.begin, region.end)) - { - return region.perms; - } - } + uc_free(regions); + }); - return UC_PROT_NONE; + return accessor(std::span(regions, count)); +} + +inline uint32_t get_memory_protection(const unicorn& uc, const uint64_t address) +{ + return access_memory_regions(uc, [&](const std::span regions) -> uint32_t + { + for (const auto& region : regions) + { + if (is_within_start_and_end(address, region.begin, region.end)) + { + return region.perms; + } + } + + return UC_PROT_NONE; + }); +} + +inline bool is_memory_allocated(const unicorn& uc, const uint64_t address) +{ + return access_memory_regions(uc, [&](const std::span regions) + { + for (const auto& region : regions) + { + if (is_within_start_and_end(address, region.begin, region.end)) + { + return true; + } + } + + return false; + }); } inline uint32_t map_nt_to_unicorn_protection(const uint32_t nt_protection) @@ -102,4 +127,4 @@ inline uint32_t map_unicorn_to_nt_protection(const uint32_t unicorn_protection) } return PAGE_READONLY; -} \ No newline at end of file +} diff --git a/src/emulator/syscalls.cpp b/src/emulator/syscalls.cpp index ed30011f..b10f81c7 100644 --- a/src/emulator/syscalls.cpp +++ b/src/emulator/syscalls.cpp @@ -243,6 +243,61 @@ namespace uc.reg(UC_X86_REG_RAX, STATUS_SUCCESS); } + void handle_NtAllocateVirtualMemory(const unicorn& uc) + { + const auto process_handle = uc.reg(UC_X86_REG_R10); + const unicorn_object base_address{uc, uc.reg(UC_X86_REG_RDX)}; + const unicorn_object bytes_to_allocate{uc, uc.reg(UC_X86_REG_R9)}; + //const auto allocation_type = uc.reg(UC_X86_REG_R9D); + const auto page_protection = static_cast(uc.read_stack(6)); + + if (process_handle != ~0ULL) + { + uc.reg(UC_X86_REG_RAX, STATUS_NOT_IMPLEMENTED); + return; + } + + constexpr auto allocation_granularity = 0x10000; + const auto allocation_bytes = bytes_to_allocate.read(); + //allocation_bytes = align_up(allocation_bytes, allocation_granularity); + //bytes_to_allocate.write(allocation_bytes); + + const auto protection = map_nt_to_unicorn_protection(page_protection); + + auto allocate_anywhere = false; + auto allocation_base = base_address.read(); + if (!allocation_base) + { + allocate_anywhere = true; + allocation_base = allocation_granularity; + } + else if (is_memory_allocated(uc, allocation_base)) + { + uc.reg(UC_X86_REG_RAX, STATUS_SUCCESS); + return; + } + + bool succeeded = false; + + while (true) + { + succeeded = uc_mem_map(uc, allocation_base, allocation_bytes, protection) == UC_ERR_OK; + if (succeeded || !allocate_anywhere) + { + break; + } + + allocation_base += allocation_granularity; + } + + base_address.write(allocation_base); + + uc.reg(UC_X86_REG_RAX, succeeded + ? STATUS_SUCCESS + : STATUS_NOT_SUPPORTED // No idea what the correct code is + ); + } + void handle_NtAllocateVirtualMemoryEx(const unicorn& uc) { const auto process_handle = uc.reg(UC_X86_REG_R10); @@ -258,9 +313,9 @@ namespace } constexpr auto allocation_granularity = 0x10000; - auto allocation_bytes = bytes_to_allocate.read(); - allocation_bytes = align_up(allocation_bytes, allocation_granularity); - bytes_to_allocate.write(allocation_bytes); + const auto allocation_bytes = bytes_to_allocate.read(); + //allocation_bytes = align_up(allocation_bytes, allocation_granularity); + //bytes_to_allocate.write(allocation_bytes); const auto protection = map_nt_to_unicorn_protection(page_protection); @@ -271,6 +326,11 @@ namespace allocate_anywhere = true; allocation_base = allocation_granularity; } + else if (is_memory_allocated(uc, allocation_base)) + { + uc.reg(UC_X86_REG_RAX, STATUS_SUCCESS); + return; + } bool succeeded = false; @@ -285,6 +345,31 @@ namespace allocation_base += allocation_granularity; } + base_address.write(allocation_base); + + uc.reg(UC_X86_REG_RAX, succeeded + ? STATUS_SUCCESS + : STATUS_NOT_SUPPORTED // No idea what the correct code is + ); + } + + void handle_NtFreeVirtualMemory(const unicorn& uc) + { + const auto process_handle = uc.reg(UC_X86_REG_R10); + const unicorn_object base_address{uc, uc.reg(UC_X86_REG_RDX)}; + const unicorn_object bytes_to_allocate{uc, uc.reg(UC_X86_REG_R8)}; + + if (process_handle != ~0ULL) + { + uc.reg(UC_X86_REG_RAX, STATUS_NOT_IMPLEMENTED); + return; + } + + const auto allocation_base = base_address.read(); + const auto allocation_size = bytes_to_allocate.read(); + + const auto succeeded = uc_mem_unmap(uc, allocation_base, allocation_size) == UC_ERR_OK; + uc.reg(UC_X86_REG_RAX, succeeded ? STATUS_SUCCESS : STATUS_NOT_SUPPORTED // No idea what the correct code is @@ -306,6 +391,12 @@ void handle_syscall(const unicorn& uc, process_context& context) case 0x12: handle_NtOpenKey(uc); break; + case 0x18: + handle_NtAllocateVirtualMemory(uc); + break; + case 0x1E: + handle_NtFreeVirtualMemory(uc); + break; case 0x19: handle_NtQueryProcessInformation(uc, context); break;