SReverseby Simpa Labs

Packed builds

Analyzing a packed Android APK

A packed APK opens in a decompiler and shows almost nothing, because the classes that matter are not in the file. The application code is stored encrypted and decrypted into memory while the app starts.

What a packed APK contains

Packing protects the executable classes rather than the code itself. The classes.dex file in the archive is a small stub or decryptor, and the real classes sit encrypted in an asset or inside a native library. At startup the stub decrypts them and hands the bytes to the runtime through a class loader, so the code exists only in the process memory of a running app.

Everything else in the archive is still there. Resources, assets, the manifest and the native libraries are readable, and they carry a surprising amount of the API surface on their own. The unpacking work is about the classes, and the rest of the archive is where you start.

Identify the packing stage statically

Read the manifest first and note the application class, the content providers and any components that start early. A packer usually needs to run before the real application class, so an unusual entry point or a provider that initialises quickly is a strong signal.

  • The DEX count in the archive shows the shape of the build, since a stub holds a small number of classes while a normal app holds thousands.
  • The asset list shows large or oddly named files that hold the encrypted payload.
  • The native library list shows whether a custom decryptor ships in the build or the app relies on a platform library.
  • Strings in the stub reveal the cipher, the loader class name and the asset it reads.

That gives you the stage to hook without unpacking anything, which matters because the runtime step is the expensive one.

Dump the real classes at runtime

The decrypted bytes must pass through a class loader, and that is the moment to copy them. Instrument the constructors used to hand bytes to the runtime, along with the method that defines a class from a byte array, and write the input to a file. Hooking the file read that supplies the asset catches payloads that are decrypted in native code before they reach the loader.

When instrumentation is blocked by detection, the alternatives are memory based. Dump the process memory and search for the structure each class file begins with, then carve the entries out. Another approach copies the application's private data directory after it has started, because some packers leave decrypted copies in a cache file.

Detection raises the cost of this stage rather than closing it. Hooks installed before the checks run, or a modified runtime, usually get the payload out, and the effort is bounded because the decryption happens once per process start.

Rebuild a readable APK

Once you have the dumped classes, assemble them into a file the decompiler can read. Replace the stub with the dumped set, then reopen the archive in a decompiler and confirm that the real package names appear. Keep the original archive as a reference, because the rebuilt one may not run: signature checks, resource references and the loader itself can all depend on the original layout.

A rebuilt archive is for reading rather than for shipping. Its purpose is to give you named classes, method signatures and string references in a tool that can search them.

What remains after unpacking

Unpacking reveals the build as the developer compiled it, and most release builds are obfuscated. Renaming has removed class and method names, string encryption hides the literals, and reflection hides which methods are called from where. None of that is caused by the packer, and all of it survives the dump.

Work from behaviour at this point. Strings recovered after decryption give the endpoint and header names, and captured traffic shows what a real request looks like. Where a value is computed, read the method that produces it, and where a call target is chosen at runtime, resolve it by observing the app rather than by reading the source.

Which parts of the API work packing blocks

Packing rarely blocks the endpoint inventory. Captures give paths and payloads, and strings recovered from the decrypted classes fill in the rest, so the shape of the API is available either way.

It blocks the work that needs the algorithm. When a signature is computed in the packed classes, nothing can reproduce it until those classes are readable, which makes unpacking a prerequisite rather than an optional step. SReverse works on protected builds and carries the recovered logic into a callable client. If the runtime checks are the obstacle rather than the packing, Frida detection analysis covers how they work, and Android obfuscation reverse engineering covers what is left after the dump.

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?