/* Lab */

Android Malware Analysis

Jan 18, 2023 · 10 min read

1. Preparing the Lab

We’ve chosen to use the first configuration:

Android Studio and an emulator that needs a virtualization backend (needs more resources)

We started with option 3, but encountered issues with the VirtualBox image, particularly the smartphone emulator, which kept loading and timing out. Option 2 is terrible because installing malware on the phone doesn’t sound like a great idea.

The computer is running Windows 11 with WSL enabled. WSL uses a subset of Hyper-V. The quickest way to disable Hyper-V is to run the reversible command (auto instead of off) in PowerShell and then reboot the computer.

bcdedit /set hypervisorlaunchtype off

More details about bcedit command here.

Now, since we deactivated Hyper-V and can no longer use WSL, we’re going to use Powershell 💀. Also we’ll use Ghidra instead of radare2.

This is the only configuration/compromise we had to do.

Everything seems good, it’s time to start working.

2. Lab Exercices

2.1 Labs from Teaching Android Mobile Security

A. Programming an antidote for a ransomware

We used the emulated smartphone’s camera to take a selfie, this is what we got:

Upon opening the the app, we get the following screen:

We find that the images we’ve taken are now encrypted:

After decompiling with JadX, we find this important function in MainService.

The antidote is simple, we have to copy the source of the application while changing var.encrypt() by var.decrypt().

And of course it works !

B. Packers

Upon giving PackLab the permission to access the contacts, they were deleted. In Jadx we can see that when permissions are given, beEvilSetup is called. The details of this method are:

public native void decodeMethod(String paramString1, String paramString2);

decodeMethod is a native method that will load the code of the beEvil method which is the malicious method. Let’s look at the content of native-lib to understand how it does it.

The loaded asset butterfly.png is indeed not an image, it’s probably just raw data:

In native-lib, this data is xored with the word register w11 which remains a constant in the loop’s body block. To find the value of life w11 lies in previous block: It’s 0x42.

The next step is to download the data in butterfly.png, write a python script to emulate the xoring done by decodeMethod. The result is a new file that we’ll name unpacked_malware.dex. Indeed it’s a Dalvik dex file:

We can now ran Jadx again to decompile it and see the content of the beEvil method:

Unfortunately, there is no remedy to this malware.

C. Hacking a spyware

The used permissions are:

<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>

The only permissions that immediately jump out to me are INTERNET, ACCESS_FINE_LOCATION which should not be needed for a kitchen timer.

KitchenTimerService is a service used to schedule tasks that fire KitchenTimerService.ACTION ("Kitchen Timer Service") intents. The receiver of this intent is registered in onCreate method of the Main class.

When this intent is received, user data containing device identifier, phone number and geographic address of the user is sent out to an external server as GET query parameters.

I’ve customized the provided gist to create a python server listening on 8080. We think the Java 8 part was necessary because the jar throws an exception. we decided to do the address translation manually:

  1. Run the emulator with a writable file system
emulator -avd Pixel_6_Pro_API_24 -partition-size 512 -writable-system
  1. Acquire root privileges in the emulator with adb root and remount the /system partition in writable mode with adb remount. Finally run adb shell.
  2. Run echo "10.0.2.2 14243444.com" >> /etc/hosts. In essense, 10.0.2.2 should point to the host machine.
  3. The only remaining task is to redirect outgoing packets from 10.0.2.2:80 to 10.0.2.2:8080
iptables -t nat -A OUTPUT -p tcp -d 10.0.2.2 --dport 80 -j DNAT --to-destination 10.0.2.2:8080

Actually nevermind the last step if you can run your python server on the port 80 directly.

Let’s finally see what this malware does:

The spyware crashes before it can figure out the geocoordinates. We imagine this is because our Python server sends an empty reply. We changed that, and now it successfully gets the geocoordinates. It sometimes randomly opens up Japanese google, we guess this is a form of diversion ? Not sure. but anyways, we confirmed our suspicions about this user tracking spyware.

3. The challenge begins

1. The easy one

This malware is a ransomware that encrypts files on the victim’s smartphone.

When the malware is launched for the first time (detection via preferences), it launches the newone activity. This activity encrypts files starting with the SD Card, but we observed that the images we took are also encrypted. we guess this is because listFiles() returns the path ../.

The encryption function:

The second time this application is launched, the lock activity is started. This shows the classic ransomware screen above. Reading more code, this malware encrypts files using DES (Data Encryption Standard). This is a symmetric encryption algorithm whose key is present in the code:

But it is easier to solve challenge that ransomware and decrypt the file system:

You can get this.val$xx by clicking Copy:

Then we sha_1 . md5 this value:

And of course it works.

2. The easy one #2

Using some quality OCR to dechipher the program:

It doesn’t tell much except the existence of a password and/or a timer to exit the program. Oh, it seems we can’t exit the program because the malware forces the focus back on the app. This is the case even if the phone is rebooted.

Clicking the back button few times shows this prompt:

Looking at JadX, the solution to the prompt challenge is easy to spot:

And of course it works.

3. The hard one

Upon installing the app, Nothing happened.

We thought that adb didn’t install the app correctly, so we went on to install it again. Of course, it doesn’t work. It is also impossible to delete the app. It seems that our malware is installed. Using JadX, we get a hardly readable code, the few thing that we can notice right away are:

Looking at the ressources, we find our first clues:

Indeed when visiting the accessibility settings we find:

Looking at the devtools Package summary we found this:

The malware is installed as a privileged app, which explains why it can’t be uninstalled. But how can it be installed on a read-only file system ?

ProxyService also runs some services:

Let’s try to gain control of the external file.

a. Getting the secret key

Which gives the output:

b. decrypting the file using python

And it actually works.

We find the code behind the services run by ProxyService. This code is hard to read and we give up 😞.