Skip to main content

droids1 picoCTF 2019 Solution

Reverse engineer an Android APK to understand how it validates user input and recover the hidden flag.

Published: April 2, 2026Updated: August 25, 2026

Description

Find the password in droids1.apk. The password check compares input against a string resource - decompile the APK with jadx to find the password, then enter it in the emulator to get the flag.

Download the APK file.

bash
wget <url>/droids1.apk

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1Decompile with jadx and find the password check
    Observation
    This is an Android APK with a password check. Decompiling it with jadx gives readable Java, where the comparison logic and any string resource IDs it references will be right there.
    Decompile droids1.apk with jadx. Open MainActivity and find the getFlag method. It compares the user input against a string fetched from resources via getString(R.string.password). Look in the strings.xml resource file to read the actual password value.
    bash
    jadx droids1.apk -d droids1_java/
    bash
    cat droids1_java/resources/res/values/strings.xml | grep password
    What didn't work first

    Tried: Use apktool to decompile the APK and look for the password in the smali output.

    apktool produces smali, Dalvik assembly with register references like v0 and p1, rather than readable Java. The string resource shows up as a hex constant like 0x7f0a0012, which you then trace through the resource table by hand. jadx decompiles to Java and resolves resource names, so the getString(R.string.password) call reads plainly.

    Tried: Run 'strings droids1.apk' to extract the password directly from the APK binary.

    strings on the raw APK emits a flood of class names, XML tags, and DEX metadata. String resources are stored in a compiled binary XML format (resources.arsc), so the password is not present as plain ASCII anywhere in the archive. jadx, or aapt dump resources, parses resources.arsc and shows the key-value pairs in readable form.

    Learn more

    Android app logic lives in Java/Kotlin classes compiled to DEX bytecode. The main entry point is typically MainActivity.java. Button click handlers call validation methods. In jadx, search for methods containing string comparisons (equals(), compareTo()) to find password checks.

  2. Step 2Find the password construction
    Observation
    getFlag calls getString(R.string.password) rather than using a literal. So the actual password lives in strings.xml, and the resource ID needs resolving there.
    Read the decompiled check method. The password may be: a string literal, built by concatenating string constants, derived from a formula, or loaded from a resource. Extract the exact string.
    Learn more

    Common obfuscation patterns in Android: StringBuilder used to concatenate parts of the password, Base64 decoding of an encoded string at runtime, or character arrays that are harder for decompilers to identify as strings. The jadx decompiler handles most of these transparently.

  3. Step 3Enter the password in the emulator to get the flag
    Observation
    The app only reveals the flag at runtime, after a correct password is entered. So install the APK in an emulator over ADB and submit the password recovered from strings.xml.
    Install the APK in an Android emulator using ADB. Launch the app, type the password you found in strings.xml into the text field, and press the button. The app displays the flag when the correct password is entered.
    bash
    adb install droids1.apk
    bash
    # Launch the emulator, open the app, type the password from strings.xml, and press the button
    What didn't work first

    Tried: Patch the APK with apktool to bypass the password check, then reinstall it to get the flag without knowing the password.

    Patching smali means editing the comparison opcode, re-signing the APK with a debug key, and reinstalling: several steps, each easy to get wrong. Here the password sits in plaintext in strings.xml, so reading it with jadx is far faster. Save patching for when the password is computed at runtime.

    Tried: Use 'adb shell input text PASSWORD' to type the password programmatically instead of typing it in the emulator UI.

    adb shell input text works for plain ASCII, but if the soft keyboard is not focused on the input field the keystrokes go to whatever does have focus and the field stays empty. Safer to tap the field with adb shell input tap first, confirm focus, then send the text, or just type in the emulator window.

    Learn more

    ADB (Android Debug Bridge) allows you to install, run, and interact with apps on connected devices or emulators. The am start command launches an Activity by its package and class name.

Interactive tools
  • 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.
  • 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.
  • 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.

Flag

Reveal flag

picoCTF{pining.for.the.fjords}

The password is stored as a string resource in strings.xml - readable by jadx. Enter it in the emulator to display the flag.

Key takeaway

Android APKs are ZIP archives holding DEX bytecode and XML resources, and decompilers like jadx and apktool recover both. A secret in strings.xml, hardcoded in Java, or baked into DEX as a constant is not protected at all; it is one tool invocation from being read. Secrets that have to live on a device should be fetched at runtime from a server that does real authentication, not bundled into the package.

Related reading

Useful tools for Reverse Engineering

Where to go next