Good Carder
Professional
- Messages
- 751
- Reaction score
- 493
- Points
- 63
Introduction: Why Mobile Apps Have Become Fortresses Being Stormed from Within
A modern mobile banking app isn't just a user-friendly interface. It's a multi-layered fortress: code obfuscation, DEX integrity checking, root, emulator, and debugger detection, SSL pinning, and hundreds of other mechanisms. A researcher's job isn't to crack the fortress from the outside, but to convince it that you're part of the solution. To do this, you need to not only understand the security but also be able to bypass it by modifying the app itself or intercepting its calls on the fly.Part 1: APK Unpacking and Initial Analysis
1.1. APKTool: Decoding resources and smali code
The first step in examining any Android app is unpacking the APK. APKTool operates at a lower level than decompilers: it extracts all resources, converts binary XML into a readable format, and converts DEX files to smali — assembly for the Dalvik virtual machine. This allows you not only to view but also modify the app's code and then rebuild it.
Code:
# Basic unpacking command
apktool d target.apk -o target_unpacked/
# Rebuilding after modification
apktool b target_unpacked/ -o target_modified.apk
1.2. JADX: Decompilation into Readable Java/Kotlin Code
While APKTool produces assembler, JADX (especially JADX-GUI) decompiles DEX directly into Java/Kotlin, which is much easier to understand business logic.Practical approach:
- Primary reconnaissance via JADX – quick analysis of package structure, search for key classes, string constants (URL, API, flags).
- Deep analysis with APKTool - if JADX fails (obfuscation, custom loaders), unpack APKTool and examine smali.
1.3. Obfuscation and early protection signature detection
After unpacking, we look at the structure:- Several DEX files (classes2.dex, classes3.dex) - some of the logic may be moved to separate modules.
- Heavily obfuscated class names (aa, bbc) are a sign of ProGuard at work.
- Native libraries (lib/armeabi-v7a/*.so) - critical logic (cryptography, integrity checks) is often moved to C/C++ code.
The next step is to bypass the security mechanisms themselves. To do this, you first need to understand how they work.
Part 2. Obfuscation and the First Barrier: ProGuard / DexGuard
2.1. ProGuard — Android Obfuscation Standard
ProGuard is an open-source tool built into Android Studio. It does four things: compression, optimization, obfuscation, and code pre-checking. Obfuscation renames classes, methods, and fields to short, unreadable names (aa, bb), making the logic difficult to understand.2.2. DexGuard is a commercial beast
DexGuard is a paid, more aggressive solution. In addition to standard obfuscation, it adds string encryption, obfuscated code injection into resources, reflection calls, and integration with native libraries.2.3. Obfuscation Bypass Methods
- Analysis via mapping file - If the application is yours or you've found a mapping.txt file (often in leaks), ProGuard offers ReTrace to reconstruct stack traces.
- Dynamic analysis – obfuscation hinders static analysis but doesn't obscure the logic at runtime. Hooks in key APIs reveal the actual values of parameters, regardless of their names.
- Working with encrypted strings — DexGuard can store sensitive strings in encrypted form and decrypt them at runtime. Encrypted strings are decrypted at the point of use. A hook to the decryption point will reveal the original string.
2.4. A Practical Example of Login Interception
Let's say an application calls abcx(str) to verify a password. The method is obfuscated, but dynamic analysis (Frida) reveals that it sends a POST request to https://api.bank.com/login. After decompiling, you look for the string where this URL is initialized — this is often the entry point for further analysis.Part 3. Dynamic Analysis: Frida and Objection
Static analysis isn't enough — especially when obfuscation and anti-tamper checks only work at runtime. This is where real-time instrumentation comes in.3.1. Frida: The Swiss Army Knife of Dynamic Instrumentation
Frida injects the V8 (Chrome) engine into the target process and allows arbitrary JavaScript code to be executed directly in the application's memory to intercept, modify, and analyze calls. It runs on rooted devices via frida-server (a background process that accepts commands from your computer), or on unrooted devices via frida-gadget injected into the APK.Device installation:
Bash:
# Download frida-server for your architecture and run
adb push frida-server /data/local/tmp/
adb shell chmod +x /data/local/tmp/frida-server
adb shell /data/local/tmp/frida-server &
Basic script for call interception:
JavaScript:
Java.perform(function() {
var MainActivity = Java.use("com.bank.MainActivity");
// Intercept the login method
MainActivity.login.implementation = function(username, password) {
console.log("[*] Login called with: " + username + ", " + password);
// Modify the response
var result = this.login(username, password);
console.log("[*] Result: " + result);
return true; // always successful
};
});
Running the script:
Bash:
frida -U com.bank.app -l hook_login.js
3.2. Objection: runtime exploration toolkit
Objection is a wrapper around Frida that automates common tasks and provides an interactive environment for exploring applications at runtime.Objection allows you to:
- Explore loaded classes - view hierarchy, methods, fields directly at runtime.
- Bypass SSL pinning with one command: android sslpinning disable (standard implementations).
- Bypass root detection: android root disable.
APK patching for unrooted devices:
Bash:
objection patchapk --source original.apk --target patched.apk --use-aapt2
3.3. Advanced scripts for bypassing detection
When standard commands aren't enough, custom Frida scripts are written. They:- Identify detection methods through static or dynamic analysis.
- Native checks are hooked —if detection is implemented in C/C++, standard Java hooks won't help. You need to hook functions at the native code level.
- They are injected before anything else to intercept checks at application startup.
An example of a complex Frida script that bypasses root, emulator, and SSL pinning simultaneously is provided by the Frida Universal Android Hardening Bypass repository.
Part 4. Disguising the Environment: Magisk and LSPosed
4.1. Magisk – System Root
Magisk makes changes to the boot partition without affecting the system partition. This allows the app to "think" the system is untouched, even if you have root access. After installing Magisk, the settings include:- Hiding the Magisk app - packaging with a random package name.
- Enabling Zygisk is a mechanism for running stealth code directly in the Zygote process.
- Clear DenyList - a list of applications from which you want to hide root.
- Disabling forced application of DenyList (Enforce DenyList) - to avoid breaking modules.
4.2. LSPosed — Next-Generation Xposed Framework
LSPosed allows you to intercept and modify application behavior at the Java level. Installation is via a Magisk ZIP module.BypassRootCheckPro is a module for LSPosed that intercepts not only Java root checks but also native (C/C++) calls, working where traditional methods fail.
4.3. Other modules for camouflage
- TrickyStore — helps bypass Magisk checks by analyzing keys and certificates.
- DeviceSpoofLab — spoofing device identifiers (IMEI, Android ID, MAC addresses).
- Shamiko is a module for deeper concealment of Magisk traces.
4.4. Combination for total invisibility
For maximum concealment, the following stack is used: LSPosed (for Java hooks) → Magisk + Shamiko (to hide root) → DeviceSpoofLab (to spoof identifiers) → BypassRootCheckPro (to intercept specific banking checks).Part 5. Anti-Tamper Mechanisms and Their Bypass
5.1. DEX Integrity Check
The app calculates a hash (checksum) of its DEX files each time it's launched and checks it against a "reference" value hardcoded into the app's code or native library. Substituting classes after unpacking APKTool will change the hash, and the check will fail.Bypass methods:
- Patching the check itself means finding the place in the code where the hash is calculated and replacing it with one that always returns "success".
- Substitute files after verification - download the patch after the integrity check is complete.
- Bypass via Frida - intercept a call that returns true regardless of the actual hash.
5.2. Application signature verification
The app compares its signature with the reference signature via PackageManager.getPackageInfo(). If the signature doesn't match, the app refuses to run.Workaround: patch the verification via Frida, intercept the getPackageInfo call, and return the reference signature instead of the real one. Alternatively, re-sign the APK with the same key as the original (if known). However, more often than not, it's the verification that's patched.
5.3. Debugger detection
android.os.Debug.isDebuggerConnected() returns true if a debugger (such as Android Studio or jdb) is connected to the application. Many banking apps check this flag and crash if it is.Workaround: Frida hook – replace the return value with false.
5.4 Native Level: Checks in C/C++
The most serious checks are moved to native libraries (.so). This is because they are more difficult to analyze and modify. Such checks may include:- ptrace - check if a debugger is attached via the ptrace system call.
- /proc/self/maps — scanning for frida, xposed, substrate.
- Scanning processes for the presence of frida-server, gdb, android_server.
- Checking system properties - ro.kernel.qemu (emulator), ro.debuggable (debug build), etc.
These checks remain undetected by Java hooks.
Bypassing native checks:
- Hooks at the native code level - using Frida on the C-API (Interceptor.attach on symbols in .so).
- Patching the .so libraries themselves — using IDA Pro or Ghidra: find the verification function, modify the return instructions, and rebuild the APK.
- Changing values in /proc and system properties using Magisk modules.
Part 6. Final Checklist for Researching a Protected Application
- Unpacking and static analysis. Decompilation via JADX-GUI; in cases of severe obfuscation, APKTool unpacking and smali analysis. Detection of obvious root/emulator checks, URL and API endpoint search.
- Environment setup. Rooted device with Magisk + Shamiko + LSPosed. Disable Enforce DenyList, enable Zygisk. Install BypassRootCheckPro and DeviceSpoofLab modules.
- Dynamic analysis via Frida/Objection. SSL pinning bypass (sslpinning disable on Android). Root detection bypass (root disable on Android). Custom scripting if standard methods fail.
- Working with native checks. Identifying native functions by analyzing .so files in IDA/Ghidra. Writing Frida scripts to hook native code. Patching .so files and rebuilding APKs if necessary.
- Bypass anti-tamper. Bypasses DEX integrity and signature checks via Frida hooks on the relevant functions. Ensures that the application doesn't crash after modification.
- Simulate user behavior. After completely bypassing checks, automate actions (login, payments) via Appium or UI Automator to scale research.
Conclusion: Emulation is not hacking, but dancing on the edge.
Emulating mobile banking apps isn't a technological trick, but a constant arms race between defenders and researchers. Obfuscation, anti-tampering, emulator detection, integrity checks — all of this becomes transparent if you know where to look and which tools to use.Today's banking apps check not only root, but also the fact of system modification, the presence of dynamic instrumentation frameworks, the integrity of DEX, and signatures. Bypassing each mechanism requires an understanding of how it works and the ability to use Frida, Objection, or Magisk/LSPosed at the right moment.
Three key takeaways:
- Static analysis isn't enough. Obfuscation and native checks hide logic until runtime. Without Frida or similar tools, it's impossible to understand the actual behavior of an application.
- Modern bypass is a multi-layered emulation. You need to be not just a rooted device, but a convincing replica of a clean, unmodified phone. Each layer of protection requires its own layer of disguise.
- Native code is the last bastion. The most sophisticated checks are always moved to C/C++ .so libraries. Bypassing them requires either extensive reverse engineering or specific hooks for system calls and memory access.
A quick one-line reminder:
"APKTool will unpack, JADX will show, Frida will intercept, Objection will bypass, Magisk will hide, LSPosed will replace. Each layer of protection requires its own tool, but without understanding the app's logic, it's just a bunch of commands. Emulation isn't hacking, it's the art of being invisible."
