Obtaining .NET Assemblies from Android Full AOT Compiled Applications
Recently on a mobile engagement, I came across an Android application built with Xamarin using full Ahead of Time (AOT) compilation. This technology allows a developer to create an application in C#, and the Xamarin platform compiles that code into platform-specific binaries without the use of the Mono Just-In-Time (JIT) compiler according to the documentation. While AOT is great for performance and application size, it poses a problem when one attempts to dynamically instrument and manipulate the application for security testing. Normally you can interact with and manipulate the Mono assemblies with Frida and frida-mono-api, but in this instance, the assembly, class, and method names were unknown and there wasn’t a straightforward way to obtain them. However, I did discover a method to obtain this information which I outline below.
Extraction Process
After extracting the contents of the APK (apktool d example.apk), I expected to see a number of “libaot-*.so” files under lib/$arch based on the documentation I had read. However, I only found the libraries listed below.
![](https://www.lares.com/wp-content/uploads/2021/02/ZACAOT1.png)
Not knowing where to start, I grepped these libraries for my application name which matched libmonodroid_bundle_app.so. Performing static analysis on libmonodroid_bundle_app.so in Ghidra indicated that there were assembly references exported by the library.
![](https://www.lares.com/wp-content/uploads/2021/02/ZACAOT2.png)
These exports appeared to be used by the mono_mkbundle_init function.
![](https://www.lares.com/wp-content/uploads/2021/02/ZACAOT3.png)
Following the referenced code, I found that mono_mkbundle_init eventually called the my_inflate function.
![](https://www.lares.com/wp-content/uploads/2021/02/ZACAOT4.png)
The source code for the my_inflate function in the Mono source code indicated that decompressed and registered Mono assemblies. This spawned the idea of searching the binary for compressed data. Using the binwalk tool, I discovered that libmonodroid_bundle_app.so contained a number of compressed sections and I extracted them using binwalk’s -e flag.
![](https://www.lares.com/wp-content/uploads/2021/02/ZACAOT5.png)
Low and behold, the compressed regions were the .NET assemblies.
![](https://www.lares.com/wp-content/uploads/2021/02/ZACAOT6.png)
Opening the extracted assemblies revealed the full assemblies referred to in the shared library exports. With the assemblies in hand, it was back to testing with the well-known methods of runtime manipulation via Frida and static analysis of the assemblies.
![](https://www.lares.com/wp-content/uploads/2021/02/ZACAOT7.png)
While there’s likely a more elegant way of extracting the assemblies, this quick and dirty method proved useful for gaining access to the assemblies without excessive reverse engineering effort or custom tool development.