Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions _authors/darvin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
short_name: darvin
name: Darvin
position: Misc, Forensics
website: https://darvin.gitbook.io
layout: author
---
Spends his time modding games and herding squirrels.
112 changes: 112 additions & 0 deletions _posts/2026-05-06-1337-2026-maple-signals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
---
layout: post
title: "[1337 Challenges 2026] Maple Signals"
author: darvin
---

Category: Forensics

A group of ppl are in a circle chatting when I enter the room, with a few others sitting at the sides working solo. I don't recognize any of the faces, so I find an empty seat by the corner and pull up the [Maple Bacon 1337 Challenges page](https://maplebacon.org/challenge/).

## Maple Bacon

It is my first CTF. I know almost nothing about cybersecurity. I scroll through the challenges and pick the OSINT one because it looks the simplest. It is just a photo in .JPG format, can't be that hard right? The goal is to find the location of where the picture was taken and the nearby classrooms. I figure the coordinates would be in the metadata, then I would pop them into Google Maps, and that would be it.

Using **Exiftool**, I find nothing useful in the metadata. So are they really expecting us to walk around and physically find it? I beg Aditya, who is right behind me, for a hint. He smirks at me and says "Start walking!". I prefer not to sneak around the campus in the evening, so that is the end of my first attempt to solve a challenge.

Pushing forward, I pick the second seem-to-be-the-simplest challenge – Forensics. It is just a .WAV file. It even comes with a nice short story in the description. Maybe this time, the metadata would prove to be helpful. 

> ## Forensics - maple signals <a href="#forensics---maple-signals" id="forensics---maple-signals"></a>
>
> **Author:** [Yana](https://maplebacon.org/authors/yana/)
>
> Hey, I am sending you my new sample. I know you have been waiting for a long time. It is not meant to be listened to like a normal track, but you’ll recognize what to do once you open it. Everything you need is already inside the sound - nothing extra. Handle it the same way we always do.
>
> Let me know when you get the message ;)
>
> **Details:**
>
> * Genre: experimental
> * Tempo: \~100 BPM
> * Key: doesn’t really matter, u will see it
>
> #### Files <a href="#files-3" id="files-3"></a>
>
> * [`maple-signals.wav`](https://maplebacon.org/assets/1337-2026/forensics/maple-signals.wav)

And I am wrong again. There don't seem to be any hints in the metadata. Not knowing what else to do, I ask Gemini for help. "Download [**Sonic Visualiser**](https://www.sonicvisualiser.org/), that's what the pros use," it answers. I am not a pro, but I will use it. Opening the .WAV file, I am greeted with a solid blue bar. Oh, I am zoomed out too far. As I zoom in, the solid bar starts to turn into a waveform. Cool, but I still have no idea what I am looking at. Playing around with the menus, it seems beside waveform, there are also different [spectrogram](https://en.wikipedia.org/wiki/Spectrogram) layers. After cycling through all of them, zooming in and out, I am still clueless about where the flag is. I guess I am not a pro after all.

<div>
<figure>
<img src="/assets/images/1337-2026/solidbar.png" alt="">
<figcaption>The solid blue bar</figcaption>
</figure>
<figure><img src="/assets/images/1337-2026/waveform.png" alt="">
<figcaption>After zooming in</figcaption>
</figure>
<figure><img src="/assets/images/1337-2026/spectro.png" alt=""><figcaption>Spectrogram</figcaption></figure>
</div>

The next suggestion Gemini gives me is [Slow Scan Television (SSTV)](https://en.wikipedia.org/wiki/Slow-scan_television). Maybe the flag is an image hidden in the spectrogram. Except when I compare the sound of our [.WAV file](https://maplebacon.org/assets/1337-2026/forensics/maple-signals.wav) to a SSTV sample on [YouTube](https://www.youtube.com/watch?v=EJbFg4sjINo), they sound nothing alike. Another dead end.

Perhaps sensing the hopelessness, Yana comes over to check on me. After seeing that I am stuck, she suggests trying another challenge. It might be easier. I tell her I want to give this one more hour. She looks at me and says "It is all about perspective," and leaves.

Then Zhou, who sits at the other corner of the room, rolls his chair over and asks "Wanna work together?" We show each other what we have gotten so far. When I show him one of the spectrograms, he says "That looks like a bar code." We try scanning it with a bar code scanner. Unfortunately, it doesn't work. It would be really cool if it does.

<figure><img src="/assets/images/1337-2026/barcode.png" alt=""><figcaption>The "Bar Code"</figcaption></figure>

Part not willing to admit defeat, part trying to impress each other, we find ourselves staring at the challenge description, then a small detail starts catching our attention: **100 BPM**.&#x20;

It seems weirdly specific to include that in a block of text that is mostly for flavor. "Does that mean 100ms?" I ask Zhou. "**10ms**," he replies. (As it turns out, we were both wrong lol. 100 BPM is 1 beat every 600ms. We were thinking 100Hz which is 1 cycle per 10ms.) Then Zhou has to go. Before he leaves, he shows me a Python library called `librosa`. He has been using it to read the .WAV file in his Python script.

Switching back to Sonic Visualiser, I continue playing with the different "perspectives". Then suddenly, I see it. In the **Waveform** layer, with the timescale sets to **10ms**, the waveform is not continuous anymore. There are distinct spikes, some upward, some downward, hidden at constant intervals, sort of like Morse code.

<figure><img src="/assets/images/1337-2026/spikes.png" alt=""><figcaption>The "perspective" showing the spikes.</figcaption></figure>

I am about to grab a pen to transcribe the code manually, but then I remember the Python library Zhou just showed me. With a bit of help from Gemini to understand the API, I now have a Python script that reads the .WAV file in 10ms chunks and prints 0 or 1 depending on the _spike_ direction. (It is not really a spike, see explanation below)

## Solve Script

A .WAV file usually has the [sampling rate](https://en.wikipedia.org/wiki/Sampling_\(signal_processing\)) of 44100Hz (samples/sec), so a chunk of 10ms would contain 441 samples. Here is an example of a chunk that would correlate to 1 in binaries. A chunk that correlates to 0 in binaries would have same values but negative.&#x20;

<table><thead><tr><th width="206">Samples</th><th>Level</th></tr></thead><tbody><tr><td>1</td><td>0.8</td></tr><tr><td>2</td><td>0.79189396</td></tr><tr><td>3</td><td>0.7677402</td></tr><tr><td>...</td><td>...</td></tr><tr><td>439</td><td>0.7280281</td></tr><tr><td>440</td><td>0.7677402</td></tr><tr><td>441</td><td>0.79189396</td></tr></tbody></table>

In our .WAV file, the peak is always at the first sample of each chunk. So when we have two chunks that correlate to alternate values, for example `10` , then last sample of the first chunk and the first sample of the second chunk would be `0.79189396` and `-0.8` . This discontinuity creates the spikes we see.

```python
import librosa
import numpy as np

y, sr = librosa.load("maple-signals.wav", sr=None)
samples_per_chunk = int(sr * 0.01) # 44100 samples/sec * 10ms = 441 samples
bits = []

for i in range(0, len(y), samples_per_chunk):
chunk = y[i : i + samples_per_chunk]
peak = chunk[np.argmax(np.abs(chunk))]
bits.append("1" if peak > 0 else "0")

bin = "".join(bits)
print(bin)
```

With the binaries fresh out of the oven, and a random [binary-to-ASCII decoder](https://www.rapidtables.com/convert/number/binary-to-ascii.html) I found on Google (I recognize it is ASCII because we were just talking about it in CPSC 121), a string that is not complete gibberish shows up.

At this point, I am still not sure exactly what a flag looks like, so I message Zhou. He explains that the flag should be in `maple{...}` format. And that's how I got my first flag.

p.s. Also thank you to Lyndon who showed me how to actually submit it to maple-chan.

## Flag

> ### **`maple{M4ple_bY__fr<3nd}`**

## Takeaway

* Submit your flags to @Maple-chan in Discord, e.g. `/submit maple{test}`.&#x20;
* The complexity of a chall's setup doesn't correlate to its difficulty. A chall with a single .JPG file could also be the most difficult one.
* Work with others, especially when you are stuck. I never found out if the 100 BPM -> 100 Hz leap of logic was intentional, or whether it was just luck. But it did help us solve the chall.

## Details
<sup>LLM used:</sup> <sup>**Gemini 3.0 Pro**</sup>
<sup>time to solve:</sup> <sup>**~3 hr**</sup>
<sup>solve date:</sup> <sup>**1/16/2026**</sup>
Binary file added assets/images/1337-2026/barcode.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/1337-2026/solidbar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/1337-2026/spectro.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/1337-2026/spikes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/1337-2026/waveform.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.