← Back to list

#6th for MetaCTF August 2025

TL;DR: Placed 6th, how I prepared, how long it took me to solve everything, walkthrough of my favorite challenge.

Jonathan Garcia · 2025-08-28 23:03 · 11 claps · 2.5 min read
#ctf-walkthrough #cybersecurity #reverse-engineering #metactf #first-post
Open on Medium ↗
Wiki topics: 🔒 · Cybersecurity

#6th for MetaCTF August 2025

TL;DR: Placed 6th, how I prepared, how long it took me to solve everything, walkthrough of my favorite challenge.

6th Place in MetaCTF August 2025

6th Place in MetaCTF August 2025

This was my first MetaCTF that I took part of. Though I was going to participate in my first one two months prior to this, I ended up forgetting lol.

How did I prepare?

Leading up to this, I have been part of the US Cyber Combine where this week we’ve been doing “Speed CTFs” in all five categories and at the time of writing this, we have our last one being “Reverse Engineering.”

Speed CTF?

Speed CTFs consist of short time frames for each challenge and I would say the combine has definitely prepped me for high pressure environments like this one — quick pace, quick thinking, quick execution.

How long did I solve everything?

I solved every challenge in 48 minutes (9.6 minutes per challenge), though, that could’ve been better but I was brain farting in the web application challenge lol.

[Binary Exploitation] Spreadsheet (Walkthrough)

The spreadsheet is a fixed 10×10 grid (A–J, 1–10 -> 100 cells). A bounds check bug mistakenly allows column E(the 11th column). When you Edit K10, the code computes an index of 100 and writes one element past the 100-cell array—right into a neighboring global pointer used by the (L)oad feature (savefile). By setting K10 to flag.txt and then pressing L, the program opens our path and loads the flag into the sheet; P prints it.

The silly bug (Off-by-One on Column)

The valid columns should be A..J (0..9), but the input validation mistakenly allows A..K (0..10).

A..J columns

A..J columns

The rows are 1..10 (converted to 0..9 internally)

Index Math:

index = (row - 1) * 10 + col

A few examples for using the normal cells would be: A1 -> (0) 10 + 0 = 0 J10 -> (9) 10 + 9 = 99 (last valid cell) [Exploit] K10 -> (9) * 10 + 10 = 100 (one past the end)

How it looks in Memory:

[ cells[100] ][ savefile pointer ][ ... ]
   0 .. 99         index 100

cells[100] is our grid storage. And immediately after that array sits a global savefile pointer the program uses for **(L)**oad/**(S)**ave . When you Edit K10 and enter flag.txt, the program stores your string and (because of the OOB write) overwrites savefile to point to your string.

Turning It into File Read

After poisoning savefile via K10, hitting **L** makes the program do roughly:

fopen(savefile, "r");

Now **savefile == "flag.txt", so it tries to open `./flag.txt** in its working dir (the service runs from/srv/app`, so this succeeds.

Next, the loader reads the file contents into the sheet starting at the first cells and then **P** prints the grid—and you see the flag.

Execution

Flag: MetaCTF{c0mm4_c0mm4_c0mm4_c0mma_c0mm4_ch4m3l30n}

Final Thoughts

I found MetaCTF pretty fun — I plan on continuing to do more of these in the future when I have the time as I am taking 6 dual enrollments and 2 APs for my senior year.

Thanks for reading!


메타데이터
post_id
42a19559f28c
slug
6th-for-metactf-august-2025-42a19559f28c
url
https://medium.com/@J8NN/6th-for-metactf-august-2025-42a19559f28c
canonical_url
https://medium.com/@J8NN/6th-for-metactf-august-2025-42a19559f28c
author_url
https://medium.com/@J8NN
status
ok
fetched_at
2026-07-17 21:46:37