Bit-O-Asm-4

Published: March 5, 2024

Description

The fourth assembly dump again loads 0x9fe1a but subtracts 0x65 before returning. Convert the result into decimal for the flag.

Fetch the dump and focus on the subtraction at <+31>.

wget https://artifacts.picoctf.net/c/511/disassembler-dump0_d.txt
cat disassembler-dump0_d.txt

Solution

  1. Step 1Track the operations
    EAX is assigned 0x9fe1a and then SUB 0x65 executes. No other arithmetic touches the register before return.
    Learn more

    The SUB instruction subtracts a value from a register or memory location in place. sub eax, 0x65 means EAX = EAX - 0x65. Like ADD, it modifies flags (carry, overflow, zero, sign) that conditional branches can test - but since this function just returns after the subtract, the flags are irrelevant here.

    A key skill this challenge reinforces is verifying that no other instructions between the SUB and the RET touch EAX. In a longer function there might be other instructions that modify EAX - a PUSH/POP pair, a CALL that overwrites it, or a conditional MOV. Confirming that the final value is indeed the post-subtraction result requires scanning every subsequent instruction for EAX writes.

    This kind of careful instruction-by-instruction analysis is exactly what reverse engineers do when tracing through license-key validation routines, cryptographic transformations, or anti-debugging checks. The habit of asking "does anything modify this value before it reaches the point I care about?" prevents mistakes that could waste hours during a real engagement.

  2. Step 2Compute the result
    Evaluate 0x9fe1a - 0x65 = 654,773 and wrap it with picoCTF{...}.
    python3 - <<'PY'
    print(0x9fe1a - 0x65)
    PY
    Learn more

    Subtraction in hex follows the same rules as in decimal, but carries propagate in powers of 16 instead of 10. 0x9fe1a - 0x65: the low byte 1a (26 decimal) minus 65 (101 decimal) would go negative, triggering a borrow, giving b5(181 decimal) in the result's low byte. Letting Python handle this avoids manual borrow tracking.

    Notice that 0x65 is the ASCII code for 'e'. While this is coincidental here, it illustrates how the same number carries different meanings depending on context - always ask whether a constant is meant to be an integer, a character, a flag bitmask, or something else. In this series the constants are pure integers, but in real binaries this ambiguity appears constantly.

    Completing all four Bit-O-Asm challenges builds the core loop of assembly reading: locate the relevant instructions, trace the data flow, apply any arithmetic, and convert to the required representation. This loop scales directly to reading real compiler output, whether you are auditing a closed-source binary, analyzing a firmware image, or studying how a C compiler optimizes a particular expression.

Flag

picoCTF{...}

Double-check the direction of the subtraction: EAX minus 0x65, not the other way around.

Want more picoGym Exclusive writeups?

Useful tools for Reverse Engineering

Related reading

What to try next