SReverseby Simpa Labs

Xamarin

Reconstructing an API from a Xamarin app

A Xamarin app carries .NET assemblies in the package, and those assemblies decompile to C# that keeps type names, method names and string constants. The request logic is often legible from a decompiler window.

Where the assemblies live

Xamarin.Android packages the managed side of the application as .NET assemblies inside the APK. In many builds those assemblies are stored in a compressed blob with a manifest that lists them, and the runtime loads and unpacks them at startup rather than reading individual files from the package. Newer .NET for Android builds keep assemblies in the package as well, sometimes compressed per file. Either way, the first step is to list the package contents and locate the assembly store, because the file names on disk differ from the names the app uses.

Once the store is unpacked, you have assemblies that are complete enough for a decompiler. That is the main structural difference from a Java or Kotlin app processed by R8, where shrinking removes names and inlines methods. A Xamarin build keeps metadata unless a .NET obfuscator was applied, and the metadata is what makes the decompiled output readable.

Decompile and read the client

Open the assemblies in a .NET decompiler such as ILSpy, dnSpy or dotPeek. The application code appears as C# with class names, method names and string constants intact. Request logic is usually concentrated in a service layer, and the shape of that layer tells you what to expect on the wire.

  • HttpClient calls appear as typed methods. A method that builds a URL, sets headers and awaits a response gives you the endpoint, the verb, the header set and the response model in a single screen of code.
  • Refit interfaces carry their routes in attributes. When the project uses a declarative client, the interface methods are decorated with the path template and the HTTP method, so the endpoint inventory is a list of interface declarations rather than a set of call sites.
  • RestSharp requests name their resource and method. The client builds a request object with the path and verb as constructor arguments, which makes the call sites easy to enumerate.
  • Model classes describe the payload. Property names and serialisation attributes define the JSON fields, including the names that differ from the C# property names.

Read the signing code directly

Signature generation is where a readable assembly saves the most time. The canonical string assembly, the hash call and the key are usually visible in one method, and the key is frequently a constant that a decompiler shows as a plain string. Compare it with a captured signature by recomputing the hash over the message for one request, and the scheme is confirmed without running the app.

Where the key is not constant, the code that derives it is still readable, so you can see whether it mixes device values, fetches a secret at startup or loads a keystore-backed key. That answers the question of whether the flow can run on a server far earlier than instrumenting the device would.

Compressed, trimmed and obfuscated builds

Build settings change what extraction gives you. Compression means the assemblies are not readable until the blob is unpacked, which a script can do once the store format is understood. Trimming and linking remove code the build believes is unused, so a method you expected can be absent or inlined into its caller, and the fix is to look for the behaviour rather than the name. Ahead-of-time compilation translates some methods into native code while the assembly keeps the metadata, so a decompiler shows a stub where the body used to be and the implementation sits in a shared library.

A .NET obfuscator renames types and members and can encrypt strings. The control flow of the client survives renaming, so the endpoint and header logic remains findable by structure even when every identifier is meaningless. Encrypted strings are the harder case, and the string accessor is again the function to hook, because it returns plaintext to the rest of the application.

Read the app when the file is not enough

Some builds encrypt the assembly store or decrypt it with a key held elsewhere, so the copy on disk is not directly readable. In that case, attach an instrumentation tool to the running process and work at the managed layer, dumping the assemblies once the runtime has loaded them. Xamarin apps run on a Mono runtime in most builds, so the process exposes a managed heap that a script can walk to find loaded types and strings.

The disk copy is the cheaper route when it works, and it usually does. Treat runtime instrumentation as the fallback for builds that were deliberately hardened, rather than the first approach.

From decompiled C# to a client

A decompiled Xamarin assembly is close to a specification: endpoints, verbs, headers, payload models and the signing routine are all named. The remaining work is reimplementing it in the target language and reproducing the values that come from the device or from a session. Once those match, the client behaves the way the app does.

Private API authentication covers the session side, and APK to Python covers the delivery format. Xamarin Android reverse engineering is the service for this build type.

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?