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:
| Option | Description |
|---|---|
-advance, --advanced | Dumps out advanced usage output |
-version, --version | Outputs the current software version |
Decoding Options (used with apktool d file.apk {options}):
| Option | Description |
|---|---|
-api, --api-level <API> | Sets the API level used in generated smali files (defaults to targetSdkVersion) |
-b, --no-debug-info | Prevents baksmali from writing out debug info (.local, .param, .line, etc.) |
-f, --force | Forces deletion of the destination directory and forces decoding of AndroidManifest.xml regardless of options |
-m, --match-original | Matches 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-res | Prevents decompiling resources; keeps resources.arsc intact |
-resm, --resource-mode <mode> | Sets mode for unresolved resources: remove (default), dummy, or keep |
-s, --no-src | Prevents 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}):
| Option | Description |
|---|---|
-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-original | Copies the original AndroidManifest.xml and META-INF |
-d, --debug | Adds debuggable="true" to AndroidManifest.xml |
-f, --force-all | Overwrites existing files during build (resources and sources) |
-n, --net-sec-conf | Adds a generic Network Security Configuration file to the APK |
-na, --no-apk | Disables repacking of built files into a new APK |
-nc, --no-crunch | Disables 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}):
| Option | Description |
|---|---|
-f, --force | Forces 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}):
| Option | Description |
|---|---|
-p, --frame-path <DIR> | Sets the folder framework files are stored/read from |
Install Framework Options (apktool if|install-framework {options}):
| Option | Description |
|---|---|
-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):
| Option | Description |
|---|---|
-v, --verbose | Verbose output (includes log messages tagged FINE) |
-q, --quiet | Quiet 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.sofile 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.xmland 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
-fwhen 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
apksignerorjarsignerwith a debug or self-signed keystore. - Keep a
dist/directory convention in mind — by default,apktool bwrites output to<project>/dist/<name>.apkunless-ois specified. - When targeting apps that reference OEM-specific resources (common with Samsung, Xiaomi/MIUI, Huawei devices), install the correct vendor framework APK with
apktool ifbefore decoding, or you will see “resource not found” errors. - Match the
--api-levelused in build to the original app’sminSdkVersion/targetSdkVersionwhere possible to avoid Smali verification issues after rebuilding.
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
Can't find AndroidManifest.xml | Corrupted or non-standard APK | Verify the APK is valid with unzip -l file.apk; try -f to force decode |
Invalid config flags detected. Dropping resources. | Malformed or obfuscated resource entries | Re-run decode with -f to force decode anyway, then manually inspect/fix before build |
Build fails with brut.androlib.exceptions.AndrolibException | Modified smali contains a syntax error | Review your edits for typos; validate smali syntax carefully, especially register counts |
framework-res.apk not found errors on decode | Custom/OEM APK requires a vendor framework | Pull 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 rebuild | Sign the APK using apksigner sign --ks debug.keystore output.apk |
| Rebuilt APK crashes immediately | -m (match-original) was used, breaking rebuild compatibility | Avoid -m unless you only need to inspect files; do not use it if you intend to rebuild |
apktool: command not found | Apktool not installed or not in PATH | Reinstall 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/