"Reversing fundamental de aplicaciones Android"
"Reversing fundamental de aplicaciones Android" | |
---|---|
Nombre del charlista | Ant1; 4nt1 |
Topico de la charla | Android; Hacking APKs. |
Fecha de la charla | 06/12/2024 |
Enlace a la charla | https://nc.ssepi0l-pv.cl/index.php/s/Sr3P9ka5rjanFn6 |
Ubicación | Interwebs. |
Esta charla realizada por Ant1 trató sobre lo más básico de lo básico a la hora de auditar aplicaciones del mundo Android. Debido a que es un tema extenso, tuvo poco tiempo para exponer todo lo que le habría gustado exponer, y terminó realizando un speedrun de la charla.
Herramientas necesarias.
Para realizar auditorías de aplicaciones Android, es si o si necesario tener las siguientes tools.
Genymotion/Emulador de Android.
Más que Genymotion, necesitarás un emulador de Android. Esto, si bien se recomienda, no es completamente necesario, ya que puedes utilizar un dispositivo físico para realizar las pruebas. Sin embargo, usar un emulador es más rápido y menos tediosos.
Android Tools (adb)
Las Android-Tools son herramientas que se utilizan - en muchos casos - para ayudar en el desarrollo de aplicaciones de este sistema operativo. Sin embargo, adb es altamente útil para revisar logs, establecer conexiones depuradoras con el teléfono o máquina virtual, configurar proxies, entre otras cosas.
Métodos de instalación.
Dependiendo de tu entorno, puede ser un proceso sencillo o un tanto complejo.
Linux
En Linux el proceso es bastante sencillo. Revisa con tu distro cómo se llama el paquete android-tools
.
sudo apt install android-tools
sudo pacman -S android-tools
En otras distros, el nombre puede cambiar.
Windows
En Windows, la instalación de estas herramientas puede ser un dolor de cabeza. Existen varias formas de conseguir estas tools:
- Mediante Android Studio SDK.
- Mediante APK Easy Tool
- Mediante Google Android Tools.
Una vez consigas el ADB, debes añadirlo a tu PATH.
Frida
Frida requiere tener Python 3 instalado en el computador. Si usas Linux, muy probablemente ya tienes python3
instalado. En Windows, debes descargarlo, instalarlo y añadirlo a tu PATH.
Ahora, teniendo Python instalado, debes instalar PIP. Si usas Windows, probablemente ya lo tienes. En Linux, es probable que debas instalarlo.
sudo apt install python3-pip
sudo pacman -S python-pip
A continuación, debes instalar frida.
python -m pip install frida
En este momento, tienes que verificar que frida
esté en tu PATH, tanto en Linux como en Windows.
frida --version
Linux
En el caso de no tenerlo en el PATH, debes hacer lo siguiente:
export PATH=$USER/.local/bin:
Y estaría listo.
frida-server
frida-server
es un elemento esencial a la hora de trabajar con Android. Este programa nos permite interceptar la ejecución de un aplicativo y tomar control sobre él. No utilizarlo significaría tener que parchear la aplicación original con un frida-gadget
, lo cual si bien es posible, puede terminar siendo un proceso tedioso.
Tener en cuenta: la versión del frida-server
y la de frida
DEBEN SER LA MISMA. De no ser la misma, la ejecución fallará o será altamente inestable.
Procedimiento de instalación
Para instalar frida-tools
en nuestro dispositivo, es necesario dejar el binario en el dispositivo; no se puede instalar, ya que como tal, no es un APK, sino un ELF. Esto se puede realizar de la siguiente manera:
adb push frida-tools /data/local/tmp/frida-server
adb shell chmod 777 /data/local/tmp/frida-server
adb shell su -c "/data/local/tmp/frida-server"
Con esto listo, el frida-server
estaría ejecutándose en nuestro dispositivo.
JADX
JADX nos permitirá decomprimir, decompilar y revisar el código de las APKs rápidamente, además de ayudarnos a crear scripts con Frida. Es una herramienta de debugging que nos permitirá leer el código fácil y rápidamente.
Herramientas no esenciales.
Burp Suite
Si bien Burp Suite es bastante útil en algunas auditorías Android, no es requerido.
Objection
Muchas veces, Frida y Objection van de la mano. Pero estrictamente hablando, no se requiere.
Preparación del ambiente.
Con las herramientas instaladas y funcionando, podemos comenzar a auditar. Primero, debes crear una máquina virtual. En el caso de que estés realizando una auditoría real, prueba con Android 8 primero y revisa si la aplicación abre. Si abre, felicitaciones: tienes una primera vulnerabilidad :).
Con la máquina virtual creada, verifica que esta esté conectada a tu adb
. Esto se puede realizar con el comando adb devices
. Si aparece un dispositivo, está conectada correctamente a adb
. Caso contrario, debes investigar qué está fallando.
Con estas validaciones hechas, se recomienda ejecutar adb remount
, lo cual nos ayudará a remontar el filesystem de Android en modo lectura-escritura (rw), que nos permitirá a instalar aplicaciones utilizando adb
y hacer cambios en el dispositivo.
Plantillas
Les compartiré un recurso que utilizo para crear scripst con Frida. Estas plantillas las fui sacando de varios lugares. Disfruten.
// template for function reimplementation
Java.perform(function() {
const let MainActivity = Java.use(com.app.MainActivity);
MainActivity.function.implementation = function() {
// new function
};
});
// template for static functions
Java.perform(function() {
var classRef = Java.use("<package_name>.<class>");
classRef.<method_to_hook>.implementation = function(args) {
// Custom logic to execute when the method is called
}
});
// method invocation
Java.perform(function() {
var <class_reference> = Java.use("<package_name>.<class>");
<class_reference>.<static_method>();
});
// variable value swapping
Java.perform(function (){
var <class_reference> = Java.use("<package_name>.<class>");
<class_reference>.<variable>.value = <value>;
});
// non-static method call
Java.perform(function() {
var class_reference = Java.use("<package_name>.<class>");
var class_instance = class_reference.$new(); // Class Object
class_instance.<method>(); // Calling the method
});
// existing instance method invocation
Java.performNow(function() {
Java.choose('<Package>.<Class_Name>', {
onMatch: function(instance) {
/*
depending on the Java.choose() package.class pick, it'll be the instance in function(instance).
there is no need to change the instance value, and changing it might actually make the app fail.
run your code here.
*/
},
onComplete: function() {}
});
});
// object passing
Java.performNow(function() {
Java.choose('<Package>.<Class_Name>', {
onMatch: function(instance) {
console.log("Instance found");
var checker = Java.use("<Package>.<Class_Name>.<Method>");
var checker_obj = checker.$new(); // Class Object
checker_obj.x.value = VALUE;
checker_obj.y.value = VALUE;
instance.getFlag(checker_obj); // invoking the getFlag method
},
onComplete: function() {}
});
});
// hooking the main thread (UI thread)
Java.perform(function() {
var <class_reference> = Java.use("<package_name>.<class>");
<class_reference>.$init.implementation = function(<args>){ // eyes set on the $init parameter. it's used for main thread hooking.
/*
YOUR CODE GOES HERE !
*/
}
});
// intercepting native apis with the Interceptor function
Interceptor.attach(targetAddress, {
onEnter: function (args) {
console.log('Entering ' + functionName);
// Modify or log arguments if needed
},
onLeave: function (retval) {
console.log('Leaving ' + functionName);
// Modify or log return value if needed
}
});
/*
- Using the Frida API: Module.enumerateExports()
- Using the Frida API: Module.getExportByName()
- Using the Frida API: Module.findExportByName()
- Calculate the offset and add it to the Module.getBaseAddress() (Base address)
- Using the Frida API: Module.enumerateImports()
*/
// changing variable values in native libraries
var flag = Module.enumerateExports("libFridaNine.so")[0]['address'];
Interceptor.attach(flag, {
onEnter: function (args) {
// Modify or log arguments if needed
},
onLeave: function (retval) {
// Modify or log return value if needed
}
});
Cierre
El resto de cosas que deben aprender, las encontrarán en la charla.