DEV Community

Cover image for Improving Binary Security in Mobile Application: A Deep Dive into Obfuscation
Yusuff Jokanola O.
Yusuff Jokanola O.

Posted on

Improving Binary Security in Mobile Application: A Deep Dive into Obfuscation

Introduction

Mobile applications increasingly serve as the gateway to critical business operations, making them high-value targets for reverse engineering and code tampering. This threat is formally recognized in the OWASP Mobile Top 10 (2024) risks. This category highlights M7: Insufficient Binary Protection enable attackers to extract secrets, reverse engineer proprietary logic, and repackage apps for malicious use.

In the context of React Native, this threat is especially relevant because the application’s core logic is bundled in JavaScript and then compiled into Hermes bytecode for performance optimization. While the use of Hermes offers a foundational layer of obfuscation through bytecode compilation, it is not a foolproof defense. Its output can still be decompiled or analyzed by determined adversaries (though advanced analysis techniques are beyond the scope of this article). Crucially, React Native apps also include several native files (Java/Kotlin on Android) and metadata that can reveal insights about the app’s internal structure, such as all the third-party packages in use. This information, when combined with the decompiled Hermes bytecode, can help attackers better understand the app’s architecture, identify potential weaknesses, and target specific vulnerabilities.

In this article, we’ll explore how Android reverse engineering affects React Native applications, why it remains a top-tier security concern, and outline key mitigation strategies—with a focus on implementing code obfuscation as an essential defense layer.

Prerequisites for Analysis

To practically understand and test the security posture of your application against reverse engineering, you must have the production-ready Android Package Kit (APK) file.

For React Native (Bare Workflow)

You will typically generate the APK directly using Android Studio or the command line.

For Expo (Managed Workflow)

The .apk file is produced after a release build (eas build --platform android). If you receive an Android App Bundle (.aab) file from your build service or Google Play Console, you must use the Google-provided bundletool to extract a Universal or device-specific .apk for analysis.

bundletool can be used to Converts .aab to .apk files for testing.

How Attackers/CyberSecurity Analyst Decompile Your App

Disclaimer: This section is for educational purposes only, intended to help developers understand and mitigate attack vectors. The techniques described are mimic standard practices used by security analysts and penetration testers to assess application security.

The standard process for reverse engineering an Android application involves several key steps, primarily centered around a tool called Apktool.

The Decompilation Process

Apktool is the go-to utility for unpacking and repacking Android APKs. It extracts the resources and decompiles the compiled code into a more readable format called Smali.

APK Acquisition: The attacker obtains the APK from an app store or directly from a compromised device.

Decompilation Command: After installing apktool run below command in your preferred terminal

Apktool Installation

apktool d app-release.apk
Enter fullscreen mode Exit fullscreen mode

This creates a new directory containing the decompiled files.

Code Inspection: The attacker then navigates and analyzes the resulting files, which include the app's native code and resource structure.

Anatomy of a Decompiled App (Before Obfuscation)

In an unprotected (or minimally protected) React Native or Expo application, the directory structure and file contents offer clear signposts to an attacker.

Example Decompiled app directory

Decompiled App with Minimal Obfuscation

smali/ directory Contains .smali files, which are a human-readable assembly-like language derived from the app's native Java/Kotlin bytecode. Proprietary Logic: Function names, variable names, class structures, and API endpoint references are often intact and descriptive as shown in the image above.

How to Improve Obfuscation in Expo Apps

For React Native apps, particularly those built with the Expo Managed Workflow, you can leverage the powerful built-in tooling for advanced binary protection. The key is to enable and fine-tune ProGuard (or R8, the modern equivalent) through the expo-build-properties plugin in your app.json or app.config.js.

Configuration Steps

By default, Expo enables basic resource shrinking. For stronger protection, you must explicitly enable code obfuscation and resource compression for release builds, you can customize your app.config.js or app.json, by add expo-build-properties in your plugins

[
  "expo-build-properties",
  {
    "android": {
      // 1. **Crucial:** Enables R8/ProGuard for code obfuscation and shrinking.
      "enableProguardInReleaseBuilds": true,

      // 2. Optimizes the size of the final APK by compressing bundled assets.
      "enableBundleCompression": true, 

      // 3. Removes unused resources (like images or unused strings) to shrink size.
      "enableShrinkResourcesInReleaseBuilds": true,

      // 4. Advanced: Allows custom ProGuard rules for fine-tuning obfuscation.
      "extraProguardRules": "-dontwarn com.squareup.okhttp3.**\n-keep class com.myapp.secure.** { *; }"
    }
  }
],
Enter fullscreen mode Exit fullscreen mode

Implementing extraProguardRules
The extraProguardRules property is powerful for fine-tuning the
protection: You can write specific rules to further obfuscate proprietary code or to prevent obfuscation on specific native modules that rely on introspection (reflection) to function correctly.

Best Practice: Always use a -keep rule for classes that are accessed dynamically (e.g., via reflection, JNI, or third-party SDKs) to prevent R8/ProGuard from renaming or stripping them, which would cause runtime crashes.

Anatomy of a Decompiled App (After Obfuscation)

After implementing robust obfuscation, the same directories and files become significantly less useful to the attacker, drastically increasing the time and effort required for reverse engineering.

Decompiled App with Custom Obfuscation

After implementing robust obfuscation, the same directories and files become significantly less useful to the attacker, drastically increasing the time and effort required for reverse engineering.

Directory/File Post-Obfuscation State Impact on Attacker
smali/ directory File and function names are replaced with meaningless, single-letter or short, randomized strings (e.g., a1.smali, b.smali).
Deterrence: The attacker loses context. A file named a.smali provides no clues about its function, forcing manual, tedious analysis of the bytecode's flow and content.

NB
⚠️ Warning and Testing: You must thoroughly test your application after enabling or tightening obfuscation. Since some native packages (especially those using reflection) may be affected by renamed classes, rigorous regression testing across all functionalities is non-negotiable before deploying the secure build.

Final Thoughts

While basic, default obfuscation provides a minimal barrier, it may not deter a determined attacker targeting a high-value application. As the threat landscape evolves, and with attackers increasingly leveraging Large Language Models (LLMs) to accelerate the decoding of default binary encoding provided by frameworks, developers must respond with sufficient binary protection.

Obfuscation is a layer of defense, not a complete solution. When combined with other critical controls—such as Root/Jailbreak Detection, Runtime Application Self-Protection (RASP), Certificate Pinning, and proper Secret Management—a comprehensive strategy will significantly increase the cost and effort required for a successful reverse engineering attack, stretching the attacker's resources to their limit. For serious, commercially-sensitive projects, insufficient binary protection is a risk you simply cannot afford.

Top comments (0)