n0ps

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.

Untitled

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.

Untitled

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.

Untitled

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.

Untitled

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.

Untitled

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.

Untitled

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.

Untitled

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.