> Windows Syscalls
ntoskrnl.exeT1542.003T1542T1106

NtModifyBootEntry

Reemplaza una BOOT_ENTRY existente en el BCD con un nuevo descriptor, indexado por su ID.

Prototipo

NTSTATUS NtModifyBootEntry(
  PBOOT_ENTRY BootEntry
);

Argumentos

NameTypeDirDescription
BootEntryPBOOT_ENTRYinPuntero a una BOOT_ENTRY cuyo campo `Id` selecciona la entrada existente a sobrescribir. El resto de la estructura se convierte en el nuevo contenido.

IDs de syscalls por versión de Windows

Versión de WindowsID de syscallBuild
Win10 15070x102win10-1507
Win10 16070x107win10-1607
Win10 17030x10Bwin10-1703
Win10 17090x10Cwin10-1709
Win10 18030x10Ewin10-1803
Win10 18090x10Fwin10-1809
Win10 19030x110win10-1903
Win10 19090x110win10-1909
Win10 20040x115win10-2004
Win10 20H20x115win10-20h2
Win10 21H10x115win10-21h1
Win10 21H20x116win10-21h2
Win10 22H20x116win10-22h2
Win11 21H20x11Cwin11-21h2
Win11 22H20x11Dwin11-22h2
Win11 23H20x11Dwin11-23h2
Win11 24H20x11Fwin11-24h2
Server 20160x107winserver-2016
Server 20190x10Fwinserver-2019
Server 20220x11Bwinserver-2022
Server 20250x11Fwinserver-2025

Módulo del kernel

ntoskrnl.exeNtModifyBootEntry

APIs relacionadas

BcdSetElementData (bcd.dll)bcdedit.exe /set {bootmgr} pathSetFirmwareEnvironmentVariableWNtAddBootEntryNtDeleteBootEntryNtEnumerateBootEntriesNtSetBootEntryOrder

Stub del syscall

4C 8B D1            mov r10, rcx
B8 1F 01 00 00      mov eax, 0x11F
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

Notas no documentadas

A diferencia de NtAddBootEntry, NtModifyBootEntry no tiene parámetro `Id` de salida — el ID es la *clave primaria* incrustada en la BOOT_ENTRY entrante. El kernel localiza la entrada firmware correspondiente (variable EFI `Boot####` en UEFI, entrada dentro de la subárbol BCD en BIOS) y la reescribe atómicamente. Se requiere SeSystemEnvironmentPrivilege. El mismo blob opaco `OsOptionsLength` se respeta, permitiendo parchear de una sola vez elementos BCD arbitrarios (BcdLibraryDevice_ApplicationDevice, BcdOSLoaderString_KernelPath, etc.).

Uso común por malware

La variante de persistencia BCD más sigilosa: en lugar de *añadir* una entrada sospechosa que los defensores verían en `bcdedit /enum`, el malware **muta la entrada legítima `{current}` de Windows** para que su elemento `path` apunte a un bootmgr malicioso o a un binario EFI encadenado que luego vuelve al cargador real. El usuario no ve ninguna opción extra del menú; el sistema simplemente arranca pasando por el stage 0 del atacante. Esta es la técnica atribuida a ESPecter (modifica el objeto BCD existente Windows Boot Manager) y al reconocimiento `bcdedit /set {bootmgr} path` de TrickBoot. BlackLotus también parchea la entrada existente para deshabilitar comprobaciones de integridad BitLocker antes de ejecutar su bootkit.

Oportunidades de detección

Las modificaciones BCD impactan la misma telemetría que las adiciones: ETW Microsoft-Windows-Kernel-Boot, deltas de registro en `HKLM\BCD00000000` y evento de auditoría 4673 para SeSystemEnvironmentPrivilege. Comparar específicamente los elementos `path`, `device` y `nx` de los objetos `{current}` y `{bootmgr}` contra una baseline dorada — cualquier cambio fuera de la ventana de Patch Tuesday es sospechoso. Windows Defender Application Control (WDAC) no puede impedir la llamada, pero aplicar **Boot Integrity** vía Measured Boot + un servicio de atestación remota (Azure Attestation, salud de dispositivos Intune) detecta la deriva post-arranque porque las mediciones TPM PCR[4]/PCR[7] divergirán de la política esperada.

Ejemplos de syscalls directos

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

NtModifyBootEntry PROC
    mov  r10, rcx          ; PBOOT_ENTRY (Id baked into the struct)
    mov  eax, 11Fh         ; Win11 24H2
    syscall
    ret
NtModifyBootEntry ENDP

cHijack the existing Windows entry path

// Conceptual: rewrite the {current} Windows entry so its bootmgr path becomes our shim.
// Read the existing entry via NtEnumerateBootEntries, mutate the FilePath, write back.
NTSTATUS hijack_current(ULONG id, const wchar_t* shim_path) {
    BYTE buf[1024] = {0};
    PBOOT_ENTRY be = (PBOOT_ENTRY)buf;
    be->Version = 1;
    be->Length  = sizeof(buf);
    be->Id      = id;                 // ID returned by NtEnumerateBootEntries
    be->Attributes = BOOT_ENTRY_ATTRIBUTE_ACTIVE;
    be->BootFilePathOffset = FIELD_OFFSET(BOOT_ENTRY, OsOptions);
    // Build a FILE_PATH(\EFI\evil\shim.efi) here ...
    return NtModifyBootEntry(be);
}

rustNaked stub

use std::arch::asm;

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

Mapeos MITRE ATT&CK

Last verified: 2026-05-20