Phase 1: Static Reconnaissance and Framework Triage
Before attempting to decompile an application, a security engineer must identify the technological stack of the target binary. Modern Android applications are no longer strictly Java or Kotlin; they are frequently built using cross-platform frameworks, compilation environments, or commercial packers which fundamentally alter how code is reversed.
1. Fingerprinting and Protection Detection
The initial step uses static binary analysis tools like APKiD to inspect the APK file headers, manifest attributes, and compilation signatures. This check yields three critical pieces of information: * Compilation Source: Identifies if the application is written in standard JVM languages (Java/Kotlin), compiled directly to native code via Ahead-of-Time engines (like Flutter's Dart VM or Unity's IL2CPP), or packaged as a hybrid web application (React Native, Cordova). * Obfuscation Detection: Detects signatures of renaming obfuscators (ProGuard, R8) or control-flow obfuscators (Obfuscator-LLVM for native code). * Packing and Protection: Detects if the application is wrapped in a commercial packer or digital rights management (DRM) shield (e.g., DexGuard, Arxan). If a packer is detected, standard decompilers will only see a small bootstrap stub, meaning the actual application payload must be extracted from memory during dynamic execution.
2. Basic Unpacking and Decompilation
If the APK is unprotected, the analyst uses binary translation tools:
* Apktool: Disassembles the application’s resources, layouts, asset folder, and translates the Dalvik Executable (.dex) files into Smali assembly code. This is necessary because some configuration files (like the manifest) are compiled into binary XML format and must be parsed back into readable XML.
* JADX: Decompiles the Dalvik bytecode (classes.dex) back into standard Java source code. The GUI allows the analyst to trace cross-references (where a function is declared versus where it is called) and perform global text searches.
Phase 2: Configuration Auditing & Attack Surface Mapping
With the application's resources and code decompiled, the analyst maps out the attack surface by reviewing configurations and exposed components.
1. AndroidManifest.xml Analysis
The manifest file is the central blueprint for the operating system to interact with the application. The analyst audits this file for security configuration errors:
* Component Exposure: The engineer catalogs all components (Activities, Services, Broadcast Receivers, Content Providers) that have the attribute android:exported="true". This attribute allows any other application on the device to launch or query that component without user permission, opening paths for unauthorized access or data leakage.
* Data Backups: If android:allowBackup is set to true, the private data directory of the application can be extracted via the Android Debug Bridge (ADB) on a device with USB debugging enabled, bypassing sandboxing.
* Cleartext Policy: Checking android:usesCleartextTraffic to determine if the application is allowed to send unencrypted HTTP traffic, exposing users to local interception attacks.
* Network Security Configuration: Locating the referenced network_security_config.xml in the resources. Analysts check if the configuration trusts user-installed certificates (which simplifies traffic interception) or if it relies strictly on pre-defined Certificate Authority (CA) chains.
2. Secrets and Endpoint Extraction
Using static analysis, engineers scan the decompiled code and resources for sensitive credentials. This is often automated using pattern-matching regular expressions and entropy-based scanners targeting: * API keys for cloud environments (AWS, GCP, Azure), databases (Firebase), or third-party gateways. * Hardcoded authentication tokens, staging passwords, or administrative credentials. * Staging, development, or internal server URLs and IP addresses, which can expose hidden backend endpoints not meant for public access.
Phase 3: Setting Up the Dynamic Analysis Environment
Because modern applications protect their network traffic and run runtime checks, static analysis is rarely sufficient. A dynamic environment allows the analyst to run, inspect, and modify the application in real-time.
1. Rooting and Runtime Hooking
Dynamic analysis is executed on a rooted physical device or a virtualized system (like Genymotion). The security engineer provisions the device to allow deep system-level inspection: * Systemless Rooting (Magisk / KernelSU): Grants superuser access to the host machine without modifying the device's read-only system partitions. * Frida Server: Installed on the device, this daemon acts as an agent. It injects a JavaScript runtime (QuickJS) into the memory space of the target application, allowing the engineer to hook and modify Java classes or native C functions on the fly.
2. Intercepting Encrypted Traffic (SSL Pinning Bypass)
Most secure applications enforce SSL/TLS Pinning, meaning the application ignores system-level certificates and only trusts specific keys or certificates compiled directly into the binary. This blocks intercept proxies like Burp Suite or mitmproxy from reading the traffic.
To bypass this:
* Dynamic Hooking: The analyst uses Frida to locate and hook common trust validation classes in the application memory (such as OkHttp's CertificatePinner, the default Android TrustManager, or Conscrypt's TrustManagerImpl).
* Overriding Logic: The hook dynamically intercepts the certificate checking function during the TLS handshake, replacing the validation logic so that it always returns a positive validation, regardless of the proxy certificate presented. This allows the interception proxy to decrypt and read all API requests and responses.
3. Defeating Client-Side Protections
Many apps include defenses to detect rooted devices or emulators:
* Environmental Checks: The application checks for superuser binaries (like /system/bin/su), open ports matching the Frida daemon, or device properties associated with emulators (e.g., ro.hardware=goldfish).
* Bypassing via Frida: The analyst writes Frida scripts to intercept calls to filesystem check APIs (like java.io.File.exists()) and system property queries (like SystemProperties.get()), modifying the return values so the application believes it is running on a standard, non-rooted device.
Phase 4: Runtime Vulnerability Hunting and Exploitation
With a bypassed and intercepted environment, the analyst interacts with the application to identify dynamic and logic-based vulnerabilities.
1. Local Storage Auditing (Sandbox Inspection)
The analyst performs actions in the app (such as logging in, searching, or making purchases) and then inspects the application's private directory (/data/data/[package_name]/) on the device:
* SharedPreferences: Checking the XML files for raw authentication credentials, session tokens, or personal identifiable information (PII).
* Local Databases: Auditing SQLite databases. If the developer attempted local encryption but stored the encryption key statically in the source code or resource assets, the encryption can be bypassed.
* Temporary files / Caches: Verifying if sensitive images, PDFs, or network responses are cached unencrypted on the filesystem.
2. Inter-Process Communication (IPC) Exploitation
Using the list of exported components mapped in Phase 2, the analyst attempts to send malicious intents (signals) using the Android Debug Bridge (adb shell am commands) or customized testing apps:
* Intent Redirection: Forcing a public, exported activity to launch a private, unexported activity on its behalf, allowing the analyst to bypass authentication screens or local pin locks.
* Content Provider Injection: If a content provider is exported and fails to parameterize queries, the analyst attempts to run SQL injection or Directory Traversal payloads against the custom Content URIs (e.g., content://com.target.provider/) to extract databases or access private system files.
3. WebView Auditing
WebViews embed browser instances within the application. Analysts verify:
* Insecure JavaScript Interfaces: If the app exposes custom Java objects to JavaScript inside the WebView (addJavascriptInterface), any Cross-Site Scripting (XSS) vulnerability on the loaded web page can be leveraged to execute code within the context of the native app.
* Insecure File Access: If setAllowFileAccess or setAllowUniversalAccessFromFileURLs is enabled, malicious JavaScript running in a WebView can read local sandbox files and transmit them to external servers.
4. API and Business Logic Verification
Through the interception proxy, the analyst performs standard web security testing against the backend APIs: * Broken Object Level Authorization (IDOR): Swapping user identifiers in API requests to see if the server returns other users' data without validating the current session token's permissions. * Business Logic Manipulation: Attempting to alter pricing, parameters, or states in API payloads before they are encrypted or sent by the application.