# PinBreaker: diseñando un laboratorio de reversing básico sobre un PIN hardcodeado

6 min read
Table of Contents

Máquina creada por: Oscar
Plataforma: The Hackers Labs
Sistema operativo: Android
Dificultad: principiante


Sobre este CTF

PinBreaker lo diseñé como un laboratorio corto y muy directo para introducir una idea concreta: cómo un mecanismo de validación aparentemente simple puede quedar completamente expuesto cuando la lógica sensible se deja embebida en el cliente.

No planteé esta máquina como una sucesión de trucos ni como un reto pensado para alargar artificialmente la resolución. La construí para enseñar una cadena muy concreta y fácil de reconocer: distribución de un artefacto Android, análisis estático del APK, localización de una validación insegura y obtención de la flag a partir del dato descubierto.

La parte importante no era “adivinar” un PIN, sino obligar a leer la aplicación como lo haría un atacante. Cuando una app incluye secretos hardcodeados y toma decisiones de seguridad en el lado cliente, el problema no es el PIN en sí, sino el modelo de confianza. Ese es el aprendizaje que quería fijar con este CTF.

También quise que el formato fuese distinto al de una máquina clásica. Aquí no hay una intrusión remota ni una escalada local tradicional. El foco está en el reversing básico y en entender que muchos fallos de seguridad no aparecen en un servicio expuesto a red, sino en cómo se empaqueta y distribuye la lógica de una aplicación.


Información técnica

CampoValor
NombrePinBreaker
IP objetivoNo aplica
ServiciosNo aplica; el objetivo es un APK Android
Cadena principalanálisis estático del APK → extracción de PIN hardcodeado → cálculo de SHA256
Dificultadprincipiante

Preparación del laboratorio

El artefacto entregado en este caso no era una máquina accesible por red, sino un paquete comprimido de pequeño tamaño que incluía el APK de la aplicación y un PDF con instrucciones básicas de uso.

Ese detalle forma parte del diseño. Quería romper la expectativa habitual de “levantar máquina, escanear y enumerar” para llevar al participante a otro terreno: el análisis de aplicaciones. La superficie de ataque aquí no era un servicio TCP, sino el propio binario distribuido al usuario.

Desde el punto de vista didáctico, esta primera fase enseña algo muy básico pero importante: no todos los fallos explotables requieren interacción dinámica. A veces basta con inspeccionar con calma el artefacto correcto.


Análisis estático del APK

Para revisar la aplicación, el camino natural era usar JADX en su versión gráfica y abrir directamente el paquete APK.

Terminal window
jadx-gui pinbreaker.apk

Una vez cargada la aplicación, la navegación por el código descompilado llevaba al paquete principal y, dentro de él, a la clase MainActivity, donde estaba implementada la lógica de validación.

En esta fase lo que quería enseñar era el valor del análisis estático básico en Android. No hacía falta instrumentación, hooking ni ejecución en emulador. Bastaba con revisar el flujo de la aplicación y localizar el punto donde se toma la decisión de aceptar o rechazar el PIN.

Ese planteamiento refleja un error muy común fuera de un CTF: colocar lógica sensible en el cliente y asumir que, por estar compilada dentro de una app, ya queda razonablemente protegida. En realidad, cuando el control de acceso depende de una comparación local con un valor embebido, el mecanismo deja de ser una barrera y pasa a ser una pista.


Localización de la validación del PIN

Dentro de MainActivity aparecía una función equivalente a checkPin(String), encargada de recibir el valor introducido y compararlo con un dato estático. La validación devolvía un booleano en función de si el PIN coincidía o no con el valor esperado.

Del análisis del código se extraía el PIN correcto:

8524947156

Aquí el aprendizaje que buscaba no era solamente “sacar un valor del código”, sino entender por qué ese diseño es débil. El problema representado es el de un secreto hardcodeado dentro de una aplicación distribuida al usuario final. En cuanto el atacante tiene acceso al APK, también tiene acceso potencial a la lógica que gobierna la autenticación local.

Este tipo de fallo aparece con frecuencia en escenarios reales: claves incrustadas, validaciones offline, comparaciones directas contra constantes o checks locales que intentan sustituir controles del lado servidor. PinBreaker resume ese patrón de forma deliberadamente simple para que la idea quede limpia.


Obtención de la flag

Una vez recuperado el PIN, la segunda parte del laboratorio consistía en transformarlo en la flag mediante SHA256.

El detalle importante aquí es evitar el salto de línea para no alterar el hash resultante. Por eso el comando correcto es:

Terminal window
echo -n "8524947156" | sha256sum

En una de las notas aparecía el uso de echo sin -n, pero para que el resultado sea consistente con el objetivo del laboratorio es necesario calcular el hash de la cadena exacta, sin añadir un retorno de carro al final.

La salida de ese comando proporciona el valor que se utiliza como flag.

Desde el punto de vista de diseño, esta última fase sirve para cerrar el laboratorio con una verificación objetiva y simple. No quise añadir pasos extra ni complicaciones artificiales. El reto estaba en localizar correctamente el dato sensible y entender la debilidad estructural; el hash sólo formaliza la entrega.


Lectura técnica de la cadena completa

La cadena de PinBreaker es muy corta, pero no es arbitraria:

  1. Se entrega una aplicación Android como artefacto.
  2. El participante inspecciona el código descompilado.
  3. Encuentra una validación local basada en un valor fijo.
  4. Extrae el PIN correcto.
  5. Deriva la flag a partir de ese valor.

Lo relevante es que cada fase existe para reforzar una misma idea: cuando la aplicación cliente contiene secretos o decisiones de seguridad que deberían estar protegidas de otra forma, el atacante no necesita romper nada sofisticado; le basta con leer.

Eso es exactamente lo que quería enseñar al diseñar esta máquina. No hay explotación espectacular porque no hacía falta. La debilidad ya estaba en la arquitectura de confianza.


Qué quería enseñar al diseñar PinBreaker

PinBreaker está pensado como una introducción a fallos de diseño en aplicaciones móviles donde la validación se resuelve completamente en cliente. La intención no era poner a prueba una cadena compleja de explotación, sino enseñar a reconocer una mala decisión de diseño que vuelve trivial el bypass.

FaseQué enseñaError representado
Entrega del APKEl artefacto distribuido también es superficie de ataqueConfiar en que el cliente ocultará la lógica
Análisis con JADXEl reversing básico basta para auditar flujos sensiblesAusencia de protección real sobre la lógica de validación
Revisión de MainActivityLa autenticación local puede desmontarse leyendo el códigoPIN o secreto hardcodeado
Extracción del PINEl dato sensible deja de ser secreto al estar embebidoExposición directa de credenciales o claves en cliente
Cálculo de SHA256El valor comprometido permite completar el flujo previstoDependencia total de un secreto ya recuperable

La enseñanza reutilizable fuera del CTF es clara: una aplicación no debe asumir que el código del lado cliente es un lugar seguro para guardar secretos o tomar decisiones de seguridad críticas. Ofuscación, empaquetado o compilación no resuelven ese problema de fondo.


Recursos y referencias

  • JADX, para decompilación y revisión estática de APKs.
  • sha256sum, para derivar la flag a partir del PIN recuperado.
  • Conceptos de reversing básico en Android y validación insegura del lado cliente.
My avatar

¿Te ha resultado útil o interesante este post? Soy Oscar, Senior Platform Engineer y SRE, y en este blog comparto mis reflexiones, experimentos y retos técnicos sobre automatización, seguridad (especialmente el diseño de CTFs), optimización de rendimiento y el impacto de la tecnología en el desarrollo profesional.

Conecta y conversemos: LinkedIn Mi código y proyectos en: GitHub


More Posts