> Windows Syscalls
ntoskrnl.exeT1057T1622T1106

NtQueryVirtualMemory

Liefert Informationen über Seiten im virtuellen Adressraum eines Zielprozesses.

Prototyp

NTSTATUS NtQueryVirtualMemory(
  HANDLE                   ProcessHandle,
  PVOID                    BaseAddress,
  MEMORY_INFORMATION_CLASS MemoryInformationClass,
  PVOID                    MemoryInformation,
  SIZE_T                   MemoryInformationLength,
  PSIZE_T                  ReturnLength
);

Argumente

NameTypeDirDescription
ProcessHandleHANDLEinHandle auf den abgefragten Prozess. Erfordert PROCESS_QUERY_INFORMATION.
BaseAddressPVOIDinAdresse innerhalb der abzufragenden Region. Muss nicht seitengerichtet sein.
MemoryInformationClassMEMORY_INFORMATION_CLASSinInformationsklasse (MemoryBasicInformation, MemoryMappedFilenameInformation, MemoryRegionInformation, MemoryWorkingSetExInformation, ...).
MemoryInformationPVOIDoutVom Aufrufer allokierter Puffer für die zurückgegebene Struktur.
MemoryInformationLengthSIZE_TinGröße des Ausgabepuffers in Bytes.
ReturnLengthPSIZE_ToutOptional. Erhält die Anzahl geschriebener oder benötigter Bytes.

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
Win10 15070x23win10-1507
Win10 16070x23win10-1607
Win10 17030x23win10-1703
Win10 17090x23win10-1709
Win10 18030x23win10-1803
Win10 18090x23win10-1809
Win10 19030x23win10-1903
Win10 19090x23win10-1909
Win10 20040x23win10-2004
Win10 20H20x23win10-20h2
Win10 21H10x23win10-21h1
Win10 21H20x23win10-21h2
Win10 22H20x23win10-22h2
Win11 21H20x23win11-21h2
Win11 22H20x23win11-22h2
Win11 23H20x23win11-23h2
Win11 24H20x23win11-24h2
Server 20160x23winserver-2016
Server 20190x23winserver-2019
Server 20220x23winserver-2022
Server 20250x23winserver-2025

Kernel-Modul

ntoskrnl.exeNtQueryVirtualMemory

Verwandte APIs

VirtualQueryVirtualQueryExNtQueryInformationProcessNtReadVirtualMemoryNtProtectVirtualMemory

Syscall-Stub

4C 8B D1            mov r10, rcx
B8 23 00 00 00      mov eax, 0x23
F6 04 25 08 03 FE 7F 01   test byte ptr [0x7FFE0308], 1
75 03               jne short +3
0F 05               syscall
C3                  ret
CD 2E               int 2Eh
C3                  ret

Undokumentierte Hinweise

NtQueryVirtualMemory behält SSN `0x23` über alle Windows-10-/11-/Server-Builds. Es ist die Kernel-Seite von VirtualQuery / VirtualQueryEx, exponiert aber eine deutlich reichere Informationsfläche: MemoryBasicInformation (Zustand, Typ, Schutz), MemoryMappedFilenameInformation (das hinterlegende Image / die Datei als NT-Pfad), MemoryRegionInformation (vollständige VAD-Subtree-Info ab Win10 1803), MemoryImageInformation, MemoryWorkingSetExInformation (Bits pro Seite gültig / locked / shared / shareable). Jede Klasse mappt auf einen eigenen MmQueryVirtualMemory-Branch.

Häufige Malware-Nutzung

Aufklärungs-Klassiker. Den Adressraum enumerieren, um (a) das AMSI-/ETWTI-Mapping im Host-Prozess vor dem Patchen zu lokalisieren, (b) saubere PE-Header in ntdll/kernel32 für `Perun's Fart`-artiges Fresh-Copy-Unhooking zu finden, (c) einen Remote-Prozess auf RWX- oder kürzlich allokierte RW-Regionen abzusuchen, (d) zu bestätigen, dass die Section eines manuell gemappten Image nicht von einem EDR ungemappt wurde. MemoryMappedFilenameInformation erlaubt zudem, im Host geladene EDR-DLLs zu identifizieren, ohne die PEB-Loader-Liste anzufassen.

Erkennungs­möglichkeiten

Hohe Aufrufraten sind normal — Debugger, Profiler und sogar Defender selbst durchlaufen Adressräume permanent. Interessante Telemetrie: Cross-Process-Queries (ProcessHandle != aktuell) aus nicht-instrumentalen Binaries, besonders gefolgt von NtProtectVirtualMemory oder NtWriteVirtualMemory auf dasselbe Ziel innerhalb von Millisekunden. Der ETW-Threat-Intelligence-Provider (`Microsoft-Windows-Threat-Intelligence`) emittiert ProtectVirtualMemory- und AllocVirtualMemory-Events für Cross-Process-Aktionen; Query-dann-Write zu korrelieren ist eine starke Injection-Heuristik.

Direkte Syscall-Beispiele

asmx64 direct stub

; Direct syscall stub for NtQueryVirtualMemory (SSN 0x23, all builds)
NtQueryVirtualMemory PROC
    mov  r10, rcx          ; syscall convention
    mov  eax, 23h          ; SSN
    syscall
    ret
NtQueryVirtualMemory ENDP

cAMSI mapping locator

// Walk the host VA space and locate amsi.dll's image mapping using
// MemoryMappedFilenameInformation -> AmsiScanBuffer can then be patched.
#include <windows.h>

#define MemoryMappedFilenameInformation 2

typedef NTSTATUS (NTAPI *pNtQueryVirtualMemory)(
    HANDLE, PVOID, ULONG, PVOID, SIZE_T, PSIZE_T);

PVOID FindAmsi(void) {
    pNtQueryVirtualMemory NtQueryVirtualMemory =
        (pNtQueryVirtualMemory)GetProcAddress(
            GetModuleHandleA("ntdll.dll"), "NtQueryVirtualMemory");

    BYTE buf[1024];
    SIZE_T ret;
    for (ULONG_PTR addr = 0x10000; addr < 0x7FFFFFFFFFFF; addr += 0x10000) {
        if (NtQueryVirtualMemory((HANDLE)-1, (PVOID)addr,
                MemoryMappedFilenameInformation, buf, sizeof buf, &ret) == 0) {
            UNICODE_STRING *us = (UNICODE_STRING*)buf;
            if (wcsstr(us->Buffer, L"\\amsi.dll"))
                return (PVOID)addr;
        }
    }
    return NULL;
}

rustMEMORY_BASIC_INFORMATION sweep

// Cargo: windows-sys = "0.59" (Win32_System_Memory, Win32_Foundation)
use windows_sys::Win32::System::Memory::*;
use windows_sys::Win32::Foundation::HANDLE;

// Find RWX regions in a remote process — implant validation, EDR audit, or victim recon.
pub unsafe fn find_rwx(proc_handle: HANDLE) -> Vec<usize> {
    let mut out = Vec::new();
    let mut addr: usize = 0;
    let mut mbi: MEMORY_BASIC_INFORMATION = core::mem::zeroed();
    while VirtualQueryEx(proc_handle, addr as _, &mut mbi,
                         core::mem::size_of_val(&mbi)) != 0 {
        if mbi.State == MEM_COMMIT && mbi.Protect == PAGE_EXECUTE_READWRITE {
            out.push(mbi.BaseAddress as usize);
        }
        addr = mbi.BaseAddress as usize + mbi.RegionSize;
    }
    out
}

MITRE ATT&CK-Mappings

Last verified: 2026-05-20