← Back to Writeups
CUSTOMEasyMisc

LEts a GO

XESXOR9/10/20262 min read
#misc#custom#easy#backslash_zip_extraction#broken_solver_reproduction#hidden_dotfile_discovery#ordered_fragment_concatenation#windows

LEts a GO

Platform: broncoctf2026 | Category: Misc | Type: Challenge | Difficulty: Easy | OS: Windows | Author: XESXOR | Date: 2026-07-11 | Status: Solved Techniques: backslash_zip_extraction, broken_solver_reproduction, hidden_dotfile_discovery, ordered_fragment_concatenation

Summary

Task: a zip expands to 333 tiny files in a deep noisy directory tree full of decoys; 50 hidden .part_NN fragments must be reassembled. Solution: walk the tree, collect files named .part_00..49, order them numerically and concatenate to recover the flag.

LEts a GO — broncoctf2026

Description

LEts a GO

Go step by step, brick by brick.

(provided file: lego_bricks_challenge.zip)

The title is wordplay on LEGO / "let's-a go", and "brick by brick" hints that scattered fragments must be assembled in order to build the flag.

Analysis

The archive lego_bricks_challenge.zip uses backslash path separators (Windows-style). On macOS/Linux unzip warns and does not build the directory tree correctly, so it must be extracted with a small Python zipfile loop that rewrites \ into real subdirectories.

Once extracted, the archive expands to 333 tiny files (~4.4 KB total) arranged in a deep, realistic-looking project tree: .git/, .cache/, .config/systemd/, src/modules/network/protocols/, data/raw/sensors/, tmp/system_logs/, etc. Almost everything is a decoy:

  • empty or 1–4 byte .part_NN fragments,
  • red-herring go.sum, Dockerfile, docker-compose.yml, package.json, robots.txt, README.md, .htaccess, .npmrc, .DS_Store files.

The abundance of go.sum / "GO" references and the LEGO theme is intentional misdirection.

The key discovery is a hidden file lego_bricks_challenge/src/modules/network/protocols/.solver.py (906 bytes). Its docstring reads:

Hidden solver for: LEt's a GO! — concatenate .part_00 .. .part_49

Its core logic:

python
pattern = re.compile(r"^\.part_(\d+)$")
parts = {}
for dirpath, _, filenames in os.walk(start_dir):
    for fn in filenames:
        m = pattern.match(fn)
        if m:
            idx = int(m.group(1))
            if 0 <= idx <= 49:
                with open(os.path.join(dirpath, fn)) as fh:
                    parts[idx] = fh.read()
flag = "".join(parts[i] for i in sorted(parts))

Gotcha: running the bundled .solver.py directly fails with SyntaxError: Non-UTF-8 code starting with '\x97' — the docstring contains a Windows-1252 em dash (0x97) and there is no # -*- coding -*- declaration. So the algorithm is reproduced in a clean snippet instead.

Solution

  1. Extract the backslash-path zip with Python:
python
import zipfile, os
with zipfile.ZipFile("lego_bricks_challenge.zip") as z:
    for name in z.namelist():
        real = name.replace("\\", "/")
        dst = os.path.join("extracted", real)
        if real.endswith("/"):
            os.makedirs(dst, exist_ok=True)
            continue
        os.makedirs(os.path.dirname(dst), exist_ok=True)
        with z.open(name) as src, open(dst, "wb") as out:
            out.write(src.read())
  1. Walk the tree, gather the 50 real fragments (.part_00 .. .part_49), order them numerically and concatenate:
python
from pathlib import Path
parts = {}
for p in Path('extracted/lego_bricks_challenge').rglob('.part_*'):
    try:
        i = int(p.name[6:])
    except ValueError:
        continue
    if 0 <= i <= 49:
        parts[i] = p.read_bytes()
print(b''.join(parts[i] for i in sorted(parts)))

All 50 fragments were present with no gaps. The ordered concatenation yields the flag — a play on "Everything Is Awesome" from The LEGO Movie.