Skip to main content

GDB baby step 1 picoGym Exclusive Solution

A beginner-friendly reverse engineering challenge using a debugger to inspect a register value at runtime.

Published: March 5, 2024Updated: August 25, 2026

Description

Disassemble debugger0_a and report the final value placed into EAX before main returns. Format the answer as picoCTF{n}, where n is the decimal representation of that value.

Make the binary executable and open it inside gdb with layout asm so you can watch instructions update EAX.

Alternatively, run objdump -D debugger0_a | less and search for main to read the assembly without a debugger.

bash
wget https://artifacts.picoctf.net/c/512/debugger0_a
bash
chmod +x debugger0_a
bash
gdb --args ./debugger0_a

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1Observe the assignment
    Observation
    The question is what EAX holds when main returns. Disassemble it and find the last MOV writing a constant into that register before the RET.
    Stepping through main shows a MOV that loads 0x86342 into EAX right before the function returns. No further arithmetic occurs afterward.
    Learn more

    GDB (GNU Debugger) is the standard debugger for Linux programs written in C, C++, and assembly. It lets you pause execution at any point, inspect registers and memory, modify values, and step through instructions one at a time. The layout asm command switches GDB to a split-screen mode that shows the disassembly alongside the command prompt, making it easy to see which instruction is about to execute.

    Opening a binary in GDB without running it first allows pure static inspection: you can disassemble functions (disas main) and read the assembly without the program executing any code. This is useful when a binary has side effects you want to avoid (network connections, file writes, anti-debugging checks). Many CTF binaries are safe to run, but building the habit of inspecting before executing is important for real-world work.

    The two approaches shown - GDB and objdump - represent dynamic and static analysis respectively. Static analysis reads the binary without running it; dynamic analysis runs it under controlled conditions. Professional reverse engineers use both, switching between them depending on which provides more clarity. For this challenge, static analysis via objdump is sufficient and faster.

  2. Step 2Convert to decimal
    Observation
    The disassembly gives 0x86342, and the flag wants a decimal integer. Convert before submitting.
    Use printf or python to convert 0x86342 to decimal, since the flag expects picoCTF{...} where n is decimal.
    python
    python3 - <<'PY'
    print(0x86342)
    PY
    bash
    printf "picoCTF{%d}\n" 0x86342

    Expected output

    picoCTF{549698}
    What didn't work first

    Tried: Running the binary and reading its printed output instead of inspecting a register

    The binary never prints the value. It returns from main with it, and the shell only ever sees the low byte of that (549698 truncates to 66), so running it produces an empty prompt and a useless exit status. Disassemble main and read the MOV that loads the constant.

    Tried: Converting the hex value as a string ('86342') to decimal using atoi or int() instead of treating it as a base-16 number

    Passing those digits to int() with no base reads them as decimal and hands back the same number, not 549698. The flag wants the decimal value of a hexadecimal constant, so specify base 16 or use the 0x literal.

    Learn more

    0x86342 in decimal is 549,698. The conversion follows the standard positional notation for base 16: 8×16&sup4; + 6×16³ + 3×16² + 4×16 + 2. Both the printf and Python approaches handle this instantly, which is why learning a few reliable conversion tools matters more than memorizing the arithmetic.

    In GDB you can also print converted values directly: print/d $eax prints EAX in decimal, print/x $eax in hex, and print/t $eax in binary. The GDB print command is a full expression evaluator - you can even do arithmetic inside it: print 0x86342 immediately shows 549698.

    This challenge series is explicitly designed to build comfort with the GDB workflow: download a binary, make it executable, load it in the debugger, set breakpoints, run, inspect registers. These are the exact steps a vulnerability researcher takes when analyzing a real target. Mastering this flow on simple binaries makes the transition to complex targets much smoother.

Interactive tools
  • Cyclic Pattern GeneratorGenerate de Bruijn cyclic patterns and find buffer overflow offsets. The browser equivalent of pwntools cyclic and cyclic_find.
  • pwntools Payload BuilderPack integers into little-endian bytes (p32 / p64), unpack bytes back to integers, and build flat ROP payloads with offset-based insertion.
  • Hex ViewerView text or raw hex bytes as a xxd-style hex dump with byte offset, hex columns, and ASCII sidebar. Highlights printable characters and null bytes.

Flag

Reveal flag

picoCTF{...}

Every run produces the same deterministic constant, so any disassembly workflow that recovers 0x86342 works.

Key takeaway

x86 calling conventions put an integer return value in EAX, so reading that register just before the RET tells you exactly what the function hands back. objdump and GDB's disassembler show this without running anything, which is static analysis at its simplest. The same reading carries into license checks, anti-debugging routines, and exploit work, where what sits in EAX decides which branch execution takes.

Related reading

Useful tools for Reverse Engineering

Where to go next