> Windows Syscalls
ntoskrnl.exeT1106T1553

NtCompareSigningLevels

Compara dos valores SE_SIGNING_LEVEL usando el orden de policy de Code Integrity e indica si el primero domina al segundo.

Prototipo

NTSTATUS NtCompareSigningLevels(
  SE_SIGNING_LEVEL FirstSigningLevel,
  SE_SIGNING_LEVEL SecondSigningLevel
);

Argumentos

NameTypeDirDescription
FirstSigningLevelSE_SIGNING_LEVELinPrimer nivel de firma a comparar (0 Unchecked, 4 Authenticode, 6 Store, 8 Antimalware, 12 Microsoft, 14 Windows).
SecondSigningLevelSE_SIGNING_LEVELinSegundo nivel de firma a comparar contra el primero.

IDs de syscalls por versión de Windows

Versión de WindowsID de syscallBuild
Win10 17030x98win10-1703
Win10 17090x99win10-1709
Win10 18030x9Awin10-1803
Win10 18090x9Awin10-1809
Win10 19030x9Awin10-1903
Win10 19090x9Awin10-1909
Win10 20040x9Cwin10-2004
Win10 20H20x9Cwin10-20h2
Win10 21H10x9Cwin10-21h1
Win10 21H20x9Cwin10-21h2
Win10 22H20x9Cwin10-22h2
Win11 21H20x9Ewin11-21h2
Win11 22H20x9Ewin11-22h2
Win11 23H20x9Ewin11-23h2
Win11 24H20xA0win11-24h2
Server 20190x9Awinserver-2019
Server 20220x9Ewinserver-2022
Server 20250xA0winserver-2025

Módulo del kernel

ntoskrnl.exeNtCompareSigningLevels

APIs relacionadas

NtGetCachedSigningLevelNtSetCachedSigningLevelWldpQueryDynamicCodeTrustCiCompareSigningLevels

Stub del syscall

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

Un helper de comparación pura expuesto como syscall puramente para que la policy de ordenamiento de Code Integrity viva en *un* solo lugar — el kernel — en vez de re-implementarse en cada componente user-mode que la necesita. Devuelve `STATUS_SUCCESS` (0) cuando `FirstSigningLevel` es mayor o igual a `SecondSigningLevel` en el retículo CI, y `STATUS_NOT_FOUND` (0xC0000225) en caso contrario. Importante: el ordenamiento *no* es numérico: aunque las constantes resultan ser monotónicas (`0 < 4 < 6 < 8 < 12 < 14`), el kernel pasa por `CiCompareSigningLevels` en `ci.dll`, que aplica equivalencias definidas por policy (por ejemplo `SE_SIGNING_LEVEL_STORE` y `SE_SIGNING_LEVEL_ANTIMALWARE` pueden tratarse como equivalentes bajo banderas específicas de policy WHQL). De ahí el syscall — para centralizar esa policy. Introducido en Windows 10 1703 junto con el resto de la superficie API de Code Integrity moderna; no presente en Windows 10 1507 / 1607.

Uso común por malware

Valor ofensivo casi nulo. Es una función *pura* (sin efectos secundarios, sin privilegios, sin acceso a recursos) que toma dos enteros y devuelve un status — no hay nada que abusar. La única razón real para que un atacante la llame es bookkeeping: loaders red-team que han construido una primitiva CIG-bypass pueden llamarla para revisar dos veces que el nivel que han forjado domina el nivel requerido por el objetivo, antes de comprometerse con la inyección. Por lo demás ninguna familia de malware está documentada usándola, y los EDR la ignoran.

Oportunidades de detección

No es un punto de detección significativo. La función no tiene efecto secundario observable, ETW no loguea eventos por llamada para ella, y el volumen del autouso legítimo de `ci.dll` es suficientemente alto como para que el hunt basado en ratio sea impracticable. El esfuerzo de detección se gasta mejor en sus *llamantes* — cualquiera que llame `NtCompareSigningLevels` desde fuera de `ci.dll`, `wldp.dll`, `lsass.exe` y un puñado de componentes Defender es inusual pero no necesariamente malicioso. Con telemetría de syscall user-mode, unir las llamadas `NtCompareSigningLevels` con llamadas adyacentes `NtSetCachedSigningLevel` / `NtGetCachedSigningLevel` desde el mismo hilo es una señal mucho más fuerte que esta llamada aislada.

Ejemplos de syscalls directos

cDoes the cached level satisfy the target's CIG requirement?

// Used internally by ci.dll and by some EDRs to short-circuit policy decisions.
// Returns STATUS_SUCCESS if `have` dominates `need`, STATUS_NOT_FOUND otherwise.
#include <windows.h>
#include <winternl.h>

typedef NTSTATUS (NTAPI* pNtCompareSigningLevels)(UCHAR, UCHAR);

BOOL satisfies(UCHAR have, UCHAR need) {
    pNtCompareSigningLevels f = (pNtCompareSigningLevels)GetProcAddress(
        GetModuleHandleA("ntdll.dll"), "NtCompareSigningLevels");
    return NT_SUCCESS(f(have, need));
}

// Example: do we meet ProcessSignaturePolicy.MicrosoftSignedOnly = 1?
// satisfies(SE_SIGNING_LEVEL_MICROSOFT, SE_SIGNING_LEVEL_MICROSOFT) == TRUE
// satisfies(SE_SIGNING_LEVEL_AUTHENTICODE, SE_SIGNING_LEVEL_MICROSOFT) == FALSE

asmx64 direct stub (Win11 24H2 / Server 2025, SSN 0xA0)

NtCompareSigningLevels PROC
    mov  r10, rcx
    mov  eax, 0A0h
    syscall
    ret
NtCompareSigningLevels ENDP

Mapeos MITRE ATT&CK

Last verified: 2026-05-20