
Einmalige anonyme Active-Directory-Enumeration über SAMR und LSARPC — Null-Session, ohne Anmeldedaten, mit strukturierter wiederverwendbarer Ausgabe.
Ein Single-Pass-Active-Directory-Enumerator für eine anonyme (Null-)Session,
unter Verwendung der Named Pipes \samr und \lsarpc. Keine Anmeldedaten erforderlich.
Es tut nichts, was die klassischen Tools nicht auch können. Was es tut, ist, alles in
einem Durchlauf zu sammeln und die Ergebnisse übersichtlich aufzubereiten. In einem Engagement landest du ohne Domänenkonto, findest den DC über DNS und willst das Gesamtbild – Konten,
Details pro Benutzer, Gruppen, Richtlinien und die LSA/DNS-Informationen –, ohne rpcclient-Sessions
oder mehrere separate Skripte zusammenzustückeln und deren stdout manuell zu parsen. Dies erledigt diesen Durchlauf für dich und schreibt strukturierte, wiederverwendbare Ausgaben:
manifest.json, sofort einsetzbaren userlist.txt /
computerlist.txt und einer gespeicherten RID-Liste, die du wiederverwenden kannst, statt zweimal zu brute-forcen.Bitte führe dies nur gegen Systeme aus, die dir gehören oder für die du ausdrücklich autorisiert bist, zu testen. Das Verzeichnis von jemand anderem ohne Erlaubnis zu enumerieren, ist nicht in Ordnung, und je nachdem, wo du bist, kann es illegal sein.
Es gibt zwei Versionen, die sich identisch verhalten. Verwende die Bibliothek, die du hast:
adnullenum.py — basiert auf impacket.$ enden), werden
von echten Benutzern getrennt.Es markiert außerdem interessante Konten für dich: Dinge wie „Passwort nicht erforderlich“, „Passwort läuft nie ab“, AS-REP-roastable, unconstrained delegation, nie angemeldet oder eine Beschreibung, die ein Passwort erwähnt.
Ein paar Dinge, die sich daraus natürlich ergeben:
Alles hier ist Standard-anonymes SAMR/LSARPC, und die etablierten Tools erreichen bereits dieselben Daten. Dies ist ein Komfort-Wrapper, keine neue Fähigkeit, daher lohnt es sich, die Alternativen zu kennen:
--rid-brute, --users,
--pass-pol) deckt dieselbe Enumeration innerhalb eines viel größeren Frameworks ab.samrdump.py (Benutzer/Gruppen/Aliase +
Details pro Benutzer) und lookupsid.py (RID-Cycling über LSA). Kein einzelner Durchlauf, kein
SAMR→LSA-Fallback, nur stdout.rpcclient legt die zugrunde liegenden Aufrufe offen (queryuser, enumdomusers,
querydominfo, lsaquery, lookupsids, …), aber interaktiv und nur stdout.
Sein enumdomusers listet Standardbenutzer nach Namen auf, keine Maschinen- ($) Konten, und
vollständige Details gibt es mit queryuser einzeln. Ohne eingebaute RID-Cycling-Schleife
kann es Computer nicht wiederherstellen oder eingeschränkte Enumeration umgehen. Siehe
Manuell durchführen.Was adnullenum hinzufügt, ist die Verpackung: ein Null-Session-Durchlauf statt mehrerer Tools, SAMR-first mit einem optionalen LSA-Fallback, kuratierte Flags für interessante Konten und ordentliche Multi-Format-Ausgabe, die du direkt an den nächsten Schritt weitergeben oder später erneut öffnen kannst. Wenn dieser Workflow zu deiner Arbeitsweise passt, verwende es; wenn du lieber ein kampferprobtes Tool möchtest, greife zu enum4linux-ng oder NetExec.
Du brauchst Python 3.9+ und eine SMB-Bibliothek. Eine virtuelle Umgebung hält es ordentlich:
# clone / copy the files, then from the project folder:
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install impacket # for adnullenum.py
Das war's. Führe python3 adnullenum.py --help aus, um alles zu sehen.
Alles läuft über einen einzigen --mode. Der Standard ist recon, was das
Sicherste ist, was man zuerst ausführt.
| Modus | Was du bekommst |
|---|---|
recon | Domäneninformationen, Zählungen, Passwort-/Sperrrichtlinie und die LSA-/DNS-Details. Kein Brute-Forcing. Nur ein Blick. |
rids | Findet, welche Konten existieren, und sortiert sie in Benutzer / Computer / Gruppen. |
users | Das Obige plus vollständige Details zu jedem echten Benutzer und die Zusammenfassung der „interessanten Konten“. Füge --include-groups hinzu, um auch die Gruppen jedes Benutzers aufzulisten. |
groups | Domänengruppen und integrierte Aliase mit ihren Mitgliedern. |
full | Alles davon. |
# 1. Is anonymous access open, and how big is this domain?
python3 adnullenum.py 10.0.0.10
# 2. Grab everything
python3 adnullenum.py 10.0.0.10 --mode full
# 3. Just the account inventory, wider net for a big domain
python3 adnullenum.py 10.0.0.10 --mode rids --start-rid 1000 --max-rid 200000
# 4. Go slower to stay quiet
python3 adnullenum.py 10.0.0.10 --mode users --sleep 1 --jitter 40
# 5. Also write JSON (txt and csv are always written)
python3 adnullenum.py 10.0.0.10 --mode full --json
Wenn die Domäne dich Benutzer nicht direkt auflisten lässt (häufig), fällt das Tool auf RID-Cycling zurück: Es bittet den DC, Konto-IDs in Stapeln von 1000 in Namen zu übersetzen. Standardmäßig tastet es aufwärts ab, bis es alles gefunden hat, was der DC als existierend angibt, oder bis 5000 IDs in Folge leer zurückkommen. Du kannst es stattdessen auf einen exakten Bereich festlegen:
python3 adnullenum.py 10.0.0.10 --mode rids --range 500-50000
Einige DCs verweigern anonymes SAMR vollständig (enumdomains und RID-Übersetzung kommen
als ACCESS_DENIED zurück). Der Durchlauf gibt nicht auf:
\lsarpc, das häufig antwortet, wenn SAMR es nicht tut.--lsa-fallback übergibst, wiederholt das Tool denselben Sweep über LSA
LsarLookupSids unter Verwendung der Domänen-SID, was dir immer noch das Konto-
Inventar liefert (Namen und Typen, einschließlich Computer). Es ist standardmäßig deaktiviert, weil
es ein zweiter Brute-Force-Durchlauf ist; ohne das Flag stoppt der Durchlauf beim Recon und
sagt es dir.Das Finden der Konten ist der langsame Teil, daher speichert das Tool die Liste (rids.txt) im
Ausgabeordner jedes Durchlaufs. Richte einen späteren Durchlauf mit --session auf diesen Ordner und
es überspringt das Brute-Forcing und verwendet wieder, was du bereits gefunden hast:
python3 adnullenum.py 10.0.0.10 --mode rids
# -> output/20260917-1530_10.0.0.10_rids/
python3 adnullenum.py 10.0.0.10 --mode users \
--session output/20260917-1530_10.0.0.10_rids
--session nimmt den Ordner eines vorherigen Durchlaufs. (--rid-file macht dasselbe
aus einer einfachen Textdatei mit einer RID pro Zeile.)
Jeder Durchlauf legt einen zeitgestempelten Ordner unter output/ ab:
output/20260917-1530_10.0.0.10_full/
├── rids.txt # the account IDs found (reuse with --session)
├── manifest.json # summary: counts, interesting accounts, run details
├── access_denied.txt # only if something was denied/restricted (with a timestamp)
├── output
├──── lists/ # ready-to-use lists (see below)
├──── txt/ # easy to read
└──── csv/ # easy to grep / open in a spreadsheet
txt und csv werden immer geschrieben; füge --json für einen json/-Ordner hinzu.
Der Ordner lists/ enthält zwei einfache Dateien, die dafür gemacht sind, direkt andere Tools zu versorgen:
lists/userlist.txt — direkt einsetzbar für AS-REP Roasting, Password Spraying
oder die --users-Liste eines Crackers. Im Modus users/full enthält sie nur aktivierte
Konten; im Modus rids (keine Details pro Benutzer) ist es jeder Benutzer.lists/computerlist.txt — Maschinenkontonamen mit beibehaltenem $ (der
sAMAccountName), für Pre-Windows-2000-Maschinenkonto-Prüfungen.Hast du vergessen, sie anzusehen, oder nur rids ausgeführt und willst jetzt die Listen? Richte es auf den
Ordner des Durchlaufs und sie werden aus den CSVs neu erstellt, ohne Netzwerk:
python3 adnullenum.py --lists-from output/20260917-1530_10.0.0.10_full
Auf dem Bildschirm bekommst du eine begrenzte Vorschau, damit eine große Domäne dein Terminal nicht überflutet
(--limit, Standard 100 pro Abschnitt) – die Dateien enthalten immer die vollständigen Daten.
Farbe ist an, wenn du an einem Terminal bist; --no-color schaltet sie aus.
Ein full-Durchlauf gegen einen Test-DC (bereinigt). Auf dem Bildschirm bekommst du Recon, den RID-
Sweep, die Zusammenfassung der interessanten Konten und die Liste der geschriebenen Dateien:
$ python3 adnullenum.py 10.0.0.10 --mode full
[*] Connecting to 10.0.0.10:445 anonymously ...
[+] SAM domain: CORP (S-1-5-21-1111111111-2222222222-3333333333)
...
[ COUNTS ]
Users: 43
Groups: 0
Aliases: 17
[ PASSWORD POLICY ]
Min length: 7
Max age: 42 days
Properties: COMPLEX
[*] Bruting RIDs via SAMR (chunk=1000, open-ended 500-100000, stop-after 5000)
[*] up to RID 1498: 31 resolved, gap=0
[*] stop: 5000 consecutive empty RIDs (--stop-after 5000)
[+] Resolved: 5 users, 4 computers, 22 groups, 0 other
[*] Deep-querying 5 users (skipping 4 computers)
[!] Administrator (RID 500) PWD_NEVER_EXPIRES
[!] Guest (RID 501) (disabled) PWD_NOT_REQUIRED, PWD_NEVER_EXPIRES
[!] svc_sql (RID 1104) ASREP_ROASTABLE
[+] 5 users: 3 enabled, 2 disabled, 3 interesting (full detail in the users file)
[ FILES WRITTEN in output/20260101-120000_10.0.0.10_full ]
txt/recon.txt / csv/recon.csv domain info + password/lockout policy
txt/inventory.txt / csv/inventory.csv all resolved accounts
txt/users.txt / csv/users.csv full per-user detail
txt/groups.txt / csv/groups.csv groups + aliases with members
rids.txt existing RIDs (reuse with --session)
lists/userlist.txt usernames, one per line
lists/computerlist.txt machine accounts (with $)
manifest.json run metadata + counts
Ein einzelner Datensatz aus txt/users.txt (die primäre Gruppe und direkte Gruppen sind
zu Namen aufgelöst):
[+] RID 500
Enabled: True
SamAccountName: Administrator
SID: S-1-5-21-1111111111-2222222222-3333333333-500
Description/AdminComment: Built-in account for administering the computer/domain
Last Logon: 2026-09-03 17:58:26+09:00
Password Last Set: 2026-01-23 05:14:35+09:00
Primary Group: Domain Users (513)
Account Control: NORMAL_ACCOUNT | PASSWORD_NEVER_EXPIRES
Logon Count: 92
Direct Domain Groups: Domain Users; Administrators; Domain Admins
>> INTERESTING: PWD_NEVER_EXPIRES
Alles hier ist Standard-SAMR/LSARPC, sodass du dieselben Fakten einen Aufruf nach dem
anderen mit Sambas rpcclient abrufen kannst. Verbinde dich zuerst anonym:
rpcclient -U "" -N 10.0.0.10
| Dieses Tool | rpcclient-Äquivalent |
|---|---|
recon (Domäneninformationen + Zählungen) | querydominfo |
recon (Passwortrichtlinie) | getdompwinfo |
recon (LSA-Domäne + SID) | lsaquery, lsaenumsid |
rids (Name/SID-Übersetzung) | lookupnames <name>, lookupsids <SID> |
rids (serverseitige Liste) | enumdomusers (nur Standardbenutzer — keine $-Maschinenkonten) |
users (Details pro Benutzer) | queryuser <rid> oder queryuser <name>, querydispinfo |
groups | enumdomgroups, querygroupmem <rid>, enumalsgroups builtin, queryaliasmem builtin <rid> |
enumdomusers gibt Standardbenutzerkonten nur nach Namen zurück; Maschinen- ($) Konten
werden herausgefiltert, und vollständige Details bedeuten, queryuser Konto für Konto auszuführen.
rpcclient hat keine eingebaute RID-Cycling-Schleife, sodass es die Maschinen-
konten (oder irgendetwas anderes) nicht wiederherstellen kann, wenn die serverseitige Enumeration eingeschränkt ist; du müsstest
lookupsids selbst über einen Bereich skripten. Es hat außerdem keinen Befehl für die Sperrrichtlinie
und gibt nicht die LSA-DNS-/Forest-/GUID- oder Vertrauensstellungsinformationen zurück, weshalb dieses Tool
PolicyDnsDomainInformation direkt abfragt.
Für skriptgesteuerte Äquivalente und wie dieses Tool mit ihnen zusammenhängt, siehe Wie es sich vergleicht.
Wenn du auf der blauen Seite bist und das abschalten willst, ist der anonyme Pfad die Sache, die geschlossen werden muss:
RestrictAnonymousSAM / RestrictAnonymous).Nichts davon hindert einen angemeldeten Benutzer daran, dieselben Daten zu lesen – das ist normal und zu erwarten. Es schließt nur den Pfad ohne Anmeldedaten.
\samr oder Richtlinien-/Lookup-Aufrufe gegen \lsarpc in kurzer Zeit.--sleep und --jitter die Aufrufe verteilen können, alarmiere auf die Gesamt-
anzahl über ein Zeitfenster statt nur auf die Rate.--lsa-fallback hinzu, um
LSA LsarLookupSids für das Inventar zu versuchen (siehe „Wenn SAMR gesperrt ist“). Wenn auch LSA-
Lookups blockiert sind, ist nur Recon (Domänenname + SID) möglich.MIT. Siehe LICENSE.