The assemblies live in a container
A Xamarin app compiles C# to .NET assemblies and ships those assemblies inside the APK, and the request code is among them. The runtime does not read them from a folder of files in every build. Depending on the packaging options, the assemblies are stored as individual files, embedded inside a native shared library, or collected into an assembly store with a blob and a manifest. Which layout the build used decides where you look.
The shared library case surprises people. The file has the name and the structure of a native library, it sits in the per-architecture library folder, and its payload is a set of managed assemblies rather than native code the app calls.
The packaging also ships the runtime that loads the assemblies, as a native library of its own. That library is the loader the container was built for, so its presence confirms that the packaging is Xamarin or its .NET successor rather than a native C++ app that happens to carry a large shared object.
Why a build embeds assemblies in a native library
Loading many small files costs time on the first run, and the loader has to map each one separately. Bundling the assemblies into a single library reduces the number of files the installer writes and lets the runtime map one object and read the assemblies from inside it. The packaging choice is a startup and install decision, and it changes the container without changing the assemblies themselves.
Finding the container
- The library folder names the architecture. Pull every per-architecture split, because a bundle install delivers only the one the device selected and the container ships once per architecture.
- Size identifies the container quickly. An app with little native code that carries a large shared library has that library for a reason, and the assembly payload is usually the reason.
- A name that matches no dependency is a signal. A library that is not a well known runtime dependency and is not referenced by another binary is worth opening.
- The assembly store is a separate pair of files. Newer packaging writes a blob and a manifest rather than embedding into the library, so look for those names before concluding the app holds no assemblies.
Extracting the assemblies
Two routes reach the same assemblies and they answer different questions. The static route reads the container and separates the stored entries, which is fast and needs no device. The runtime route observes the load and writes each assembly as the runtime hands it to the loader, which costs a device and settles the container format at the same time.
The runtime route is the more reliable of the two when the container is unfamiliar, because it does not depend on understanding the packaging. The loader has to receive a readable assembly image in memory for the app to start at all, and writing that image to a file produces an assembly a .NET decompiler opens.
Reading the payload before extracting it is worth a few minutes. A container whose entries begin with an executable signature holds the assemblies whole, and a container whose entries begin with a short marker holds them compressed, which changes the extraction step. The difference is visible in a hex dump and saves a decompiler from rejecting every file you pull out.
Why the file you expected may be missing
Packaging options move the assemblies between layouts from one release to another, and an app bundle distribution splits the package by architecture. A search of the base APK alone can therefore find nothing while the assemblies sit in another file the device installed. Collect the full installed set before deciding that the app stores no assemblies.
Reading the C# and building a client
Xamarin assemblies keep type names, method names and string constants in most builds, so a decompiler shows the HTTP client, the endpoint constants and the code that prepares a request. That legibility is the advantage of this packaging format, and it means the reconstruction proceeds from reading rather than from instrumentation. The result is a client that reproduces the app's requests, delivered as a Python, JavaScript or TypeScript library with an importable Postman collection and documentation, starting at $120 with most projects finished in 24 to 72 hours.
Related work
Reviewed 28 September 2026 · SReverse research desk