← Back to list

Reverse-Engineering Android APKs with JADX

In this article, we explore how to reliably decompile Android APKs into readable Java/Kotlin, connect code to resources, and sanity-check…

PI in Neural Engineer · 2025-12-11 18:59 · 50 claps · 3.3 min read paywalled
#jadx #reverse-engineering #decompiler #software-development #software
Open on Medium ↗
Wiki topics: 📱 · Mobile Development

Reverse-Engineering Android APKs with JADX

In this article, we explore how to reliably decompile Android APKs into readable Java/Kotlin, connect code to resources, and sanity-check what I recover — even when obfuscation fights back. You will learn a fast, DEX-native path with JADX, a dex2jar → CFR fallback, and a handful of reverse-engineering tricks that make digging through mobile artifacts faster.

Prereqs

  • Java 11+ on your PATH (java -version).
  • apktool and unzip for resource decoding; adb/zipalign only if you plan to repack.
  • macOS/Linux commands shown; swap : for ; on Windows classpaths.

Peek Inside the APK First

Before any decompiler work, I always peek at the ZIP to see manifests, DEX files, and assets:

unzip -l app-release.apk | head

That quick glance tells me how many classes*.dex files exist and whether extra resources or native libraries are bundled.

Fast Path: Use JADX (DEX-Aware)

Install the CLI

# macOS
brew install jadx  # or download the release zip and add bin/jadx to PATH

# Linux (Debian/Ubuntu): 
sudo apt-get install jadx

Decompile to Sources

jadx -d out-jadx app-release.apk
find out-jadx -name '*.java' | head

JADX works directly on DEX opcodes (no dex2jar hop), so control flow, switch maps, and Kotlin metadata stay intact. It emits Java/Kotlin-like sources you can navigate and simultaneously decodes AndroidManifest.xml and resources into readable XML so layout IDs and strings map back to code.

Browse with the GUI

jadx-gui app-release.apk

The GUI view is great for quickly hopping between packages, searching strings, and inspecting control flow graphs.

Inspect Resources Alongside Code

APK behavior is frequently driven by resources — layouts, strings, and bundled assets — so I read those next to the code to understand UI flows, feature flags, and network endpoints:

# macOS
brew install apktool ripgrep
# Linux (Debian/Ubuntu): 
sudo apt-get install apktool ripgrep

apktool d app-release.apk -o out-apktool
rg --no-heading --line-number 'apiKey' out-apktool/res out-jadx
  • apktool d decodes resources, 9-patch images, and AndroidManifest.xml.
  • Searching across out-apktool (resources) and out-jadx (code) lets me map IDs and strings back to the exact call sites.

When to Bring in CFR (via dex2jar)

JADX is my default, but CFR is handy when I want a second opinion that stays closer to raw bytecode or when JADX restructures aggressive control flow. Install dex2jar if you do not have it:

# macOS
brew install dex2jar
# Linux (Debian/Ubuntu)
sudo apt-get install dex2jar
unzip app-release.apk 'classes*.dex' -d tmp/apk-dex

d2j-dex2jar /tmp/apk-dex/classes.dex -o tmp/classes.jar

java -jar cfr.jar tmp/classes.jar --outputdir out-cfr

The CFR output can be compared against JADX output to triangulate intent and spot decompiler artifacts.

Handling Obfuscation

Obfuscation deliberately makes bytecode harder to read by renaming identifiers, flattening control flow, inlining helpers, and hiding entry points. JADX handles common Android/R8 patterns well: it is DEX-native, understands switch maps, follows Kotlin metadata, and can auto-deobfuscate short names. When that is not enough, I pivot to smali (the human-readable assembly for DEX bytecode) or a second decompiler view to keep intent clear.

ProGuard/R8 typically shrinks class and method names to terse symbols like a, b, or c, but it cannot easily hide string literals, URLs, intent actions, or JNI method signatures. I use rg across both out-jadx and out-apktool to cluster related features, locate entry points, and trace where important strings are used. Then I enable JADX deobfuscation (--deobf, --deobf-min 3) to stabilize symbol names so the codebase reads consistently while I analyze it.

Control-flow tricks show up as opaque predicates, flattened switches, or reordered blocks that make Java output look illogical. When I see suspicious branches or nonsensical conditions in JADX, I open the corresponding smali (out-jadx/sources/**/*.smali) to follow the exact register-level flow and confirm what actually executes. If JADX restructures too aggressively, I run dex2jar + CFR for a second perspective and diff the two outputs around the hot code paths to triangulate intent.

Native code deserves its own sweep: I look for lib/*.so, check architectures with file lib/arm64-v8a/libfoo.so, and skim strings output to spot exported symbols or hardcoded endpoints. Then I cross-reference the JNI method names I see in out-jadx to understand how Java hands data into the native layer and to uncover reflective or dynamically loaded entry points that might otherwise stay hidden.

Validate What You Recovered

  • Compare manifest components (activities, services, receivers) against decompiled code to ensure every entry point is accounted for.
  • Grep for secrets, URLs, file paths, and analytics beacons; verify suspicious logic in smali if names are obfuscated.
  • If you plan to patch/rebuild, use apktool b, re-sign with apksigner, and test on an emulator before trusting changes.

Wrap-Up

Decompiling Android apps is smoother when you pair a DEX-native decompiler with resource awareness and a backup view. By starting with JADX, skimming resources via apktool, and pulling in CFR when control flow looks off, you can move from APK to understandable source quickly — even with obfuscation in play.

If you found this helpful, consider following my profile and signing up for the newsletter . Have thoughts or questions? Share them in the comments below

REFERENCES


메타데이터
post_id
ebded67ceb8f
slug
reverse-engineering-android-apks-with-jadx-ebded67ceb8f
url
https://blog1.neuralengineer.org/reverse-engineering-android-apks-with-jadx-ebded67ceb8f
canonical_url
https://blog1.neuralengineer.org/reverse-engineering-android-apks-with-jadx-ebded67ceb8f
author_url
https://medium.com/@pi45757
status
ok
fetched_at
2026-06-17 15:18:21