█████╗ ██████╗ ██████╗ ██████╗ █████╗ ██████╗ ██╗ ██╗
██╔══██╗██╔══██╗ ██╔════╝ ██╔══██╗██╔══██╗██╔══██╗██║ ██║
███████║██║ ██║ ██║ ███╗██████╔╝███████║██████╔╝███████║
██╔══██║██║ ██║ ██║ ██║██╔══██╗██╔══██║██╔═══╝ ██╔══██║
██║ ██║██████╔╝ ╚██████╔╝██║ ██║██║ ██║██║ ██║ ██║
╚═╝ ╚═╝╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝
Active Directory · attack-path graph · operator-first
A modern, local, BloodHound-style attack-path graph for Active Directory.
Import a BloodHound collector ZIP, explore AD relationships through a clean, fast,
operator-focused web UI, and walk the abuse paths to Domain Admin — all offline,
no Node, no Docker, no pip install — the Python standard library plus a
single vendored MIT file (lib/multipart.py).
Crafted & weaponized by c4sh$r · authorized engagements only · companion to ⚡ ADAutoPwn
BloodHound is excellent — but sometimes you just want a lightweight local viewer that opens instantly, doesn't dump 5,000 nodes on screen at once, keeps one engagement isolated, highlights the abuse paths with ready-to-run commands, and feels native to an offensive workflow.
That's ADAutoGraph. You import a BloodHound ZIP, pick a domain, and build the visible graph progressively — from searches, focused object actions, ACL views, or full attack paths. Mark what you own, and it draws the chain to Domain Admin for you.
It's the graphical companion to ⚡ ADAutoPwn:
that tool can launch ADAutoGraph automatically at the end of a run, import the
freshly-collected BloodHound data, and pre-mark every principal it already
compromised as owned — so the path lights up the moment the browser opens.
⚠️ Legal: Use only against systems you are explicitly authorized to test — your own lab, a CTF, or a signed engagement. You are responsible for your actions.
| Area | What you get |
|---|---|
| Import | BloodHound collector ZIPs → normalized users, groups, computers, domains, OUs, GPOs, containers and ACL edges, stored in data/graph.db (SQLite) |
| Multi-domain | A domain/project selector — import many datasets, keep each isolated, switch freely |
| Progressive graph | Starts empty; build only the context you need via search / views / object actions — huge datasets stay readable |
| Modern canvas | Deterministic static layout (no force physics, no magnetic drift), per-node drag, directional arrows (who controls whom), edge labels baked into the line and colored by severity |
| Severity-aware ACLs | 🔴 Critical (DCSync, GenericAll, WriteDACL, GetChangesAll) · 🟠 High (WriteOwner, Owns, ForceChangePassword, Shadow Credentials) · 🟡 Medium (WriteSPN, AddMember, ReadGMSAPassword, delegation) |
| Views | Overview · Attack paths · ACLs · High value · Owned · All — one click each |
| Object inspector | Full imported properties, outbound + inbound edges, abuse-focused edge list, raw property view |
| Attack-path builder | Mark objects as owned → it traverses abuse edges, group membership and OU containment to high-value targets, and falls back to the best reachable chain when there's no clean DA route |
| Group & OU delegation | The inspector expands rights a principal wields indirectly — through group membership (nested + AddSelf/AddMember) and through control of an OU/Container (GenericAll on an OU → the users it holds), each shown with the exact via trail. The writeup's D.Anderson → Marketing OU → E.Rodriguez → Chiefs Marketing → M.Harris chain, inline. |
| Member-of context | Group memberships surfaced with what they grant (e.g. Remote Management Users → WinRM, Protected Users → hardened) — access no ACL edge represents |
| ADCS / ESC | Load certipy find -json → CertTemplate/CA nodes + ESC edges, flagging exactly which principal is vulnerable to which ESC (and every group member inherits it). Plus a built-in ESC1–ESC16 playbook modal with chained certipy commands, parameterized to the active domain |
| Kerberos delegation | A delegation card per object: which flavour is configured (unconstrained · constrained · constrained without protocol transition · RBCD), the exact SPNs it may delegate to and which object each resolves to, who may act on its behalf, and its own SPNs. When protocol transition is off, the commands are the RBCD + -additional-ticket S4U2Proxy chain — not the getST that dies on KDC_ERR_BADOPTION. It also detects an Administrator flagged sensitive (NOT_DELEGATED) and impersonates the target's machine account instead |
| Follow the chain | Selecting an object can expand its whole onward attack chain, not just the first hop — a bounded BFS over abusable, membership and containment edges, laid out in columns by distance, stopping at the domain object instead of dumping the directory |
| Command snippets | Per-edge Linux and Windows abuse commands, color-coded, with a copy button. Multi-step abuses are emitted as a numbered recipe including the steps that come before the abuse (join the group, write the OU ACE -inheritance) and the cleanup after, using distinguishedNames and sAMAccountNames so they run as pasted |
| Owned, your way | Toggle owned in the UI or pre-seed it on import (used by ADAutoPwn) |
| Manage the DB | Delete any imported graph straight from the domain list (cascades its nodes/edges) |
ADAutoGraph is built to drop into the ADAutoPwn workflow:
- ADAutoPwn auto-launches the server at the end of a run, imports the
BloodHound zip, pre-marks owned principals, and opens your browser — no
manual steps. (
--no-webto disable,--web-portto change the port.) - Visualize any run's data on demand, even standalone:
adautopwn --graph /path/to/bloodhound.zip -d corp.local --web
- If you cloned ADAutoGraph next to ADAutoPwn (or set
ADAUTOGRAPH_DIR), ADAutoPwn finds it automatically.install.shover there clones it for you and putsadautographon yourPATH.
git clone https://github.com/C4sh3R/ADAutoGraph.git
cd ADAutoGraph
chmod +x server.pyNo pip install, no Node, no Docker. It runs on the Python standard library
plus one vendored MIT dependency shipped inside the repo
(lib/multipart.py, from defnull/multipart —
see THIRD_PARTY_NOTICES.md), which replaces the cgi
module removed in Python 3.13. Works on Python 3.10 → 3.13+.
ln -sf "$PWD/server.py" ~/.local/bin/adautograph # ~/.local/bin is on PATH
# now just: adautographserver.py resolves its own directory, so the symlink works from anywhere.
(ADAutoPwn's install.sh also clones ADAutoGraph and creates this symlink for you.)
adautograph # or: python3 -B server.py
# → ADAutoGraph listening on http://127.0.0.1:8765Then in the browser:
- Import a BloodHound
.zip. - Open the imported domain.
- Search for a user, group, computer or domain object.
- Click a node to inspect its properties, edges and abuse commands.
- Mark compromised objects as
owned(right panel). - Hit Attack paths to draw the chain from what you own to Domain Admin.
adautograph --host 127.0.0.1 --port 8765| Option | Description | Default |
|---|---|---|
--host |
Bind address | 127.0.0.1 |
--port |
HTTP port | 8765 |
Small JSON API (handy for scripting / tooling like ADAutoPwn):
| Method & path | Purpose |
|---|---|
POST /api/import |
Multipart upload: zip (BloodHound zip), optional name, optional owned (names/SIDs, separated by spaces/commas/newlines → pre-marked owned) |
GET /api/domains |
List imported domains (id, name, counts) |
GET /api/domain/<id>/graph |
Graph payload for a view (?view=…&q=…&focus=…&rel=abusable|outbound|inbound|all|chain). rel=chain walks the full onward chain from focus and tags each node with its depth |
GET /api/domain/<id>/search?q= |
Search nodes |
GET /api/domain/<id>/stats |
Node/edge stats |
GET /api/domain/<id>/node/<sid> |
Full object + edges, inherited rights (groupDelegated) and the Kerberos delegation card |
POST /api/domain/<id>/owned/<sid> |
Toggle a node's owned flag |
# import a zip and pre-mark owned principals in one shot
curl -F "zip=@bloodhound.zip" -F "name=corp.local" \
-F "owned=jdoe,svc_sql,DC01\$" http://127.0.0.1:8765/api/importADAutoGraph/
├── server.py # the whole backend (stdlib http.server + sqlite3)
├── lib/
│ └── multipart.py # vendored MIT multipart parser (replaces stdlib `cgi`, gone in 3.13)
├── tests/
│ └── test_multipart_form.py
├── web/
│ ├── index.html
│ ├── style.css
│ └── app.js # the canvas renderer + UI
├── data/
│ └── graph.db # imported data — local only, git-ignored (delete to reset)
├── assets/screenshot.png
├── requirements.txt
├── THIRD_PARTY_NOTICES.md
├── LICENSE
└── README.md
ADAutoGraph is free and source-available (noncommercial), built on a lot of late nights. If it made an engagement smoother or helped you learn, consider buying me a coffee — it directly fuels the next feature. 🙏
PRs and issues are very welcome — the AD graph space has endless room to grow.
git clone https://github.com/<you>/ADAutoGraph.git && cd ADAutoGraph
git checkout -b feature/my-idea
# hack on server.py (backend) or web/app.js (renderer) — keep it pip-dependency-free
python3 -c "import ast; ast.parse(open('server.py').read())" # must stay clean
python3 -m unittest discover -s tests # tests must pass
git commit -am "feat: my idea" && git push origin feature/my-idea- More abuse-command recipes per edge (Linux + Windows).
- Session /
AdminTo/CanRDPlateral edges in the attack-path traversal. - Export the current graph (PNG / JSON).
- Saved layouts per domain.
- Dark / light themes.
Test against a lab or a box you're allowed to use, and never commit loot (the
.gitignorealready blocksdata/*.dband uploads).
ADAutoGraph is not a replacement for the official BloodHound / BloodHound Enterprise. It's a lightweight local viewer focused on offensive workflow, abuse readability and fast inspection — and on pairing tightly with ADAutoPwn.
PolyForm Noncommercial 1.0.0 — see LICENSE. Free to use, modify
and share for noncommercial purposes (research, education, personal use,
nonprofits). Commercial use, selling or reselling is not permitted — all
commercial rights are reserved by the author (c4sh$r). Provided for
authorized security testing only; the author assumes no liability for misuse.
