Skip to main content

Ready Gladiator 1 picoCTF 2023 Solution

Craft a CoreWars warrior that can defeat an Imp opponent at least once across 100 rounds.

Published: April 26, 2023Updated: August 25, 2026

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 <PORT_FROM_INSTANCE> 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 <PORT_FROM_INSTANCE> < 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 1Adopt a published warrior
    Observation
    The description points at the documented Imp Ex example, and the original Imp is a simple move loop that never writes a killing DAT. Replace it outright with a published bomber-class warrior rather than trying to patch it.
    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 move instruction, changing the stride or adding copies, rarely produces a winner, because its weakness is that it never writes a killing DAT at all. However many copies run, none of them can kill the opponent. Switch warrior class entirely to a bomber, which plants fatal traps across memory.

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

    Redcode has addressing modes and opcode rules that intuition gets wrong: confusing immediate with direct addressing, forgetting that offsets are relative to the current instruction. A hand-written warrior with a syntax error is silently rejected or fails to compile on the server. Starting from a documented working warrior 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: the snippet above is the classic Dwarf pattern, the original 4-stride bomber and about as short as a bomber gets; 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 2Collect the reward
    Observation
    The server runs 100 rounds and only prints the flag in the final summary. Keep the connection open for the whole run rather than closing it 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 appears only in the summary after all 100 rounds finish. Interrupt early, or pipe the input without letting the server complete, and the session ends before it prints. Let all 100 rounds run and read the whole 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, and the winning insight is always coverage rate and stride against the opponent's speed. A bomber wins by writing fatal instructions faster than its target can advance, which is the same resource-race logic behind denial-of-service mitigation and cache-poisoning defense. Reasoning about stride relative to memory size is the same skill as choosing step sizes in hash table probing or coverage analysis in fuzzing.

Related reading

Useful tools for Reverse Engineering

Where to go next