FridaLab Writeup
Se procederá a la descarga de una aplicación en formato APK que permitirá realizar diversas tareas con Frida y comprender mejor sus métodos.
Métodos Estáticos vs Métodos Dinámicos
Es importante tener en cuenta la diferencia al utilizar Frida, ya que dependiendo de si se desean utilizar los métodos estáticos o dinámicos, se deberá utilizar una u otra opción en Frida. Para los métodos estáticos, se recomienda utilizar “java.use” en Frida, mientras que para los métodos dinámicos se deberá usar “java.choose”.
Métodos Estáticos
En general, se utilizan las clases estáticas para contar con una biblioteca de funciones a las que se puede acceder desde cualquier parte del programa, sin necesidad de instanciarlas.
Métodos dinámicos
En el caso de que se trate de un método dinámico, se requerirá instanciar la clase correspondiente para poder utilizar dicho método.
por ejemplo
A clasedinamica = new A();
clasedinamica.b(); // usando el metodo dinamico
Para dar inicio a los retos, es necesario contar con una plantilla básica que consiste en lo siguiente:
Java.perform(function () {
// Aqui ponemos el código
});
Retos
Reto 1 Change class challenge_0’s variable ‘chall01’ to: 1
Reto 3 Make chall03() return true
Reto 4 Send “frida” to chall04()
Reto 5 Always send “frida” to chall05()
Reto 6 Run chall06() after 10 seconds with correct value
Reto 7 Bruteforce check07Pin() then confirm with chall07()
Reto 8 Change ‘check’ button’s text value to ‘Confirm’
Instalación
Se procede a descargar el archivo APK para llevar a cabo los retos correspondientes. desde su página principal FridaLab
Una vez descargado el archivo APK, se debe instalar en el equipo. Para ello, se puede acceder al directorio donde se encuentra la aplicación y, utilizando la terminal de CMD, instalarla con el comando adb install FridaLab.apk
Ahora se puede verificar que la aplicación ha sido instalada correctamente en el equipo, como se puede observar, se dispone de un total de 8 retos.
Reto 1
Para comenzar con el reto que consiste en cambiar la variable “chall01” por 1 en la clase “challenge_01”, se requiere tener en ejecución el frida-server en el dispositivo y contar con frida-tool instalada en el equipo host.
Se puede verificar si se cuenta con frida-tool instalada en el equipo host mediante el comando frida-ps -Uai
Si se muestra que FridaLab está en ejecución, entonces se tiene la confirmación de que la herramienta está disponible.
Para llevar a cabo el cambio de la variable, se puede crear un archivo JavaScript con las órdenes correspondientes. En este caso, se denominará “Reto1.js”. Cabe destacar que se trata de un método estático.
Por lo tanto, para ejecutar el archivo “Reto1.js” y realizar el cambio de la variable “chall01”, se puede utilizar el siguiente comando:
challenge_01.getChall01Int();
Para cambiar la variable, basta con llamar a la clase correspondiente, la variable y cambiar su valor. Como una opción adicional, se puede agregar un mensaje que indique que el proceso se ha realizado correctamente, por ejemplo “OK”.
Este código emplea la herramienta Frida para interactuar con una aplicación de Android. La función “Java.perform” se utiliza para realizar una tarea en el hilo de la interfaz de usuario de la aplicación. Dentro de esta función, se crea una variable “challenge_01” utilizando la función “Java.use” para acceder a la clase “uk.rossmarks.fridalab.challenge_01”. Luego, se cambia el valor del atributo “chall01” de esta clase a 1. Por último, se emite un mensaje de confirmación en la consola indicando que el valor de la variable “chall01” ha sido modificado correctamente, mediante la frase “OK”. El archivo “Reto1.js” quedaría de la siguiente manera:
Java.perform(function()
{
var challenge_01 = Java.use('uk.rossmarks.fridalab.challenge_01');
challenge_01.chall01.value = 1;
console.warn('OK');
});
Para ejecutar el script Reto1.js previamente creado, se puede utilizar el comando frida -U -l <script.js> -f <Identifier>
que incluye opciones como ‘-U’, que permite conectar a través de USB, ‘-l SCRIPT’, que permite cargar el script, y ‘-f TARGET’, que permite especificar el target o proceso a atacar, en este caso, la aplicación uk.rossmarks.fridalab.
Se ejecuta el comando y se puede observar que la variable ha sido modificada correctamente.”
Reto 2
En este reto, se necesita ejecutar la función chall02(), la cual se identifica como un método dinámico al revisar el código de la aplicación. Para lograr esto, se requiere utilizar la clase Java.choose, tal y como se explicó al inicio del artículo.
En este caso, se va a utilizar la función de JavaScript “setTimeout()” para ejecutar una tarea después de un tiempo determinado. Además, se va a utilizar la función “Java.choose()” para encontrar una instancia de la aplicación y se usará la función “onMatch()” para realizar una tarea en esa instancia. Finalmente, se utilizará la función “onComplete()” para indicar que se han encontrado todas las instancias y opcionalmente se imprimirá un mensaje de confirmación (“OK”) una vez que se haya ejecutado todo el proceso.
Con este orden de ideas, se creará un archivo llamado Reto2.js siguiendo las instrucciones mencionadas anteriormente.
En este código se utiliza la herramienta Frida para interactuar con una aplicación de Android. La función Java.perform
es ejecutada en el hilo de la interfaz de usuario de la aplicación. Dentro de esta función, se establece un temporizador de 3 segundos (setTimeout) para esperar antes de continuar con la siguiente línea de código.
La siguiente línea de código utiliza la función Java.choose
para buscar una clase específica en la aplicación: “uk.rossmarks.fridalab.MainActivity”. Si se encuentra una instancia de esta clase, se llama al método “chall02” en esa instancia y se escribe un mensaje de advertencia en la consola (“OK”). Si no se encuentra ninguna instancia, no se hace nada.
Java.perform(function ()
{
setTimeout(function ()
{
Java.choose("uk.rossmarks.fridalab.MainActivity" ,
{
onMatch : function(instance)
{
instance.chall02();
console.warn('OK');
},
onComplete:function(){}
});
}, 3000);
});
Entonces, se ejecuta el comando de Frida desde la ruta donde se encuentra el archivo “Reto2.js” con la siguiente línea de comando: frida -U -l Reto2.js -f uk.rossmarks.fridalab
Esto permite interactuar con la aplicación de Android y cumplir con el segundo reto.
Reto 3
En este reto se requiere que el método chall03() retorne un valor verdadero (true). Sin embargo, al revisar el código de la aplicación, se descubre que su valor por defecto es falso (false). Por lo tanto, se necesita implementar un script que permita cambiar este valor a verdadero (true).
En este caso, se utiliza la función Java.use
para encontrar un método estático llamado “chall03” en la aplicación. A continuación, se utiliza la función implementation
para modificar el valor de retorno del método y hacer que devuelva “true”. También se agrega una línea opcional para escribir un mensaje de confirmación (“OK”) en la consola cuando se ha completado la tarea.
Este código utiliza la herramienta Frida para interactuar con una aplicación de Android. La función Java.perform
se utiliza para ejecutar una tarea en el hilo de la interfaz de usuario de la aplicación. Dentro de esta función, se establece un temporizador de 3 segundos (setTimeout) para esperar antes de continuar con la siguiente línea de código.
La siguiente línea de código utiliza la función Java.use
para obtener acceso a la clase “uk.rossmarks.fridalab.MainActivity”. Luego se sobrescribe el método “chall03” de esta clase con una nueva implementación que siempre devuelve true. El código en cuestión se vería así:
Java.perform(function ()
{
setTimeout(function ()
{
Java.use('uk.rossmarks.fridalab.MainActivity').chall03.implementation = function()
{
return true;
}
console.warn('OK');
}, 3000);
});
Se ejecuta el comando frida -U -l Reto3.js -f uk.rossmarks.fridalab
desde la ruta donde se encuentra el archivo “Reto3.js”. Con este comando se logra cargar el script “Reto3.js” y realizar la intercepción de la aplicación “uk.rossmarks.fridalab” utilizando los parámetros “-U -l”. Como resultado, se pudo cumplir satisfactoriamente con el tercer reto.
Reto 4
En este reto se solicita enviar la palabra “frida” a través del método “chall04()”. Al revisar el código, se observa que este método es muy similar al “chall02()”.
Al ser un método dinámico, se utilizará Java.choose, como se hizo en el Reto 2. No obstante, en este caso se enviará la palabra “frida” tal como se requiere.
En este código se utiliza Frida para interactuar con una aplicación de Android. La función Java.perform
es empleada para ejecutar una tarea en el hilo de la interfaz de usuario de la aplicación. Dentro de esta función, se establece un temporizador de 3 segundos (setTimeout) para esperar antes de continuar con la siguiente línea de código.
En la siguiente línea de código se utiliza la función Java.choose
para buscar una clase específica en la aplicación, concretamente: “uk.rossmarks.fridalab.MainActivity”. Si se encuentra una instancia de dicha clase, se llama al método “chall04” de esa instancia, pasándole el argumento ‘frida’. Además, se escribe un mensaje de advertencia en la consola que indica “OK”. Si no se encuentra ninguna instancia, no se realiza ninguna acción. De esta manera, el código quedará así:
Java.perform(function ()
{
setTimeout(function ()
{
Java.choose("uk.rossmarks.fridalab.MainActivity" ,
{
onMatch : function(instance)
{
instance.chall04('frida');
console.warn('OK');
},
onComplete:function(){}
});
}, 3000);
});
Se ejecuta el comando de frida desde la ruta donde se encuentra el archivo Reto4.js. Para ello, se utiliza el siguiente comando: frida -U -l Reto4.js -f uk.rossmarks.fridalab
. De esta forma, se cumple exitosamente con el cuarto reto.
Reto 5
En este reto se requiere enviar la palabra ‘frida’ siempre, al método ‘chall05’ de una aplicación Android, empleando la función Java.choose. En el código proporcionado, se hace referencia al método ‘chall05’ con el argumento ‘notfrida!’.
Para asegurarse de que se envíe siempre la palabra ‘frida’ al método ‘call05’, se realizará un cambio en el valor de la línea 40 del código proporcionado, mediante el uso de una llamada específica. Se utilizará el comando ‘this.call05.call’ para realizar dicho cambio.
Este código hace uso de la herramienta Frida para interactuar con una aplicación de Android. Se utiliza la función Java.perform
para ejecutar una tarea en el hilo de la interfaz de usuario de la aplicación, y se establece un temporizador de 3 segundos (setTimeout) dentro de esta función para esperar antes de continuar con la siguiente línea de código.
La siguiente línea de código utiliza la función Java.choose
para buscar una clase específica en la aplicación de Android: ‘uk.rossmarks.fridalab.MainActivity’. Si se encuentra una instancia de esta clase, se sobrescribe el método ‘chall05’ con una nueva implementación que llama al método original con el argumento ‘frida’. Se advierte que esta acción puede modificar el comportamiento original del método y causar errores.
Finalmente, se escribe un mensaje de advertencia en la consola (‘OK’). De esta manera, el código quedará así:
Java.perform(function ()
{
setTimeout(function ()
{
Java.choose("uk.rossmarks.fridalab.MainActivity" ,
{
onMatch : function(instance)
{
instance.chall05.implementation = function ()
{
this.chall05.call(this,'frida');
}
console.warn('OK');
},
onComplete:function(){}
});
}, 3000);
});
Se ejecuta el comando de frida desde la ruta donde se encuentra el archivo “Reto5.js”, utilizando el siguiente comando: frida -U -l Reto5.js -f uk.rossmarks.fridalab
De esta manera, se logra cumplir con el quinto reto.
Reto 6
El reto requiere que se ejecute la función “chall06()” con el valor correcto después de que hayan pasado 10 segundos. Al revisar el código, se observa que hay tres métodos: uno para obtener el tiempo de inicio de la aplicación, otro para obtener el valor de “chall06()” después de transcurridos los 10 segundos, y un tercero para realizar las verificaciones de tiempo y convertir “chall06()” en una variable “i”
En MainActivity, se está agregando un número aleatorio a chall06.
En el reto 6, se debe confirmar que la función chall06 recibe el parámetro entero ‘i’ y si el resultado es verdadero, entonces se cumple con el desafío.
En este caso, se le indica al programa que espere 10000 milisegundos antes de tomar el valor de chall06 y enviarlo a la clase challenge_06. Además, se está imprimiendo el valor de chall06 en la consola utilizando la instrucción console.log().
En este código se utiliza Frida para modificar el comportamiento de una aplicación Android. Se ejecuta una tarea en el hilo de la interfaz de usuario de la aplicación mediante la función Java.perform
. Se establece un temporizador de 10 segundos (setTimeout) para esperar antes de continuar con la siguiente línea de código.
Se utiliza la función Java.use
para obtener acceso a la clase “uk.rossmarks.fridalab.challenge_06” y se sobreescribe el método “addChall06”. La nueva implementación escribe un mensaje de advertencia en la consola (“OK”), busca una instancia de la clase “uk.rossmarks.fridalab.MainActivity” utilizando la función Java.choose
y, si se encuentra una instancia, llama al método “chall06” en esa instancia y le pasa el valor del atributo “chall06” de la clase “uk.rossmarks.fridalab.challenge_06”. También se imprime en la consola el valor de “chall06.value”.
En resumen, este código utiliza Frida para modificar el comportamiento del método “addChall06” de la clase “uk.rossmarks.fridalab.challenge_06”, de manera que se busque una instancia de la clase “uk.rossmarks.fridalab.MainActivity” y se llame al método “chall06” en esa instancia, pasándole el valor del atributo “chall06” de la clase “uk.rossmarks.fridalab.challenge_06” como argumento. Además, se imprime en la consola el valor del atributo “chall06.value”
Java.perform(function ()
{
setTimeout(function ()
{
var challenge_06 = Java.use('uk.rossmarks.fridalab.challenge_06');
challenge_06.addChall06.implementation = function ()
{
console.warn("OK");
Java.choose("uk.rossmarks.fridalab.MainActivity" ,
{
onMatch : function(instance)
{
instance.chall06(challenge_06.chall06.value);
console.log("el código es: " + challenge_06.chall06.value);
},
onComplete:function(){}
});
}
}, 10000);
});
Se ejecuta el comando de frida desde la ruta donde se encuentra el archivo “Reto6.js”, con el comando frida -U -l Reto6.js -f uk.rossmarks.fridalab
Este comando cumple con el sexto reto de la aplicación.
Reto 7
En este reto se requiere realizar una fuerza bruta sobre el método “check07Pin()” y una vez obtenido el PIN correcto, llamar al método “chall07()”. La clase cuenta con dos métodos estáticos, el primero establece el valor de la variable “chall07” con un número aleatorio, mientras que el segundo establece el valor de “true” si la cadena es igual.
En esta parte del código, se realiza una comparación de “check07Pin()” y el número aleatorio que se encuentra en el atributo “chall07” de la clase “challenge_07”. Si ambos valores son iguales, entonces se asigna el valor 1 a la variable “completeArr”.
Para este reto, se realiza un recorrido de los números desde 19999 hasta 10000, a través de un bucle for. Sin embargo, se omite el primer número, de manera que el recorrido se realiza desde 9999 hasta 0000. Esto se hace con el propósito de entrar en la condición si el código es, por ejemplo, 0025.
Este código es un script de JavaScript que utiliza la herramienta “frida” para instrumentar una aplicación Java en ejecución.
El script tiene las siguientes funciones:
- Utiliza la función “Java.perform” de Frida para ejecutar una función anónima.
- Utiliza la función “setTimeout” de JavaScript para esperar 3 segundos antes de ejecutar el resto del código.
- Utiliza “Java.use” de Frida para obtener una instancia de la clase “challenge_07” en la aplicación Java.
- Imprime el valor actual de la variable “chall07” en la consola.
- Utiliza un bucle “for” para recorrer los números entre 19999 y 10000.
- Dentro del bucle, utiliza la función “slice” de JavaScript para obtener los 4 últimos dígitos de cada número y almacenarlos en una variable “num2”
- Utiliza el método “check07Pin” de la clase “challenge_07” para comparar el valor de “num2” con el valor actual de la variable “chall07”
- Si la comparación es verdadera, utiliza “Java.choose” de Frida para encontrar una instancia de la clase “MainActivity” en la aplicación Java y ejecuta el método “chall07” con el valor de “num2” como parámetro.
En resumen, se utiliza Frida para instrumentar una aplicación Java en ejecución y encontrar una instancia de la clase “challenge_07”. Luego, se recorren los números del 19999 al 10000 y se compara el valor de los 4 últimos dígitos de cada número con el valor actual de la variable “chall07”. Si se encuentra una coincidencia, se busca una instancia de la clase “MainActivity” y se ejecuta el método “chall07” con el valor de los 4 últimos dígitos como parámetro. Esto sugiere que el objetivo del código es encontrar el código PIN correcto para superar el desafío número 7.
Java.perform(function ()
{
setTimeout(function ()
{
var challenge_07 = Java.use('uk.rossmarks.fridalab.challenge_07');
console.log("el PIN es: " + challenge_07.chall07.value);
for (var i = 19999; i >= 10000; i--)
{
var num = i.toString();
var num2 = num.slice(1);
if (challenge_07.check07Pin(num2))
{
Java.choose("uk.rossmarks.fridalab.MainActivity" ,
{
onMatch : function(instance)
{
instance.chall07(num2);
console.warn('OK');
},
onComplete:function(){}
});
}
}
}, 3000);
});
Se ejecuta el comando de frida desde la ruta donde se encuentra el archivo frida -U -l Reto7.js -f uk.rossmarks.fridalab
y se observa que con él se cumple el séptimo reto.
Reto 8
En este reto, se pide cambiar el valor del botón “check” por “Confirm”. Para lograrlo, se debe buscar en el código la clase “R”, luego la propiedad “Id”, y finalmente la propiedad “Check”. Si el valor de esta propiedad es igual a “Confirm”, entonces se habrá cumplido con el reto.
Si se accede a la clase R - id - check, se puede observar que tiene un identificador en Hexadecimal, el cual puede ser utilizado para realizar el cambio requerido en el reto.
También se puede observar que el código realiza una llamada al identificador en hexadecimal correspondiente al botón con la palabra “check”, a través de la clase R - id - check.
Y también se puede encontrar en el archivo activity_main.xml con el mismo texto que se encuentra en la aplicación.
Se observa que el MainActivity realiza una importación de la clase Button de android.widget, donde se encuentra el botón de la aplicación. En este punto, se dispone de la información sobre el lugar donde se invoca el botón y su identificador.
En este reto se realiza una llamada a la instancia del botón utilizando el identificador correspondiente. A continuación, se convierte el objeto a la clase del botón utilizando java.cast, y se modifica su texto. Como último paso, se envía un mensaje opcional de “ok” para indicar que el proceso ha finalizado.
Este código utiliza la herramienta “Frida” para modificar una aplicación de Android en tiempo de ejecución. Se emplea la función “setTimeout” para esperar 2 segundos antes de continuar con el resto del código. Posteriormente, se utiliza la función “Java.choose” para seleccionar una actividad específica de la aplicación, denominada “uk.rossmarks.fridalab.MainActivity”. Dentro de esta función, se utiliza “Java.use” para obtener una instancia de un botón en la interfaz de usuario y modificar su texto a “Confirm” utilizando el método “setText”.
Java.perorm(function ()
{
setTimeout(function ()
{
Java.choose("uk.rossmarks.fridalab.MainActivity" ,
{
onMatch : function(instance)
{
var button = Java.use('android.widget.Button');
var identifier = instance.findViewById(0x7f07002f);
var check = Java.cast(identifier, button);
var string = Java.use('java.lang.String');
check.setText(string.$new("Confirm"));
console.warn("OK");
},
onComplete:function(){}
});
}, 2000);
});
Al ejecutar el comando de frida desde la ruta donde se encuentra el archivo Reto8.js, frida -U -l Reto8.js -f uk.rossmarks.fridalab
se cumple satisfactoriamente con el octavo reto.