Eres un APK muy malo…

Las estafas a través de aplicaciones instaladas en nuestros smartphones están a la orden del día: suscripción a servicios premium, llamadas a números internacionales, robo de información, etc…. . Si te dedicas a este mundillo de la seguridad, seguro que alguna vez te haya tocado analizar un apk que uno de los jefes se ha instalado y el móvil ha empezado a hacer cosas raras. En este artículo vamos a analizar un apk identificado como malware (SMS-Fraud).

EL FICHERO APK

El fichero .apk o Android Package File es un formato específico para aplicaciones android con extension .apk (basicamente se trata de un fichero .zip renombrado) cuya estructura es la siguiente:

  • AndroidManifest.xml: es el fichero de configuración de la aplicación. Está formado por:
    • Permisos que necesita la aplicación para su correcto funcionamiento.
    • Pantallas o Activities de la aplicación.
    • Servicios o Services que van a correr en segundo plano.
    • Receptores o Receivers que pueden manejar eventos del sistema o de otras aplicaciones, como el reinicio del móvil o la llegada de un SMS.
  • assets: directorio en el que se almacenan ficheros específicos de la aplicación.
  • classes.dex: este fichero es el bytecode de la aplicación necesario para que pueda ejecutarse en la máquina virtual de Android (Dalvik VM). Los ficheros .dex son para la Dalvik VM como los ficheros .class de Java lo son para la JVM.
  • lib: directorio en el que se almacenan librerías de código nativo de las que depende la ejecución de la aplicación.
  • META-INF: directorio que almacena el fichero MANIFEST.MF que contiene los hashes de todos los recursos utilizados por la aplicación con el objetivo de verificar que no se han modificado. También contiene el fichero CERT.RSA que contiene la clave pública del desarrollador.
  • res: directorio en el que se almacenan todos los recursos como ficheros xml, imágenes, ficheros de estilos, etc… .
  • resources.arsc: fichero que relaciona todos y cada uno de los recursos con su identificador correspondiente.

Estos ficheros .apk son descargados desde markets oficiales (o desde uno no oficial, con ciertos riesgos) y se instalan en el dispositivo. Nosotros para nuestras pruebas hemos descargado un apk de Koodous que es un antivirus social formado por una comunidad que es la que analiza los apks:

Nosotros para el análisis estático hemos descargado EroTube.apk, un apk identificado en Koodous como SMS-Fraud.

TIPOS DE ANÁLISIS

Para llevar a cabo un análisis completo de una aplicación android es necesario realizar dos tipos de análisis:

  • Análisis estático: se basa en los recursos, fichero de propiedades y código fuente de la aplicación.
  • Análisis dinámico: se basa en el comportamiento de la aplicación durante su ejecución controlada.

En principio vamos a basar este artículo en el análisis estático.

ANÁLISIS ESTÁTICO

Vamos a dividir este tipo de análisis en varios puntos con el objetivo de llevar un orden e intentar no dejarnos cosas por revisar. Los puntos son los siguientes:

  • Análisis de permisos: para ellos revisaremos el fichero de configuración AndroidManifest.xml .
  • Exploración de recursos: revisaremos los directorios de recursos de la aplicación con el objetivo de identificar posibles imágenes o ficheros que sean un indicio de actividad sospechosa.
  • Búsqueda de cadenas: buscaremos patrones dentro del código de la aplicación ¿al que accederemos a través del ficero classes.dex? .
  • Revisión del código fuente: realizando la decompilación del fichero classes.dex (código compilado para la Dalvik VM) accederemos a los ficheros .jar con el código fuente.
  • Verificación el certificado: comprobaremos la validez del certificado así como la información del mismo.

HERRAMIENTAS PARA ANÁLISIS ESTÁTICO

Vamos a utilizar tres herramientas principalmente:

DEX2JAR

Esta herramienta nos permitirá convertir ficheros .dex, compilados para la Dalvik VM, en ficheros .jar, compilados para la JVM. Sólo nos sirve para ficheros de código fuente:

 

APKTOOL

Esta herramienta nos sirve para la extracción de recursos en binario, como por ejemplo el fichero AndroidManifest.xml :

JD-GUI

Esta herramienta nos servirá para abrir los ficheros .class y poder leer el código fuente. También podremos guardar los recursos .class para obtener los correspondientes .java :

PRIMER PUNTO: ANÁLISIS DE COMPONENTES

Como primer punto del análisis de nuestro apk, vamos a proceder a identificar tanto los permisos que necesita la aplicación como los demás componentes (activities, services, receivers, content providers) que se encuentran declarados en el fichero AndroidManifest.xml . Como sabemos, los ficheros apk son realmente ficheros comprimidos en .zip. Podríamos pensar que al descomprimirlo seríamos capaces de acceder a los ficheros del apk y ver su contenido, pero no es así.

Como prueba, procedemos a descomprimir un apk y observamos que ahí se encuentra el fichero AndroidManifest.xml, muy fácil ¿no?. Pero al abrirlo, observamos lo siguiente:

Este es un formato de código binario utilizado por Android. Para poder convertir el fichero a un formato legible y ver su contenido, utilizaremos la herramienta apktool sobre el apk de la siguiente forma apktool d <nombre_fichero> :

Al terminar el proceso, accedemos al directorio resultante, que coincidirá con el nombre del apk. Para no tener conflictos con el nombre del directorio más adelante, renombraremos el directorio EroTube a EroTube_apktool :

Ahora sí,  el fichero de configuración AndroidManifest.xml ya es legible. En este fichero se declaran los siguientes elementos que tendremos que tener en cuenta:

  • Permisos: deberemos revisarlos cuidadosamente, sobre todo cuando la aplicación requiera permisos que no están relacionados con lo que ofrece la aplicación (enviar SMS/MMS o realizar llamadas) o que son permisos con privilegios (modificar configuración del sistema o descargar ficheros sin notificación).
  • Activities: se corresponden con cada una de las pantallas empleadas por la aplicación.
  • Services: son servicios que corren en segundo plano y pueden llevar a cabo acciones sin interacción del usuario.
  • Receivers: son clases que pueden manejar eventos del sistema, como por ejemplo, la aplicación envía un SMS y lee el código de confirmación del SMS recibido, todo en segundo plano.
  • Content Providers: componentes que permiten compartir información con otras aplicaciones.

ANALIZANDO ANDROIDMANIFEST.XML

Vamos a centrarnos en los permisos que la aplicación necesita para su correcto funcionamiento, sin dejar de lado el resto de elementos. Se observa que la aplicación utiliza los siguientes componentes declarados en el fichero:

PERMISOS

Esta aplicación declara permisos para acceder a internet, reiniciar el sistema, acceder al estado de la red y el teléfono,acceder a la localización, acceder al bloqueo del dispositivo, escribir en la tarjeta de memoria, hacer que vibre el dispositivo, acceder a las cuentas de usuario, etc… :

También observamos a la derecha el paquete al que pertenecen los componentes. Ya tenemos un listado de los permisos declarados pero, ¿cuales son los que nos tienen que hacer dudar?. Veamos a continuación un listado de aquellos permisos que son considerados como peligrosos y que hay que tener más en cuenta (fuente: https://www.incibe.es/extfrontinteco/img/File/intecocert/EstudiosInformes/situacion_del_malware_para_android.pdf) :

  • android.permission.INTERNET: Permite a las aplicaciones acceso total a Internet.
  • android.permission.READ_PHONE_STATE: Permite el acceso de sólo lectura al estado del teléfono.
  • android.permission.WRITE_EXTERNAL_STORAGE: Permite a una aplicación escribir en el almacenamiento externo.
  • android.permission.ACCESS_NETWORK_STATE: Permite que las aplicaciones accedan a información sobre las redes.
  • android.permission.SEND_SMS: Permite a una aplicación enviar sms.
  • android.permission.RECEIVE_SMS: Permite que una aplicación para monitorear los mensajes SMS entrantes, para grabar o realizar el procesamiento en ellos.
  • android.permission.WAKE_LOCK: Permite el acceso a los bloqueos de energía para mantener el procesador durmiendo o mantener la pantalla apagada.
  • android.permission.RECEIVE_BOOT_COMPLETED: Permite que una aplicación reciba el ACTION_BOOT_COMPLETED que se emite después de que el sistema termine de iniciarse.
  • com.android.launcher.permission.INSTALL_SHORTCUT: Permite a una aplicación instalar un acceso directo.
  • android.permission.READ_SMS: Permite a una aplicación leer los sms.
  • android.permission.CALL_PHONE: Permite a una aplicación realizar llamadas de teléfono sin necesidad de usar el dialer de Android.
  • android.permission.GET_TASKS: Permite a una aplicación obtener información sobre las tareas en ejecución actual o reciente.
  • android.permission.ACCESS_COARSE_LOCATION: Permite que una aplicación acceda a la ubicación aproximada derivada de fuentes de ubicación de red, como las torres de celulares y Wi-Fi.
  • android.permission.ACCESS_FINE_LOCATION: Permite que una aplicación acceda a la ubicación precisa derivada de fuentes de localización como el GPS, las torres celulares y Wi-Fi.
  • android.permission.ACCESS_WIFI_STATE: Permite que las aplicaciones accedan a información sobre redes Wi-Fi.
  • android.permission.PROCESS_OUTGOING_CALLS: Permite que una aplicación visualice el número al que se está llamando con la opción de redirigir la llamada a un número diferente o cancelarla.
  • android.permission.SYSTEM_ALERT_WINDOW: Permite que una aplicación abra ventanas utilizando el tipo TYPE_SYSTEM_ALERT, que se muestra en la parte superior de todas las demás aplicaciones.
  • android.permission.WRITE_SETTINGS: Permite que una aplicación lea o escriba la configuración del sistema.
  • android.permission.INSTALL_PACKAGES: Permite que una aplicación instale paquetes.
  • android.permission.WRITE_SMS: Permite a una aplicación escribir sms.

ACTIVITIES

A través de este fichero elaboraremos un listado de las clases que revisaremos, comenzando por la clase test.app.MainActivity que es el que sirve de punto de entrada a la aplicación ya que declara un intent-filter formado por una acción (android.intent.action.MAIN) y una categoría (android.intent.category.LAUNCHER):

Cuando un componente de aplicación declara un intent-filter pero no establece la propiedad android:exported=false o sí establece la propiedad pero con valor android:exported=true, se considera que tiene visibilidad pública. En este caso, nuestro activity declara un intent-filter pero no establece la propiedad android:exported=false para que no tenga visibilidad pública, lo que permite ser ejecutado por otras aplicaciones. Adicionalmente, también se podría restringir el acceso complementando la propiedad anterior con el atributo permission .

SERVICES

La aplicación hace uso de cuatro servicios. Entre ellos destacamos el servicio .test.app.USSDService que declara un intent-filter y establece el atributo android:exported=true, lo que lo convierte en un componente público accesible por otras aplicaciones:

RECEIVERS

Se declaran tres receivers de los cuales todos declaran un intent-filter pero no establecen el atributo android:exported=false, lo que los convierte en componentes públicos accesibles por otras aplicaciones:

CONTENT PROVIDERS

La aplicación no hace uso de providers por lo que no rellenamos este apartado.

SEGUNDO PUNTO: ANÁLISIS DE RECURSOS

Como siguiente punto, antes de buscar cadenas en el código fuente, es revisar la carpeta de recursos de la aplicación con el objetivo de detectar imágenes u otro tipo de fichero que nos hagan sospechar de la aplicación. Un fichero importante para revisar es el fichero strings.xml . En este caso, el fichero en sí no contiene nada interesante, excepto un texto en ruso que nos ha llamado la atención:

Al traducir el texto observamos que avisa al usuario en algún momento de que se requiere elevación para “actualizar y añadir ventajas”, eso sí, todo en segundo plano. Esto es algo muy sospechoso… :

BÚSQUEDA DE CADENAS

Descomprimiremos el fichero .apk para acceder al fichero classes.dex sobre el que vamos a realizar las búsquedas de cadenas. En este caso, utilizaremos el parámetro -d para indicarle un nombre de directorio unzip <fichero_apk> -d <nuevo_directorio> cuyo nombre será EroTube_unzip:

Terminado el proceso tendremos nuestro directorio EroTube_unzip con todos los recursos utilizados por la aplicación:

El comando que vamos a utilizar para realizar la búsqueda de cadenas es el comando strings de Linux:

Con él, extraeremos todas las cadenas imprimibles del fichero classes.dex y las guardaremos en un fichero .txt . Después realizaremos un cat sobre el fichero .txt para mostrar todo su contenido y filtraremos con el comando grep, con el que buscaremos cadenas a través de expresiones regulares. En este ejemplo, buscaremos la expresion regular ‘^http:\/\/’  para obtener direcciones url con protocolo http :

Observamos que la búsqueda ha sacado una coincidencia muy interesante: la dirección url parece ser un C&C (Command & Control) para controlar malware, por ejemplo en las botnets.

TERCER PUNTO: ANÁLISIS DE CÓDIGO FUENTE

Para empezar a revisar el código fuente, primero tendremos que convertir el fichero classes.dex utilizando el proceso d2j-dex2jar de la siguiente forma d2j-dex2jar classes.dex :

El resultado es el fichero classes-dex2jar.jar . Para poder abrirlo, utilizaremos un decompilador de código como es JD-GUI, aunque hay muchos otros. Esto nos mostrará todos los ficheros .class que forman el fichero anterior. Hay que destacar que al hacer la decompilación se pierde mucha información, como nombre de variables, lo que dificulta el análisis manual del código:

Una buena práctica a la hora de dificultar la ingeniería inversa es realizar la ofuscación del código fuente para modificar el contenido del fichero .dex y los archivos xml preservando el original. Este código tiene un alto porcentaje de similitud con el código Java pero no es el código fuente origen. Si lo que realmente nos interesa son los ficheros .java , iremos a Archivo >> Save resouces , guardándose todos los recursos en un directorio que indiquemos. Nosotros hemos creado el directorio fuentes en la que guardaremos el fichero .zip :

Al descomprimir el fichero se identifican las carpetas que empiezan a formar los paquetes en los que se encuentran los ficheros .java:

Dentro de estas jerarquías de carpetas encontraremos los ficheros de código fuente .java:

Comenzaremos a revisar el código fuente identificando los permisos necesarios y descartando los que no se estén utilizando de forma fraudulenta. Abriremos en el JD-GUI el activity que sirve de punto de entrada a la aplicación, .MainActivity (ver ciclo de vida de la aplicación android) :

Tal y como se puede observar, la aplicación instancia una clase WebView en la que habilita Javascript, añade un api para el manejo de Javascript y carga el fichero index.html ubicado en el directorio html, el cual tiene la siguiente apariencia (abierto en Firefox):

Realmente este mensaje indica que no somos compatibles, dándonos únicamente la opción de pulsar en el botón OK. Revisando el código fuente observamos que el botón nos redirige a la página www.proandroid.net:

Esta página se corresponde con un market no oficial de descarga de aplicaciones en el que la mayoría de las aplicaciones son malware:

Este proceso de entender que hace la aplicación es muy tedioso y a veces complicado.

Habiendo entendido un poco como funciona, comprobaremos para que necesita cada uno de los permisos y cómo los usa. Empezaremos con el permiso de envío de recepción y envío de sms, android.permission.SEND_SMS . Haciendo una búsqueda, por ejemplo sendSms, obtenemos varias coincidencias:

Analizando cada una de las coincidencias identificamos una llamada a un método sendSms() en un BroadcastReceiver. Estos componentes actuarán en función de los eventos indicados en el fichero AndroidManifest.xml, que en este caso, actuará cada vez que se reciba un SMS, ejecutando el método onReceive():

Si accedemos a la clase que contiene ese método sendSms(), comprobamos el código del mismo:

Parece ser que esta aplicación realiza el envío de SMS a través de un servicio en segundo plano, utilizando el permiso android.permission.SEND_SMS de forma malintencionada. Además, en esta clase también se han encontrado otros métodos que extraen información del terminal, como son los siguientes:

Otro permiso que vamos a descartar es el de android.permission.INSTALL_PACKAGES que permite instalar aplicaciones. Al igual que el paso anterior, realizaremos una búsqueda relacionada, por ejemplo la cadena Download . Una vez que obtenemos coincidencias verificaremos cada una de las clases. En este caso hemos encontrado el método cleandownloads() para eliminar descargas:

La funcionalidad de este método es acceder al directorio Downloads ubicado en la tarjeta SD y eliminar todos los ficheros con extensión .apk, por lo que entendemos que se ha descargado previamente. Un poco sospechoso que un apk se descargue e instale otro apk . Después de investigar (que es lo principal en estos análisis) encontramos la clase InstallService que implementa un servicio con un método downloadFile() . Este servicio al iniciarse, invoca al método onHandleIntent() que tiene el siguiente contenido:

Se observa que este método comprueba que el tipo de instalación es APK, crea los directorios necesarios y descarga el fichero con nombre install.apk en un directorio de la tarjeta SD, posiblemente el directorio Downloads (ver segundo cuadrado rojo). Así, se está utilizando el permiso android.permission.INSTALL_PACKAGES de forma malintencionada.

Estos ejemplos que hemos visto con dos permisos de la aplicación habría que llevarlo a cabo para todos los permisos identificados como peligrosos para una aplicación y descartar su uso malintencionado.

RESULTADO DE ANTIVIRUS

Como punto final, hemos analizado el apk en varios servicios online para ver los resultados que nos muestra. El primer servicio que hemos probado es http://www.mobiseclab.org cuyos resultados detallan que la aplicación realiza tanto la lectura como el envío de SMS al iniciarse, instala un nuevo apk o esconde el icono de la aplicación, entre otras cosas:

Otro servicio online y el más conocido de todos es https://www.virustotal.com cuyos resultados indican de la peligrosidad de la aplicación:

De los 58 antivirus utilizados para analizar la aplicación, 38 la han detectado como maliciosa.

ANÁLISIS DINÁMICO

Para la parte del análisis dinámico, una buena forma de empezar es capturando el tráfico generado por la aplicación, a través del uso de un emulador y un proxy web como OWASP ZAP o Burpsuite . Para ello podéis seguir el tutorial de nuetro compañero alastor montando nuestro propio laboratorio Android .

Esperamos que os haya gustado.

“Don’t give up, great things take time”.

2 comentarios sobre “Eres un APK muy malo…

  1. Buen articulo.

    Me ha encantado la forma tan descriptiva de como realizar todos los pasos.
    Creo que falta profundizar un poco en el tema de los permisos que utiliza esta aplicación, y su posible uso fraudulento (llamadas, envio de informacion del usuario, etc).

    Pero esta bastante completo.

    Un saludo.

    1. Este artículo se hizo con el primer apk descargado de un market no oficial. Cierto es que falta profundizar un poco más en los permisos. Creo que volveré a hacer el artículo pero con una aplicación que tenga bien definida la actividad fraudulenta. Muchas gracias por leernos y un saludo.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *