> Windows Syscalls
ntoskrnl.exeT1112T1070.009T1547.001

NtDeleteValueKey

Elimina un único valor nombrado de una clave de registro abierta, dejando intacta la clave.

Prototipo

NTSTATUS NtDeleteValueKey(
  HANDLE          KeyHandle,
  PUNICODE_STRING ValueName
);

Argumentos

NameTypeDirDescription
KeyHandleHANDLEinHandle a una clave abierta con acceso KEY_SET_VALUE.
ValueNamePUNICODE_STRINGinNombre del valor a eliminar. Una UNICODE_STRING vacía elimina el valor sin nombre (por defecto).

IDs de syscalls por versión de Windows

Versión de WindowsID de syscallBuild
Win10 15070xC8win10-1507
Win10 16070xCBwin10-1607
Win10 17030xCEwin10-1703
Win10 17090xCFwin10-1709
Win10 18030xD0win10-1803
Win10 18090xD1win10-1809
Win10 19030xD2win10-1903
Win10 19090xD2win10-1909
Win10 20040xD6win10-2004
Win10 20H20xD6win10-20h2
Win10 21H10xD6win10-21h1
Win10 21H20xD7win10-21h2
Win10 22H20xD7win10-22h2
Win11 21H20xDCwin11-21h2
Win11 22H20xDDwin11-22h2
Win11 23H20xDDwin11-23h2
Win11 24H20xDFwin11-24h2
Server 20160xCBwinserver-2016
Server 20190xD1winserver-2019
Server 20220xDBwinserver-2022
Server 20250xDFwinserver-2025

Módulo del kernel

ntoskrnl.exeNtDeleteValueKey

APIs relacionadas

RegDeleteValueWRegDeleteKeyValueWNtSetValueKeyNtDeleteKeyNtQueryValueKey

Stub del syscall

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

Elimina una celda de valor única de la lista de valores de la clave padre. El kernel borra el CM_KEY_VALUE correspondiente y libera su celda de datos — sin soft-delete ni papelera. Devuelve STATUS_OBJECT_NAME_NOT_FOUND si no existe valor con ese nombre, lo que significa que sondear la presencia de un valor intentando borrarlo *no* es seguro (lo borra de verdad). El wrapper Win32 RegDeleteValueW es un simple shim.

Uso común por malware

Anti-forense y limpieza *selectiva* de persistencia. Cuando el valor Run del operador convive con diez valores Run legítimos, eliminar la clave `Run` completa sería evidente; NtDeleteValueKey permite al implante quitar sólo su propio valor durante una desinstalación elegante o cuando una detección de EDR ha disparado y el operador quiere limitar el rastro. También sirve para revertir manipulaciones de configuración — p. ej. borrar un valor de persistencia justo antes de que el script de triage del SOC se ejecute y recrearlo después desde una copia en memoria.

Oportunidades de detección

Alta fidelidad cuando el objetivo es una *ruta de persistencia conocida*: Sysmon Event 12 (DeleteValue) sobre `HKLM\Software\Microsoft\Windows\CurrentVersion\Run\*`, `RunOnce`, `Image File Execution Options`, o cualquier `HKLM\SYSTEM\CurrentControlSet\Services\<X>\ImagePath` es anómalo fuera de contextos GPO / SCCM. ETW Microsoft-Windows-Kernel-Registry emite DeleteValue con la ruta de la clave padre y el nombre del valor. Los EDR hookean CmRegisterCallbackEx → RegNtPreDeleteValueKey para visibilidad barata. Una pareja delete-then-recreate (Event 12 seguido de Event 13 con el mismo nombre) en pocos segundos es un patrón casi canónico de limpieza de persistencia.

Ejemplos de syscalls directos

cSelective Run-value cleanup

// Delete only our value, leaving the host's other Run entries untouched.
UNICODE_STRING valueName;
RtlInitUnicodeString(&valueName, L"OneDriveUpdate");
NTSTATUS st = NtDeleteValueKey(hRunKey, &valueName);
if (st == STATUS_OBJECT_NAME_NOT_FOUND) {
    // Already gone; nothing to clean.
}

asmx64 direct stub (Win11 24H2 SSN 0xDF)

NtDeleteValueKey PROC
    mov  r10, rcx
    mov  eax, 0DFh
    syscall
    ret
NtDeleteValueKey ENDP

rustTear-down on shutdown signal

// Cargo: ntapi = "0.4", widestring = "1"
fn cleanup_persistence(h_run_key: HANDLE) {
    for name in ["OneDriveUpdate", "WinStoreHelper"] {
        let w = U16CString::from_str(name).unwrap();
        let mut us = UNICODE_STRING {
            Length: (w.len() * 2) as u16,
            MaximumLength: ((w.len() + 1) * 2) as u16,
            Buffer: w.as_ptr() as _,
        };
        unsafe { NtDeleteValueKey(h_run_key, &mut us); }
    }
}

Mapeos MITRE ATT&CK

Last verified: 2026-05-20