Blind try of MobSF over a suspicious Android sample

@cryptax
7 min readMay 27, 2021

--

MobSF is an open source framework for mobile application analysis. I’ve already used it from time to time, but never in-depth, as the combination DroidLysis+JEB(+potentially Frida, or a Frida derivative like Dexcalibur) works out fine for me. However, hey, we always need to learn new techniques, so I decided it was time to try MobSF for real. In this article, I intentionally use only MobSF, and over a suspicious Android sample I have never analyzed before. Please note I am not an author of this tool, and the way I use it may be non-optimized. I’ll walk you through my analysis, and we’ll sort out what this sample is doing (I don’t know yet!). It’s SHA256 hash is 8810ca80d21173528be71109cd9e5a73afce98a080892643ffdcbe53ac9b6893 .

Static analysis with MobSF

I upload the sample to my own edition of MobSF (version 3.4.4 beta). I like the fact the sample never leaves my host as MobSF runs locally.

For an impatient user, a 3-minute analysis seems a bit long, however it completes without any issue :)

Using online translation, it seems this sample poses as the “Plant vs Zombies” game. “Fun” fact: the application’s certificate is issued for common name “Obfuscapk”. We can expect the sample to be obfuscated 😉. I skip MobSF permission list, I’ll go back to it if needed. The Android API table immediately catches my eye:

Looks like an asset is decrypted and perhaps dynamically loaded afterwards

With MobSF, we can directly click on the links of the table, therefore I jump to DecryptAsset and validate it does what it says: decrypt an asset with AES/ECB, using a hard-coded key.

Which asset is decrypted and is it loaded dynamically?

This easy task is a bit difficult to perform with MobSF because there is no cross reference feature. Workaround: I can view source code, and search content for “decryptasset” (it’s not case sensitive). I notice decryptAsset is used by a constructor of class p0cc175b9.p92eb5ffe.p69691c7b:

public static final String b = "mosco";
...
public p69691c7b(Context context) { this.Z = false; try { InputStream decryptAsset = DecryptAsset.decryptAsset(context.getAssets(), b);...

The same happens in p0cc175b9.p0cc175b9.p0cc175b9.p2510c390 with an asset named “ueiso”. The code also shows that all native librairies are encrypted, and will be decrypted before loading.

Conclusion: the malware decrypts 2 assets (“mosco” and “ueiso”) with a hard-coded AES key, using AES-ECB.

As for dynamic class loading, apparently class p4d236d9a.p856d3eb2.p2852dea9.p9efab239.paed8d309 loads all JARs in a given path, but I am unable to find who uses this class — thus which JAR this might refer to. It is possible the assets “mosco” and “ueiso” decrypt into JARs. We could decrypt the assets statically at this point to check, but I’ll leave this step for later with dynamic analysis.

Executing OS commands?

The Android API table lists several other interesting entries. I particularly like the fact that when I click on the code, it highlights the part of the code that uses that API. For example, see below why MobSF warns the code “executes OS commands”:

The code issues 2 commands: (1) logcat -d -v RAW -s AndroidRuntime:E -p package , which retrieves error messages of the malware, and (2) clears the log. Fortunately, neither command are real issues because they only concern the malware itself and its capacity to debug itself.

MobSF says malware author(s) do not write secure code 😆

The code analysis section of MobSF details implementation issues of the malware. In the case of malware analysis, we do not care so much if developers code insecurely 😉. Yet I spot in there that the malware also decrypts resources, this time with AES-CBC.

CnC?

The section also warns about IP address disclosure. I was hoping to get a CnC from that point, but it’s a “false positive” (for malware analysis) because it relates to code using various gateways depending on the network operator. The “Domain Malware Check” section lists several domains.

Some are obviously benign (e.g maps.google.com), but I’ll definitely check d.wiyux.com, lzn1007.blog.sohu.com, and wap.juliu.net (not shown on the image, below).

Where are those URLs used? I was going to search the code, but the URL table in MobSF shows it for me 😄

The URL table shows where URLs are used. Very handy.

I can immediately check what the malware is sending to hxxp://d.wiyux.com (minor bug/feature request: the corresponding code was not highlighted).

The code shows the malware posts various device information to Wiyux.com. Nothing too sensitive apart the IMEI (returned by p() in did, q() returns the android ID). In some other classes, the code sets cookies for this URL.

The URL lzn1007.blog.sohu.com is the programmer’s website. Not interesting.

public static final String str_help_msg_en = “Plants VS Zombs 2.4\nProgrammer:lzn1007\nMAIL:liangzhenning@gmail.com\nBlog:http://lzn1007.blog.sohu.com\n\nGame Mode:\nDAY:Ordinary mode of existence.\nNIGHT: [..]

Finally, there is a dirty post to wap.juliu.net, where the code sends the smartphone’s IMEI and IMSI. This is a security issue, however I have seen it so many times I am not sure this is enough to classify a sample as “malware”.

The code sends the IMEI, SIM serial number, IMSI and Build model.

Conclusion: the code is dirty and leaks sensitive information (IMEI, IMSI), but this cannot qualify as a CnC.

Dynamic analysis

Time to do some dynamic analysis. In particular, I’m interested in those encrypted assets, code they have. MobSF detects my emulator fine, but unfortunately dynamic analysis fails.

Actually, the error message is not precise enough. I try in a shell and get the following error:

$ adb install ksapp.apk
Performing Streamed Install
adb: failed to install ksapp.apk: Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: Failed to collect certificates from /data/app/vmdl1088091278.tmp/base.apk: META-INF/OBFUSCAT.SF indicates /data/app/vmdl1088091278.tmp/base.apk is signed using APK Signature Scheme v2, but no such signature was found. Signature stripped?]

At this stage, I spent time trying to solve the issue… I installed Lucky Patcher to disable signature verification for my APK, but unfortunately it did not work 😠. I also tried option -t and -d of adb install, but that does not bypass signature verification. Finally, I solved the problem by re-signing the APK myself (but I don’t like this solution — never like to “touch” a sample):

  1. Generate a test keystore with keytool
  2. Sign the “faulty” apk with apksigner (ships with the Android SDK). In my case: ~/Android/Sdk/build-tools/30.0.3/apksigner sign — ks my.jks — min-sdk-version 25 — in ksapp.apk — out signed-ksapp.apk

We need to have MobSF re-analyze signed-ksapp.apk (for dynamic analysis of ksapp.apk, MobSF will only try to install ksapp.apk and does not give the user control to install the app him/herself), and launch dynamic analysis. This time, I ran in a communication problem with my emulator: MobSF complained it could not connect to the emulator. After Lucky Patch install + failed patches, it’s not that surprising, I decided to re-launch my emulator with wiped data. Aaaah, it worked! I like the fact MobSF handles everything itself: finding the emulator, installing the sample, launching a Frida server.

The dynamic analysis UI is nice, but IMHO not ergonomic at all! The colums for Frida Logs or Frida Code Editor are too small (unless your screen is very large!)

I leave all the default options checked, and on the right pane, search for the Frida script aes_key (might be useful to the assets) and load it. By the way, it’s possible to add other scripts to the list by adding them to ./mobsf/DynamicAnalyzer/tools/frida_scripts/others/.

Unfortunately, I do not get any useful information for this sample:

  • Frida logs show nothing interesting [in the case of this sample]
  • The AES script does not launch: probably the sample does not reach the point where AES decryption is triggered?
The sample is stuck on this splash screen and crashes when I click 😢 to try and get more code executed.

Have I missed anything?

I finally resorted to my favorite decompiler: asset decryption is more complicated than expected: it is encrypted twice + the resulting decrypted data follows some special format.

The sample is detected by some AV vendors as “Ksapp”, where this refers to a botnet which can execute remote commands. IMHO, this is a False Positive, because this particular sample does not do that. Some other vendors say that Ksapp is a trojan that steals the IMEI, IMSI and SIM serial number. This is more in line with my analysis.

I think I haven’t missed anything, please feel free to let me know if I did.

Recap / Conclusion

This sample leaks the IMEI, IMSI and SIM serial number to a remote host. The sample is not operational (APK signature issue + crash). A bit disappointing for malware analysis 😉.

MobSF worked well.

  • Pros. I particularly like the “Android API” and “URL” tables. I also like to quickly jump to relevant part of the code. The dynamic analysis works well — compared to House and Dexcalibur, I appreciated it installs the APK + Frida server automatically.
  • Cons (personal!). For malware analysts, the static analysis displays lots of useless information e.g we don’t care how the developer could have secured his/her code better 😉 + Research with the code is limited: MobSF clearly does not have the features of a real decompiler. I miss cross references! Finally, I didn’t like the UI of dynamic analysis : too small, not intuitive, presence of useless features (e.g taking screenshots of the emulator, or viewing the emulator in the web page : we can do that easily from the emulator) while some other feature would need more explanation (what do the options do, indicate if Frida script is loaded or not, respawn an APK etc). On this account, Dexcalibur’s web interface is much better : we understand what buttons do quite intuitively. The good news is that all of this is perfectly fixable 😃

— Cryptax

--

--

@cryptax
@cryptax

Written by @cryptax

Mobile and IoT malware researcher. The postings on this account are solely my own opinion and do not represent my employer.

No responses yet