# 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.