
Enumerazione anonima di Active Directory in un solo passaggio tramite SAMR e LSARPC — sessione nulla, senza credenziali, con output strutturato riutilizzabile.
Un enumeratore Active Directory a passaggio singolo per una sessione anonima (null), che utilizza le named pipe \samr e \lsarpc. Nessuna credenziale richiesta.
Non fa nulla che gli strumenti classici non possano fare. Quello che fa è raccogliere tutto in una sola esecuzione e presentare i risultati in modo pulito. Durante un engagement ti trovi senza un account di dominio, trovi il DC tramite DNS e vuoi il quadro completo: account, dettagli per utente, gruppi, policy e le parti LSA/DNS, senza dover mettere insieme sessioni rpcclient o diversi script separati e poi analizzare manualmente il loro stdout. Questo esegue quel passaggio per te e scrive output strutturato e riutilizzabile:
manifest.json, userlist.txt / computerlist.txt pronti all'uso, e una lista di RID salvata che puoi riutilizzare invece di forzare due volte.Esegui questo strumento solo su sistemi che possiedi o che sei esplicitamente autorizzato a testare. Enumerare la directory di qualcun altro senza permesso non è accettabile e, a seconda di dove ti trovi, potrebbe essere illegale.
Esistono due versioni che si comportano in modo identico. Usa quella per cui hai la libreria:
adnullenum.py — basato su impacket.$) sono separati dagli utenti reali.Segnala anche account interessanti per te: cose come "password non richiesta", "password che non scade mai", AS-REP-roastable, delega non vincolata, mai effettuato il logon, o una descrizione che menziona una password.
Un paio di cose che derivano naturalmente da questo:
Tutto qui è SAMR/LSARPC anonimo standard, e gli strumenti consolidati raggiungono già gli stessi dati. Questo è un wrapper di comodità, non una nuova capacità, quindi vale la pena conoscere le alternative:
--rid-brute, --users, --pass-pol) copre la stessa enumerazione all'interno di un framework molto più ampio.samrdump.py (utenti/gruppi/alias + dettaglio per utente) e lookupsid.py (RID cycling su LSA). Nessuna esecuzione singola, nessun fallback SAMR→LSA, solo stdout.rpcclient espone le chiamate sottostanti (queryuser, enumdomusers, querydominfo, lsaquery, lookupsids, …) ma in modo interattivo e solo stdout. Il suo enumdomusers elenca gli utenti standard per nome, nessun account macchina ($), e il dettaglio completo è queryuser uno alla volta. Senza un ciclo di RID-cycling integrato non può recuperare i computer o aggirare l'enumerazione limitata. Vedi Farlo a mano.Ciò che adnullenum aggiunge è il packaging: una singola esecuzione in sessione null invece di diversi strumenti, SAMR-first con un fallback LSA opt-in, flag curati per gli account interessanti e output ordinato multi-formato che puoi passare direttamente al passo successivo o riaprire più tardi. Se quel flusso di lavoro si adatta a come lavori, usalo; se preferisci uno strumento collaudato, rivolgiti a enum4linux-ng o NetExec.
Ti servono Python 3.9+ e una libreria SMB. Un ambiente virtuale mantiene tutto ordinato:
# 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
Tutto qui. Esegui python3 adnullenum.py --help per vedere tutto.
Tutto passa attraverso un singolo --mode. Il default è recon, che è la cosa sicura da eseguire per prima.
| Modalità | Cosa ottieni |
|---|---|
recon | Informazioni di dominio, conteggi, policy di password/lockout e i dettagli LSA/DNS. Nessun brute-forcing. Solo un'occhiata in giro. |
rids | Trova quali account esistono e li suddivide in utenti / computer / gruppi. |
users | Quanto sopra, più il dettaglio completo su ogni utente reale e il riepilogo degli "account interessanti". Aggiungi --include-groups per elencare anche i gruppi di ogni utente. |
groups | Gruppi di dominio e alias builtin con i loro membri. |
full | Tutto quanto. |
# 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
Se il dominio non ti permette di elencare gli utenti direttamente (cosa comune), lo strumento ripiega sul RID cycling: chiede al DC di tradurre gli ID account in nomi in batch da 1000. Per default esegue una scansione verso l'alto finché non ha trovato tutto ciò che il DC dice esistere, o finché 5000 ID consecutivi non tornano vuoti. Puoi invece vincolarlo a un intervallo esatto:
python3 adnullenum.py 10.0.0.10 --mode rids --range 500-50000
Alcuni DC rifiutano completamente SAMR anonimo (enumdomains e la traduzione dei RID tornano ACCESS_DENIED). L'esecuzione non si arrende:
\lsarpc, che risponde frequentemente quando SAMR non lo fa.--lsa-fallback, lo strumento ritenta la stessa scansione su LSA LsarLookupSids usando il SID del dominio, che ti dà comunque l'inventario degli account (nomi e tipi, inclusi i computer). È disattivato per default perché è un secondo passaggio di brute-force; senza il flag l'esecuzione si ferma al recon e lo dice.Trovare gli account è la parte lenta, quindi lo strumento salva la lista (rids.txt) nella cartella di output di ogni esecuzione. Punta un'esecuzione successiva a quella cartella con --session e salterà il brute e riutilizzerà ciò che hai già trovato:
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 accetta la cartella di un'esecuzione precedente. (--rid-file fa lo stesso da un file di testo semplice con un RID per riga.)
Ogni esecuzione crea una cartella con timestamp sotto output/:
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 e csv vengono sempre scritti; aggiungi --json per avere anche una cartella json/.
La cartella lists/ contiene due file di testo pensati per alimentare direttamente altri strumenti:
lists/userlist.txt — da inserire direttamente nell'AS-REP roasting, nel password spraying o nella lista --users di un cracker. In modalità users/full contiene solo account abilitati; in modalità rids (senza dettaglio per utente) è ogni utente.lists/computerlist.txt — nomi di account macchina con il $ mantenuto (il sAMAccountName), per i controlli sugli account macchina pre-Windows 2000.Hai dimenticato di guardarli, o hai eseguito solo rids e ora vuoi le liste? Punta alla cartella dell'esecuzione e vengono ricostruite dai CSV, senza bisogno di rete:
python3 adnullenum.py --lists-from output/20260917-1530_10.0.0.10_full
Sullo schermo ottieni un'anteprima limitata così un dominio grande non inonda il terminale (--limit, default 100 per sezione) — i file hanno sempre i dati completi. Il colore è attivo quando sei su un terminale; --no-color lo disattiva.
Un'esecuzione full contro un DC di test (sanificato). Sullo schermo ottieni il recon, la scansione dei RID, il riepilogo degli account interessanti e la lista dei file scritti:
$ 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
Un singolo record da txt/users.txt (il gruppo primario e i gruppi diretti sono risolti in nomi):
[+] 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
Tutto qui è SAMR/LSARPC standard, quindi puoi estrarre gli stessi fatti una chiamata alla volta con rpcclient di Samba. Connettiti prima in modo anonimo:
rpcclient -U "" -N 10.0.0.10
| Questo strumento | Equivalente rpcclient |
|---|---|
recon (info dominio + conteggi) | querydominfo |
recon (policy password) | getdompwinfo |
recon (dominio LSA + SID) | lsaquery, lsaenumsid |
rids (traduzione nome/SID) | lookupnames <name>, lookupsids <SID> |
rids (lista lato server) | enumdomusers (solo utenti standard — nessun account macchina $) |
users (dettaglio per utente) | queryuser <rid> o queryuser <name>, querydispinfo |
groups | enumdomgroups, querygroupmem <rid>, enumalsgroups builtin, queryaliasmem builtin <rid> |
enumdomusers restituisce gli account utente standard solo per nome; gli account macchina ($) vengono filtrati, e il dettaglio completo significa eseguire queryuser un account alla volta. rpcclient non ha un ciclo di RID-cycling integrato, quindi non può recuperare gli account macchina (o qualsiasi altra cosa) quando l'enumerazione lato server è limitata; dovresti scriptare lookupsids su un intervallo da solo. Inoltre non ha un comando per la policy di lockout e non restituisce i DNS/foresta/GUID LSA o i trust, motivo per cui questo strumento interroga direttamente PolicyDnsDomainInformation.
Per gli equivalenti scriptati e come questo strumento si relaziona ad essi, vedi Come si confronta.
Se sei dalla parte blu e vuoi chiudere tutto questo, il percorso anonimo è la cosa da chiudere:
RestrictAnonymousSAM / RestrictAnonymous).Niente di tutto ciò impedisce a un utente autenticato di leggere gli stessi dati — è normale e previsto. Chiude solo il percorso senza credenziali.
\samr, o chiamate di policy/lookup contro \lsarpc, in poco tempo.--sleep e --jitter possono distribuire le chiamate, allerta sul conteggio totale su una finestra piuttosto che solo sulla frequenza.--lsa-fallback per provare LSA LsarLookupSids per l'inventario (vedi "Quando SAMR è bloccato"). Se anche le lookup LSA sono bloccate, è possibile solo il recon (nome del dominio + SID).MIT. Vedi LICENSE.