The attacker's toolkit

Reverse engineering an Android app does not require deep expertise or expensive tools. The entire toolkit is free and well-documented. This is what makes mobile app security fundamentally different from server-side security—your code ships to the attacker's machine.

jadx

Dalvik-to-Java decompiler. Opens an APK and produces readable Java source code. GUI version allows browsing classes, searching strings, and cross-referencing calls. The primary static analysis tool.

apktool

Decodes resources, manifest, and smali (Dalvik assembly). Essential for understanding permissions, exported components, and resource files. Can also rebuild modified APKs for re-signing and testing.

Frida

Dynamic instrumentation toolkit. Injects JavaScript into running processes, hooks functions at runtime, intercepts method calls, modifies return values, and bypasses security checks. The most powerful dynamic analysis tool available.

Step 1: obtaining and decompiling the APK

The attacker pulls the APK from Google Play using tools like apkeep or from their device with adb shell pm path com.yourapp followed by adb pull. There is no way to prevent this—once the app is published, the binary is public.

Running jadx -d output/ target.apk decompiles the Dalvik bytecode to Java source. The process takes seconds even for large apps. The attacker now has a browsable, searchable source code tree.

Step 2: what is immediately visible

API endpoints and base URLs

Every API URL your app communicates with is embedded in the binary as a string constant. Searching for https:// or /api/ reveals your entire backend API surface. The attacker now knows every endpoint to probe for authorization vulnerabilities, injection flaws, and business logic abuse. Even with obfuscation, string constants are preserved.

Hardcoded secrets

Searching for patterns like sk_live_, FLWSECK-, Bearer, api_key, password, and secret reveals embedded credentials. In our pentests of Nigerian fintech apps, we find hardcoded secrets in approximately 40% of first-time assessments. These include payment gateway keys, Firebase configs, and internal service credentials.

Business logic

Transaction validation rules, fee calculations, referral bonus logic, discount codes, and rate limiting thresholds—all visible in decompiled code. If your app enforces transaction limits client-side ("maximum transfer: ₦500,000"), the attacker sees that check and knows to bypass it by calling the API directly without that constraint.

Authentication flow

The entire authentication implementation is visible: how tokens are generated, where they are stored, what headers are used, how biometric checks are implemented. If biometric auth uses a simple boolean callback, the attacker knows exactly which function to hook with Frida to bypass it.

What We Typically Find

The string search that reveals everything

In a recent assessment of a Nigerian digital banking app, a single grep across the decompiled source for the word "secret" returned: the Paystack secret key, an internal admin API key, a hardcoded AES encryption key used for local data, and debug credentials for a staging environment that shared a database with production. Total analysis time: four minutes.

Step 3: dynamic analysis with Frida

Static analysis shows the code. Dynamic analysis lets the attacker interact with the running app. Frida is the standard tool.

With a rooted Android device or emulator, the attacker installs the Frida server, attaches to the running app process, and injects JavaScript hooks. Common attacks:

How to defend: layered protection

You cannot prevent reverse engineering entirely. You can make it expensive, time-consuming, and detectable.

Code obfuscation

Enable R8 (Android's built-in shrinker/obfuscator) with aggressive rules. For Flutter, use --obfuscate --split-debug-info. For React Native, compile with Hermes. These measures rename classes and methods to meaningless identifiers, making the decompiled code harder to navigate.

String encryption

Use commercial tools like DexGuard or open-source solutions to encrypt string constants at build time and decrypt them at runtime. This prevents simple string searches from finding API URLs and configuration values. Not foolproof (the decryption runs in the app), but significantly raises the analysis bar.

Anti-tampering and integrity checks

Verify the app's signature at runtime to detect repackaged/modified APKs. Check binary integrity to detect instrumentation frameworks like Frida (which injects a shared library into the process). Use Google's Play Integrity API for device attestation.

Server-side enforcement

This is the most important defence: never trust the client. All business logic, authorization checks, rate limits, and transaction validation must be enforced server-side. The client can be modified; the server cannot. See our guide on securing fintech APIs for server-side best practices.

Want to see what an attacker sees when they decompile your app? We will reverse engineer it, extract every exposed secret and vulnerability, and deliver a detailed report with fix priorities.

Get a Mobile App Security Assessment

The mindset shift

Stop thinking of your APK as protected software. Think of it as published source code. Design your architecture with the assumption that the attacker has read every line. Put your secrets on the server, enforce your rules on the server, and use the mobile app as an untrusted client. This is the only approach that survives reverse engineering.

Related reading

Blog: Hardcoded API Keys in Mobile Apps · Securing Flutter & React Native Apps · iOS vs Android Security

Guides: Mobile App Pentest Nigeria · Pentest Tools & Methodology · Web App Pentest Nigeria

Services: Penetration Testing · API Security · Vulnerability Assessment

Frequently asked questions

{faqs.map((faq) => (
{faq.q}

{faq.a}

))}