
Recently I stumbled upon an Android app that didn’t work as I expected it to. So, I had no choice but to examine its viscera!
I launched the latest version of GDA, opened the studied APK, and immediately noticed that it looks somewhat suspicious. Classes of all activities contain approximately the same boilerplate code looking something like this:
public class MainActivity extends BaseActivity{ private ArrayList refList; public static final String __md_methods; static { MainActivity.__md_methods = "n_onCreate:(Landroid/os/Bundle;)V:GetOnCreate_Landroid_os_Bundle_Handler ..... _ILandroid_os_Bundle_Handler:Android.Locations.ILocationListenerInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=nulln"; Runtime.register("Megaprogram.Activity.MainActivity, Megaprogram", MainActivity.class, MainActivity.__md_methods); } public void MainActivity(){ super(); if (this.getClass() == MainActivity.class) { Object[] objArray = new Object[0]; TypeManager.Activate("Megaprogram.Activity.MainActivity, Megaprogram", "", this, objArray); } return;
This makes me thinking that something is wrong with this APK. Is it some kind of framework?.. If you change the .
extension to .
, then the assemblies
folder immediately catches your eye: first, such folders are uncommon for ordinary mobile apps; and second, it contains numerous DLL libraries.
Names of many libraries contain the word Xamarin; so, it becomes clear where such uniformity comes from: the main program code is written in C# and is located in a DLL library; only boilerplate pieces of code designed for interaction between the Mono runtime and the Android Runtime (ART) virtual machine are written in Java.
Enough theory, let’s get to work!
Selecting tools
When I deal with .Net, I always use three tools.
-
dotPeek by JetBrains. The program makes it possible to decompile and examine
.
anddll .
files. In my opinion, dotPeek offers the most handy navigation through the decompiled code, which makes it the optimal tool for algorithm analysis.exe dotPeek main window -
dnSpy is used to decompile, edit, compile, and debug .Net assemblies. It must be noted that not all of its functions always work (except for decompiling): much depends on the specific situation. In my case, the compilation function didn’t work: the program was unable to link together the Mono and Android namespaces.
dnSpy main window -
Simple Assembly Explorer is a rather old, but still efficient utility making it possible to decompile
.
anddll .
into C# or CIL code (Common Intermediate Language is a ‘high-level assembler’ used by the .NET virtual machine – an intermediate language developed by Microsoft for the .NET Framework platform). Most importantly, this tool can compile CIL code, which enables you to easily make changes in the studied files.exe Simple Assembly Explorer main window
Instead of the standard apktool, I am going to use 7z to unpack and pack the APK. A bit later, I will explain why.
Unpacking the APK
Initially, I tried to use the well-known apktool to unpack the APK, but encountered problems with subsequent packing: too bad, apktool ‘doesn’t know’ such a file type as .
and doesn’t consider it a standard file type for an APK. Only files whose names are present in the array below are considered standard ones:
private final static String[] APK_STANDARD_ALL_FILENAMES = new String[] {"classes.dex", "AndroidManifest.xml", "resources.arsc", "res", "lib", "libs", "assets", "META-INF" };.
When an APK is assembled, all unknown files are compressed (compression type: DEFLATED), while Xamarin expects its DLLs to be uncompressed (STORED) and cannot read them properly. My first idea was to fix and rebuild apktool, but then I decided to take an easier way: unpack and pack files without compression using a standard archiver. After all, I don’t need to decode the manifest or get the Smali code.
Unpacking:
7z.exe x program.apk -oprogram_apk
After unpacking, in addition to typical APK files, I see the assemblies
directory with a bunch of dll
files inside. Out of them, the library whose name matches the name of the app is of special interest. Let’s dissect it.
Patching .Net
Analysis of the DLL and identification of the place to be modified is beyond the scope of this article (frankly speaking, this topic requires a separate book); so, I will focus only on technical aspects. As said above, dnSpy refused to compile the modified library, and I had to use Simple Assembly Explorer (SAE) for this purpose.
Let’s say I need a given function to always return true
:
protected bool IsOnline(){ ConnectivityManager connectivityManager = (ConnectivityManager)this.GetSystemService#0x0a0001d5("connectivity"); if (connectivityManager == null) { return false; } NetworkInfo activeNetworkInfo = connectivityManager.get_ActiveNetworkInfo#0x0a0002ad(); return activeNetworkInfo != null && activeNetworkInfo.get_IsConnected#0x0a0002ae();}
Since modifications can only be made in IL code, I switch to the Details tab in the SAE window and see the following picture:
0 L_0000: ldarg.0
1 L_0001: ldstr "connectivity"
2 L_0006: callvirt Java.Lang.Object Android.Content.Context::GetSystemService(System.String)
3 L_000b: castclass Android.Net.ConnectivityManager
4 L_0010: stloc.0
5 L_0011: ldloc.0
6 L_0012: brtrue.s 9 -> ldloc.0
7 L_0014: ldc.i4.0
8 L_0015: ret
9 L_0016: ldloc.0
10 L_0017: callvirt Android.Net.NetworkInfo Android.Net.ConnectivityManager::get_ActiveNetworkInfo()
11 L_001c: stloc.1
12 L_001d: ldloc.1
13 L_001e: brfalse.s 17 -> ldc.i4.0
14 L_0020: ldloc.1
15 L_0021: callvirt System.Boolean Android.Net.NetworkInfo::get_IsConnected()
16 L_0026: ret
17 L_0027: ldc.i4.0
18 L_0028: ret
I have two options:
- Take a fundamental approach: learn the CIL language and write the required code myself; or
- Write the required function in C# and compile it to CIL, thus, getting the required code automatically.
I chose the second option since it’s much easier and faster. Furthermore, I found a very useful site sharplab.io where you can convert code from C# to CIL.
On the left tab, I enter:
bool function() { return true;}
On the right tab, I see among other things:
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: stloc.0
IL_0003: br.s IL_0005
IL_0005: ldloc.0
IL_0006: ret
I insert the obtained code into the library using Simple Assembly Explorer and save the modified DLL. Time to assemble a new APK (provided that I did everything correctly).
Rebuilding the APK
As said above, I am going to use 7z in the uncompressed mode for building. The APK built this way will be larger than the original one, but in this particular case, its size doesn’t matter:
7z.exe a -tzip -mx0 -r0 program_patched_unalign_unsigned.apk .program_apk*.*
FYI: -tzip
is the archive format, -mx0
means no compression, and -r0
means recursive traversal of all subdirectories.
Prior to the building, I delete the META-INF
directory containing the old signature. It’s not needed anymore because I have to sign the APK myself. Then I have to create a signing certificate and copy it to the keystore. If you already have a certificate, you can skip this step. I create a certificate using the keytool utility from the JDK:
"c:AndroidAndroid Studiojrebinkeytool.exe" -genkey -v -keystore keys.keystore -alias key -keyalg RSA -keysize 2048 -validity 10000
As usual, it asks the standard questions:
Enter keystore password:
Re-enter new password:
What is your first and last name?
[
What is the name of your organizational unit?
[
What is the name of your organization?
[
What is the name of your City or Locality?
[
What is the name of your State or Province?
[
What is the two-letter country code for this unit?
[
Is CN=x, OU=x, O=x, L=x, ST=x, C=x correct?
[
Generating 2 048 bit RSA key pair and self-signed certificate (SHA256withRSA) wi
th a validity of 10 000 days
for: CN=x, OU=x, O=x, L=x, ST=x, C=x[
After that, I proceed to signing:
jarsigner.exe -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore keys.keystore -signedjar program_pathed_unalign.apk program_pathed_unalign_unsigned.apk key
The newly-created file, program_pathed_unalign.
, is almost ready for installation. ‘Almost’ because it must be first aligned using the zipalign program from Android SDK Build-Tools. This procedure ensures that all uncompressed files in the archive are aligned relative to the file beginning. This, in turn, makes it possible to access files directly, without copying the data to RAM, which reduces the app’s memory usage.
Aligning:
zipalign.exe -v 4 program_pathed_unalign.apk program_pathed.apk
That’s it! Now I can safely install the program on a phone or emulator and start testing it.
Conclusions
As you can see, the analysis of Xamarin assemblies is no more difficult in comparison with native Android OS apps; you just need to take into account some APK building aspects.

2023.07.20 — Evil modem. Establishing a foothold in the attacked system with a USB modem
If you have direct access to the target PC, you can create a permanent and continuous communication channel with it. All you need for this…
Full article →
2023.04.19 — Kung fu enumeration. Data collection in attacked systems
In penetration testing, there's a world of difference between reconnaissance (recon) and data collection (enum). Recon involves passive actions; while enum, active ones. During recon,…
Full article →
2022.06.01 — Cybercrime story. Analyzing Plaso timelines with Timesketch
When you investigate an incident, it's critical to establish the exact time of the attack and method used to compromise the system. This enables you to track the entire chain of operations…
Full article →
2023.01.22 — Top 5 Ways to Use a VPN for Enhanced Online Privacy and Security
This is an external third-party advertising publication. In this period when technology is at its highest level, the importance of privacy and security has grown like never…
Full article →
2022.02.09 — F#ck da Antivirus! How to bypass antiviruses during pentest
Antiviruses are extremely useful tools - but not in situations when you need to remain unnoticed on an attacked network. Today, I will explain how…
Full article →
2023.07.07 — VERY bad flash drive. BadUSB attack in detail
BadUSB attacks are efficient and deadly. This article explains how to deliver such an attack, describes in detail the preparation of a malicious flash drive required for it,…
Full article →
2022.06.01 — First contact. Attacks on chip-based cards
Virtually all modern bank cards are equipped with a special chip that stores data required to make payments. This article discusses fraud techniques used…
Full article →
2023.07.07 — Evil Ethernet. BadUSB-ETH attack in detail
If you have a chance to plug a specially crafted device to a USB port of the target computer, you can completely intercept its traffic, collect cookies…
Full article →
2023.06.08 — Cold boot attack. Dumping RAM with a USB flash drive
Even if you take efforts to protect the safety of your data, don't attach sheets with passwords to the monitor, encrypt your hard drive, and always lock your…
Full article →
2022.06.03 — Playful Xamarin. Researching and hacking a C# mobile app
Java or Kotlin are not the only languages you can use to create apps for Android. C# programmers can develop mobile apps using the Xamarin open-source…
Full article →