> Windows Syscalls
ntoskrnl.exeT1542.001T1082T1014

NtEnumerateDriverEntries

Liefert eine gepackte Liste aller registrierten EFI_DRIVER_ENTRYs — die UEFI-Driver####-Variablen, die vor dem Boot-Manager dispatcht werden.

Prototyp

NTSTATUS NtEnumerateDriverEntries(
  PVOID  Buffer,
  PULONG BufferLength
);

Argumente

NameTypeDirDescription
BufferPVOIDoutVom Aufrufer allokierter Puffer, der eine gepackte Folge von EFI_DRIVER_ENTRY_LIST-Datensätzen empfängt (NextEntryOffset + eingebetteter EFI_DRIVER_ENTRY). Darf NULL sein, um die benötigte Größe abzufragen.
BufferLengthPULONGin/outEingabe: Größe von Buffer in Byte. Ausgabe: geschriebene Byte oder benötigte Größe, wenn STATUS_BUFFER_TOO_SMALL zurückgegeben wird.

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
Win10 15070xD0win10-1507
Win10 16070xD3win10-1607
Win10 17030xD6win10-1703
Win10 17090xD7win10-1709
Win10 18030xD8win10-1803
Win10 18090xD9win10-1809
Win10 19030xDAwin10-1903
Win10 19090xDAwin10-1909
Win10 20040xDFwin10-2004
Win10 20H20xDFwin10-20h2
Win10 21H10xDFwin10-21h1
Win10 21H20xE0win10-21h2
Win10 22H20xE0win10-22h2
Win11 21H20xE5win11-21h2
Win11 22H20xE6win11-22h2
Win11 23H20xE6win11-23h2
Win11 24H20xE8win11-24h2
Server 20160xD3winserver-2016
Server 20190xD9winserver-2019
Server 20220xE4winserver-2022
Server 20250xE8winserver-2025

Kernel-Modul

ntoskrnl.exeNtEnumerateDriverEntries

Verwandte APIs

GetFirmwareEnvironmentVariableW (DriverOrder / Driver####)bcdedit.exe /enum FIRMWAREBcdEnumerateObjects (bcd.dll)NtQueryDriverEntryOrderNtAddDriverEntry

Syscall-Stub

4C 8B D1            mov r10, rcx
B8 E8 00 00 00      mov eax, 0xE8
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

Gleiches Zwei-Aufruf-Schema wie NtEnumerateBootEntries — einmal mit `Buffer = NULL` aufrufen, um die benötigte Größe zu erfahren, dann mit der Allokation erneut. Durchläuft die verkettete Liste über `EFI_DRIVER_ENTRY_LIST.NextEntryOffset`. SeSystemEnvironmentPrivilege ist auch zum Lesen erforderlich. Auf UEFI liest es indirekt die globale `DriverOrder`-Variable sowie jede referenzierte `Driver####`.

Häufige Malware-Nutzung

Sowohl offensiv als auch defensiv genutzt. Offensiv: APT-Recon zum Fingerprinten der Firmware, bevor entschieden wird, welcher DRIVER_ENTRY-Hijack tragfähig ist — der MosaicRegressor-Installer enumeriert DriverOrder, um einen stabilen Slot eines verwundbaren OEM-Treibers zum Patchen zu finden. Defensiv: Incident-Response und proaktive Forensik rufen ihn (oder `bcdedit /enum FIRMWARE`) auf, um die aktuelle Treiberliste zu dumpen und gegen eine Cleanroom-Baseline desselben Hardwaremodells zu vergleichen — die zuverlässigste einfache Methode zur Erkennung von LoJax-/MosaicRegressor-artigen Implants ohne vollständigen SPI-Dump.

Erkennungs­möglichkeiten

Enumeration allein ist gutartig — Verteidiger führen sie ständig aus. Interessantes Signal ist die **Enumeration durch einen unerwarteten Prozess**: ein Nicht-OEM-, Nicht-Microsoft-, Nicht-EDR-Userland-Prozess, der ein Token mit SeSystemEnvironmentPrivilege öffnet und die Treiberliste liest, ist ein starker Staging-Indikator. Den Aufrufer (Event ID 4673) mit der Prozess-Kommandozeile via Sysmon Event ID 1 paaren. Verlässlichste Verteidigung bleibt Secure Boot mit aktueller DBX sowie Measured Boot + Remote Attestation, die PCR[2] bei jedem dispatchten DXE-Treiber erweitern.

Direkte Syscall-Beispiele

asmx64 direct stub (Win11 24H2, SSN 0xE8)

NtEnumerateDriverEntries PROC
    mov  r10, rcx          ; PVOID Buffer
    mov  eax, 0E8h         ; Win11 24H2
    syscall
    ret
NtEnumerateDriverEntries ENDP

cDefensive: dump every DXE entry path + hash

// Walk DriverOrder, print FriendlyName + DriverFilePath of each registered DXE entry.
extern NTSTATUS NTAPI NtEnumerateDriverEntries(PVOID, PULONG);

void dump_drivers(void) {
    ULONG size = 0;
    NtEnumerateDriverEntries(NULL, &size);
    if (!size) return;
    PBYTE buf = (PBYTE)HeapAlloc(GetProcessHeap(), 0, size);
    if (NT_SUCCESS(NtEnumerateDriverEntries(buf, &size))) {
        PBYTE p = buf;
        while (p < buf + size) {
            PEFI_DRIVER_ENTRY_LIST list = (PEFI_DRIVER_ENTRY_LIST)p;
            PEFI_DRIVER_ENTRY de = &list->DriverEntry;
            wprintf(L"id=%08X name=%s\n", de->Id,
                    (LPCWSTR)((PBYTE)de + de->FriendlyNameOffset));
            if (!list->NextEntryOffset) break;
            p += list->NextEntryOffset;
        }
    }
    HeapFree(GetProcessHeap(), 0, buf);
}

rustNaked stub

use std::arch::asm;

#[unsafe(naked)]
unsafe extern "system" fn nt_enumerate_driver_entries(_buf: *mut u8, _len: *mut u32) -> i32 {
    asm!(
        "mov r10, rcx",
        "mov eax, 0xE8",   // Win11 24H2
        "syscall",
        "ret",
        options(noreturn),
    );
}

MITRE ATT&CK-Mappings

Last verified: 2026-05-20