ARMssembly 0 picoCTF 2021 Solution

Published: April 2, 2026

Description

What integer does this ARM assembly program return when given arguments 182476535 and 3742084308? Flag format: picoCTF{XXXXXXXX} - 8 lowercase hex characters representing a 32-bit value.

Download chall.S.

bash
wget <url>/chall.S
  1. Step 1Read the assembly and identify the pattern
    Open chall.S. The function takes two 32-bit args in w0 and w1, compares them with cmp, and returns the larger via a conditional branch. That's max(a, b).
    bash
    less chall.S
    Learn more

    AArch64 ARM (64-bit ARM) passes the first four integer arguments in registers x0 through x3. The w-prefixed registers (w0, w1) are the lower 32 bits of the corresponding x registers. The assembly uses cmp to set flags, then a conditional branch to pick the larger value and store it in w0 (the return value register).

    How cmp works: The cmp w0, w1 instruction subtracts w1 from w0 and discards the result, but updates the processor's condition flags: N (negative), Z (zero), C (carry), and V (overflow). Subsequent conditional branch instructions like b.gt (branch if greater than), b.le (branch if less than or equal), or b.eq (branch if equal) read these flags. The combination of cmp followed by a conditional branch is the ARM equivalent of an if statement.

    ARM is everywhere: AArch64 (ARM64) runs all Apple Silicon Macs, all modern Android phones, and most embedded systems. ARM CTF challenges are good practice for real-world mobile and embedded security work. For deeper static analysis on these binaries, see the Ghidra reverse engineering guide.

  2. Step 2Pick the larger argument and convert to hex
    max(182476535, 3742084308) = 3742084308. Convert to hex with Python and zero-pad to 8 chars.
    python
    python3 -c "print(f'{max(182476535, 3742084308):08x}')"
    Learn more

    f'{n:08x}' formats n as lowercase hex padded to 8 digits. For 3742084308 this gives df0bacd4.

  3. Step 3Verify by running the binary under QEMU
    Cross-compile chall.S to an AArch64 binary, run it under qemu-aarch64-static, and inspect the return value. The exit code is masked to 8 bits, so add a tiny printf wrapper to see the full 32-bit value.
    bash
    aarch64-linux-gnu-gcc -static -o chall chall.S
    bash
    qemu-aarch64-static ./chall 182476535 3742084308; echo $?
    Learn more

    QEMU emulates AArch64 binaries on an x86 host. Combined with aarch64-linux-gnu-gcc you can assemble and execute ARM code without physical ARM hardware. The exit code is truncated to 8 bits, so the bare program will print something like 212 (which is 0xd4, the low byte of 0xdf0bacd4) confirming the low byte of your computed answer. To see all 32 bits, write a small C wrapper that calls the function and printfs the result, or use Ghidra's AArch64 decompiler to confirm the logic statically.

Flag

picoCTF{...}

The body shows the worked example with the raw 32-bit return value 0xdf0bacd4. Submit it inside the picoCTF{...} wrapper as the challenge expects.

Want more picoCTF 2021 writeups?

Useful tools for Reverse Engineering

Related reading

What to try next