What obfuscation removes and what it leaves
Obfuscators of the R8, ProGuard and DexGuard family rename classes, fields and methods, encrypt string literals, remove line numbers and source file attributes, and sometimes reshape control flow so the decompiler cannot rebuild the original conditional. None of that changes what the code does. The call graph survives renaming, annotations in the class file survive unless the tool explicitly strips them, and the reflection and framework entry points the app needs at run time have to keep working.
That is why JADX output on an obfuscated APK remains useful for API work. A class named a.b.c still implements an OkHttp interceptor, still builds a Request, still passes a header map into a signing helper. You are reading structure and data flow rather than names.
Read the structure before the names
Start where the output is most reliable, and let each answer narrow the next question.
- Trace the call chain with cross references. Pick a known entry point such as a Retrofit interface method and follow who calls it, which interceptor is attached to the client, and where the assembled request is handed to the network stack.
- Use string constants as anchors. When encryption is off, endpoint paths, header names and JSON field names still appear as literals, and searching one literal lands you in the class that handles it. When encryption is on, the literals are gone from the class and the decrypt routine becomes the anchor instead.
- Read annotations as documentation. Retrofit, Moshi, Gson, Room and serialisation annotations carry path templates, parameter locations and wire names, and they rarely survive renaming in a way that loses meaning.
- Switch to the smali view when a method decompiles badly. The failing output is usually local to one method, and the instruction listing shows the exact sequence of calls without the high-level reconstruction.
Find the routine you actually need
On a protected build, identify the target by its inputs and outputs rather than by its name. A signing helper takes a request and returns a string. A token routine takes credential fields and returns a session value. A response decryptor takes a byte array and returns JSON. Write down the signature, then search the decompiled tree for methods with that shape near code you have already identified.
String decryption changes where you look. A class that calls the same helper on every literal is a renamed name table, and the helper itself is the first thing worth reading. Once you know how the plaintext is recovered, you can hook that helper or reproduce it, and every literal in the app becomes readable at once.
Flow obfuscation adds steps rather than secrets. Opaque predicates, dispatcher loops and reordered blocks obscure the source shape, but the observable behaviour of the method is unchanged, which is why tracing the same inputs through the real execution path beats trying to recover readable source.
Obfuscation also varies in strength across a build. Tooling that renames aggressively may leave the network layer almost untouched, because Retrofit annotations and OkHttp types come from libraries the app cannot rename, and a project that pays for string encryption often spends it on the classes it considers sensitive. Reading the decompiled output tells you where that budget went before you commit to a plan.
Where the output stops being enough
Some of the logic you need lives outside the dex. A protected build can move signing, key derivation or integrity checks into a native library reached through JNI, and a decompiler will show only the method declaration and a native keyword. When that happens the Java layer still tells you the call API specification, the arguments and where the result is used, which is what you need before moving to the library itself.
Working from decompiled output is therefore a process rather than a single pass. You read what survived, identify the pieces you cannot read, and decide for each whether to reproduce it, hook it under the debugger, or analyse it natively. The endpoint inventory, header set and data shapes that come out of the first pass are usually enough to plan that remainder.
Related work
Reviewed 28 September 2026 · SReverse research desk