Advertisement

Main Ad

Puppy HTB Walkthrough

Welcome to another Hack the Box exercise. In this walkthrough, I have documented how I owned the Puppy machine on Hack the Box. Hack The Box is a cybersecurity platform that helps you bridge knowledge gaps and prepares you for cyber security jobs. You can also test and grow your penetration testing skills, from gathering information to reporting. If you are new to this blog, please do not forget to like, comment and subscribe to my YouTube channel and follow me on LinkedIn for more updates.

About the Machine

Puppy is an easy-difficulty Linux machine.

The first step in pwning the Puppy machine like I have always done in my previous writeups is to connect my Kali Linux terminal with Hack the Box server. To establish this connection, I ran the following command in the terminal:

sudo openvpn puppy.ovpn

Once the connection was successful, I started the target machine and I was assigned an IP address 10.10.11.70.

planning htb writeup

The next step was adding puppy.htb to my /etc/hosts by running the following command:

sudo nano /etc/hosts

After adding puppy.htb to my /etc/hosts file, I kicked things off with a version scan to see what services the target was running:

nmap puppy.htb -sV

Nmap quickly confirmed the host was alive and responding, but most of its ports were filtered — only 15 TCP ports came back as open.

Right away, a few stood out. Port 88 (Kerberos) and port 389 (LDAP) screamed Active Directory. Combined with 445 (SMB) and 5985 (WinRM), this was starting to look like a Windows Domain Controller. Nmap even revealed the hostname as DC, confirming my suspicion. The reported domain name PUPPY.HTB0. was a dead giveaway that this box was running in an AD environment.

Port 53 (DNS) was open and running Simple DNS Plus, meaning I might be able to attempt a DNS zone transfer to enumerate domain records. Kerberos on port 88 opened the door to potential AS-REP roasting or Kerberoasting attacks later on.

Another interesting find was port 2049 (NFS) — pretty rare to see alongside Windows services. If accessible, it could expose mounted directories without authentication.

On top of that, the scan showed 135 (MSRPC), 139 (NetBIOS), and 445 (SMB), all of which are prime for SMB enumeration. LDAP’s global catalog service was also available on 3268, which could allow pulling information about users, groups, and computers across the domain.

Finally, port 5985 was running Microsoft HTTPAPI 2.0, which is typically used by WinRM. If I get valid domain credentials later, this port could be my remote shell entry point.

In short, the target is almost certainly the Domain Controller for the PUPPY.HTB environment, and the mix of Kerberos, LDAP, SMB, DNS, and WinRM gives me plenty of avenues for further enumeration and potential exploitation.


Machine Information

On the Puppy machine page, there are two credentials which are likely to be a username and password (levi.james / KingofAkron2025!) I am going to be using this credentials going forward in my writeup.

puppy htb walkthrough

With the domain services mapped out from the earlier Nmap scan, I decided to probe SMB more closely. Since anonymous access didn’t yield anything useful, I tried authenticating with the credentials I had for levi.james using rpcclient - a tool that allows direct interaction with Windows RPC services over SMB:

rpcclient 10.10.11.70 -U levi.james

After entering the password, I was dropped into the rpcclient prompt. One of my first moves here was to run enumdomusers, which lists all the user accounts in the domain. The result was a tidy list of domain users, complete with their relative IDs (RIDs):

The first three accounts - Administrator, Guest, and krbtgt are standard in any Active Directory environment. The rest are real domain users, which means they’re potential targets for password spraying, Kerberos attacks, or other credential-based enumeration later on.

One account in particular caught my eye: steph.cooper_adm. The _adm suffix is often used to denote administrative accounts, and having this username could be extremely useful for privilege escalation down the line.

At this point, I had a clear list of domain usernames, giving me a solid foundation for further attacks such as AS-REP roasting, Kerberoasting, or targeted password guessing against high-value accounts.


Armed with the valid domain credentials for levi.james, I moved on to enumerating SMB shares. Since SMB often hides some juicy files in domain environments, I ran smbmap to quickly see what was available to me:

smbmap -H 10.10.11.70 -u levi.james -p 'KingofAkron2025!'

The connection was successful — I was authenticated against the host puppy.htb. The results came back with several shares, but permissions were a mixed bag:

  • ADMIN$ and C$ — Both are administrative shares that require higher privileges, so no access here.
  • DEV — This one caught my eye because of its name (DEV-SHARE for PUPPY-DEVS), but unfortunately, I didn’t have permissions to access it either.
  • IPC$ — Accessible in read-only mode. This is typically used for inter-process communication but can sometimes leak useful information.
  • NETLOGON — Read-only. This is the domain logon share, often containing logon scripts or policy files.
  • SYSVOL — Read-only. Another critical Active Directory share that stores domain-wide public files, including Group Policy objects.

Even though most shares were locked down, the read-only access to SYSVOL and NETLOGON could still be valuable — especially if they contain scripts or policy files that store credentials in plaintext. I made a mental note to come back and explore these further, as they can often lead to credential harvesting in real-world and CTF scenarios.

For now, I had confirmed that my domain credentials were working over SMB, and I knew exactly which shares were accessible for deeper enumeration.


Before moving forward with domain enumeration, I needed to make sure my system clock was in sync with the Domain Controller. Kerberos authentication is notoriously sensitive to time drift — even a few minutes off can break ticket requests. My local clock was way out of sync, so I disabled automatic NTP sync and manually set it to match the DC:

timedatectl set-ntp off sudo ntpdate 10.10.11.70

The output confirmed that my clock was stepped forward by several hours, now matching the Domain Controller’s time. This ensured that Kerberos-based tools would work without throwing authentication errors.

With time in sync, I moved on to a more comprehensive Active Directory enumeration using BloodHound. Instead of the GUI collector, I used bloodhound-python, which works well from a Linux attack box and doesn’t require a Windows agent. Running it with the -c All flag meant I was collecting all available data:

bloodhound-python -u 'levi.james' -p 'KingofAkron2025!' -d puppy.htb -ns 10.10.11.70 -c All --zip

  • -u and -p → Domain username and password
  • -d → Target domain
  • -ns → Name server to use for lookups (the DC in this case)
  • -c All → Collect all available enumeration data
  • --zip → Output a ready-to-import .zip file for the BloodHound GUI

The script authenticated to the DC, queried LDAP, and quickly mapped out the domain. The results were promising:

  • 1 domain found: puppy.htb
  • 1 computer — the Domain Controller itself
  • 10 users
  • 56 groups
  • 3 Group Policy Objects (possible sources of misconfigurations)
  • 3 Organizational Units
  • 19 containers (Active Directory objects)
  • 0 trusts — meaning this is a single-domain environment

The scan finished in 25 seconds and generated a ZIP file containing the collected data. With this in hand, I could import it into the BloodHound GUI and start visualizing attack paths — especially any routes that could take me from levi.james to a high-privilege account like steph.cooper_adm.

This step was critical — not only did I now have a full AD map, but I could also start planning my privilege escalation strategy based on real relationships and permissions in the environment.

I upload the file to Bloodhound to find the relationship and found out that user james has write permission for the group developers. While reviewing the BloodHound output, I noticed that the DEVELOPERS group had some interesting privileges over the DEV SMB share I’d seen earlier during enumeration — the same one I couldn’t access before. If I could get levi.james added to that group, I’d likely gain access to files that were previously off-limits.

For this, I turned to bloodyAD, a Python toolkit for manipulating Active Directory objects over LDAP. Since my account already had the necessary permissions to modify group memberships, I ran the following command:

bloodyAD --host '10.10.11.70' -d 'dc.puppy.htb' -u 'levi.james' -p 'KingofAkron2025!' add groupMember DEVELOPERS levi.james

Within seconds, the tool confirmed:

This meant that my user levi.james was now officially a member of the DEVELOPERS group. The plan was simple — reconnect to the SMB service, try the DEV share again, and see what new doors had just been unlocked.

After adding levi.james to the DEVELOPERS group, it was time to see if my hunch about the DEV share was correct. I connected to it using smbclient with my newly elevated group membership:

smbclient //10.10.11.70/DEV -U levi.james

This time, authentication succeeded and I was dropped into the SMB shell. A quick ls command revealed several interesting files and directories:

The KeePassXC installer caught my attention, but the real gem here was the recovery.kdbx file. KeePass databases often store sensitive credentials, and if I could crack it, I might find domain passwords or other useful secrets.

I immediately downloaded the .kdbx file to my attack box for offline analysis:

With the file in hand, the next step would be to extract its hash and attempt to crack the master password, potentially unlocking a trove of credentials for further exploitation.

With the recovery.kdbx file safely on my attack box, my first instinct was to see if it could be opened directly in KeePassXC. I launched the application and pointed it at the file:

keepassxc /home/boltech/Desktop/PuppyHTB/recovery.kdbx

The database loaded into the KeePassXC GUI without issue, but as expected, it immediately prompted me for the master password. Without that password, the database contents remained encrypted and inaccessible.

This confirmed two things:

  1. The file was intact and recognized as a valid KeePass database.

  2. I would need to crack the master password before I could extract any credentials from it.

At this point, the plan was clear — convert the .kdbx file into a hash format that could be attacked with a password-cracking tool like John the Ripper or Hashcat, and then attempt to recover the password.

With the recovery.kdbx file confirmed as a valid KeePass database, the next step was to recover its master password. Instead of manually extracting the hash and setting up John the Ripper, I opted to use keepass4brute — a dedicated KeePass password brute-forcing tool available on GitHub.

git clone https://github.com/r3nt0n/keepass4brute.git puppy htb walkthrough

git clone https://github.com/r3nt0n/keepass4brute.git

I cloned the repository from the author’s page and navigated into the project directory:

Armed with the rockyou.txt wordlist from SecLists, I launched the attack against the database:

./keepass4brute.sh /home/boltech/Desktop/PuppyHTB/recovery.kdbx /usr/share/SecLists/Passwords/Leaked-Databases/rockyou.txt

The tool began cycling through potential passwords, testing 166 attempts per minute. Barely a few dozen words into the list, it struck gold:

The master password was liverpool. With this in hand, I could now open the KeePass database in KeePassXC and extract whatever credentials it contained — potentially giving me the keys to further compromise the domain.

I attempted to open the KeePass database with the password liverpool and it was successful.

puppy hack the box walkthrough hack the box writeup puppy

hack the box writeup puppy

hack the box walkthrough puppy

With the KeePass master password liverpool in hand, I reopened the recovery.kdbx file in KeePassXC. This time, the database unlocked without resistance, revealing a neatly organized list of stored credentials.

Inside, I found multiple domain user accounts, each with their corresponding passwords:

  • Adam SilverHJKL2025!
  • Antony C. EdwardsAntman2025!
  • Jamie WilliamJamieLove2025!
  • Samuel BlakeILY2025!
  • Steve TuckerSteve2025!

This was a goldmine — not just one set of credentials, but several, potentially belonging to users with varying privilege levels in the domain. With these accounts, I could attempt Kerberos attacks, SMB enumeration, WinRM access, or even privilege escalation depending on the rights each user had.

The next step would be to test these credentials against the domain to determine which accounts could provide me with more access, and ideally, a path toward administrative control.


With multiple usernames and passwords recovered from the KeePass database, the next step was to identify which combinations were valid in the domain. To do this efficiently, I split the data into two separate files — one for usernames and one for passwords:

puppy hack the box

puppy hack the box

I then used netexec (formerly CrackMapExec) to spray all possible combinations against the SMB service on the Domain Controller:

netexec smb 10.10.11.70 -u users.txt -p passwords.txt

The tool began testing each username/password pair. Most attempts returned STATUS_LOGON_FAILURE, confirming invalid combinations. However, one stood out:

This meant that the credentials for Antony C. Edwards were valid and could successfully authenticate over SMB. With a working domain account in hand, I now had a new foothold in the environment — and the next logical move would be to enumerate what resources ant.edwards could access, potentially leading to privilege escalation.


With valid credentials for ant.edwards in hand, my next move was to map out the domain from this new user’s perspective. I launched another round of enumeration with bloodhound-python, this time authenticating as ant.edwards:

bloodhound-python -u 'ant.edwards' -p 'Antman2025!' -d puppy.htb -ns 10.10.11.70 -c All --zip

This collected every possible piece of Active Directory relationship data (-c All), queried the Domain Controller (-ns 10.10.11.70), and packaged the results in a .zip ready for import into the BloodHound GUI.

The tool successfully authenticated, retrieved a Kerberos TGT, and queried LDAP without errors. The output confirmed:

  • 1 domain (puppy.htb)
  • 1 computer — the Domain Controller (DC.PUPPY.HTB)
  • 10 user accounts
  • 56 security groups
  • 3 Group Policy Objects
  • 3 Organizational Units
  • 19 containers
  • 0 trusts — a standalone domain environment

In just under 30 seconds, the enumeration was complete and a new dataset was saved as 20250809010554_bloodhound.zip.

By importing this into BloodHound, I could visualize the AD structure from ant.edwards’s vantage point, looking for privilege escalation paths or group memberships that could get me closer to domain admin.

(bloodhound GUI image here)

With the enumeration data loaded into the BloodHound GUI, I began exploring potential attack paths starting from ant.edwards’s account. It didn’t take long to spot something interesting — BloodHound flagged that ant.edwards had FullControl rights over the user object adam.silver.

In Active Directory, FullControl is essentially the golden ticket for that object: it means I can modify any of its attributes, including the password, without needing the current one. This immediately presented a privilege escalation opportunity — by resetting Adam’s password, I could take over his account and see if he had access to more sensitive resources.

At this point, the objective was clear: exploit this control to gain Adam’s credentials and pivot further into the network.

Armed with the knowledge that ant.edwards had FullControl over adam.silver, I decided to put it to use. Using the bloodyAD tool, I connected to the domain controller and issued a password reset for Adam’s account — no need for his old credentials.

bloodyAD --host '10.10.11.70' -d 'dc.puppy.htb' -u 'ant.edwards' -p 'Antman2025!' set password ADAM.SILVER Asdf1234

With Adam’s credentials now in hand, I wanted to enumerate more details about his account to understand potential privileges or group memberships. Using ldapsearch, I queried the domain controller for adam.silver’s LDAP record:

ldapsearch -x -H ldap://10.10.11.70 -D "ANT.EDWARDS@PUPPY.HTB" -W -b "DC=puppy,DC=htb" "(sAMAccountName=ADAM.SILVER)"

While reviewing Adam’s LDAP attributes, I noticed that his userAccountControl value was set to 66050. In Active Directory, this integer is actually a bitmask — a combination of flags that control account behavior. Breaking it down, 66050 represented:

  • 0x10200 (66048) → Normal account
  • + 0x0002 (2) → Account disabled

In other words, Adam’s account existed, had a home directory, and was in interesting groups… but it was currently disabled.

ldapsearch -x -H ldap://10.10.11.70 -D "ANT.EDWARDS@PUPPY.HTB" -W -b "DC=puppy,DC=htb" "(sAMAccountName=ADAM.SILVER)" puppy htb walkthrough

To enable the account, I simply needed to remove the disabled flag. This meant changing userAccountControl from 66050 to 66048. Using ldapmodify, I replaced the attribute with the new value:

darkcorp htb walkthrough

The modification succeeded, effectively re-enabling Adam’s account and making it ready for interactive logins or remote access. With Adam’s userAccountControl modified to 66048, I wanted to make sure the change actually stuck. Using ldapsearch, I queried the DC for Adam’s account entry:

editor htb walkthrough

The output confirmed that Adam’s account was no longer disabled — the userAccountControl field now read 66048, matching the “normal account” flag. This meant I had successfully re-enabled Adam’s domain account.

Looking further down the LDAP entry, I noticed some other interesting details:

  • memberOf showed Adam was part of the DEVELOPERS group and Remote Management Users — the latter hinting at possible RDP or WinRM access.
  • homeDirectory pointed to C:\Users\adam.silver, confirming a local profile existed.
  • logonCount was non-zero, showing the account had been used before and wasn’t just a dormant placeholder.

At this stage, I had:

  1. Reset Adam’s password to something I knew.
  2. Re-enabled his account so it could be used.

The stage was now set to pivot into Adam’s account and explore what kind of privileges or network access it could offer.

With Adam’s account re-enabled and the password reset to something I controlled, it was time to see if his membership in Remote Management Users would actually pay off. I fired up Evil-WinRM and attempted a direct connection to the target:

evil-winrm -i 10.10.11.70 -u 'ADAM.SILVER' -p 'Asdf1234'

The connection went through without a hitch, dropping me into a PowerShell session on the DC as adam.silver. Navigating to the desktop directory, I quickly spotted something promising:

The listing revealed two files — a Microsoft Edge shortcut and, more importantly, a user.txt file. The -ar--- permissions confirmed it was readable, and the timestamp suggested it was the CTF’s intended user flag.

At this point, I had gone from gaining control over Adam’s account to remote shell access and was now just one step away from capturing my first flag.

With the user.txt file in sight, I used PowerShell’s cat command to reveal its contents:

The terminal responded with the string:

z

a:

z

a:

z

Post a Comment

0 Comments