babygame01 picoCTF 2023 Solution

Published: April 26, 2023

Description

Navigate the BabyGame binary to obtain the flag. Use the secret L command to change your player character, then walk off the left edge of the map to write your character value into the win variable. Press P to auto-navigate to the exit and collect the flag.

Run the binary locally to understand the map mechanics (chmod +x game && ./game).

When ready, connect to nc saturn.picoctf.net 52987 to obtain the real flag.

bash
chmod +x game && ./game
bash
nc saturn.picoctf.net 52987
  1. Step 1Use L to set your player character to @
    The game has a hidden command L that changes the player character to whatever key you type next. Type L followed by a to set your character to @ (ASCII 0x40 = 64 decimal). The game will stamp this byte value into memory at your position.
    bash
    # After connecting, type:
    bash
    l
    bash
    @
    Learn more

    Reverse-engineering the binary in Ghidra reveals the move handler. When the input is l (lowercase L), the code reads the next character and stores it as the player tile. The player tile is the byte value that gets written to memory when the player moves. Setting it to @ (0x40 = 64) is important because the win variable check compares against 64.

  2. Step 2Walk off the left edge of the map
    Move to the left edge of the map (column 0) and press 'a' four more times. The game has no bounds check on the left edge, so your position goes negative and the player stamp writes your character value (64) into the win variable, which sits 4 bytes before the start of the map array. The game prints Player has flag: 64 to confirm.
    bash
    # Navigate to the leftmost column, then press:
    bash
    aaaa
    Learn more

    The stack layout places the win variable 4 bytes before the start of the map array. Moving left from column 0 without a bounds check decrements the x coordinate to -1, -2, -3, -4, and at each step writes the player character byte to that negative offset relative to the map base. After 4 left presses, the write lands on the win variable and sets it to 0x40 (64).

    This is an out-of-bounds write bug. The fix is a bounds check: if (x > 0) x--;. Without it, the player coordinates can go negative and clobber adjacent stack memory.

  3. Step 3Press P to auto-solve and reach the exit
    Once the win variable is set, press P to auto-navigate to the exit. Locally you will see "flag.txt not found", so repeat the moves remotely via netcat to have the server print the flag.
    Learn more

    Netcat (nc) is a raw TCP/UDP utility that connects stdin/stdout to a network socket. When a CTF challenge runs a binary on a remote server, nc host port lets you interact with it exactly as if you were at a local terminal - every keypress you type is sent over the wire and the server's output is streamed back.

    The reason the flag only appears remotely is that flag.txt exists only on the server's filesystem. Local runs teach you the mechanics; the remote session is where the actual secret is stored. This pattern is extremely common in CTF binary challenges: download and analyze locally, exploit remotely.

    For challenges that require many precise keystrokes, players often script the interaction with pwntools in Python (e.g., p.send(b'a' * 4)), which provides reliable, repeatable input over the same TCP connection.

Flag

picoCTF{gamer_m0d3_enabl...8e6}

The netcat session is required; local runs simply teach you the map layout.

Want more picoCTF 2023 writeups?

Useful tools for Binary Exploitation

Related reading

What to try next