SEEN CTF 2025—Writeup

Welcome back to another writeup! 🚩 This time, I’ll be walking you through a detailed, step-by-step breakdown of how we tackled and solved the challenges from SEEN CTF 2025. In this writeup, I’ll not only share the exact methods and techniques we used, but also provide insights, thought processes, and alternative approaches that might help you in future competitions. Whether you’re a beginner looking to learn or a seasoned player comparing strategies, I hope this guide gives you both knowledge and inspiration for your own CTF journey!

AUDITION

Challenge Name #1: first_task

In the challenge description, the term leash_protocol is emphasized, and within the provided game materials, there’s also a file with the same name. Opening this file in a text editor like Notepad shows that it’s technically readable, but the content appears messy and difficult to interpret. A practical approach here is to adjust or correct the file’s encoding to make the text more understandable.

Here's a Python script to automate this.

import chardet

input_file = "leash_protocol"

# Detect encoding
with open(input_file, "rb") as f:
    raw = f.read()
    enc = chardet.detect(raw)["encoding"]

# Read and print
with open(input_file, "r", encoding=enc, errors="ignore") as f:
    text = f.read()

print(text)

Run the script and use grep for filtering.

python3 utf-8_encoder.py | grep "SEEN"

And here's the result

Challenge Name #2: corp_portal

In the challenge description, we’re provided with a link to a login page. At first glance, it looks like a standard login form, but let’s take a closer look by inspecting it to understand what’s happening behind the scenes.

While examining the source code, we notice that the credentials are hardcoded, and the password is written in a flag-like format. However, the expected flag format should be SEEN{}. To make sense of this, let’s attempt to decode it using common ciphers, such as the Caesar cipher.

Challenge Name #3: unsecured

The challenge description indicates that our goal is to obtain some form of Clearance.

Looking at the source code, we can see that after a successful login, the page redirects to dashboard.html. Interestingly, we can bypass the login entirely and access dashboard.html directly by simply modifying the URL.

This is the dashboard.html, now let's take a look at the source code of this.

At the end, you’ll notice that the dashboard links to another HTML page called file.html. Let’s take a closer look at it.

This is file.html, and as mentioned earlier, we need to find some kind of clearance. Here, we can see a file that matches the description—the Clearance Documentation. Let’s take a closer look.

You can use Ctrl + F for this but the flag is already obvious hehe.

Challenge Name #4: company_memo

The challenge states that we need to locate a file named quarterlybudgets.pdf and inspect it. This one is straightforward—if we examine the list on file.html, we can see Quarterly Budgets 2025. Let’s go ahead and check it.

There's nothing useful at the contents of this PDF File, now let's check the metadata.

Here's the result

Challenge Name #5: logging

The challenge description mentions that there’s a log file in the same directory, but it’s not listed on files.html. So how can we locate it? One way is to enumerate the directory using Gobuster to find all files with the .log extension.

gobuster dir -u https://zdvlg8fx0mugwaof.apollodon.tech -w wordlist.txt -t 50 -x log -k

Here's the result

There it is, now let's check the access.log .

Challenge Name #6: the_name

For this challenge, we’re provided with a link to a login page, which is indicated to be vulnerable to SQL injection (SQLi). Let’s take a closer look.

This is the login page, now let's do the classic 1=1 payload.

' OR '1'='1

And it works!!!! We're in!

Just do the same payload again xD..

Challenge Name #7: getaway

In this challenge, the corporate logo is referenced, and we can find it listed on file.html. Let’s go ahead and take a closer look.

And in the file.html, the title of this has this word inside a parenthesis "(High-Res)" So I wonder, what if we increase the resolution of this image.. We use Aperi'solve for this, and this is the result.

AXIOM CORP

Challenge Name #8: thorne's website

In this challenge, we are presented with a webpage that requires a password. It’s specified that the verification happens entirely on the client side, which means tools like BurpSuite or ZAP won’t be effective. The flag is embedded in the frontend itself. Let’s take a closer look.

This is the webpage, now let's check the source code.

As you can see, this project is using Next.js. Let’s take a closer look at it.

I noticed a Base64 encoded string here, now let's decode it. (VGgwcm4zX1MzY3VyM19QQHN3)

Now let's enter this as a password.

It works, but something is blocking us to get the flag, so let's check the source code again.

try {
    let s = await fetch("/api/".concat(btoa("notes")), {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ password: e })
    });

This line of JavaScript is making a POST request to an API endpoint. It first encodes the string "notes" in Base64 using btoa() and appends it to "/api/". Then it sends a JSON payload containing a password field with the value e.

Now let's navigate to /api/notes using curl.

curl -X POST https://huilaumycqq3yrno154j36g65cf2fwm0.apollodon.tech/api/notes -H "Content-Type: application/json" -d '{"password": "Th0rn3_S3cur3_P@sw"}' | grep "SEEN"

Challenge Name #9: network_sniff

We were provided with a pcap file named traffic.pcap. Before opening it in Wireshark, I ran strings combined with grep on the file, hoping to filter out and reveal the flag directly.

strings traffic.pcap | grep "SEEN"

Challenge Name #10: the_truth

In this challenge, we’re given a zip file, and it’s noted that the password (or ciphertext) is encrypted using a Vigenère cipher.

vfffrqbumef

In the challenge number 8, the key is mentioned as cybernaut so I decode and the plaintext is thebadbatch , but the problem is when I enter the bad batch, the plaintext is not the correct password.... So I entered the ciphertext instead as the password and it works. Weird.

Challenge Name #11: daemon

In this challenge, we’re given an executable file. Most people would immediately open it in Ghidra or try running the program. But in CTFs, it’s important not to overthink—challenges are often simpler than they seem. In this case, you can use the same strings and grep approach we applied to the pcap file earlier. Yes, it’s really that simple.

THE STELLAR SOVEREIGNTY

Challenge Name #12: loyalist

In this challenge, we’re again provided with a .pcap file, and as usual, using strings combined with grep proves to be the most effective approach.

Challenge Name #13: gateway

In this challenge, we are given a link for a webpage but CLI style, and it was asking for username and password and I enter the credentials we've got from loyalist.

The core logic is this

function checkCookieStatus() {
  const cookies = document.cookie.split(";");
  let bypassCookie = false;

  for (let i = 0; i < cookies.length; i++) {
    const cookie = cookies[i].trim().split("=");
    if (cookie[0] === "bypass" && cookie[1] === "true") {
      bypassCookie = true;
      break;
    }
  }

We will just use a bypass payload for this.

document.cookie = "bypass=true";

Just enter that to the console and refresh the page.

Challenge Name #14: prime_bug

Here we are given a ciphertext

The main issue is that we have the values of p, q, and the private key, but we don’t yet have the decrypted number sequence. However, if we encrypt the correct decrypted sequence, it produces the same ciphertext. Looking back at the description, the word “sovereignty” catches our attention, and it turns out that the ciphertext corresponds to 11 characters — which is actually the decrypted text.

Challenge Name #15: stellar_redemption

The description mentioned that we needed to find some kind of kill switch or key. After carefully analyzing every detail, the URL “S33N2025” stood out. When we submitted this as the final flag, it worked perfectly!

Final Flag: SEEN{S33N2025}

I am proud to share that our efforts paid off — we secured Top 1 and emerged as the champions of SEEN CTF 2025. This achievement would not have been possible without the exceptional dedication, skill, and support of my fellow members: Brylle (ka1ro), Alisha (isha), Arvin (y3y), Matt (emoa), and every single player who contributed, collaborated, and challenged us along the way. Your expertise, encouragement, and energy were invaluable in making this victory possible.

This competition was not just about ranking or accolades — it was about pushing the boundaries of our knowledge, sharpening our skills, and embracing the spirit of cybersecurity and ethical hacking. To all the participants, thank you for making SEEN CTF 2025 a truly unforgettable experience. Every challenge solved and every obstacle overcome has left a lasting impression, and I am inspired to continue striving for excellence in future competitions.

Last updated