> Windows Syscalls
ntoskrnl.exeT1055T1559T1106

NtQueryInformationAtom

Devuelve metadatos sobre un átomo individual o sobre toda la tabla global de átomos — nombre, refcount, pin count, contadores de uso.

Prototipo

NTSTATUS NtQueryInformationAtom(
  RTL_ATOM                Atom,
  ATOM_INFORMATION_CLASS  InformationClass,
  PVOID                   AtomInformation,
  ULONG                   AtomInformationLength,
  PULONG                  ReturnLength
);

Argumentos

NameTypeDirDescription
AtomRTL_ATOMinID de átomo a consultar. Ignorado cuando InformationClass = AtomTableInformation (volcado completo).
InformationClassATOM_INFORMATION_CLASSinAtomBasicInformation (por átomo: nombre + refcount + pin) o AtomTableInformation (conteo + lista de IDs).
AtomInformationPVOIDoutBuffer del llamador que recibe una estructura ATOM_BASIC_INFORMATION o ATOM_TABLE_INFORMATION.
AtomInformationLengthULONGinTamaño de AtomInformation en bytes.
ReturnLengthPULONGoutRecibe el número de bytes realmente escritos. Sirve para dimensionar una llamada subsiguiente si se devuelve STATUS_BUFFER_TOO_SMALL.

IDs de syscalls por versión de Windows

Versión de WindowsID de syscallBuild
Win10 15070x12Fwin10-1507
Win10 16070x135win10-1607
Win10 17030x13Awin10-1703
Win10 17090x13Dwin10-1709
Win10 18030x13Fwin10-1803
Win10 18090x140win10-1809
Win10 19030x141win10-1903
Win10 19090x141win10-1909
Win10 20040x147win10-2004
Win10 20H20x147win10-20h2
Win10 21H10x147win10-21h1
Win10 21H20x148win10-21h2
Win10 22H20x148win10-22h2
Win11 21H20x14Ewin11-21h2
Win11 22H20x150win11-22h2
Win11 23H20x150win11-23h2
Win11 24H20x152win11-24h2
Server 20160x135winserver-2016
Server 20190x140winserver-2019
Server 20220x14Dwinserver-2022
Server 20250x152winserver-2025

Módulo del kernel

ntoskrnl.exeNtQueryInformationAtom

APIs relacionadas

GetAtomNameWGlobalGetAtomNameWGlobalGetAtomNameANtAddAtomNtFindAtomNtDeleteAtom

Stub del syscall

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

La contraparte de lectura de NtAddAtom. La clase `AtomBasicInformation` devuelve una `ATOM_BASIC_INFORMATION` con el UsageCount (refcount), los Flags (pineado vs ordinario), el NameLength (en bytes) y los bytes de nombre — y al igual que con NtAddAtom, el kernel entrega los bytes crudos almacenados, independientemente de la validez UTF-16. La clase `AtomTableInformation` devuelve el conteo de átomos seguido de un array con todos los RTL_ATOM IDs — una primitiva de enumeración completa. Los wrappers Win32 `GlobalGetAtomNameW` y `GetAtomNameW` son la vía más común; herramientas sigilosas y la extensión WinDbg !atom usan el syscall en crudo.

Uso común por malware

**Atom Bombing etapa 2**: este syscall es el que realiza la escritura cross-process — el malware encola una APC en la víctima que llama a `GlobalGetAtomNameA`, que internamente invoca NtQueryInformationAtom; el propio kernel escribe los bytes de 'nombre' del átomo (el shellcode contrabandeado) en el buffer del espacio de direcciones de la víctima. Como la escritura la hace el kernel en nombre de la víctima, los hooks NtWriteVirtualMemory usermode no ven nada. **Inspección sigilosa de IPC**: herramientas red-team y de monitorización de persistencia llaman AtomTableInformation para volcar toda la tabla global y buscar residuos binarios, entradas sobredimensionadas o nombres conocidos malos — la misma primitiva que defensivamente detecta residuales de Atom Bomb puede usarse ofensivamente para leer el estado IPC en vivo de apps legítimas (topics DDE de Office, estado IME, nombres de clase de Explorer).

Oportunidades de detección

Las llamadas AtomBasicInformation ocurren constantemente vía GlobalGetAtomName — cada drag-and-drop, cada ronda de marshalling COM, cada conversación DDE. La detección debe centrarse en el contexto: AtomBasicInformation invocado desde un hilo recién reanudado vía NtTestAlert / KiUserApcDispatcher hacia un buffer recién asignado es el indicador canónico de etapa 2 de Atom Bomb (los EDR que desplegaron las reglas Atom Bomb de la era 2017 buscan exactamente esto). AtomTableInformation es más raro en rutas de código normales y es una señal ligeramente más fuerte — un proceso no-sistema que lo invoque merece un pivot. El snapshot WinDbg / forense de la tabla global (`!atom`) es la primitiva blue-team ortogonal — cualquier entrada con bytes binarios o longitud > algunos cientos es sospechosa.

Ejemplos de syscalls directos

asmx64 direct stub (Win11 24H2)

; Direct syscall stub for NtQueryInformationAtom (SSN 0x152 on Win11 24H2)
NtQueryInformationAtom PROC
    mov  r10, rcx          ; syscall convention
    mov  eax, 152h         ; SSN — varies per build
    syscall
    ret
NtQueryInformationAtom ENDP

cAtom Bombing — stage 2 (kernel writes shellcode into target)

// Inside the victim process, the queued APC runs this code.
// GlobalGetAtomNameA -> NtQueryInformationAtom -> kernel copies the atom
// 'name' bytes (which were our shellcode in stage 1) into 'buf'.
#include <windows.h>

VOID StageTwoApc(PVOID context) {
    USHORT atomId = (USHORT)(ULONG_PTR)context;
    char   buf[4096]; // attacker-sized to fit the shellcode
    UINT   got = GlobalGetAtomNameA(atomId, buf, sizeof(buf));
    // Stage 3 (not shown): NtSetContextThread / ROP -> NtProtectVirtualMemory
    // flips buf to RWX and pivots execution into it.
    (void)got;
}

cAtom table enumeration (defensive or offensive)

// Dump every atom in the global table and print its name + refcount.
// Use defensively: hunt for binary residue (Atom Bomb IOC).
// Use offensively: read live IPC state (DDE topics, IME state).
#include <windows.h>
#include <winternl.h>
#include <stdio.h>

typedef struct _ATOM_TABLE_INFORMATION {
    ULONG  NumberOfAtoms;
    USHORT Atoms[1];
} ATOM_TABLE_INFORMATION;

typedef struct _ATOM_BASIC_INFORMATION {
    USHORT UsageCount;
    USHORT Flags;
    USHORT NameLength;
    WCHAR  Name[1];
} ATOM_BASIC_INFORMATION;

typedef NTSTATUS (NTAPI *pNtQueryInformationAtom)(
    USHORT, ULONG, PVOID, ULONG, PULONG);

VOID DumpAtomTable(VOID) {
    pNtQueryInformationAtom NtQueryInformationAtom = (pNtQueryInformationAtom)
        GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationAtom");
    BYTE tbuf[8192]; ULONG ret = 0;
    if (NtQueryInformationAtom(0, /*AtomTableInformation*/ 1,
                               tbuf, sizeof(tbuf), &ret) < 0) return;
    ATOM_TABLE_INFORMATION* ti = (ATOM_TABLE_INFORMATION*)tbuf;
    for (ULONG i = 0; i < ti->NumberOfAtoms; ++i) {
        BYTE abuf[1024]; ULONG ar = 0;
        if (NtQueryInformationAtom(ti->Atoms[i], /*AtomBasicInformation*/ 0,
                                   abuf, sizeof(abuf), &ar) < 0) continue;
        ATOM_BASIC_INFORMATION* ai = (ATOM_BASIC_INFORMATION*)abuf;
        wprintf(L"0x%04X  rc=%u  name=%.*s\n",
                ti->Atoms[i], ai->UsageCount, ai->NameLength / 2, ai->Name);
    }
}

Mapeos MITRE ATT&CK

Last verified: 2026-05-20