Image
Evadiendo las Protecciones de Seguridad en Aplicaciones iOS

Evadiendo las Protecciones de Seguridad en Aplicaciones iOS

¡Hola, lectores!

En este artículo, presentaremos una explicación detallada sobre cómo evadir la detección de múltiples protecciones de la biblioteca de código abierto IOSSecuritySuite para aplicaciones iOS. Para ello, nos basaremos en el estudio llevado a cabo por Raffaele Sabato en su informe titulado "iOS Swift Anti-Jailbreak Bypass with Frida", el cual se encuentra referenciado en este texto.

Introducción a IOSSecuritySuite

IOSSecuritySuite es una biblioteca de seguridad y anti-tampering fácil de usar, desarrollada en Swift. Proporciona una serie de funciones y comprobaciones para detectar amenazas como el Jailbreak, herramientas de ingeniería inversa y emuladores de iOS.

Requisitos

  • Dispositivo Apple con Jailbreak (modificado para permitir la ejecución de software no autorizado)
  • Hopper Disassembler
  • Frida

Preparación del entorno

En este caso, utilizaremos la aplicación SwiftSecurity disponible en GitHub. Esta aplicación ya tiene implementada la biblioteca IOSSecuritySuite y es perfecta para realizar pruebas. Aunque es una versión más antigua, los métodos que presentaremos también pueden aplicarse en versiones más modernas.

Encontrarás un archivo IPA precompilado en el directorio raíz llamado SwiftSecurity.ipa. Para comenzar, descarga el archivo IPA y descomprímelo como si se tratara de un archivo ZIP.

Análisis de las funciones de protección

A continuación, abriremos el archivo "Payload/SwiftSecurity.app/SwiftSecurity" con Hopper Disassembler y buscaremos la cadena "jailbr" para localizar la función "amIJailbrokenWithFailMessage" de IOSSecuritySuite. Esta búsqueda nos permite identificar si la aplicación realiza comprobaciones relacionadas con el Jailbreak del dispositivo. No obstante, es crucial destacar que en caso de que se haya implementado algún tipo de ofuscación de código, estas cadenas podrían no ser detectadas.

Una vez confirmado el uso IOSSecuritySuite, verificaremos si hay más funciones en uso de esta biblioteca buscando la cadena "static IOSSecuritySuite".

Identificamos 5 funciones en uso y sus valores de retorno (booleanos):

  • amIDebugged: verifica si el proceso actual está siendo depurado.
  • denyDebugger: deniega el uso del depurador.
  • amIRunInEmulator: verifica si se está ejecutando un emulador.
  • amIReverseEngineered: indica si se está realizando ingeniería inversa en la aplicación.
  • amIJailbrokenWithFailMessage: verifica si el dispositivo está jailbroken.

Para obtener más información más detallada sobre lo que comprueba cada una de estas funciones, se puede revisar el código fuente disponible en GitHub.

Evadiendo las protecciones de seguridad

A continuación, analizaremos qué aspectos debemos evadir. Abriremos la aplicación y comprobaremos qué es exactamente lo que se está detectando.

Una vez determinado que se está detectando Jailbreak (debido a la presencia de checkra1n) e ingeniería inversa (a través de la instalación de Frida), asumimos que las funciones asociadas a estas comprobaciones son "amIJailbrokenWithFailMessage" y "amIReverseEngineered".

Para evadir estas funciones, abriremos el archivo "Payload/SwiftSecurity.app/Frameworks/IOSSecuritySuite.framework/IOSSecuritySuite" en Hopper y buscaremos la función "amIJailbrokenWithFailMessage". Este código realiza una verificación para determinar si el dispositivo tiene Jailbreak. Si detecta que el dispositivo está jailbroken, el método devuelve true (0x01). Sin embargo, nuestro objetivo es cambiar el valor de retorno a false (0x00) para evitar esta verificación. Prestaremos especial atención a la dirección de memoria que ejecuta la instrucción RET (retorno), en este caso, 0x8f0c, ya que la necesitaremos más adelante.

Realizaremos el mismo procedimiento con la función "amIReverseEngineered", cuya dirección de la instrucción RET en este caso es 0x90d4.

Una vez obtenidas las direcciones relevantes, crearemos un código en JavaScript para Frida que permita interceptar y modificar el comportamiento de las funciones detectadas en tiempo de ejecución:

var targetModule = "IOSSecuritySuite";
var addr = ptr(0x8f0c);
var moduleBase = Module.getBaseAddress(targetModule);
var targetAddress = moduleBase.add(addr);

Interceptor.attach(targetAddress, {
onEnter: function (args) {
if (this.context.x0 == 0x01) {
this.context.x0 = 0x00;
console.log("[+] amIJailbrokenWithFailMessage bypassed");
}
},
});

var addr = ptr(0x90d4);

var moduleBase = Module.getBaseAddress(targetModule);

var targetAddress = moduleBase.add(addr);

Interceptor.attach(targetAddress, {
onEnter: function (args) {
if (this.context.x0 == 0x01) {
this.context.x0 = 0x00;

console.log("[+] amIReverseEngineered bypassed");
}
},
});

Este código utiliza Frida para modificar el comportamiento de las funciones con el fin de evitar la detección de Jailbreak e ingeniería inversa. A continuación, presentamos una explicación organizada y clara del código:

  1. Obtención de la dirección base del módulo: El código utiliza la función "Module.getBaseAddress()" de Frida para encontrar la dirección base del módulo "IOSSecuritySuite". Esto se logra buscando el módulo por su nombre.
  2. Cálculo de las direcciones objetivo: Después de obtener la dirección base del módulo, se le suma un desplazamiento específico (0x8f0c y 0x90d4) para obtener las direcciones de la instrucción de retorno (RET) de las funciones "amIJailbrokenWithFailMessage" y "amIReverseEngineered". Estas instrucciones de retorno son el punto en el que las funciones terminan y retornan el control al código que las llamó.
  3. Enganche en las direcciones de retorno: Utilizando la función "Interceptor.attach()" de Frida, el código se engancha en las direcciones de retorno encontradas en los pasos anteriores. El enganche permite interceptar las funciones en tiempo de ejecución y modificar los valores de retorno según sea necesario.
  4. Modificación de los valores de retorno: Dentro de la función "onEnter", se verifica el valor de retorno original (almacenado en el registro x0) de la función interceptada. Si el valor original es 0x01 (indicando detección de Jailbreak o ingeniería inversa), se modifica el valor de retorno a 0x00 para evadir la detección. Además, se muestra un mensaje en la consola indicando que se ha evadido exitosamente la protección correspondiente.

Una vez que se haya guardado el código JavaScript anterior, se puede utilizar Frida para cargar y ejecutar el script en la aplicación objetivo. Esto se logra utilizado el comando "frida -U -l bypass.js -f info.s7ven.SwiftSecurity", permitiendo así evadir las protecciones de seguridad implementadas.

En algunos casos, las técnicas mencionadas pueden no ser suficientes para evadir todas las protecciones de una aplicación. Si la aplicación cuenta con comprobaciones personalizadas adicionales para detectar el Jailbreak, se puede recurrir a Shadow, una herramienta alternativa para evadir las detecciones modernas de Jailbreak en iOS. Esto puede combinarse con las técnicas previamente mencionadas. Sin embargo, es importante tener en cuenta que cada situación es diferente y no existe una solución universal para evadir todas las protecciones. Es necesario realizar un análisis exhaustivo de la aplicación objetivo y adaptar las técnicas según sea necesario.

Recuerda que este artículo tiene fines educativos y se recomienda utilizar este conocimiento de manera ética y legal.

Referencias

¡Y hasta aquí el artículo sobre la evasión de las protecciones de seguridad en aplicaciones iOS!

¡No dudéis en compartirlo para que llegue a más personas! :)

¡Nos leemos muy pronto!


Víctor García Barón