crypt0p3g/adnullenum
adnullenum is a single-pass Active Directory enumerator that uses anonymous (null) SMB sessions over the \samr and \lsarpc named pipes to pull domain info, password/lockout policy, RID-cycled account inventory, per-user detail, and group membership without credentials. It consolidates what rpcclient, impacket's samrdump.py/lookupsid.py, enum4linux-ng, and NetExec each do separately into one run, falls back to LSA lookups when SAMR is locked down, flags interesting accounts (AS-REP-roastable, PASSWORD_NOT_REQUIRED, unconstrained delegation, etc.), and writes ready-to-use userlist.txt/computerlist.txt plus a reusable RID cache. The README also gives blue-team guidance on closing null-session access (RestrictAnonymousSAM, Pre-Windows 2000 Compatible Access group) and detecting it via Event 4661/4662/4624/5140.
What it is
adnullenum (github.com/crypt0p3g/adnullenum) is a Python 3.9+ null-session AD enumerator shipped as two interchangeable scripts — adnullenum.py (impacket-based) — run via a single --mode flag (recon, full, rids, users).
How it works
RID sweeps go through SAMR in batches of 1000, by default open-ended upward until 5000 consecutive IDs come back empty (or a pinned --range). Each run writes a timestamped folder under output/ containing rids.txt, manifest.json, txt/csv (JSON optional), and the lists/ folder. A prior run's RID list can be replayed into a new mode via --session <folder> (or --rid-file) to skip re-bruting. If --lists-from <folder> is given, userlist.txt/computerlist.txt are rebuilt from existing CSVs with no network call.
Preconditions / Affected
Requires only an anonymous SMB session (port 445 only, no RPC endpoint mapper 135). If SAMR RID translation returns ACCESS_DENIED, LSA fallback requires the explicit --lsa-fallback flag (off by default, described as a second brute-force pass). If LSA lookups are also blocked, the tool degrades to recon-only (domain name + SID), and the README states no anonymous tool can enumerate accounts on such a target.
What to do
Example commands from the README:
python3 adnullenum.py 10.0.0.10 # recon (default, safe first step)
python3 adnullenum.py 10.0.0.10 --mode full
python3 adnullenum.py 10.0.0.10 --mode rids --start-rid 1000 --max-rid 200000
python3 adnullenum.py 10.0.0.10 --mode users --sleep 1 --jitter 40 # throttled
python3 adnullenum.py 10.0.0.10 --mode rids --range 500-50000
python3 adnullenum.py 10.0.0.10 --mode rids --session output/20260917-1530_10.0.0.10_rids
python3 adnullenum.py --lists-from output/20260917-1530_10.0.0.10_fullDetection guidance beyond generic event IDs: alert on raw call volume from a single source against \samr/\lsarpc in a short window rather than rate, since --sleep/--jitter spread calls out specifically to evade rate-based alerting.
Caveats
The README itself frames this as a packaging convenience, not new capability — enum4linux-ng and NetExec reach the same data and are recommended if a "battle-tested tool" is preferred. Per-user detail and group membership still require SAMR; when SAMR is blocked those stages are skipped regardless of LSA fallback success.
Organisations named here
- Pre-Windows 2000 Compatible Access
- RID cycling
- unconstrained delegation
Technologies named here
- adnullenum
- Active Directory
- Impacket
- SMBv1
- enum4linux-ng
- NetExec
- samrdump.py
- lookupsid.py
- rpcclient
- Python
- SMB
Techniques named here
- Null session / anonymous SAMR enumeration
- LSARPC enumeration
- RID cycling / RID brute forcing
- LSA fallback for RID translation
- AS-REP Roasting
- Pre-Windows 2000 machine account checks
- Interesting account flagging
- Throttled enumeration
Related in Offensive Security