← Back to list

SecLeaf 7-Day CTF Challenge

Day 1 Write-Up

APT-0 · 2026-06-11 04:32 · 5 claps · 5.0 min read
#ctf #secleaf #cybersecurity #ctf-write-ups #capture-the-flag
Open on Medium ↗
Wiki topics: 🔒 · Cybersecurity

SecLeaf 7-Day CTF Challenge

Day 1 Write-Up

Overview

On Day 1 of the SecLeaf CTF Challenge, four beginner-friendly challenges were completed on picoGym spanning web exploitation, forensics, cryptography, and general skills. Each challenge introduced a unique concept and set of tools.

Without wasting time, Let’s get to it!

Challenge 1: Bookmarklet

Category: Web Exploitation | Difficulty: Easy

Description

The challenge presented a web page containing a JavaScript bookmarklet. The bookmarklet held an encrypted flag and the decryption logic, using a XOR-style cipher with the key ‘picoctf’.

Walkthrough

The challenge gave me a URL. First thing I did was run curl on it to see what was there.

curl http://titan.picoctf.net:58468/

The HTML came back and right away I spotted a JavaScript snippet sitting in a textarea. It had an encrypted flag and the logic to decrypt it a loop that XORs each character against a key called “picoctf”. The result was supposed to pop up in an alert box.

Since I was in the terminal and not a browser, I figured I could just run it with Node.js. I swapped the alert() for console.log() and tried running it directly with node -e. That blew up with a syntax error because the outer quotes and the inner quotes in the JS were clashing.

So I saved the code to a file instead and ran it that way. Still got garbage output. Something was off with the characters.

I went deeper. Saved the full page with curl, used hexdump to look at the raw bytes of the encrypted string, and ran a Python script to inspect them.

That's when I saw it the encrypted characters were stored as UTF-8 two-byte sequences, but the JavaScript was treating them as single Latin-1 bytes. The encoding mismatch was breaking the decryption.

The fix was to read the file in binary, decode it as UTF-8, then re-encode as Latin-1 before running the cipher.

Bingo! Flag picoCTF{p@g3_turn3r_18d2fa20}

What I learned: Page source can contain everything you need. Character encoding is not something to overlook UTF-8 and Latin-1 handle the same characters very differently at the byte level.

Challenge 2: Scan Surprise

Category: Forensics | Difficulty: Easy

Description

A zip file was provided containing a PNG image. The challenge name hinted that the image needed to be ‘scanned’. The PNG turned out to be a QR code containing the flag.

Walkthrough

As seen, in the challenge there was a zip file. Downloaded the zip, unzipped it, and found a PNG file buried inside at home/ctf-player/drop-in/flag.png.

I tried to cat it just to see what was there got the usual binary garbage you get when you print an image to the terminal. The challenge name said “Scan Surprise.” That word scan combined with a PNG made me think QR code immediately, and i also might have seen the QR code in the challenge instance, so i thought of zbarimg.

Bingo! Flag picoCTF{p33k_@_b00_19eccd10}

What I learned: CTF challenge names are always a hint. Scan = QR code. zbarimg reads QR codes and barcodes straight from the terminal without needing to open anything visually.

Challenge 3: interencdec

Category: Cryptography | Difficulty: Easy

Description

A file named enc_flag contained an encoded string. The challenge involved multiple layers of encoding that had to be peeled back one by one to reveal the flag.

Walkthrough

The challenge came with a file called enc_flag. I catted it and got this:

YidkM0JxZGtwQlRYdHFhR3g2YUhsZmF6TnFlVGwzWVROclh6ZzJhMnd6TW1zeWZRPT0nCg==

That == at the end is the giveaway for Base64. Decoded it and got:

b’d3BqdkpBTXtqaGx6aHlfazNqeTl3YTNrXzg2a2wzMmsyfQ==’

Another == at the end so it’s Base64 again. But before I decoded it a second time I had to notice something. That b’…’ wrapper is Python’s way of showing a bytes object. The actual string to decode is just what’s inside the quotes, not including the b’ at the start or the ‘ at the end. That tripped me up for a second. Stripped the wrapper, decoded the Base64 again, and got a string:

wpjvJAM{jhlzhy_k3jy9wa3k_86kl32k2}

That was ROT Cipher, from there it was easy, decoding it gave the flag

picoCTF{caesar_d3cr9pt3d_86de32d2}

So the full chain was: Base64 → Base64 → Caesar cipher → flag

What I learned: Layered encodings are very common in CTF crypto. Always check if the output of one decode is still encoded. Also when Python shows b’…’, the data is the content inside the quotes only.

Challenge 4: Commitment Issues

Category: General Skills | Difficulty: Easy

Description

A zip file contained a Git repository. The file message.txt had been changed to say ‘TOP SECRET’, but the original content (the flag) was still in the Git commit history.

Walkthrough

The challenge had a resource zip file, Unzipped the file and found a Git repository with a Multiple files.

The challenge is called Commitment Issues. That’s a Git Hint. Someone committed something and then tried to hide it. Git never actually deletes history. Every change ever made to a file lives in the commit log. I ran:

Two commits showed up:

create flag remove sensitive info

I grabbed the hash from the create flag commit and ran:

Bingo! Flag picoCTF{s@n1t1z3_be3dd3da}

What I learned: Git history is permanent. If sensitive data gets committed even once, it can always be recovered. git log shows you the full history, git show <hash> lets you see exactly what a file looked like at that point in time.

Final Thoughts

Day 1 done. Four flags across web exploitation, forensics, cryptography, and general skills.

See you on to Day 2.

@SecLeaf Day 1

Written by George Matty (APT-0) | CyLab | SecLeaf 7-Day Challenge

“The best Hackers don’t just break things, they understand them.”


메타데이터
post_id
ff53795c237b
slug
secleaf-7-day-ctf-challenge-ff53795c237b
url
https://medium.com/@geomattyx23/secleaf-7-day-ctf-challenge-ff53795c237b
canonical_url
https://medium.com/@geomattyx23/secleaf-7-day-ctf-challenge-ff53795c237b
author_url
https://medium.com/@geomattyx23
status
ok
fetched_at
2026-07-28 16:41:10