NtQueryBootEntryOrder
Liest die geordnete Liste der BOOT_ENTRY-IDs aus der Firmware — die Sequenz, die die Plattform beim nächsten Einschalten versucht.
Prototyp
NTSTATUS NtQueryBootEntryOrder( PULONG Ids, PULONG Count );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| Ids | PULONG | out | Vom Aufrufer allokiertes Array, das die geordneten BOOT_ENTRY-Kennungen empfängt. Darf NULL sein, um den erforderlichen Count abzufragen. |
| Count | PULONG | in/out | Eingabe: Anzahl der ULONG-Slots in Ids. Ausgabe: Anzahl der geschriebenen IDs oder benötigte Anzahl, wenn STATUS_BUFFER_TOO_SMALL zurückgegeben wird. |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0x128 | win10-1507 |
| Win10 1607 | 0x12E | win10-1607 |
| Win10 1703 | 0x133 | win10-1703 |
| Win10 1709 | 0x135 | win10-1709 |
| Win10 1803 | 0x137 | win10-1803 |
| Win10 1809 | 0x138 | win10-1809 |
| Win10 1903 | 0x139 | win10-1903 |
| Win10 1909 | 0x139 | win10-1909 |
| Win10 2004 | 0x13F | win10-2004 |
| Win10 20H2 | 0x13F | win10-20h2 |
| Win10 21H1 | 0x13F | win10-21h1 |
| Win10 21H2 | 0x140 | win10-21h2 |
| Win10 22H2 | 0x140 | win10-22h2 |
| Win11 21H2 | 0x146 | win11-21h2 |
| Win11 22H2 | 0x148 | win11-22h2 |
| Win11 23H2 | 0x148 | win11-23h2 |
| Win11 24H2 | 0x14A | win11-24h2 |
| Server 2016 | 0x12E | winserver-2016 |
| Server 2019 | 0x138 | winserver-2019 |
| Server 2022 | 0x145 | winserver-2022 |
| Server 2025 | 0x14A | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
4C 8B D1 mov r10, rcx B8 4A 01 00 00 mov eax, 0x14A 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
Auf UEFI ist dies im Kern ein Wrapper über die firmwaredefinierte NVRAM-Variable `BootOrder` (EFI Global Variable, GUID `{8BE4DF61-93CA-11d2-AA0D-00E098032B8C}`). Das Array ist die *Reihenfolge*, in der die Firmware jede `Boot####`-Variable versucht. Der erste Aufruf nutzt typischerweise einen NULL-`Ids`-Puffer, um die Größe zu ermitteln, der zweite holt die Daten. SeSystemEnvironmentPrivilege ist erforderlich.
Häufige Malware-Nutzung
Voraussetzung für NtSetBootEntryOrder: Bootkit-Installer lesen die aktuelle Reihenfolge, fügen ihre frisch registrierte ID an Position 0 ein (oder dort, wo sie sie relativ zu bestehenden Einträgen benötigen) und schreiben sie zurück. Sie nutzen die Abfrage außerdem zur Verifizierung, dass die Persistenz einen Reboot überstanden hat — wenn `Ids[0]` nicht mehr die Angreifer-GUID ist, weiß das Implant, dass ein Verteidiger oder ein BIOS-Update die Reihenfolge wiederhergestellt hat, und führt die Installation erneut aus. Diese Schleife ist im Persistenz-Modul von BlackLotus dokumentiert.
Erkennungsmöglichkeiten
Gleiche Einschränkungen wie bei NtEnumerateBootEntries — Read-only und häufig legitim. Hochpräziser Indikator ist das *Paar*: Query + Set mit einem Delta, das einen nicht-Microsoft-signierten Loader an die Spitze hebt. Das Ergebnis dieses Syscalls gegen eine saubere Baseline vergleichen; noch besser: die EFI-`BootOrder`-Variable in das Asset-Inventar einbinden (Eclypsium, CHIPSEC oder Intune-Gerätestatus-Attestation) und auf Änderungen alarmieren.
Direkte Syscall-Beispiele
asmx64 direct stub (Win11 24H2, SSN 0x14A)
NtQueryBootEntryOrder PROC
mov r10, rcx ; PULONG Ids
mov eax, 014Ah ; Win11 24H2
syscall
ret
NtQueryBootEntryOrder ENDPcRead current BootOrder
extern NTSTATUS NTAPI NtQueryBootEntryOrder(PULONG, PULONG);
void show_order(void) {
ULONG count = 0;
NtQueryBootEntryOrder(NULL, &count); // STATUS_BUFFER_TOO_SMALL, fills count
if (!count) return;
PULONG ids = (PULONG)HeapAlloc(GetProcessHeap(), 0, count * sizeof(ULONG));
if (NT_SUCCESS(NtQueryBootEntryOrder(ids, &count))) {
for (ULONG i = 0; i < count; ++i) wprintf(L"%u -> id=%08X\n", i, ids[i]);
}
HeapFree(GetProcessHeap(), 0, ids);
}rustNaked stub
use std::arch::asm;
#[unsafe(naked)]
unsafe extern "system" fn nt_query_boot_entry_order(_ids: *mut u32, _count: *mut u32) -> i32 {
asm!(
"mov r10, rcx",
"mov eax, 0x14A", // Win11 24H2
"syscall",
"ret",
options(noreturn),
);
}MITRE ATT&CK-Mappings
Last verified: 2026-05-20