GDB baby step 3

Published: March 5, 2024

Description

Debugger0_c stores 0x2262c96b on the stack. Examine the bytes exactly as they appear in memory and wrap them (in order) inside picoCTF{...}.

Memory inspectionDownload debugger0_c

Launch the binary under gdb and switch to layout asm to see where the MOV that stores 0x2262c96b executes.

Set a breakpoint right afterward (main+25) so the stack contents can be inspected before anything is overwritten.

wget https://artifacts.picoctf.net/c/531/debugger0_c
chmod +x debugger0_c
gdb --args ./debugger0_c

Solution

  1. Step 1Break after the store
    Place b *(main+25) so execution halts immediately after the constant is written to the stack. Run the program to hit that breakpoint.
    b *(main+25)
    run
    Learn more

    This challenge introduces memory inspection: reading raw bytes from a specific address rather than just reading a register value. After the MOV instruction writes 0x2262c96b to [rbp-0x4], the four bytes are stored in RAM at that stack address. Breaking immediately after the store lets you inspect those bytes before anything overwrites them.

    The key concept is that the CPU stores multi-byte integers in little-endian byte order on x86. Little-endian means the least significant byte is stored at the lowest memory address. So the 32-bit value 0x2262c96b is stored in memory as the byte sequence 6b c9 62 22(lowest byte first). When the challenge asks you to report the bytes "in order," it means in the order they appear in memory - which is the reversed byte order compared to how you read the constant in the assembly listing.

    Understanding endianness is critical in networking (network byte order is big-endian), binary exploitation (shellcode must account for byte order when encoding addresses), and file format parsing (file formats vary by endianness - JPEG is big-endian, most x86 executables are little-endian). Getting endianness wrong is one of the most common sources of bugs in low-level code.

  2. Step 2Dump four bytes from the stack
    Use x/4xb $rbp-4 (little-endian, so subtract four bytes from RBP) to view the byte order as stored in memory. Concatenate those bytes, preserving order, to form the hexadecimal inside the flag.
    x/4xb $rbp-4
    Learn more

    The GDB examine command (x) reads memory at an arbitrary address and displays it in a chosen format. The syntax x/4xb $rbp-4 means: examine 4 units, formatted as hex, each unit being one byte, starting at the address $rbp - 4. GDB prints each byte individually, separated by spaces, which makes it easy to read the byte sequence in memory order.

    To build the flag, concatenate the four bytes exactly as GDB prints them. Because x86 is little-endian, the byte GDB prints first is the least-significant byte of the original 32-bit value - so the output will appear "reversed" compared to 0x2262c96b. The challenge is testing whether you understand this reversal and report the bytes in memory order rather than the logical order.

    The x command is invaluable in real debugging and exploitation work. When inspecting a buffer overflow, you might use x/32xb $rsp to view 32 bytes of stack data. When verifying a shellcode injection, x/10i $rip disassembles ten instructions starting at the instruction pointer. Learning the format specifiers (x=hex, d=decimal, s=string, i=instruction, b=byte, h=halfword, w=word, g=giant/8-byte) is worth the small investment.

Flag

picoCTF{0x6b......22}

Your exact byte sequence may differ; always copy the four bytes exactly as x/4xb prints them.

Want more picoGym Exclusive writeups?

Useful tools for Reverse Engineering

Related reading

What to try next