Saltar al contenido principal

Por qué tuve que aprender Assembly y Smali: cuando las herramientas automáticas te abandonan

15 de enero de 2025

El momento que me bajó los humos como pentester móvil

Mes 8 de mi carrera en pentesting móvil. Me creía la muerte porque dominaba APKTool y podía leer código Java decompilado como si fuera El Comercio dominical.

Mi workflow “profesional” de siempre:

apktool d empresa-secure.apk
# Abrir MainActivity.java y buscar vulnerabilidades obvias
# Profit... ¿verdad?

Plot twist que me humilló: Una aplicación enterprise me puso en mi lugar de la forma más brutal posible.

El código decompilado parecía jeroglíficos alienígenas. Métodos con nombres como a.b.c.d(), variables llamadas e y f, y mi “análisis profesional” se redujo a adivinar qué carajo hacía cada función.

Ahí me cayó la ficha: Si quería ser más que un script kiddie con herramientas automáticas, necesitaba bajar hasta el assembly. No había de otra.

El momento que me bajó los humos como pentester móvil

Mes 8 de mi carrera en pentesting móvil. Me creía la muerte porque dominaba APKTool y podía leer código Java decompilado como si fuera El Comercio dominical.

Mi workflow “profesional” de siempre:

apktool d empresa-secure.apk
# Abrir MainActivity.java y buscar vulnerabilidades obvias
# Profit... ¿verdad?

Plot twist que me humilló: Una aplicación enterprise me puso en mi lugar de la forma más brutal posible.

El código decompilado parecía jeroglíficos alienígenas. Métodos con nombres como a.b.c.d(), variables llamadas e y f, y mi “análisis profesional” se redujo a adivinar qué carajos hacía cada función.

Ahí lo entendí: Si quería ser más que un script kiddie con herramientas automáticas, necesitaba bajar hasta el assembly. No había alternativa.

Cuando APKTool te deja plantado como pata

Lo que mi cerebro esperaba encontrar:

public boolean isRooted() {
    if (checkSuperUser() || checkRootBinary()) {
        return true;
    }
    return false;
}

La realidad que me cacheteó:

public boolean a() {
    return b() ? c() : d();
}

private boolean b() {
    return a.a.a.a(this.e, this.f);
}

Mi reacción interna: “¿Qué chucha hace este código?”

La ofuscación había convertido mi herramienta favorita en un adorno caro. APKTool seguía jalando perfectamente, pero el código que me mostraba era tan útil como instrucciones de IKEA escritas en quechua.

Mi primera respuesta de novato: Googlear “cómo desofuscar código Android automáticamente”. Spoiler: No existe solución mágica.

Mi segunda respuesta: Llorar un toque, aceptar la realidad, y aprender assembly como adulto responsable.

Ghidra: mi relación tóxica favorita

Aquí es donde Ghidra - el disassembler que la NSA nos regaló al mundo - se convirtió en mi salvavidas.

El código nativo que APKTool nunca ve

El problema real: Las aplicaciones serias esconden su lógica crítica en librerías nativas (archivos .so). APKTool solo decompila la parte Java, pero el juego importante está en C/C++.

Mi descubrimiento que me cambió la perspectiva:

# Extraer librerías nativas del APK
unzip -j app.apk lib/arm64-v8a/libsecurity.so
# Abrir en Ghidra para análisis de bajo nivel
ghidra libsecurity.so

Lo que encontré me voló la peluca: Root detection, certificate pinning, y anti-debugging - todo implementado en código nativo. APKTool ni enterado que existían.

Desenmascarando “cifrado militar” casero

Caso que me marcó de por vida: Una app que se las daba de usar “algoritmos criptográficos de grado militar”.

En el código Java decompilado solo veía:

byte[] result = NativeLib.encrypt(data, key);

Pero en assembly revelaba la verdad del pollo pelado:

; "Cifrado militar" = XOR con rotación de bits
mov r0, #0x42
xor r1, r0, r2
ror r1, #3

Mi jeta cuando lo entendí: “¿En serio? ¿Su ‘algoritmo militar’ es un XOR misio con rotación?”

Sin Ghidra, habría creído el verso. Con Ghidra, pude demostrar que su “seguridad impenetrable” se rompía en 5 minutos.

objdump: el análisis express cuando no necesitas artillería pesada

No siempre necesitas la complejidad de Ghidra. A veces, objdump - una herramienta de línea de comandos para analizar binarios - te da exactamente lo que buscas en segundos.

Reconocimiento rápido de funciones

# Ver funciones exportadas que delatan intenciones
objdump -T libsecurity.so | grep -i root
# Output que me hizo sonreír:
0000a4c0 g    DF .text  000000b4  Base  check_root_access
0000a580 g    DF .text  0000008c  Base  hide_root_detection

Información dorada: Los nombres de las funciones me revelan exactamente qué hace la librería, sin necesidad de reversing completo.

Cazando strings hardcodeadas como amateur

# Buscar credenciales y secretos enterrados
objdump -s -j .rodata libsecurity.so | strings | grep -i key
# Lo que encontré (sin exagerar):
"SECRET_API_KEY_2024"
"DEBUG_MODE_ENABLED"  
""ROOT_CHECK_BYPASS"

Mi cara cuando lo vi: 😱

¿En serio hardcodearon la API key en la librería? Sí, paltazo. Y no es tan raro como uno creería.”


**¿En serio hardcodearon la API key en la librería?** Sí, en serio. Y no es tan raro como uno creería.

## Smali: el lenguaje que odias hasta que lo necesitas

Mientras APKTool me daba código Java ilegible, **Smali** - el lenguaje ensamblador de Android - se convirtió en mi traductor personal.

### Cuando el código ofuscado encuentra su match

**El dilema**: El código Java ofuscado es jeroglífico, pero Smali es más directo con la lógica subyacente.

**Ejemplo real que me salvó la vida:**

**Java decompilado (completamente inútil):**
```java
if (a.b.c.d(e.f.g.h())) {
    return i.j.k.l();
}

El mismo código en Smali (súbitamente legible):

invoke-static {}, Lcom/app/RootDetection;->isDeviceRooted()Z
move-result v0
if-eqz v0, :cond_0
const/4 v1, 0x1
return v1
:cond_0
const/4 v1, 0x0
return v1

Mi traducción mental: “Si isDeviceRooted() retorna true, devuelve 1, sino 0”.

¡Toma lacra! Bypass encontrado.

Cirugía de precisión sin malograr la app

La ventaja letal de Smali: Puedes modificar lógica específica sin tocar el resto del código. Es como operar con bisturí en lugar de machete.

Mi hack favorito de todos los tiempos:

# ANTES:
if-eqz v0, :cond_0  # Si NO está rooteado, continúa
# DESPUÉS:  
if-nez v0, :cond_0  # Si SÍ está rooteado, continúa

Resultado: Bypass completo de root detection cambiando literalmente una letra (eqznez).

¿Es elegante? Ni a patadas. ¿Funciona? Como reloj suizo.

Recursos que realmente funcionan (battle-tested)

Para empezar sin sufrir innecesariamente

Squally: El juego de Steam que salvó mi pellejo

Cheat Engine: La puerta de entrada perfecta al análisis de memoria

Flippy Bit: Bitwise operations sin morir de aburrimiento

Para trabajo profesional (con bases sólidas)

Para Assembly ARM avanzado:

Para dominar Smali:

Para Ghidra profesional:

La lección aprendida: Gamificación primero, herramientas serias después. Tu salud mental vale oro.

Mi filosofía post-aprendizaje: evolución sin revolución

La gamificación es el secreto mejor guardado del aprendizaje técnico

Squally me enseñó assembly básico mejor que 10 tutoriales de YouTube combinados. ¿Por qué funciona la gamificación donde fallan los métodos tradicionales?

Cheat Engine me demostró que análisis de memoria no es brujería negra, es técnica aplicada. Flippy Bit me hizo entender operaciones bitwise que uso diariamente en reversing.

Mi recomendación más controversial: Si vas a aprender assembly y análisis de memoria, empieza haciendo trampa en videojuegos. Tu cerebro agradecerá la dopamina, y las técnicas son 100% transferibles al pentesting móvil.

Las herramientas automáticas son punto de partida, no destino final

La realidad del workflow moderno:

PERO cuando te enfrentas a protecciones implementadas por gente que sabe lo que hace, necesitas bajar al metal. No hay de otra.

La regla del 80/20 en análisis de bajo nivel

80% del tiempo: Las herramientas automáticas cubren perfectamente tus necesidades
20% del tiempo: Necesitas assembly/Smali para no quedar como chibolo ante protecciones serias

Ese 20% crítico es lo que separa pentesters profesionales de script kiddies con herramientas fancy.

Context switching: tu habilidad más valiosa

La clave no es ser experto en todo, sino saber cuándo usar qué:

Ejemplo práctico: Uso MobSF para compliance inicial, jadx para código Java limpio, y Ghidra + Smali solo cuando encuentro protecciones que requieren cirugía de precisión.

La realidad incómoda: el pentesting móvil se está complicando

Las aplicaciones empresariales serias no se van a quedar para siempre en código Java legible que jadx puede manejar sin despeinarse.

La tendencia inevitable que viene

Lo que veo en proyectos recientes:

Si tu toolkit de pentesting solo incluye herramientas automáticas, vas a quedar obsoleto más rápido que un Nokia 3310 intentando correr TikTok.

Mi predicción personal (basada en casos reales)

En 2-3 años, saber al menos assembly básico será prerequisito obligatorio para pentesting móvil serio, no un nice-to-have que queda bonito en el CV.

¿Por qué? Porque las empresas que invierten en seguridad real ya no confían en “security by obscurity” básica. Están implementando protecciones que requieren análisis de bajo nivel para ser comprendidas (y bypasseadas).

Balance final: ¿valió la pena el sufrimiento gamificado?

Expectativa vs. Realidad

Lo que NO pasó: No me convertí en exploitation god ni descubrí 0-days que me hicieron famoso en el barrio.

Lo que SÍ gané (y vale más que el oro):

El beneficio más importante: Ahora distingo entre vulnerabilidades reales y false positives de scanners automáticos. Esa diferencia vale oro en pentesting profesional.

Mi hoja de ruta recomendada (aprendida a golpes)

Si decides tomar este camino masoquista pero que vale la pena:

  1. Fase 1 - Gamificación sin dolor: Squally + Cheat Engine + Flippy Bit para construir fundamentos sin trauma
  2. Fase 2 - Análisis de memoria real: Cheat Engine te prepara bacán para modificar apps Android en runtime
  3. Fase 3 - Casos progresivos: Apps simples primero, después aplicaciones enterprise con protecciones serias
  4. Fase 4 - Toolkit híbrido: Combina Ghidra + objdump + Smali según el contexto específico del análisis

La verdad pragmática

Si tu objetivo es hacer compliance checks rutinarios con MobSF y generar reportes automáticos, probablemente no necesites este nivel de profundidad técnica.

Pero si quieres analizar aplicaciones que se defienden en serio - banking apps, enterprise security, protecciones anti-tampering comerciales - no hay de otra. Y la buena noticia es que los juegos + Cheat Engine hacen el aprendizaje mucho menos doloroso que la ruta tradicional.

Reflexión honesta final

Todavía odio assembly complejo cuando aparece en código ofuscado de 500 líneas. Pero Squally y Cheat Engine me enseñaron que no todo el reversing es sufrimiento existencial puro.

Ghidra sigue siendo mi relación tóxica profesional favorita, pero ahora tengo fundamentos sólidos gracias a haber empezado “haciendo trampa” en videojuegos en lugar de sufrir con tutoriales académicos áridos de mierda.

¿Lo recomiendo? Solo si realmente quieres hacer pentesting móvil profesional y no quedarte en análisis superficial forever.


PD: La ironía es deliciosa - aprendí más sobre análisis de memoria y assembly modificando HP en videojuegos que en años de leer documentación “seria”. A veces el camino no convencional es el más efectivo, pues.