Why a lab, and why this lab

The four-part “Assessing Active Directory” series starts with a Kali host and zero credentials. This post is the one that comes before it: how the target was built in the first place. A single Domain Controller stops teaching you anything after a day, because real Active Directory breaks across trusts, delegation, certificate services, and ACL chains — relationships that only exist when more than one domain is involved. So the lab is GOAD (Game of Active Directory) by Orange Cyberdefense, which packs two forests, three domains, and five Windows servers into one network, along with more than forty deliberate misconfigurations.

Everything below is real: a laptop that is just powerful enough, a hypervisor that needed patching, and a provisioning run that took almost five hours.

The architecture

Two forests and a child domain. sevenkingdoms.local is the forest root; north.sevenkingdoms.local is its child domain; essos.local is a separate forest linked by a cross-forest trust. Three Domain Controllers carry them, two member servers hold the services, and one Linux box does the provisioning.

Windows 11 host (VMnet4 · 192.168.56.1)
└── VMware Workstation 26H1
    ├── DC01   kingslanding  192.168.56.10  (WS2019 · sevenkingdoms.local · ADCS)
    ├── DC02   winterfell    192.168.56.11  (WS2019 · north.sevenkingdoms.local)
    ├── DC03   meereen       192.168.56.12  (WS2016 · essos.local)
    ├── SRV02  castelblack   192.168.56.22  (WS2019 · IIS + MSSQL)
    ├── SRV03  braavos       192.168.56.23  (WS2016 · MSSQL · LAPS)
    └── PROVISIONING         192.168.56.3   (Ubuntu 22.04 · Ansible jumpbox)
VMNET4 · HOST-ONLY · 192.168.56.0/24 · NO GATEWAY Windows hostVMware + Vagrant Jumpbox (.3)Ansible sevenkingdoms.local forest DC01 · .10 · AD CS DC02 · .11 · NORTH SRV02 · .22 essos.local forest DC03 · .12 SRV03 · .23
The lab boundary as built: Vagrant creates the machines, the jumpbox configures them, and every target stays on an isolated host-only network.
DomainNetBIOSDCKind
sevenkingdoms.localSEVENKINGDOMSDC01 (.10)forest root
north.sevenkingdoms.localNORTHDC02 (.11)child domain
essos.localESSOSDC03 (.12)separate forest

SRV02 is a north member, SRV03 is an essos member, and the certificate authority (CertSvc) runs on DC01. Two trusts hold it together: the implicit parent/child trust between sevenkingdoms and north, and a cross-forest trust to essos.

The host: barely enough

ComponentValue
MachineThinkPad X1 Carbon
CPUIntel Core Ultra 7 268V — 8 cores / 8 threads
RAM32 GB
OSWindows 11

The honest summary is sufficient, but at the edge. Six VMs get 12 vCPUs on an 8-core machine (1.5× oversubscribed) and about 20 GB of RAM against 32 GB total. For attacking one target at a time — which is how a pentest is actually run — the idle VMs cost almost nothing. For a parallel Ansible run, the machine crawls. The full install took 4 hours 42 minutes, and the slowest step was a DC03 reboot that blew past the 600-second Ansible timeout.

VMvCPURAM
DC01 / DC02 / DC0322048 MB
SRV0224096 MB
SRV0323584 MB
PROVISIONING22000 MB

Provisioning: Vagrant, Ansible, and the jumpbox

GOAD’s supported path is Vagrant (to create the VMs) plus Ansible (to build the domains inside them). On VMware, GOAD uses a jumpbox model: Vagrant first boots an Ubuntu box (the PROVISIONING machine at .3), copies the GOAD source onto it, and then Ansible runs from the jumpbox to reach each Windows VM over WinRM and turn it into a domain.

Vagrant ──► 6 VMs (boxes: windows_2019 ×3, windows_2016 ×2, ubuntu ×1)
   │
   └─► scp GOAD source ──► jumpbox (.3)
                              │
                              └─► ansible-playbook build.yml
                                    ├── dc01 → AD + ADCS + trust
                                    ├── dc02 → child domain
                                    ├── dc03 → second forest
                                    ├── srv02 → IIS + MSSQL
                                    └── srv03 → MSSQL + LAPS

The result is a lab that provisions deterministically and can be torn down and rebuilt with one command.

The parts that had to be patched

The clean description hides the friction. VMware Workstation 26H1 moved to 64-bit, which broke Vagrant’s VMware utility in ways that each required a patch:

  • WOW6432Node registry fix — the utility looked for VMware under the 32-bit view and found nothing, so InstallPath and ProductVersion had to be created under HKLM\SOFTWARE\WOW6432Node\VMware, Inc.\VMware Workstation.
  • VMnet4 created by hand — Vagrant could not create the network itself (the vmrest API returned 400), so the host-only network was created manually in the Virtual Network Editor.
  • scp path mangling — GOAD’s copy step passed Windows backslash paths to scp, which treated them as remote hosts; it was patched to forward slashes and a tar + scp fallback for rsync.
  • fix_ip.ps1 scheduled-task — applying a static IP killed the WinRM TCP session mid-boot and locked Vagrant, so the IP change was deferred to a scheduled task that runs after the session closes.
  • Python 3.14 configparser — comment lines written with set() broke the config parser, so the writer was changed to Python comments.

These are the real content of “lab setup.” The tooling is mature, but a 64-bit hypervisor transition and a new Python version are enough to break the whole pipeline, and each failure looked like a provisioning bug rather than what it was. The patches are kept as local-patches.diff so they survive an upstream git pull.

Networking: host-only on purpose

The lab network is a host-only 192.168.56.0/24 on VMnet4 — no gateway, no internet, DHCP on only for Vagrant’s first WinRM contact. The VMs use static addresses and have no route out, which is exactly what you want for an attack lab: it cannot reach the internet, and the internet cannot reach it.

SettingValue
NetworkVMware VMnet4, host-only
Subnet192.168.56.0/24
Host IP192.168.56.1
Gatewaynone
DNS (inside lab)192.168.56.10

The attack host (Kali) reaches it over the LAN: the Windows host forwards between the physical network and VMnet4 (IPEnableRouter=1, forwarding enabled on both interfaces), and the client just needs a route for 192.168.56.0/24. The rule worth writing down from all this: keep it host-only and route in — do not bridge VMnet4 onto a corporate network.

Running the lab

cd C:\Users\pwc-cyber\GOAD
$env:PATH = 'C:\Program Files\Vagrant\bin;' + $env:PATH
$I = '6c9cb8-goad-vmware'

.\.env\Scripts\python.exe goad.py -t status   -l GOAD -p vmware -i $I
.\.env\Scripts\python.exe goad.py -t start    -l GOAD -p vmware -i $I
.\.env\Scripts\python.exe goad.py -t stop     -l GOAD -p vmware -i $I
.\.env\Scripts\python.exe goad.py -t snapshot -l GOAD -p vmware -i $I
.\.env\Scripts\python.exe goad.py -t reset    -l GOAD -p vmware -i $I

The VMs run headless — vmrun list shows them, but they never appear in the Workstation GUI, and you never close them from the GUI (it desynchronizes Vagrant). A snapshot was taken before any testing began, so a broken lab is a -t reset away.

Credentials worth knowing up front

The lab’s entry points — every domain has a known Domain Admin, and the full user/group/ACL catalog lives in one file (ad/GOAD/data/config.json) that is the single source of truth:

ScopeAccountPassword
sevenkingdoms DArobert.baratheoniamthekingoftheworld
sevenkingdoms DAcersei.lannisteril0vejaime
north DAeddard.starkFightP3aceAndHonor!
essos DAdaenerys.targaryenBurnThemAll!
MSSQL SA (SRV02)saSup1_sa_P@ssw0rd!
MSSQL SA (SRV03)sasa_P@ssw0rd!Ess0s

What this buys

Once it is up, the attack surface is the whole point: Kerberoasting and AS-REP roasting, constrained and unconstrained delegation, eight-hop ACL chains, AD CS ESC1–ESC15, MSSQL linked servers, LAPS, and more — which is exactly what the series that follows walks through, one technique at a time, with the detection and the fix beside each one. That series starts with GOAD Part 1: From Zero Credentials to the Attack Graph.

Evidence and limits

This write-up records one completed GOAD deployment on a ThinkPad X1 Carbon: the six-machine inventory, the VMnet4 topology, the 4 h 42 min provisioning run, the exact failure points, and the commands used to start, stop, snapshot, and reset the instance. The account names and passwords shown above are GOAD’s intentionally vulnerable fixtures, not credentials from another environment.

The result is not a benchmark for every VMware or GOAD release. The registry, scp, static-IP, and Python patches describe this Windows 11 / VMware Workstation 26H1 / Python 3.14 combination. A different provider or version may fail elsewhere. The lab remained host-only with no gateway; nothing here was run against a production or third-party network.

References

Sources & freshness

How current is this note?

Sources checkedNovember 2, 2026

The latest source-review, content-update, or publication date is shown.

ReviewPublic sources reviewed

Primary public records were checked. Environment-specific behavior remains outside the claim unless separately reproduced.