> Windows Syscalls
ntoskrnl.exeT1564.004T1564T1106

NtQueryEaFile

Liest NTFS Extended Attributes (EAs) von einem Datei-Handle, optional gefiltert oder seitenweise.

Prototyp

NTSTATUS NtQueryEaFile(
  HANDLE           FileHandle,
  PIO_STATUS_BLOCK IoStatusBlock,
  PVOID            Buffer,
  ULONG            Length,
  BOOLEAN          ReturnSingleEntry,
  PVOID            EaList,
  ULONG            EaListLength,
  PULONG           EaIndex,
  BOOLEAN          RestartScan
);

Argumente

NameTypeDirDescription
FileHandleHANDLEinHandle auf eine geöffnete Datei (muss FILE_READ_EA-Zugriff enthalten).
IoStatusBlockPIO_STATUS_BLOCKoutEmpfängt Abschlussstatus und in Buffer geschriebene Bytes.
BufferPVOIDoutEmpfängt ein Array von FILE_FULL_EA_INFORMATION-Datensätzen.
LengthULONGinGröße von Buffer in Bytes.
ReturnSingleEntryBOOLEANinBei TRUE wird nur das erste passende EA zurückgegeben, auch wenn mehr in Buffer passen.
EaListPVOIDinOptionale Liste von FILE_GET_EA_INFORMATION-Einträgen für bestimmte EAs (NULL = alle).
EaListLengthULONGinGröße von EaList in Bytes, oder 0 wenn EaList NULL ist.
EaIndexPULONGinOptionaler 1-basierter Index in der EA-Liste der Datei, ab dem die Enumeration startet.
RestartScanBOOLEANinBei TRUE startet die Enumeration beim ersten EA neu; FALSE setzt vom vorherigen Aufruf fort.

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
Win10 15070x12Dwin10-1507
Win10 16070x133win10-1607
Win10 17030x138win10-1703
Win10 17090x13Bwin10-1709
Win10 18030x13Dwin10-1803
Win10 18090x13Ewin10-1809
Win10 19030x13Fwin10-1903
Win10 19090x13Fwin10-1909
Win10 20040x145win10-2004
Win10 20H20x145win10-20h2
Win10 21H10x145win10-21h1
Win10 21H20x146win10-21h2
Win10 22H20x146win10-22h2
Win11 21H20x14Cwin11-21h2
Win11 22H20x14Ewin11-22h2
Win11 23H20x14Ewin11-23h2
Win11 24H20x150win11-24h2
Server 20160x133winserver-2016
Server 20190x13Ewinserver-2019
Server 20220x14Bwinserver-2022
Server 20250x150winserver-2025

Kernel-Modul

ntoskrnl.exeNtQueryEaFile

Verwandte APIs

NtSetEaFileZwQueryEaFileGetFileInformationByHandleEx (FileFullEaInformation)BackupRead (BACKUP_EA_DATA stream)FILE_FULL_EA_INFORMATIONFILE_GET_EA_INFORMATION

Syscall-Stub

4C 8B D1            mov r10, rcx
B8 50 01 00 00      mov eax, 0x150     ; Win11 24H2 SSN
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

Gegenstück zu `NtSetEaFile`. Mit 9 Argumenten, zwei davon auf x64 über den Stack, gehört dies zu den klobigeren Datei-Syscalls — Aufrufstellen wickeln ihn meist in einen kleinen Helper, der `NULL/0/NULL/FALSE` für das optionale Filter/Index/Restart-Trio übergibt, wenn alle EAs gewünscht sind. Der Kernel liefert `STATUS_NO_EAS_ON_FILE` für Dateien ohne EA-Stream und `STATUS_NONEXISTENT_EA_ENTRY` für ein fehlendes benanntes Lookup zurück — beides nützliche negative Orakel beim Sondieren.

Häufige Malware-Nutzung

Die Leseseite des EA-Stealth-Patterns: ein Implant, der zuvor Konfiguration oder Shellcode via `NtSetEaFile` versteckt hat, lädt es später mit `NtQueryEaFile` zurück. Das EA über den `EaList`-Parameter explizit zu benennen ist gegenüber einer vollständigen Enumeration vorzuziehen, weil es weniger Telemetrie-Spuren hinterlässt und Scanner umgeht, die alle EAs der Datei durchlaufen. Manche Loader nutzen den EA-Pfad auch als Integritäts-Seitenkanal — Existenz und exakte Größe des Payloads fungieren als Manipulationsdetektor vor der Entschlüsselung.

Erkennungs­möglichkeiten

`NtQueryEaFile` allein ist harmlos — das OS selbst ruft ihn auf Roaming-Profile-Freigaben auf und immer dann, wenn WSL/Cygwin-Berechtigungs-EAs gelesen werden. Das Signal liegt im *Muster*: ein Prozess, der eine Nicht-WSL-Datei mit FILE_READ_EA öffnet und unmittelbar in den zurückgegebenen Blob entschlüsselt/springt. ETW Microsoft-Windows-Kernel-File `FileQueryEa`-Event, gekoppelt mit einem nachfolgenden VirtualProtect→RX auf einer frisch aus diesem Puffer beschriebenen Region, ist die hochgradig zuverlässige Korrelation. Isolierte EA-Queries aus `svchost.exe`, `lsass.exe` oder einem signierten Microsoft-Binary gegen eine vom Benutzer schreibbare Datei sollten hervorgehoben werden.

Direkte Syscall-Beispiele

cTargeted single-EA read

// Fetch only the 'CONFIG.BIN' EA — avoids a noisy full enumeration.
HANDLE h = CreateFileW(L"C:\\ProgramData\\update.dat", FILE_READ_EA, FILE_SHARE_READ,
                       NULL, OPEN_EXISTING, 0, NULL);

struct {
    ULONG  NextEntryOffset;
    UCHAR  EaNameLength;
    CHAR   EaName[12];   // "CONFIG.BIN\0" + padding
} eaList = { 0, 10, "CONFIG.BIN\0" };

BYTE out[4096];
IO_STATUS_BLOCK iosb;
NTSTATUS st = NtQueryEaFile(h, &iosb, out, sizeof(out),
                            TRUE,                  // single entry
                            &eaList, sizeof(eaList),
                            NULL,                  // no index
                            TRUE);                 // restart scan
if (NT_SUCCESS(st)) {
    PFILE_FULL_EA_INFORMATION ea = (PFILE_FULL_EA_INFORMATION)out;
    decrypt_and_run(ea->EaName + ea->EaNameLength + 1, ea->EaValueLength);
}

asmx64 direct stub

; NtQueryEaFile direct syscall (Win11 24H2 SSN 0x150)
NtQueryEaFile PROC
    mov  r10, rcx
    mov  eax, 150h
    syscall
    ret
NtQueryEaFile ENDP

rustEnumerate every EA on a file

// Cargo: windows-sys = "0.59"
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::System::LibraryLoader::*;

type NtQueryEaFileFn = unsafe extern "system" fn(
    HANDLE, *mut u8, *mut u8, u32, u8, *const u8, u32, *mut u32, u8,
) -> i32;

unsafe fn dump_eas(h: HANDLE) -> Vec<(String, Vec<u8>)> {
    let nt = GetModuleHandleA(b"ntdll.dll\0".as_ptr());
    let f: NtQueryEaFileFn = std::mem::transmute(
        GetProcAddress(nt, b"NtQueryEaFile\0".as_ptr()).unwrap()
    );
    let mut buf = vec![0u8; 0x10000];
    let mut iosb = [0u8; 16];
    let st = f(h, iosb.as_mut_ptr(), buf.as_mut_ptr(), buf.len() as u32,
               0, std::ptr::null(), 0, std::ptr::null_mut(), 1);
    if st < 0 { return vec![]; }
    // Walk NextEntryOffset chain ... (omitted for brevity)
    Vec::new()
}

MITRE ATT&CK-Mappings

Last verified: 2026-05-20