Técnicas de evasión de bloqueo y rooteo en dispositivos Android


A la hora de afrontar un análisis forense de dispositivos Android, una de las dificultades a las que nos enfrentamos es a que dicho dispositivo se encuentre bloqueado. En el siguiente artículo repasaremos las estratégias más utilizadas para evadir dicho bloqueo, incluyendo los tipos de elevación de privilegios, necesarios en muchas ocasiones.
Para comenzar, habría que repasar los 4 tipos de bloqueo del dispositivo que Android nos proporciona:
Slide (none). Es el modo más básico, simplemente realizando el gesto del desplazamiento el dispositivo quedará desbloqueado.
Pattern lock. En este modo se proporciona un patrón sobre los puntos marcados que debe seguirse para conseguir el desbloqueo del dispositivo. El único requisito sobre dicho patrón es que contenga al menos el paso por 4 puntos.
PIN. En este modo el usuario debe introducir un código numérico para desbloquear el dispositivo.  El único requisito sobre el PIN es que conste de al menos 4 digitos.
Password. En este modo el usuario debe introducir con código alfanumérico para desbloquear el dispositivo.  El único requisito sobre la contraseña es que conste de al menos 4 caracteres.
Los modos de bloqueo pueden configurarse desde las opciones generales, en el apartado de seguridad, en la opción “Screen lock”, como podemos ver a continuación: 1_tipos_bloqueo
Una vez clasificados los tipos, vamos a enumerar las diferentes aproximaciones para evadir estas protecciones: Smudge Attacks. En esencia se trata de ver las marcas físicas sobre la pantalla del dispositivo. Aunque a priori parezca un tanto cojido con los pelos, el hecho de tomar una fotografía de la pantalla y jugar con los cambios de colores, brillos, ponerla en negativo y demás pueden tener resultados muy satisfactorios. En el siguiente papper detallan esta aproximación desde una manera formal: http://static.usenix.org/event/woot10/tech/full_papers/Aviv.pdf Pattern Lock Crack Evadir esta protección es muy sencilla solo si se tiene acceso al modo debug del dispositivo rooteado. En patrón se almacena en el dispositivo en forma de hash en el fichero /data/system/gesture.key, como podemos ver a continuación:
2_gesturekey
Si tenemos acceso ADB de root, podemos eliminar el fichero y crear uno nuevo vacío:  
rm gesture.key touch gesture.key
A partir de ese momento, cualquier gesto desbloqueará el dispositivo. Si no tenemos acceso al modo debug, es posible a través de la interfaz JTAG, el proceso está descrito en el siguiente enlace: http://forensics.spreitzenbarth.de/2012/02/28/cracking-the-pattern-lock-on-android/ Password Crack && PIN Crack Evadir estas protecciones es muy sencillo solo si se tiene acceso al modo debug del dispositivo rooteado. La contraseña y/o PIN se almacena en el dispositivo en forma de hash en el fichero /data/system/password.key, como podemos ver a continuación:
3_passwordkey
Si tenemos acceso ADB de root, podemos eliminar el fichero y crear uno nuevo vacío:
rm password.key touch password.key
A partir de ese momento, cualquier contraseña y/o PIN desbloqueará el dispositivo. La gracia visto lo visto es tener el dispositivo rooteado, pero rootear un dispositivo en el transcurso de un análisis forense entraña dificultades en el proceso, ya que el principio fundamental es que las modificaciones de la envidencia tiendan a cero. Vamos a repasar el proceso. Lo primero al acceder a un dispositivo es saber si somos root en el mismo, tal vez el usuario lo tiene rooteado. ¿Cómo saberlo manipulando lo menos posible el dispositivo? Lo más sencillo es conectar al mismo mediante ADB y ejecutar la siguiente sentencia:
adb shell su
Si como respuesta entramos a la shell, somos root, si obtenemos un “Permision denied” nos lo tenemos que ganar. Antes que nada, no pensemos que ser o no root es algo abosluto, en entornos Android tenemos diferentes tipos de rooteo, y no todos tienen las mismas implicaciones desde el punto de vista forense, por lo que debemos evaluar en cada caso cuál necesitamos y actuar en consecuencia.
Root permanente. Es el más habitual. Entramos al dispositivo y somos root, ¿porqué? Normalmente es así porque se ha habilitado alguna ROM personalizada o se le han proporcionado al dispositivo binarios ARM para comandos como “su“. La referencia es XDA Developers.
Root temporal. Se elevan privilegios solo hasta el renicio, normalmente tras aprovechar una vulnerabilidad en ejecución. Esta forma es ideal desde el punto de vista práctico, si bien entraña riesgos porque se va a modificar en dinámico, puede causar inestabilidad y aprovechar vulnerabilidades para elevar privilegios puede ser muy discutido desde el punto de vista del proceso.
A continuación indico un par de aplicaciones para conseguir este objetivo:
psneuter. Aplicación que gana acceso a root utilizando una vulnerabilidad en Android. https://github.com/tmzt/g2root-kmod/tree/master/scotty2/psneuter
SuperOneClick. Aplicación que reune múltiples exploits para rootear el dispositivo. http://shortfuse.org/?page_id=2
Mercury. Este framework de análisis dinámico incorpora exploits para rootear el dispositivo. http://labs.mwrinfosecurity.com/tools/2012/03/16/mercury/
Root recovery. En este modo se habilita una particion de recuperación en el dispositivo que permite el acceso privilegiado solo cuando se carga dicha partición. Este tipo de rooteo es el más indicado para procedimientos forenses. La problemática es que cada fabricante maneja las particiones de recuperación de una manera diferente y en algunos casos no será trivial. A continuación dejo, por cortesía de @hidark, a modo de ejemplo el proceso para el modelo ASUS Transformer TF101: Arrancamos el dispositivo presionando los botones “power” y “subir volumen“, no ves nada en la pantalla, pero si la tienes conectada al PC puedes apreciar con un “dmesg” desde el PC que el dispositivo entró en modo APX:
5_apx_transformer
Después ya se puede cargar un bootloader específico mediante wheelie (http://androidroot.mobi/2012/05/27/introducing-wheelie-nvflash-for-asus-transformer-tf101-b70/) y extraer las particiones mediante nvflash (http://forum.xda-developers.com/showthread.php?t=1676845). Es importante tener en cuenta que este método ha de ser probado previamente en entorno de laboratorio para que la ejecución sobre la evidencia sea lo más limpia posible.

Daniel Medianero

Volatility VS Citadel 1.3.4.5

Como analista forense y de malware siempre he sido un gran fan de Volatility, la ya archiconocida herramienta de análisis de memoria escrita en Python que sigue creciendo día a día. Por ese motivo, desde que hace algo más de un año vi el artículo de Michael Ligh en su blog sobre la extracción de las claves de cifrado de ZeuS siempre había querido probar eso mismo con otras familias de malware.
En este caso he elegido Citadel, que es una de las variantes de ZeuS que más guerra están dando desde la filtración del código fuente del mismo. En concreto la versión 1.3.4.5 que, aún no siendo la última, nos servirá de base para las siguientes versiones (Aunque se rumorea que la 1.3.5.1 podría ser la última que veamos) u otras familias.
Cuando juntamos Volatility con Yara, la potencia disponible para el procesamiento automático de malware se multiplica. En ambas cosas se basa zeusscan2, uno de los plugins resultantes del artículo comentado anteriormente. El mismo hace uso de reglas Yara sobre la memoria de una máquina infectada para detectar y acceder a las zonas de memoria susceptibles de contener la información que nos interesa extraer del binario. Para ello es necesario un exhaustivo análisis previo sobre la familia a “automatizar”, que en este caso, al tratarse de una variante de la familia ZeuS de sobra conocida y documentada, el trabajo se limitará a detectar las diferencias existentes con la misma.
De entrada sabemos que ZeuS 2.X contiene la siguiente información embebida en el binario:
  • URL de descarga inicial del fichero de configuración
  • Clave RC4 usada para descifrar el fichero de configuración
  • Información sobre la localización del binario y la configuración en la máquina infectada
Los dos primeros datos se encuentran en una zona del binario codificada mediante XOR con los bytes contenidos al comienzo de la última sección del fichero PE, mientras que la última es una zona cifrada mediante la clave RC4 con una estructura fija (En adelante nos referiremos a ello como el “objeto mágico”, para seguir la convención usada en el plugin para Volatility de ZeuS).
Nota: En el caso de ZeuS existe una segunda clave RC4 contenida en la última estructura comentada, pero dado que Citadel carece de ella, no es relevante para el objetivo del artículo.
De esta forma el flujo de extracción y procesamiento de los datos que buscamos sería algo como:
  1. Localización de la configuración embebida
  2. Decodificación de la misma mediante un XOR con los bytes situados al comienzo de la última sección del fichero PE
  3. Extracción de la URL de descarga de la configuración y la clave RC4
  4. Localización y decodificación del “objeto mágico”
  5. Extracción de los datos restantes
Ahora que sabemos la base sobre la que se asienta Citadel, podemos estudiar las diferencias para adaptar el plugin a la nueva familia. Las similitudes (a nivel de binario al menos) son más que las diferencias, así que una vez entendido lo anterior, los cambios no revisten demasiada complicación.
La principal diferencia viene marcada por el cifrado usado en los ficheros de configuración descargados, que pasa de RC4 a AES, pero para el “objeto mágico” se mantiene RC4. Dicha clave AES no está contenida en el binario como tal, sino que es calculada en tiempo de ejecución de la siguiente forma:
RC4(md5(BO_LOGIN_KEY))
La BO_LOGIN_KEY o binary key, se trata de una clave de 16 bytes en hexadecimal que sí está contenida en el binario y que además de para el cálculo de la clave AES se usa para la comunicación con su panel de control, por lo que, a la localización de la configuración embebida y el “objeto mágico”, hemos de añadir la de dicha clave “hardcodeada”.
Al flujo anterior habría que añadirle por otro lado:
  1. Localización de la BO_LOGIN_KEY
  2. Cálculo de la clave AES
Con todo esto, elegimos el siguiente código desensamblado para generar las nuevas reglas Yara que nos ayuden a localizar las variables comentadas en memoria:
8BEC                                  MOV EBP,ESP
83EC 0C                             SUB ESP,0C
8A82 00010000                  MOV AL,BYTE PTR DS:[EDX+100]
8845 FE                              MOV BYTE PTR SS:[EBP-2],AL
8A82 01010000                  MOV AL,BYTE PTR DS:[EDX+101]
8845 FD                             MOV BYTE PTR SS:[EBP-3],AL
8A82 02010000                  MOV AL,BYTE PTR DS:[EDX+102]
B9 801A1300                      MOV ECX,131A80                                                   ; BO_LOGIN_KEY
8845 FF                              MOV BYTE PTR SS:[EBP-1],AL
E8 BEF2FFFF                    CALL 0015BC16
———————————————————————————
56                                        PUSH ESI
BA 54050000                      MOV EDX,554                                                          ; Embedded configuration length
52                                        PUSH EDX
68 602A4000                       PUSH pyko.00402A60                                             ; Embedded configuration
50                                        PUSH EAX
E8 47E30100                      CALL pyko.004290C1
8B0D B4394300                 MOV ECX,DWORD PTR DS:[4339B4]
030D 943D4300                 ADD ECX,DWORD PTR DS:[433D94]
8BF2                                   MOV ESI,EDX
2BC8                                  SUB ECX,EAX
———————————————————————————
68 03010000                      PUSH 103
8D85 10FBFFFF               LEA EAX,[LOCAL.316]
50                                       PUSH EAX
8D85 FCFEFFFF              LEA EAX,[LOCAL.65]
50                                       PUSH EAX
E8 B4E20100                     CALL pyko.004290C1
B8 1C010000                     MOV EAX,11C
50                                       PUSH EAX
68 283C4300                     PUSH pyko.00433C28                                               ; Magic object
Una vez que llegamos al punto del flujo de procesamiento en el que se decodifica el “objeto mágico” nos encontramos con una estructura con un aspecto similar al siguiente:
Este objeto, al igual que pasaba con ZeuS 2.X, tiene una longitud fija en la mayoría de los casos y una estructura como la que sigue:
{‘_ZEUS_MAGIC’ : [ 0x11C, {
'struct_size' : [ 0x0, ['unsigned int']], \
‘guid’ : [ 0x4, ['array', 0x30, ['unsigned short']]], \
‘guid2′ : [ 0x7C, ['array', 0x10, ['unsigned char']]], \
‘exefile’ : [ 0x9C, ['array', 0x14, ['unsigned char']]], \
‘keyname’ : [ 0xEC, ['array', 0xA, ['unsigned char']]], \
‘value1′ : [ 0xF6, ['array', 0xA, ['unsigned char']]], \
‘value2′ : [ 0x100, ['array', 0xA, ['unsigned char']]], \
‘value3′ : [ 0x10A, ['array', 0xA, ['unsigned char']]], \
‘guid_xor_key’ : [ 0x114, ['unsigned int']], \
‘xorkey’ : [ 0x118, ['unsigned int']], \
}]}
Por lo tanto ya disponemos de todo lo que buscábamos:
Espero que este ejemplo ayude a ver un poco más claramente las posibilidades que nos ofrecen Yara y Volatility para el análisis y automatización de malware cuando trabajan en conjunto.
El plugin para la versión 1.3.4.5 lo podéis encontrar aquí. Michael Ligh lo ha integrado, además, con las versiones del plugin para ZeuS 1 y 2.X, por lo que en adelante estará disponible también en la rama principal de Volatility, aunque no activado por defecto; para su uso habrá que lanzar Volatility de la siguiente forma:
$ python vol.py –plugins=contrib/plugins/malware citadelscan1345 -f ….
En cuanto a la versión 1.3.5.1, el proceso a seguir sería similar excepto porque habría que localizar una nueva clave “hardcodeada” y tener en cuenta que el tamaño y estructura del “objeto mágico” cambia en cada muestra.
Feliz análisis!
Follow me on Twitter: @smvicente

Analizando el malware Trojan-Spy.AndroidOS.Zitmo.a v1.2.8

En otro post hemos visto, de que es capaz nuestro “Galletero” con la versión versión 1.2.3 de Android. Esta entrada, la dedicaremos a la misma familia pero a la última versión con la que hemos chocado últimos días, la versión 1.2.8.
El vichaco es distribuido por las mismas vías que hemos comentado en el post anterior, por SMS, y de la misma manera, haciéndose pasar por una aplicación de seguridad y enviada desde una entidad financiera la que utiliza la víctima.
Esta versión, está un poco modificada, obtiene varias funciones nuevas de la hablaremos un poco más adelante, y un punto de defensa que el desarrollador implementa, que también indicaremos en mas adelante. Iremos paso a paso, y empezaremos por la clase “MainActivity”. Aquí se ha introducido un paso extra para obtener la URL y almacenarla temporalmente en una variable, para después seguir ya con el proceso que viene siendo habitual en versiones anteriores y continuar cargando el resto de las funciones.

En la clase de “SecurityReceiver” se importan nuevas cosillas como:
  • import java.util.zip.CRC32;
  • import java.util.Random;
  • import java.text.SimpleDateFormat; (antes se importaba el java.util.Date)
Como veis, importa CRC32, curioso eh!? A ver dónde lo utiliza….ah sí, aquí está, asigna una variable global con el valor no modificable.

Luego utiliza la nueva función llamada “SqlCheckLastSend” donde calcula CRC32 de la URL a la que reporta y la compara con esta constante. Parece que comprueba si la URL es correcta.

Y ya está, parece que no lo utiliza en ningún otro sitio. Le veo muy poco sentido. Bueno, vamos a seguir.
En esta ocasión, el desarrollador decidió que también quería enviar y almacenar en la BBDD la fecha y hora de los mensajes obtenidos.


Como ya sabemos del post anterior, este “Galletero” es capaz de recibir órdenes, bien, pues parece que en esta versión le modificaron un poco la función encargada de interpretarlos. Las funciones como tales, se han quedado intactas, sin embargo los símbolos que interpreta se han modificado, veremos. Antes se recibían estos símbolos: “%”, “:”, “*” y “,”, pues ahora recibe esto: “#”, “/”, “!” y “.”. Donde cada uno de ellos recibe esta funcionalidad:
  • Estos son los comandos que nuestro “Galletero” de la versión 1.2.3 es capaz de recibir:
    • “%” – GET INFO, extrae el número del mensaje y envía el reporte.
    • “:” – Report Number Update, extrae el número del mensaje de texto. Guardar el número, para utilizar éste, como un punto de reporte alternativo y envía el reporte
    • “*” – Uninstall, activa el flag de desinstalación de la aplicación, extrae el número del mensaje y envía el reporte.
    • “,” – Fin de control por mensajes, elimina el número de control alternativo, extrae el número de mensaje de texto y envía el reporte
  • Y estos son los que el “Galletero” de la versión 1.2.8 recibirá
    • “#” – GET INFO, extrae el número del mensaje y envía el reporte.
    • “/” – Report Number Update, extrae el número del mensaje de texto, guardaa el numero para utilizar este como un punto de reporte alternativo y envía el informe.
    • “!” – Uninstall, activa el flag de desinstalación de la aplicación, extrae el número del mensaje y envía el informe.
    • “.” – Fin de control por mensajes, elimina el número de control alternativo, extrae el número de mensaje de texto y envía el informe.
Bueno, seguimos, la clase “ValueProvider” obtiene una nueva función llamada “reverseString”, la cual se encarga de cambiar los caracteres de un string al revés. Para que lo usara…

A si, aquí esta, la función “GetActivationCode” se ha modificado, bien parece que utiliza la función “reverseString”, vamos a ver. El código de activación ahora es el siguiente, se obtiene en “deviceId” utilizando “reverseString” se le da la vuelta y al final se le añade un “3″.

Lo demás sigue gestionándose de la misma manera como en la versión 1.2.3.
Parece que el desarrollo de nuestro “Galletero” sigue y veremos más variantes, con más implementación y defensas.
Reference: Malware analysis Trojan-Spy.AndroidOS.Zitmo.a version 1.2.3