Skip to main content

ASCII FTW picoGym Exclusive Solution

Analyze a disassembled binary and convert raw byte values into readable characters to find the flag.

Published: March 5, 2024Updated: August 25, 2026

Description

The asciiftw binary constructs the flag byte-by-byte using movb instructions. Extract those literals from the disassembly and convert them from hex to ASCII.

Disassembly parsingDownload asciiftw

Download the PIE binary, mark it executable, and run objdump -d to disassemble main.

Filter for movb instructions-each contains the next byte of the flag.

bash
wget https://artifacts.picoctf.net/c/508/asciiftw
bash
chmod +x asciiftw
bash
objdump -d asciiftw | grep movb

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1Collect the bytes
    Observation
    The description says the flag is built one byte at a time with movb instructions. Filter the disassembly for those and read off each immediate operand in order.
    Pipe objdump's output through grep/cut to isolate the immediate operand passed to movb. Concatenate them into a single hex string.
    bash
    objdump -d asciiftw | grep movb | grep -oE '[$]0x[0-9a-f]{2}' | sed 's/[$]0x//' | tr -d '\n'
    What didn't work first

    Tried: Run 'strings asciiftw' to find the flag directly in the binary.

    strings finds contiguous runs of printable characters, and the flag is never stored as one. It is assembled a byte at a time, so nothing useful appears. The bytes live scattered across individual instructions rather than in a data section, which is why the disassembly is where to look.

    Tried: Use 'grep movb' alone without the second grep -oE filter to extract the operands.

    Without the regex filter, grep prints whole disassembly lines: instruction addresses, opcode bytes, register operands. The immediates are buried among all of it and cannot go straight into xxd. Extract just the immediate from each line.

    Learn more

    objdump is a command-line utility that displays information about object files and executables. The -d flag disassembles executable sections, converting the raw machine-code bytes back into human-readable assembly mnemonics. This is one of the most fundamental tools in binary reverse engineering.

    The movb instruction (move byte) copies a single 8-bit value into a memory location or register. When a program constructs a string or flag at runtime by writing one character at a time, each character appears as an immediate operand - a literal hex value embedded directly in the instruction. Filtering the disassembly for movb lines reveals every byte the program is about to write.

    The pipeline here combines several Unix tools: grep -oE extracts only the matching portion of each line (the immediate operand, which objdump prints in AT&T syntax as $0x70), sed strips the $0x prefix, and tr -d removes the newlines to produce one continuous hex stream. This kind of shell pipeline - chaining small, focused tools - is a core skill in CTF forensics and everyday systems work.

  2. Step 2Convert from hex
    Observation
    Those operands are hex literals in the ASCII range. Concatenate them and pipe the stream through xxd -r -p.
    Send the aggregated hex into xxd -p -r to turn it back into ASCII text.
    bash
    objdump -d asciiftw | grep movb | grep -oE '[$]0x[0-9a-f]{2}' | sed 's/[$]0x//' | tr -d '\n' | xxd -r -p

    Expected output

    picoCTF{ASCII_IS_EASY_8960...}
    What didn't work first

    Tried: Pipe the hex output into 'xxd -r' without the -p flag.

    Without -p, xxd expects its own dump layout: address column, hex columns, ASCII sidebar. A raw hex stream does not match that, so you get garbled or empty output. -p accepts continuous hex digits with no formatting.

    Tried: Use Python's bytes.fromhex() directly on the grep output including the '0x' prefix and commas.

    bytes.fromhex wants bare hex digits with no prefixes or separators, so a string full of 0x prefixes and commas raises an error. Strip those in the pipeline first.

    Learn more

    xxd is a hex dump utility that can both produce and consume hexadecimal representations of binary data. When run with -r (reverse) and -p (plain hex without formatting), it reads a stream of hex digits and outputs the corresponding raw bytes - effectively decoding hex back into ASCII text.

    The reason this works is that every printable ASCII character has a well-defined hex equivalent (for example, 'A' is 0x41, and 'p' is 0x70). The movb immediates are just these values stored directly in the binary. By collecting and decoding them in order, you reconstruct the string the program would have placed in memory at runtime.

    This technique generalizes broadly: any binary that builds a sensitive string (key, flag, password) byte-by-byte through immediate stores is vulnerable to static extraction via disassembly. Real-world malware analysts use the same method to extract hardcoded C2 domains or decryption keys from obfuscated samples.

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.
  • Base64 & Base32 DecoderDecode Base64 and Base32 strings with auto-detection. Multi-layer mode unwraps nested encodings automatically.

Flag

Reveal flag

picoCTF{ASCII_IS_EASY_8960...}

Any pipeline that extracts the movb immediates and feeds them into a hex→ASCII converter produces the same flag.

Key takeaway

A binary that assembles a string one byte at a time never stores it contiguously, so strings misses it while the disassembly always has it: each character is a hex immediate in its own instruction, and grep plus a hex-to-ASCII conversion rebuilds the whole thing statically. Crackmes and license-key checks use this on every architecture, whenever the author wants no searchable literal in the file.

Related reading

Useful tools for Reverse Engineering

Where to go next