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
| Name | Type | Dir | Description |
|---|---|---|---|
| KeyHandle | HANDLE | in | Handle a una clave abierta con acceso KEY_SET_VALUE. |
| ValueName | PUNICODE_STRING | in | Nombre 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 Windows | ID de syscall | Build |
|---|---|---|
| Win10 1507 | 0xC8 | win10-1507 |
| Win10 1607 | 0xCB | win10-1607 |
| Win10 1703 | 0xCE | win10-1703 |
| Win10 1709 | 0xCF | win10-1709 |
| Win10 1803 | 0xD0 | win10-1803 |
| Win10 1809 | 0xD1 | win10-1809 |
| Win10 1903 | 0xD2 | win10-1903 |
| Win10 1909 | 0xD2 | win10-1909 |
| Win10 2004 | 0xD6 | win10-2004 |
| Win10 20H2 | 0xD6 | win10-20h2 |
| Win10 21H1 | 0xD6 | win10-21h1 |
| Win10 21H2 | 0xD7 | win10-21h2 |
| Win10 22H2 | 0xD7 | win10-22h2 |
| Win11 21H2 | 0xDC | win11-21h2 |
| Win11 22H2 | 0xDD | win11-22h2 |
| Win11 23H2 | 0xDD | win11-23h2 |
| Win11 24H2 | 0xDF | win11-24h2 |
| Server 2016 | 0xCB | winserver-2016 |
| Server 2019 | 0xD1 | winserver-2019 |
| Server 2022 | 0xDB | winserver-2022 |
| Server 2025 | 0xDF | winserver-2025 |
Módulo del kernel
APIs relacionadas
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 ENDPrustTear-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