Refactor: reorganización completa del proyecto y documentación consolidada

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
This commit is contained in:
2025-12-05 11:22:13 +01:00
parent aa02d7c896
commit 68fac80520
42 changed files with 66402 additions and 4876 deletions

591
docs/GHIDRA_GUIDE.md Normal file
View File

@@ -0,0 +1,591 @@
# 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.