← Volver al inicio
Android APK Reversing Smali dex2jar Apktool
Avanzado

Android Reversing: Modificación de Binarios (Smali)

15/03/2022

La Ingeniería Inversa (Reversing) en Android consiste en desensamblar una aplicación (APK) para estudiar su lógica, extraer secretos o modificar su comportamiento (Patching). En esta guía abordaremos el parcheo de vulnerabilidades en InsecureBankv2 y cómo saltarse los controles del famoso CTF KGB Messenger.

1. El Ciclo de Vida del Reversing

El código Java/Kotlin que escriben los desarrolladores se compila a un formato bytecode llamado DEX (Dalvik Executable). Para analizarlo, tenemos dos caminos:

2. InsecureBankv2: Parcheando el AndroidManifest

En el laboratorio anterior vimos que la actividad .PostLogin estaba exportada, permitiendo un Bypass del Login. Vamos a parchear la APK para arreglar la vulnerabilidad.

# 1. Desensamblar la APK original:
apktool d InsecureBankv2.apk -o InsecureBank_Source

# 2. Abrir InsecureBank_Source/AndroidManifest.xml con tu editor.
# Cambiar: android:exported="true" -> android:exported="false"

# 3. Recompilar la APK a partir de la carpeta modificada:
apktool b InsecureBank_Source -o InsecureBank_Patched.apk

# 4. Firmar la nueva APK (Android no instala apps sin firma):
# Generar una clave falsa:
keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
# Firmar la APK:
apksigner sign --ks my-release-key.keystore InsecureBank_Patched.apk

# 5. Instalar la versión parcheada en el dispositivo:
adb install InsecureBank_Patched.apk

3. KGB Messenger CTF: Bypass de Lógica en Smali

El CTF KGB Messenger es una app que, al abrirla, comprueba si el idioma de tu dispositivo está en ruso ("Russia"). Si no lo está, la app se cierra. Nuestro objetivo es parchear el binario para saltarnos este control.

Paso 1: Identificar el Control

Abriendo la APK en JADX, vemos algo como esto en MainActivity.java:

String locale = Locale.getDefault().getCountry();
if (!locale.equals("RU")) {
    System.exit(0);
}

Paso 2: Parchear en Smali

Desensamblamos con Apktool y abrimos smali/com/kgb/messenger/MainActivity.smali. Buscamos la instrucción de salto condicional (Branching).

# Código Smali original:
invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z
move-result v0
if-eqz v0, :cond_0   # "if-eqz" significa "If Equal to Zero" (Si NO son iguales, salta a cond_0 que cierra la app)
...
:cond_0
invoke-static {v0}, Ljava/lang/System;->exit(I)V

El Parcheo: Cambiamos la instrucción if-eqz por if-nez (If Not Equal to Zero). Ahora la lógica se invierte: la app se cerrará solo si el dispositivo ESTÁ en ruso. Recompilamos, firmamos y la app se abrirá en nuestro emulador en inglés.

🔴 Simulador de Parcheo Smali

Te has infiltrado en el código ensamblador (Smali) de un Malware bancario. La app realiza una comprobación de seguridad: verifica si el dispositivo está "Rooteado". Demuestra tus habilidades de Reversing indicando cómo manipular las instrucciones para burlar esta defensa.

>_ INICIAR RETO CTF 27

4. Obtención de Credenciales y Criptografía

Una vez dentro del KGB Messenger, nos pide un usuario y contraseña. En el código Java descompilado (JADX), vemos que la app carga un string llamado user_name y comprueba la contraseña contra un MD5.

# En InsecureBank_Source/res/values/strings.xml encontramos:
<string name="user_name">Stearling Archer</string>
<string name="flag_part1">RkxBR3tLNEc4X...</string>

La contraseña no está en el código, pero aplicando OSINT/Ingeniería Social sobre el personaje "Sterling Archer", deducimos que la contraseña es Guest. Al introducirla, la app nos da acceso y podemos descifrar los mensajes en AES que están hardcodeados en MessengerActivity.java.

5. Glosario Rápido de Instrucciones Smali

InstrucciónSignificado Lógico
if-eqz v0, :cond_0If Equal Zero (Si v0 == 0 / false, salta a cond_0)
if-nez v0, :cond_0If Not Equal Zero (Si v0 != 0 / true, salta a cond_0)
move-result v0Guarda el resultado de la última función en el registro v0
const/4 v0, 0x1Asigna el valor 1 (true) al registro v0
goto :goto_0Salto incondicional hacia la etiqueta :goto_0