Android Malware Analysis Series - EDALAT.apk - Part 2.2
Introduction
In the first section of this blog post I did a brief walkthrough of my static analysis process with the Android malware sample. Part 2.2 will detail the dynamic analysis process I undertake. Again this is a learning process for me and is not intended as a professional walk-through. If you are looking for material that focuses heavily on the process I would recommend Maddie Stones amazing work here.
Dynamic Analysis
Android Studio
I started the dynamic process by installing the malware on an emulated Android device. Since I do not want to harm my personal testing device/s. After installing the apk with adb I navigated to the main application dashboard to verify the installation. We can see the malware loaded onto the Android device highlighted in the red rectangle.
I started by loading a frida
script to verify which classes are started at runtime. The goal was to make a cross comparison of my static analysis process. I was able to see the MainActivity
and MainActivity2
. If you want to know more about this script I suggest reading this article here.
Once the classes are loaded and the malware started I submit a random phone number into the UI. The phone number needed to start with 980. I was immediately met with application asking to send and view sms messages as I had observed in the permissions of the decompiled AndroidManidest.xml
file.
I allowed the SMS permissions on the device and the malware stalls for a second. But eventually loads the hardcoded URL. Though appears to time out due to the dead domain. This is one of the malicious domains we saw earlier in the MainActivity2
class.
Doing a quick analysis of the local storage in the malwares directory we can then see the number is saved to the shared_prefs
folder in an XML
file called info. Which was loaded from the MainActivity
class into the connect
class in part 2.1.
Catching MyReceiver class
In the static analysis section we observed that the malware will capture sms sent to the device via the MyReceiver class. I wanted to test this by sending a sms to the emulator and catching the class loading via the classLoader.js
script in frida
.
In the screenshot below we can see the class being instantiated when a sms is sent to the emulated device.
File System Access Analysis
In this section I uninstalled the apk, started the frida server on my emulated device, and then hooked the malware with the following script by French Yeti.
https://codeshare.frida.re/@FrenchYeti/android-file-system-access-hook/
This allowed frida
to dump the application state changes on a file system level. We could see the state changes being saved to the shared_prefs
folder and the malware loading the malicious webView
via the components View
. Again verifying some of the prior analysis I had done leading up to this.
frida -U -f realrat.siqe.holo -l file-system-access-hook ✭ master
____
/ _ | Frida 16.0.2 - A world-class dynamic instrumentation toolkit
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at https://frida.re/docs/home/
. . . .
. . . . Connected to Android Emulator 5554 (id=emulator-5554)
Spawned `realrat.siqe.holo`. Resuming main thread!
[Android Emulator 5554::realrat.siqe.holo ]-> ---------------------------
[Java::File.new.1] New file : /data/user/0/realrat.siqe.holo/shared_prefs/info.xml.bak
---------------------------
[Java::FileOuputStream.new.0] New output stream to file ([unknow]<File:-983702262>):
---------------------------
[Java::FileOuputStream.new.1] New output stream to file ([unknow]):
---------------------------
[Java::FileOuputStream.write.2] Write 115 bytes from 0 ([unknow]<File:-983702262>):
0000 3C 3F 78 6D 6C 20 76 65 72 73 69 6F 6E 3D 27 31 ...ml version.'.\n0010 2E 30 27 20 65 6E 63 6F 64 69 6E 67 3D 27 75 74 ..' encoding.'ut\n0020 66 2D 38 27 20 73 74 61 6E 64 61 6C 6F 6E 65 3D f-.' standalone.\n0030 27 79 65 73 27 20 3F 3E 0A 3C 6D 61 70 3E 0A 20 'yes' ....map.. \n0040 20 20 20 3C 73 74 72 69 6E 67 20 6E 61 6D 65 3D .string name.\n0050 22 70 68 6F 6E 65 22 3E 39 38 30 32 32 33 36 36 "phone".........\n0060 39 33 3C 2F 73 74 72 69 6E 67 3E 0A 3C 2F 6D 61 .../string.../ma\n0070 70 3E 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 p..\n [32640] bytes of zeroes
---------------------------
[Java::File.read.2] New file : /system/lib
---------------------------
[Java::File.new.1] New file : /system/lib/net.properties
---------------------------
[Java::FileInputStream.new.0] New input stream from file (/system/lib/net.properties):
---------------------------
[Java::FileOuputStream.new.0] New output stream to file ([unknow]<File:94129132>):
---------------------------
[Java::FileOuputStream.new.1] New output stream to file ([unknow]):
---------------------------
[Java::FileOuputStream.new.0] New output stream to file ([unknow]<File:94129132>):
---------------------------
[Java::FileOuputStream.new.1] New output stream to file ([unknow]):
---------------------------
[Java::File.new.1] New file : /data/user/0/com.android.chrome
---------------------------
[Java::File.new.1] New file : /data/user_de/0/com.android.chrome
---------------------------
[Java::File.new.1] New file : /data/user/0/com.android.chrome
---------------------------
[Java::File.new.1] New file : /system/app/Chrome/Chrome.apk
---------------------------
[Java::File.new.1] New file : /system/app/Chrome/Chrome.apk
---------------------------
[Java::File.new.1] New file : /system/app/Chrome/lib/x86
---------------------------
[Java::File.new.1] New file : /system/app/Chrome/Chrome.apk!/lib/x86
---------------------------
[Java::File.new.1] New file : /system/lib
---------------------------
[Java::File.new.1] New file : /vendor/lib
---------------------------
[Java::File.new.1] New file : /system/lib
---------------------------
[Java::File.new.1] New file : /vendor/lib
---------------------------
[Java::File.new.1] New file : /system/app/Chrome/Chrome.apk
---------------------------
[Java::File.new.1] New file : /data/local/tmp/webview-command-line
---------------------------
[Java::FileInputStream.new.0] New input stream from file (/data/local/tmp/webview-command-line):
---------------------------
[Java::File.new.1] New file : /system/app/Chrome/Chrome.apk
---------------------------
[Java::File.new.1] New file : /system/app/Chrome/Chrome.apk
---------------------------
[Java::File.new.1] New file : /data/user/0/realrat.siqe.holo/shared_prefs/WebViewChromiumPrefs.xml.bak
---------------------------
[Java::File.read.2] New file : /data/user/0/realrat.siqe.holo/app_webview/metrics_guid
---------------------------
[Java::File.read.2] New file : /data/user/0/realrat.siqe.holo/app_webview/variations_seed_new
---------------------------
[Java::File.read.2] New file : /data/user/0/realrat.siqe.holo/app_webview/variations_seed
---------------------------
[Java::FileInputStream.new.0] New input stream from file (/data/user/0/realrat.siqe.holo/app_webview/variations_seed_new):
---------------------------
[Java::FileInputStream.new.0] New input stream from file (/data/user/0/realrat.siqe.holo/app_webview/variations_seed):
---------------------------
[Java::File.read.2] New file : /data/user/0/realrat.siqe.holo/app_webview/variations_stamp
---------------------------
[Java::File.read.2] New file : /data/user/0/realrat.siqe.holo/app_webview/variations_seed_new
---------------------------
[Java::File.read.2] New file : /data/user/0/realrat.siqe.holo/app_webview/webview_data.lock
---------------------------
[Java::File.new.1] New file : /data/user/0/com.android.chrome
---------------------------
[Java::File.new.1] New file : /data/user_de/0/com.android.chrome
---------------------------
[Java::File.new.1] New file : /proc/meminfo
---------------------------
[Java::FileInputStream.new.0] New input stream from file (/proc/meminfo):
---------------------------
[Java::File.new.1] New file : /data/user/0/com.android.chrome
---------------------------
[Java::File.read.2] New file : /data/user/0/realrat.siqe.holo/app_webview/variations_stamp
---------------------------
[Java::FileOuputStream.new.0] New output stream to file ([unknow]<File:-1232766913>):
---------------------------
[Java::FileOuputStream.new.1] New output stream to file ([unknow]):
---------------------------
[Java::FileInputStream.read.2] Read from file,offset,len (/proc/meminfo,0,8192)
[8192] bytes of zeroes
---------------------------
[Java::File.read.2] New file : /data/user/0/realrat.siqe.holo/app_webview/paks
---------------------------
[Java::FileOuputStream.write.2] Write 36 bytes from 0 ([unknow]<File:94129132>):
0000 6C 69 62 63 6F 72 65 2E 69 6F 2E 44 69 73 6B 4C libcore.io..isk.\n0010 72 75 43 61 63 68 65 0A 31 0A 32 30 31 31 30 35 ru.ache.........\n0020 0A 32 0A 0A 38 25 42 31 25 44 41 25 41 46 25 44 .....%..%..%..%.\n0030 38 25 41 41 25 32 30 25 44 38 25 41 43 25 44 38 .%..%..%..%..%..\n0040 25 41 46 25 44 42 25 38 43 25 44 38 25 41 46 25 %..%..%..%..%..%\n0050 32 30 25 44 39 25 38 36 25 44 38 25 42 35 25 44 ..%..%..%..%..%.\n0060 38 25 41 38 25 32 30 25 44 41 25 41 39 25 44 38 .%..%..%..%..%..\n0070 25 42 31 25 44 38 25 41 46 00 00 00 00 00 00 00 %..%..%..\n [8064] bytes of zeroes
---------------------------
[Java::FileOuputStream.new.1] New output stream to file ([unknow]):
---------------------------
[Java::FileOuputStream.write.2] Write 127 bytes from 0 ([unknow]<File:-1232766913>):
0000 3C 3F 78 6D 6C 20 76 65 72 73 69 6F 6E 3D 27 31 ...ml version.'.\n0010 2E 30 27 20 65 6E 63 6F 64 69 6E 67 3D 27 75 74 ..' encoding.'ut\n0020 66 2D 38 27 20 73 74 61 6E 64 61 6C 6F 6E 65 3D f-.' standalone.\n0030 27 79 65 73 27 20 3F 3E 0A 3C 6D 61 70 3E 0A 20 'yes' ....map.. \n0040 20 20 20 3C 69 6E 74 20 6E 61 6D 65 3D 22 6C 61 .int name."la\n0050 73 74 56 65 72 73 69 6F 6E 43 6F 64 65 55 73 65 st.ersion.ode.se\n0060 64 22 20 76 61 6C 75 65 3D 22 33 34 39 37 31 30 d" value."......\n0070 30 31 37 22 20 2F 3E 0A 3C 2F 6D 61 70 3E 0A 00 ..." /.../map..\n [32640] bytes of zeroes
---------------------------
[Java::File.read.2] New file : /data/user/0/realrat.siqe.holo/cache/WebView
Droidlysis
Droidlysis
is a great tool written by cryptax for automatic disassembly and analysis.
I use a Docker container since it is easier for me to spin up an instance run an apk file through the application without the need to worth about storage.
Below is a quick screenshot of the report output. Catching all of the same permissions, components, classes and the c2 server we found in the static analysis phase.
python3 droidlysis --input ../355cd2b71db971dfb0fac1fc391eb4079e2b090025ca2cdc83d4a22a0ed8f082.apk
Processing: ./../355cd2b71db971dfb0fac1fc391eb4079e2b090025ca2cdc83d4a22a0ed8f082.apk ...
Filename: ./../355cd2b71db971dfb0fac1fc391eb4079e2b090025ca2cdc83d4a22a0ed8f082.apk
Launching unzip process on ./../355cd2b71db971dfb0fac1fc391eb4079e2b090025ca2cdc83d4a22a0ed8f082.apk with output dir=./355cd2b71db971dfb0fac1fc391eb4079e2b090025ca2cdc83d4a22a0ed8f082.apk-355cd2b71db971dfb0fac1fc391eb4079e2b090025ca2cdc83d4a22a0ed8f082/unzipped
caution: filename not matched: classes2.dex
============= Report ============
Sanitized basename : 355cd2b71db971dfb0fac1fc391eb4079e2b090025ca2cdc83d4a22a0ed8f082.apk
SHA256 : 355cd2b71db971dfb0fac1fc391eb4079e2b090025ca2cdc83d4a22a0ed8f082
File size : 2630329 bytes
Is small : False
Nb of classes : 2133
Nb of dirs : 136
Certificate properties
algo : SHA1withRSA(weak)
dev : True
serialno : 936eacbe07f201df
country : 235
owner : EMAILADDRESS=android@android.com,CN=Android,OU=Android,O=Android,L=MountainView,ST=California,C=US
timestamp : (2008, 2, 29, 6, 3, 46)
year : 2008
Manifest properties
activities : ["'ir.siqe.holo.MainActivity2'", "'ir.siqe.holo.MainActivity'"]
listens_incoming_sms: True
main_activity : ir.siqe.holo.MainActivity
package_name : realrat.siqe.holo
permissions : ['INTERNET', 'INTERNET', 'ACCESS_NETWORK_STATE', 'RECEIVE_SMS', 'READ_SMS']
receivers : ["'ir.siqe.holo.MyReceiver'"]
Smali properties / What the Dalvik code does
javascript : True (Loads JavaScript in WebView)
json : True (Uses JSON objects)
nop : True (DEX bytecode contains NOP instructions.)
post : True (Tries to perform an HTTP POST. There might be False Positives...)
receive_sms : True (Receiving SMS)
user_agent : True (Specifies a HTTP User Agent)
webview : True (Displays a URL in the WebView. Very much used to display custom pages with JavaScript, sometimes malicious...)
Wide properties / What Resources/Assets do
urls : ['https://google.com', 'https://eblaqie.org']
ARM properties / What native ARM libraries do
DEX properties / About classes.dex format
magic : 35
Kit properties / Detected 3rd party SDKs
appcompat : True (AndroidX Support Library)
googlegson : True
okhttp : True (Square OkHttp client for Android)
okio : True (Square I/O API for Java)
support : True (Android Support)
END
https://github.com/cryptax/droidlysis
APKiD
Running a quick scan of the apk through APKiD
we can see it captures the virtual machine check and a compiler check.
https://github.com/rednaga/APKiD
Conclusion
This concludes part 2.2 I will be working through another set of Android malware samples in the coming weeks. Feel free to ping me on mastadon or twitter with any questions.