Ready Gladiator 1 picoCTF 2023 Solution

Published: April 26, 2023

Description

Now you must occasionally beat the Imp. Modify the warrior to something more aggressive, such as the documented "Imp Ex" example.

Replace the original Imp with a more capable warrior (Imp Ex is the canonical example).

Submit the modified file via nc saturn.picoctf.net 63042 and win at least one round.

bash
cat <<'RED' > imp.red
;redcode-94
;name Imp Ex
add #4, 3
mov 2, @2
jmp -2
dat #0, #0
end
RED
bash
nc saturn.picoctf.net 63042 < imp.red

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
Same plumbing as Gladiator 0 (a warrior file piped into nc); the netcat for CTF guide covers the request/response shape if you have not seen it.
  1. Step 1
    Adopt a published warrior
    Observation
    I noticed the challenge description explicitly called out the documented 'Imp Ex' example and that the original Imp (a simple MOV loop) never writes DAT kill instructions, which suggested replacing it entirely with a published bomber-class warrior rather than trying to patch the Imp.
    Imp Ex from the Core War docs beats a stock Imp close to 100 percent of the time. One copy is enough for at least one round win.
    What didn't work first

    Tried: Trying to modify the original Imp by making it move faster or duplicate itself.

    Tweaking the Imp's single MOV instruction (changing the stride or adding copies) rarely turns it into a winner because the Imp's inherent weakness is that it never writes DAT kill instructions. No matter how many copies run, they can't kill the opponent. The correct approach is to switch to a completely different warrior class - a bomber - that actively plants fatal DAT traps across memory.

    Tried: Writing a warrior from scratch without referencing the Core War documentation, guessing at Redcode syntax.

    Redcode has specific addressing modes and opcode rules that are easy to get wrong from intuition alone (for example, confusing immediate '#' with direct addressing, or forgetting that offsets are relative to the current instruction). A hand-crafted warrior with syntax errors will be silently rejected or fail to compile on the server. Using a documented working warrior like Imp Ex guarantees a valid baseline.

    Learn more

    Imp Ex (Imp Exterminator) is the textbook anti-Imp warrior. It is a tiny bomber that writes DAT instructions across memory faster than the Imp can run, killing the Imp's process when execution lands on a bombed cell. Empirically, Imp Ex (or any tuned 4-stride bomber against a 1-stride Imp) wins close to 100 percent of stock-Imp matches when offsets are randomised.

    The server runs ICWS-94 Redcode (the modern standard). The header line ;redcode-94 tells the parser which dialect to use; without it some servers fall back to the 1988 standard, which lacks the instruction modifiers (.ab, .i, etc.) that newer warriors rely on. Sticking with the trio of unmodified opcodes add, mov, jmp in the snippet above keeps it portable across both dialects.

    Quick addressing-mode reference for reading other warriors:

    #  immediate     -> the literal value (e.g. add #4, 3 adds 4)
       direct        -> offset from current instruction (no prefix)
    @  indirect      -> follow the B-field of the target cell, then dereference
    <  pre-decrement -> decrement target's B-field, then use it indirectly
    >  post-increment-> use indirectly, then increment target's B-field
    *  A-indirect    -> like @ but follow A-field (ICWS-94 only)
    {  A-pre-decr    -> ICWS-94
    }  A-post-incr   -> ICWS-94
    $  direct (94)   -> explicit form of no-prefix direct

    Walking through Imp Ex line by line. add #4, 3 adds the literal 4 to the B-field of instruction at offset +3 (the dat #0, #0 bomb pointer), so the bomb's target advances by 4 each iteration. mov 2, @2 copies the instruction at offset +2 (the dat bomb itself) to the address pointed to indirectly by instruction +2's B-field, dropping a death trap. jmp -2 loops back to the add. The add mutates the bomb pointer in place, so each cycle bombs a fresh cell on a stride of 4 covering the entire Imp's sweep path.

    Other warriors worth keeping in your back pocket: Dwarf is the original 4-stride bomber and is even shorter than Imp Ex; Tiger is a faster bomber with a 5-cell stride that historically scored well on the Hill. Cross-checking your result against multiple warriors helps confirm the server is not silently rejecting one of them on parse error.

  2. Step 2
    Collect the reward
    Observation
    I noticed the server runs 100 rounds and only prints the flag in the final summary, which meant the connection had to be kept open for the full run rather than closed after the first visible win.
    Once 100 matches finish, the service prints the flag in the summary. Anything north of 1 win clears the threshold.
    What didn't work first

    Tried: Disconnecting from nc after the first win result appears, before the 100-round summary is printed.

    The flag is only printed in the final summary after all 100 rounds complete. Closing the connection early (Ctrl+C) or piping the input without letting the server finish terminates the session before the flag appears. Let the server run all 100 rounds and read the full output.

    Learn more

    "At least one round" is the lenient bar. A bomber that wins close to 100 of 100 makes the test pass on the first connect. The 100-round format is statistical: random starting offsets vary how the warriors meet, so partial-win warriors prove they are genuinely capable rather than getting one lucky pairing.

    The progression across the three Ready Gladiator challenges (lose all, win some, win all) mirrors strategy work in CTFs more broadly: understand the game, achieve partial success, then turn the corner to consistent wins.

Flag

Reveal flag

picoCTF{1mp_1n...5_...}

Any warrior capable of beating the Imp at least once will work; Imp Ex is a handy template.

Key takeaway

Core War is a miniature adversarial computing environment where programs compete by overwriting each other's memory; the winning insight is always about coverage rate and stride relative to the opponent's movement speed. Bomber warriors win by writing fatal DAT instructions faster than the target can advance, which is the same resource-race logic that underlies denial-of-service mitigations and cache-poisoning defenses. Understanding stride relative to memory size is directly analogous to choosing step sizes in hash table probing and coverage analysis in fuzzing.

Related reading

Want more picoCTF 2023 writeups?

Useful tools for Reverse Engineering

What to try next