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