GDB baby step 1 picoGym Exclusive Solution

Published: March 5, 2024

Description

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

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 1
    Observe the assignment
    Observation
    I noticed the challenge asks for the final value placed into EAX before main returns, which pointed directly to disassembling main and looking for the last MOV instruction that writes a constant into EAX 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 2
    Convert to decimal
    Observation
    I noticed the disassembly revealed the constant 0x86342 in hexadecimal, and the flag format requires a decimal integer inside picoCTF{...}, which suggested converting the hex value to base 10 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 does not print the EAX value to stdout; it simply returns from main with that value as the exit code. Running ./debugger0_a produces no visible output, so you see only an empty prompt. The correct approach is to disassemble main and read the MOV instruction that loads the constant, not to run the program and hope it prints something.

    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 the string '86342' to Python's int() with no base argument interprets it as base 10, giving 86342 instead of 549698. The flag format requires the decimal value of the hexadecimal constant 0x86342, so the conversion must use base 16 - either int('86342', 16) or the 0x prefix literal like int(0x86342).

    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.

Flag

Reveal flag

picoCTF{...}

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

Key takeaway

The x86 and x86-64 calling conventions place a function's integer return value in the EAX (or RAX) register, so reading that register right before a RET instruction reveals exactly what the function will return to its caller. Disassembly tools like objdump and GDB's disas command expose this without executing the binary at all, which is static analysis in its simplest form. The same register-reading skill scales directly to reverse engineering license checks, anti-debugging routines, and exploit development where controlling EAX determines whether execution reaches a success or failure branch.

Related reading

Want more picoGym Exclusive writeups?

Useful tools for Reverse Engineering

Do these first

What to try next