CTF-writeups

My writeups for various ctf challenges

View on GitHub

🏁 NahamCon 2025

Deflation Gangster [Reverse Engineering]

The attachment had a windows lnk file (ImportantDocs.lnk) which had a hidden powershell script reading bytes from a zip file (ImportantDocs.zip) and saving it as flag.txt but there was no embedded zip files found in the attachment.

Then strings on the attachment (gangster.zip) revealed a base64 encoded text. On the decoding, it revealed the flag.

flag{af1150f07f900872e162e230d0ef8f94}

FlagsFlagsFlags [Reverse Engineering]

The binary checks a user-supplied flag by performing byte-by-byte comparisons between the input and a hidden flag.

The disassembly had lots of fake flags.

The main comparison happens at 0x4942D6, where cmp r9b, r8b is executed. This is where the byte-by-byte comparission happesns.

Using GDB set break point at the address 0x4942D6 and check the contents of the registers r9b and r8b.

r9b → user input

r8b → flag byte

then repeat the process byte by byte with the correct flag byte to get the complete flag.

gdb ./flagsflagsflags
break *0x4942D6
run
info registers r9 r8

flag{20dec9363618a397e9b2a0bf5a35b2e3}

Puzzle Pieces [Forensics]

The challenge provided an attachment containing multiple .exe files. Executing each individually caused a command prompt to flash and close immediately, revealing no visible output.

To capture the output, each .exe was executed with output redirection using:

program.exe >> output.txt

Each executable, when run this way, output four characters to the file.

Upon analyzing the executables’ last modified timestamps, it was observed that the .exe files were meant to be executed in chronological order. Running the programs in order based on last modified time resulted in the correct sequence of character outputs.

Concatenating the outputs in this order revealed the complete flag.

flag{512faff5e7d89c9b8bd4b9517af9bfaa}

The Martian [Misc]

Running binwalk on the given file revealed 4 embedded files within it

Extracted files had an image revealing the flag

flag{0db031ac265b3e6538aff0d9f456004f}

Method In The Madness [Web]

The challenge featured a web page with 6 checkboxes, each initially unchecked. By experimenting with different HTTP request methods, it became clear that each checkbox responded to a specific HTTP method. The objective was to “check” all boxes by sending the HTTP method for each one.

Each checkbox responded only to a specific HTTP method: GET , POST , PUT , DELETE , PATCH , OPTIONS

flag{bd399cb9c3a8b857588d8e13f490b6fd}

Infinite Queue [Web]

This challenge simulated a ticket queue system. Upon submitting an email, the server responded with: An estimated wait time , A JWT token This JWT was used to check queue status, and it included fields like: email , queue_time (in epoch timestamp) , exp (token expiration)

Inspecting the token revealed that:

Exploitation

Final Step

flag{b1bd4795215a7b81699487cc7e32d936}

NoSequel [Web]

This challenge presented a search interface for querying a database with two collections:

While the Movies collection did not support complex queries, the Flags collection accepted MongoDB-style queries, including $regex. The interface hinted that regex queries like:

title: { "$regex": "The" }

Exploitation

flag{4cb8649d9ecb0ec59d1784263602e686}

Quartet [Forensics]

The challenge provided four binary files:

Approach :

  1. Concatenated all the parts in the correct order to reconstruct the ZIP.
  2. Extract the zip: Despite warnings about multi-part archive structure, the extraction succeeded and produced a file named quartet.jpeg.
  3. Searched for the flag inside the extracted JPEG using strings

flag{8f667b09d0e821f4e14d59a8037eb376}

Screenshot [Forensizs]

The challenge provided a screenshot of a hex dump of a ZIP file (flag.zip).

Approach

  1. Performed OCR (Optical Character Recognition) on the screenshot to extract the hex values of the ZIP file from the Screenshot.png.
  2. Script to reconstruct the zip from hex dump:
# Raw hex data broken into groups (space-separated)
hex_dump = """
504b 0304 3300 0100 6300 2f02 b55a 0000
0000 4300 0000 2700 0000 0800 0b00 666c
6167 2e74 7874 0199 0700 0200 4145 0300
003d 42ff d1b3 5f95 0314 24f6 8b65 c3f5
7669 f14e 8df0 003f e240 b3ac 3364 859e
4c2d bc3c 36f2 d4ac c403 7613 85af e4e3
f90f bd29 d91b 614b a2c6 efde 11b7 1bcc
907a 72ed 504b 0102 3f03 3300 0100 6300
2f02 b55a 0000 0000 4300 0000 2700 0000
0800 2f00 0000 0000 0000 2080 b481 0000
0000 666c 6167 2e74 7874 0a00 2000 0000
0000 0100 1800 8213 8543 07ca db01 0000
0000 0000 0000 0000 0000 0000 0000 0199
0700 0200 4145 0300 0050 4b05 0600 0000
0001 0001 0065 0000 0074 0000 0000 00
"""

# Clean and convert to binary
hex_cleaned = hex_dump.replace("\n", "").replace(" ", "")
zip_bytes_from_blocks = bytes.fromhex(hex_cleaned)

# Save to file
block_output_path = "flag.zip"
with open(block_output_path, "wb") as f:
    f.write(zip_bytes_from_blocks)

block_output_path, len(zip_bytes_from_blocks)
  1. Extracting the flag.zip with given password gives the flag.txt revealing the flag.
flag{907e5bb257cd5fc818e88a13622f3d46}

The Oddeyssey [pwn]

This challenge simulated reading The Odyssey, split into 24 books with paragraphs displayed one at a time.

Challenge Behavior

Exploitation Automated script using pwntools :

from pwn import *

# Set up pwntools for remote connection
host = "challenge.nahamcon.com"
port = 31491

# Start connection
conn = remote(host, port)

# Read continuously until we get the flag
while True:
  line = conn.recvline(timeout=10)
  if not line:
      break

  decoded = line.decode(errors='ignore').strip()
  print(decoded)

  # Automatically continue when prompted
  if decoded.lower().startswith("press enter"):
      conn.sendline()

  # Stop if the flag is found
  if "flag{" in decoded:
      print(f"\nFlag found: {decoded}")
      break

# Clean exit
conn.close()

flag{0b51aae6b09b85d1bb13b0b8c3003a6a}