Bugfixes - minidump load, memory tail boundary (#568)

Minor change to allow minidump load to work with pages with copy
permission set.

File was probing memory via VirtualQuery incrementally, previously this
ran forever as Sogen doesn't replicate Windows behaviour.

Added exclusive allocation end boundary so that allocation / info check
on last page of user space VA works. Modified
memory_manager::find_free_allocation_base and
memory_manager::get_region_info to use exclusive boundary.
Added check to NtQueryVirtualMemory - now correctly returns
STATUS_INVALID_PARAMETER when run against memory outside of user space
VA. Kernel modules should use ZwQueryVirtualMemory not the user land
API.
This commit is contained in:
Maurice Heumann
2025-10-25 10:55:18 +02:00
committed by GitHub
5 changed files with 20 additions and 8 deletions

View File

@@ -504,7 +504,7 @@ uint64_t memory_manager::find_free_allocation_base(const size_t size, const uint
start_address = align_up(region_end, ALLOCATION_GRANULARITY);
}
if (start_address + size <= MAX_ALLOCATION_ADDRESS)
if (start_address + size <= MAX_ALLOCATION_END_EXCL)
{
return start_address;
}
@@ -516,7 +516,7 @@ region_info memory_manager::get_region_info(const uint64_t address)
{
region_info result{};
result.start = MIN_ALLOCATION_ADDRESS;
result.length = static_cast<size_t>(MAX_ALLOCATION_ADDRESS - result.start);
result.length = static_cast<size_t>(MAX_ALLOCATION_END_EXCL - result.start);
result.permissions = nt_memory_permission();
result.initial_permissions = nt_memory_permission();
result.allocation_base = {};
@@ -541,7 +541,7 @@ region_info memory_manager::get_region_info(const uint64_t address)
if (lower_end <= address)
{
result.start = lower_end;
result.length = static_cast<size_t>(MAX_ALLOCATION_ADDRESS - result.start);
result.length = static_cast<size_t>(MAX_ALLOCATION_END_EXCL - result.start);
return result;
}

View File

@@ -12,6 +12,7 @@
constexpr auto ALLOCATION_GRANULARITY = 0x0000000000010000ULL;
constexpr auto MIN_ALLOCATION_ADDRESS = 0x0000000000010000ULL;
constexpr auto MAX_ALLOCATION_ADDRESS = 0x00007ffffffeffffULL;
constexpr auto MAX_ALLOCATION_END_EXCL = MAX_ALLOCATION_ADDRESS + 1ULL;
// This maps to the `basic_memory_region` struct defined in
// emulator\memory_region.hpp

View File

@@ -51,8 +51,10 @@ inline std::optional<nt_memory_permission> try_map_nt_to_emulator_protection(uin
case PAGE_EXECUTE_READWRITE:
common = memory_permission::all;
break;
case 0:
case PAGE_EXECUTE_WRITECOPY:
common = memory_permission::all;
break;
case 0:
default:
return std::nullopt;
}

View File

@@ -20,6 +20,15 @@ namespace syscalls
return STATUS_NOT_SUPPORTED;
}
if (base_address < MIN_ALLOCATION_ADDRESS || base_address >= MAX_ALLOCATION_END_EXCL)
{
if (return_length)
{
return_length.write(0);
}
return STATUS_INVALID_PARAMETER;
}
if (info_class == MemoryBasicInformation)
{
if (return_length)

View File

@@ -443,8 +443,8 @@ void windows_emulator::setup_hooks()
this->callbacks.on_rdtscp();
const auto ticks = this->clock_->timestamp_counter();
this->emu().reg(x86_register::rax, ticks & 0xFFFFFFFF);
this->emu().reg(x86_register::rdx, (ticks >> 32) & 0xFFFFFFFF);
this->emu().reg(x86_register::rax, static_cast<uint32_t>(ticks));
this->emu().reg(x86_register::rdx, static_cast<uint32_t>(ticks >> 32));
// Return the IA32_TSC_AUX value in RCX (low 32 bits)
auto tsc_aux = 0; // Need to replace this with proper CPUID later
@@ -457,8 +457,8 @@ void windows_emulator::setup_hooks()
this->callbacks.on_rdtsc();
const auto ticks = this->clock_->timestamp_counter();
this->emu().reg(x86_register::rax, ticks & 0xFFFFFFFF);
this->emu().reg(x86_register::rdx, (ticks >> 32) & 0xFFFFFFFF);
this->emu().reg(x86_register::rax, static_cast<uint32_t>(ticks));
this->emu().reg(x86_register::rdx, static_cast<uint32_t>(ticks >> 32));
return instruction_hook_continuation::skip_instruction;
});