GDB Test Drive picoCTF 2022 Solution

Published: July 20, 2023

Description

Practice GDB: break at main+99, run, and jump to main+104 to skip a delay and print the flag.

Make the binary executable (chmod +x gdbme).

Drop the GDB commands into a file (drive.gdb) and load with gdb -x drive.gdb gdbme so the run is reproducible.

After jump *(main+104), type c to continue execution; the flag prints and the program exits.

bash
chmod +x gdbme
bash
printf 'layout asm\nbreak *(main+99)\nrun\njump *(main+104)\nc\n' > drive.gdb
bash
gdb -x drive.gdb gdbme
  1. Step 1Set up the breakpoint
    Break at *(main+99), run, then jump past the sleep at *(main+104). With ASLR/PIE on, main+99 may not resolve before the program loads - run info address main after the first run to grab the live address and add 99/104 to it instead of relying on the symbolic offset.
    Learn more

    GDB (GNU Debugger) is the standard debugger for Linux programs. It can pause execution at specific points (breakpoints), inspect registers and memory, modify values at runtime, and change the instruction pointer to jump to arbitrary locations in the code. These capabilities make it an essential tool for both software development and reverse engineering.

    A breakpoint at *(main+99) tells GDB to pause execution 99 bytes into the main function. The * dereferences the address expression - without it, GDB would interpret the argument as a line number. The layout asm command switches the TUI (text user interface) to show the assembly disassembly, which is useful for understanding exactly what instruction you're stopped at.

    GDB supports scripting via here-documents (as shown in the command) or via -x script.gdb to run a file of GDB commands. Automating debugger sessions this way is powerful for CTF challenges that require repeatable interaction with a binary, and is the foundation of tools like pwndbg and pwntools which wrap GDB for exploit development.

  2. Step 2Skip the wait
    Jumping to main+104 lands past the sleep call. GDB does not auto-resume after a jump - type c (continue) so the rest of main runs and the flag actually prints.
    Learn more

    The jump command in GDB changes the instruction pointer (RIP on x86-64) to a new address and resumes execution from there. This lets you skip over any instruction or block of code - in this case, a sleep() call that would otherwise make the program wait an impractically long time before printing the flag.

    Anti-debugging tricks like deliberate sleep calls, infinite loops, or timing checks are common in CTF binaries and real malware to frustrate analysis. The sleep approach is the simplest: the program is correct and will eventually print the flag, but waiting would take too long. More sophisticated techniques include checking if a debugger is attached via ptrace(PTRACE_TRACEME), detecting breakpoints by looking for 0xCC bytes in the code, or using timing side-channels.

    Knowing how to patch around such checks - either by jumping past them in GDB or by binary patching the file with a hex editor - is a core reverse engineering skill. The jump command is the lightest-weight approach since it doesn't modify the binary on disk.

Flag

picoCTF{d3bugg3r_dr1v3_197c3...}

Great intro to gdb's `jump` command for skipping instructions.

Want more picoCTF 2022 writeups?

Useful tools for Reverse Engineering

Related reading

Do these first

What to try next