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:

  • Inspecting the true AndroidManifest.xml (permissions, exported components, intent filters) in readable form, since the manifest inside a compiled APK is stored in an unreadable binary XML format.
  • Patching application logic at the Smali level — for example, disabling a root-detection check, removing SSL pinning enforcement, or inserting a Frida Gadget for instrumentation on a non-rooted device.
  • Extracting and modifying string resources, layouts, and drawables.
  • Rebuilding and re-signing a modified APK for redeployment during testing.

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

  • Manifest and permission auditing – Reading the true, decompiled AndroidManifest.xml to identify exported activities/services/receivers, dangerous permissions, and deep link intent filters that could be attack surfaces.
  • Patching applications for security testing – Modifying smali code to disable root detection, certificate pinning, or anti-debugging checks, then rebuilding and re-signing the APK for dynamic testing on a test device.
  • Injecting a Frida Gadget – Decoding the APK, adding the libfrida-gadget.so file and a small smali loader call, and rebuilding, to enable Frida-based instrumentation on non-rooted devices.
  • Resource and localization review – Extracting res/values/strings.xml and other resource files to search for hardcoded API keys, backend URLs, or debug flags left in the app.
  • Malware sample static triage – Quickly decoding a suspicious APK to inspect its manifest and smali logic without needing to fully compile/run the sample.

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

  • Always use -f when re-decoding an APK you have decoded before, to avoid mixing stale files from a previous decode with the new one.
  • Use -r (no-res) when you only need to inspect or patch smali code — it decodes significantly faster since it skips resource decompilation.
  • Use -s (no-src) when you only need to inspect resources like strings, layouts, or the manifest, and don’t need smali — this also speeds up decoding.
  • After building a modified APK, remember it must be signed before it can be installed (Apktool does not sign APKs). Use apksigner or jarsigner with a debug or self-signed keystore.
  • Keep a dist/ directory convention in mind — by default, apktool b writes output to <project>/dist/<name>.apk unless -o is specified.
  • When targeting apps that reference OEM-specific resources (common with Samsung, Xiaomi/MIUI, Huawei devices), install the correct vendor framework APK with apktool if before decoding, or you will see “resource not found” errors.
  • Match the --api-level used in build to the original app’s minSdkVersion/targetSdkVersion where possible to avoid Smali verification issues after rebuilding.

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

  • Apktool Official Website: https://apktool.org/
  • Apktool CLI Parameters Documentation: https://apktool.org/docs/cli-parameters/
  • Apktool GitHub Repository: https://github.com/iBotPeaches/Apktool
  • Kali Linux Tools – Apktool: https://www.kali.org/tools/apktool/
  • OWASP MASTG – Static Analysis on Android: https://mas.owasp.org/MASTG/Android/0x05c-Reverse-Engineering-and-Static-Analysis/
Total
1
Shares

Leave a Reply

Previous Post
MobSF: Complete Guide to Mobile Application Security Testing and Malware Analysis Using Kali Linux

MobSF: Complete Guide to Mobile Application Security Testing and Malware Analysis Using Kali Linux

Next Post
JADX: Complete Guide to Android APK Decompilation and Source Code Analysis Using Kali Linux

JADX: Complete Guide to Android APK Decompilation and Source Code Analysis Using Kali Linux

Related Posts