Bundle 99
Bundle 99
Platform: Broncoctf2026 | Category: Steganography | Type: Challenge | Difficulty: Easy | OS: NA | Author: D3v0o0Nu11 | Date: 2026-07-11 | Status: Solved Techniques: file_type_identification, kis_text_brush_extraction, png_text_chunk_metadata, zip_extraction
Summary
Task: unknown extensionless file that is a Krita .bundle (ZIP) of brush presets. Solution: identify via file/MIME, unzip, then read the Brush 99.kpp PNG metadata with exiftool to extract the kis_text_brush text= attribute containing the flag.
Recon
Port scan
nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
| Port | Service | Version | Notes |
|---|---|---|---|
| <PORT> | <SVC> | <VER> | <notes> |
Enumeration highlights
- Event:
broncoctf2026| ID:20260711_broncoctf2026_bundle_99 - Tags: zip, exiftool, png_metadata, krita, resourcebundle, kpp, brush_preset, file_identification
- Indicators: extensionless file identified as Zip data (MIME application/x-krita-resourcebundle), internal entries paintoppresets/*.kpp, preview.png, META-INF/manifest.xml, .kpp is a PNG carrying serialized preset XML in a Preset text chunk
- Source:
20260711_broncoctf2026_bundle_99.md
Foothold
Vulnerability / Misconfiguration
- File_type_identification
- Kis_text_brush_extraction
- Png_text_chunk_metadata
- Zip_extraction
<command>
Exploitation
- See original writeup content for detailed exploitation.
Privilege Escalation
Enumeration
sudo -l find / -perm -4000 2>/dev/null getcap -r / 2>/dev/null cat /etc/crontab ps aux
Exploitation
- N/A for challenge-type writeup; see exploitation above.
- Flag obtained via challenge solve.
<command>
Flags
| Flag | Location | Value |
|---|---|---|
| flag | REDACTED |
Key Takeaways / Lessons
- file_type_identification
- kis_text_brush_extraction
- png_text_chunk_metadata
- zip_extraction
- Tags: zip, exiftool, png_metadata, krita, resourcebundle, kpp, brush_preset, file_identification
Original Writeup
<details><summary>Click to expand original content</summary>Description
Yoshie found this random file laying around. Do you have any idea what this 'bundle' is? Apparently someone told him it's the 99th bundle of brushes? What is that supposed to mean... P.S. This challenge can be solved without downloading any software, but you'll have to hunt for a way to run the related program online and send the bundle to it.
English summary: An extensionless file Bundle_99 (83110 bytes) is provided. The wordplay ("bundle", "brushes", "99th bundle", "run the related program online") points to Krita and its .bundle resource bundle format. The goal is to recover a bronco{...} flag. The intended path was to load the bundle in Krita (or a web build of Krita) and paint with a text brush to stamp the flag — but the flag is stored as plaintext in the brush preset's PNG metadata, so no software is required.
Analysis
Recon on the unknown file:
$ file Bundle_99
Bundle_99: Zip data (MIME type "application/x-krita-resourcebundle"?)
$ strings Bundle_99 | grep -Ei 'mimetype|kpp|preview|manifest|meta'
mimetype
application/x-krita-resourcebundle
paintoppresets/Brush 99.kpp
preview.png
META-INF/manifest.xml
meta.xml
Key deductions:
- The
filemagic + MIMEapplication/x-krita-resourcebundleidentifies this as a Krita resource bundle — a ZIP container. Krita is the "related program" the description hints at. - The internal entry
paintoppresets/Brush 99.kppis the "99th bundle of brushes" / "Brush 99" wordplay: a single brush preset named Brush 99. - Krita
.kppbrush presets are PNG files (here 200×200 RGBA) that store the serialized preset XML inside a PNG text chunk namedPreset. Krita text brushes (kis_text_brush) store their rendered string in atext=attribute — a perfect place to hide a flag.
No pixel LSB stego is involved; preview.png is just a laughing emoji and is a decoy.
Solution
- Extract the ZIP container:
unzip Bundle_99 -d extracted
- The brush preset is a PNG with the serialized preset XML in its
Presettext chunk. Read the embedded metadata with exiftool (no need to run Krita):
exiftool "extracted/paintoppresets/Brush 99.kpp"
- Among the
<param>entries in the serialized preset, thebrush_definitionparam holds a Krita text brush. The relevant snippet:
<Brush font="Segoe UI,9,-1,5,50,0,0,0,0,0" spacing="0.2" pipe="false"
type="kis_text_brush" BrushVersion="2"
text="bronco{REDACTED}"/>
The text= attribute of the kis_text_brush is the flag — the string that would be stamped onto the canvas if you actually painted with this brush in Krita.
One-liner alternative
unzip -p Bundle_99 "paintoppresets/Brush 99.kpp" | strings | grep -o 'text="bronco{[^"]*}"'
# text="bronco{REDACTED}"
</details>
Auto-tracked: saved to WriteUps; run
/xesor-reviseto fold lessons into XESXor_Methodology.md.
signed by XESXOR