Bypassing Android App Security in 3, 2, 1, pwned. Defeating Root Control Detection
¡Hola de nuevo, lectores!
Una vez más, os traemos otro artículo que seguro es de vuestro interés. En esta ocasión, nuestros compañeros del Red Team de Perú nos explicarán uno de los tantos despliegues técnicos existentes a través de un análisis estático para llevar a cabo la evasión del control de seguridad anti-root en aplicaciones Android.
0x00. Defeating Root Control Detection
Hoy en día, las empresas utilizan diferentes mecanismos (técnicas y herramientas) intentando elevar la seguridad de sus aplicaciones, buscando de algún modo no ponerlas fácil a los ojos de hackers o ciberdelincuentes. Por ejemplo, si hablamos de seguridad en aplicaciones Android, quizás las bancarias sean un buen ejemplo de ello, debido a que la mayoría de las aplicaciones evitan ejecutarse en dispositivos con altos privilegios (root).
Pese a los grandes esfuerzos de las empresas por blindar sus aplicaciones, estas terminan no contando con el nivel de seguridad que esperaban.
En este artículo vamos a describir uno de los tantos despliegues técnicos utilizando análisis estático para llevar a cabo la evasión del control de seguridad anti-root en aplicaciones Android.
0x01. Control Anti-Root
La detección de root en aplicaciones móviles se refiere a las técnicas utilizadas para detectar si un dispositivo móvil ha sido rooteado o liberado, lo que puede ser importante para los desarrolladores de aplicaciones que desean asegurarse de que sus aplicaciones se utilicen en dispositivos seguros y libres de riesgos.
0x02. Atacando el control Anti-Root
Para efectos de la práctica, procedemos a instalar la supuesta aplicación bancaria en un emulador que tiene activado los privilegios de root. Si ejecutamos la aplicación, esta detecta el entorno controlado (emulador) con altos privilegios o modo root y nos muestra un mensaje al respecto.
Aplicación bancaria de prueba.
Mensaje de control de la aplicación.
0x03. Decompilando la aplicación
Para poder ver las entrañas de la aplicación, en primer lugar, debemos decompilarla. Nosotros vamos a utilizar la herramienta APK Easy Tool v1.60 para este fin. El uso de esta herramienta es sencilla, basta con ubicar la ruta o arrastrar el instalador (archivo APK) de la aplicación y luego dar click a la opción “Decompile”, esperamos a que el proceso de decompilado termine y nos muestre el mensaje de “Decompile sucessfull” (Ubicado al margen inferior izquierdo).
Proceso de decompilación.
Decompilación finalizada.
Archivos producto de la decompilación.
0x04. Análisis con IDA Pro
Ahora procederemos a analizar la aplicación con IDA Pro con el fin de localizar las clases o funciones donde se realiza la validación del control de root.
En primer lugar, abrimos el archivo APK con IDA Pro y seleccionamos APK Android Package, luego debemos esperar unos minutos mientras IDA Pro decompila el archivo APK e interpreta su código e instrucciones.
Cargamos el archivo APK en IDA Pro.
Interpretación de código desde IDA Pro.
Una vez finalizada la carga completa del archivo APK, procedemos a depurarlo utilizando tanto el emulador como con IDA Pro, al hacer esto IDA Pro nos muestra una advertencia que tenemos que aceptar, esto permite que IDA Pro se comunique con el emulador y después ejecuta la aplicación en tiempo de ejecución. Desde el emulador observamos que nos muestra el mensaje “Waiting for debugger”.
Mensaje de advertencia de depuración del IDA Pro.
Depuración en tiempo de ejecución desde IDA Pro y el Emulador.
0x05 Localizando la Validación de root
Una vez que IDA Pro termina de interpretar el código, se detiene en el Entry Point o punto de entrada de la aplicación, donde podemos visualizarlo mediante un flujo continuo muy específico. Después de haber analizado diversas clases, funciones y métodos de la aplicación, llegamos hasta la “zona caliente” (término que se usa para indicar el lugar donde se realiza la validación de root), colocamos un punto de interrupción o breakpoint en las condiciones “if” y traceamos hasta ejecutar esas líneas.
Entry Point de la aplicación.
Zona de validación del control Root.
0x06. Comprendiendo el flujo de la validación
Si analizamos las líneas de código donde posiblemente se realice la validación, vemos que según sea el valor de la condición boolean “0” o “1” saltaría hacia una función u otra, mostrando el mensaje de root o continuando con su ejecución habitual. Ahora sí estamos seguros que dentro de la ruta app\Activities\SplashActivity.smali se encuentra la validación de root, la cual vamos a parchar para bypasear (evadir) este control.
Fragmento de código del flujo de la validación.
0x07. Analizando el flujo de la validación con Jadx
Para discernir nuestro análisis previo desde IDA Pro, respecto al flujo de la validación, vamos a utilizar el decompilador Jadx (Una herramienta desarrollada en Java).
Podemos observar la función “isMyDeviceRooted” la cual contiene 2 variables “z” y “z2”, las cuales devuelven de un valor booleano, un “true” o “false” para continuar su ejecución y según sea la condición mostrar una opción u otra.
Función “isMyDeviceRooted” desde Jadx.
Nosotros procederemos a realizar la modificación de la respuesta en ambas variables “z” y “z2”, forzando de esa manera a que ambas variables siempre devuelvan un “false”, con esto lograremos que no se muestre el mensaje de detección de root. Para lograr lo anteriormente descrito, abrimos el archivo “SplashActivity.smali” con un editor de texto y ubicamos la función “isMyDeviceRooted” y unas líneas más abajo encontramos la constante 0x1 que representa al booleano “true”, que debemos de cambiar por 0x0 o “false”. Una vez realizado el cambio, procedemos a guardar.
Archivo “SplashActivity.smali” que contiene la validación de “isMyDeviceRooted”.
Función “isMyDeviceRooted” devolviendo un valor boolean “True” (0x1).
Función “isMyDeviceRooted” devolviendo un valor boolean “False” (0x0).
Visualizamos los cambios en jadx y vemos que ambas variables z y z2 tienen el valor “False”.
0x08. Compilando el archivo classes2.dex
Procedemos a compilar el archivo classes2.dex con los cambios realizados. Para ello, utilizamos el APK Easy Tool con la opción “Compile Smali”.
Compilando classes2.dex
Procedemos a reemplazar el archivo classes2.dex del APK por el generado por nosotros y procedemos a firmarlo, porque cambiamos la estructura del archivo con los cambios realizados, y la firma anterior cambió. Para esto, usaremos Uber-APK-signer-1.2.1 de nuevo para que sea válido y pueda instalarse en el emulador.
Reemplazamos classes2.dex del APK.
Firmando el archivo APK con Uber APK signer.
0x09. Instalando la versión modificada de la aplicación
Ahora, desinstalamos la aplicación del emulador e instalamos el nuevo instalador APK generado por nosotros con todos los cambios. Procedemos a instalar el nuevo archivo APK en el emulador, pero vemos que ahora nos muestra otro mensaje de alerta “Te recomendamos descargar la versión oficial”. Aquí podemos deducir que existe un control de integridad que verifica si la aplicación fue instalada desde el PlayStore o desde un medio externo que podría ser inseguro.
Archivo APK con evasión de control root.
Mensaje de posible control de Integridad de la aplicación.
0x10. Bonus track: Atacando el control de Integridad de la aplicación
Revisamos nuevamente el código de la aplicación, en este caso lo hacemos desde Jadx, el cual nos permite entender mejor el código fuente, ya que este lo interpreta y lo hace más legible. En este caso, podemos observar que líneas debajo de la función de validación de root existe otra función llamada “InstallTools.verifyInstaller”, la cual siempre devuelve un valor “false”.
Función de control de integridad “InstallTools.verifyInstaller”.
En este caso, debemos modificar la función “InstallTools.verifyInstaller” en la aplicación para que siempre devuelva un valor boolean 0x1 o “true”, de esa manera lograremos el bypass de ese control de integridad.
Función de control de integridad “InstallTools.verifyInstaller” devolviendo valor boolean “True”.
Revisamos si los cambios se reflejan en Jadx, vemos que si se actualizó el código.
Función de control de integridad “InstallTools.verifyInstaller” devolviendo valor “True” desde Jadx.
Procedemos a compilar el archivo classes2.dex con los nuevos cambios realizados.
Compilando nuevamente classes2.dex
Procedemos a reemplazar el archivo classes2.dex del APK por el generado por nosotros.
Reemplazamos classes2.dex del APK
Ahora que el archivo APK ha sido modificado en su estructura, necesitamos volver a firmarlo. Para esto, usaremos Uber-APK-signer-1.2.1 de nuevo para que sea válido y pueda instalarse en el emulador.
Firmando el archivo APK con Uber APK signer
Ahora desinstalamos la aplicación del emulador e instalamos el nuevo instalador APK generado por nosotros.
Archivo APK con evasión de control de integridad
Procedemos a instalar el nuevo instalador APK en el emulador, pero vemos que ahora ya no nos muestra ningún mensaje de alerta y nos carga el “Login” de la aplicación solicitando que ingresemos nuestras credenciales de acceso, mostrando previamente algunas imágenes de nuestro logro.
Logo de bienvenida de la aplicación. |
Pantalla de “Login” de la aplicación. |
¡Y hasta aquí se alarga este estupendo artículo! Os recordamos que las aplicaciones utilizadas en toda la demo han sido las siguientes: IDA Pro 7.7, APK Easy Tool 1.6 Portable, Uber APK signer 1.2.1 y Jadx-gui-1.4.4.
Esperamos que genere interés y os guste, pues no todos los días se aprende a mejorar la seguridad de las aplicaciones ;) ¡Ya sabéis que siempre hay que andar con mil ojos y blindarse ante los hackers!
Si os ha gustado, no dudéis en compartirlo en vuestras redes sociales y, como siempre, ¡nos leemos en el próximo post!