El crackme es el típico de usuario y número de serie. Si no introduces un nombre te salta un messagebox indicándotelo y si introduces cualquier información sale un mensaje de error.
Si dejamos solamente el serial en blanco nos sale un mensaje de error muy interesante diciéndonos que introduzcamos un número entre 1 y 2^32. Por lo tanto ya sabemos que nuestro serial está entre 1 y 4294967296.
PEiD no arroja resultados pero una primera impresión con Ollydbg hace creer que está programado en ensamblador y que no está comprimido.
Al ataque con Ollydbg
Cargamos el crackme en Ollydbg y hacemos click derecho Search for > Names
Vemos dos referencias interesantes como son:
&USER32.GetDlgItemInt
&USER32.GetDlgItemTextA
Ponemos sendos breakpoints y damos al play.
Vemos que para en USER32.GetDlgItemTextAy que retorna al offset 4010E7
Vamos a 4010E7 y vemos que pasa.
Hace un Test eax,eax por si hemos introducido algún nombre y si no es así nos muestra la nag.
Continuamos con la ejecución y para en el siguiente breakpoint, esta vez el referente a USER32.GetDlgItemInt, vamos al offset 401108 a ver que nos espera.
Se puede ver claramente que carga en EAX nuestro número de serie en hexa, lo compara con ESI que vale 0 y si son iguales nag de error y si no continua a 401120 donde guarda en la pila nuestro nombre y serial y llama al offset 401000.
Veamos que hay en el offset 401000.
Aquí vemos una primera parte con un bucle en el que interviene nuestro nombre y donde obtendremos el “HashName” y posteriormente una operaciones aritméticas en las que finalmente modifica el valor de EAX. Tengamos en cuenta que la comprobación final es un Test eax,eax o lo que es lo mismo, comprueba si EAX = 0 y si es 0 salta al mensaje de error como vemos en la imagen siguiente.
En resumen:
Obtenemos el HashName.
Realizamos unas operaciones a ese HashName (LOCAL.1) y al serial introducido (ARG.2).
Si EAX <> 0 entonces serial correcto.
Sacando el “HashName”
Veamos un ejemplo de obtención del hashname para el usuario “abc”. El bucle se repetirá tantas veces como letras tenga el nombre.
Entendiendo la comprobación del serial
En resumen:
Necesitamos que EAX <> 0.
Necesitamos que (HashName XOR Serial) = 0 ya que:
a.La negación de 0 es 0 –>NEG(0) = 0
b.La resta con acarreo de 0 – 0 = 0 –>SBB 0,0 = 0
Hay que tener en cuenta que la resta con acarreo (SBB) de cualquier número, dará como resultado en EAX = FFFFFFFF, que al incrementar en 1 quedará en 0.
Por lo tanto si cumplimos las condiciones anteriormente expuestas, al incrementar EAX con INC EAX, este quedará en 1 haciendo nuestro serial válido.
Generando el serial válido
Las operaciones que se realizan sobre nuestro serial son NOT, SUB y XOR. Por suerte para nosotros son reversibles quedando nuestro serial así:
Serial válido = [NOT(HashName) + 0xBADC0DE5] XOR 0x1337C0DE
Como no es propósito de este manual enseñar a hacer un keygen desde 0, muestro el código importante y adjunto los links del código fuente. Si quieres ver como se hace un keygen básico en ASM desde cero mira el tutorial del Keygen para el KeygenMe#01 de eBuC.
Enlaces
Crackme + Keygen en ASM + WinASM studio 5.1.5 [31MB]
Este es un crackme de la web de Karpoff programado por Sotanez y realizado en Delphi. Como máximo nos deja meter nombres de 10 dígitos.
El algoritmo
Es un algoritmo muy sencillo pero veremos que nos tendremos que fijar en el DUMP de Olly para saber que demonios hace. Como de costumbre abrimos Olly y en las «Referenced Strings» localizamos la palabra «Registrado«, pinchamos en ella y localizamos la porción de código que nos interesa. Vamos a analizarla.
Vemos 3 bucles, el primero pone la memoria (Dump) a cero, el segundo guarda nuestro nombre (errata en la imagen) en el Dump y el tercero realiza la suma de los valores ascii del nombre. Hasta aquí todo bien, pero vamos a hacer una prueba para el nombre deurus.
Nombre: deurus
Serial: 64+65+75+72+75+73 = 298 (664 en decimal)
Probamos el serial en el programa y nos da error, vale, vamos a analizar más a fondo los bucles.
El primer bucle hemos dicho que pone la memoria a 0, en concreto desde «45BC60» y de 4 en 4 (fíjate en el Add 4), es decir, pone a 0 los offsets 45BC60, 45BC64, 45BC68, 45BC6C, 45BC70, 45BC74, 45BC78, 45BC7C, 45BC80, 45BC84, ya que el bucle se repite 10 veces. En la imágen queda claro.
El segundo bucle se repite 11 veces y lo que hace es guardar en el dump el valor ascii de las letras de nuestro nombre. En la imagen lo vemos.
A primera vista ya vemos un valor extraño en la posición 45BC80, y es que cuando debiera haber un 0, hay un 12. Vamos a ver como afecta esto al serial final.
El tercer bucle se repite 10 veces y lo que hace es sumar los valores que haya en el DUMP en las posiciones anteriormente citadas.
En concreto suma 64+65+75+72+75+73+0+0+12+0 = 2AA (682 en decimal). Probamos 682 como serial y funciona. Realizando más pruebas vemos que para nombres con un tamaño inferior a 5 letras se ocupan las posiciones 45BC70 y 45BC80 con valores extraños, el resto de posiciones se mantienen a 0. En las imágenes inferiores se pueden apreciar más claramente los valores extraños.
Nombre de tamaño < 5.
Nombre de tamaño >5 y <9
Nombre de tamaño = 10
En resumen:
Nombre de tamaño < 5 –> Ascii SUM + 14h Nombre de tamaño >5 y <9 –> Ascii SUM + 12h Nombre de tamaño =10 –> Ascii SUM
Con esto ya tenemos todo lo que necesitamos para nuestro keygen.
char Nombre[11];
GetWindowText(hwndEdit1, Nombre, 11);
char Serial[20];
int len = strlen(Nombre);
int suma = 0;
for(int i = 0; i <= len; i = i + 1)
{
suma += Nombre[i];
}
if(len < 5){
suma +=0x14;
}
if(len > 5 && len < 9){
suma +=0x12;
}
wsprintf(Serial,"%d",suma);
SetWindowText(hwndEdit2, TEXT(Serial));
La película «Contact«, estrenada en 1997 y dirigida por Robert Zemeckis, es una adaptación de la novela homónima de Carl Sagan. Más allá de su profunda exploración sobre la existencia de vida extraterrestre y el debate entre ciencia y fe, la película ofrece un interesante vistazo a la tecnología de la época. En este análisis, nos enfocaremos en los aspectos tecnológicos presentes en la película, detallando los sistemas operativos, software y hardware utilizados por los protagonistas.
Sinopsis
La Dra. Eleanor «Ellie» Arroway, interpretada por Jodie Foster, es una científica dedicada al proyecto SETI (Búsqueda de Inteligencia Extraterrestre). Tras años de búsqueda, capta una señal proveniente del espacio profundo que contiene instrucciones para construir una máquina enigmática. A medida que se desarrolla la trama, Ellie enfrenta desafíos políticos, religiosos y personales mientras lucha por interpretar el mensaje y lo que podría significar para la humanidad.
Análisis Tecnológico
Sistemas Operativos y Software
Uno de los aspectos más destacados en Contact es la presencia del sistema operativo UNIX. A lo largo de la película, se observan pistas que indican su uso, como pegatinas en las pantallas con mensajes del estilo: «Join the UNIX PARTY (The open system platform)». UNIX, desarrollado en la década de 1970, es conocido por su estabilidad y eficiencia, características esenciales en entornos científicos y de investigación.
La utilización de Netscape Navigator es recurrente. El logo de Netscape aparece en varias ocasiones, especialmente durante las videoconferencias que se muestran sin retrasos apreciables. Netscape fue uno de los primeros navegadores web ampliamente utilizados y jugó un papel crucial en la expansión de Internet durante los años 90.
Es importante destacar que, aunque la película promueve la idea de sistemas abiertos a través del uso de UNIX, Netscape Navigator no era software libre en el momento en que se rodó la película. Durante esa época, antes de 1997, Netscape era un navegador propietario. Sin embargo, en sistemas UNIX, Netscape tenía poca competencia y era el navegador predominante, soportando estándares abiertos como HTTP y HTML. Curiosamente, en 1998, poco después del estreno de la película, Netscape liberó el código fuente de su navegador, iniciando el proyecto Mozilla y contribuyendo significativamente al movimiento del software libre.
El software o plataforma denominada MADDEN HADDEN es utilizado por los protagonistas en diversas localizaciones, sugiriendo que es un estándar en su campo. Aunque en la realidad no existe un software conocido con ese nombre en el ámbito científico, en la película parece ser una herramienta integral para el análisis de datos y comunicación.
Videoconferencias y Comunicaciones
Las videoconferencias sin «lags» (retrasos) que se muestran en la película son notables, especialmente considerando las limitaciones tecnológicas de la época. La presencia del logo de Netscape durante estas comunicaciones resalta el optimismo sobre las capacidades de Internet en 1997. En ese entonces, las conexiones de alta velocidad no eran comunes, y las videollamadas de calidad eran más una aspiración que una realidad.
Estándares y Sistemas Abiertos
La promoción de sistemas abiertos es evidente en la película. El uso de UNIX, basado en estándares abiertos, refleja una filosofía de colaboración y accesibilidad en el ámbito científico. Aunque Netscape Navigator no era software libre durante la producción de la película, su soporte para estándares abiertos de Internet lo convirtió en una herramienta esencial para la comunicación y el intercambio de información entre científicos y profesionales.
Hardware
En términos de hardware, la película presenta una variedad de equipos representativos de la tecnología de los años 90:
Monitor NEC MultiSync XE21: Un monitor CRT de 21 pulgadas conocido por su alta resolución y calidad de imagen, ideal para aplicaciones que requieren detalles precisos.
Monitores con marcas ocultas: Es interesante notar que en varios monitores se utilizan post-its o adhesivos para cubrir la marca y el modelo. Esto podría deberse a decisiones de producción para evitar publicidad no deseada o cuestiones legales relacionadas con derechos de marca.
Monitor CTX: Aunque no se especifica el modelo, los monitores CTX eran populares por su fiabilidad y rendimiento a un costo razonable.
Monitor Hansol Mazellan 17px: Los monitores Hansol eran reconocidos por su calidad en la reproducción de gráficos, siendo utilizados en diseño y aplicaciones multimedia.
Monitor IBM: IBM fue pionera en tecnología informática, y sus monitores eran sinónimo de calidad y durabilidad. Aunque no se especifica el modelo exacto, es probable que se trate de uno de sus populares monitores CRT utilizados en entornos profesionales.
Evolución de UNIX y Windows
Para entender el contexto tecnológico de la época, es útil comparar la evolución de UNIX y Windows, así como de los navegadores Netscape Navigator e Internet Explorer.
Detalles Adicionales
Cobertura de marcas: La práctica de cubrir las marcas y modelos en los monitores podría indicar un intento de la producción por crear un entorno más universal y atemporal, evitando asociar la tecnología presentada con productos específicos que podrían quedar obsoletos rápidamente. En bastantes fotogramas se nota que esto es completamente intencionado.
Representación de la tecnología: La película equilibra la precisión técnica con las necesidades narrativas. Si bien algunas representaciones, como las videoconferencias fluidas, eran tecnológicamente avanzadas para la época, sirven para enfatizar la conectividad y colaboración global entre los científicos.
SETI y la Búsqueda de Vida Extraterrestre: En Contact, la Dra. Ellie Arroway dedica su vida al proyecto SETI (Search for Extraterrestrial Intelligence), reflejando el esfuerzo real de la comunidad científica por encontrar señales de inteligencia extraterrestre. SETI es una iniciativa internacional que utiliza radiotelescopios para detectar posibles comunicaciones de civilizaciones fuera de la Tierra. La película captura la pasión y los desafíos asociados con este tipo de investigación, destacando la dedicación de los científicos que trabajan en el límite de lo conocido.
El Mensaje de Arecibo: El radiotelescopio de Arecibo en Puerto Rico juega un papel significativo tanto en la realidad como en la película. En 1974, desde este observatorio, se envió el famoso Mensaje de Arecibo, una transmisión de radio dirigida al cúmulo estelar M13, diseñada para demostrar los avances tecnológicos humanos y nuestra existencia a posibles civilizaciones extraterrestres. El mensaje contenía información codificada sobre la composición humana, nuestro sistema numérico, la estructura del ADN y nuestra posición en el sistema solar. En «Contact», aunque la señal recibida por Ellie proviene de Vega y no está directamente relacionada con el Mensaje de Arecibo, la película establece paralelismos con este acontecimiento histórico. La utilización de Arecibo como escenario subraya la conexión entre los esfuerzos reales y ficticios en la búsqueda de inteligencia extraterrestre. La película explora la posibilidad de que, así como enviamos mensajes al espacio, podríamos recibir respuestas o comunicaciones de otras civilizaciones.
Matthew McConaughey: Es interesante notar cómo este actor ha participado en dos de las películas más destacadas de la ciencia ficción: Contact e Interstellar. En Contact, McConaughey interpreta un papel secundario como Palmer Joss, un escritor y asesor espiritual que cuestiona las implicaciones éticas y filosóficas del descubrimiento científico. Diecisiete años después, en Interstellar, asume el rol protagonista de Cooper, un ex piloto de la NASA que emprende una misión interestelar para salvar a la humanidad.
Números primos: El inicio de la investigación seria de la señal extraterrestre en la película se desencadena cuando, al analizar la señal recibida, los científicos descubren que esta codifica una secuencia de números primos. Este hallazgo resulta crucial, ya que los números primos, al ser divisibles únicamente por 1 y por sí mismos, no surgen de forma aleatoria en procesos naturales conocidos. Su presencia en la señal sugiere intencionalidad e inteligencia detrás de su emisión, lo que confirma que no se trata de ruido cósmico sino de una posible comunicación deliberada desde una civilización avanzada. Este descubrimiento impulsa a los científicos a profundizar en la decodificación, marcando el verdadero inicio de la búsqueda de vida extraterrestre.
Conclusión
Contact no solo es una obra que invita a reflexionar sobre nuestro lugar en el universo y la posibilidad de vida más allá de la Tierra, sino que también es un retrato de la tecnología de su tiempo. La inclusión de sistemas operativos como UNIX, navegadores como Netscape y hardware específico refleja una atención al detalle que enriquece la narrativa. A pesar de que Netscape Navigatorno era software libre durante la producción de la película, su presencia destaca la importancia de los estándares abiertos y la colaboración en el avance científico.
También destaca por su compromiso con la precisión científica, en gran parte debido a la influencia de Carl Sagan, autor de la novela original y asesor en la producción. La representación de los procedimientos del SETI, el análisis de señales y las discusiones éticas y filosóficas reflejan debates reales en la comunidad científica. La inclusión de elementos como el Mensaje de Arecibo y las operaciones del radiotelescopio añaden autenticidad a la narrativa y acercan al público a la realidad de la exploración espacial.
Este BTM va otra vez sobre IPs. Si amigos del séptimo arte, viendo un capítulo de mi querida «The Sinner» me han vuelto a chirriar los dientes. La verdad que viendo el capítulo no te da tiempo a apreciarlo, únicamente me quedo con que aparece una URL y lo reviso a posteriori (esto lo digo para los curiosos que me preguntáis).
En esta ocasión me tiene un poco inquieto ya que es una serie que cuida enormemente los detalles y el fallo que os voy a mostrar parece intencionado. La imagen en cuestión es esta:
Fotograma del capítulo 2×06
Aparece un buscador con una URL más o menos creíble si no fuera porque la IP que aparece es IMPOSIBLE. La máxima IPv4 es 255.255.255.255, es decir, no han dado ni una, y eso es lo que me tiene mosca. Si hubieran utilizado 82.47.25.29 hubiera quedado bien y estaríamos hablando de un problema de geolocalización de IPs, ya que el rango 82.47.xx.xx le pertenece a UK y deberíamos discernir si el servidor está en EEUU o no…
En definitiva, puede ser un fallo a propósito, un guiño o tener un significado. No se que deciros, bueno si, ¡lo investigaré!
Aviso: Este crackme forma parte de una serie de pruebas de Yoire.com que todavía está en activo. Lo ético si continuas leyendo este manual es que no utilices la respuesta para completar la prueba sin esfuerzo. 😉
Saltando el Anti-Debug
Abrimos el crackme con Ollydbg y nos salta una protección Anti-Debug.
Si nos fijamos en las «Text Strings» vemos que es la clásica isDebuggerPresent. Pinchamos en ella y vemos claramente el salto que debemos forzar, se encuentra en el offset 401015. Podemos invertir el salto o cambiarlo a JMP para que salte siempre.
Rutina de comprobación del serial
A simple vista vemos instrucciones como FILD y FIDIVR que trabajan con los registros FPU, por lo que tendremos que fijarnos en dichos registros.
Retomemos analizando la rutina de comprobación.
FLD DWORD PTR DS:[403080] - Carga el entero "720300" en ST7
FSTP [LOCAL.1] - Guarda "720300" en memoria (Local 1)
MOVSX EDX,BYTE PTR DS:[EAX] - Coje nuestro primer dígito en ascii y lo carga en EDX
SUB EDX,30 - Le resta 30 a EDX
PUSH EDX - Carga EDX en la pila
FILD DWORD PTR SS:[ESP] - Carga el valor de EDX en ST0
POP EDX - Recupera el valor de la pila
FDIVR [LOCAL.1] - Divide Local 1 entre nuestro dígito hex y lo guarda en ST0
FSTP [LOCAL.1] - Guarda el resultado de ST0 en Local 1
INC EAX - Siguiente dígito
CMP BYTE PTR DS:[EAX],0 - Comprueba si quedan dígitos en nuestro serial
JNZ SHORT 05_crack.004010F4 - Bucle
Después de la rutina de comprobación simplemente comprueba el valor del resultado de la división con 1 y si es verdad serial válido.
Buscando un serial válido
Podríamos hacer fuerza bruta, pero en esta ocasión no es necesario ya que con la calculadora, boli y papel lo sacamos rápido.
Hoy vamos a ver como extraer el script de un ejecutable compilado por Autoit, modificarlo y recompilarlo como nuestro keygen. Como comprobareis si no se ofusca o se toman otro tipo de medidas recuperar información sensible es muy sencillo.
AutoIt es un lenguajefreeware multiproposito y de automatización para Microsoft Windows. Es un Visual Basic Killer, ya que mejora las características de los ejecutables (entre otras portabilidad, velocidad y peso, no fat-coding), y facilitan la programación con un buen repertorio de funciones «pre-diseñadas», y usando un Basic de fácil aprendizaje. Se ha expandido desde sus comienzos de automatización incluyendo muchas mejoras en el diseño del lenguaje de programación y sobre todo en nuevas funcionalidades.
El Script
Func CHECKKEY($USER, $PASS)
Local $OPKEY = "", $SIG = ""
Local $USER_LEN = StringLen($USER)
Local $PASS_LEN = StringLen($PASS)
If $USER_LEN < $PASS_LEN Then
MsgBox(0, "ERROR", "Invalid username or key.")
Exit
ElseIf $USER_LEN < 4 Then
MsgBox(0, "ERROR", "Invalid username or key.")
Exit
EndIf
$PASS_INT = Int($USER_LEN / $PASS_LEN)
$PASS_MOD = Mod($USER_LEN, $PASS_LEN)
$OPKEY = _STRINGREPEAT($PASS, $PASS_INT) & StringLeft($PASS, $PASS_MOD)
For $INDEX = 1 To $USER_LEN
$SIG &= Chr(BitXOR(Asc(StringMid($USER, $INDEX, 1)), Asc(StringMid($OPKEY, $USER_LEN - $INDEX + 1, 1))))
Next
If $SIG = _STRINGREPEAT(Chr(32), $USER_LEN) Then
MsgBox(0, "INFO", "Your key was registered.")
Exit
Else
MsgBox(0, "INFO", "Your key is invalid.")
EndIf
EndFunc
El Algoritmo
El algoritmo es tremendamente sencillo ya que es nuestro nombre al revés y en mayúsculas.
Modificando el script para generar nuestro propio keygen
El decompilador se llama myAut2exe y tiene este aspecto.
Programar en AutoIt es muy sencillo e intuitivo. Nuestro keygen quedaría así.
$MAIN = GUICreate("Another keygen by deurus", 300, 80, -1, -1, 382205952, 385)
$NAME_LBL = GUICtrlCreateLabel("Username", 5, 5, 60, 20, BitOR(4096, 1))
$NAME_INP = GUICtrlCreateInput("", 70, 5, 225, 20, 1)
$PASS_LBL = GUICtrlCreateLabel("Key", 5, 30, 60, 20, BitOR(4096, 1))
$PASS_INP = GUICtrlCreateInput("", 70, 30, 225, 20, 1)
$REGISTER = GUICtrlCreateButton("Register", 5, 55, 60, 20)
$GIVE_UP = GUICtrlCreateButton("Generate", 70, 55, 60, 20) <- Change name of button, Give Up by Generate
$TASK = GUICtrlCreateButton("?", 140, 55, 20, 20)
$AUTHOR = GUICtrlCreateLabel("keygen by deurus", 165, 55, 130, 20, BitOR(4096, 1))
GUISetState(@SW_SHOW, $MAIN)
While True
$MSG = GUIGetMsg()
Switch $MSG
Case $REGISTER
Call("CHECKKEY", GUICtrlRead($NAME_INP), GUICtrlRead($PASS_INP))
Case $GIVE_UP
Call("GETKEY", GUICtrlRead($NAME_INP), GUICtrlRead($PASS_INP)) <- Add the function to the button
Case $TASK
MsgBox(0, "Info", "keygen by deurus")
Case - 3
Exit
EndSwitch
Sleep(15)
WEnd
Func GETKEY($USER, $PASS) <- this is our keygen function
Local $OPKEY = "", $SIG = ""
Local $USER_LEN = StringLen($USER)
Local $PASS_LEN = StringLen($USER)
If $USER_LEN < 4 Then
GUICtrlSetData($PASS_INP ,"min 4 chars");
Else
For $INDEX = 1 To $USER_LEN
$SIG = Chr(BitXOR(Asc(StringMid($USER, $INDEX, 1)), 32)) & $SIG
Next
GUICtrlSetData($PASS_INP ,$SIG);
EndIf
EndFunc
Func CHECKKEY($USER, $PASS) <- check function, the original
Local $OPKEY = "", $SIG = ""
Local $USER_LEN = StringLen($USER)
Local $PASS_LEN = StringLen($PASS)
If $USER_LEN < $PASS_LEN Then
MsgBox(0, "ERROR", "Invalid username or key.")
ElseIf $USER_LEN < 4 Then
MsgBox(0, "ERROR", "Invalid username or key.")
Exit
EndIf
$PASS_INT = Int($USER_LEN / $PASS_LEN)
$PASS_MOD = Mod($USER_LEN, $PASS_LEN)
$OPKEY = _STRINGREPEAT($PASS, $PASS_INT) & StringLeft($PASS, $PASS_MOD)
For $INDEX = 1 To $USER_LEN
$SIG &= Chr(BitXOR(Asc(StringMid($USER, $INDEX, 1)), Asc(StringMid($OPKEY, $USER_LEN - $INDEX + 1, 1))))
Next
If $SIG = _STRINGREPEAT(Chr(32), $USER_LEN) Then
MsgBox(0, "INFO", "Your key was registered.")
Else
MsgBox(0, "INFO", "Your key is invalid.")
EndIf
EndFunc
Aviso: Este crackme forma parte de una serie de pruebas de Yoire.com que todavía está en activo. Lo ético si continuas leyendo este manual es que no utilices la respuesta para completar la prueba sin esfuerzo. 😉
Analizando
Abrimos el crackme con Ollydbg y vamos a las referenced strings.
Pinchamos sobre cualquiera.
Vemos un «Call» donde seguramente se generará un SUM en función del serial metido ya que después del Call vemos una comprobación contra «B79E763E» lo que nos da una pista de que vamos a tener que utilizar fuerza bruta para llegar a ese valor. Vamos a explorar el Call.
Lo que resalto con la flecha son una par de Calls que podemos NOPear ya que lo único que hacen es ralentizar la generación del SUM.
A continuación vamos a analizar el algoritmo de generación del SUM.
AperiSolve es un conjunto de herramientas de análisis esteganográfico que nos ayuda a echar un primer vistazo cuando sospechamos que una imagen esconde algo.
Zsteg es una herramienta especializada en la detección y extracción de información oculta en imágenes, especialmente en formatos PNG y BMP. Está orientada a la esteganografía basada en bit-planes y es muy popular en entornos CTF y análisis forense, gracias a su capacidad para automatizar búsquedas exhaustivas de datos escondidos en los bits menos significativos (LSB) y en configuraciones de color poco habituales. Su principal fortaleza es que no se limita a examinar un único plano: prueba sistemáticamente combinaciones de canales (R, G, B, A), número de bits, orden de lectura y posicionamiento, detectando patrones que podrían pasar inadvertidos en una revisión manual.
Entre sus características más destacadas se encuentran la identificación automática de firmas de archivos (ZIP, PNG, texto ASCII, GZIP, etc.), la extracción directa de bitstreams reconstruidos y el soporte para diferentes rutas de exploración, como b1,rgb,lsb,xy, que describen exactamente cómo se han recuperado los datos. Esta capacidad de correlacionar parámetros técnicos con resultados concretos convierte a zsteg en una herramienta muy eficiente tanto para localizar contenido oculto como para entender la técnica esteganográfica aplicada.
En AperiSolve se utiliza únicamente la parte de Zsteg encargada de ejecutar el análisis automático y devolver todas las detecciones posibles de esteganografía LSB en imágenes PNG y BMP. Concretamente, AperiSolve llama al comando zsteg <imagen> tal como está implementado en el módulo analyze_zsteg , y captura la salida completa línea por línea. Esta salida incluye todas las combinaciones probadas de bit-planes (b1, b2…), canales (r, g, b, a), orden de bits (lsb/msb) y métodos de recorrido (xy), junto con cualquier coincidencia que zsteg reconozca como firma de archivo o texto. Es decir, AperiSolve no aplica filtros ni interpretación adicional: muestra exactamente lo que zsteg detecta y lo organiza para que el usuario pueda identificar rápidamente si existe un archivo embebido, contenido ASCII, o algún patrón de interés.
Para entender mejor a que se refiere todo esto vamos a repasar lo básico.
¿Qué es LSB y qué es MSB?
Cuando hablamos de esteganografía en imágenes PNG/BMP, nos referimos a manipular bits dentro de los canales de color (R, G, B, A). Cada canal tiene un valor de 0–255, es decir, 8 bits:
R = 11001010
G = 00110101
B = 11100001
LSB — Least Significant Bit (bit menos significativo). Es el bit más débil, el de la derecha:
1100101[0] ← LSB
Modificarlo cambia muy poco el color, por eso se usa en esteganografía. Ejemplo: cambiar 11001010 ↦ 11001011 no cambia el color perceptible.
MSB — Most Significant Bit (bit más significativo). Es el bit más importante, el de la izquierda:
[1]1001010 ← MSB
Modificarlo sí altera mucho el color. A veces se usa pero suele ser detectable.
Cuando Zsteg muestra una línea del estilo b1,rgb,lsb,xy .. file: Zip archive data, está indicando que ha analizado la imagen extrayendo bits según la ruta especificada —en este caso, 1 bit por píxel (b1), combinando los canales rojo, verde y azul (rgb), utilizando el bit menos significativo (lsb) y recorriendo los píxeles en orden normal de lectura (xy)— y que, tras recomponer esos bits, el resultado coincide con la cabecera reconocible de un tipo de archivo real. Por eso aparece “file: Zip archive data”: significa que los bits ocultos forman un flujo válido cuya firma corresponde a un archivo ZIP. En otras ocasiones puede detectar texto ASCII, PNG, JPEG u otros formatos. En resumen, cuando Zsteg muestra esta línea no solo indica dónde se ocultan los datos, sino que confirma que lo recuperado es un archivo auténtico y probablemente extraíble, ya que la estructura binaria coincide con un formato conocido.
Si vemos que Zsteg nos ofrece algo interesante, podemos extraerlo mediante el comando:
zsteg -E b1,rgb,lsb,xy imagen.png > dump.bin
También es habitual usar herramientas como StegSolve. En este caso debemos dirigirnos a Analyse > Data extract para comprobar lo encontrado por zsteg y extraerlo mediante Save Bin.
Zsteg
> Significado <
StegSolve
b1
Extrae 1 bit por canal (bit plano 0, el menos significativo).
En Bit Planes, marca Red 0, Green 0, Blue 0. Solo esos.
rgb
Usa R + G + B en ese orden para reconstruir los bytes.
En Bit Plane Order, selecciona RGB.
lsb
Lee los bits empezando por el LSB (bit 0) antes que el MSB.
En Bit Order, selecciona LSB First.
xy
Recorre la imagen por filas (izquierda → derecha, arriba → abajo).
En Extract By, elige Row.
Más allá de este caso concreto, conviene recordar que la esteganografía no se limita a los LSB: existen métodos basados en paletas, metadatos, manipulación de PNG chunks, secuencias alfa, audio incrustado o capas completas en formatos no comprimidos. Por ello, un análisis completo debería combinar la búsqueda clásica de LSB con herramientas complementarias como binwalk, foremost, exiftool, strings, o incluso análisis manual de cabeceras hexadecimales.
Este es un crackme de la web de Karpoff programado por Sotanez y realizado en Delphi. Como máximo nos deja meter nombres de 10 dígitos.
El algoritmo
Es un algoritmo muy sencillo pero veremos que nos tendremos que fijar en el DUMP de Olly para saber que demonios hace. Como de costumbre abrimos Olly y en las «Referenced Strings» localizamos la palabra «Registrado«, pinchamos en ella y localizamos la porción de código que nos interesa. Vamos a analizarla.
Vemos 3 bucles, el primero pone la memoria (Dump) a cero, el segundo guarda nuestro nombre (errata en la imagen) en el Dump y el tercero realiza la suma de los valores ascii del nombre. Hasta aquí todo bien, pero vamos a hacer una prueba para el nombre deurus.
Nombre: deurus
Serial: 64+65+75+72+75+73 = 298 (664 en decimal)
Probamos el serial en el programa y nos da error, vale, vamos a analizar más a fondo los bucles.
El primer bucle hemos dicho que pone la memoria a 0, en concreto desde «45BC60» y de 4 en 4 (fíjate en el Add 4), es decir, pone a 0 los offsets 45BC60, 45BC64, 45BC68, 45BC6C, 45BC70, 45BC74, 45BC78, 45BC7C, 45BC80, 45BC84, ya que el bucle se repite 10 veces. En la imágen queda claro.
El segundo bucle se repite 11 veces y lo que hace es guardar en el dump el valor ascii de las letras de nuestro nombre. En la imagen lo vemos.
A primera vista ya vemos un valor extraño en la posición 45BC80, y es que cuando debiera haber un 0, hay un 12. Vamos a ver como afecta esto al serial final.
El tercer bucle se repite 10 veces y lo que hace es sumar los valores que haya en el DUMP en las posiciones anteriormente citadas.
En concreto suma 64+65+75+72+75+73+0+0+12+0 = 2AA (682 en decimal). Probamos 682 como serial y funciona. Realizando más pruebas vemos que para nombres con un tamaño inferior a 5 letras se ocupan las posiciones 45BC70 y 45BC80 con valores extraños, el resto de posiciones se mantienen a 0. En las imágenes inferiores se pueden apreciar más claramente los valores extraños.
Nombre de tamaño < 5.
Nombre de tamaño >5 y <9
Nombre de tamaño = 10
En resumen:
Nombre de tamaño < 5 –> Ascii SUM + 14h Nombre de tamaño >5 y <9 –> Ascii SUM + 12h Nombre de tamaño =10 –> Ascii SUM
Con esto ya tenemos todo lo que necesitamos para nuestro keygen.
char Nombre[11];
GetWindowText(hwndEdit1, Nombre, 11);
char Serial[20];
int len = strlen(Nombre);
int suma = 0;
for(int i = 0; i <= len; i = i + 1)
{
suma += Nombre[i];
}
if(len < 5){
suma +=0x14;
}
if(len > 5 && len < 9){
suma +=0x12;
}
wsprintf(Serial,"%d",suma);
SetWindowText(hwndEdit2, TEXT(Serial));
Alerta de Spoiler: El reto está en activo a fecha de publicación.
Spoiler alert: The challenge is still alive.
Este tipo de retos son de lo más variopinto pero una de las primeras cosas que se suele hacer es ver el código fuente y fijarse en los enlaces para hacernos una idea del tipo de vulnerabilidades a explotar. Empezamos por explorar el código fuente.
A simple vista no hay nada sospechoso pero me llama la atención el enlace de la imagen del gatito «source/cat.gif«. Si fisgamos dentro de la carpeta «source» podemos ver que nos muestra el contenido de la carpeta como se puede apreciar en la imagen a continuación.
Contenido de la carpeta source
La carpeta «app» suena interesante. Hacemos clic y vemos lo siguiente.
Notice: Undefined index: commit in C:/xampp/htdocs/challenge-land/Realistic/shop/source/app/index.php on line 2
Vemos que el error mostrado muestra más información de la debida y la aprovecharemos en beneficio propio. Aquí la clave está en el fichero index.php y en el parámetro commit. Haremos una prueba para ver que vamos por el buen camino.
Hay varias respuestas sugerentes pero quizá la más relevante es la 8. Ahora bien, solo falta encontrar donde introducir el usuario y la clave.
Si volvemos a la página principal vemos en el enlace algo interesante, me refiero a index.php?page=index. Tras probar varias cosas la que funciona es la típica, admin.
Al entrar vemos que nos redirige al index de nuevo tras pocos segundos. Aquí hay dos opciones, desactivar javascript para evitar la redirección o entrar directamente a la página admin.php. Optamos por el camino fácil entrando directamente en admin.php:
Hoy tenemos aquí un crackme de los que te hacen temblar las conexiones neuronales. Estamos acostumbrados al típico serial asociado a un nombre y a veces nos sorprenden.
El crackme data del año 2000, está realizado por aLoNg3x y lo tenéis colgado en crackmes.de. En crackmes.de también disponéis de una solución muy elegante realizada por cronos, pero que no acaba de saciar nuestro afán de descubrir todas las soluciones posibles.
El algoritmo
Abrimos el crackme con Olly y enseguida encontramos la rutina de comprobación junto con los mensajes de éxito y error. Os dejo la rutina comentada como siempre.
004012D7 |. 83C4 08 ADD ESP,8 ;
004012DA |. 09C0 OR EAX,EAX ;
004012DC |. /74 16 JE SHORT Zebrone.004012F4 ; Salta a Bad boy
004012DE |. |6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
004012E0 |. |68 26324000 PUSH Zebrone.00403226 ; |Title = "Great !!!"
004012E5 |. |68 30324000 PUSH Zebrone.00403230 ; |Text = "Congratulations, you have cracked the Zebra Crackme ver 1.1"
004012EA |. |FF75 08 PUSH [ARG.1] ; |hOwner = 0011067C ('Zebra - aLoNg3x - 1.1 Version',class='#32770')
004012ED |. |E8 C6010000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
004012F2 |. |EB 14 JMP SHORT Zebrone.00401308
004012F4 |> \6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
004012F6 |. 68 F8314000 PUSH Zebrone.004031F8 ; |Title = "Hmmmm :P"
004012FB |. 68 01324000 PUSH Zebrone.00403201 ; |Text = "Sorry... The Serial isn't correct :Þ"
00401300 |. FF75 08 PUSH [ARG.1] ; |hOwner = 0011067C ('Zebra - aLoNg3x - 1.1 Version',class='#32770')
00401303 |. E8 B0010000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
00401308 |> 31C0 XOR EAX,EAX
0040130A |. 40 INC EAX
0040130B |. EB 39 JMP SHORT Zebrone.00401346
0040130D |> 6A 00 PUSH 0 ; /Result = 0
0040130F |. FF75 08 PUSH [ARG.1] ; |hWnd = 0011067C ('Zebra - aLoNg3x - 1.1 Version',class='#32770')
00401312 |. E8 89010000 CALL <JMP.&USER32.EndDialog> ; \EndDialog
00401317 |. 31C0 XOR EAX,EAX
00401319 |. 40 INC EAX
0040131A |. EB 2A JMP SHORT Zebrone.00401346
0040131C |> 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL
0040131E |. 68 40304000 PUSH Zebrone.00403040 ; |Title = "Zebra ver. 1.1"
00401323 |. 68 4F304000 PUSH Zebrone.0040304F ; |Text = "This is the 1.1 Zebra Crackme, Thanks to Quequero and Koma, to have said me a bug of the previous version. (It was due to an orrible cpu appoximation). As usually you cannot patch this .EXE, you've to find one of the many correct solut"...
00401328 |. FF75 08 PUSH [ARG.1] ; |hOwner = 0011067C ('Zebra - aLoNg3x - 1.1 Version',class='#32770')
0040132B |. E8 88010000 CALL <JMP.&USER32.MessageBoxA> ; \MessageBoxA
00401330 |. 31C0 XOR EAX,EAX
00401332 |. 40 INC EAX
00401333 |. EB 11 JMP SHORT Zebrone.00401346
00401335 |> 6A 00 PUSH 0 ; /Result = 0
00401337 |. FF75 08 PUSH [ARG.1] ; |hWnd = 0011067C ('Zebra - aLoNg3x - 1.1 Version',class='#32770')
0040133A |. E8 61010000 CALL <JMP.&USER32.EndDialog> ; \EndDialog
0040133F |. 31C0 XOR EAX,EAX
00401341 |. 40 INC EAX
00401342 |. EB 02 JMP SHORT Zebrone.00401346
00401344 |> 31C0 XOR EAX,EAX
00401346 |> C9 LEAVE
00401347 \. C2 1000 RETN 10
================================================================
0040134A /$ 55 PUSH EBP
0040134B |. 89E5 MOV EBP,ESP
0040134D |. 83EC 68 SUB ESP,68
00401350 |. FF75 08 PUSH [ARG.1] ; /x1
00401353 |. E8 78010000 CALL <JMP.&CRTDLL.atof> ; \atof
00401358 |. DD55 E8 FST QWORD PTR SS:[EBP-18]
0040135B |. 83EC 08 SUB ESP,8
0040135E |. DD1C24 FSTP QWORD PTR SS:[ESP]
00401361 |. E8 82010000 CALL <JMP.&CRTDLL.floor>
00401366 |. DD5D F8 FSTP QWORD PTR SS:[EBP-8]
00401369 |. FF75 0C PUSH [ARG.2] ; /x2
0040136C |. E8 5F010000 CALL <JMP.&CRTDLL.atof> ; \atof
00401371 |. DD55 D8 FST QWORD PTR SS:[EBP-28]
00401374 |. 83EC 08 SUB ESP,8
00401377 |. DD1C24 FSTP QWORD PTR SS:[ESP]
0040137A |. E8 69010000 CALL <JMP.&CRTDLL.floor>
0040137F |. 83C4 18 ADD ESP,18
00401382 |. DD55 F0 FST QWORD PTR SS:[EBP-10]
00401385 |. DC4D F8 FMUL QWORD PTR SS:[EBP-8]
00401388 |. D9EE FLDZ
0040138A |. DED9 FCOMPP ; floor(x1)*floor(x2)=0 ???
0040138C |. DFE0 FSTSW AX ; <<Store status word
0040138E |. 9E SAHF ; <<Store AH into FLAGS
0040138F |. 75 07 JNZ SHORT Zebrone.00401398 ; Si salta todo OK
00401391 |. 31C0 XOR EAX,EAX
00401393 |. E9 96000000 JMP Zebrone.0040142E ; Bad boy
00401398 |> DD45 F8 FLD QWORD PTR SS:[EBP-8] ; <<Floating point load
0040139B |. DC5D F0 FCOMP QWORD PTR SS:[EBP-10] ; x1 = x2 ???
0040139E |. DFE0 FSTSW AX ; <<Store status word
004013A0 |. 9E SAHF ; <<Store AH into FLAGS
004013A1 |. 75 07 JNZ SHORT Zebrone.004013AA ; Si salta todo OK
004013A3 |. 31C0 XOR EAX,EAX
004013A5 |. E9 84000000 JMP Zebrone.0040142E ; Bad boy
004013AA |> DD45 F8 FLD QWORD PTR SS:[EBP-8] ; <<Floating point load
004013AD |. DD5D C8 FSTP QWORD PTR SS:[EBP-38]
004013B0 |. D9E8 FLD1 ; Carga 1 en el stack
004013B2 |. DD55 C0 FST QWORD PTR SS:[EBP-40] ; <<Floating point store
004013B5 |. DC5D C8 FCOMP QWORD PTR SS:[EBP-38] ; x1 > 1 ???
004013B8 |. DFE0 FSTSW AX ; <<Store status word
004013BA |. 9E SAHF ; <<Store AH into FLAGS
004013BB |. 77 2D JA SHORT Zebrone.004013EA ; Si salta bad boy
004013BD |. DF2D 38304000 FILD QWORD PTR DS:[403038] ; <<Load integer>> 2540BE400 = 10^10
004013C3 |. DD55 B8 FST QWORD PTR SS:[EBP-48] ; <<Floating point store
004013C6 |. DC5D C8 FCOMP QWORD PTR SS:[EBP-38] ; x1 < 10^10 ???
004013C9 |. DFE0 FSTSW AX ; <<Store status word
004013CB |. 9E SAHF ; <<Store AH into FLAGS
004013CC |. 72 1C JB SHORT Zebrone.004013EA ; Si salta bad boy
004013CE |. DD45 F0 FLD QWORD PTR SS:[EBP-10] ; <<Floating point load
004013D1 |. DD5D B0 FSTP QWORD PTR SS:[EBP-50] ; <<Store and pop
004013D4 |. DD45 C0 FLD QWORD PTR SS:[EBP-40] ; <<Floating point load
004013D7 |. DC5D B0 FCOMP QWORD PTR SS:[EBP-50] ; x2 > 1 ???
004013DA |. DFE0 FSTSW AX ; <<Store status word
004013DC |. 9E SAHF ; <<Store AH into FLAGS
004013DD |. 77 0B JA SHORT Zebrone.004013EA ; Si salta bad boy
004013DF |. DD45 B8 FLD QWORD PTR SS:[EBP-48] ; <<Floating point load>> carga 10^10
004013E2 |. DC5D B0 FCOMP QWORD PTR SS:[EBP-50] ; x2 < 10^10 ???
004013E5 |. DFE0 FSTSW AX ; <<Store status word
004013E7 |. 9E SAHF ; <<Store AH into FLAGS
004013E8 |. 73 04 JNB SHORT Zebrone.004013EE ; Salta si menor
004013EA |> 31C0 XOR EAX,EAX
004013EC |. EB 40 JMP SHORT Zebrone.0040142E ; Bad boy
004013EE |> DD45 F8 FLD QWORD PTR SS:[EBP-8] ; <<Floating point load>> carga x1
004013F1 |. D9FE FSIN ; Sin(x1)
004013F3 |. DD5D A8 FSTP QWORD PTR SS:[EBP-58] ; <<Store and pop
004013F6 |. DD45 F0 FLD QWORD PTR SS:[EBP-10] ; <<Floating point load>> carga x2
004013F9 |. D9FE FSIN ; Sin(x2)
004013FB |. DD5D A0 FSTP QWORD PTR SS:[EBP-60] ; <<Store and pop
004013FE |. DD45 A8 FLD QWORD PTR SS:[EBP-58] ; <<Floating point load
00401401 |. DC4D A0 FMUL QWORD PTR SS:[EBP-60] ; Sin(x1) * Sin(x2)
00401404 |. DF2D 30304000 FILD QWORD PTR DS:[403030] ; <<Load integer>> 2386F26FC10000 = 10^16
0040140A |. DEC9 FMULP ST(1),ST ; 10^16 * (Sin(x1) * Sin(x2))
0040140C |. 83EC 08 SUB ESP,8
0040140F |. DD1C24 FSTP QWORD PTR SS:[ESP] ; <<Store and pop
00401412 |. E8 D1000000 CALL <JMP.&CRTDLL.floor>
00401417 |. 83C4 08 ADD ESP,8
0040141A |. DD5D 98 FSTP QWORD PTR SS:[EBP-68]
0040141D |. D9EE FLDZ ; <<Load 0.0 onto stack
0040141F |. DC5D 98 FCOMP QWORD PTR SS:[EBP-68] ; 10^16 * (Sin(x1) * Sin(x2)) = 0 ???
00401422 |. DFE0 FSTSW AX
00401424 |. 9E SAHF ; <<Store AH into FLAGS
00401425 |. 75 05 JNZ SHORT Zebrone.0040142C ; Si NO salta todo OK
00401427 |. 31C0 XOR EAX,EAX
00401429 |. 40 INC EAX
0040142A |. EB 02 JMP SHORT Zebrone.0040142E
0040142C |> 31C0 XOR EAX,EAX
0040142E |> C9 LEAVE
0040142F \. C3 RETN
La primera dificultad que podemos encontrar es que utiliza instrucciones FPU y coma flotante, ya que si no tenemos la vista entrenada nos puede resultar un engorro. Superado esto, la rutina de comprobación se puede resumir así:
x1 * x2 != 0
x1 != x2
x1 > 1 y < 10^10
x2 > 1 y < 10^10
Floor[10^16 * sin(x1) * sin(x2)] = 0
A priori no parece que tenga mucha dificultad, pero vamos a analizarlo más concienzudamente. Necesitamos que la parte entera del resultado de la multiplicación sea 0, algo que parece sencillo, pero fíjate que la constante 10^16 nos obliga a su vez, a que el resultado delseno sea muy pequeño, cosa que como comprobaréis limita mucho los resultados satisfactorios.
Repasando trigonometría
Cuando nos enseñó nuestro profesor la función del seno nos hizo el siguiente dibujo:
Partiendo de la circunferencia unitaria, podemos concluir que el seno de alpha es igual a la altura x. Como lo que nos interesa a nosotros es que el seno sea muy pequeño, en realidad estamos buscando que la x sea lo más pequeña posible. Llegamos entonces a la conclusión de que las soluciones para enteros entre 1 y 10^10 van a ser muy reducidas. Además nos percatamos que el ángulo alpha va a tener que estar muy proximo a 0º – 360 (0 – 2π) y a 180º (π). En el siguiente gráfico queda claro el estrecho margen en el que nos movemos.
Si habéis leído la solución de cronos ahora le encontraréis algo más de sentido a por que él utilizó fracciones continuas de π y cogió como resultado los numeradores más cercanos a 10^10, en su caso 245850922 y 411557987.
Como veis, el exponente negativo (^-17) debe ser mayor que el positivo (^16) para tener éxito.
Fuerza bruta
Lo que vamos a hacer a continuación es buscar todos los senos con exponente negativo ^-8 ó ^-9 de enteros entre 1 y 10^10, y vamos a cruzar los resultados para determinar todos los resultados válidos.
Preparamos el programa y le dejamos trabajar. En principio vamos a filtrar todos los resultados que tengan exponente negativo y luego ya aislaremos los que nos interesan. Esto lo hago por curiosidad.
La fuerza bruta nos arroja 63663resultados con exponente negativo entre ^-5 y ^-9, de los cuales solamente nos quedamos con 65, que son los comprendidos a exponentes de entre ^-8 y ^-9. Los números mágicos son los siguientes:
Los rojos son exponentes ^-9, el resto ^-8.
La mayoría de estos números solo valen con ciertas combinaciones, de hecho, ninguno vale para todos. Esto se debe, a parte del propio exponente, a que hay senos positivos y negativos y para hacer válido a un seno negativo hay que combinarlo con otro negativo. Esto último se debe únicamente a la interpretación que hace el crackme.
Finalmente cruzamos los resultados y obtenemos 44 combinaciones de seriales válidos que si obviamos repeticiones se reducen a la mitad.
Combinaciones válidas:
Conclusiones
Podemos concluir que para cada 10^10 enteros hay 22 soluciones posibles. Finalmente comentar que si aLoNg3x no hubiera puesto el límite en 10^10, habría soluciones infinitas.
La solución que he encontrado yo, es convertir el código brainfuck a algo más amigable y depurarlo hasta encontrar la solución. La conversión la he realizado con VBBrainFNET y luego la depuración con Visual Studio. El crackme te pide una clave de cuatro cifras para darte la solución, pero si no quieres volverte loco puedes amañar los bucles para encontrar la solución.
Warning: This challenge is still active and therefore should not be resolved using this information. Aviso: Este reto sigue en activo y por lo tanto no se debería resolver utilizando esta información.
En los retos de esteganografía ya uno se espera de todo, y cuantos más haces más enrevesados encuentras. Hoy no, hoy vamos a tratar un clásico dentro de este tipo de retos, ocultar un archivo dentro de otro.
Buscando la solución
Prácticamente lo primero que hago cuando me descargo una imágen en éste tipo de retos es abrirla con un editor hexadecimal, y en este caso hemos dado en el clavo. La abrimos con un editor cualquiera y al final del archivo encontramos que estamos tratando con un archivo ZIP (cabecera PK).
La abrimos con 7zip y vemos el prometido archivo txt, dentro ¿qué abrá?
Warning: This challenge is still active and therefore should not be resolved using this information. Aviso: Este reto sigue en activo y por lo tanto no se debería resolver utilizando esta información.
Este es el típico reto de Javascript, no tiene mucha complicación pero he decidido dedicarle una entrada por que me llamó la atención lo que utiliza de usuario y clave.
El Script
function getStyle(el,styleProp)
{
var x = document.getElementById(el);
if (x.currentStyle)
var y = x.currentStyle[styleProp];
else if (window.getComputedStyle)
var y = document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp);
if (y.substr(0, 1) == "#"){ return y; } else {
var value = y.split(',');
var R = value[0].substr(4);
var G = value[1];
var B = value[2].substr(0, value[2].length-1);
var RGB = "#" + toHex(R)+ toHex(G)+toHex(B);
return RGB;
}
}
function toHex(N) {
if (N==null) return "00";
N=parseInt(N); if (N==0 || isNaN(N)) return "00";
N=Math.max(0,N); N=Math.min(N,255); N=Math.round(N);
return "0123456789ABCDEF".charAt((N-N%16)/16)
+ "0123456789ABCDEF".charAt(N%16);
}
function pw (form)
{
var d1, d2, d3;
if (navigator.appName == "Netscape"){
d1= getStyle('content', 'background-color');
} else {
d1= getStyle('content', 'backgroundColor');
}
d2=form.Name.value;
d3=form.Password.value;
if (d2==d1.length) {
if (d3==d1) {
window.open ("../" + d1.substr(1, 10), "_self")
} else {
alert("Muhaha! Wrong!")
}
} else {
alert("Muhaha! Wrong!")
}
}
En el formulario vemos que llama a la función «pw» y ésta a su vez llama a la función «getStyle«, bueno, pués es tan simple como poner un «alert();» dentro de la función «pw» para cazar la clave. Con éste método podemos cazar la clave del 90% de este tipo de pruebas.
Con esto ya tenemos la clave. El usuario responde a la siguiente sentencia «d2==d1.length«, es decir, es el número de dígitos de la clave.
Hemos interceptado un mensaje secreto, pero ninguno de nuestros traductores lo sabe interpretar, ¿sabrías interpretarlo tú? Lo único que hemos encontrado es esto en un foro: шжзклмнпфъ = 1234567890
Parece que el mensaje secreto está encriptado utilizando un alfabeto cifrado que corresponde a números. Según la clave proporcionada (шжзклмнпфъ = 1234567890), cada letra del alfabeto cirílico se sustituye por un número.
Primero, descompondremos la clave dada: ш = 1 ж = 2 з = 3 к = 4 л = 5 м = 6 н = 7 п = 8 ф = 9 ъ = 0
Este parece ser un mensaje cifrado en números. La secuencia de números se puede interpretar de varias maneras (como ASCII, coordenadas, etc.). Si asumimos que es un texto codificado en ASCII:
Convertimos cada número a su correspondiente carácter ASCII:
72 = H 97 = a 99 = c 107 = k 79 = O 110 = n 123 = { 69 = E 108 = l 95 = _ 84 = T 101 = e 116 = t 114 = r 105 = i 115 = s 95 = _ 101 = e 115 = s 95 = _ 117 = u 110 = n 95 = _ 106 = j 117 = u 101 = e 130 = ? 111 = o 95 = _ 82 = R 117 = u 115 = s 111 = o 125 = }
Juntando todo:
HackOn{El_Tetris_e_s_u_n_j_u_e?o_Ruso}
La parte «{El_Tetris_e_s_u_n_j_u_e?o_Ruso}» parece un mensaje en español. Probablemente deba ser leído como: HackOn{El_Tetris_es_un_juego_Ruso}
Así, el mensaje secreto es: HackOn{El_Tetris_es_un_juego_Ruso}.
La imagen de portada de la entrada ha sido generada con ChatGPT.