Skip to content

Asdjdh/ad-lab-forge

Repository files navigation

ad-lab-forge

DRAFT — automation harness for building a blind, gradeable, vulnerable Active Directory lab.

ad-lab-forge builds a fully unattended Windows Server domain controller inside VMware, driven from a non-admin Windows host over WinRM/NTLM, then deploys a randomized vulnerable Active Directory using two well-known external generators (BadBlood + Vulnerable-AD), and finally seals a ground-truth answer key so the lab can be attacked "blind" and graded objectively.


Overview

The harness orchestrates the whole lifecycle of a throwaway AD attack range:

  1. Unattended OS install — an autounattend.xml answer file installs Windows Server with autologon, enables WinRM + RDP, and (if present) installs VMware Tools.
  2. Host-driven configuration — a small Python orchestrator (lab_build.py) pushes and runs PowerShell inside the guest over WinRM, so the host never needs local admin or domain join.
  3. Promotion — the guest promotes itself to a forest root DC (detached as SYSTEM so it survives the dcpromo reboot), optionally adds AD CS (Enterprise Root CA), and lays down a university-style OU/group/service-account structure.
  4. Arming the blind layer — the external randomized generators run, so every build produces a different set of misconfigurations and attack paths.
  5. Hardening to "apex" — the easy/known wins (AS-REP roasting, crackable Kerberoast, weak service creds) are stripped so only a deep, chained, emergent path survives.
  6. Sealing ground truth — the builder enumerates the armed state once and writes an answer key plus a machine-readable attack graph, which are moved out-of-band so the attacker never sees them.

Why it's different

  • Non-admin host control. The host drives the guest entirely over WinRM/NTLM (lab_build.py, winrm_run.py) — no local admin on the host, no TrustedHosts gymnastics, no domain join. Files are pushed as chunked base64; long-running steps run as detached SYSTEM scheduled tasks so they survive reboots.
  • Randomized → genuinely blind. The vulnerable surface comes from two external randomized generators (BadBlood, Vulnerable-AD). Because the author of the lab is not the author of the generators and every run differs, the attack session can be truly blind.
  • Sealed ground-truth grading. After arming, the builder records the exact roastable accounts, delegations, adminCount=1 principals and dangerous ACEs into an answer key, plus a compact JSON attack graph that the included Python solvers (graph_solve.py, verify_path.py) use to confirm a foothold → Domain Admin path exists and how long it is. This makes a blind attempt objectively gradeable.
  • Snapshot round-reset. Snapshot the armed VM (e.g. vmrun snapshot) so each attack "round" can be reset to an identical starting state; the assumed-breach foothold can be re-created after any revert. (Snapshotting is a manual step, not scripted in this repo.)

Architecture

 Non-admin Windows host                         VMware guest: LAB-DC01 (Windows Server)
 ──────────────────────                         ────────────────────────────────────────
  lab_build.py / winrm_run.py  ──WinRM/NTLM──▶   PowerShell (run / push / detached SYSTEM task)
        │                                         │
        │  push + run *.ps1                        ├─ promote-dc.ps1     forest root DC (+reboot)
        │                                          ├─ add-adcs.ps1       Enterprise Root CA
        │                                          ├─ theme-ou.ps1       OUs / groups / svc accounts
        │                                          ├─ fetch-tools.ps1    pull BadBlood + Vulnerable-AD
        │                                          ├─ arm-vulns.ps1      run the randomized generators
        │                                          ├─ create-foothold.ps1 assumed-breach low-priv user
        │                                          ├─ plant-deep-path.ps1 one deliberate deep ACL chain
        │                                          ├─ harden-apex.ps1    strip easy wins
        │                                          ├─ enum-acls.ps1      emit attack-graph.json
        │                                          └─ seal-groundtruth.ps1 write answer-key.txt
        ▼
  graph_solve.py / verify_path.py   ◀── attack-graph.json (analyzed off the DC, out-of-band)

Prerequisites

  • A Windows host with VMware Workstation (Pro or Player; the orchestrator uses VMware NAT to reach the guest).
  • Python 3 on the host with pywinrm (pip install pywinrm).
  • A Windows Server installation ISO (the answer file targets Windows Server 2025 Standard — adjust the image name in autounattend/autounattend.xml for other editions).
  • Guest internet access (so fetch-tools.ps1 can pull the external generators from GitHub).
  • An isolated lab network segment. Do not attach this to any production or campus network.

Quick start

All credentials/IPs/domain values are placeholders read from environment variables. Set them to your own values before running. Never commit real secrets.

# 1) Configure (host side) — placeholders shown; change them
$env:DC_IP            = "192.168.56.10"          # guest IP on the VMware NAT segment
$env:DC_ADMIN_USER    = "Administrator"
$env:DC_ADMIN_PASSWORD= "CHANGEME-Admin-Pass"    # must match autounattend.xml
$env:LAB_DOMAIN       = "lab.local"
$env:LAB_NETBIOS      = "LAB"
$env:DC_DSRM_PASSWORD = "CHANGEME-DSRM-Pass"

# 2) Build the autounattend ISO from ./autounattend (replace __ADMIN_PASSWORD__ first) and boot the VM.
#    install-tools.ps1 runs automatically at first logon (VMware Tools, WinRM, RDP), then reboots.

# 3) Promote the DC. promote-dc.ps1 reboots the guest, so run it DETACHED as SYSTEM, then wait:
python lab_build.py detach promote-dc.ps1 PromoteDC
python lab_build.py wait-domain 1200             # poll until the forest is up

# 4) Configure + arm the forest (run synchronously, in order):
python lab_build.py run add-adcs.ps1
python lab_build.py run theme-ou.ps1
python lab_build.py run fetch-tools.ps1
python lab_build.py run arm-vulns.ps1
python lab_build.py run plant-deep-path.ps1
python lab_build.py run create-foothold.ps1
python lab_build.py run harden-apex.ps1
python lab_build.py run enum-acls.ps1
python lab_build.py run seal-groundtruth.ps1

# 5) Pull the sealed attack-graph.json off the DC (out-of-band), then analyze it:
$env:ATTACK_GRAPH = ".\attack-graph.json"
python graph_solve.py
python verify_path.py

Configuration reference (environment variables)

Variable Used by Example default
DC_IP lab_build.py, winrm_run.py 192.168.56.10
DC_ADMIN_USER lab_build.py, winrm_run.py Administrator
DC_ADMIN_PASSWORD lab_build.py, winrm_run.py, unattend CHANGEME-Admin-Pass
DC_DSRM_PASSWORD promote-dc.ps1 CHANGEME-DSRM-Pass
LAB_DOMAIN most .ps1, lab_build.py wait-domain lab.local
LAB_NETBIOS promote-dc.ps1, enum-acls.ps1 LAB
LAB_OU_ROOT theme-ou.ps1, plant-deep-path.ps1 LAB
LAB_DC_NAME seal-groundtruth.ps1, enum-acls.ps1 LAB-DC01
LAB_CA_NAME add-adcs.ps1 LAB-Root-CA
LAB_SUBNET24 promote-dc.ps1, diag.ps1 192.168.56
SVC_PASSWORD theme-ou.ps1 CHANGEME-Svc-Pass
FOOTHOLD_SAM foothold/harden/enum/solver scripts j.kareem
FOOTHOLD_PASSWORD create-foothold.ps1, harden-apex.ps1 CHANGEME-Foothold-Pass
DA_TARGET_SAM plant-deep-path.ps1 (required) (none — set per build)
ATTACK_GRAPH graph_solve.py, verify_path.py attack-graph.json

Script reference

File Purpose
lab_build.py Host→guest WinRM/NTLM orchestrator: run, push (chunked base64), detach (SYSTEM task), wait-domain, wait-file.
winrm_run.py Minimal one-shot "run this PowerShell in the guest" helper (inline / file / stdin).
autounattend/autounattend.xml Unattended Windows Server install: disk layout, autologon, RDP, first-logon bootstrap.
autounattend/install-tools.ps1 Guest first-logon bootstrap: install VMware Tools, enable WinRM + RDP, mark completion, reboot.
promote-dc.ps1 Static-IP the NIC, install AD DS + DNS, promote a new forest root DC (auto-reboot). Run detached as SYSTEM.
add-adcs.ps1 Install AD CS Enterprise Root CA + Web Enrollment (EAP-TLS surface + ADCS ESC surface).
theme-ou.ps1 Create the university-style OU tree, role/WiFi security groups, and seed service accounts.
fetch-tools.ps1 Download BadBlood and Vulnerable-AD into the guest (not bundled here).
arm-vulns.ps1 Run the randomized generators (BadBlood bulk objects + Invoke-VulnAD).
create-foothold.ps1 Create the assumed-breach low-priv "student" account (the given entry point).
plant-deep-path.ps1 Plant one deliberate deep, solvable GenericAll ACL chain hidden in the BadBlood noise.
harden-apex.ps1 Strip easy wins (AS-REP, Kerberoast, weak svc creds); leave only the deep emergent + ADCS ESC paths.
enum-acls.ps1 Enumerate dangerous ACEs + memberships as DA → compact attack-graph.json.
seal-groundtruth.ps1 Write the armed-state answer key (roastable, delegation, adminCount, dangerous ACEs).
graph_solve.py Off-box analysis: which principals reach Domain Admin via the ACL graph, and how deep.
verify_path.py Off-box: confirm and print the foothold→DA path from the graph.
diag.ps1 Guest sanity diagnostics (identity, network profile, internet, ADDS state).

Credits (third-party generators)

This harness does not bundle the vulnerability generators — it fetches them at build time. All credit for the randomized vulnerable-AD content goes to their authors:

Please review and comply with the licenses of those projects when you use them.


Security / ethics note

This project builds a synthetic, isolated, throwaway Active Directory lab for authorized security training and self-study only. It is intentionally vulnerable and must never be exposed to production networks, real user data, or any system you are not explicitly authorized to test. All names, domains, and accounts produced are fictional. Keep the lab on an isolated segment, and treat the sealed answer keys as out-of-band material (they are git-ignored and should never be published).


License

MIT — see LICENSE.

About

Build an unattended, randomized, gradeable vulnerable Active Directory lab in VMware from a non-admin Windows host over WinRM — armed with BadBlood + Vulnerable-AD and sealed with a ground-truth answer key for blind red-team training.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors