APKTool: Complete Guide to Android APK Reverse Engineering and Application Analysis Using Kali Linux

APKTool: Complete Guide to Android APK Reverse Engineering and Application Analysis Using Kali Linux

Apktool is a tool for reverse engineering third-party, closed, binary Android application packages (APK files). It is written in Java and maintained by Connor Tumbleson (iBotPeaches) and Ryszard Wiśniewski. Apktool’s core capability is bidirectional conversion: it can decode an APK’s compiled resources (including the binary AndroidManifest.xml and resources.arsc) and its DEX bytecode into a near-original, human-readable, editable project structure — decoded XML resources and Smali (a human-readable disassembly of Dalvik bytecode) — and then rebuild that same project structure back into a working APK after modifications have been made.

This makes Apktool the primary tool for tasks such as:

Apktool has a project-like directory structure and supports installing “framework” files, which are required to correctly decode resources for APKs that depend on system or OEM-specific resource frameworks (common on Samsung, MIUI, and other vendor-customized Android builds).

How to Install

Apktool comes pre-installed on Kali Linux under the Reverse Engineering / Web Application Analysis tool categories. If it is missing or you need to update it, use the following methods.

Method 1 – APT (Kali Linux default repositories):

sudo apt update
sudo apt install apktool -y

Method 2 – Manual installation (latest version from GitHub):

# Ensure Java is installed (Apktool requires Java 8 or higher)
sudo apt install default-jdk -y

# Download the wrapper script
sudo curl -o /usr/local/bin/apktool \
  https://raw.githubusercontent.com/iBotPeaches/Apktool/master/scripts/linux/apktool

# Download the latest apktool jar (check releases page for current version number)
sudo curl -L -o /usr/local/bin/apktool.jar \
  https://github.com/iBotPeaches/Apktool/releases/download/v2.9.3/apktool_2.9.3.jar

# Make both files executable
sudo chmod +x /usr/local/bin/apktool
sudo chmod +x /usr/local/bin/apktool.jar

Verify installation:

$ apktool --version
2.9.3

Syntax

apktool [options]
apktool d[ecode] [options] <file.apk>
apktool b[uild] [options] <app_path>
apktool if|install-framework <framework.apk> [options]
apktool empty-framework-dir [options]
apktool list-frameworks [options]

All Command-Line Options

Utility Options:

OptionDescription
-advance, --advancedDumps out advanced usage output
-version, --versionOutputs the current software version

Decoding Options (used with apktool d file.apk {options}):

OptionDescription
-api, --api-level <API>Sets the API level used in generated smali files (defaults to targetSdkVersion)
-b, --no-debug-infoPrevents baksmali from writing out debug info (.local, .param, .line, etc.)
-f, --forceForces deletion of the destination directory and forces decoding of AndroidManifest.xml regardless of options
-m, --match-originalMatches generated files as close as possible to the originals (may prevent re-build)
-p, --frame-path <DIR>Sets the folder framework files are stored/read from
-r, --no-resPrevents decompiling resources; keeps resources.arsc intact
-resm, --resource-mode <mode>Sets mode for unresolved resources: remove (default), dummy, or keep
-s, --no-srcPrevents disassembling dex files; leaves dex untouched and moves it on build
-t, --frame-tag <TAG>Uses framework files tagged by TAG

Building Options (used with apktool b folder {options}):

OptionDescription
-a, --aapt <FILE>Loads aapt/aapt2 binaries from a specified location instead of the internal version
-api, --api-level <API>Sets the API level of smali files to build against (defaults to minSdkVersion)
-c, --copy-originalCopies the original AndroidManifest.xml and META-INF
-d, --debugAdds debuggable="true" to AndroidManifest.xml
-f, --force-allOverwrites existing files during build (resources and sources)
-n, --net-sec-confAdds a generic Network Security Configuration file to the APK
-na, --no-apkDisables repacking of built files into a new APK
-nc, --no-crunchDisables crunching resource files during build (no automatic bitmap optimization)
-o, --output <FILE>Sets the name/path of the output APK (default: dist/{apkname}.apk)
-p, --frame-path <DIR>Sets the folder framework files are stored/read from

Empty Framework Directory Options (apktool empty-framework-dir {options}):

OptionDescription
-f, --forceForces deletion of the destination directory
-p, --frame-path <DIR>Sets the folder framework files are stored/read from

List Framework Directory Options (apktool list-frameworks {options}):

OptionDescription
-p, --frame-path <DIR>Sets the folder framework files are stored/read from

Install Framework Options (apktool if|install-framework {options}):

OptionDescription
-p, --frame-path <DIR>Sets the folder framework files are stored/read from
-t, --tag <TAG>Tags the installed framework file with TAG

Common Options (usable with any command):

OptionDescription
-v, --verboseVerbose output (includes log messages tagged FINE)
-q, --quietQuiet output

Basic Usage (Expected Output in Bash)

Decoding an APK:

$ apktool d SdkControllerApp.apk
I: Using Apktool 2.9.3 on SdkControllerApp.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
I: Loading resource table from file: /root/.local/share/apktool/framework/1.apk
I: Regular manifest package...
I: Decoding file-resources...
I: Decoding values */* XMLs...
I: Baksmaling classes.dex...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files...

Rebuilding the APK:

$ apktool b SdkControllerApp
I: Using Apktool 2.9.3
I: Checking whether sources has changed...
I: Smaling smali folder into classes.dex...
I: Checking whether resources has changed...
I: Building resources...
I: Building apk file...
I: Copying unknown files/dir...

Practical Examples with Output

Example 1 — Decode an APK with default options:

$ apktool d InsecureBankv2.apk
I: Using Apktool 2.9.3 on InsecureBankv2.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
I: Loading resource table from file: /root/.local/share/apktool/framework/1.apk
I: Regular manifest package...
I: Decoding file-resources...
I: Decoding values */* XMLs...
I: Baksmaling classes.dex...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files...

Example 2 — Force overwrite an existing decoded directory:

$ apktool d -f InsecureBankv2.apk
I: Using Apktool 2.9.3 on InsecureBankv2.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
I: Decoding file-resources...
I: Decoding values */* XMLs...
I: Baksmaling classes.dex...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files...

Example 3 — Decode without touching resources (source only):

$ apktool d -r InsecureBankv2.apk -o InsecureBankv2_nores
I: Using Apktool 2.9.3 on InsecureBankv2.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
I: Baksmaling classes.dex...
I: Copying assets and libs...
I: Copying original files...

Example 4 — Decode without disassembling dex files (resources only):

$ apktool d -s InsecureBankv2.apk -o InsecureBankv2_nosrc
I: Using Apktool 2.9.3 on InsecureBankv2.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
I: Decoding file-resources...
I: Decoding values */* XMLs...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files...

Example 5 — Inspect the decoded manifest for permissions:

$ cat InsecureBankv2/AndroidManifest.xml | grep uses-permission
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.READ_SMS"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.CAMERA"/>

Example 6 — Locate a smali file to patch (e.g., root detection):

$ find InsecureBankv2 -name "RootDetection*.smali"
InsecureBankv2/smali/com/android/insecurebankv2/RootDetectionActivity.smali

Example 7 — Rebuild the modified APK:

$ apktool b InsecureBankv2 -o InsecureBankv2_patched.apk
I: Using Apktool 2.9.3
I: Checking whether sources has changed...
I: Smaling smali folder into classes.dex...
I: Checking whether resources has changed...
I: Building resources...
I: Building apk file...
I: Copying unknown files/dir...

Example 8 — Build with debuggable flag enabled (useful for dynamic testing):

$ apktool b -d InsecureBankv2 -o InsecureBankv2_debuggable.apk
I: Using Apktool 2.9.3
I: Checking whether sources has changed...
I: Smaling smali folder into classes.dex...
I: Checking whether resources has changed...
I: Building resources...
I: Building apk file...

Example 9 — Install a custom OEM framework file (e.g., Samsung framework-res):

$ apktool if framework-res_samsung.apk
I: Framework installed to: /root/.local/share/apktool/framework/2.apk

Example 10 — Decode using an installed custom framework:

$ apktool d -p /root/.local/share/apktool/framework SamsungApp.apk
I: Using Apktool 2.9.3 on SamsungApp.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
I: Loading resource table from file: /root/.local/share/apktool/framework/2.apk
I: Decoding file-resources...
I: Decoding values */* XMLs...
I: Baksmaling classes.dex...

Example 11 — List installed frameworks:

$ apktool list-frameworks
Framework files found:
* /root/.local/share/apktool/framework/1.apk (framework-res.apk, tag: None)
* /root/.local/share/apktool/framework/2.apk (samsung, tag: samsung)

Example 12 — Empty (clean) the framework directory:

$ apktool empty-framework-dir -f
I: Removing: /root/.local/share/apktool/framework

Common Use Cases

Automation with Bash

The following script automates decoding, patching a target string in smali files, and rebuilding an APK in bulk across multiple files.

#!/bin/bash
# apktool_batch.sh - Batch decode, search, and rebuild APKs

INPUT_DIR="./apks"
OUTPUT_DIR="./decoded"
SEARCH_TERM="RootDetection"

mkdir -p "$OUTPUT_DIR"

for apk in "$INPUT_DIR"/*.apk; do
    name=$(basename "$apk" .apk)
    echo "[*] Decoding $name..."
    apktool d -f "$apk" -o "${OUTPUT_DIR}/${name}" -q

    echo "[*] Searching for '${SEARCH_TERM}' in smali..."
    matches=$(grep -rl "$SEARCH_TERM" "${OUTPUT_DIR}/${name}/smali" 2>/dev/null)

    if [ -n "$matches" ]; then
        echo "[+] Found matches in $name:"
        echo "$matches"
    else
        echo "[-] No matches found in $name"
    fi

    echo "[*] Rebuilding $name..."
    apktool b "${OUTPUT_DIR}/${name}" -o "${OUTPUT_DIR}/${name}_rebuilt.apk" -q
    echo "[+] Rebuilt: ${OUTPUT_DIR}/${name}_rebuilt.apk"
    echo "----------------------------------------"
done

Sample run:

$ chmod +x apktool_batch.sh
$ ./apktool_batch.sh
[*] Decoding InsecureBankv2...
[*] Searching for 'RootDetection' in smali...
[+] Found matches in InsecureBankv2:
decoded/InsecureBankv2/smali/com/android/insecurebankv2/RootDetectionActivity.smali
[*] Rebuilding InsecureBankv2...
[+] Rebuilt: decoded/InsecureBankv2_rebuilt.apk
----------------------------------------

Tips and Best Practices

Troubleshooting

ProblemCauseSolution
Can't find AndroidManifest.xmlCorrupted or non-standard APKVerify the APK is valid with unzip -l file.apk; try -f to force decode
Invalid config flags detected. Dropping resources.Malformed or obfuscated resource entriesRe-run decode with -f to force decode anyway, then manually inspect/fix before build
Build fails with brut.androlib.exceptions.AndrolibExceptionModified smali contains a syntax errorReview your edits for typos; validate smali syntax carefully, especially register counts
framework-res.apk not found errors on decodeCustom/OEM APK requires a vendor frameworkPull the vendor’s framework-res.apk from the device via adb pull and install it with apktool if
Rebuilt APK won’t install (INSTALL_PARSE_FAILED_NO_CERTIFICATES)APK was not signed after rebuildSign the APK using apksigner sign --ks debug.keystore output.apk
Rebuilt APK crashes immediately-m (match-original) was used, breaking rebuild compatibilityAvoid -m unless you only need to inspect files; do not use it if you intend to rebuild
apktool: command not foundApktool not installed or not in PATHReinstall with sudo apt install apktool or verify /usr/local/bin/apktool is executable and in $PATH

References

Exit mobile version