PurpleForest: An Active Directory Lab That Fights Back
Most AD labs teach one half of the job. PurpleForest builds both: a Windows domain to attack, full telemetry through Vector, and Graylog to catch you. Run the attack, read the logs, write the rule, watch it fire, then evade it.
active-directory purple-team homelab detection-engineering siem graylog vector sigma
Most Active Directory labs teach you one half of the job.
Offensive labs hand you a deliberately broken domain and a list of attacks. You run Rubeus, you get a hash, you move on, and you learn nothing about what the defender saw. Detection labs go the other way: a SIEM full of sample data, and rules you never watched fire against a real attack.
The gap between them is where the actual work lives. A detection engineer who has never run the attack writes brittle rules. A red teamer who has never read the telemetry doesn't know which of their choices were loud.
So I built PurpleForest: one lab that does both, fully automated, and free to run on your own hardware. This post introduces it. Part 1 is the full build guide, and the posts after that are the exercises.
#What you get
Four virtual machines on an isolated network, built with Vagrant and configured with Ansible:
| VM | What it is | Role |
|---|---|---|
DC01 |
Windows Server 2022 | Domain controller for the corp.lab forest |
WS01 |
Windows 10 22H2 (11 optional) | A domain-joined workstation: your foothold |
SIEM01 |
Ubuntu 24.04 | Graylog, OpenSearch and MongoDB |
KALI |
Kali rolling | The attacker, and the Ansible control node |
Both Windows hosts ship their logs (the Security event log, Sysmon, and PowerShell script blocks) through Vector to Graylog. Detections are written in Sigma, so they stay useful if you run Splunk or Elastic instead.
#The loop
Every exercise follows the same seven steps:
- Scenario: what the attacker wants, and where they sit in the kill chain.
- Attack: the exact tooling and commands, reproducible.
- Telemetry: which log source, which event IDs, and the raw event.
- Detection: the Sigma rule and the Graylog query, and why it works.
- Alert: the alert firing, with tuning notes and expected false positives.
- Evasion: how a real attacker dodges it, and what that costs them.
- Cleanup: roll back to the snapshot.
Step 6 is the one most write-ups skip, and it's the one that makes the rest worth reading. A rule you haven't tried to beat is a rule you don't understand yet.
#Four design decisions
#1. The attack paths are off until you want them
Most vulnerable-AD labs are broken in a dozen ways at once. That's realistic, but it's terrible for learning: when an attack works, you can't tell which flaw it used, and when a detection fires, you can't tell which attack tripped it.
PurpleForest separates the noise from the flaws. BadBlood fills the domain with thousands of users, groups and messy ACLs, so BloodHound output and event volumes look like a real network. But the deliberate attack paths all ship switched off. Each exercise turns on only the flaw it needs, with one Ansible flag:
ansible-playbook site.yml -e misconfig_kerberoast=true| Flag | Exercise |
|---|---|
misconfig_kerberoast |
Kerberoasting |
misconfig_asreproast |
AS-REP roasting |
misconfig_weak_spray_target |
Password spraying |
misconfig_password_in_desc |
Credentials in AD attributes |
misconfig_acl_genericall |
ACL abuse |
misconfig_unconstrained_deleg |
Delegation abuse |
misconfig_smb_signing_off |
NTLM relay |
#2. Audit policy is automated, not left to a README
Out of the box, Windows doesn't log most of what Active Directory detections need. That is the single biggest reason home-lab detections silently never fire: the rule is fine, and the event it's looking for was never written.
So the audit policy is part of the build. By the time the playbook finishes, the events the exercises depend on are already being recorded.
#3. Vector, not agent sprawl
Plenty of labs install one agent for Windows events, another for Sysmon, and a third for anything else. PurpleForest uses one collector with one config language, fanning out to wherever you point it. It's the same pattern real security data pipelines are moving towards.
Vector also buffers to disk (512 MB here), so the SIEM can go down mid-attack without losing events. That is worth demonstrating to yourself once.
#4. Reproducible, and isolated on purpose
Snapshots are built into the tooling (.\lab.ps1 snapshot and .\lab.ps1 restore), so every exercise starts from the same baseline. If a snapshot ever goes wrong, the whole lab rebuilds from code.
The lab lives on its own host-only network, 10.10.10.0/24. Each VM also has a NAT adapter, because the build downloads a lot, but nothing is ever bridged to your real network. Keep it that way, and point poisoning tools like Responder and ntlmrelayx at the lab interface only. On a real network they make for a genuinely bad afternoon.
#What you need
| Host | Windows 10/11 |
| Host RAM | 32 GB recommended |
| Disk | About 150 GB free |
| Hypervisor | VMware Workstation Pro (free for personal use) |
| Vagrant | 2.4+ with the vagrant-vmware-desktop plugin and the VMware Utility |
With everything running, the lab uses about 20 GB of RAM, or about 16 GB if you bring your own Kali. On a smaller host, drop WS01 and attack the domain controller directly. You lose the lateral-movement scenarios but keep most of the AD content.
No operating system images ship with the repo. Vagrant pulls public boxes at build time, and the Windows ones are Microsoft evaluation builds (180 days for Server, 90 for the client).
#Building it
The one thing people trip over is that the build happens on two machines. Vagrant runs on the Windows host, because a guest VM can't create sibling VMs in its own hypervisor. Ansible runs from Kali, because Ansible has no supported Windows control node and Kali is already on the lab network.
In short:
- On the Windows host,
.\lab.ps1 setupinstalls Vagrant and its VMware plugin and asks where to put the lab, then.\lab.ps1 upbuilds the VMs. - Inside Kali,
scripts/bootstrap-kali.shsets up the control node, thenansible-playbook site.ymlbuilds the domain, the SIEM and the telemetry. - Back on the host,
.\lab.ps1 snapshotsaves the baseline before you attack anything.
The full walkthrough, with screenshots and every fix I needed along the way, is in Part 1: Building an AD Purple-Team Lab from Zero.
The passwords are deliberately weak, because several exercises depend on weak credentials existing. Never expose this lab to a network you value.
#The roadmap
The series covers Active Directory first, then living-off-the-land techniques, Linux, cloud and Kubernetes.
#Contributing
Exercise contributions are welcome. The one rule: an exercise isn't finished until the detection fires and you've written down how to evade it. The details are in the repo's CONTRIBUTING.md.
The code is MIT licensed. It stands on the shoulders of GOAD, BadBlood and sysmon-modular.
Grab it from GitHub, follow Part 1 to build it, and take the snapshot. The exercises are being planned now, and the first one is coming soon.