> Windows Syscalls
ntoskrnl.exeT1055T1559T1497

NtFindAtom

Recherche un atome global existant par son nom et renvoie son ID 16 bits sans incrémenter le refcount.

Prototype

NTSTATUS NtFindAtom(
  PWSTR     AtomName,
  ULONG     Length,
  PRTL_ATOM Atom
);

Arguments

NameTypeDirDescription
AtomNamePWSTRinBuffer UTF-16 dont les octets seront comparés aux entrées d'atomes existantes.
LengthULONGinTaille du buffer en octets.
AtomPRTL_ATOMoutReçoit l'ID atome 16 bits si trouvé. Facultatif — passer NULL pour seulement tester l'existence.

IDs de syscalls par version de Windows

Version de WindowsID de syscallBuild
Win10 15070x14win10-1507
Win10 16070x14win10-1607
Win10 17030x14win10-1703
Win10 17090x14win10-1709
Win10 18030x14win10-1803
Win10 18090x14win10-1809
Win10 19030x14win10-1903
Win10 19090x14win10-1909
Win10 20040x14win10-2004
Win10 20H20x14win10-20h2
Win10 21H10x14win10-21h1
Win10 21H20x14win10-21h2
Win10 22H20x14win10-22h2
Win11 21H20x14win11-21h2
Win11 22H20x14win11-22h2
Win11 23H20x14win11-23h2
Win11 24H20x14win11-24h2
Server 20160x14winserver-2016
Server 20190x14winserver-2019
Server 20220x14winserver-2022
Server 20250x14winserver-2025

Module noyau

ntoskrnl.exeNtFindAtom

APIs liées

GlobalFindAtomAGlobalFindAtomWFindAtomANtAddAtomNtQueryInformationAtom

Stub du syscall

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

Notes non documentées

Le SSN `0x14` est stable de 1507 à 24H2 — les interfaces d'atom table ne bougent simplement pas. NtFindAtom est le frère lecture-seule de NtAddAtom : il parcourt la table de hash globale, compare byte-à-byte l'entrée Length-octets à chaque entrée, et renvoie l'ID existant sans toucher au refcount. Contrairement à NtAddAtom, NtFindAtom renvoie STATUS_OBJECT_NAME_NOT_FOUND si le nom est absent (NtAddAtom le créerait). Wrappers Win32 : `GlobalFindAtomA/W`.

Usage courant par les malwares

**Rendez-vous Atom Bombing** — le second implant (ou un thread frère) appelle NtFindAtom sur une chaîne marqueur convenue pour découvrir si le shellcode stage-1 est déjà dans la table et apprendre son ID avant d'enqueuer l'APC qui déclenche `GlobalGetAtomNameA` dans la cible. Sert aussi à la **coordination IPC inter-implant** où la table d'atomes joue le rôle de magasin clé/valeur partagé secret : les implants publient identifiants de session, IDs de beacon ou hashes d'URL de callback comme noms d'atomes, et les pairs les `NtFindAtom` pour se découvrir sans toucher disque, registre ou sockets. **Détection de sandbox** — interroger la table pour des atomes laissés par les harnais sandbox (Triage et Joe Sandbox enregistrent chacun un petit ensemble d'atomes reconnaissables au boot) ; présence = environnement d'analyse. Pas cher, aucun import au-delà de ntdll, indétectable par les EDR centrés fichier/registre.

Opportunités de détection

Volume encore plus faible que NtAddAtom dans la télémétrie d'alerte — la plupart des produits traitent la table d'atomes en boîte noire. Chasse utile : **NtFindAtom appelé par un processus qui n'appelle jamais NtAddAtom**, avec un Length suggérant une recherche de marqueur plutôt qu'un nom de classe de fenêtre (typiquement 8-64 octets), corrélé avec un NtQueueApcThread vers un processus distant — signe fort de rendez-vous Atom Bombing. ETW Microsoft-Windows-Kernel-Audit-API-Calls expose le syscall. WinDbg `!atom` montre la table globale courante et fait foi en IR. Le moteur comportemental de Defender a ajouté (~2018) une détection spécifique Atom Bomb qui se déclenche sur la chaîne complète GlobalAddAtomA + GlobalGetAtomNameA-via-APC, mais NtFindAtom seul ne la déclenche généralement pas.

Exemples de syscalls directs

asmx64 direct stub

; Direct syscall stub for NtFindAtom (SSN 0x14, all builds)
NtFindAtom PROC
    mov  r10, rcx          ; syscall convention
    mov  eax, 14h          ; SSN
    syscall
    ret
NtFindAtom ENDP

cRendezvous marker lookup (Atom Bombing stage-2 helper)

// Stage-2 implant looks up the agreed marker atom to find the stage-1
// shellcode payload uploaded via NtAddAtom by a sibling. Returns the
// atom ID, ready to feed to GlobalGetAtomNameA via an APC in the target.
#include <windows.h>
#include <winternl.h>

typedef NTSTATUS (NTAPI *pNtFindAtom)(PWSTR, ULONG, PUSHORT);

USHORT FindRendezvousAtom(PCWSTR marker) {
    pNtFindAtom NtFindAtom = (pNtFindAtom)GetProcAddress(
        GetModuleHandleA("ntdll.dll"), "NtFindAtom");
    USHORT id = 0;
    ULONG bytes = (ULONG)(wcslen(marker) * sizeof(WCHAR));
    NTSTATUS s = NtFindAtom((PWSTR)marker, bytes, &id);
    return NT_SUCCESS(s) ? id : 0;
}

rustSandbox marker probe

// Cargo: ntapi = "0.4", widestring = "1"
// Probe the global atom table for known sandbox-harness markers. Presence
// of any of these signals an analysis environment.
use ntapi::ntexapi::NtFindAtom;
use widestring::U16CString;

const MARKERS: &[&str] = &[
    "TriageHostMarker_v3",
    "JoeSandboxAgent_active",
    "AnyRun_Probe",
];

pub unsafe fn looks_like_sandbox() -> bool {
    for &m in MARKERS {
        let w = U16CString::from_str(m).unwrap();
        let mut id: u16 = 0;
        let s = NtFindAtom(w.as_ptr() as _, (w.len() * 2) as u32, &mut id);
        if s >= 0 && id != 0 { return true; }
    }
    false
}

Mappings MITRE ATT&CK

Last verified: 2026-05-20