Mob psycho picoCTF 2024 Solution

Published: April 3, 2024

Description

Can you handle APKs? Download the android apk here.

APK unpacking

Download mobpsycho.apk and unzip it in a separate directory (APK unzip dumps lots of files).

bash
wget https://artifacts.picoctf.net/c_titan/53/mobpsycho.apk && \
mkdir mobpsycho_dir && cd mobpsycho_dir && \
unzip ../mobpsycho.apk

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
The Hex Dumps for CTF guide covers the xxd -r -p reverse-hex pattern at the heart of this solve, plus the recognition cues for hex-encoded strings hidden inside other formats.
  1. Step 1
    Find the flag file
    Observation
    I noticed the challenge provided an APK file and Android apps store raw resources (text, config, and asset files) inside the res/ directory of their ZIP structure, which suggested scanning that directory with find and strings to locate any file referencing the flag.
    Recursively scan extracted files with find and strings, scoped to res/ for speed. The flag lives at res/color/flag.txt.
    bash
    find res -type f -exec strings {} + | grep flag
    bash
    find . -type f -name 'flag*'
    What didn't work first

    Tried: Run strings on the APK file directly before unzipping it

    strings on the raw .apk will emit a flood of ZIP metadata and DEX bytecode fragments; the flag string is buried or absent because ZIP compression means the file bytes are not plain ASCII. Unzipping first lets strings operate on the uncompressed resource files where the flag is stored as a plain text hex string.

    Tried: Search only the top-level directory with grep -r . instead of scoping to res/

    grep -r . over the entire extracted tree also processes classes.dex, which is large binary Dalvik bytecode. The grep will still find the flag eventually, but it can take far longer and may output thousands of false-positive binary matches. Scoping to res/ (or using find with -exec strings) targets the resource layer where Android apps store raw text files.

    Learn more

    An APK (Android Package Kit) is simply a ZIP archive containing everything an Android app needs: compiled Dalvik bytecode (classes.dex), resources, assets, a manifest, and native libraries. Because it is a standard ZIP, any tool that can unzip an archive can explore its contents without needing a real Android device.

    find ... -exec strings {} + applies strings to every regular file under the path and pipes the union into grep. It's the safer alternative to a top-level strings *: that glob skips dotfiles, expands at most one level, and chokes on directories. Scoping to res/ avoids dumping classes.dex through strings just to look for a filename you already suspect lives in resources.

    • The res/ directory holds Android XML resources, drawables, and raw files, a common hiding spot for CTF secrets.
    • The assets/ directory is another frequent location for embedded files that are not compiled into the DEX.
    • For deeper analysis, tools like jadx or apktool decompile DEX bytecode back to readable Java/Smali.
  2. Step 2
    Decode the hex
    Observation
    I noticed that flag.txt contained a continuous string of [0-9a-f] character pairs with no address offsets or spaces, which are the hallmarks of a plain hex dump and suggested using xxd -r -p to convert the hex digits back to readable ASCII.
    flag.txt contains hex; pipe it through xxd -r -p (or CyberChef's From Hex) to recover the ASCII flag.
    bash
    xxd -r -p res/color/flag.txt

    Expected output

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

    Tried: Run xxd -r res/color/flag.txt without the -p flag

    xxd -r without -p expects the standard xxd address-offset format (e.g. '00000000: 7069 636f ...'). flag.txt contains a continuous hex string with no offsets, so xxd -r produces garbled or empty output. The -p flag tells xxd the input is plain hex with no column structure.

    Tried: Open flag.txt in a text editor and read it as the flag

    The raw contents of flag.txt look like a long string of hex digits (e.g. 7069636f435446...) which is not a valid picoCTF flag. The actual flag is the ASCII result of decoding those hex pairs - each pair encodes one character. Submitting the raw hex string will be rejected.

    Learn more

    Hiding data as hexadecimal is a simple obfuscation technique: each byte of the original string is represented as two hex digits (e.g., the letter 'p' becomes 70). The value is human-unreadable at a glance but trivially reversible.

    xxd -r -p reverses a plain hex dump back to binary. The -r flag means "reverse" (hex to binary) and -p means the input is in plain/continuous hex format without address offsets. This combination is the standard Linux one-liner for hex decoding.

    CyberChef's From Hex recipe performs the same operation visually, making it useful when you want to see intermediate steps or chain multiple decodings (e.g., hex then base64 then ROT13). Real malware samples often layer encodings precisely to slow down analysts.

    The decoded output is pure ASCII printable text from p through }: that's the entire flag, copy it as-is. If you see \0 or other null bytes inside the output, that's a sign the input hex had odd-length bytes, stray spaces, or trailing whitespace that xxd -r -p mishandled, not part of the flag itself.

Interactive tools
  • File Magic IdentifierIdentify file types from magic numbers. Paste hex bytes or drop a file to detect PNG, JPEG, ZIP, PDF, ELF, PCAP, SQLite, and dozens of other formats.
  • Strings ExtractorPull printable text from any binary, library, or image. ASCII and UTF-16 detection, configurable minimum length, flag-like highlight, no command line needed.

Flag

Reveal flag

picoCTF{ax8mC0RU6ve_NX85l4ax8mCl_a3e...}

The decoded hex string inside res/color/flag.txt is the flag.

Key takeaway

Android APKs are standard ZIP archives, so any data bundled as a raw resource file is accessible to anyone who can run unzip, no Android device or emulator required. App developers sometimes store API keys, hardcoded credentials, or other secrets in the res/ or assets/ directories under the assumption that users cannot inspect an installed APK; that assumption is wrong. The same static-analysis workflow (unzip, strings, grep, jadx for DEX) applies to real-world app security assessments and bug bounty programs targeting Android applications.

Related reading

Want more picoCTF 2024 writeups?

Tools used in this challenge

Do these first

What to try next