Con The Ring inauguro una nueva sección llamada Blooper Tech Movie (BTM), algo así como pifias o tomas falsas tecnológicas en películas. Aunque no os lo creáis, los creadores del séptimo arte y sus asesores son humanos, y como tal se rigen por la ley del mínimo esfuerzo. En este BTM vamos a ver como una simple escena nos puede arruinar la excelente atmósfera de intriga que hasta ese momento se respiraba.
BTM
Transcurridos 70 minutos de película vemos que la protagonista está en una redacción buscando información sobre la maldita cinta de vídeo en un PC.
Hasta aquí todo correcto, pero instantes después vemos que realiza una búsqueda sobre «Moesko Islands» y cuando se abre el plano y podemos ver la barra de direcciones, en realidad vemos un archivo local situado en «C:\WIN98\Desktop\search.com\2_moesko_island_pt2.html«. A continuación la secuencia, se pueden ver los enlaces «locales» en el segundo 13 y 17.
Teniendo en cuenta que la película data del año 2002, me parece increíble que los productores no se lo curraran un poco más y registraran un dominio como «jdoesearch.com» y simularan que se realizan las búsquedas ONline y no OFFline como se están haciendo en realidad.
Quizá no tenían pensado mostrar la parte superior del navegador o simplemente pensaron que nadie se fijaría pero el caso es que para cualquiera que haya navegado por Internet más de 2 veces, si se fija en la barra de direcciones su expresión facial cambia a WTF!.
Aquí tenemos un CrackMe diferente a lo que estamos acostumbrados, ya que en vez del típico número de serie asociado a un nombre la comprobación se realiza mediante checkboxes con una matriz de 7×3. El CrackMe está realizado en Visual C++ lo que facilita en parte encontrar rápidamente la rutina de comprobación.
Comprobación
004013C5 > /8B7424 10 MOV ESI,[DWORD SS:ESP+10] ;
004013C9 . |33FF XOR EDI,EDI
004013CB > |8B86 74304000 MOV EAX,[DWORD DS:ESI+403074] ;
004013D1 . |8BCB MOV ECX,EBX
004013D3 . |50 PUSH EAX
004013D4 . |E8 6F020000 CALL <JMP.&MFC42.#3092_CWnd::GetDlgItem> ; Lee el estado del checkbox
004013D9 . |8B48 20 MOV ECX,[DWORD DS:EAX+20]
004013DC . |6A 00 PUSH 0
004013DE . |6A 00 PUSH 0
004013E0 . |68 F0000000 PUSH 0F0
004013E5 . |51 PUSH ECX ;
004013E6 . |FFD5 CALL NEAR EBP
004013E8 . |3B86 20304000 CMP EAX,[DWORD DS:ESI+403020] ; Comprueba el estado del checkbox (1 activado 0 desactivado)
004013EE . |75 20 JNZ SHORT Matrix_C.00401410 ; Salto a chico malo
004013F0 . |47 INC EDI ; Incrementa contador
004013F1 . |83C6 04 ADD ESI,4
004013F4 . |83FF 07 CMP EDI,7 ; ¿Hemos terminado de leer las columnas? ¿contador = 7?
004013F7 .^|7C D2 JL SHORT Matrix_C.004013CB ; si terminan las columnas deja pasar
004013F9 . |8B4424 10 MOV EAX,[DWORD SS:ESP+10]
004013FD . |83C0 1C ADD EAX,1C ; contador de filas
00401400 . |83F8 54 CMP EAX,54 ; 3 filas = 1C+1C+1C=54
00401403 . |894424 10 MOV [DWORD SS:ESP+10],EAX
00401407 .^\7C BC JL SHORT Matrix_C.004013C5 ; ¿Hemos terminado de leer la fila? ¿contador = 54?
00401409 . 68 D8304000 PUSH Matrix_C.004030D8 ; ASCII "Registration successful!"
0040140E . EB 05 JMP SHORT Matrix_C.00401415
00401410 > 68 C8304000 PUSH Matrix_C.004030C8 ; ASCII "Not registered!"
En la rutina de comprobación se ve fácil un CMP EDI,7 por lo que podemos deducir que si el creador no se ha molestado mucho la comprobación se realiza de izquierda a derecha y de arriba hacia abajo.
Orden de comprobación
Tal es así que si ponemos un breakpoint en 4013E8, podemos ir sacando el estado correcto de los checkboxes sin mucha molestia.
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.
Realistic Challenge 4: There is a site offering protection against hackers to website owners, the service is far too overpriced and the people running the service don’t know anything about security. Look around their site, and see how protected it is.
Hay un sitio que ofrece protección contra los hackers. El servicio tiene un precio abusivo, echa un vistazo a la web y evalúa su pretección.
Analizando a la víctima
Vemos un escueto menú pero con cosas interesantes.
Pinchamos sobre «Testimonials» y a continuación en «Customer 1»
Vemos que hay solo 3 «customers», vamos a introducir manualmente un 5 haber que pasa.
Ok, nos genera el siguiente error.
Probamos ahora con un enlace interno que nos genera el siguiente error.
Tenemos un directorio interesante «secure«, si entramos en el nos salta un Login típico protegido con «.htaccess«. Lo lógico a continuación es hacernos con el archivo «.htpasswd«
Una vez obtenido el contenido del archivo «.htpasswd» lo siguiente es crackear el password con John the Ripper. Nos logueamos en la carpeta secure y reto superado.
Aquí tenemos un crackme hecho en Java, lo que como comprobareis a continuación no es muy buena idea ya que conseguir el código fuente e incluso modificarlo no es muy dificil.
Decompilado
Abrimos la víctima con nuestro decompilador favorito y nos fijamos en su contenido.
Lo interesante está en la clase Main > doneActionPerformed(ActionEvent), ya que contiene el código al ejecutar el botón que chequea el serial.
Llegados a este punto podríamos hacer cualquier cosa, parchear, que el serial válido nos lo mostrara una MessageBox etc. Pero vamos a hacer algo mejor, vamos a modificar la victima para crear nuestro keygen personalizado.
Creando un Keygen a partir de la víctima
Solamente tendremos que modificar un poco la apariencia y modificar la rutina de comprobación del serial para que lo muestre en la caja de texto del serial. Finalmente abrá que recompilar.
Aquí resalto el texto a modificar para el aspecto.
Así queda la modificación para mostrar el serial correcto en la caja de texto.
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.
Realistic Challenge 4: There is a site offering protection against hackers to website owners, the service is far too overpriced and the people running the service don’t know anything about security. Look around their site, and see how protected it is.
Hay un sitio que ofrece protección contra los hackers. El servicio tiene un precio abusivo, echa un vistazo a la web y evalúa su pretección.
Analizando a la víctima
Vemos un escueto menú pero con cosas interesantes.
Pinchamos sobre «Testimonials» y a continuación en «Customer 1»
Vemos que hay solo 3 «customers», vamos a introducir manualmente un 5 haber que pasa.
Ok, nos genera el siguiente error.
Probamos ahora con un enlace interno que nos genera el siguiente error.
Tenemos un directorio interesante «secure«, si entramos en el nos salta un Login típico protegido con «.htaccess«. Lo lógico a continuación es hacernos con el archivo «.htpasswd«
Una vez obtenido el contenido del archivo «.htpasswd» lo siguiente es crackear el password con John the Ripper. Nos logueamos en la carpeta secure y reto superado.
Este un crackme muy interesante para principiantes ya que la rutina no es muy compleja. Está hecho en ensamblador.
Saltar el antidebug
Arrancamos el crackme en Olly damos al play y se cierra. Buscamos en las «Intermodular Calls» y vemos «IsDebuggerPresent«, clickamos sobre ella y vemos el típico call, lo NOPeamos.
Aquí vemos el call.
Call Nopeado.
Encontrando un serial válido
Encontrar en serial válido en esta ocasión es muy sencillo, basta con buscar en las «String References» el mensaje de «Bad boy» y fijarse en la comparación.
El algoritmo
Si nos fijamos en el serial generado nos da muchas pistas pero vamos a destriparlo ya que tampoco tiene mucha complicación. De nuevo miramos en las «String references» y clickamos sobre el mensaje de «bad boy«. Encima de los mensajes vemos claramente la rutina de creación del serial.
Comprueba si el dígito está es mayúsculas y si está le sume 2C al valor ascii.
Suma el valor ascii de todos los dígitos menos el último.
SUM + 29A
SUM * 3039
SUM – 17
SUM * 9
Finalmente concatena letras siguiendo este criterio:
Len(nombre) = 4 -> coje la última letra
Len(nombre) = 5 -> coje las dos últimas
Len(nombre) = 6 -> coje las tres últimas
Len(nombre) = 7 -> coje las cuatro últimas
Len(nombre) = 8 -> coje las cinco últimas
Len(nombre) = 9 -> coje las seis últimas
Len(nombre) = A -> coje las siete últimas
Ejemplo para deurus
d e u r u (s)
64+65+75+72+75 = 225
225 + 29A = 4BF
4BF * 3039 = E4DE87
E4DE87 - 17 = E4DE70
E4DE70 * 9 = 80BD1F0
;Pasamos a decimal y concatenamos
134992368rus
Ejemplo para Deurus
D e u r u (s)
44(+2C)+65+75+72+75 = 25D
25D + 29A = 4F7
4BF * 3039 = EF6AFF
EF6AFF - 17 = EF6AE8
EF6AE8 * 9 = 86AC228
;Pasamos a decimal y concatenamos
141214248rus
Como curiosidad decirtos que con el tiempo valores del estilo 29A y 3039 os pegarán rápido al ojo ya que equivalen a 666 y 12345 en decimal. Por cierto 29A fue un grupo de hackers creadores de virus muy conocido en la escena Nacional e Internacional.
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.
Realistic Challenge 4: There is a site offering protection against hackers to website owners, the service is far too overpriced and the people running the service don’t know anything about security. Look around their site, and see how protected it is.
Hay un sitio que ofrece protección contra los hackers. El servicio tiene un precio abusivo, echa un vistazo a la web y evalúa su pretección.
Analizando a la víctima
Vemos un escueto menú pero con cosas interesantes.
Pinchamos sobre «Testimonials» y a continuación en «Customer 1»
Vemos que hay solo 3 «customers», vamos a introducir manualmente un 5 haber que pasa.
Ok, nos genera el siguiente error.
Probamos ahora con un enlace interno que nos genera el siguiente error.
Tenemos un directorio interesante «secure«, si entramos en el nos salta un Login típico protegido con «.htaccess«. Lo lógico a continuación es hacernos con el archivo «.htpasswd«
Una vez obtenido el contenido del archivo «.htpasswd» lo siguiente es crackear el password con John the Ripper. Nos logueamos en la carpeta secure y reto superado.
Analizamos el programa con PEiD y nos muestra que está hecho en ensamblador.
Unas pruebas introduciendo datos nos muestran que el nombre debe tener entre 3 y 10 dígitos.
Determinando la rutina de creación del serial con Ollydbg
Llegados a este punto tenemos dos opciones que funcionan en el 90% de los casos. La primera es mediante las referenced strings o mediante los names.
Para el primer caso, con el keygenme cargado en olly, click derecho y Search > All referenced text strings. Haciendo doble click en “You got it” o en “Bad boy” vamos directamente a la rutina de comprobación del serial o muy cerca de ella en la mayoría de los casos.
Para el segundo caso, haremos click derecho y Search > Name (label) in current módule, o Ctrl+N. Vemos dos llamadas interesantes como son user32.GetDlgItemInt y user32.GetDlgItemTextA. Lo más seguro es que user32.GetDlgItemInt coja del textbox nuestro serial y user32.GetDlgItemTextA coja nuestro nombre. Para este caso colocaríamos breakpoints en las dos llamadas.
En mi caso elijo la primera opción. Nada más pulsar en “You got it” nos fijamos un poco más arriba y vemos las funciones donde coge el nombre y el serial y a simple vista se ven las operaciones que hace con ellos.
Generando un serial válido
Como se muestra en la imagen siguiente, la creación del serial es muy sencilla y al final la comparación es lineal ya que se compara nuestro serial con el serial válido. Veamos el serial válido para el usuario “abc” cuyos dígitos en hexadecimal son 0x61, 0x62 y 0x63.
Letra a
Letra b
Letra c
Suma + 0x61
Suma * 0x20
Suma xor 0xBEFF
Suma / 4
Suma = 0x2CB7
Suma + 0x62
Suma * 0x20
Suma xor 0xBEFF
Suma / 4
Suma = 0x14777
Suma + 0x63
Suma * 0x20
Suma xor 0xBEFF
Suma / 4
Suma = 0xA116F
Suma xor 0xBEA4 = 0xAAFCB
Serial válido = 700363
Generando un keygen con WinASM studio desde cero
Abrimos WinASM studio y pulsamos en File > New Project y en la pestaña dialog elegimos base.
Vemos que se nos generan tres archivos, uno con extensión asm, otro con extensión inc y otro con extensión rc. El archivo asm es el que contendrá nuestro código. El archivo inc no lo vamos a usar para simplificar las cosas y el archivo rc es nuestro formulario al que pondremos a nuestro gusto.
Empecemos con el aspecto del formulario. Por defecto viene como se muestra en la siguiente imagen. Que por cierto, es todo lo que necesitamos para un keygen básico.
Y el aspecto final:
Ahora veamos cómo viene nuestro archivo asm inicialmente y que haremos con él. En la siguiente imagen lo indico.
Encima de la sección .code hemos creado dos secciones como son .data y .data? y hemos declarado las variables necesarias.
szFormat está declarada en formato integer (%i). Más tarde la utilizaremos junto a la función wsprintf para dar formato a un número.
szSizeMin: habla por sí misma.
szSizeMax: habla por sí misma.
szCap: habla por sí misma.
szName: contendrá el nombre introducido.
szCode: contendrá el serial válido.
Nuestro código queda de la siguiente manera:
A partir de aquí ya simplemente es escribir el código necesario para generar el serial válido. Una de las ventajas que tiene el ensamblador para hacer keygens sin muchas complicaciones, es que prácticamente es copiar el código que nos muestra Ollydbg. Si os fijáis a continuación, en el botón llamado “IDC_OK” (no le he cambiado el nombre) he puesto todo el código necesario para generar la simple rutina del serial.
Como veis el bucle del nombre es una copia de lo que nos mostró Ollydbg. Una vez que tenemos en EAX nuestro serial válido, mediante la función wsprintf guardamos en la variable szCode el serial válido con formato integer. Finalmente mediante la función SetDlgItemText, mostramos el serial válido en la caja de texto 1002, que es la del serial.
Hace poco me puse a leer El oscuro pasajero de Jeff Lindsay, novela que inspiró la serie Dexter. La nostalgia me invadió y al final decidí volver a ver la primera temporada que tanto me gustó hace unos años. Para mi sorpresa, muchos de los detalles que recordaba de la serie eran incorrectos o incompletos. Bueno, el caso es que en esta ocasión me he fijado más en los detalles y he descubierto una pequeña perla en el capítulo 8 de la primera temporada.
ALERTA DE SPOILER: Aunque la serie tiene unos añitos no quisiera fastidiarsela a nadie. Si continuas leyendo puede que te enteres de algo que no quieras.
En un momento dado, a Dexter se le ocurre la feliz idea de contactar con el asesino en serie que le está dejando regalitos y no se le ocurre mejor idea que hacerlo en una web de contactos cualquiera. La web en cuestión es www.miamilist12.com/miami/main y Dexter decide escribir un mensaje en el hilo missed connections. A continuación la secuencia de imágenes.
mailto:frozenbarbie@hotmail.???
La simple idea de escribir en un tablón, foro, lista, etc y esperar que el asesino en serie lo lea ya es una locura. Pero señor@s, esto es ficción, y por supuesto el asesino no solo ve el mensaje si no que responde a Dexter creando un pequeño error con las direcciones de email. Y es que cuando el asesino ve el mensaje se puede apreciar que la dirección de email de Dexter es frozenbarbie@hotmail.web y cuando el asesino le responde, se ve claramente que lo hace a la dirección frozenbarbie@hotmail.com. A continuación las imágenes.
Además me ha llamado la atención que aunque es evidente que el asesino usa Windows XP, se puede apreciar que han retocado en post-producción el botón de inicio para que quede oculto.
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.
Resumidamente, esta técnica consiste en ocultar información en el bit menos significativo de cada uno de los píxeles de una imagen, consiguiendo así que el cambio realizado sea invisible al ojo humano. El problema de esta técnica, es que la información oculta puede obtenerse fácilmente si esta no se ha codificado previamente o si no se sigue un patrón concreto a la hora de ocultarla.
Desde la web del reto nos avisan de que esto es un simple truco pero espectacular. Nos animan a descargar una imágen y a encontrar la solución oculta.
Aprovecho este reto para presentaros una herramienta vital al enfrentaros a ciertos retos sobre esteganografía, steganabara.
Steganabara tiene dos apartados muy interesantes, uno es «color table» y otro «bit mask«, hoy veremos en acción a «bit mask».
No os preocupéis por la solución ya que cambia para cada usuario y sesión.
Buscando la solución oculta
Abrimos steganabara y empezamos a trastear con bit mask.
Al poco tiempo ya vemos que vamos bien encaminados.
El otro día navegando por la red fuí a dar a un mirror de la gran web «Karpoff Spanish Tutor«. Para los que no la conozcais, debeis saber que fué una referencia para el Cracking en la escena nacional. Contenía manuales, cursos, utilidades y todo lo que te pudieras imaginar y/o necesitar para iniciarte en el mundillo del Cracking. Por aquel entonces yo era un cigoto en esto de la Ingeniería Inversa pero la web de Karpoff sentó mis bases y contribuyó a mi afán por saber y compartir. El lector debería saber que estamos hablando de finales de los 90, por lo que este crackme y sucesivos de la web de Karpoff ahora pueden parecer más fáciles pero hay que tener en cuenta que ahora tenemos mejores herramientas.
El objetivo es sacar un serial valido o hacer un generador de llaves, esta hecho para newbies y no tiene ninguna otra proteccion.
El crackme está hecho en Delphi y no tiene ningún tipo de protección antidebug ni nada por el estilo.
El algoritmo
Abrimos Delphi Decompiler y buscamos en los eventos el botón de registro, en este caso se llama «focusClick» y vemos que su RVA apunta a la dirección «442AEC«, lo apuntamos y abrimos el crackme con Ollydbg.
En Olly pulsamos Ctrl+G e introducimos el offset anterior. Un poco más abajo vemos un Call interesante, entramos en el.
Dentro del Call vemos a simple vista dos funciones muy interesantes como son «GetVolumeInformationA» y «GetUserNameA«.
Traceamos el código y vemos que obtiene el número de serie del disco C y el usuario de windows y finalmente los concatena. Se puede ver a simple vista en el Stack o Pila.
No necesitamos saber nada más, probamos el número de serie cazado y funciona. Os adjunto el keygen hecho en C++.
Lo que más me ha gustado del capítulo es el guiño que han hecho a la RaspBerry PI. La escena transcurre al inicio del capítulo cuando uno de los protagonistas se conecta a un vehículo para hackearlo con una Raspi 3 Model B con varios pines del GPIO doblados. Os dejo unas capturas a continuación donde se aprecia el logo.
Captura del episodio
Captura del episodio
Captura del episodio
Captura del episodio
La conexión
Ya puestos, la conexión parece micro usb tipo B. Al fondo se ve lo que parece un puerto HDMI.
Captura del episodio
Captura del episodio
Captura del episodio
Cable comercial
La pifia
Lo que no me ha gustado es que al fijarme en el software que corre en el vehículo aparece un flamante OMNIBOOT.EXE con un aspecto parecido al símbolo de sistema, es decir, nos intentan vender que en un futuro el software que gestiona el vehículo es alguna variación de Windows, algo poco probable a día de hoy al menos. Con este tipo de predicciones no se puede escupir hacia arriba pero actualmente es más probable un nucleo tipo Linux u otro propietario al estilo Tesla.
Software del vehículo
Os dejo todas las capturas relevantes a continuación.
Renombramos entonces la extensión a png y continuamos.
Imagen oculta
Esta parte la afrontaremos con Steganabara, una herramienta muy útil que siempre uso cuando me enfrento a un reto «stego». En esta ocasión utilizaremos el análisis de color. Para ello pulsamos sobre «Analyse > Color table«.
En la tabla de colores tenemos la descomposición de colores RGBA y su frecuencia de aparición. Ordenamos por frecuencia descendiente y hacemos doble clic sobre la fila para abrir la imagen resultante.
A continuación un resumen de las imágenes obtenidas.
Como podéis observar, la imagen oculta es un código QR. Lo escaneamos con nuestra app preferida y obtenemos un texto encriptado.
A partir de aquí el reto pasa a ser de encriptación. Con el tiempo diferenciareis fácilmente el tipo de cifrado con sólo ver el texto. En este caso lo primero que se nos ocurre es comprobar dos cifrados clásicos como son el cifrado César y el Vigenere.
Tras desestimar el cifrado César realizamos un ataque de «fuerza bruta» al cifrado Vigenere mediante análisis estadístico. En la imagen que muestro a continuación se puede ver que la clave está cerca de ser «HPHQTC» pero todavía no se lee correctamente.
Ya que la fuerza bruta de por sí no termina de darnos la respuesta correcta, pasamos a probar algo muy útil, esto es, descifrar por fuerza bruta pero dándole una palabra para comparar. En este caso en concreto vemos que una posible palabra que pudiera estar en el texto encriptado es «PASSWORD», probamos y reto terminado.
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: Debido a que este reto está en activo no publicaré a donde pertenece.
Ya sabéis que los retos stego son muy variopintos. El otro día me encontré con uno que parecía que iba a ser complejo pero en realidad era bastante sencillo.
Tras varias pruebas complejas infructuosas, se me ocurrió descomponer por canales y efectivamente ese era el camino. Para ello yo utilicé la herramienta StegSolve de mi querido Caesum, pero podéis resolverlo incluso online con Pinetools.
Empezamos con lo que espero que sea una serie de crackmes RSA. En este caso en particular y como el propio autor nos adelanta, se trata de RSA-200.
En criptografía, RSA (Rivest, Shamir y Adleman) es un sistema criptográfico de clave pública desarrollado en 1977. Es el primer y más utilizado algoritmo de este tipo y es válido tanto para cifrar como para firmar digitalmente.
Funcionamiento de RSA
Inicialmente es necesario generar aleatoriamente dos números primos grandes, a los que llamaremos p y q.
A continuación calcularemos n como producto de p y q:
n = p * q
Se calcula fi:
fi(n)=(p-1)(q-1)
Se calcula un número natural e de manera que MCD(e, fi(n))=1 , es decir e debe ser primo relativo de fi(n). Es lo mismo que buscar un numero impar por el que dividir fi(n) que de cero como resto.
Mediante el algoritmo extendido de Euclides se calcula d que es el inverso modular de e.
Puede calcularse d=((Y*fi(n))+1)/e para Y=1,2,3,... hasta encontrar un d entero.
El par de números (e,n) son la clave pública.
El par de números (d,n) son la clave privada.
Cifrado: La función de cifrado es.
c = m^e mod n
Descifrado: La función de descifrado es.
m = c^d mod n
OllyDbg
Con OllyDbg analizamos la parte del código que nos interesa.
Lo primero que observamos es que el código nos proporciona el exponente público (e) y el módulo (n).
e = 10001
n = 8ACFB4D27CBC8C2024A30C9417BBCA41AF3FC3BD9BDFF97F89
A continuación halla c = serial^d mod n. Finalmente Divide c entre 0x1337 y lo compara con el nombre.
Como hemos visto en la teoría de RSA, necesitamos hallar el exponente privado (d) para poder desencriptar, según la fórmula vista anteriormente.
Fórmula original: m=c^d mod n
Nuestra fórmula: Serial = x^d mod n. Siendo x = c * 0x1337
Calculando un serial válido
Existen varios ataques a RSA, nosotros vamos a usar el de factorización. Para ello vamos a usar la herramienta RSA Tool. Copiamos el módulo (n), el exponente público (e) y factorizamos (Factor N).
Hallados los primos p y q, hallamos d (Calc. D).
Una vez obtenido d solo nos queda obtener x, que recordemos es nombre * 0x1337.
Cuando decimos nombre nos referimos a los bytes del nombre en hexadecimal, para deurus serían 646575727573.
Ejemplo operacional
Nombre: deurus
x = 646575727573 * 0x1337 = 7891983BA4EC4B5
Serial = x^d mod n
Serial = 7891983BA4EC4B5^32593252229255151794D86C1A09C7AFCC2CCE42D440F55A2D mod 8ACFB4D27CBC8C2024A30C9417BBCA41AF3FC3BD9BDFF97F89
Serial = FD505CADDCC836FE32E34F5F202E34D11F385DEAD43D87FCD
Como la calculadora de Windows se queda un poco corta para trabajar con números tan grandes, vamos a usar la herramienta Big Integer Calculator. A continuación os dejo unas imágenes del proceso.
Keygen
En esta ocasión hemos elegido Java ya que permite trabajar con números grandes de forma sencilla, os dejo el código más importante.
JButton btnNewButton = new JButton("Generar");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
BigInteger serial = new BigInteger("0");
BigInteger n = new BigInteger("871332984042175151665553882265818310920539633758381377421193");//módulo
BigInteger d = new BigInteger("316042180198461106401603389463895139535543421270452849695277");//exponente privado
BigInteger x = new BigInteger("4919");//0x1337
String nombre = t1.getText();
BigInteger nombre2 = new BigInteger(nombre.getBytes());
nombre2 = nombre2.multiply(x);
serial = nombre2.modPow(d, n);
t2.setText(serial.toString(16).toUpperCase());
}
});
Introducción Objetivo del juego y normas Código inicial Primeras modificaciones Terminando la faena Código ganador Curiosidades Enlaces Introducción Hace tiempo
Se nos entrega un ELF que decompilado presenta este aspecto:
/* This file was generated by the Hex-Rays decompiler version 8.4.0.240320.
Copyright (c) 2007-2021 Hex-Rays <info@hex-rays.com>
Detected compiler: GNU C++
*/
#include <defs.h>
//-------------------------------------------------------------------------
// Function declarations
__int64 (**init_proc())(void);
__int64 sub_401020();
__int64 sub_401030(); // weak
__int64 sub_401040(); // weak
__int64 sub_401050(); // weak
__int64 sub_401060(); // weak
__int64 sub_401070(); // weak
// int puts(const char *s);
// int printf(const char *format, ...);
// __int64 __isoc99_scanf(const char *, ...); weak
// void __noreturn exit(int status);
void __fastcall __noreturn start(__int64 a1, __int64 a2, void (*a3)(void));
void dl_relocate_static_pie();
char *deregister_tm_clones();
__int64 register_tm_clones();
char *_do_global_dtors_aux();
__int64 frame_dummy();
int __fastcall main(int argc, const char **argv, const char **envp);
_BYTE *__fastcall encode(__int64 a1);
__int64 __fastcall validar(const char *a1);
int banner();
int comprar();
void _libc_csu_fini(void); // idb
void term_proc();
// int __fastcall _libc_start_main(int (__fastcall *main)(int, char **, char **), int argc, char **ubp_av, void (*init)(void), void (*fini)(void), void (*rtld_fini)(void), void *stack_end);
// __int64 _gmon_start__(void); weak
//-------------------------------------------------------------------------
// Data declarations
_UNKNOWN _libc_csu_init;
const char a31mparaSeguirU[43] = "\x1B[31mPara seguir usando este producto deber"; // idb
const char a32myaPuedesSeg[61] = "\x1B[32mYa puedes seguir afinando tus instrumentos (y tus flags "; // idb
const char aDirigaseANuest[21] = "\nDirigase a nuestra p"; // idb
__int64 (__fastcall *_frame_dummy_init_array_entry)() = &frame_dummy; // weak
__int64 (__fastcall *_do_global_dtors_aux_fini_array_entry)() = &_do_global_dtors_aux; // weak
__int64 (*qword_404010)(void) = NULL; // weak
char _bss_start; // weak
//----- (0000000000401000) ----------------------------------------------------
__int64 (**init_proc())(void)
{
__int64 (**result)(void); // rax
result = &_gmon_start__;
if ( &_gmon_start__ )
return (__int64 (**)(void))_gmon_start__();
return result;
}
// 404090: using guessed type __int64 _gmon_start__(void);
//----- (0000000000401020) ----------------------------------------------------
__int64 sub_401020()
{
return qword_404010();
}
// 404010: using guessed type __int64 (*qword_404010)(void);
//----- (0000000000401030) ----------------------------------------------------
__int64 sub_401030()
{
return sub_401020();
}
// 401030: using guessed type __int64 sub_401030();
//----- (0000000000401040) ----------------------------------------------------
__int64 sub_401040()
{
return sub_401020();
}
// 401040: using guessed type __int64 sub_401040();
//----- (0000000000401050) ----------------------------------------------------
__int64 sub_401050()
{
return sub_401020();
}
// 401050: using guessed type __int64 sub_401050();
//----- (0000000000401060) ----------------------------------------------------
__int64 sub_401060()
{
return sub_401020();
}
// 401060: using guessed type __int64 sub_401060();
//----- (0000000000401070) ----------------------------------------------------
__int64 sub_401070()
{
return sub_401020();
}
// 401070: using guessed type __int64 sub_401070();
//----- (00000000004010D0) ----------------------------------------------------
// positive sp value has been detected, the output may be wrong!
void __fastcall __noreturn start(__int64 a1, __int64 a2, void (*a3)(void))
{
__int64 v3; // rax
int v4; // esi
__int64 v5; // [rsp-8h] [rbp-8h] BYREF
char *retaddr; // [rsp+0h] [rbp+0h] BYREF
v4 = v5;
v5 = v3;
_libc_start_main(
(int (__fastcall *)(int, char **, char **))main,
v4,
&retaddr,
(void (*)(void))_libc_csu_init,
_libc_csu_fini,
a3,
&v5);
__halt();
}
// 4010DA: positive sp value 8 has been found
// 4010E1: variable 'v3' is possibly undefined
//----- (0000000000401100) ----------------------------------------------------
void dl_relocate_static_pie()
{
;
}
//----- (0000000000401110) ----------------------------------------------------
char *deregister_tm_clones()
{
return &_bss_start;
}
// 404050: using guessed type char _bss_start;
//----- (0000000000401140) ----------------------------------------------------
__int64 register_tm_clones()
{
return 0LL;
}
//----- (0000000000401180) ----------------------------------------------------
char *_do_global_dtors_aux()
{
char *result; // rax
if ( !_bss_start )
{
result = deregister_tm_clones();
_bss_start = 1;
}
return result;
}
// 404050: using guessed type char _bss_start;
//----- (00000000004011B0) ----------------------------------------------------
__int64 frame_dummy()
{
return register_tm_clones();
}
//----- (00000000004011B6) ----------------------------------------------------
int __fastcall main(int argc, const char **argv, const char **envp)
{
int v4; // [rsp+10h] [rbp-10h] BYREF
int v5; // [rsp+14h] [rbp-Ch]
unsigned __int64 v6; // [rsp+18h] [rbp-8h]
v6 = __readfsqword(0x28u);
v5 = 0;
puts("\n\x1B[31m -----------Se le ha acabado el periodo de prueba gratuito-----------\n");
puts(a31mparaSeguirU);
do
{
banner();
__isoc99_scanf("%d", &v4);
if ( v4 == 3 )
exit(0);
if ( v4 > 3 )
goto LABEL_10;
if ( v4 == 1 )
{
comprar();
continue;
}
if ( v4 == 2 )
v5 = validar("%d");
else
LABEL_10:
puts("Opcion invalida, pruebe otra vez");
}
while ( !v5 );
puts(a32myaPuedesSeg);
return 0;
}
// 4010B0: using guessed type __int64 __isoc99_scanf(const char *, ...);
//----- (0000000000401291) ----------------------------------------------------
_BYTE *__fastcall encode(__int64 a1)
{
_BYTE *result; // rax
int i; // [rsp+14h] [rbp-4h]
for ( i = 0; i <= 33; ++i )
{
if ( *(char *)(i + a1) <= 96 || *(char *)(i + a1) > 122 )
{
if ( *(char *)(i + a1) <= 64 || *(char *)(i + a1) > 90 )
{
result = (_BYTE *)*(unsigned __int8 *)(i + a1);
*(_BYTE *)(i + a1) = (_BYTE)result;
}
else
{
result = (_BYTE *)(i + a1);
*result = (5 * ((char)*result - 65) + 8) % 26 + 65;
}
}
else
{
result = (_BYTE *)(i + a1);
*result = (5 * ((char)*result - 97) + 8) % 26 + 97;
}
}
return result;
}
//----- (00000000004013DB) ----------------------------------------------------
__int64 __fastcall validar(const char *a1)
{
int i; // [rsp+Ch] [rbp-64h]
char v3[48]; // [rsp+10h] [rbp-60h] BYREF
__int64 v4[6]; // [rsp+40h] [rbp-30h] BYREF
v4[5] = __readfsqword(0x28u);
qmemcpy(v4, "RisgAv{rIU_ihHwvIxA_sAppCsziq3vzC}", 34);
printf("\nIntroduce tu licencia: ");
__isoc99_scanf("%s", v3);
encode((__int64)v3);
for ( i = 0; i <= 33; ++i )
{
if ( v3[i] != *((_BYTE *)v4 + i) )
{
puts("\n\x1B[31mTu licencia es incorrecta\x1B[37m\n");
return 0LL;
}
}
puts("\n\x1B[32mEres un crack, lo conseguiste\x1B[37m");
return 1LL;
}
// 4010B0: using guessed type __int64 __isoc99_scanf(const char *, ...);
// 4013DB: using guessed type char var_60[48];
//----- (00000000004014CE) ----------------------------------------------------
int banner()
{
puts(" ___________OPCIONES___________");
puts(" | 1: Comprar licencia premium |");
puts(" | 2: Validar clave de licencia |");
puts(" | 3: Salir |");
puts(" ------------------------------");
return printf("> ");
}
//----- (0000000000401526) ----------------------------------------------------
int comprar()
{
return puts(aDirigaseANuest);
}
//----- (0000000000401540) ----------------------------------------------------
void __fastcall _libc_csu_init(unsigned int a1, __int64 a2, __int64 a3)
{
signed __int64 v3; // rbp
__int64 i; // rbx
init_proc();
v3 = &_do_global_dtors_aux_fini_array_entry - &_frame_dummy_init_array_entry;
if ( v3 )
{
for ( i = 0LL; i != v3; ++i )
(*(&_frame_dummy_init_array_entry + i))();
}
}
// 403E10: using guessed type __int64 (__fastcall *_frame_dummy_init_array_entry)();
// 403E18: using guessed type __int64 (__fastcall *_do_global_dtors_aux_fini_array_entry)();
//----- (00000000004015B0) ----------------------------------------------------
void _libc_csu_fini(void)
{
;
}
//----- (00000000004015B8) ----------------------------------------------------
void term_proc()
{
;
}
// nfuncs=33 queued=21 decompiled=21 lumina nreq=0 worse=0 better=0
// ALL OK, 21 function(s) have been successfully decompiled
Para resolver el juego y obtener una licencia válida, nos fijamos en el proceso de validación que se encuentra en la función validar (líneas 237 a 258). Esta función compara una entrada de licencia codificada con una licencia codificada almacenada en el programa.
La licencia almacenada es "RisgAv{rIU_ihHwvIxA_sAppCsziq3vzC}", y se utiliza la función encode (líneas 207 a 234) para codificar la entrada del usuario antes de compararla. La función encode aplica un cifrado simple a la entrada, alterando los caracteres alfabéticos según una fórmula específica.
La función de cifrado encode realiza lo siguiente:
Si el carácter es una letra minúscula (a-z), se convierte según la fórmula (5 * (char - 97) + 8) % 26 + 97.
Si el carácter es una letra mayúscula (A-Z), se convierte según la fórmula (5 * (char - 65) + 8) % 26 + 65.
Nos construimos una función en Python para decodificar la Flag y reto superado.
Hace tiempo que me aficioné a los retos de Hacking y Cracking, y si bien la mayoría de ellos consisten en desencriptar una clave o realizar ingeniería inversa sobre un ejecutable, también los hay sobre programación pura y dura.
En esta ocasión se nos proporciona un código «muestra» parecido a PHP o C++ y tenemos que ingeniarnoslas para mejorarlo y ganar a la máquina.
Objetivo del juego y normas
El objetivo de esta misión es ganar a Tr0n en su propio juego: las carreras de motos. Se te proporcionará un programa (código) funcional para que veas como se controla el vehiculo. Usando tu inteligencia, tendrás que entender su uso y mejorarlo, ya que no es lo suficientemente bueno como para ganar a Tr0n. Tr0n lleva ya bastante tiempo en la parrilla de juegos y es bastante habilidoso 🙂
Cuando venzas a Tr0n un mínimo de 5 veces consecutivas, se te dará por superada esta prueba.
Buena suerte!!!
[ Available functions / Funciones disponibles ]
direction() returns current direction, change to a new one with direction([newdir])
getX(), getY() returns X and Y coordinates
collisionDistance() | collisionDistance([anydir]) returns the distance until collision
Note: parameters [*dir] can be empty or one of this values: UP DOWN LEFT or RIGHT
[ Constants / Constantes ]
UP DOWN LEFT RIGHT MAX_X MAX_Y
[ Rules / Reglas ]
Try to survive driving your bike and … / Intenta sobrevivir conduciendo tu moto y…
Don’t cross any line / No cruces ninguna línea
or crash with the corners! / o choques con las esquinas!
[ Mission / Mision ]
Use well this controller and beat Tr0n 5 consecutive times to score in this game
Usa bien este controlador y vence a Tr0n 5 veces consecutivas para puntuar en este juego
Código inicial
Nada más comenzar vemos que hemos perdido nuestra primera partida con el siguiente código:
Lo primero que tenemos que modificar son las distancias de las coordenadas que estan puestas en «<10» al mínimo, que sería «<2«. También sustituir la aleatoriedad «rand(0,1)==0» por algo más útil y comenzar a usar la función «collisionDistance()«.
Como podéis observar en el código inferior, usamos la función «collisionDistance()» para detectar cuando estamos a punto de chocar «collisionDistance() ==1» y para detectar a que lado nos conviene más girar en función de donde podamos recorrer más distancia «if($c->collisionDistance([LEFT]) >2) $c->direction(LEFT); else $c->direction(RIGHT);«.
El código anterior de por sí no nos resuelve mucho si no afinamos un poco más, comprobando todos las posibles colisiones y tomando la dirección correcta en función de la mayor distancia a recorrer.
El código no es infalible ya que como comprabaréis vosotros mismos, no se puede ganar siempre por el mero hecho de la aleatoriedad y de la suerte. Cuando dispongais de un código decente, ejecutarlo varias veces para estar seguros antes de desecharlo.
Curiosidades
Como se suele decir, la banca siempre gana, y en este caso no iba a ser menos y es que en caso de empate ¡la banca gana!
Por último deciros que podéis utilizar el código ya que la web detecta los códigos ganadores para que no se repitan.
Para parchear un ejecutable realizado en .Net primero necesitamos ubicarnos. Abrimos IL Dasm y vamos al evento «Form_Load«, nos fijamos en los bytes y los buscamos con un editor hexadecimal. Fijaros bien en los bytes ya que siguen un orden específico, en la imágen del editor hexadecimal se aprecia perfectamente. Para que quede parcheada la Nag basta con sustituir los valores por ceros. Se parchea todo excepto el «RET (2A)».
Para la otra Nag sería lo mismo.
El algoritmo
El algoritmo es muy sencillo, consiste en la concatenación de varias palabras y un número aleatorio. El problema viene con el número aleatorio ya que lo tendremos que parchear para poder registrar el programa.
Buscamos el evento click en IL Dasm y nos fijamos que aparece el número «5F5E0FF» que en decimal equivale a «99999999«, buscamos los bytes en el editor hexadecimal y lo parcheamos a 1. De este modo anulamos la aletoriedad, ahora el número siempre es 1.
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 del año 2000 empacado y con un algoritmo aunque no muy complicado largo de tracear. Está empacado varias veces, algo poco habitual pero recordemos que es un crackme antiguo. Tras el empacado se encuentra Delphi.
Si lo pasamos por PEiD nos dice que Aspack 2.1, Exeinfo no está muy seguro y RDG packer detector en el escaneo avanzado nos encuentra Aspack, UPX y PE-Pack.
En principio nos enfrentamos a Aspack 2.1, abrimos el crackme con OllyDbg y vemos el típico PUSHAD.
Pulsamos F8 (Step Over) y a continuación click derecho sobre el registro ESP y Follow in DUMP.
Seleccionamos los primeros cuatro bytes útiles del dump y les ponemos un Breakpoint de Hardware, Access y Dword.
Pulsamos F9 y nos para aquí:
Ya tenemos a Aspack contra las cuerdas, pulsamos F8 hasta después del RETN para llegar al OEP (Original Entry Point).
Pero en el supuesto OEP vemos otro PUSHAD por lo que esto no ha terminado. Investigando un poco más vemos que la segunda capa se corresponde con PE-PACK 1.0. La estrategia a seguir es la misma, como ya tenemos el breakpoint puesto pulsamos F9 y nos para aquí:
Pulsamos F8 y nos llega a otro PUSHAD. Esta vez es UPX.
Pulsamos de nuevo F9 y paramos aquí:
Pulsamos F8 y esta vez si llegamos al OEP (4576EC).
A continuación vamos a dumpear el archivo en memoria. Vamos a plugins > OllyDumpEX, pulsamos sobre «Get EIP as OEP» y finalmente sobre «Dump«.
Minimizamos Olly (no cerrar), abrimos el programa ImportREC y seleccionamos el ejecutable «Sweeet1.exe».
Pegamos el OEP original (576EC), le damos a AutoSearch y a continuación a Get Imports.
Finalmente pulsamos Fix Dump y elegimos el ejecutable dumpeado anteriormente. Esto nos genera un ejecutable dumpeado que es el ejecutable válido.
Ahora PEiD nos dice que estamos tratando con un crackme hecho en Delphi.
Hemos pasado por tres capas de compresión casi idénticas, vamos a analizarlas.
El algoritmo
Cuando abrimos el crackme nos fijamos en que genera una key. Esta key se genera en función del disco duro desde el que se ejecuta.
Como la secuencia de generación del serial válido es larga os pongo lo más importante muy resumido y con ejemplos como siempre.
El serial es del siguiente tipo:
Serial = 1ªParte-2ªParte-3ªParte
Serial = 0000XXXXX-SerialCalculado-xxxx000Z8
Comprobación del tamaño del nombre
----------------------------------
........
00456EAA E8 01CCFAFF CALL sweeet1_Fix_dump_rebuilded.00403AB0
00456EAF 83F8 04 CMP EAX,4 ------------------------------------------------; Nombre >=4
00456EB2 7D 13 JGE SHORT sweeet1_Fix_dump_rebuilded.00456EC7
00456EB4 A1 08954500 MOV EAX,DWORD PTR DS:[sweeet1_Fix_dump_rebuilded.459508]
00456EB9 8B00 MOV EAX,DWORD PTR DS:[EAX]
00456EBB E8 0869FEFF CALL sweeet1_Fix_dump_rebuilded.0043D7C8
00456EC0 BB 01000000 MOV EBX,1
00456EC5 EB 15 JMP SHORT sweeet1_Fix_dump_rebuilded.00456EDC
00456EC7 83FB 25 CMP EBX,25
00456ECA 7D 0E JGE SHORT sweeet1_Fix_dump_rebuilded.00456EDA
00456ECC 83C3 32 ADD EBX,32
00456ECF 83C3 1E ADD EBX,1E
00456ED2 83EB 4F SUB EBX,4F
00456ED5 83FB 25 CMP EBX,25 -----------------------------------------------; Nombre <=25
00456ED8 ^ 7C F2 JL SHORT sweeet1_Fix_dump_rebuilded.00456ECC
00456EDA 33DB XOR EBX,EBX
00456EDC 33C0 XOR EAX,EAX
........
1ºBucle - Nuestro nombre (A)
----------------------------
........
00456F55 BE 1B000000 MOV ESI,1B -------------------------------; ESI = 1B
00456F5A EB 21 JMP SHORT sweeet1_dump_.00456F7D
00456F5C 8D55 D4 LEA EDX,[EBP-2C]
00456F5F A1 34A84500 MOV EAX,DWORD PTR DS:[sweeet1_dump_.45A8
00456F64 8B80 C4020000 MOV EAX,DWORD PTR DS:[EAX+2C4]
00456F6A E8 B5DAFCFF CALL sweeet1_dump_.00424A24
00456F6F 8B45 D4 MOV EAX,DWORD PTR SS:[EBP-2C]
00456F72 0FB64418 FF MOVZX EAX,BYTE PTR DS:[EBX+EAX-1]---------; Coje digito
00456F77 03F0 ADD ESI,EAX ------------------------------; digito + ESI
00456F79 43 INC EBX
00456F7A 0FAFF3 IMUL ESI,EBX ----------------------------; multiplica por i (bucle)
00456F7D 8D55 D4 LEA EDX,[EBP-2C]
........
2ºBucle - La key (B)
--------------------
........
00456F9C |. BF 1A000000 MOV EDI,1A -------------------------;EDI = 1A
00456FA1 |. BB 01000000 MOV EBX,1
00456FA6 |. EB 1E JMP SHORT sweeet1_.00456FC6
00456FA8 |> 8D55 D4 /LEA EDX,[LOCAL.11]
00456FAB |. A1 34A84500 |MOV EAX,DWORD PTR DS:[45A834]
00456FB0 |. 8B80 D0020000 |MOV EAX,DWORD PTR DS:[EAX+2D0]
00456FB6 |. E8 69DAFCFF |CALL sweeet1_.00424A24
00456FBB |. 8B45 D4 |MOV EAX,[LOCAL.11]
00456FBE |. 0FB64418 FF |MOVZX EAX,BYTE PTR DS:[EAX+EBX-1]--;Coje dígito
00456FC3 |. 03F8 |ADD EDI,EAX -----------------------;Suma dígito a dígito
00456FC5 |. 43 |INC EBX
00456FC6 |> 8D55 D4 LEA EDX,[LOCAL.11]
00456FC9 |. A1 34A84500 |MOV EAX,DWORD PTR DS:[45A834]
00456FCE |. 8B80 D0020000 |MOV EAX,DWORD PTR DS:[EAX+2D0]
00456FD4 |. E8 4BDAFCFF |CALL sweeet1_.00424A24
00456FD9 |. 8B45 D4 |MOV EAX,[LOCAL.11]
00456FDC |. E8 CFCAFAFF |CALL sweeet1_.00403AB0
00456FE1 |. 3BD8 |CMP EBX,EAX
00456FE3 |.^ 7C C3 \JL SHORT sweeet1_.00456FA8
........
Generación del serial central
-----------------------------
........
00456FE5 |. B9 01000000 MOV ECX,1
00456FEA |. BB 01000000 MOV EBX,1
00456FEF |. 8BC7 MOV EAX,EDI
00456FF1 |. F7EE IMUL ESI ----------; C = A * B
00456FF3 |. 99 CDQ
........
00456FFD |. 2345 E8 AND EAX,[LOCAL.6]--; D = A and C
00457000 |. 2355 EC AND EDX,[LOCAL.5]
00457003 |. 8945 E8 MOV [LOCAL.6],EAX
00457006 |. 8955 EC MOV [LOCAL.5],EDX
........
00457032 |. 8BC7 MOV EAX,EDI
00457034 |. 99 CDQ
00457035 |. 0345 E8 ADD EAX,[LOCAL.6]--; E = D + B
00457038 |. 1355 EC ADC EDX,[LOCAL.5]
0045703B |. 8945 E0 MOV [LOCAL.8],EAX
0045703E |. 8955 E4 MOV [LOCAL.7],EDX
........
00405732 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10]
00405736 F72424 MUL DWORD PTR SS:[ESP]
00405739 8BC8 MOV ECX,EAX
0040573B 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4]
0040573F F76424 0C MUL DWORD PTR SS:[ESP+C]------; F = B * D
00405743 03C8 ADD ECX,EAX
00405745 8B0424 MOV EAX,DWORD PTR SS:[ESP]
00405748 F76424 0C MUL DWORD PTR SS:[ESP+C]------; G = A * F
........
0045705E |. 0B0424 OR EAX,DWORD PTR SS:[ESP]-----; Serial central = G or A
........
00457077 |. E8 FC07FBFF CALL sweeet1_.00407878
0045707C |. 8B45 F8 MOV EAX,[LOCAL.2]-------------; EAX = Serial central
........
004570D1 |. E8 A207FBFF CALL sweeet1_.00407878
004570D6 |. 8B45 D0 MOV EAX,[LOCAL.12]
004570D9 |. E8 D2C9FAFF CALL sweeet1_.00403AB0--------; Obtiene longitud del serial central en hexa
004570DE |. 8BD8 MOV EBX,EAX
........
004570D1 |. E8 A207FBFF CALL sweeet1_.00407878--------;*Nota
*Nota:
A partir de aquí genera la primera y tercera parte del serial de la siguiente manera:
Serial = 1ªParte-2ªParte-3ªParte
Serial = 0000XXXXX-SerialCalculado-xxxx000Z8
1ºParte = 3ºdigSerial+1ºdigSerial+2ºdigSerial+3ºdigSerial+4ºdigNombreMayu+2ºdigNombreMayu+5ºdigNombreMayu+1ºdigNombreMayu+3ºdigNombreMayu
3ºParte = 3ºdigNombreMin+1ºdigNombreMin+4ºdigNombreMin+2ºdigNombreMin+Tamaño Serial_2ªParte en Hex y de tres dígitos+Z8
Ejemplo:
Nombre: deurus
Key: C0C0A000
Serial: 6906REUDU-906297047918-udre00CZ8
1) A = 23A2A (Con nuestro nombre empezando por 1B se lo suma a ESI y se lo multiplica por i (la que toque cada vez))
2) B = 1A1 (Con nuestra Key empezando por 1A va sumando los digitos)
3) C = B * A = 3A0BE6A
4) D = A and C = 3A2A
5) E = D + B = 3BCB (Offset 457035)
6) F = B * D = 5EBE6A (Offset 48704A)
7) G = A * F = D303834164
8) Serial = G or A (Serial = D303834164 or 23A2A = D303837B6E (906297047918))
A tener en cuenta:
1ªParte del serial siempre mayúsculas.
2ªParte siempre numérico. Usa el registro de 64 bits (Qword) con signo.**Nota
Los retos de criptografía pueden ser muy variados como he dicho anteriormente. El secreto suele estar en saber a que te enfrentas y posteriormente construir una herramienta para descifrarlo o usar una ya existente (la mayoría de los casos).
Una web con la que suelo resolver la mayoría de retos es dcode.fr. Si os fijáis en el enlace, la lista de categorías asciende a 48 y disponéis de unos 800 algoritmos para rebanaros los sesos.
A continuación veamos unos cuantos retos que podéis encontrar por la red. Cabe destacar que normalmente el título del reto dice mucho del algoritmo.
Solución: Aquí nuestro primer impulso es utilizar fuerza bruta a MD5, pero cuando nos damos contra la pared el siguiente candidato es LAN Manager. Aquí la opción que más os guste, Cain, John The Ripper, etc.
Con John The Ripper tenemos que preparar un archivo de texto del estilo: deurus.info:1011:4C240DDAB17D1796AAD3B435B51404EE:4C240DDAB17D1796AAD3B435B51404EE:::
Solución: Para la primera parte la conversión es directa. Para la segunda, la dificultad reside en darse cuenta que hay que separar en grupos de cinco y decodificar por separado.
Conversiones, cifra clásica, hash, simétricos, asimétricos, combinaciones de varios algoritmos y un largo etcetera. Como veis los hay para todos los gustos, ten en cuenta que aquí os muestro una pequeñísima parte de lo que os encontrareis en las webs de retos, pero para despertar la curiosidad es suficiente.
Hoy tenemos aquí otro crackme sacado del baúl de los recuerdos. En este caso se trata de una protección por tiempo límite a través de un keyfile llamado «data.det«. Disponemos de tres días o nueve sesiones antes de que el crackme expire.
El algoritmo
La primera vez que ejecutamos el crackme, crea el fichero «data.det» y realiza lo siguiente:
Lee el fichero data.det que inicialmente tiene 10 bytes a cero y el último byte un 60(`).
Comprueba que tenga 11 bytes (B) y continúa.
Al detectar el fichero vacío le mete valores codificandolos con XOR 6969. Los almacena en memoria 4030AB y siguientes.
En cada ejecución realiza tres comprobaciones.
Recordemos el contenido del fichero:
B7 6E 63 69 6D 69 6B 69 68 69 60 ·ncimikihi`
1) Mes y año (4 primeros bytes)
004010A8 |> \8B0D AB304000 MOV ECX,DWORD PTR DS:[4030AB] ; ECX=69636EB7
004010AE |. 81F1 69696969 XOR ECX,69696969 ; 69636EB7 xor 69696969 = A07DE (A = mes y 7DE = año)
004010B4 |. A1 E4304000 MOV EAX,DWORD PTR DS:[4030E4]
004010B9 |. 3BC1 CMP EAX,ECX ; Compara con mes y año actuales
004010BB |. 0F85 85000000 JNZ timetria.00401146 ; Bad boy
2) Día (7º y 8º byte)
004010C1 |. 66:8B0D B1304000 MOV CX,WORD PTR DS:[4030B1] ; CX = 696B
004010C8 |. 66:81F1 6969 XOR CX,6969 ; 696B xor 6969 = 2
004010CD |. 66:A1 EA304000 MOV AX,WORD PTR DS:[4030EA] ; AX = día actual obtenido con GetSystemTime
004010D3 |. 66:2BC1 SUB AX,CX ; Los resta
004010D6 |. 66:83F8 03 CMP AX,3 ; Compara con 3
004010DA |. 77 6A JA SHORT timetria.00401146 ; Si el resultado >=3 Bad Boy
3) Sesiones (11º byte)
004010DC |. 2805 00304000 SUB BYTE PTR DS:[403000],AL ;
004010E2 |> A0 B5304000 MOV AL,BYTE PTR DS:[4030B5] ; AL = numero de sesiones actual
004010E7 |. 34 69 XOR AL,69 ; 61 Xor 69 = 8
004010E9 |. 3C 00 CMP AL,0 ; Compara con 0
004010EB |. 74 59 JE SHORT timetria.00401146 ; Salta si hemos superado las 9 sesiones. Bad boy
004010ED |. FEC8 DEC AL ; Si no le resta 1
004010EF |. A2 01304000 MOV BYTE PTR DS:[403001],AL
004010F4 |. 34 69 XOR AL,69 ; y le hace xor 69 para codificar el nuevo valor de sesión
004010F6 |. A2 B5304000 MOV BYTE PTR DS:[4030B5],AL
Con esto ya podemos alterar el archivo a nuestro antojo sin necesidad de parchear.
Keygen
Try
ano = ano Xor 26985
mes = mes Xor 26985
dia = dia Xor 26985
anos = Hex(ano).ToString
mess = Hex(mes).ToString
dias = Hex(dia).ToString
If txtsesiones.Text <= 255 Then
sesioness = Hex(sesiones)
Else
sesiones = 255
End If
sesioness = Hex(sesiones)
'key = 00 00 00 00 00 00 00 00 00 00 00
'key = año+año+mes+mes+X+X+dia+dia+X+sesiones
key = Chr(Convert.ToInt32(anos.Substring(2, 2), 16)) & Chr(Convert.ToInt32(anos.Substring(0, 2), 16)) _
& Chr(Convert.ToInt32(mess.Substring(2, 2), 16)) & Chr(Convert.ToInt32(mess.Substring(0, 2), 16)) _
& Chr(106) & Chr(105) _
& Chr(Convert.ToInt32(dias.Substring(2, 2), 16)) & Chr(Convert.ToInt32(dias.Substring(0, 2), 16)) _
& Chr(103) & Chr(105) _
& Chr(Convert.ToInt32(sesioness.Substring(0, 2), 16))
'Creo el archivo llave
Dim ruta As String = Application.StartupPath & "\DATA.DET"
If File.Exists(ruta) Then
File.Delete(ruta)
End If
Using sw As StreamWriter = New StreamWriter(ruta, True, System.Text.Encoding.Default)
sw.Write(key)
sw.Close()
End Using
MsgBox("DATA.DET generado correctamente", MsgBoxStyle.Information + MsgBoxStyle.OkOnly, "Info")
Catch ex As Exception
MsgBox("Ocurrió algún error" & vbCrLf & ex.Message)
End Try
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.
Realistic Challenge 4: There is a site offering protection against hackers to website owners, the service is far too overpriced and the people running the service don’t know anything about security. Look around their site, and see how protected it is.
Hay un sitio que ofrece protección contra los hackers. El servicio tiene un precio abusivo, echa un vistazo a la web y evalúa su pretección.
Analizando a la víctima
Vemos un escueto menú pero con cosas interesantes.
Pinchamos sobre «Testimonials» y a continuación en «Customer 1»
Vemos que hay solo 3 «customers», vamos a introducir manualmente un 5 haber que pasa.
Ok, nos genera el siguiente error.
Probamos ahora con un enlace interno que nos genera el siguiente error.
Tenemos un directorio interesante «secure«, si entramos en el nos salta un Login típico protegido con «.htaccess«. Lo lógico a continuación es hacernos con el archivo «.htpasswd«
Una vez obtenido el contenido del archivo «.htpasswd» lo siguiente es crackear el password con John the Ripper. Nos logueamos en la carpeta secure y reto superado.
Hace poco me reencontré con esta entrañable serie que tanto me entretuvo cuando era pequeño y para mi sorpresa, me percaté de que nunca había visto el episodio piloto. La nostalgia me llevó a tragarme el episodio entero y a disfrutar a lo grande de la parafernalia técnica de la que hace gala para justificar la creación que da nombre a la serie.
La visión tecnológica de los años 80
Esto hay que analizarlo con perspectiva. Estamos en los años 80 y nos están presentando un coche capaz de mantener una conversación, es decir, nos están presentando una inteligencia artificial (IA) llamada KITT. Puede parecer que el término inteligencia artificial es nuevo pero realmente se acuño en 1956 por John McCarthy. A partir de ese momento surgieron líneas de estudio e hipótesis pero a partir de los 70 se puede considerar que la investigación sobre la IA perdió financiación y quedó en el congelador hasta los años 90. Dicho esto, cuando nos presentan a KITT lo hacen de la siguiente manera:
Devon Miles: Está totalmente controlado por microprocesadores que hacen físicamente imposible que se vea implicado en ningún tipo de colisión o percance a no ser que se lo ordene su piloto específicamente
Michael Knight: ¿Piloto?, no me diga que esta cosa vuela
Devon Miles: ¡No!, pero piensa
Michael Knight: ¿Piensa?, ¿mi coche piensa?
Intel daba a conocer el primer microprocesador allá por el 71 y la serie se estrenó en el 82 lo que le da credibilidad en ese aspecto, aunque dudo que el público de esa época supiera que era un microprocesador, un ordenador y menos una IA.
Los Chips
La serie arranca con un grupo de personas realizando espionaje industrial donde nos muestran las hojas de datos de dos chips Japoneses como son el PD8257-5 y el PD780. Un aplauso para los guionistas y sus asesores ya que el PD8257-5 es una interfaz de comunicaciones y el PD780 un microprocesador de 8 bits.
Detalle del esquema del chip PD8257-5 y del set de instrucciones del chip PD780
Lo más interesante es que lo que se muestra es real como podéis apreciar en la siguiente imagen
Detalle del esquema mostrado en la serie VS la hoja de datos
A continuación un detalle de las capturas realizadas:
Más adelante vuelven a aparecer imágenes en un PC que parecen puestas en post-producción y que son robadas en un maravilloso disco de 5 1/4.
Los diálogos
Llaman la atención mucho los diálogos centrados en el microprocesador como si de un ser superior se tratase, éste es la referencia continua y la parte central del guion de los dos primeros capítulos. Curiosamente aparecen en pantalla multitud de imágenes de circuitos integrados pero no se llega a ver ningún microprocesador. Por otro lado, es interesante el esfuerzo que hacen los guionistas por que llamemos a KITT él en vez de ello, convirtiendo al coche en un personaje más.
Otra cosa que llama mucho la atención son los tópicos de los que hace gala como la asociación de los microprocesadores a los videojuegos o que la empresa villana esté afincada en Silicon Valley. Incluso el nombre KITT es un tópico ya que las siglas vienen de Knight Industries Two Thousand que en cristiano quiere decir Industrias Knight 2000. Y es que en mi opinión el año 2000 se imaginaba como una barrera lejana en la que todo iba a ser tecnológicamente más avanzado.
Conclusiones
Tengo que reconocer que me ha sorprendido que dieran realismo a los chips mostrados teniendo en cuenta que aparecen muy pocos segundos en pantalla y podían haber puesto cualquier cosa.
Por otro lado, la realidad es que en el año 2022 aún nos queda recorrido para llegar a tener un coche fantástico y lo más parecido que tenemos hoy día sería un Tesla con Alexa.
Aquí tenemos un Crackme clásico creado por Scarebyte hallá por el año 2000 y que cuenta con varias fases siendo un crackme muy interesante para iniciarse o simplemente para divertirse. Al estar realizado en Delphi, los apartados de las checkboxes y de las trackbars se simplifican y mucho, pero aún así hay que currarselo un poco para dejar todo bien atado. Si os fijáis en las soluciones que aparecen en crackmes.de, en aquellos años se usaba DEDE y aunque yo usaré otra herramienta, DEDE sigue siendo igual de útil.
Desempacado
PEiD nos dice que nos enfrentamos a ASPack 1.08.03 -> Alexey Solodovnikov, así que vamos al lío.
Eliminar la NAG
Tan sencillo como poner un Breakpoint a User32.MessageBoxA. La llamada a NOPear está en la dirección 441CF2.
Password
Desde las string references localizamos los mensajes de chico bueno y chico malo que nos llevan al código a analizar.
0044C3CD |. E8 5294FDFF CALL CrackMe_.00425824
0044C3D2 |. 8B45 FC MOV EAX,[LOCAL.1]
0044C3D5 |. E8 9A76FBFF CALL CrackMe_.00403A74
0044C3DA |. 83F8 0C CMP EAX,0C ; Lengh C = 12
0044C3DD |. 0F85 53010000 JNZ CrackMe_.0044C536 ; Salto a chico malo
0044C3E3 |. 8D55 FC LEA EDX,[LOCAL.1]
0044C3E6 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C3EC |. E8 3394FDFF CALL CrackMe_.00425824
0044C3F1 |. 8B45 FC MOV EAX,[LOCAL.1]
0044C3F4 |. 8038 43 CMP BYTE PTR DS:[EAX],43 ; 1º dígito serial = C
0044C3F7 |. 0F85 27010000 JNZ CrackMe_.0044C524 ; Salto a chico malo
0044C3FD |. 8D55 F8 LEA EDX,[LOCAL.2]
0044C400 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C406 |. E8 1994FDFF CALL CrackMe_.00425824
0044C40B |. 8B45 F8 MOV EAX,[LOCAL.2]
0044C40E |. 8078 03 6F CMP BYTE PTR DS:[EAX+3],6F ; 4º dígito serial = o
0044C412 |. 0F85 0C010000 JNZ CrackMe_.0044C524 ; Salto a chico malo
0044C418 |. 8D55 F4 LEA EDX,[LOCAL.3]
0044C41B |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C421 |. E8 FE93FDFF CALL CrackMe_.00425824
0044C426 |. 8B45 F4 MOV EAX,[LOCAL.3]
0044C429 |. 8078 08 6F CMP BYTE PTR DS:[EAX+8],6F ; 9º dígito serial = o
0044C42D |. 0F85 F1000000 JNZ CrackMe_.0044C524 ; Salto a chico malo
0044C433 |. 8D55 F0 LEA EDX,[LOCAL.4]
0044C436 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C43C |. E8 E393FDFF CALL CrackMe_.00425824
0044C441 |. 8B45 F0 MOV EAX,[LOCAL.4]
0044C444 |. 8078 01 6C CMP BYTE PTR DS:[EAX+1],6C ; 2º dígito serial = l
0044C448 |. 0F85 D6000000 JNZ CrackMe_.0044C524 ; Salto a chico malo
0044C44E |. 8D55 EC LEA EDX,[LOCAL.5]
0044C451 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C457 |. E8 C893FDFF CALL CrackMe_.00425824
0044C45C |. 8B45 EC MOV EAX,[LOCAL.5]
0044C45F |. 8078 04 20 CMP BYTE PTR DS:[EAX+4],20 ; 5º dígito serial = espacio
0044C463 |. 0F85 BB000000 JNZ CrackMe_.0044C524 ; Salto a chico malo
0044C469 |. 8D55 E8 LEA EDX,[LOCAL.6]
0044C46C |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C472 |. E8 AD93FDFF CALL CrackMe_.00425824
0044C477 |. 8B45 E8 MOV EAX,[LOCAL.6]
0044C47A |. 8078 0A 52 CMP BYTE PTR DS:[EAX+A],52 ; 11º dígito serial = R
0044C47E |. 0F85 A0000000 JNZ CrackMe_.0044C524 ; Salto a chico malo
0044C484 |. 8D55 E4 LEA EDX,[LOCAL.7]
0044C487 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C48D |. E8 9293FDFF CALL CrackMe_.00425824
0044C492 |. 8B45 E4 MOV EAX,[LOCAL.7]
0044C495 |. 8078 07 75 CMP BYTE PTR DS:[EAX+7],75 ; 8º dígito serial = u
0044C499 |. 0F85 85000000 JNZ CrackMe_.0044C524 ; Salto a chico malo
0044C49F |. 8D55 E0 LEA EDX,[LOCAL.8]
0044C4A2 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C4A8 |. E8 7793FDFF CALL CrackMe_.00425824
0044C4AD |. 8B45 E0 MOV EAX,[LOCAL.8]
0044C4B0 |. 8078 09 6E CMP BYTE PTR DS:[EAX+9],6E ; 10º dígito serial = n
0044C4B4 |. 75 6E JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo
0044C4B6 |. 8D55 DC LEA EDX,[LOCAL.9]
0044C4B9 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C4BF |. E8 6093FDFF CALL CrackMe_.00425824
0044C4C4 |. 8B45 DC MOV EAX,[LOCAL.9]
0044C4C7 |. 8078 02 6E CMP BYTE PTR DS:[EAX+2],6E ; 3º dígito serial = n
0044C4CB |. 75 57 JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo
0044C4CD |. 8D55 D8 LEA EDX,[LOCAL.10]
0044C4D0 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C4D6 |. E8 4993FDFF CALL CrackMe_.00425824
0044C4DB |. 8B45 D8 MOV EAX,[LOCAL.10]
0044C4DE |. 8078 05 69 CMP BYTE PTR DS:[EAX+5],69 ; 6º dígito serial = i
0044C4E2 |. 75 40 JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo
0044C4E4 |. 8D55 D4 LEA EDX,[LOCAL.11]
0044C4E7 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C4ED |. E8 3293FDFF CALL CrackMe_.00425824
0044C4F2 |. 8B45 D4 MOV EAX,[LOCAL.11]
0044C4F5 |. 8078 0B 6E CMP BYTE PTR DS:[EAX+B],6E ; 12º dígito serial = n
0044C4F9 |. 75 29 JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo
0044C4FB |. 8D55 D0 LEA EDX,[LOCAL.12]
0044C4FE |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C504 |. E8 1B93FDFF CALL CrackMe_.00425824
0044C509 |. 8B45 D0 MOV EAX,[LOCAL.12]
0044C50C |. 8078 06 67 CMP BYTE PTR DS:[EAX+6],67 ; 7º dígito serial = g
0044C510 |. 75 12 JNZ SHORT CrackMe_.0044C524 ; Salto a chico malo
0044C512 |. BA 78C54400 MOV EDX,CrackMe_.0044C578 ; ASCII "Right Password"
0044C517 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C51D |. E8 3293FDFF CALL CrackMe_.00425854
0044C522 |. EB 22 JMP SHORT CrackMe_.0044C546
0044C524 |> BA 90C54400 MOV EDX,CrackMe_.0044C590 ; ASCII "Wrong Password"
0044C529 |. 8B83 E8020000 MOV EAX,DWORD PTR DS:[EBX+2E8]
0044C52F |. E8 2093FDFF CALL CrackMe_.00425854
0044C534 |. EB 10 JMP SHORT CrackMe_.0044C546
0044C536 |> BA 90C54400 MOV EDX,CrackMe_.0044C590 ; ASCII "Wrong Password"
Chequeo rápido
ABCD EFGHIJK
Clno iguonRn
; 1º dígito serial = C
; 4º dígito serial = o
; 9º dígito serial = o
; 2º dígito serial = l
; 5º dígito serial = espacio
; 11º dígito serial = R
; 8º dígito serial = u
; 10º dígito serial = n
; 3º dígito serial = n
; 6º dígito serial = i
; 12º dígito serial = n
; 7º dígito serial = g
Básicamente chequea la frase «Cool Running» de forma desordenada como se ve justo encima, siendo el password correcto «Clno iguonRn«. Os dejo el código para que lo analicéis.
Nº serie asociado a un nombre
De nuevo con las string references localizamos el código.
0044C648 /. 55 PUSH EBP
0044C649 |. 8BEC MOV EBP,ESP
0044C64B |. 83C4 F8 ADD ESP,-8
0044C64E |. 53 PUSH EBX
0044C64F |. 56 PUSH ESI
0044C650 |. 33C9 XOR ECX,ECX
0044C652 |. 894D F8 MOV [LOCAL.2],ECX
0044C655 |. 8BF0 MOV ESI,EAX
0044C657 |. 33C0 XOR EAX,EAX
0044C659 |. 55 PUSH EBP
0044C65A |. 68 83C74400 PUSH CrackMe_.0044C783
0044C65F |. 64:FF30 PUSH DWORD PTR FS:[EAX]
0044C662 |. 64:8920 MOV DWORD PTR FS:[EAX],ESP
0044C665 |. 33C0 XOR EAX,EAX
0044C667 |. 8945 FC MOV [LOCAL.1],EAX
0044C66A |. A1 80F84400 MOV EAX,DWORD PTR DS:[44F880] ; Eax = Nombre
0044C66F |. E8 0074FBFF CALL CrackMe_.00403A74
0044C674 |. 83F8 06 CMP EAX,6 ; Cmp lengh nombre con 6
0044C677 |. 0F8E F0000000 JLE CrackMe_.0044C76D ; Salta si <= 6
0044C67D |. A1 80F84400 MOV EAX,DWORD PTR DS:[44F880] ; Eax = Nombre
0044C682 |. E8 ED73FBFF CALL CrackMe_.00403A74
0044C687 |. 83F8 14 CMP EAX,14 ; Cmp lengh nombre con 20 (14h)
0044C68A |. 0F8D DD000000 JGE CrackMe_.0044C76D ; salta si >= 20
0044C690 |. A1 80F84400 MOV EAX,DWORD PTR DS:[44F880]
0044C695 |. E8 DA73FBFF CALL CrackMe_.00403A74
0044C69A |. 85C0 TEST EAX,EAX
0044C69C |. 7E 17 JLE SHORT CrackMe_.0044C6B5
0044C69E |. BA 01000000 MOV EDX,1
0044C6A3 |> 8B0D 80F84400 /MOV ECX,DWORD PTR DS:[44F880] ; Bucle in
0044C6A9 |. 0FB64C11 FF |MOVZX ECX,BYTE PTR DS:[ECX+EDX-1]
0044C6AE |. 014D FC |ADD [LOCAL.1],ECX ; Suma dig nombre y guarda en 12FBC4
0044C6B1 |. 42 |INC EDX
0044C6B2 |. 48 |DEC EAX
0044C6B3 |.^ 75 EE \JNZ SHORT CrackMe_.0044C6A3 ; Bucle out
0044C6B5 |> A1 84F84400 MOV EAX,DWORD PTR DS:[44F884] ; Eax = Compañia
0044C6BA |. E8 B573FBFF CALL CrackMe_.00403A74
0044C6BF |. 83F8 02 CMP EAX,2 ; Cmp lengh compañia con 2
0044C6C2 |. 7E 18 JLE SHORT CrackMe_.0044C6DC ; Salta si <= 2
0044C6C4 |. A1 84F84400 MOV EAX,DWORD PTR DS:[44F884] ; Eax = Compañia
0044C6C9 |. E8 A673FBFF CALL CrackMe_.00403A74
0044C6CE |. 83F8 08 CMP EAX,8 ; Cmp lengh compañia con 8
0044C6D1 |. 7D 09 JGE SHORT CrackMe_.0044C6DC ; Salta si >= 8
0044C6D3 |. 8B45 FC MOV EAX,[LOCAL.1] ; Eax = sum nombre
0044C6D6 |. 6BC0 02 IMUL EAX,EAX,2 ; Sum nombre * 2
0044C6D9 |. 8945 FC MOV [LOCAL.1],EAX
0044C6DC |> 68 98C74400 PUSH CrackMe_.0044C798 ; ASCII "I Love Cracking and "
0044C6E1 |. 8D55 F8 LEA EDX,[LOCAL.2]
0044C6E4 |. 8B45 FC MOV EAX,[LOCAL.1]
0044C6E7 |. E8 68B0FBFF CALL CrackMe_.00407754
0044C6EC |. FF75 F8 PUSH [LOCAL.2] ; sum del nombre
0044C6EF |. 68 B8C74400 PUSH CrackMe_.0044C7B8 ; ASCII " Girls ;)"
0044C6F4 |. B8 8CF84400 MOV EAX,CrackMe_.0044F88C
0044C6F9 |. BA 03000000 MOV EDX,3
0044C6FE |. E8 3174FBFF CALL CrackMe_.00403B34 ; Concatena 1º frase + sum nombre + 2ºfrase
0044C703 |. 33C0 XOR EAX,EAX
0044C705 |. 8945 FC MOV [LOCAL.1],EAX
0044C708 |. A1 88F84400 MOV EAX,DWORD PTR DS:[44F888] ; Eax = Serial
0044C70D |. E8 6273FBFF CALL CrackMe_.00403A74
0044C712 |. 8BD8 MOV EBX,EAX
0044C714 |. A1 8CF84400 MOV EAX,DWORD PTR DS:[44F88C]
0044C719 |. E8 5673FBFF CALL CrackMe_.00403A74
0044C71E |. 3BD8 CMP EBX,EAX ; Compara tamaño frase con tamaño serial
0044C720 |. 75 4B JNZ SHORT CrackMe_.0044C76D
0044C722 |. A1 88F84400 MOV EAX,DWORD PTR DS:[44F888]
0044C727 |. E8 4873FBFF CALL CrackMe_.00403A74
0044C72C |. 85C0 TEST EAX,EAX
0044C72E |. 7E 27 JLE SHORT CrackMe_.0044C757
0044C730 |. BA 01000000 MOV EDX,1
0044C735 |> 8B0D 88F84400 /MOV ECX,DWORD PTR DS:[44F888] ; Bucle in -->
0044C73B |. 0FB64C11 FF |MOVZX ECX,BYTE PTR DS:[ECX+EDX-1]
0044C740 |. 034D FC |ADD ECX,[LOCAL.1]
0044C743 |. 8B1D 8CF84400 |MOV EBX,DWORD PTR DS:[44F88C]
0044C749 |. 0FB65C13 FF |MOVZX EBX,BYTE PTR DS:[EBX+EDX-1] ; Compara dígito a dígito nuestro serial
0044C74E |. 2BCB |SUB ECX,EBX ; con la concatenación anterior
0044C750 |. 894D FC |MOV [LOCAL.1],ECX
0044C753 |. 42 |INC EDX
0044C754 |. 48 |DEC EAX
0044C755 |.^ 75 DE \JNZ SHORT CrackMe_.0044C735 ; <-- Bucle out
0044C757 |> 837D FC 00 CMP [LOCAL.1],0
0044C75B |. 75 10 JNZ SHORT CrackMe_.0044C76D ; Salta si algo ha ido mal
0044C75D |. 8B86 14030000 MOV EAX,DWORD PTR DS:[ESI+314]
0044C763 |. BA CCC74400 MOV EDX,CrackMe_.0044C7CC ; "You have found the correct Serial :)"
En resumen
Tamaño del nombre entre 7 y 19.
Tamaño de la compañía entre 3 y 7 aunque no interviene en el serial.
Suma los valores ascii de los dígitos del nombre y lo multiplica por 2.
Concatena «I Love Cracking and » + «sum del nombre» + » Girls ;)».
Checkbox
Para afrontar esta parte del reto vamos a usar una herramienta llamada Interactive Delphi Reconstructoro IDR. En su día la mejor herramienta era DEDE, pero IDR a mi parecer es algo más potente.
Básicamente IDR nos permite sin quebraderos de cabeza localizar el código del botón que comprueba la secuencia de checkboxes correcta. Cargamos el crackme en IDR y dentro de la pestaña «Units (F2)«, abajo del todo hacemos doble click sobre «F Crack» y vemos que nos muestra todos los controles del formulario. El botón que nos interesa se llama «SpeedButton3«.
Si hacemos doble click sobre el nos muestra el código que se muestra a continuación.
Como podéis apreciar, las checkboxes involucradas son la 3, 5, 6, 9, 11, 12, 13, 15, 19 y 20. Solo nos falta saber cuales se corresponden con esa numeración y aquí ya depende de cada uno, yo en su día saqué los números a mano mediante el orden de tabulación, pero ya que tenemos IDR, el nos va a dar la solución de una forma sencilla y rápida.
Vamos a la pestaña «Forms (F5)«, seleccionamos la opción Form y hacemos doble click sobre el formulario.
Veréis que aparece el formulario con todos los recursos, incluso los puedes modificar. Localizar los checkboxes ahora es un juego de niños.
Os dejo un vídeo.
Trackbar
De nuevo, con la ayuda de IDR, localizamos la parte del código y analizamos su funcionamiento. Esta parte es la más divertida ya que requiere de un keygen pero en vez de coger el número de serie de una caja de texto lo obtiene de 5 trackbars como muestra la siguiente imagen.
1) Siendo nuestro serial : 1 2 3 4 5
a b c d e
2) Realiza las operaciones matemáticas:
Round(((Cos(sqrt(b^3+5)) + (-sqrt(a+1)) + Ln(c*3+1) + (-sqrt(d+2)) + ((e*3)/2))+0.37)*1000))
3) Obtenemos un hash resultante de 5415
4) XORea los dígitos de la siguiente manera:
(5)35 xor 86 = B6
(4)34 xor 83 = BD
(1)31 xor 86 = B7
(5)35 xor 8D = B8
De modo que tenemos B6BDB7B8
5) Compara B6BDB7B8 con B5BAB2BA
6) Revertimos el XOR para obtener el hash bueno
B5 xor 86 = 36(6)
BA xor 83 = 33(3)
B2 xor 86 = 34(4)
BA xor 8D = 37(7)
Luego el hash bueno es 6347
7) Debemos hacer fuerza bruta buscando:
Round(((Cos(sqrt(b^3+5)) + (-sqrt(a+1)) + Ln(c*3+1) + (-sqrt(d+2)) + ((e*3)/2))+0.37)*1000)) = 6347
Para obtener los seriales válidos podemos hacer bucles recursivos hasta recorrer las 10^5 opciones posibles. Una forma de hacerlo en VBNet es la siguiente.
Dim tmp As Double
Dim an, bn, cn, dn, en As Integer
For an = 0 To 9
For bn = 0 To 9
For cn = 0 To 9
For dn = 0 To 9
For en = 0 To 9
tmp = Round(((Cos(Sqrt((Pow(bn, 3)) + 5)) + (-Sqrt(an + 1)) + Log(cn * 3 + 1) + (-Sqrt(dn + 2)) + ((en * 3) / 2) + 0.37) * 1000))
txtdebug.Text = "a-b-c-d-e = Hash || " & an & "-" & bn & "-" & cn & "-" & dn & "-" & en & " = " & tmp
If tmp = 6347 Then
ListBox1.Items.Add("Serial: " & an & bn & cn & dn & en)
End If
Application.DoEvents()
Next
Next
Next
Next
Next
Os dejo como siempre el crackme y el keygen en los enlaces.
Es un crackme realizado en ensamblador y en el que el objetivo es remover la NAG de la forma más limpia posible.
Analizando a la víctima
Abrimos el crackme con Olly y ya a simple vista vemos los mensajes de la Nag y parte del código interesante. Si necesitaramos localizar la Nag podemos mirar en las intermodular calls las típicas subrutinas, en este caso se ve claramente a MessageBoxA, bastaría con poner un breakpoint para localizar quien llama.
Encima de SetDlgItemTextA vemos el código que analiza si la Nag tiene que aparecer.
004010E6 |. E8 C4000000 CALL Nag1.004011AF ; ; Llamada interesante a analizar
004010EB |. 803D B0324000 03 CMP BYTE PTR DS:[4032B0],3
004010F2 |. 74 12 JE SHORT Nag1.00401106 ; ; Si de la llamada volvemos con un 3 -> Parcheo chapuza
004010F4 |. 803D B0324000 02 CMP BYTE PTR DS:[4032B0],2
004010FB |. 74 1A JE SHORT Nag1.00401117 ; ; Si de la llamada volvemos con un 2 -> Sin parchear
004010FD |. 803D B0324000 01 CMP BYTE PTR DS:[4032B0],1
00401104 |. 74 22 JE SHORT Nag1.00401128 ; ; Si de la llamada volvemos con un 1 -> Buen trabajo Joe!
........
004011AF /$ 68 A2324000 PUSH Nag1.004032A2 ; /String2 = "Value1"
004011B4 |. 68 A9324000 PUSH Nag1.004032A9 ; |String1 = "Value2"
004011B9 |. E8 64000000 CALL <JMP.&kernel32.lstrcmpA> ; \lstrcmpA
004011BE |. 50 PUSH EAX ; kernel32.BaseThreadInitThunk
004011BF |. 85C0 TEST EAX,EAX ; kernel32.BaseThreadInitThunk
004011C1 |. 75 10 JNZ SHORT Nag1.004011D3
004011C3 |. 33C0 XOR EAX,EAX ; kernel32.BaseThreadInitThunk
004011C5 |. 58 POP EAX ; kernel32.75CDEE1C
004011C6 |. 85C0 TEST EAX,EAX ; kernel32.BaseThreadInitThunk
004011C8 |. 74 15 JE SHORT Nag1.004011DF
004011CA |. C605 B0324000 03 MOV BYTE PTR DS:[4032B0],3
004011D1 |. EB 17 JMP SHORT Nag1.004011EA
004011D3 |> 58 POP EAX ; kernel32.75CDEE1C
004011D4 |. 33C0 XOR EAX,EAX ; kernel32.BaseThreadInitThunk
004011D6 |. C605 B0324000 02 MOV BYTE PTR DS:[4032B0],2
004011DD |. EB 0B JMP SHORT Nag1.004011EA
004011DF |> 33C0 XOR EAX,EAX ; kernel32.BaseThreadInitThunk
004011E1 |. C605 B0324000 01 MOV BYTE PTR DS:[4032B0],1
004011E8 |. EB 00 JMP SHORT Nag1.004011EA
004011EA \> C3 RETN
Vemos dentro del Call 4011AF que Compara si Value1 = Value2 y dependiendo de esa comparación guarda en memoria (4032B0), los valores 1, 2 ó 3.
Basta con modificar en un editor hexadecimal la parabra «Value2» por «Value1» y ya tenemos el problema resuelto.
Al pulsar Re-Check
Notas finales
Se podía haber parcheado un montón de código para obtener el mismo resultado pero fijándonos en el código lo hemos conseguido parcheandoun solo byte. Recuerda, cuando halla que parchear, cuantos menos bytes mejor.
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.
Realistic Challenge 5: There is a new company out called NullCo. Have a look around the site and see what you can do.
Hay una nueva compañia llamada NullCo. Echa un vistazo a la web haber que puedes hacer.
Analizando a la víctima
Echamos un vistazo a la web y lo único interesante que vemos es un buscador.
Miramos el código fuente y vemos una ruta interesante.
Si exploramos la ruta «http://www.thisislegal.com/nc/adm/» nos aparece un login. Metemos cualquier cosa y el mensaje de error da demasiada información.
Ahora fijémonos en el menú productos. Pinchamos sobre cualquier producto y a continuación en la imagen para ampliarla, veremos el siguiente enlace.
Vamos a ver si podemos explotar «i.php«. Probamos a obtener información sensible del servidor.
Probamos «http://www.thisislegal.com/nc/i.php?img=adm/login.pwd» y nos da error, seguramente por que está anexionando la extensión de la imagen, es decir, el script está interpretando esto:
Esta es la primera entrega de tres en las que vamos a ver tres crackmes que todo reverser debería hacer. Son la serie del autor Cruehead. Aunque los hice hace ya muchos años, he decidido documentarlos para que el lector que empieza pueda deleitarse. En este caso se trata del típico Nombre / Serial.
El algoritmo
El algoritmo de este crackme es lo más sencillo que nos podemos encontrar.
Abrimos el crackme con Olly y buscamos en las «string references» el mensaje de error. Pinchamos sobre el y en la parte superior enseguida vemos 2 calls muy interesantes.
Veamos que hace con el nombre.
Para «deurus» pondría todo en mayúsculas, sumaría su valor ascii y le haría XOR 0x5678.
Hace poco me reencontré con esta entrañable serie que tanto me entretuvo cuando era pequeño y para mi sorpresa, me percaté de que nunca había visto el episodio piloto. La nostalgia me llevó a tragarme el episodio entero y a disfrutar a lo grande de la parafernalia técnica de la que hace gala para justificar la creación que da nombre a la serie.
La visión tecnológica de los años 80
Esto hay que analizarlo con perspectiva. Estamos en los años 80 y nos están presentando un coche capaz de mantener una conversación, es decir, nos están presentando una inteligencia artificial (IA) llamada KITT. Puede parecer que el término inteligencia artificial es nuevo pero realmente se acuño en 1956 por John McCarthy. A partir de ese momento surgieron líneas de estudio e hipótesis pero a partir de los 70 se puede considerar que la investigación sobre la IA perdió financiación y quedó en el congelador hasta los años 90. Dicho esto, cuando nos presentan a KITT lo hacen de la siguiente manera:
Devon Miles: Está totalmente controlado por microprocesadores que hacen físicamente imposible que se vea implicado en ningún tipo de colisión o percance a no ser que se lo ordene su piloto específicamente
Michael Knight: ¿Piloto?, no me diga que esta cosa vuela
Devon Miles: ¡No!, pero piensa
Michael Knight: ¿Piensa?, ¿mi coche piensa?
Intel daba a conocer el primer microprocesador allá por el 71 y la serie se estrenó en el 82 lo que le da credibilidad en ese aspecto, aunque dudo que el público de esa época supiera que era un microprocesador, un ordenador y menos una IA.
Los Chips
La serie arranca con un grupo de personas realizando espionaje industrial donde nos muestran las hojas de datos de dos chips Japoneses como son el PD8257-5 y el PD780. Un aplauso para los guionistas y sus asesores ya que el PD8257-5 es una interfaz de comunicaciones y el PD780 un microprocesador de 8 bits.
Detalle del esquema del chip PD8257-5 y del set de instrucciones del chip PD780
Lo más interesante es que lo que se muestra es real como podéis apreciar en la siguiente imagen
Detalle del esquema mostrado en la serie VS la hoja de datos
A continuación un detalle de las capturas realizadas:
Más adelante vuelven a aparecer imágenes en un PC que parecen puestas en post-producción y que son robadas en un maravilloso disco de 5 1/4.
Los diálogos
Llaman la atención mucho los diálogos centrados en el microprocesador como si de un ser superior se tratase, éste es la referencia continua y la parte central del guion de los dos primeros capítulos. Curiosamente aparecen en pantalla multitud de imágenes de circuitos integrados pero no se llega a ver ningún microprocesador. Por otro lado, es interesante el esfuerzo que hacen los guionistas por que llamemos a KITT él en vez de ello, convirtiendo al coche en un personaje más.
Otra cosa que llama mucho la atención son los tópicos de los que hace gala como la asociación de los microprocesadores a los videojuegos o que la empresa villana esté afincada en Silicon Valley. Incluso el nombre KITT es un tópico ya que las siglas vienen de Knight Industries Two Thousand que en cristiano quiere decir Industrias Knight 2000. Y es que en mi opinión el año 2000 se imaginaba como una barrera lejana en la que todo iba a ser tecnológicamente más avanzado.
Conclusiones
Tengo que reconocer que me ha sorprendido que dieran realismo a los chips mostrados teniendo en cuenta que aparecen muy pocos segundos en pantalla y podían haber puesto cualquier cosa.
Por otro lado, la realidad es que en el año 2022 aún nos queda recorrido para llegar a tener un coche fantástico y lo más parecido que tenemos hoy día sería un Tesla con Alexa.
Los retos de criptografía pueden ser muy variados como he dicho anteriormente. El secreto suele estar en saber a que te enfrentas y posteriormente construir una herramienta para descifrarlo o usar una ya existente (la mayoría de los casos).
Una web con la que suelo resolver la mayoría de retos es dcode.fr. Si os fijáis en el enlace, la lista de categorías asciende a 48 y disponéis de unos 800 algoritmos para rebanaros los sesos.
A continuación veamos unos cuantos retos que podéis encontrar por la red. Cabe destacar que normalmente el título del reto dice mucho del algoritmo.
Solución: Aquí nuestro primer impulso es utilizar fuerza bruta a MD5, pero cuando nos damos contra la pared el siguiente candidato es LAN Manager. Aquí la opción que más os guste, Cain, John The Ripper, etc.
Con John The Ripper tenemos que preparar un archivo de texto del estilo: deurus.info:1011:4C240DDAB17D1796AAD3B435B51404EE:4C240DDAB17D1796AAD3B435B51404EE:::
Solución: Para la primera parte la conversión es directa. Para la segunda, la dificultad reside en darse cuenta que hay que separar en grupos de cinco y decodificar por separado.
Conversiones, cifra clásica, hash, simétricos, asimétricos, combinaciones de varios algoritmos y un largo etcetera. Como veis los hay para todos los gustos, ten en cuenta que aquí os muestro una pequeñísima parte de lo que os encontrareis en las webs de retos, pero para despertar la curiosidad es suficiente.
Si te interesa el mundo del hacking, ya sea como aficionado o como profesional, seguramente querrás estar al día de las últimas novedades, técnicas y herramientas que se utilizan en este campo. Para ello, una buena opción es suscribirte a alguna de las revistas sobre hacking que existen en el mercado. Estas publicaciones te ofrecen información de calidad, actualizada y veraz sobre todo lo relacionado con la seguridad informática, el pentesting, el hacking ético y otros temas de interés. En este artículo te presentamos cinco revistas sobre hacking que deberías leer si quieres ampliar tus conocimientos y habilidades en este ámbito.
Es una de las revistas más populares y reconocidas sobre hacking. Se publica desde el año 2005 y cuenta con una amplia comunidad de lectores y colaboradores. Su contenido abarca desde los aspectos más básicos hasta los más avanzados del hacking, con artículos, tutoriales, entrevistas, casos de estudio y reseñas de herramientas. Además, tiene ediciones especiales dedicadas a temas específicos como el hacking web, el hacking móvil, el malware o el IoT. Puedes acceder a su versión digital o impresa desde su página web.
Es una revista electrónica sobre hacking que se publica desde el año 1985. Tiene una periodicidad irregular y se distribuye de forma gratuita a través de Internet. Sus contenidos son principalmente artículos técnicos sobre hacking, seguridad informática, programación, etc. También incluye algunos textos de ficción y humor relacionados con el hacking. Es una revista muy apreciada por la comunidad hacker por su calidad y originalidad.
2600: The Hacker Quarterly es una revista legendaria entre los hackers, ya que se publica desde 1984 y ha sido testigo de la evolución de este movimiento a lo largo de las décadas. Su nombre hace referencia a la frecuencia de 2600 Hz que se usaba para hackear las líneas telefónicas en los años 60 y 70. En sus páginas encontrarás artículos sobre hacking, seguridad informática, cultura hacker, activismo digital y mucho más.
Revista especializada en pentesting o pruebas de penetración, una de las ramas más importantes del hacking ético. Su contenido está dirigido tanto a principiantes como a expertos en esta materia, con artículos prácticos, teóricos y metodológicos sobre cómo realizar pentests eficaces y profesionales. También incluye entrevistas a destacados pentesters, reseñas de herramientas y reportajes sobre proyectos y eventos relevantes. Puedes descargar su versión digital desde su página web o comprar su versión impresa.
Es una revista para los entusiastas del hacking creativo, es decir, aquellos que usan la tecnología para crear proyectos innovadores y divertidos. En sus páginas encontrarás ideas, tutoriales, consejos y reseñas sobre temas como la electrónica, la robótica, el hardware libre, el software libre, el internet de las cosas, la impresión 3D y mucho más..
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.
Realistic Challenge 3: Your school is employing a web designer who is charging far too much for site design and doesn’t know anything about protecting the site. However, he’s sure that there’s no way anyone can hack into any site he’s designed, prove him wrong!
En tu escuela están haciendo una web nueva muy rápido. El creador asegura que no le pueden hackear, demuéstrale que está equivocado.
Analizando a la víctima
Echamos un vistazo y vemos en el menú cosas interesantes. La primera de ellas es un Login que pronto descartamos ya que no parece llevar a ninguna parte. La segunda sirve para mandar enlaces al administrador y que este los publique posteriormente en la web.
Vamos a trastear un poco con la opción de mandar enlaces. En el código fuente ya vemos algo interesante y es que hay un campo oculto con el valor a 1 al mandar el enlace. Probamos a mandar un enlace sin tocar nada y nos dice que lo manda pero que lo tienen que aprobar. Vamos a probar ahora cambiando el valor del parámetro oculto a 0 con Firebug.
¡Funcionó!, el enlace ha pasado el filtro.
¿Cómo podemos aprovechar esto?, pués la forma más común es «XSS cross site scripting«. Veamos una prueba. Con el parámetro oculto otra vez en 0 mandamos el siguiente enlace y reto superado.