0xnhl

Beneath the Armor

/ Update
3 min read

Beneath the Armor (Forensics) - Detailed Writeup#

Given file: iron-challenge.png

Challenge prompt:

“History repeats itself, even for ironman, life goes on cycles”

Expected flag format: apoorvctf{...}

Challenge intuition#

The prompt hints at something cyclic/repetitive:

  • “History repeats itself”
  • “life goes on cycles”

In steganography tasks, this often suggests periodic extraction patterns such as:

  • bit-plane extraction,
  • channel-wise cycles (R -> G -> B -> R …),
  • repeating masks or modular indexing.

So instead of only metadata carving, we should test pixel-bit extraction paths.

1) Fast triage#

First, verify if this is a plain image or has obvious appended data.

file "iron-challenge.png"
exiftool "iron-challenge.png"
binwalk "iron-challenge.png"
bash

Observed:

  • Valid PNG, 1920 x 1076, RGB, non-interlaced.
  • No suspicious textual metadata fields carrying a flag.
  • No additional embedded file signatures after image end.

Conclusion: likely in-pixel stego, not metadata/appended payload.

2) PNG structure sanity check#

I parsed chunk layout to see whether uncommon chunks (tEXt, zTXt, iTXt, custom chunks) exist.

Result:

  • IHDR x1
  • IDAT x50
  • IEND x1

No extra ancillary chunks with hidden text.

That reinforces the bit-level pixel hypothesis.

3) Guided hypothesis from the hint#

The phrase “goes on cycles” naturally maps to cycling through channels and/or bit positions.

A strong candidate is:

  • walk pixels in row-major order,
  • for each pixel, take bits in a repeating channel pattern,
  • pack extracted bits into bytes,
  • search for apoorvctf{ in the resulting byte stream.

Because RGB itself is a 3-step cycle, one useful pattern is using different bit-planes per channel in a periodic way.

4) Successful extraction pattern#

The pattern that yields the flag:

  • traversal: row-major (top-left to bottom-right),
  • per pixel bit picks:
    • R -> bit 0 (LSB),
    • G -> bit 1,
    • B -> bit 2,
  • pack bits with big-endian bit order into bytes.

This is effectively a modular cycle on channels/bit positions:

  • channel cycle: R, G, B
  • bit cycle: 0, 1, 2

which matches the challenge hint about cycles.

5) Reproducible solver script#

I saved the solver as solve_iron.py.

Run:

python3 solve_iron.py
bash

Output:

apoorvctf{m0dul4r_4r17hm371c_15_fun_y34h}
text

6) Why this works#

  • The hidden payload is not in metadata/chunks; it is encoded in pixel bits.
  • The challenge hint explicitly points to cyclic logic.
  • The successful decoder uses a cyclic modular mapping over channels/bit positions.
  • Reconstructing bytes with the correct bit order reveals printable ASCII flag text.

7) Final flag#

apoorvctf{m0dul4r_4r17hm371c_15_fun_y34h}

Notes for writeup reuse#

  • Keep solver deterministic; avoid manual extraction.
  • If similar tasks fail initially, brute-force combinations over:
    • traversal order (row/column),
    • channel order (RGB permutations),
    • bit indices (0..7 per channel),
    • pack bit order (big/little).
  • Search extracted byte streams for known flag prefix to quickly rank candidates.
Beneath the Armor
https://nahil.xyz/vault/writeups/apoorvctf2026/forensics/beneath-the-armor/
Author Nahil Rasheed
Published at March 24, 2026
Disclaimer This content is provided strictly for educational purposes only.