Skip to content

Latest commit

 

History

29 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

hashstat

Analyze an NTDS.dit / pwdump for password reuse, weak/cracked passwords, and — with an optional BloodHound export — which of those accounts are actually live. A faster, batteries-included take on Pipal for AD credential audits, built for output that reads clearly in a screenshot and drops straight into a report.

Pure Python standard library. No dependencies.

hashstat demo

Why

A raw NTDS dump tells you the hashes but not the story. hashstat turns it into the findings you actually report:

  • Reuse — how many accounts share a password, the biggest clusters, and who is in them (admins, service accounts, tier-crossing a_useruser pairs).
  • Weak — which passwords fell to a wordlist (reads John's pot), and the overlap of shared and weak.
  • Live risk — join a BloodHound users.json and disabled accounts are excluded by default, so your reset list is only real, usable accounts. adminCount / SPN get tagged.
  • Hand-off lists — cracked accounts, LM-enabled accounts, no-password accounts, and disabled accounts, each exportable as CSV and redactable for sharing.

Install / run

No install needed — it's a single file:

./hashstat.py <NTDS_FILE>

Input is a standard pwdump / secretsdump line (a leading SMB <ip> 445 <HOST> NetExec banner is tolerated):

domain\user:rid:lmhash:nthash:::

Optionally install as a command:

pip install .        # provides the `hashstat` entrypoint

Quick start

# everything, using John's cracked pot + BloodHound enrichment
./hashstat.py ntds.dit -a --bloodhound users.json

# offline demo against the bundled synthetic sample (no John needed)
./hashstat.py sample/ntds.dit.sample -a --potfile sample/ntds.dit.sample.pot --bloodhound sample

Sections

Flag Shows
-o, --overview account/domain census + affected total (reuse OR weak)
-r, --reuse shared-password clusters (cracked plaintext shown inline)
-p, --privileged the "security story": admin / service / tier-crossing reuse
-w, --weak clusters whose shared password was also cracked
-c, --cracked cracked-password stats
-u, --cracked-users per-user cracked list (reset hand-off)
-l, --lm-users accounts with an LM hash enabled
-b, --blank-users accounts with NO password (blank NT hash)
-D, --disabled-users disabled accounts (needs --bloodhound)
-g, --groups full reuse-group membership, categorized
-y, --hygiene username==password, LM, blanks (+ positives)
-a, --all every analysis section

Overview views

The overview renders in several styles via --view (default plain):

./hashstat.py ntds.dit --view tree      # grouped Scope / Credentials / Risk rollup
./hashstat.py ntds.dit --view bars      # horizontal bars, grouped so small risk counts stay visible
./hashstat.py ntds.dit --view bars-pct  # every metric as a % of analyzed accounts
./hashstat.py ntds.dit --view domains   # per-domain distribution bars
./hashstat.py ntds.dit --view sankey    # a 2D flow diagram (needs a ~100-col terminal)
./hashstat.py ntds.dit --view all       # show them all
./hashstat.py ntds.dit -v               # -v is shorthand for --view all (safe to cluster, e.g. -av)

Comma-separate to combine, e.g. --view tree,domains. -v takes no value — use the long --view NAME to pick a single view.

Cracked passwords

hashstat doesn't crack — it reads results you already have, from John or hashcat, for both NT and LM:

# John: crack NT and/or LM, then just run -- hashstat calls `john --show` for both
john --format=nt --wordlist=rockyou.txt ntds.dit
john --format=lm --wordlist=rockyou.txt ntds.dit
./hashstat.py ntds.dit -a                 # auto: john --show (NT+LM) + hashcat's potfile

# hashcat: crack, then point at (or auto-find) its potfile
hashcat -m 1000 nt_hashes  rockyou.txt    # NT
hashcat -m 3000 lm_hashes  rockyou.txt    # LM (per 7-char half)
./hashstat.py ntds.dit -a                 # auto-finds ~/.local/share/hashcat/hashcat.potfile
./hashstat.py ntds.dit -a --potfile hashcat.potfile   # or point at any john/hashcat potfile

When a password is recovered only from its LM hash it's UPPERCASE (LM is case-insensitive); those accounts are counted as cracked and tagged LM in the -u list. A true-case NT crack always wins when both exist.

BloodHound enrichment

./hashstat.py ntds.dit -a --bloodhound users.json      # users file (sibling groups.json auto-found)
./hashstat.py ntds.dit -a --bloodhound ./bloodhound/   # or a dir containing the BloodHound json

Joins on the SID's RID (falling back to sAMAccountName) and pulls enabled, admincount, hasspn, pwdneverexpires, pwdlastset, lastlogontimestamp, passwordnotreqd. If a BloodHound groups file is present (in the dir, or a sibling of the users file), it also resolves exact Domain Admin / Enterprise Admin / Administrators membership (following nested groups). Disabled accounts are excluded from analysis by default and surface under -D instead (review for deletion, not reset). Use --include-disabled to analyze them too.

With enrichment the overview also reports ntdsaudit-style account-hygiene stats for the active set — no-password-required, non-expiring password, stale password (>90d / >1yr), unused account (>90d / >1yr), adminCount, SPN, and LM-hash counts.

Reporting helpers

# reset hand-off list, live accounts only, as CSV
./hashstat.py ntds.dit -u --bloodhound users.json --csv > reset_list.csv

# accounts to delete rather than reset
./hashstat.py ntds.dit -D --bloodhound users.json --csv > delete_list.csv

# redact passwords + hashes (stable pw-NN aliases) — safe to screenshot/share
./hashstat.py ntds.dit -a -s

--csv follows the selected list (-u/-l/-b/-D, else cracked). -s/--screenshot replaces every password and NT hash with a stable alias so a shared screenshot still shows which accounts share a secret without revealing it.

Sample data

The repo ships a fully synthetic, fictional (ACME) dataset so you can try every feature offline — no real credentials, nothing to generate:

  • sample/ntds.dit.sample — 5,000 users (+ machine accounts) with real NT & LM hashes
  • sample/ntds.dit.sample.pot — John potfile covering every password
  • sample/ntds.dit.sample.bloodhound.users.json — matching BloodHound users export (with disabled accounts)
  • sample/ntds.dit.sample.bloodhound.groups.json — BloodHound groups (Domain/Enterprise/builtin Admins)

Passwords come from a public wordlist so john cracks them all.

Safety

Real engagement dumps must never be committed. .gitignore blocks NTDS/SAM/secrets/ kerberos files, cracked-credential lists, and John pots; only the synthetic sample/ files are whitelisted. Keep it that way.

Credits

Account-hygiene stat set inspired by dionach/ntdsaudit.

by Leon Johnson

About

Tool to analyze NTDS hashes and passwords

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages