NtSetBootEntryOrder
Schreibt die Boot-Reihenfolge der Firmware — das Array der BOOT_ENTRY-IDs, das die Plattform der Reihe nach versucht.
Prototyp
NTSTATUS NtSetBootEntryOrder( PULONG Ids, ULONG Count );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| Ids | PULONG | in | Array von BOOT_ENTRY-Kennungen in der gewünschten Versuchsreihenfolge. Index 0 wird zuerst versucht. |
| Count | ULONG | in | Anzahl der Einträge in Ids. Muss jeder aktuell registrierten ID entsprechen — Teilreihenfolgen werden abgelehnt. |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0x16C | win10-1507 |
| Win10 1607 | 0x174 | win10-1607 |
| Win10 1703 | 0x17A | win10-1703 |
| Win10 1709 | 0x17D | win10-1709 |
| Win10 1803 | 0x17F | win10-1803 |
| Win10 1809 | 0x180 | win10-1809 |
| Win10 1903 | 0x181 | win10-1903 |
| Win10 1909 | 0x181 | win10-1909 |
| Win10 2004 | 0x187 | win10-2004 |
| Win10 20H2 | 0x187 | win10-20h2 |
| Win10 21H1 | 0x187 | win10-21h1 |
| Win10 21H2 | 0x189 | win10-21h2 |
| Win10 22H2 | 0x189 | win10-22h2 |
| Win11 21H2 | 0x191 | win11-21h2 |
| Win11 22H2 | 0x194 | win11-22h2 |
| Win11 23H2 | 0x194 | win11-23h2 |
| Win11 24H2 | 0x196 | win11-24h2 |
| Server 2016 | 0x174 | winserver-2016 |
| Server 2019 | 0x180 | winserver-2019 |
| Server 2022 | 0x18F | winserver-2022 |
| Server 2025 | 0x196 | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
4C 8B D1 mov r10, rcx B8 96 01 00 00 mov eax, 0x196 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
Das Schreib-Gegenstück zu NtQueryBootEntryOrder. Auf UEFI ruft der Kernel letztlich `EFI_SET_VARIABLE` gegen die globale `BootOrder`-Variable auf (Vendor-GUID `{8BE4DF61-93CA-11d2-AA0D-00E098032B8C}`) mit `EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS`. SeSystemEnvironmentPrivilege ist Pflicht und der Aufruf scheitert mit STATUS_INVALID_PARAMETER, wenn eine übergebene ID nicht existiert.
Häufige Malware-Nutzung
Der Schlussstein der BCD-basierten Bootkit-Installation: nachdem ein bösartiges `Boot####` per NtAddBootEntry registriert wurde, ist dies der Aufruf, der dem Angreifer den nächsten Reboot **sichert**, indem er diese ID an Position 0 hebt. Ohne diesen Schritt bleibt der Angreifer-Eintrag inaktiv — UEFI probiert den vorhandenen Windows Boot Manager zuerst und erreicht ihn nie. Die Umsortierung macht das Implant erst aktiv. BlackLotus, ESPecter und das TrickBoot-Modul beenden ihren Installationspfad jeweils mit dieser Primitive.
Erkennungsmöglichkeiten
**Hochpräzisester BCD-Indikator der Familie.** Jede Änderung an `BootOrder`, die einen nicht-Microsoft-, nicht-OEM-Recovery-Eintrag auf Slot 0 hebt, ist im Wesentlichen diagnostisch für einen Bootkit-Versuch. Überwachen: ETW Microsoft-Windows-Kernel-Boot-Reihenfolgeänderungs-Events, Sysmon-Registry-Events auf BCD-Schreibvorgängen und die EFI-`BootOrder`-Variable via periodischem CHIPSEC- oder Eclypsium-Scan. Verteidiger sollten Endpoints zusätzlich in **Measured Boot + Remote Attestation** einschreiben — die PCR[4]-Messungen (Hash des Boot-Manager-Image) und PCR[7] (Secure-Boot-Policy + Signaturen-DB-Hash) weichen bereits beim allerersten kompromittierten Boot von der erwarteten Baseline ab, bevor der Nutzer überhaupt angemeldet ist.
Direkte Syscall-Beispiele
asmx64 direct stub (Win11 24H2, SSN 0x196)
NtSetBootEntryOrder PROC
mov r10, rcx ; PULONG Ids
mov eax, 0196h ; Win11 24H2
syscall
ret
NtSetBootEntryOrder ENDPcPromote attacker ID to slot 0 (PoC)
// PoC: read order, move our_id to the front, write back.
extern NTSTATUS NTAPI NtQueryBootEntryOrder(PULONG, PULONG);
extern NTSTATUS NTAPI NtSetBootEntryOrder(PULONG, ULONG);
NTSTATUS promote(ULONG our_id) {
ULONG count = 0;
NtQueryBootEntryOrder(NULL, &count);
PULONG ids = (PULONG)HeapAlloc(GetProcessHeap(), 0, count * sizeof(ULONG));
NtQueryBootEntryOrder(ids, &count);
// find our_id, swap to front
for (ULONG i = 0; i < count; ++i) {
if (ids[i] == our_id) {
memmove(&ids[1], &ids[0], i * sizeof(ULONG));
ids[0] = our_id;
break;
}
}
NTSTATUS s = NtSetBootEntryOrder(ids, count);
HeapFree(GetProcessHeap(), 0, ids);
return s;
}rustNaked stub
use std::arch::asm;
#[unsafe(naked)]
unsafe extern "system" fn nt_set_boot_entry_order(_ids: *const u32, _count: u32) -> i32 {
asm!(
"mov r10, rcx",
"mov eax, 0x196", // Win11 24H2
"syscall",
"ret",
options(noreturn),
);
}MITRE ATT&CK-Mappings
Last verified: 2026-05-20