repetitions picoCTF 2023 Solution

Published: April 26, 2023

Description

A mysterious file named enc_flag hides nested encodings. Your task is to unwrap each layer until the plain-text flag appears.

Fetch enc_flag from a shell where you can chain decoding utilities.

Detect how deep the nesting goes: try CyberChef Magic, or loop base64 -d until picoCTF{ appears.

bash
wget https://artifacts.picoctf.net/c/451/enc_flag
The fastest browser-based approach is the Base64 & Base32 Decoder in Multi-layer Base64 mode, which unwraps every layer in one pass. For background on Base64 and the rest of the encoding zoo you will meet in CTFs, see the CTF encodings guide.
  1. Step 1Detect how many layers you have
    Loop base64 decoding and stop when the output contains picoCTF{. That confirms the depth without guessing.
    python
    python3 - <<'PY'
    import base64, pathlib
    data = pathlib.Path('enc_flag').read_bytes().strip()
    for i in range(1, 20):
        try:
            data = base64.b64decode(data)
        except Exception as e:
            print(f'layer {i}: decode failed ({e})')
            break
        if b'picoCTF{' in data:
            print(f'layer {i}: found flag -> {data.decode(errors="replace")}')
            break
        print(f'layer {i}: still encoded ({data[:32]!r}...)')
    PY
    Learn more

    Nested Base64 encoding means the data has been Base64-encoded several times in a row. Each layer wraps the previous output, so to recover the original you decode exactly as many times as it was encoded. For this challenge that turns out to be six.

    The loop above is more robust than counting layers by eye: it stops as soon as picoCTF{ appears and tells you how many decodes that took. If the output ever stops looking like Base64 (mixed case + digits + = padding) before the flag shows, the next layer is probably hex, gzip, or a different encoding instead.

  2. Step 2Apply six base64 decodes (the fixed-depth path)
    Once you know the depth is six, a flat shell pipeline reads enc_flag once and pipes through five more decodes.
    bash
    base64 --decode enc_flag | base64 --decode | base64 --decode | base64 --decode | base64 --decode | base64 --decode
    Learn more

    The first base64 --decode enc_flag reads the file directly (no UUOC) and emits decoded bytes. Each subsequent | base64 --decode peels another layer. After six total decodes you land on plain ASCII containing the flag.

    Want a sanity-check sentinel inside the pipeline? Append | grep -o "picoCTF{[^}]*}". If the flag has not surfaced, grep prints nothing and you know the depth was off by at least one.

  3. Step 3Alternative: CyberChef Magic
    CyberChef's Magic operation auto-detects multi-layer Base64 and decodes until the output stops looking encoded.
    Learn more

    CyberChef ships a Magic operation that fingerprints the input and tries cascades of decoders until the output stops looking encoded. For pure multi-layer Base64 it nails this challenge in one click.

    Magic's limits matter though: it does not handle hex-or-compressed layers cleanly, so if a layer mid-stack is gzipped, XOR'd with a key, or reversed, Magic gives up. In those cases drop into the recipe panel and chain operations manually.

Flag

picoCTF{base64_n3st...e523f49}

Each Base64 decode peels a layer; six iterations reveal the final picoCTF flag.

Want more picoCTF 2023 writeups?

Tools used in this challenge

Related reading

What to try next