17 KiB
Guía Paso a Paso: Extracción de Claves con Ghidra
Objetivo: Extraer ACCESS_KEY y SECRET_KEY de
libapi-keys.soDificultad: Principiante (no requiere experiencia previa)
Tiempo estimado: 30-45 minutos
Paso 1: Instalar Ghidra
1.1 Verificar Java
Ghidra requiere Java 17 o superior.
# Verificar versión de Java
java -version
Si no tienes Java 17+:
# 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
# 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
# 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:
- File → New Project
- Seleccionar: Non-Shared Project → Next
- Project Name:
adif-keys-extraction - Project Directory: Navegar a
/home/dasemu/Hacking/adif-api-reverse-enginereeng/tools - 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
- File → Import File
- Navegar a:
/home/dasemu/Hacking/adif-api-reverse-enginereeng/apk_extracted/lib/x86_64/libapi-keys.so - Click Select File to Import
Ghidra detectará automáticamente:
- Format: ELF (Executable and Linking Format)
- Language: x86:LE:64:default (Intel x86 64-bit)
- Click OK (dejar opciones por defecto)
- Click OK en el resumen de importación
Resultado:
- Verás
libapi-keys.soen el panel de archivos del proyecto
Paso 4: Analizar el Binario
4.1 Abrir el Archivo
- Doble click en
libapi-keys.soen el panel de archivos - Aparecerá mensaje: "libapi-keys.so has not been analyzed. Would you like to analyze it now?"
- 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
- 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
- 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:
- Click en el campo de búsqueda (arriba del panel)
- Escribir:
getAccessKeyPro - Presionar Enter
Deberías ver:
Java_com_adif_commonKeys_GetKeysHelper_getAccessKeyPro
5.3 Buscar getSecretKeyPro
Repetir búsqueda:
- Limpiar campo de búsqueda
- Escribir:
getSecretKeyPro - Presionar Enter
Deberías ver:
Java_com_adif_commonKeys_GetKeysHelper_getSecretKeyPro
Paso 6: Extraer ACCESS_KEY
6.1 Abrir Función getAccessKeyPro
- 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:
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í:
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:
(*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
- 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:
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:
- Window → Defined Strings
- Panel mostrará TODOS los strings del binario
- 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":
- Click en "Filter" (arriba)
- Filtrar por longitud mínima:
Min Length: 32 - 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:
- Click derecho → References → Show References to Address
- 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:
# Editar el archivo
nano adif_auth.py
# O con tu editor favorito
code adif_auth.py
Buscar líneas 402-403:
ACCESS_KEY = "YOUR_ACCESS_KEY_HERE" # Reemplazar
SECRET_KEY = "YOUR_SECRET_KEY_HERE" # Reemplazar
Reemplazar con las claves extraídas:
ACCESS_KEY = "la_clave_que_encontraste_en_getAccessKeyPro"
SECRET_KEY = "la_clave_que_encontraste_en_getSecretKeyPro"
9.2 Probar la Autenticación
# 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
# 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:
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:
- Window → Symbol Table
- Buscar manualmente:
Java_com_adif - Deberían aparecer todas las funciones JNI
Problema 2: El Código Decompilado es Ilegible
Solución:
- Click derecho en la función → Edit Function Signature
- Cambiar tipos de parámetros a:
jstring function_name(JNIEnv *env, jobject obj) - La decompilación mejorará
Problema 3: Las Claves Están Ofuscadas
Si ves algo como:
local_str[0] = 'A';
local_str[1] = 'K';
local_str[2] = 'I';
// ... muchas líneas
Solución:
- Las claves se construyen carácter por carácter
- Copiar todos los caracteres en orden
- Reconstruir el string manualmente
Problema 4: Ghidra No Arranca
Solución:
# 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
# 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
- ✅ Actualizar
adif_auth.pycon las claves reales - ✅ Ejecutar
python3 adif_auth.pypara verificar - ✅ Crear script de prueba
test_real_auth.py - ✅ Hacer peticiones a todos los endpoints documentados
- ✅ Verificar que obtienes Status 200 y datos reales
- ✅ 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:
- Revisa la sección Troubleshooting arriba
- Consulta la documentación de Ghidra: https://ghidra-sre.org/
- Busca en el proyecto archivos relacionados:
FINAL_SUMMARY.md- Resumen del proyectoAUTHENTICATION_ALGORITHM.md- Detalles del algoritmoREADME_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.