Esta actualización reorganiza el proyecto de reverse engineering de la API de ADIF con los siguientes cambios: Estructura del proyecto: - Movida documentación principal a carpeta docs/ - Consolidados archivos markdown redundantes en CLAUDE.md (contexto completo del proyecto) - Organización de tests en carpeta tests/ con README explicativo - APK renombrado de base.apk a adif.apk para mayor claridad Archivos de código: - Movidos adif_auth.py y adif_client.py a la raíz (antes en api_testing_scripts/) - Eliminados scripts de testing obsoletos y scripts de Frida no utilizados - Nuevos tests detallados: test_endpoints_detailed.py y test_onepaths_with_real_trains.py Descubrimientos: - Documentados nuevos hallazgos en docs/NEW_DISCOVERIES.md - Actualización de onePaths funcionando con commercialNumber real (devuelve 200) - Extraídos 1587 códigos de estación en station_codes.txt Configuración: - Actualizado .gitignore con mejores patrones para Python e IDEs - Eliminados archivos temporales de depuración y logs
592 lines
17 KiB
Markdown
592 lines
17 KiB
Markdown
# Guía Paso a Paso: Extracción de Claves con Ghidra
|
|
|
|
> **Objetivo:** Extraer ACCESS_KEY y SECRET_KEY de `libapi-keys.so`
|
|
>
|
|
> **Dificultad:** Principiante (no requiere experiencia previa)
|
|
>
|
|
> **Tiempo estimado:** 30-45 minutos
|
|
|
|
---
|
|
|
|
## Paso 1: Instalar Ghidra
|
|
|
|
### 1.1 Verificar Java
|
|
|
|
Ghidra requiere Java 17 o superior.
|
|
|
|
```bash
|
|
# Verificar versión de Java
|
|
java -version
|
|
```
|
|
|
|
**Si no tienes Java 17+:**
|
|
|
|
```bash
|
|
# Ubuntu/Debian
|
|
sudo apt update
|
|
sudo apt install openjdk-17-jdk
|
|
|
|
# Verificar instalación
|
|
java -version
|
|
```
|
|
|
|
**Salida esperada:**
|
|
```
|
|
openjdk version "17.0.x" ...
|
|
```
|
|
|
|
### 1.2 Descargar Ghidra
|
|
|
|
```bash
|
|
# Ir a tu directorio de trabajo
|
|
cd /home/dasemu/Hacking/adif-api-reverse-enginereeng
|
|
|
|
# Crear carpeta para herramientas
|
|
mkdir -p tools
|
|
cd tools
|
|
|
|
# Descargar Ghidra (versión 11.2.1 - última estable)
|
|
wget https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_11.2.1_build/ghidra_11.2.1_PUBLIC_20241105.zip
|
|
|
|
# Extraer
|
|
unzip ghidra_11.2.1_PUBLIC_20241105.zip
|
|
|
|
# Navegar a la carpeta
|
|
cd ghidra_11.2.1_PUBLIC
|
|
```
|
|
|
|
**Estructura después de extraer:**
|
|
```
|
|
tools/
|
|
└── ghidra_11.2.1_PUBLIC/
|
|
├── ghidraRun
|
|
├── support/
|
|
├── docs/
|
|
└── ...
|
|
```
|
|
|
|
### 1.3 Ejecutar Ghidra
|
|
|
|
```bash
|
|
# Dar permisos de ejecución
|
|
chmod +x ghidraRun
|
|
|
|
# Ejecutar Ghidra
|
|
./ghidraRun
|
|
```
|
|
|
|
**Qué esperar:**
|
|
- Se abrirá una ventana GUI de Ghidra
|
|
- Primera vez puede tardar 30-60 segundos
|
|
|
|
---
|
|
|
|
## Paso 2: Crear Proyecto en Ghidra
|
|
|
|
### 2.1 Crear Nuevo Proyecto
|
|
|
|
Una vez abierto Ghidra:
|
|
|
|
1. **File** → **New Project**
|
|
2. Seleccionar: **Non-Shared Project** → **Next**
|
|
3. **Project Name:** `adif-keys-extraction`
|
|
4. **Project Directory:** Navegar a `/home/dasemu/Hacking/adif-api-reverse-enginereeng/tools`
|
|
5. Click **Finish**
|
|
|
|
**Resultado:**
|
|
- Verás el proyecto creado en la ventana principal
|
|
- Panel izquierdo estará vacío (sin archivos importados aún)
|
|
|
|
---
|
|
|
|
## Paso 3: Importar libapi-keys.so
|
|
|
|
### 3.1 Importar el Archivo
|
|
|
|
1. **File** → **Import File**
|
|
2. Navegar a: `/home/dasemu/Hacking/adif-api-reverse-enginereeng/apk_extracted/lib/x86_64/libapi-keys.so`
|
|
3. Click **Select File to Import**
|
|
|
|
**Ghidra detectará automáticamente:**
|
|
- **Format:** ELF (Executable and Linking Format)
|
|
- **Language:** x86:LE:64:default (Intel x86 64-bit)
|
|
|
|
4. Click **OK** (dejar opciones por defecto)
|
|
5. Click **OK** en el resumen de importación
|
|
|
|
**Resultado:**
|
|
- Verás `libapi-keys.so` en el panel de archivos del proyecto
|
|
|
|
---
|
|
|
|
## Paso 4: Analizar el Binario
|
|
|
|
### 4.1 Abrir el Archivo
|
|
|
|
1. Doble click en `libapi-keys.so` en el panel de archivos
|
|
2. Aparecerá mensaje: **"libapi-keys.so has not been analyzed. Would you like to analyze it now?"**
|
|
3. Click **Yes**
|
|
|
|
### 4.2 Configurar Análisis
|
|
|
|
Aparecerá ventana "Analysis Options":
|
|
|
|
**Opciones recomendadas para nuestro caso:**
|
|
- ✅ **Decompiler Parameter ID** (activado)
|
|
- ✅ **Function Start Search** (activado)
|
|
- ✅ **ASCII Strings** (activado) ← **IMPORTANTE**
|
|
- ✅ **Demangler GNU** (activado)
|
|
- ✅ **Shared Return Calls** (activado)
|
|
|
|
**Resto:** Dejar por defecto
|
|
|
|
4. Click **Analyze**
|
|
|
|
**Qué esperar:**
|
|
- Proceso de análisis tomará 2-5 minutos
|
|
- Verás barra de progreso en la esquina inferior derecha
|
|
- Cuando termine, el panel principal mostrará código desensamblado
|
|
|
|
---
|
|
|
|
## Paso 5: Buscar las Funciones JNI
|
|
|
|
### 5.1 Abrir Ventana de Funciones
|
|
|
|
1. **Window** → **Functions** (o presionar `Ctrl+F`)
|
|
|
|
**Panel de funciones se abrirá** mostrando todas las funciones del binario.
|
|
|
|
### 5.2 Buscar getAccessKeyPro
|
|
|
|
En el panel de Functions:
|
|
|
|
1. Click en el campo de búsqueda (arriba del panel)
|
|
2. Escribir: `getAccessKeyPro`
|
|
3. Presionar Enter
|
|
|
|
**Deberías ver:**
|
|
```
|
|
Java_com_adif_commonKeys_GetKeysHelper_getAccessKeyPro
|
|
```
|
|
|
|
### 5.3 Buscar getSecretKeyPro
|
|
|
|
Repetir búsqueda:
|
|
|
|
1. Limpiar campo de búsqueda
|
|
2. Escribir: `getSecretKeyPro`
|
|
3. Presionar Enter
|
|
|
|
**Deberías ver:**
|
|
```
|
|
Java_com_adif_commonKeys_GetKeysHelper_getSecretKeyPro
|
|
```
|
|
|
|
---
|
|
|
|
## Paso 6: Extraer ACCESS_KEY
|
|
|
|
### 6.1 Abrir Función getAccessKeyPro
|
|
|
|
1. En el panel de Functions, doble click en:
|
|
```
|
|
Java_com_adif_commonKeys_GetKeysHelper_getAccessKeyPro
|
|
```
|
|
|
|
**Panel principal mostrará:**
|
|
- **Izquierda:** Código ensamblador (difícil de leer)
|
|
- **Derecha:** Código C decompilado (fácil de leer)
|
|
|
|
### 6.2 Analizar el Código Decompilado
|
|
|
|
En el panel derecho ("Decompile: libapi-keys.so"), busca algo similar a:
|
|
|
|
```c
|
|
JNIEnv * Java_com_adif_commonKeys_GetKeysHelper_getAccessKeyPro(JNIEnv *env, jobject obj)
|
|
{
|
|
// ... código de inicialización ...
|
|
|
|
// Buscar líneas que contengan cadenas o retornos
|
|
return (*env)->NewStringUTF(env, "ALGUNA_CADENA_AQUI");
|
|
}
|
|
```
|
|
|
|
**O puede verse así:**
|
|
|
|
```c
|
|
jstring Java_com_adif_commonKeys_GetKeysHelper_getAccessKeyPro
|
|
(JNIEnv *param_1,jobject param_2)
|
|
{
|
|
jstring pJVar1;
|
|
|
|
pJVar1 = (*(*param_1)->NewStringUTF)(param_1, "LA_CLAVE_AQUI");
|
|
return pJVar1;
|
|
}
|
|
```
|
|
|
|
### 6.3 Identificar la Clave
|
|
|
|
**La ACCESS_KEY será el string entre comillas en `NewStringUTF`**
|
|
|
|
Ejemplo:
|
|
```c
|
|
(*env)->NewStringUTF(env, "AKIAxxxxxxxxxxxxxxxx")
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
Esta es la ACCESS_KEY
|
|
```
|
|
|
|
**Copia ese string completo** → Esa es tu ACCESS_KEY
|
|
|
|
---
|
|
|
|
## Paso 7: Extraer SECRET_KEY
|
|
|
|
### 7.1 Repetir para getSecretKeyPro
|
|
|
|
1. En el panel de Functions, doble click en:
|
|
```
|
|
Java_com_adif_commonKeys_GetKeysHelper_getSecretKeyPro
|
|
```
|
|
|
|
### 7.2 Analizar el Código
|
|
|
|
Nuevamente, busca en el panel derecho:
|
|
|
|
```c
|
|
jstring Java_com_adif_commonKeys_GetKeysHelper_getSecretKeyPro
|
|
(JNIEnv *param_1,jobject param_2)
|
|
{
|
|
jstring pJVar1;
|
|
|
|
pJVar1 = (*(*param_1)->NewStringUTF)(param_1, "LA_SECRET_KEY_AQUI");
|
|
return pJVar1;
|
|
}
|
|
```
|
|
|
|
**La SECRET_KEY será el string entre comillas**
|
|
|
|
**Copia ese string completo** → Esa es tu SECRET_KEY
|
|
|
|
---
|
|
|
|
## Paso 8: Si No Ves Strings Directamente
|
|
|
|
### 8.1 Alternativa: Buscar en Strings Definidos
|
|
|
|
Si las funciones usan referencias indirectas:
|
|
|
|
1. **Window** → **Defined Strings**
|
|
2. Panel mostrará TODOS los strings del binario
|
|
3. Buscar por características:
|
|
- Longitud ~40-64 caracteres
|
|
- Formato Base64 o alfanumérico
|
|
- Probablemente consecutivos en la lista
|
|
|
|
### 8.2 Filtrar Strings Sospechosos
|
|
|
|
En el panel "Defined Strings":
|
|
|
|
1. Click en "Filter" (arriba)
|
|
2. Filtrar por longitud mínima: `Min Length: 32`
|
|
3. Revisar manualmente strings que parezcan claves
|
|
|
|
**Características de claves típicas:**
|
|
- ACCESS_KEY: ~20-40 caracteres, alfanumérico
|
|
- SECRET_KEY: ~40-64 caracteres, alfanumérico o Base64
|
|
|
|
### 8.3 Verificar Referencias
|
|
|
|
Para cada string sospechoso:
|
|
|
|
1. Click derecho → **References** → **Show References to Address**
|
|
2. Si está referenciado por las funciones JNI que buscamos, es la clave correcta
|
|
|
|
---
|
|
|
|
## Paso 9: Usar las Claves Extraídas
|
|
|
|
### 9.1 Actualizar adif_auth.py
|
|
|
|
Una vez tengas ambas claves:
|
|
|
|
```bash
|
|
# Editar el archivo
|
|
nano adif_auth.py
|
|
|
|
# O con tu editor favorito
|
|
code adif_auth.py
|
|
```
|
|
|
|
**Buscar líneas 402-403:**
|
|
|
|
```python
|
|
ACCESS_KEY = "YOUR_ACCESS_KEY_HERE" # Reemplazar
|
|
SECRET_KEY = "YOUR_SECRET_KEY_HERE" # Reemplazar
|
|
```
|
|
|
|
**Reemplazar con las claves extraídas:**
|
|
|
|
```python
|
|
ACCESS_KEY = "la_clave_que_encontraste_en_getAccessKeyPro"
|
|
SECRET_KEY = "la_clave_que_encontraste_en_getSecretKeyPro"
|
|
```
|
|
|
|
### 9.2 Probar la Autenticación
|
|
|
|
```bash
|
|
# Ejecutar el script de ejemplo
|
|
python3 adif_auth.py
|
|
```
|
|
|
|
**Salida esperada:**
|
|
```
|
|
======================================================================
|
|
ADIF API Authenticator - Ejemplo de Uso
|
|
======================================================================
|
|
|
|
Headers generados:
|
|
----------------------------------------------------------------------
|
|
Content-Type: application/json;charset=utf-8
|
|
X-Elcano-Host: circulacion.api.adif.es
|
|
X-Elcano-Client: AndroidElcanoApp
|
|
X-Elcano-Date: 20251204T123456Z
|
|
X-Elcano-UserId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
Authorization: HMAC-SHA256 Credential=...
|
|
User-key: f4ce9fbfa9d721e39b8984805901b5df
|
|
```
|
|
|
|
### 9.3 Probar Petición Real
|
|
|
|
```python
|
|
# test_real_auth.py
|
|
from adif_auth import AdifAuthenticator
|
|
import requests
|
|
|
|
# Usar las claves reales
|
|
ACCESS_KEY = "tu_access_key_extraida"
|
|
SECRET_KEY = "tu_secret_key_extraida"
|
|
|
|
auth = AdifAuthenticator(access_key=ACCESS_KEY, secret_key=SECRET_KEY)
|
|
|
|
url = "https://circulacion.api.adif.es/portroyalmanager/secure/circulationpaths/departures/traffictype/"
|
|
payload = {
|
|
"commercialService": "BOTH",
|
|
"commercialStopType": "BOTH",
|
|
"page": {"pageNumber": 0},
|
|
"stationCode": "10200",
|
|
"trafficType": "ALL"
|
|
}
|
|
|
|
headers = auth.get_auth_headers("POST", url, payload)
|
|
headers["User-key"] = auth.USER_KEY_CIRCULATION
|
|
|
|
response = requests.post(url, json=payload, headers=headers)
|
|
|
|
print(f"Status: {response.status_code}")
|
|
if response.status_code == 200:
|
|
print("¡ÉXITO! Autenticación funcionando")
|
|
print(response.json())
|
|
else:
|
|
print("Error:", response.text)
|
|
```
|
|
|
|
**Ejecutar:**
|
|
```bash
|
|
python3 test_real_auth.py
|
|
```
|
|
|
|
**Si todo funciona:**
|
|
```
|
|
Status: 200
|
|
¡ÉXITO! Autenticación funcionando
|
|
{'departures': [...], 'totalElements': 45, ...}
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Problema 1: No Veo las Funciones JNI
|
|
|
|
**Solución:**
|
|
|
|
1. **Window** → **Symbol Table**
|
|
2. Buscar manualmente: `Java_com_adif`
|
|
3. Deberían aparecer todas las funciones JNI
|
|
|
|
### Problema 2: El Código Decompilado es Ilegible
|
|
|
|
**Solución:**
|
|
|
|
1. Click derecho en la función → **Edit Function Signature**
|
|
2. Cambiar tipos de parámetros a:
|
|
```
|
|
jstring function_name(JNIEnv *env, jobject obj)
|
|
```
|
|
3. La decompilación mejorará
|
|
|
|
### Problema 3: Las Claves Están Ofuscadas
|
|
|
|
Si ves algo como:
|
|
|
|
```c
|
|
local_str[0] = 'A';
|
|
local_str[1] = 'K';
|
|
local_str[2] = 'I';
|
|
// ... muchas líneas
|
|
```
|
|
|
|
**Solución:**
|
|
|
|
1. Las claves se construyen carácter por carácter
|
|
2. Copiar todos los caracteres en orden
|
|
3. Reconstruir el string manualmente
|
|
|
|
### Problema 4: Ghidra No Arranca
|
|
|
|
**Solución:**
|
|
|
|
```bash
|
|
# Verificar Java
|
|
java -version
|
|
|
|
# Si Java < 17, actualizar
|
|
sudo apt install openjdk-17-jdk
|
|
|
|
# Reintentar
|
|
./ghidraRun
|
|
```
|
|
|
|
---
|
|
|
|
## Resumen Visual del Proceso
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ 1. Instalar Ghidra + Java 17 │
|
|
└─────────────────┬───────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ 2. Crear Proyecto → Import libapi-keys.so │
|
|
└─────────────────┬───────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ 3. Analizar (Auto Analysis con opciones por defecto) │
|
|
└─────────────────┬───────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ 4. Window → Functions → Buscar "getAccessKeyPro" │
|
|
└─────────────────┬───────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ 5. Doble click → Ver código decompilado (panel derecho) │
|
|
└─────────────────┬───────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ 6. Encontrar NewStringUTF(env, "LA_CLAVE_AQUI") │
|
|
└─────────────────┬───────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ 7. Copiar el string → Esa es la ACCESS_KEY │
|
|
└─────────────────┬───────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ 8. Repetir con "getSecretKeyPro" → SECRET_KEY │
|
|
└─────────────────┬───────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ 9. Actualizar adif_auth.py con las claves │
|
|
└─────────────────┬───────────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ 10. Probar peticiones → ¡SUCCESS! (Status 200) │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Comandos Rápidos de Referencia
|
|
|
|
```bash
|
|
# Instalar Java 17
|
|
sudo apt install openjdk-17-jdk
|
|
|
|
# Descargar y extraer Ghidra
|
|
cd /home/dasemu/Hacking/adif-api-reverse-enginereeng/tools
|
|
wget https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_11.2.1_build/ghidra_11.2.1_PUBLIC_20241105.zip
|
|
unzip ghidra_11.2.1_PUBLIC_20241105.zip
|
|
|
|
# Ejecutar Ghidra
|
|
cd ghidra_11.2.1_PUBLIC
|
|
chmod +x ghidraRun
|
|
./ghidraRun
|
|
|
|
# Archivo a analizar
|
|
# /home/dasemu/Hacking/adif-api-reverse-enginereeng/apk_extracted/lib/x86_64/libapi-keys.so
|
|
|
|
# Funciones a buscar
|
|
# Java_com_adif_commonKeys_GetKeysHelper_getAccessKeyPro
|
|
# Java_com_adif_commonKeys_GetKeysHelper_getSecretKeyPro
|
|
```
|
|
|
|
---
|
|
|
|
## Próximos Pasos Después de Extraer las Claves
|
|
|
|
1. ✅ Actualizar `adif_auth.py` con las claves reales
|
|
2. ✅ Ejecutar `python3 adif_auth.py` para verificar
|
|
3. ✅ Crear script de prueba `test_real_auth.py`
|
|
4. ✅ Hacer peticiones a todos los endpoints documentados
|
|
5. ✅ Verificar que obtienes Status 200 y datos reales
|
|
6. ✅ Actualizar documentación con resultados finales
|
|
|
|
---
|
|
|
|
## Notas Importantes
|
|
|
|
⚠️ **Seguridad:**
|
|
- Las claves extraídas son secretos de ADIF
|
|
- No las compartas públicamente
|
|
- No las subas a repositorios públicos
|
|
- Usa variables de entorno en producción
|
|
|
|
⚠️ **Legalidad:**
|
|
- Este análisis es para fines educativos
|
|
- Usa la API responsablemente
|
|
- Respeta rate limits
|
|
- No abuses del servicio
|
|
|
|
⚠️ **Mantenimiento:**
|
|
- Las claves pueden cambiar en futuras versiones de la app
|
|
- Verifica periódicamente si hay actualizaciones
|
|
- Repite el proceso si las claves dejan de funcionar
|
|
|
|
---
|
|
|
|
## Ayuda Adicional
|
|
|
|
Si encuentras problemas durante el proceso:
|
|
|
|
1. Revisa la sección **Troubleshooting** arriba
|
|
2. Consulta la documentación de Ghidra: https://ghidra-sre.org/
|
|
3. Busca en el proyecto archivos relacionados:
|
|
- `FINAL_SUMMARY.md` - Resumen del proyecto
|
|
- `AUTHENTICATION_ALGORITHM.md` - Detalles del algoritmo
|
|
- `README_FINAL.md` - Guía general
|
|
|
|
---
|
|
|
|
**¡Éxito con la extracción!** 🔑
|
|
|
|
Una vez tengas las claves, habrás completado el 100% del reverse engineering de la API de ADIF.
|