Últimamente, en el Laboratorio de Amenazas de la EFF, nos hemos centrado mucho en el ecosistema de malware de Android y en proporcionar herramientas para su análisis. Hemos observado que han aparecido muchas muestras de malware para Android de la familia tor-hydra, que se hacen pasar por aplicaciones bancarias para atraer a clientes desprevenidos y hacer que las instalen. En este post, tomaremos un ejemplo de una de estas muestras y la analizaremos utilizando herramientas de código abierto disponibles para cualquiera.
En un vistazo
El ejemplo que vamos a analizar fue visto por primera vez el 1 de marzo de 2022. Este malware en particular se presenta como la aplicación bancaria de BAWAG, una importante institución financiera de Austria. Cuando se ejecuta por primera vez, la aplicación pide al usuario que le dé permiso a los "servicios de accesibilidad". El permiso de los servicios de accesibilidad concede a la aplicación un amplio acceso para leer la pantalla e imitar la interacción del usuario. Una vez concedido el permiso, la aplicación se pone en segundo plano. Cualquier intento por parte del usuario de desinstalar la aplicación es impedido por la aplicación interrumpiendo y cerrando los diálogos de desinstalación. Si se intenta abrir la aplicación de nuevo, tampoco se consigue nada.
Analizando el paquete APK de Android
AndroidManifest.xml
El archivo de manifiesto de la aplicación Android contiene una lista de permisos, actividades y servicios que proporciona una aplicación. Si una actividad no aparece en el manifiesto de la aplicación, la aplicación no puede lanzar esa actividad. Utilizando una herramienta de análisis estático de Android como jadx
o apktool
podemos echar un vistazo al manifiesto XML. El manifiesto de la aplicación de malware solicita una amplia gama de permisos, incluyendo la capacidad de leer y enviar mensajes SMS (una forma común de propagación del malware), solicitar la instalación y eliminación de paquetes, leer contactos, iniciar llamadas y solicitar el servicio de accesibilidad antes mencionado. Además, se hace referencia a una serie de clases que no están definidas en ninguna parte de nuestro código jadx
-reversed:
com.ombththz.ufqsuqx.bot.components.commands.NLService
com.ombththz.ufqsuqx.bot.components.injects.system.InjAccessibilityService
com.ombththz.ufqsuqx.bot.components.locker.LockerActivity
com.ombththz.ufqsuqx.bot.components.locker.LockerActivity$DummyActivity
com.ombththz.ufqsuqx.bot.components.screencast.ScreencastService
com.ombththz.ufqsuqx.bot.components.screencast.ScreencastStartActivity
com.ombththz.ufqsuqx.bot.components.screencast.UnlockActivity
com.ombththz.ufqsuqx.bot.components.socks5.Socks5ProxyService
com.ombththz.ufqsuqx.bot.HelperAdmin$MyHomeReceiver
com.ombththz.ufqsuqx.bot.PermissionsActivity
com.ombththz.ufqsuqx.bot.receivers.MainReceiver
com.ombththz.ufqsuqx.bot.sms.ComposeSmsActivity
com.ombththz.ufqsuqx.bot.sms.HeadlessSmsSendService
com.ombththz.ufqsuqx.bot.sms.MmsReceiver
com.ombththz.ufqsuqx.bot.sms.SmsReceiver
com.ombththz.ufqsuqx.core.injects_core.Screen
com.ombththz.ufqsuqx.core.injects_core.Worker
com.ombththz.ufqsuqx.core.PeriodicJobReceiver
com.ombththz.ufqsuqx.core.PeriodicJobService
com.ombththz.ufqsuqx.MainActivity
info.pluggabletransports.dispatch.service.DispatchReceiver
info.pluggabletransports.dispatch.service.DispatchService
info.pluggabletransports.dispatch.service.DispatchVPN
org.torproject.android.service.OrbotService
El hecho de que el manifiesto haga referencia a las actividades, servicios y receptores que quiere que se ejecuten sin definirlos es el primer indicio de que estamos ante un "Android dropper".
Desarmando los Droppers para Android
Un dropper para Android es un malware que ofusca su comportamiento ocultando su carga útil y solamente descodificando y cargando el código que necesita en tiempo de ejecución. Como Ahmet Bilal explica, esto dificulta la detección del malware por parte de los investigadores antivirus y de seguridad, ya que incluye "reflexión, ofuscación, aplanamiento del flujo de código y códigos basura para hacer que [el] proceso de desempaquetado sea sigiloso". Aunque sea sigiloso, los pasos que da el malware para ocultarse pueden ser detectados y subvertidos con un poco de ayuda del kit de herramientas de instrumentación dinámica Frida. Frida es capaz de inyectarse en el flujo de control de una aplicación en ejecución, introduciendo su propio código. Esto puede ser útil para detectar los métodos típicos que utiliza el malware para disfrazarse y cargar la carga útil subyacente. En este caso, podemos utilizar un breve script para detectar que las clases Java se cargan dinámicamente:
var classLoader = Java.use('java.lang.ClassLoader');
var loadClass = classLoader.loadClass.overload('java.lang.String', 'boolean');
.implementation = function(str, bool){
loadClassconsole.log("== Detected ClassLoader usage ==");
console.log("Args: ", str, bool);
return this.loadClass(str, bool)
}
Al ejecutar este código, obtenemos
$ frida -U -f com.ombththz.ufqsuqx -l class-loader-usage.js --no-pause
____
/ _ | Frida 15.1.16 - 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/
Spawned `com.ombththz.ufqsuqx`. Resuming main thread!
[Android Emulator 5554::com.ombththz.ufqsuqx]-> == Detected ClassLoader usage ==
Args: com.honey.miletes.k false
== Detected ClassLoader usage ==
Args: android.support.v4.content.FileProvider false
== Detected ClassLoader usage ==
Args: com.ombththz.ufqsuqx.App false
== Detected ClassLoader usage ==
Args: com.ombththz.ufqsuqx.MainActivity false
== Detected ClassLoader usage ==
Args: com.ombththz.ufqsuqx.core.injects_core.Worker false
== Detected ClassLoader usage ==
Args: com.ombththz.ufqsuqx.bot.PermissionsActivity false
== Detected ClassLoader usage ==
Args: org.torproject.android.service.OrbotService false
Las clases que nos faltan sí se cargan dinámicamente.
Las iteraciones anteriores del malware tor-hydra
cargaban dinámicamente un archivo dex
(un archivo ejecutable de Android Dalvik), que podía verse con adb logcat
, y utilizaban la llamada syscall unlink
para eliminar ese archivo, que se vería en una llamada strace
. Para esta aplicación, podemos utilizar el comando
monkey -p com.ombththz.ufqsuqx -c android.intent.category.LAUNCHER 1 && set `ps -A | grep com.ombththz.ufqsuqx` && strace -p $2
para ver las llamadas al sistema en tiempo real. No observamos que se utilizara unlink
en esta muestra, por lo que esta iteración estaba haciendo algo diferente. Java proporciona un método en java.io.File
llamado delete
, que no activará la llamada al sistema de unlink
. Usando este script, podemos detectar cuando se usa ese método, alertarnos del archivo que se intentó borrar, y hacer que no se opere
var file = Java.use("java.io.File")
.delete.implementation = function(a){
fileconsole.log("=> Detected and bypassed Java file deletion: ", this.getAbsolutePath());
return true;
}
Los primeros archivos eliminados son de interés:
=> Detected and bypassed Java file deletion: /data/user/0/com.ombththz.ufqsuqx/tyfkjfUjju/HjIgfhjyqutIhjf/tmp-base.apk.gjGyTF88583765359401054429.88g
=> Detected and bypassed Java file deletion: /data/user/0/com.ombththz.ufqsuqx/tyfkjfUjju/HjIgfhjyqutIhjf/dfGgIgyj.HTgj
=> Detected and bypassed Java file deletion: /data/user/0/com.ombththz.ufqsuqx/tyfkjfUjju/HjIgfhjyqutIhjf/base.apk.gjGyTF81.88g
=> Detected and bypassed Java file deletion: /data/user/0/com.ombththz.ufqsuqx/tyfkjfUjju/HjIgfhjyqutIhjf
=> Detected and bypassed Java file deletion: /data/user/0/com.ombththz.ufqsuqx/shared_prefs/multidex.version.xml.bak
=> Detected and bypassed Java file deletion: /data/user/0/com.ombththz.ufqsuqx/shared_prefs/pref_name_setting.xml.bak
=> Detected and bypassed Java file deletion: /data/user/0/com.ombththz.ufqsuqx/files
=> Detected and bypassed Java file deletion: /data/user/0/com.ombththz.ufqsuqx/shared_prefs/prefs30.xml.bak
=> Detected and bypassed Java file deletion: /data/user/0/com.ombththz.ufqsuqx/files/all_tor.zip
Una vez que emitamos un adb pull
para descargar el archivo base.apk.gjGyTF81.88g
del dispositivo, podemos usar jadx
de nuevo para determinar que éste incluye las definiciones de clase que faltan y a las que se hace referencia en el manifiesto.
Investigar la carga útil sin empaquetar
Mirando en estos archivos, hay un método de ofuscación de cadenas que aparece miles de veces a lo largo del código, inalterado de instancia en instancia:
private static String $(int i, int i2, int i3) {
char[] cArr = new char[i2 - i];
for (int i4 = 0; i4 < i2 - i; i4++) {
char) ($[i + i4] ^ i3);
cArr[i4] = (
}return new String(cArr);
}
Siempre que veamos una llamada que se parezca a $(166, 217, 28670)
en el código, se refiere a esta función y utiliza la variable $
en el mismo ámbito para devolver una cadena. Podemos usar una caja de arena (sandbox) de Java como esta para definir la variable $
de ámbito local, el método $
, e imprimir la cadena decodificada.
En sources/com/ombththz/ufqsuqx/bot/network/TorConnectionHelper.java
vemos un método que parece una pista prometedora llamado loadAdminUrl
. Decodificando la llamada $(556, 664, 4277)
obtenemos una dirección codificada con extensión onion en base64:
http://loa5ta2rso7xahp7lubajje6txt366hr3ovjgthzmdy7gav23xdqwnid.onion/api/mirrors
Esta dirección está disponible en la red Tor, y contiene una URL codificada en base64 que hace referencia al servidor de comando y control (C&C), el servidor desde el que el operador del malware emite los comandos. El autor de este post se puso en contacto con el Proyecto Tor el 7 de marzo para informarles de este servidor C&C. En el arranque de la aplicación, la red Tor se conecta mediante un código extraído de Orbot para descubrir el servidor de C&C, y luego la conexión Tor se corta rápidamente. Al principio de esta investigación, el dominio hacía referencia a yuuzzlllaa.xyz
, pero desde entonces ha cambiado a zhgggga.in
. Podemos ver una página de inicio de sesión para el administrador del servidor C&C cuando se accede:
Una de las principales características de la red Tor es la resistencia a la censura. Si puede acceder a la red Tor, puede acceder a información y sitios web que no pueden ser retirados fácilmente debido a la forma en que está diseñada la red. Esto es algo bueno para los disidentes en los regímenes de censura o para los denunciantes que intentan hacer llegar información privilegiada a los periodistas: los servicios de los que dependen estarán disponibles incluso si sus adversarios no quieren que lo estén. Sin embargo, se trata de una moneda de doble cara: en este caso, el malware también es capaz de dirigir los dispositivos de las víctimas a los servidores de C&C de forma que no puedan ser retirados. No hay forma de tener una cosa sin la otra y mantener la integridad de la red intacta. En este caso, el dominio de clearnet yuuzzlllaa.xyz
fue presumiblemente retirado después de ser reportado y luego el operador del malware creó otro dominio en zhgggga.in
sin mucha interrupción del comando y control del malware. En estos casos, denunciar los dominios de C&C maliciosos parece un juego de golpear al topo: tan pronto como se retira uno, aparece el siguiente.
En el archivo com/ombththz/ufqsuqx/bot/DexTools.java
vemos un método interesante, run()
, que carga un payload de la etapa 2 desde la ruta url /payload
del admin C&C. Este es un archivo dex
que puede ser decodificado por jadx
a un ID de aplicación de com.fbdevs.payload
. Desafortunadamente para nuestro análisis, este archivo contiene principalmente código no interesante y no malicioso.
Mirando la ruta om/ombththz/ufqsuqx/bot/components/
, muchos de los componentes parecen ser heredados directamente del malware Android BianLian, del que se puede encontrar un excelente análisis aqui. Uno de los componentes no incluidos en esta iteración anterior se encuentra en la ruta socks5, que abre un servidor proxy a un host especificado para recibir comandos y lanzar ataques. Todos los componentes son activados y controlados por el servidor C&C a través de una conexión Firebase Cloud Messaging (FCM), lo que permite enviar mensajes dirigidos a dispositivos específicos.
Lucha contra el malware
A pesar de las técnicas relativamente avanzadas empleadas para frustrar el análisis, se utilizaron algunas potentes herramientas de código abierto de acceso público para interrumpir el flujo de control y aplicar ingeniería inversa a esta muestra. Un malware más complejo detectará los perfiles de hardware y podrá determinar que se está ejecutando en un emulador, y cambiará su comportamiento para ocultar aún más su funcionalidad principal. Otros desplegarán el código malicioso en cargas útiles más profundas en un intento de ocultar aún más su verdadero comportamiento. Sin embargo, este ejemplo muestra cómo se pueden dar unos sencillos pasos para pelar esas capas y descubrir finalmente el flujo de control de una nueva clase de malware. En el futuro, otras muestras de esta clase pueden ser analizadas de manera muy similar para seguir los cambios en el ecosistema y cómo los desarrolladores de malware están respondiendo a los intentos de mitigar su eficacia.
Analizar los programas maliciosos y rastrear su evolución es importante para combatirlos. No solamente da lugar a mejores firmas para que el software antivirus las utilice y proteja a los usuarios, sino que nos ayuda a entender qué protecciones son necesarias en cuanto a sistema operativo y orienta las recomendaciones de seguridad de la plataforma. A veces, puede llevar al cierre de los servidores de C&C y a que los objetivos de las redes de bots obtengan un respiro muy necesario. Y, por último, ofrece a los usuarios información sobre el software que se ejecuta en sus dispositivos para que puedan recuperar el control.