Dast is live!

Run a new scan to see dynamic findings in your reports

Dast is live!

Dast is live!

Run a new scan to see dynamic findings in your reports

No headings found on page

Obfuscation slows down reverse engineering by renaming classes and methods, but it does not prevent exploitation. Attackers use Frida to hook into running processes at runtime, where obfuscation is irrelevant for finding known Android API entry points, and critical vulnerabilities such as intent redirection, deep-link flaws, and hardcoded secrets survive obfuscation completely intact.

In our research scanning thousands of Android apps, including apps with aggressive obfuscation from major vendors, we keep finding the same critical vulnerabilities. The obfuscation does not hide them. It just makes the code harder to read. The attack paths stay wide open.

This article breaks down exactly what attackers can still exploit in obfuscated builds, and what actually needs to happen to protect your app.

What does obfuscation actually do?

Obfuscation renames classes, methods, and variables to meaningless strings: a.b.c() instead of UserAuthManager.validateToken(). It can also reorder code, insert dead branches, and strip debug metadata.

The goal is to slow down reverse engineering. And it does slow it down, sometimes by hours, sometimes by days.

It does not:

  • Change how the app behaves at runtime

  • Fix logic flaws or improper data handling

  • Remove exported components that attackers can reach

  • Protect Android API calls, which cannot be obfuscated because the Android API is part of the OS, not the app 

  • Prevent dynamic analysis while the app is actually running

The moment an attacker runs your obfuscated APK on a device, the OS executes it as-is. Every method runs. Every data flow happens. Every vulnerable condition occurs.

How attackers defeat obfuscation

Can attackers reverse-engineer obfuscated Android apps?

Yes, reliably. The standard toolkit handles most commercial obfuscation without special effort.

jadx decompiles obfuscated APKs back to readable Java. Renamed variables become var_1, var_2, ugly, but fully traceable. Researchers can follow data flows manually in a matter of hours. It also gives attackers full visibility into export flags, intent filters, and permission declarations.

Frida takes a different approach entirely. Rather than reading code, it hooks directly into a running process at runtime, intercepting method calls as they execute. This means attackers can observe what methods do - their inputs, outputs, and side effects - even without knowing what those methods are named. Obfuscation makes Frida-based analysis harder because you don't know which method to hook without first identifying it. But once identified through runtime observation, obfuscated method names are no obstacle. 

These tools are free, well-documented, and used routinely by both security researchers and malicious actors.

There is one important distinction worth naming: ProGuard and R8 (rename-only obfuscation) do not stop taint analysis or runtime hooking. DexGuard-level protection, which adds encryption, is a different category and can defeat some static analysis approaches. But most production apps use ProGuard or R8. The attack surface described below applies to the vast majority of obfuscated builds in the wild.

What attackers still find in obfuscated builds

Exported components with no access control

Android's manifest is not obfuscated. Export flags, intent filters, and permission declarations are all in plaintext. As documented in the Android developer reference for activity elements, any exported component without proper permission validation is reachable by any app on the device. Attackers can reach it directly, no decompilation required.

This is one of the most common findings in obfuscated apps. The obfuscation made the internal implementation unreadable. It did nothing to hide the entry point.

Hardcoded secrets in the binary

In most obfuscated apps, API keys, tokens, and credentials embedded in the binary survive obfuscation intact. Standard tools like ProGuard and R8 do not encrypt string values — they only rename identifiers. Both jadx and automated scanners extract these strings without difficulty. Note that some advanced tools like DexGuard can encrypt strings at rest, but encrypted strings are still decrypted at runtime, making them recoverable through dynamic analysis regardless.

Deeplink vulnerabilities and intent redirection

These are logic flaws, not naming flaws. The OWASP Mobile Application Security Testing Guide identifies intent redirection and deeplink handling as among the most critical attack surfaces in Android apps. A deeplink parameter that flows into a URL redirecting to an attacker-controlled server will leak the app's authorization token, whether the code is obfuscated or not.

Another common pattern: an app takes a nested intent from an untrusted source and passes it to startActivity(), creating a path to private components. Our SAST engine traces this entire chain, from untrusted input through renamed intermediate methods. This works because the Android API methods, such as getStringExtra() and the sinks like startActivity(), are part of the Android framework and cannot be obfuscated. The intermediate app code may be renamed, but the entry and exit points of any data flow are always visible. 

We track cross-component flows too. If a deeplink activity parses parameters and forwards them to a second activity, which then writes to a file, we see that chain even when every class and method in it is renamed to a single letter.

How Android API calls anchor taint analysis

This is the key insight that makes taint analysis effective on obfuscated code: Android API calls cannot be obfuscated. getStringExtra(), startActivity(), loadUrl(), getContentResolver(): these are all part of the Android framework, not the app. Obfuscation only renames code that belongs to the app itself. The source of a data flow and its sink are almost always Android API calls, which means they are always visible regardless of how aggressively the intermediate code is obfuscated. The renamed methods in between are just steps in a graph, and the graph still has the same start and end points.

Vendor-specific framework vulnerabilities

Samsung's Android, Xiaomi's Android, and other vendors each modify the OS itself. Vulnerabilities in vendor-specific frameworks affect your app's behavior regardless of how well you have obfuscated your code. Samsung's Android, Xiaomi's Android, and other vendors each modify the OS itself. Vulnerabilities in vendor-specific frameworks affect your app's behavior regardless of how well you have obfuscated your code.

Why taint analysis works on obfuscated code

Can static analysis tools detect vulnerabilities in obfuscated Android apps?

Modern SAST tools that use taint/dataflow analysis are largely unaffected by ProGuard or R8 obfuscation.

When we scan an APK, we decompile it to Java and trace how data flows from sources to sinks. The sources, such as getIntent().getStringExtra(), and the sinks, such as startActivity() or loadUrl(), are Android API calls that are never obfuscated. The intermediate app code connecting them may be renamed, but the graph structure is preserved. Renaming validateCreditCard() to b() does not break the source-to-sink chain. The logic is the same. The flow is the same. The vulnerability is the same.

Simple tools, grep-based scanners, and basic pattern matchers do struggle with obfuscation. If you are searching for the string "password" and it has been renamed to "b", you miss it. But that is a limitation of the approach, not a fundamental limitation of static analysis.

The honest summary: taint analysis finds vulnerabilities despite obfuscation because Android API calls anchor every data flow. But obfuscation does create real challenges. Unobfuscated builds consistently produce better results; more complete findings, clearer vulnerability paths, and fewer cases where decompilation errors interrupt the analysis. We always recommend scanning unobfuscated or minimally obfuscated builds when possible.

How Oversecured handles obfuscated APKs

When you upload an APK, Oversecured decompiles it to Java and runs taint analysis on the decompiled Java code. Class and method names become a, b, and c, but the Android API calls - sources and sinks - remain fully visible. Taint analysis follows the data flow from those fixed API entry points through whatever renamed intermediate methods the app contains. The key differentiator is cross-component taint analysis. Most tools analyze a single component in isolation. Oversecured follows data across component boundaries: from a deeplink Activity through renamed intermediate methods into a BroadcastReceiver and then into a ContentProvider. Obfuscation renames each component but does not remove the intent-passing edges between them. That chain is still fully traceable.

As one of our enterprise customers noted: "Other tools look at the code we create, while on Android specifically, Oversecured just decompiles the entire application, so even if the code is coming from a library, from some dependency, from something we don't have in the source code, you can see if there is a vulnerability."

Honest limitation: DexGuard-level protection, which adds string encryption and bytecode restructuring on top of renaming, can produce decompilation output that is too corrupted to analyze. ProGuard and R8 do not have this problem decompiles obfuscated code. But even with ProGuard and R8, obfuscation introduces real tradeoffs: decompilation errors can interrupt analysis in edge cases, and unobfuscated builds consistently give cleaner, more complete results. We always recommend providing unobfuscated builds when possible. 

One practical issue for CI/CD pipelines: ProGuard generates fresh class names on every build, which means the same vulnerability can appear as a new finding on each scan. The detection is correct; the triage system is what breaks. We are working on code-location-based matching to solve this.

What actually protects obfuscated apps

Obfuscation is a speed bump. It belongs in a defense-in-depth strategy alongside tools that actually find the bugs, not instead of them.

Static analysis (SAST) finds logic flaws, data handling errors, access control violations, and hardcoded secrets before the app ships. It works on the compiled APK without needing source code. See how it works at oversecured.com.

Dynamic analysis (DAST) finds runtime vulnerabilities that only appear when the app is actually executing: network interception, IPC manipulation, and authentication bypasses. It produces working proof-of-concept exploits, so there is no question about whether a finding is real. Zero false positives. Read more about how Oversecured DAST works.

Proper access control on exported components is non-negotiable. Review every exported activity, service, and content provider. Add validation. Remove exports that do not need to be public.

FAQ

Does ProGuard or R8 protect my Android app from attackers?

No. ProGuard and R8 rename code and remove unused classes, making reverse engineering slower. They do not fix security vulnerabilities. Attackers using Frida bypass code obfuscation entirely because Frida operates at runtime.

Can an obfuscated app still have hardcoded API keys or tokens?

Yes. String values are preserved through obfuscation. Hardcoded secrets remain in the binary and can be extracted with standard decompilation tools.

Does obfuscation stop Frida-based attacks?

No. Frida operates at runtime and can observe method behavior - inputs, outputs, and side effects - regardless of obfuscation. Obfuscation does make Frida-based analysis harder to navigate because method names are meaningless, but it does not prevent runtime observation. 

What is the difference between obfuscation and app hardening?

Obfuscation makes code harder to read. App hardening covers a broader set of protections: root detection, integrity checks, certificate pinning, secure data storage, and fixing the actual logic vulnerabilities in the code. Obfuscation alone is not hardening.

Does DexGuard-level protection defeat static analysis?

DexGuard adds encryption and code virtualization on top of renaming. This can defeat static analysis in some cases. But most production apps use ProGuard or R8, which do not defeat taint analysis. And DexGuard cannot protect against dynamic analysis: Frida and runtime monitoring work regardless.

What this means for your app

Obfuscation slows attackers down. SAST and DAST stop them.

If your mobile security strategy relies on "they won't be able to read the code," you are one Frida session away from a critical breach. The vulnerabilities are still there. The attack paths are still open. The tools to find them are free and widely used.

Security testing finds what obfuscation hides from developers but not from attackers. Run it before every release.

Run a free scan on your app and see what obfuscation is not hiding.

Keep reading

Book a personalized demo

During the demo with our cybersecurity experts you will get:

A free trial scan of your app

An analysis of your SAST and DAST findings

Practical insights on mobile security of your app

Book a personalized demo

During the demo with our cybersecurity experts you will get:

A free trial scan of your app

An analysis of your SAST and DAST findings

Practical insights on mobile security of your app

Book a personalized demo

During the demo with our cybersecurity experts you will get:

A free trial scan of your app

An analysis of your SAST and DAST findings

Practical insights on mobile security of your app