Skip to main content

stomach

Challenge

Imported from local notes.md.

Solution

Original Notes

stomach

Challenge Summary

  • Given: A remote endpoint, https://stomachbug.umbccd.net, that continuously streams data.
  • Goal: Recover the meaningful payload hidden inside the spewed network output and extract the flag.
  • Constraints: The response is an effectively endless octet-stream, so collection had to be bounded and parsed incrementally.

Initial Recon / Triage

  • Observations:
    • The service responds with application/octet-stream and suggests a filename of spew.txt.
    • The body alternates between junk printable characters and lines of the form |NNN|<hex>.
    • Chunk 000 starts with 89504e470d0a1a0a, which is the PNG signature.
    • The indexed hex lines continue until a chunk containing the PNG end marker 49454e44ae426082.
  • File identification:
    • artifacts/chunks.txt - extracted indexed hex chunk lines from the stream.
    • artifacts/spew.png - first reconstructed PNG from the stream.
    • artifacts/qr_payload.bin - raw binary payload from the first QR decode.
    • artifacts/nested.png - PNG recovered from the first QR payload.
    • artifacts/nested_qr_payload.bin - base64 text recovered from the second QR.
  • Entry points:
    • The HTTP stream at https://stomachbug.umbccd.net.
    • The indexed |NNN|hex lines embedded in that stream.

Hypotheses & Approach

  • Hypothesis 1: The endless stream contains a complete file encoded as sequential hex chunks.
  • Hypothesis 2: The reconstructed image would contain another steganographic or barcode-style layer rather than the flag directly.

Execution Steps (Reproducible)

Stage 1

Commands:

cd /root/dawg2026CTF/stomach
curl -sS --http1.1 https://stomachbug.umbccd.net/ \
| awk '/^\|[0-9][0-9][0-9]\|/ { print; if ($0 ~ /49454e44ae426082/) exit }' \
> artifacts/chunks.txt

python3 - <<'PY'
from pathlib import Path
import re, binascii

pat = re.compile(r'^\|([0-9]{3})\|([0-9a-f]+)$')
hex_parts = []
for line in Path('artifacts/chunks.txt').read_text().splitlines():
m = pat.match(line)
if m:
hex_parts.append(m.group(2))

Path('artifacts/spew.png').write_bytes(binascii.unhexlify(''.join(hex_parts)))
PY

file artifacts/spew.png

Results:

  • Captured 162 indexed hex chunks, from 000 through 161.
  • Concatenating and decoding the hex produced a valid 625x625 grayscale PNG.
  • That image was a QR code.

Stage 2

Commands:

cd /root/dawg2026CTF/stomach
zbarimg --raw artifacts/spew.png > artifacts/qr_payload.bin

python3 - <<'PY'
from pathlib import Path

utf = Path('artifacts/qr_payload.bin').read_bytes()
raw = utf.decode('utf-8').encode('latin-1')
Path('artifacts/nested.png').write_bytes(raw)
PY

zbarimg artifacts/nested.png
printf 'RGF3Z0NURnsxX0JMNE0zX1RIMFMzX0g0Wk00VF9UUjVDSzNSNX0=' | base64 -d

Results:

  • The first QR contained binary data that had been UTF-8-expanded by the decoder.
  • Converting that payload from UTF-8 text back to original byte values produced another valid PNG (205x205).
  • The second PNG was another QR code containing base64 text.
  • Base64-decoding that text yielded the final flag: DawgCTF{1_BL4M3_TH0S3_H4ZM4T_TR5CK3R5}.

Artifacts Produced

  • artifacts/chunks.txt - captured hex chunk stream.
  • artifacts/spew.png - first QR image reconstructed from the network spew.
  • artifacts/qr_payload.bin - raw bytes from the first QR decode.
  • artifacts/nested.png - PNG recovered from the first QR payload.
  • artifacts/nested_qr_payload.bin - second QR payload, containing base64 text.

Flag

DawgCTF{1_BL4M3_TH0S3_H4ZM4T_TR5CK3R5}