miscfreeeasy

parkour encoding

pingctf

Task: Minecraft world save with diamond blocks arranged along X axis encoding binary data. Solution: extract block positions, build binary string from presence/absence, decode as ASCII shifted left by 1 bit (byte >> 1).

$ ls tags/ techniques/
anvil_parser_block_extractionpalette_block_states_decodingbinary_presence_encodingascii_left_shift_decode

$ cat /etc/rate-limit

Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.

parkour encoding — pingCTF 2026

Description

even the flag is parkour in parkour civilization

The challenge references the YouTube video "Parkour Civilization" by Oliver Age 24 — a Minecraft short film where parkour is the language. The provided file is a Minecraft 1.21.11 world save (~3.7 MB zip) containing region files with .mca anvil format.

Author: tomek7667
Flag format: ping{.*}

Analysis

Initial Recon

Unzipping the world save reveals a standard Minecraft Java Edition structure:

parkour encoding/
├── level.dat           # World metadata (NBT)
├── icon.png            # World icon
├── region/             # Overworld chunks (.mca files)
│   ├── r.-1.-1.mca
│   ├── r.-1.0.mca
│   ├── r.0.-1.mca
│   ├── r.0.0.mca
│   └── ... (20 files total)
├── DIM-1/              # Nether (empty)
├── DIM1/               # End (empty)
└── data/
    └── stopwatches.dat

The level.dat shows:

  • Version Name: 1.21.11
  • DataVersion: 4671
  • WorldGenSettings: flat world (superflat)

Block Extraction

Using the anvil-parser Python library to iterate all chunks and decode the palette-based block_states of each section:

Discovery: The world contains exactly:

  • 232 minecraft:diamond_block — all at Y=0, Z=0, with X ranging from 1 to 431
  • 1 minecraft:oak_wall_sign — at position (432, 2, 0)

The sign text reads:

congratz!
btw, did you get
the flag along
the way?

This confirms: the flag is encoded in the diamond block arrangement along the X axis.

Encoding Pattern

The diamonds form a parkour path — a single straight line where:

  • Diamond present at X → bit 1
  • Gap (no diamond) at X → bit 0

Building a binary string from X=1 to X=431 (length 431 bits):

1110000011010010110111001100111011110110110011001101100001101000...

The Core Trick: ASCII Shifted Left by 1

Initial decode as raw 8-bit ASCII produces bytes like:

  • 0xE0, 0xD2, 0xDC, 0xCE, 0xF6...

...

$ grep --similar

Similar writeups