diff --git a/src/common/platform/status.hpp b/src/common/platform/status.hpp index 720f700c..583f258a 100644 --- a/src/common/platform/status.hpp +++ b/src/common/platform/status.hpp @@ -36,6 +36,7 @@ using NTSTATUS = std::uint32_t; #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) #define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L) #define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034L) +#define STATUS_INVALID_PAGE_PROTECTION ((NTSTATUS)0xC0000045L) #define STATUS_MUTANT_NOT_OWNED ((NTSTATUS)0xC0000046L) #define STATUS_SEMAPHORE_LIMIT_EXCEEDED ((NTSTATUS)0xC0000047L) #define STATUS_NO_TOKEN ((NTSTATUS)0xC000007CL) diff --git a/src/samples/test-sample/test.cpp b/src/samples/test-sample/test.cpp index fa2d844a..d7f86742 100644 --- a/src/samples/test-sample/test.cpp +++ b/src/samples/test-sample/test.cpp @@ -792,6 +792,11 @@ namespace bool test_apis() { + if (VirtualProtect(nullptr, 0, 0, nullptr)) + { + return false; + } + wchar_t buffer[0x100]; DWORD size = sizeof(buffer) / 2; return GetComputerNameExW(ComputerNameNetBIOS, buffer, &size); diff --git a/src/windows-emulator/memory_utils.hpp b/src/windows-emulator/memory_utils.hpp index e50b0098..5c490223 100644 --- a/src/windows-emulator/memory_utils.hpp +++ b/src/windows-emulator/memory_utils.hpp @@ -20,7 +20,7 @@ inline std::string get_permission_string(const memory_permission permission) return res; } -inline nt_memory_permission map_nt_to_emulator_protection(uint32_t nt_protection) +inline std::optional try_map_nt_to_emulator_protection(uint32_t nt_protection) { memory_permission_ext ext = memory_permission_ext::none; // TODO: Check for invalid combinations @@ -51,14 +51,26 @@ inline nt_memory_permission map_nt_to_emulator_protection(uint32_t nt_protection case PAGE_EXECUTE_READWRITE: common = memory_permission::all; break; + case 0: case PAGE_EXECUTE_WRITECOPY: default: - throw std::runtime_error("Failed to map protection"); + return std::nullopt; } return nt_memory_permission{common, ext}; } +inline nt_memory_permission map_nt_to_emulator_protection(uint32_t nt_protection) +{ + const auto protection = try_map_nt_to_emulator_protection(nt_protection); + if (protection.has_value()) + { + return *protection; + } + + throw std::runtime_error("Failed to map protection: " + std::to_string(nt_protection)); +} + inline uint32_t map_emulator_to_nt_protection(const memory_permission permission) { const bool has_exec = (permission & memory_permission::exec) != memory_permission::none; diff --git a/src/windows-emulator/syscalls/memory.cpp b/src/windows-emulator/syscalls/memory.cpp index 0f08c057..42ca451b 100644 --- a/src/windows-emulator/syscalls/memory.cpp +++ b/src/windows-emulator/syscalls/memory.cpp @@ -144,15 +144,19 @@ namespace syscalls base_address.write(aligned_start); bytes_to_protect.write(static_cast(aligned_length)); - const auto requested_protection = map_nt_to_emulator_protection(protection); + const auto requested_protection = try_map_nt_to_emulator_protection(protection); + if (!requested_protection.has_value()) + { + return STATUS_INVALID_PAGE_PROTECTION; + } - c.win_emu.callbacks.on_memory_protect(aligned_start, aligned_length, requested_protection); + c.win_emu.callbacks.on_memory_protect(aligned_start, aligned_length, *requested_protection); nt_memory_permission old_protection_value{}; try { - c.win_emu.memory.protect_memory(aligned_start, static_cast(aligned_length), requested_protection, + c.win_emu.memory.protect_memory(aligned_start, static_cast(aligned_length), *requested_protection, &old_protection_value); } catch (...) @@ -180,7 +184,11 @@ namespace syscalls allocation_bytes = page_align_up(allocation_bytes); bytes_to_allocate.write(allocation_bytes); - const auto protection = map_nt_to_emulator_protection(page_protection); + const auto protection = try_map_nt_to_emulator_protection(page_protection); + if (!protection.has_value()) + { + return STATUS_INVALID_PAGE_PROTECTION; + } auto potential_base = base_address.read(); if (!potential_base) @@ -204,15 +212,15 @@ namespace syscalls } if (commit && !reserve && - c.win_emu.memory.commit_memory(potential_base, static_cast(allocation_bytes), protection)) + c.win_emu.memory.commit_memory(potential_base, static_cast(allocation_bytes), *protection)) { - c.win_emu.callbacks.on_memory_allocate(potential_base, allocation_bytes, protection, true); + c.win_emu.callbacks.on_memory_allocate(potential_base, allocation_bytes, *protection, true); return STATUS_SUCCESS; } - c.win_emu.callbacks.on_memory_allocate(potential_base, allocation_bytes, protection, false); + c.win_emu.callbacks.on_memory_allocate(potential_base, allocation_bytes, *protection, false); - return c.win_emu.memory.allocate_memory(potential_base, static_cast(allocation_bytes), protection, + return c.win_emu.memory.allocate_memory(potential_base, static_cast(allocation_bytes), *protection, !commit) ? STATUS_SUCCESS : STATUS_MEMORY_NOT_ALLOCATED;