Xamarin Reverse Engineering: A Guide for Penetration Testers

Today's development landscape demands cross-platform solutions to keep up with the ever-evolving mobile environment. Xamarin is an open-source platform that gives developers access to a comprehensive selection of tools and add-ons, allowing them to create modern apps for iOS, Android, and Windows using .NET and C# frameworks.

Xamarin applications can be written on PC or Mac and compiled into native application packages, like .ipa file on iOS or .apk file on Android.

With the abstraction layer, developers have a unique opportunity to unlock cross-platform power - streamlining their application development process with up to 90% code-sharing potential. By writing in one language and achieving native performance on each platform, businesses reap greater efficiency plus familiar user experience across devices.

Let's discuss in more detail the use of Xamarin for mobile application development.

Single Stack

Xamarin offers developers a comprehensive and convenient interface with its single language- C#. Visual Studio serves as the ideal environment to power Xamarin's impressive features, such as code auto-completion, an extensive project template library, and a sophisticated solution and management system - making it one of the best development platforms available today.

Developing cycles are sped up significantly by eliminating the need to switch environments. This saves both time and effort while optimizing efficiency.

Quick Time to Market

Since the entire code is written in C# and within the .NET framework in Xamarin, there is no need for different teams to work on the app. This ensures that procedures from development to testing and deployment are streamlined, eliminating every additional expense and promising quick market time.

Lesser Runtime Errors

Xamarin contains complete strongly-typed bindings for the underlying SDKs in Android and iOS. These bindings are easy to use and navigate through and provide strong type checking during compile-time and development. This ensures lesser runtime errors and thus produces high-quality applications.

Sharable Codes

Being known as the "write once, use everywhere" cross-application platform, Xamarin takes code sharing to the next level. It creates a single codebase that is up to 90% reusable. Further, Xamarin.Essentials provides a unified API to access common resources across all three platforms, facilitating native look and performance. 

Open-source and Free

.NET platform is a vast, accessible, and open-source community with contributors from more than 3,700 companies. With Xamarin being a part of this platform, there are no fees or licensing costs, even for commercial use.

Easy Maintenance

Xamarin is the ideal choice for developers looking to save time when making changes and updates across multiple applications. With Xamarin, all you have to do is make a change in one place - the source code- and see it applied everywhere! Enjoy effortless maintenance without sacrificing quality.

Importance of Reverse Engineering for Xamarin apps

According to the IBM Security Data Breach Report of 2022, India's average data breach cost for 2022 is Rs 17.6 crore (i.e., around $2.2 million).

Security researchers use penetration testing techniques, including reverse engineering, to locate inherent issues to prevent these attacks. 

Reverse engineering is the process of extracting design and information from an existing application and recreating it entirely or a fragment based on the extracted data.

It is crucial for many reasons, including determining the vulnerability of an application, enhancing software security, making software compatible with third-party components, etc.

The guide enlists the tools required by pen testers for reverse engineering, but first, let us look at the Xamarin platform.

Understanding the Xamarin Platform

The Xamarin architecture comprises the following elements:

Visual Studio for Mac

Formerly known as Xamarin Studio, Visual Studio for Mac is Microsoft's C# integrated developer environment that runs on Mac. 

It contains many features and the same formats as Microsoft's Visual Studio for Windows: solutions (.sln) and C# projects (.csproj). 

Xamarin.Mac

Xamarin.Mac is Xamarin's closed-source version of MonoMac. Owned by Microsoft, the toolkit provides .NET access to native features of the Mac Operating System. 

It also assists in compiling .NET projects into self-contained application bundles.

Xamarin.Android

Xamarin.Android is the platform for creating C# .NET applications for Android devices. It compiles C# into Intermediate Language (IL), which is then Just-in-Time (JIT) compiled to a native assembly when the application launches.

The diagram below shows a rough layout of this architecture:

 Xamarin Android Architecture 

Xamarin Android Architecture

Xamarin offers .NET bindings to Android.* and Java.* namespaces. Xamarin.Android applications operate under the Mono execution environment, with the Android Runtime (ART) virtual machine running side by side.

The Mono execution environment calls into these namespaces through Managed Callable Wrappers (MCW) and gives Android Callable Wrappers (ACW) to the ART. 

Both these environments run on top of the Linux kernel and invoke various APIs to the user code. The arrangement allows developers to access the underlying system.

Xamarin iOS Project

Xamarin.iOS applications run under the Mono runtime environment and use full Ahead of Time (AOT) compilation to compile C# .NET codes to ARM assembly language. 

It runs along with the Objective-C Runtime. The runtime environments run on top of a UNIX-like kernel and invoke several APIs to the user code, which lets the developers access the underlying managed or native system.

The below-given diagram depicts this architecture:

UNIX-like kernel

Notes

What is .Net Runtime? 

 .Net framework is a set of assemblies, classes, and namespaces that developers can use to create applications; .Net Runtime runs the compiled code, and the process is called managed code execution. 

.NET Runtime provides several features that ensure platform independence and are compatible with older framework versions.

Which .Net version to download? 

Every application using the .NET framework needs to have .NET Runtime installed. The end-users are supposed to download Microsoft Windows Desktop Runtime, which appears in the Apps & features section as Microsoft Windows Desktop Runtime.

What is Mono Framework? 

Mono Framework was started in 2005 as an implementation of the .NET Framework for Linux (Ximian/SuSe/Novell). Sponsored by Microsoft and led by Xamarin, Mono is the .NET framework's open-source implementation based on the ECMA standards for Common Language Runtime and C#

The framework includes Web-Forms, MVC, Winforms, Olive, and MonoDevelop an IDE (also called Xamarin Studio).

Getting Started with Xamarin Reverse Engineering

Tools required for reverse engineering Xamarin apps

dotPeek

dotPeek is a decompiler that decompiles and examines multiple formats, including libraries (.dll), Windows metadata files (.winmd), and executables (.exe).

Once decompiled, an assembly can be saved as a Visual Studio project (.csproj). The merit here is that if a lost source code requires restoration from a legacy assembly, this action can save time.

Further, dotPeek provides handy navigation throughout the decompiled code, making it one of the perfect tools for Xamarin algorithm analysis. 

dotPeek

(source)

Mitmproxy

A debugging tool, Mitmproxy is one of the best reverse engineering tools for pen testers. Testers also use it for testing and privacy measurements. The software also assists in decoding varied message types, from HTML to Protobuf, intercepting specific messages on the fly, modifying them before they reach their destination, and replaying internet traffic like WebSockets, HTTP/1, HTTP/2, or other SSL/TLS-protected protocols. 

The scripting API provides complete control over the tool and automatically modifies messages, redirects traffic, visualizes messages, and implements custom commands.

Mitmproxy

(source)

dnSpy

If you are looking for a tool that provides a complete spectrum of reverse engineering services, it is dnSpy. It facilitates decompilation, simple deobfuscation, and debugging of .NET applications. It also allows modification of any .NET compiled code in its high-level C# form. 

While it lets you edit the code, recompile, and replace the patched method, dnSpy also assists in recompiling entire projects into Visual Studio-compatible source code solutions.

This reverse engineering software has no license cost, i.e., it is free to use and is updated frequently and regularly. 

.NET Reflector 

With a comprehensive add-in model and an API that extends the tool to suit your exact needs, .NET reflector saves time and simplifies development. Let's take a look at the plethora of reverse engineering services this tool provides:

  • Provides an insight into how the data flows through a library or component 
  • Provides insight into the implementation and usage of .NET languages and frameworks 
  • Finds undocumented and unexposed functionality to get more out of the APIs and technologies used.
  • Finds dependencies and different assemblies
  • Tracks down the exact location of errors in your code, third-party components, and libraries.
  • Debugs into the source of all the .NET code you work with.


(Source)

Reverse Engineering Techniques for Xamarin Apps

Decompilation of Xamarin Assemblies

Decompilation is the process used to produce source code from compiled code.

To procure information about the assemblies and executables currently in memory, Windows is a great place. To open the Modules window, select Debug > Windows > Modules. Once you detect the module that requires decompilation, right-click and select "Decompile Source to Symbol File". This action builds a symbol file that contains a decompiled source which, in turn, lets you enter into 3rd party code directly from your source code.

Visual Studio decompiles the managed code, even in the absence of symbols, allowing you to look at the code, inspect the variables and set breakpoints.

To extract source code to disk, right-click on the module with embedded source and click "Extract Embedded Source ."This will export the source files to a Miscellaneous files folder for further analysis.

Debugging and Tracing Xamarin Apps

To develop Android applications, they must be run on physical hardware or using an emulator. Let's take a look at how to debug a Xamarin App in both of these circumstances.

Debugging on the Android Emulator

Visual Studio launches the Android Emulator and runs the app on a virtual device. To test and debug a mobile application, you must select from the pre-configured virtual devices available in the device drop-down menu on Visual Studio. 

If one of these pre-configured virtual devices matches your app's target API level, you can directly launch the Emulator to start running your app on it. 

However, if your Xamarin.Android app uses a Target Framework level that does not match with the available virtual devices, you can either use the Android Device Manager to develop new virtual devices that match your target API level, or you can change the project's Minimum Android Version so that it supports the API level of the available virtual devices.

Whichever way you choose to proceed, once you choose the virtual device, select either Debug or Release mode, and then click the Play button to run the application. This will deploy the app to the emulator, which will then run the app with the configured virtual device image.

Debugging on a Device

This involves configuring a physical Android device so that the Xamarin applications can be deployed to it directly from either Visual Studio or Visual Studio for Mac.

Once the device has been selected and connected, Xamarin.Android will deploy the application and then run it. The debugger stops it when the breakpoint is reached to allow the app to be debugged like any other C# application.

To ensure that the required debug symbols are available and that the IDE can connect to the running application, you must select the Debug configuration and the external device in the IDE. 

(Source) 

Static Code Analysis

Static analysis is the Reverse Engineering technique for penetration testers where they debug compiled code, including both source code and binary code, without actually running the application. 

Under this process, pen testers use static code analyzers, i.e., software that examines the code and identifies weaknesses and issues, such as SQL injection and cross-site scripting (XSS) vulnerabilities, which might result in security incidents. 

Static code analysis can be further subdivided into two categories: source code analysis and binary code analysis.

Source Code Analysis: 

This method inspects the source code to identify faulty areas (in both client-side and server-side applications) that an attacker could exploit, such as buffer overflows, invalid pointer dereferences, vulnerabilities to format string attacks, etc. 

Binary Code Analysis: 

This technique analyses the binary code of a part of the software to uncover weaknesses within an application's programming logic. It is done by using a hex editor, which showcases all characters as hexadecimal numbers. These numbers are then converted into machine codes that can be read and analyzed for vulnerable patterns or keys. 

Dynamic Analysis using Runtime Instrumentation

Dynamic program analysis for runtime verification facilitates security or safety policy monitoring, profiling, testing, verification, debugging, fault protection, validation, behavior modification, etc. 

In C# programming, often, the user-defined variables consume a large amount of memory which decreases the performance of application program execution. This results in the unavailability of memory during program execution. Since the user cannot change the executed code, a technique that can insert the code when the program is executing is required.

Code Instrumentation using dynamic program analysis and program slicing narrows the attention to the relevant parts of the program during debugging. Additionally, these techniques provide runtime information such as unused variables space, logging information, programming faults, programming speed, etc. This also improves the overall performance of the program. 

Steps To Reverse Engineer a Xamarin Application

Xamarin is an open-source platform for building modern and performant applications for iOS, Android, and Windows with .NET. It basically is a framework that allows code developed in .Net to run on the most popular platforms out there. To perform the static and dynamic analysis, it is required to reverse engineer the application. For normal android applications, we use jadx to decompile the dex files and obtain the java code from it, but in this case, we will be dealing with dll files.

Note: This method will require you to have access to Linux/Mac as well as Windows machines. We have also provided a way through which you can run it natively on Linux/Mac distributions.

JIT vs AOT Compilation of Xamarin Applications

These two options to compile C# based Xamarin code into an application, i.e, Just in time compilation and ahead of time compilation; for more info, check out  JIT  and AOT. The way of compilation affects how the application code is shipped within the apk or the ipa file. 

Let us quickly take a look at it below:

  • Android

Xamarin allows you to compile using both the JIT and the AOT flags for android. There is also a way to go in between to get the most speed of execution using the Hybrid AOT mode. Note that the Full AOT mode is available only for the Enterprise license.

  • iOS

There is only one option in the case of iOS, ahead-of-time compilation. This is due to Apple's policies which prohibit the execution of dynamically generated code on a device.

We will go through the reversing of the JIT compiled app in this guide. JIT compiled are the most common ones that one can encounter during security assessments. 

If you encounter a Full AOT compiled application, and if the IL Assembly files are removed to reduce the build size by the developer, then the reversing requires an extra step of extracting dll files from .dll.so files from the lib folder or from the libmonodroid_bundle_app.so file. If it is a Hybrid AOT compiled app, and the IL files are still kept in the app bundle, we can use that to reverse engineer the application.

Getting the dll files from the APK

Just unzip the apk file and copy all the files present under the assemblies directory. 

Most of the application code can be found when we decompile the dll files. These dll files are compressed and cannot be directly used for decompilation. Luckily there’s a tool out there that we can use to uncompress these dll files called XamAsmUnZ.

Build the solution for the repository given above which will generate an executable file. 

Using this tool to uncompress the .NET assemblies.

The uncompressed assemblies can be opened in a tool named dnSpy or any other decompiler that supports to view the respective c# code. dnSpy is a debugger and .NET assembly editor.

Upon getting the source code, we can perform the static analysis test cases like credentials hunting, sensitive info disclosure, SSL pinning logic, API endpoints discovery, etc. With this information, it is possible to map the attack further and improve our pentesting methodology.

For the dynamic instrumentation, we can use FridaX.

Reverse Engineering a Xamarin Application

Let's reverse engineer an app named DigiD. Xamarin Framework based apps contain 90% of common code in the builds of all platforms like iOS and Android etc. 

We shall go through the steps beginning with Android, which involves an extra step of decompressing the LZ Compressed .dll files. We can use tools such as XamAsmUnZ or Xamarin_XALZ_decompress.py after deflating the .apk to uncompress the .dll files, which are then shall be used to decompile using tools such as dnSpy or ILSpy. 

Static Analysis

  1. Using Unzip tool to unpack the apk or the ipa file
  2. In the case of the .apk, .dll files from unpacking should be uncompressed, but in the case of the iOS, dll files inside the IPA files can be directly loaded into a decompiler

As we can see in the above screenshot, on the left, we have the iOS file, and on the right side, the android apk of the DigiD being unpacked using the `unzip` command.

If you are familiar with the IPA and the APK structure, you can make out that this is a typical unpacked build. In the next steps, we are gonna explore what makes Xamarin apps different from other native apps.



Unpacked apk looks like this, it contains a folder named assemblies, which is a point of interest for us while reversing Xamarin apps in the case of android. 

From the above screenshot of listing the dll files that were present in the apk, we can confirm that it is a Xamarin app. It contains app-specific dll files along with the library files that are required for the app to run, such as Xamarin.Essentails.dll or Mono.Security.dll

Those dll files are compressed, and in the next step, we are going to decompress them using Xamarin_XALZ_decompress.py, which will result in an uncompressed dll file. This process has to be repeated for all the dll files that we want to decompile. A wrapper around the python script can help us do this in bulk.

Now the uncompressed dll files are good to be loaded into a .Net decompiler of your choice. We are going to cover only the static analysis part of the reversing here, guide for patching dll files.

One has to have the basic or intermediate knowledge of C# for reading and understanding the application logic. We have a choice to either go through the decompiled C# code or the IL code. One can also modify the methods as well and rebuild the application to change the application behavior.

Choosing a decompiler for the task depends on aspects such as the operating system that you are running and if you need to debug/edit .Net assembly or just decompile the dll files and go through them. If you are on windows, it is an easy choice to just go with dnSpy or its unofficial, actively maintained version dnSpyEx/dnSpy.

Let's jump quickly onto the iOS part, it is quite straightforward due to the fact that .dll files which contain the IL Code are present in the Payload/DigiD.iOS.app folder.

From now on, the steps given below are similar for both the android and the iOS platforms. Using a decompiler, we can try to understand how the app works and learn its inner workings. The decompiler used here is dnSpy running on macOS with the help of wine.

In the above example, we can see the dll files with names starting with DigiD are the code that is responsible for how the application works. Along with those files, we have the included libraries that make the app work, such as QRCoder or System.Net.Http, etc. They can be a 3rd party library or those which come with the Xamarin framework. 

We can further look into those dll files and try building up a clear picture of what the application is capable of. In this example, we can make out that the application is capable of performing QR code scans or using NFC. It can be noticed that there are files that are specific to iOS, such as Lottie.iOS, which is used for vector animations.

There is a better way to perform static analysis on macOS using ILSpy or ILSpycmd. This eliminates the need to install software such as dnSpy, which does not work natively on Unix-like systems. 

If you prefer to use tools such as dnSpy or dotpeek, you would either need a virtual machine with a minimum of 4 gigabytes of RAM or more to smoothly install dnSpy and perform reverse engineering or install emulators such as WINE, but the native performance cannot be guaranteed.

The above screenshot shows the result of using ILSpycmd and later viewing the decompiled code inside the VSCodium IDE. We can see the command constants that are being used by the Digid application. We leave the rest of the static analysis as an exercise for the reader. 

Dynamic Analysis

Try to check if the application has any kind of SSL pinning in place. If not, using Burp as a system, CA should work for intercepting requests. Frida with Java or ObjC runtime won’t work here, but luckily there’s a tool out there that can be used for hooking into methods. Fridax allows you to easily modify the .NET binary inside a Xamarin application on runtime.

Static analysis will help you identify different methods present within the application, which can be hooked later for dynamic analysis using Fridax.

Below are a few Frida scripts that can help us bypass root detection or SSL-pinning 

  1. xamarin-antiroot
  2. xamarin-root-detect-bypass
  3. Frida-xamarin-unpin

We can conclude that it is possible to efficiently reverse engineer Xamarin apps and check for security vulnerabilities with the methodology given above.

Common Challenges Faced During Xamarin Reverse Engineering

Even with reverse engineering, an application cannot be disassembled entirely to its original state before being compiled. Furthermore, due to obfuscation of the vital and critical source code, the disassembled application only provides a little information because it results in a huge volume of relevant codes in the application, which makes reverse engineering even more difficult. Additionally, the most common issue is the non-availability of skilled reverse engineers.

Best Practices for Reducing the Risk of Xamarin App Attacks

India saw 18 Mn cyberattacks and 2 Lakh online threats daily in the first quarter of 2022. With growing cyber-crimes each year, end users' private information, such as email, address, and bank account details, is always at risk of being stolen. Therefore, it becomes necessary that stringent measures are taken to ensure complete security. And that's when penetration testing comes into the picture. With a motive to replicate the behavior of a potential hacker, it identifies and mitigates an application's vulnerabilities before the hacker can exploit them. 

Appknox being the highest-rated security solution on Gartner, the pentest team is excellently equipped to identify and neutralize these threats way before an actual attack. It is the world's most robust plug-and-play security platform for developers and businesses that focuses on mobile application security on platforms like Android and iOS, thus allowing app testing for multiple platforms.

This is further how you can reduce Xamarin app attacks using Appknox: 

  • Scan the applications for security issues in under 60 minutes, regardless of the app size. 
  • Run automated security tests against 130 test cases. 
  • Perform surface level and API tests. 
  • Run penetration tests for detecting real-time security flaws. 

 

Takeaway

With the ever-changing landscape of cyber threats, penetration testing has become a go-to option for keeping mobile applications secure. Reverse engineering is an essential technique that puts developers and pen testers on track to fully understanding how their app operates - giving them key insights into vulnerability detection and bug resolution.

By employing a reverse engineering approach for Xamarin apps, the process can be expedited. With its shared code feature, once any security vulnerabilities are identified and addressed on one platform, they automatically become secured across all other platforms with minimal adjustments needed.

 

Published on Apr 21, 2023
Akshay Shinde
Written by Akshay Shinde
Akshay Shinde is a certified penetration tester and security researcher at Appknox, a security suite that helps enterprises automate mobile security. With years of experience in ethical hacking and pen testing, he brings a wealth of knowledge on robust counterintuitive measures against evolving threats to the team.

Over the course of his career, Akshay has been rewarded for disclosures, such as Bug Bounty by Redbull, Rush by Hike, KooApp, Acko, and many more. When he's not countering hackers, you can find him playing challenging video games or watching cricket matches.

Questions?

Chat With Us

Using Other Product?

Switch to Appknox

2 Weeks Free Trial!

Get Started Now