SReverseby Simpa Labs

Class encryption

DexGuard class encryption and why analysis stalls

A decompiler finishes with far fewer classes than the app clearly uses. The target class is missing, a small loader sits where the code should be, and searches return the same startup routine. That pattern is class encryption, and it changes where the analysis happens.

The pattern on the file

Class encryption moves a set of compiled classes out of the shipped dex as directly readable bytecode and restores them while the app runs. On the file, the effect is a gap. Classes the app plainly needs are not present, and a small amount of code sits at the point where they would have been loaded. A decompiler shows a loader or an initialiser rather than the class bodies, and a reference to a missing type reads as a name with no definition.

The pattern differs from ordinary name obfuscation. A renamed class is still in the dex and still decompiles, so the methods and their structure remain visible even when the names carry no meaning. A removed class leaves nothing to read, and the search that would normally find it returns an empty result.

What the pattern indicates

It indicates that the build treats a defined set of classes as protected content and restores them at run time. The classes exist in the running process, because the app works, and the static image is incomplete by design.

It also indicates where the loader lives. Something has to supply the class bytes, and that code stays in the dex because it has to run before anything it restores. Finding the loader tells you which classes are protected and gives you the boundary between what you can read and what you cannot.

The exact packaging of the encrypted payload varies between product versions and build settings, so describe what you observe in this build rather than a remembered layout. The category is consistent even when the file names are not.

What it does not indicate

Missing classes do not mean the code was removed from the app or that the feature is dead. The class runs from memory, so a search that finds nothing has found a limitation of the search rather than an absence of behaviour.

Class encryption does not mean the app encrypts its traffic. One decision protects code from static reading and the other protects data in transit, and an app can carry either without the other. Assuming the request body is encrypted because the classes are encrypted sends the work in the wrong direction.

It also does not mean the request cannot be reproduced. The running app still speaks to its backend, and the exchange is observable regardless of how the code that builds it is stored.

Why static analysis stalls here

Decompilers operate on files. When the classes are not in the file, the tool has nothing to show, and the output looks like a failed decompile rather than a deliberate design. Reports of missing classes, unresolved references and short methods full of loader calls are the expected output, not evidence that the tool is broken.

A second stall comes from references. Even where a protected class is restored at run time, the code that calls it may reach it by a name built from strings. The call site then reads as a lookup rather than as an invocation, and the data flow that connects the user action to the request is harder to follow from the file alone.

Where the work moves

Runtime observation replaces static reading for the protected set. Record what the process loads and what the target action produces, and treat the restored class as a component with a known API specification rather than as source you can reconstruct.

  • Observe the loader. Record which classes it produces during the flow you care about, which narrows the protected set to the part that matters.
  • Intercept at the boundaries. Hook the HTTP client, the serializer and any signing helper, and record inputs and outputs without reading the code between them.
  • Enumerate what is present. List the classes that remain readable and search them for the call sites that reach the protected set, since the callers are usually not protected themselves.
  • Compare builds if more than one exists. A version without the protection, or with a smaller protected set, shows what the guarded classes do in behaviour rather than in structure.

What the deliverable needs

The client reproduces behaviour, so reading a protected class body is not a requirement. Record the boundary, the inputs and the values the app derives, then implement the same computation in a language you run. Verification compares your output with the app's on several samples and confirms that the server accepts the request.

Send the APK and the full application flow. We identify which classes are held back, observe them at run time, and reconstruct the request pipeline around them. DexGuard reverse engineering covers the class encryption layer, and Android obfuscation reverse engineering covers builds where several techniques appear together.

Reviewed 28 September 2026 · SReverse research desk

Start your full APK reconstruction

Send the full APK

Projects start at $120. Choose WhatsApp or email, then attach the APK in the app that opens. We reply within one hour with the next step and send the fixed quote after review.

Want us to contact you?