> Windows Syscalls
ntoskrnl.exeT1055T1559T1497

NtFindAtom

Sucht ein vorhandenes globales Atom über seinen Namen und liefert dessen 16-Bit-ID, ohne den Refcount zu erhöhen.

Prototyp

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

Argumente

NameTypeDirDescription
AtomNamePWSTRinUTF-16-Puffer, dessen Bytes der Kernel mit vorhandenen Atom-Einträgen vergleicht.
LengthULONGinGröße des Puffers in Bytes.
AtomPRTL_ATOMoutEmpfängt die 16-Bit-Atom-ID, falls gefunden. Optional — NULL übergeben, um nur Existenz zu prüfen.

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
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

Kernel-Modul

ntoskrnl.exeNtFindAtom

Verwandte APIs

GlobalFindAtomAGlobalFindAtomWFindAtomANtAddAtomNtQueryInformationAtom

Syscall-Stub

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

Undokumentierte Hinweise

SSN `0x14` ist von 1507 bis 24H2 stabil — Atomtabellen-Schnittstellen bewegen sich schlicht nicht. NtFindAtom ist der Read-only-Bruder von NtAddAtom: er läuft die globale Hash-Tabelle ab, vergleicht den Length-Bytes-Input bytefür Byte gegen jeden Eintrag und liefert die vorhandene ID, ohne den Refcount anzufassen. Im Gegensatz zu NtAddAtom liefert NtFindAtom STATUS_OBJECT_NAME_NOT_FOUND, wenn der Name fehlt (NtAddAtom würde ihn anlegen). Win32-Wrapper: `GlobalFindAtomA/W`.

Häufige Malware-Nutzung

**Atom-Bombing-Rendezvous** — der zweite Implant (oder ein Geschwister-Thread) ruft NtFindAtom auf einer vereinbarten Marker-Zeichenkette auf, um zu prüfen, ob Stage-1-Shellcode bereits in der Tabelle liegt, und um dessen ID zu lernen, bevor er den APC einreiht, der `GlobalGetAtomNameA` im Ziel auslöst. Auch für **Inter-Implant-IPC-Koordination**, bei der die Atomtabelle als verdeckter Key/Value-Store dient: Implants publizieren Session-Kennungen, Beacon-IDs oder Callback-URL-Hashes als Atom-Namen, und Peers ermitteln einander mit `NtFindAtom` ohne Disk-, Registry- oder Socket-Traffic. **Sandbox-Detection** — die Tabelle auf Atoms abfragen, die Sandbox-Harnesses hinterlassen (Triage und Joe Sandbox registrieren je einige erkennbare Atom-Strings beim Boot); Anwesenheit = Analyseumgebung. Billig, keine Imports außer ntdll, unsichtbar für Datei-/Registry-zentrierte EDRs.

Erkennungs­möglichkeiten

Noch geringeres Volumen als NtAddAtom in der Alarm-Telemetrie — die meisten Produkte behandeln die Atomtabelle als Blackbox. Nützliches Hunting: **NtFindAtom aufgerufen von einem Prozess, der nie NtAddAtom aufruft**, mit Length passend zu einem Marker-Lookup statt eines Window-Class-Namens (typisch 8-64 Bytes), korreliert mit anschließendem NtQueueApcThread in einen Remote-Prozess — starkes Zeichen für Atom-Bombing-Rendezvous. ETW Microsoft-Windows-Kernel-Audit-API-Calls macht den Syscall sichtbar. WinDbg `!atom` zeigt die aktuelle globale Tabelle und ist die Ground Truth in IR. Defenders Verhaltens-Engine ergänzte (~2018) eine Atom-Bomb-spezifische Detektion, die auf die vollständige Kette GlobalAddAtomA + GlobalGetAtomNameA-via-APC feuert, aber NtFindAtom allein löst sie meist nicht aus.

Direkte Syscall-Beispiele

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
}

MITRE ATT&CK-Mappings

Last verified: 2026-05-20