Solving OSINT And Steganography challenges in BITSCTF 2026 Using zsteg , cyberchef , reverse image search , strings , exiftool and other stego tools
ctftime event = https://ctftime.org/event/3122/
Difficulty Of This Event = 6.5/10
1. OSINT
Euclidean Construct
Challenge Description
The challenge provides a clue about a “major event” in Copenhagen in early 2024, mentioning odd geometric constructs (“pyramids resting on 4 balls”) erected near an unguarded section of a river. The required flag format is BITSCTF{xxx.xxx.xxx}.
Solution Walkthrough
Step 1: Identifying the Event
The first step to solving this is pinpointing the “travesty” in Copenhagen in early 2024. A quick search reveals this refers to the devastating fire that destroyed the historic Børsen (Old Stock Exchange) building on April 16, 2024.
Press enter or click to view image in full size
Image: The Børsen fire incident
Step 2: Locating the Geometric Constructs
The prompt mentions “pyramids resting on 4 balls” overlooking an “unguarded section of the river.” Following the Børsen fire, heavy concrete barriers matching this exact description were placed along the Slotsholmens Kanal on the street Børsgade to secure the scaffolding.
By dropping into Google Maps Street View and setting the timeline to post-April 2024, we can scan the canal side of the street. Sure enough, right in front of a gap in the stone parapet (the unguarded boat stairs), sits the exact concrete pyramid barrier described in the challenge.
Press enter or click to view image in full size
Press enter or click to view image in full size
Press enter or click to view image in full size
Step 3: Decoding the Location
The specific three-part flag format (///xxx.xxx.xxx) is the universal signature for What3Words, a geocoding system that maps every 3x3 meter square in the world to three random dictionary words.
By taking the exact location of that specific pyramid barrier by the water and plugging it into the What3Words grid, we get our three words: tickles.cheeks.bend.
Press enter or click to view image in full size
The Flag
BITSCTF{tickles.cheeks.bend}Tools Used
- Google Maps Street View
- What3Words
2. Steganography
MArlboro
Step 1: Initial Reconnaissance & String Analysis
We began by analyzing the initial image for hidden text and base64 encoded strings.
strings -n 10 Marlboro.jpgThis revealed a base64 string which decodes to the Malbolge interpreter link: https://zb3.me/malbolge-tools/
Step 2: Payload Extraction
Used binwalk to carve out nested files hidden within the original image.
binwalk --dd='.*' Marlboro.jpgPress enter or click to view image in full size
Image 2: binwalk command execution
After extracting the nested archives, we recovered the core challenge files.
Press enter or click to view image in full size
Image 3: Extracted zip file folder containing encrypted.bin and smoke.png
Press enter or click to view image in full size
Step 3: Steganographic Key Recovery
Ran LSB analysis on the extracted smoke.png to find hidden configuration parameters.
zsteg smoke.pngExtracted XOR Key: c7027f5fdeb20dc7308ad4a6999a8a3e069cb5c8111d56904641cd344593b657
Press enter or click to view image in full size
) Image 4: zsteg smoke.png output showing the XOR key
Step 4: Cryptographic Decryption
Loaded encrypted.bin into CyberChef. Applied the XOR recipe using the hex key recovered in Step 3. The output revealed obfuscated source code written in Malbolge (the “programming language from hell”).
the output of cyberchef from puting encrypted.bin as input file and using xo with the key we just got give malbolge code.
Step 5: Esoteric Code Execution
Taking the decrypted Malbolge payload from CyberChef, we navigated to the interpreter link recovered in Step 1.
(
Press enter or click to view image in full size
) Image 6: zb3.me Malbolge interpreter link with the decrypted code pasted
Executing the code within the interpreter successfully compiled and ran the payload, outputting the plaintext flag.
Get Fr1cTioN’s stories in your inbox
Join Medium for free to get updates from this writer.
(
Press enter or click to view image in full size
) Image 7: Output of the Malbolge tool displaying the final flag
The Flag
BITSCTF{d4mn_y0ur_r34lly_w3n7_7h47_d33p}Tools Used
strings- String extractionbinwalk- File carvingzsteg- LSB steganography analysis- CyberChef — Cryptographic operations
- Malbolge Interpreter — Esoteric code execution
2b.
Queen Roselia’s Diamond — Steganography Challenge
Challenge Desc
A steganography challenge involving a 64-bit floating-point TIFF image with multiple hidden layers, including a decoy QR code and a fragmented flag hidden in visual noise.
Solution
Step 1: Initial Reconnaissance
First, I checked the metadata and ran strings on the .tif file. exiftool showed it was a 64-bit floating-point TIFF image.
exiftool challenge_stego.tifstrings challenge_stego.tifImage 2: strings command output showing garbage data
Step 2: Extracting Layers (Python)
Since standard image viewers can’t handle 64-bit floats properly, I used a Python script to extract the 8 individual byte layers from the raw data.
sl8.py:
import numpy as np
from PIL import Image
width, height = 635, 635
offset = 8
with open('challenge_stego.tif', 'rb') as f:
f.seek(offset)
raw_data = np.fromfile(f, dtype='d', count=width * height)
data_matrix = raw_data.reshape((height, width))
byte_view = data_matrix.view(np.uint8).reshape(height, width, 8)
for i in range(8):
layer = byte_view[:, :, i]
if np.max(layer) > np.min(layer):
enhanced = ((layer - np.min(layer)) / (np.max(layer) - np.min(layer)) * 255).astype(np.uint8)
else:
enhanced = layer
Image.fromarray(enhanced).save(f'layer_{i}_enhanced.png'python3 sl8.pyPress enter or click to view image in full size
Image 3: Python script terminal output
Image 4: Extracted layer folder screenshot
Step 3: The Decoy
Looking through the extracted layers, one of them contained a QR code. I enhanced it to make it scannable.
Image 5: Enhanced QR code image
Scanning this QR code resulted in a fake flag — a clever decoy!
fake flag = BITSCTF{blud_REALLY_thought}
Step 4: Finding the Real Flag
The real flag was hidden in the visual noise of layer 7. I opened layer_7_enhanced.png in GIMP and adjusted the Color Threshold to isolate the bright white text fragments from the gray QR code background.
Press enter or click to view image in full size
Image 6.1: GIMP screenshot — Color Threshold adjustment
Image 6.2: GIMP screenshot — Revealing flag part
Image 6.3: GIMP screenshot — Revealing flag part
Image 6.4: GIMP screenshot — Revealing flag part
Step 5: Reconstructing the Flag
The text was fragmented and sheared. I pieced the visible parts together and had to guess the missing bu7 part based on the leetspeak context (qr_bu7_n07_7h47_qr).
Image 7: Final flag constructed in text editor
The Flag
bitsctf{qr_bu7_n07_7h47_qr}Tools Used
exiftool- Metadata analysisstrings- String extraction- Python (NumPy, PIL) — Custom layer extraction
- GIMP — Image manipulation and color threshold analysis