Description
Follow the memory references in the second disassembly dump to recover the value moved into EAX, then convert it from hexadecimal to decimal.
Setup
Fetch the dump and inspect the MOV that assigns DWORD PTR [rbp-0x4] to EAX.
wget https://artifacts.picoctf.net/c/510/disassembler-dump0_b.txtcat disassembler-dump0_b.txtSolution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1Resolve the stored constant
ObservationEAX is loaded from a stack slot rather than an immediate, so trace back through the function and find what was written into that slot earlier.The dump shows 0x9fe1a being written to [rbp-0x4], and that value is later moved into EAX.Learn more
This challenge introduces stack-based local variables. Rather than placing a constant directly into EAX, the compiler first stores the value in a stack slot (
[rbp-0x4]) and then loads it back into the register. This pattern is extremely common when the compiler preserves intermediate values across function calls or when the source variable has its address taken.RBP is the base pointer register, which typically points to the base of the current stack frame. Negative offsets from RBP (like
rbp-0x4) address local variables. DWORD PTR indicates a 4-byte (32-bit) memory access, consistent with writing to a 32-bit variable. Tracing the data flow - from the immediate literal through the stack slot and back into EAX - is the key skill in this step.In real reverse engineering, following these data-flow chains is called value tracking or taint analysis. Automated tools (like the taint tracking in Ghidra's decompiler or tools like DynamoRIO) do this programmatically, but manual tracing is essential for understanding what the tools produce and for analyzing obfuscated code where automation struggles.
Step 2Convert 0x9fe1a to decimal
ObservationThe constant stored there is hexadecimal and the flag wants decimal, so convert before assembling it.Translate 0x9fe1a into decimal (654874) using printf or python, then format the flag as picoCTF{...}.bashprintf "picoCTF{%d}\n" 0x9fe1aExpected output
picoCTF{654874}What didn't work first
Tried: Using Python with int('0x9fe1a', 16) but forgetting the quotes, writing int(0x9fe1a, 16) instead.
Python errors here because an unquoted 0x9fe1a is already an integer literal, and the base argument only applies to a string. Either quote the digits without the prefix, or just print the literal, since Python evaluates it for you.
Tried: Running echo 0x9fe1a | bc to convert the hex value.
bc reads decimal by default, so the 0x prefix is either a syntax error or silently dropped. For hex you have to set the input base to 16 and pass uppercase digits with no prefix. printf or Python avoids the whole question.
Learn more
Converting a multi-digit hex number to decimal requires summing each digit's value multiplied by the appropriate power of 16. For
0x9fe1a:9×16&sup4; + 15×16³ + 14×16² + 1×16 + 10 = 654874. In practice, no one does this by hand - you reach forprintf, Python, or a calculator.The
printf "%d" 0x9fe1acommand works because bash'sprintfinherits C's integer-literal conventions: the0xprefix signals a hexadecimal value. Python's built-inint()function similarly accepts a base argument:int("9fe1a", 16)gives the same result. Both are standard tools to keep in muscle memory.The broader skill here is recognizing that hex and decimal are representations, not different numbers. The CPU stores a single bit pattern; how humans write it is a matter of convention. Whenever you see a constant in a disassembly listing, ask yourself: is this a count? A character code? An address offset? A bitmask? The representation choice often hints at the intent.
Interactive tools
- 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.
- Number Base ConverterConvert numbers between binary, octal, decimal, and hexadecimal instantly. Enter any value and see all four bases update in real time.
- Endianness ConverterConvert between big-endian and little-endian byte order with visual byte layout. Supports 16-bit, 32-bit, and 64-bit words.
Flag
Reveal flag
picoCTF{...}
Each Bit-O-Asm stage reinforces reading registers and stack slots straight from the disassembly.