La esperada cuarta entrega de La Jungla de Cristal se metió de lleno en el mundo de los Hackers. Cuando la vi en su época he de reconocer que el detalle que explicaremos a continuación me pasó desapercibido.

Hablemos de mineralismo.. digo de IPs privadas

Digamos que a día de hoy, quien más y quien menos, sabe lo que es una IP y para que sirve. Si no lo sabes, digamos resumidamente que es un número que nos identifica dentro de una red. En el protocolo IPv4 son 4 grupos de números entre 0 y 255. Como todo protocolo que se precie, tiene ciertos rangos de direcciones reservados para redes privadas y el resto digamos que son públicas. El rango de direcciones privadas para IPv4 es el siguiente:

  • De 10.0.0.0 a 10.255.255.255
  • 172.16.0.0 a 172.31.255.255
  • 192.168.0.0 a 192.168.255.255
  • 169.254.0.0 a 169.254.255.255

BTM

Como hemos hablado en otras ocasiones, en el cine se exagera todo lo relacionado con el mundo tecnológico y en especial el mundo «Hacking«, y es normal encontrarnos elaborados entornos gráficos que quedan muy bien pero que no existen en el mundo real.

En la Jungla 4.0 usaron IPs privadas como públicas sin ton ni son y perdón si me repito pero, ¿nadie contrata consultores?, es decir, vas a realizar una película sobre hackers y ¿no contratas a alguien que tenga unos conocimientos mínimos?, pues al parecer es mucho pedir, las imágenes hablan por si solas.

En la imagen superior se puede ver como están conectados al sistema de ventilación del NDA. Podría pasar si estuvieran físicamente en las instalaciones del NDA y se conectaran desde un equipo de allí, pero al hacerlo de forma remota crean un enorme gazapo.

Esto es una pequeña muestra de lo que muestra la película. También hay escenas en las que se usan IPs públicas correctamente pero en general cometen el error de forma recurrente.

Enlaces


Warning: This challenge is still active and therefore should not be resolved using this information. Aviso: Este reto sigue en
Introducción Esta es la primera entrega de tres en las que vamos a  ver tres crackmes que todo reverser debería
Warning: This challenge is still active and therefore should not be resolved using this information. Aviso: Este reto sigue en
Los retos de criptografía pueden ser muy variados como he dicho anteriormente. El secreto suele estar en saber a que

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.

Introducció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.

http://www.thisislegal.com/newr/src/read.php?customer=../orders.php

Nos llama la atención «../beqref.cuc«. Parece una encriptación simple, probemos a poner eso mismo en el navegador.

http://www.thisislegal.com/newr/src/read.php?customer=../beqref.cuc

 

Nuestras sospechas son acertadas, ahora el error muestra esto.

Explotando a la víctima

Probamos varias cosas y al final conseguimos algo relevante con «order2.php«.

http://www.thisislegal.com/newr/src/read.php?customer=../beqre2.cuc
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«
http://www.thisislegal.com/newr/src/read.php?customer=../frpher/.ugcnffjq

 

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.

Links

Introducción

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.

02

Veamos que hace con el nombre.

03

Para «deurus» pondría todo en mayúsculas, sumaría su valor ascii y le haría XOR 0x5678.

Ejemplo:

deurus –> DEURUS –> 0x44+0x45+0x55+0x52+0x55+0x53 = 0x1D8 XOR 0x5678 = 0x57A0

Veamos que hace con el serial introducido.

04

 Convierte nuestro serial a hexadecimal y le hace XOR 0x1234.

Ejemplo:

Serial = 12345 –> 0x3039 XOR 0x1234 = 0x220D

Una vez que tenemos el SUMNombre y el SUMSerial los compara. Lo vemos en CMP EAX, EBX.

02

En resumen, si a nuestro SUMNombre le hacemos XOR 0x5678 y XOR 0x1234 ya tenemos el serial bueno.

Ejemplo:

deurus –> DEURUS –> 0x44+0x45+0x55+0x52+0x55+0x53 = 0x1D8 XOR 0x5678 = 0x57A0 XOR 0x1234 = 0x4594

0x4594 = 17812

El Keygen

char Nombre[20];
GetWindowText(hwndEdit1, Nombre, 20);
char Serial[20];
int len = strlen(Nombre);
int suma = 0;
boolean error = false;
   for(int i = 0; i <= len; i = i + 1)
   {
      suma += toupper(Nombre[i]);
   }
suma = suma^0x444C; //444C == 5678 xor 1234
wsprintf(Serial,"%d",suma);
SetWindowText(hwndEdit2, TEXT(Serial));

 Links


Introducción Herramientas utilizadas Desempacado con Ollydbg 2 (Videotutorial) Desempacado con Ollydbg 1 (Videotutorial) Análisis de la rutina del número de
Intro Extensión PPM Clave cifrada Un nuevo lenguaje de programación Enlaces Intro Hoy tenemos aquí un reto de esteganografía bastante
Introducción  Hoy vamos a ver como extraer el script de un ejecutable compilado por Autoit, modificarlo y recompilarlo como nuestro
AVISO: Debido a que este reto está en activo no publicaré a donde pertenece. En este reto stego nos proporcionan

Toda esta aventura comienza con un archivo llamado pretty_raw, sin extensión. Porque sí. Porque las extensiones son una invención heredada de CP/M, precursor de MS-DOS, que Windows terminó de popularizar. Porque son innecesarias. Y porque echo de menos cuando los archivos se reconocían por sus permisos… y no por cómo se llamaban.

Como iba diciendo, todo esto comienza mediante el análisis de pretty_raw. Mirando debajo de la falda con un editor hexadecimal encontramos unos cuantos bytes aleatorios hasta dar con una cabecera PNG.

Si atendemos a la captura, justo antes de la cabecera PNG tenemos 116.254 bytes (0x1C61E). Tomad nota que este número será relevante más adelante.

Extraemos el PNG, lo visualizamos y lo pasamos por todas las herramientas habidas y por haber. Nada funciona. Volvemos a visualizarlo con atención y vemos que hace referencia a un archivo llamado flag.png con unas dimensiones que no coinciden con la extraída.

Toca centrarse y pensar en que camino tomar. Hemos gastado tiempo con el PNG extraído y quizá lo mejor sea centrarse en los bytes que inicialmente hemos descartado. En concreto se trata de un bloque de 116.254 bytes, pero espera, 1570×74=116.180 bytes. ¡Mierda!, no coincide exactamente con los bytes extraídos. Bueno, da igual. Si suponemos que el PNG que buscamos no tiene compresión y que cada pixel ocupa un byte (escala de grises y 8 bits), su tamaño depende únicamente de la geometría y de cómo se almacenan las filas en memoria. Vamos a procesarlo con Python para salir de dudas.

import numpy as np
from PIL import Image

INPUT_FILE  = "pretty_raw"
OUTPUT_FILE = "pretty_raw_flag.png"

WIDTH  = 1570 # ¿estás seguro?
HEIGHT = 74
DEPTH  = 8  # bits

# Leer archivo como RAW
with open(INPUT_FILE, "rb") as f:
    raw = f.read()

expected_size = WIDTH * HEIGHT
if len(raw) < expected_size:
    raise ValueError("El archivo no tiene suficientes datos")

# Convertir a array numpy (grayscale 8 bits)
img = np.frombuffer(raw[:expected_size], dtype=np.uint8)
img = img.reshape((HEIGHT, WIDTH))

# Crear imagen
image = Image.fromarray(img, mode="L")
image.save(OUTPUT_FILE)

print(f"Imagen generada correctamente: {OUTPUT_FILE}")

El script nos devuelve un PNG válido pero con las letras torcidas. Tras darle vueltas me di cuenta de que si en el script usamos como WIDTH=1571 en lugar de 1570, la imagen resultante es correcta y tiene todo el sentido del mundo ya que 1571×74=116.254, que son exactamente los bytes que se encuentran antes del png señuelo.

Aunque el ancho visible de la imagen es de 1570 píxeles, cada fila ocupa realmente 1571 bytes. Ese byte adicional actúa como relleno (padding) y forma parte del stride o bytes por fila. Ignorar este detalle lleva a un desplazamiento erróneo acumulativo y por eso se ve la imagen torcida. En este caso concreto da igual ya que el texto se aprecia, pero si el reto hubiera sido más exigente no se vería nada.

Intro

Hoy vamos a desmitificar un poco a Visual Basic. El Crackme reza que acabemos con la nag y hagamos un keygen.

La NAG

formnag

Lo primero que debemos establecer es a que tipo de Nag nos estamos enfrentando, si es una MessageBox, se localiza y se parchea, si es un formulario la cosa ya cambia un poco, ya que encontrar esa parte del código puede resultar tedioso.

Yo voy a utilizar el camino fácil. En VB contamos con una estupenda herramienta como es VBReformer, que nos muestra las entrañas del crackme y nos posibilita cambiar ciertos parametros.

Abrimos el crackme con VBReformer y vemos su contenido. Localizamos rápidamente el formulario que aparece inicialmente (CMSplash) y el temporizador que contiene (Timer1). Inicialmente el timer tiene un interval de 7000, es decir, la nag se muestra durante 7 segundos. Es tan sencillo como cambiarlo por 1 y guardar el ejecutable (File > Save binary as).

parcheform

Si no disponemos de esta estupenda herramienta, siempre podemos localizar el timer con un editor hexadecimal. Localizamos en Olly el nombre del timer (en las string references lo veréis), y lo buscamos en el editor hexadecimal. La duración de la nag la debemos estimar nosotros y a continuación buscar ese valor hexadecimal. Imaginemos que estimamos que son 7 segundos, lo pasamos a milisegundos y a hexadecimal. 7000 = 0x1B58. Buscamos en el editor hexadecimal «Timer1» y a continuación localizamos el valor 1B58 invertido, es decir, 581B. En las imágenes inferiores se ve claro.

hextimer1original

hextimer1parcheado

Cambiando el valor ya lo tendriámos.

El algoritmo

El algoritmo de este crackme es muy sencillo pero he elegido este en concreto para que veáis las vueltas que da VB para hacer 6 operaciones matemáticas. A continuación tenéis el código íntegro comentado y debajo el resumen.

004081F5      .  FF15 F8B04000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaLenBstr>]    ;  MSVBVM50.__vbaLenBstr
004081FB      .  8BF8                     MOV EDI,EAX
004081FD      .  8B4D E8                  MOV ECX,DWORD PTR SS:[EBP-18]
00408200      .  69FF 385B0100            IMUL EDI,EDI,15B38                              ;  TEMP = Len(nombre) *15B38
00408206      .  51                       PUSH ECX
00408207      .  0F80 B7050000            JO CrackmeV.004087C4
0040820D      .  FF15 0CB14000            CALL DWORD PTR DS:[<&MSVBVM50.#516>]            ;  MSVBVM50.rtcAnsiValueBstr
00408213      .  0FBFD0                   MOVSX EDX,AX                                    ;  digito a ax
00408216      .  03FA                     ADD EDI,EDX                                     ;  TEMP +=1digito
00408218      .  0F80 A6050000            JO CrackmeV.004087C4
0040821E      .  57                       PUSH EDI                                        ;  MSVBVM50.__vbaObjSet
0040821F      .  FF15 F4B04000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaStrI4>]      ;  MSVBVM50.__vbaStrI4
00408225      .  8BD0                     MOV EDX,EAX
00408227      .  8D4D E0                  LEA ECX,DWORD PTR SS:[EBP-20]
0040822A      .  FF15 94B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaStrMove>]    ;  MSVBVM50.__vbaStrMove
00408230      .  8BBD 50FFFFFF            MOV EDI,DWORD PTR SS:[EBP-B0]
00408236      .  50                       PUSH EAX
00408237      .  57                       PUSH EDI                                        ;  MSVBVM50.__vbaObjSet
00408238      .  FF93 A4000000            CALL DWORD PTR DS:[EBX+A4]                      ;  MSVBVM50.0F050D32
0040823E      .  85C0                     TEST EAX,EAX
00408240      .  7D 12                    JGE SHORT CrackmeV.00408254
00408242      .  68 A4000000              PUSH 0A4
00408247      .  68 AC6F4000              PUSH CrackmeV.00406FAC
0040824C      .  57                       PUSH EDI                                        ;  MSVBVM50.__vbaObjSet
0040824D      .  50                       PUSH EAX
0040824E      .  FF15 18B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaHresultCheck>;  MSVBVM50.__vbaHresultCheckObj
00408254      >  8D45 E0                  LEA EAX,DWORD PTR SS:[EBP-20]
00408257      .  8D4D E4                  LEA ECX,DWORD PTR SS:[EBP-1C]
0040825A      .  50                       PUSH EAX
0040825B      .  8D55 E8                  LEA EDX,DWORD PTR SS:[EBP-18]
0040825E      .  51                       PUSH ECX
0040825F      .  52                       PUSH EDX
00408260      .  6A 03                    PUSH 3
00408262      .  FF15 80B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaFreeStrList>>;  MSVBVM50.__vbaFreeStrList
00408268      .  83C4 10                  ADD ESP,10
0040826B      .  8D45 D4                  LEA EAX,DWORD PTR SS:[EBP-2C]
0040826E      .  8D4D D8                  LEA ECX,DWORD PTR SS:[EBP-28]
00408271      .  8D55 DC                  LEA EDX,DWORD PTR SS:[EBP-24]
00408274      .  50                       PUSH EAX
00408275      .  51                       PUSH ECX
00408276      .  52                       PUSH EDX
00408277      .  6A 03                    PUSH 3
00408279      .  FF15 08B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaFreeObjList>>;  MSVBVM50.__vbaFreeObjList
0040827F      .  8B9D 40FFFFFF            MOV EBX,DWORD PTR SS:[EBP-C0]                   ;  CrackmeV.00409A68
00408285      .  83C4 10                  ADD ESP,10
00408288      .  8B83 FC020000            MOV EAX,DWORD PTR DS:[EBX+2FC]
0040828E      .  56                       PUSH ESI
0040828F      .  8985 38FFFFFF            MOV DWORD PTR SS:[EBP-C8],EAX
00408295      .  FFD0                     CALL EAX
00408297      .  8B3D 20B14000            MOV EDI,DWORD PTR DS:[<&MSVBVM50.__vbaObjSet>]  ;  MSVBVM50.__vbaObjSet
0040829D      .  50                       PUSH EAX
0040829E      .  8D45 D8                  LEA EAX,DWORD PTR SS:[EBP-28]
004082A1      .  50                       PUSH EAX
004082A2      .  FFD7                     CALL EDI                                        ;  MSVBVM50.__vbaObjSet; <&MSVBVM50.__vbaObjSet>
004082A4      .  56                       PUSH ESI
004082A5      .  8985 58FFFFFF            MOV DWORD PTR SS:[EBP-A8],EAX
004082AB      .  FF93 08030000            CALL DWORD PTR DS:[EBX+308]
004082B1      .  8D4D DC                  LEA ECX,DWORD PTR SS:[EBP-24]
004082B4      .  50                       PUSH EAX
004082B5      .  51                       PUSH ECX
004082B6      .  FFD7                     CALL EDI                                        ;  MSVBVM50.__vbaObjSet
004082B8      .  8BD8                     MOV EBX,EAX
004082BA      .  8D45 E8                  LEA EAX,DWORD PTR SS:[EBP-18]
004082BD      .  50                       PUSH EAX
004082BE      .  53                       PUSH EBX
004082BF      .  8B13                     MOV EDX,DWORD PTR DS:[EBX]                      ;  MSVBVM50.0F025A95
004082C1      .  FF92 A0000000            CALL DWORD PTR DS:[EDX+A0]
004082C7      .  85C0                     TEST EAX,EAX
004082C9      .  7D 12                    JGE SHORT CrackmeV.004082DD
004082CB      .  68 A0000000              PUSH 0A0
004082D0      .  68 AC6F4000              PUSH CrackmeV.00406FAC
004082D5      .  53                       PUSH EBX
004082D6      .  50                       PUSH EAX
004082D7      .  FF15 18B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaHresultCheck>;  MSVBVM50.__vbaHresultCheckObj
004082DD      >  8B8D 58FFFFFF            MOV ECX,DWORD PTR SS:[EBP-A8]
004082E3      .  8B55 E8                  MOV EDX,DWORD PTR SS:[EBP-18]
004082E6      .  52                       PUSH EDX
004082E7      .  8B19                     MOV EBX,DWORD PTR DS:[ECX]
004082E9      .  FF15 74B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaR8Str>]      ;  MSVBVM50.__vbaR8Str
004082EF      .  D905 08104000            FLD DWORD PTR DS:[401008]
004082F5      .  833D 00904000 00         CMP DWORD PTR DS:[409000],0
004082FC      .  75 08                    JNZ SHORT CrackmeV.00408306
004082FE      .  D835 0C104000            FDIV DWORD PTR DS:[40100C]                      ;  10 / 5 = 2
00408304      .  EB 0B                    JMP SHORT CrackmeV.00408311
00408306      >  FF35 0C104000            PUSH DWORD PTR DS:[40100C]
0040830C      .  E8 578DFFFF              CALL <JMP.&MSVBVM50._adj_fdiv_m32>
00408311      >  83EC 08                  SUB ESP,8
00408314      .  DFE0                     FSTSW AX
00408316      .  A8 0D                    TEST AL,0D
00408318      .  0F85 A1040000            JNZ CrackmeV.004087BF
0040831E      .  DEC1                     FADDP ST(1),ST                                  ;  TEMP +=2
00408320      .  DFE0                     FSTSW AX
00408322      .  A8 0D                    TEST AL,0D
00408324      .  0F85 95040000            JNZ CrackmeV.004087BF
0040832A      .  DD1C24                   FSTP QWORD PTR SS:[ESP]
0040832D      .  FF15 48B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaStrR8>]      ;  MSVBVM50.__vbaStrR8
00408333      .  8BD0                     MOV EDX,EAX
00408335      .  8D4D E4                  LEA ECX,DWORD PTR SS:[EBP-1C]
00408338      .  FF15 94B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaStrMove>]    ;  MSVBVM50.__vbaStrMove
0040833E      .  899D 34FFFFFF            MOV DWORD PTR SS:[EBP-CC],EBX
00408344      .  8B9D 58FFFFFF            MOV EBX,DWORD PTR SS:[EBP-A8]
0040834A      .  50                       PUSH EAX
0040834B      .  8B85 34FFFFFF            MOV EAX,DWORD PTR SS:[EBP-CC]
00408351      .  53                       PUSH EBX
00408352      .  FF90 A4000000            CALL DWORD PTR DS:[EAX+A4]
00408358      .  85C0                     TEST EAX,EAX
0040835A      .  7D 12                    JGE SHORT CrackmeV.0040836E
0040835C      .  68 A4000000              PUSH 0A4
00408361      .  68 AC6F4000              PUSH CrackmeV.00406FAC
00408366      .  53                       PUSH EBX
00408367      .  50                       PUSH EAX
00408368      .  FF15 18B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaHresultCheck>;  MSVBVM50.__vbaHresultCheckObj
0040836E      >  8D4D E4                  LEA ECX,DWORD PTR SS:[EBP-1C]
00408371      .  8D55 E8                  LEA EDX,DWORD PTR SS:[EBP-18]
00408374      .  51                       PUSH ECX
00408375      .  52                       PUSH EDX
00408376      .  6A 02                    PUSH 2
00408378      .  FF15 80B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaFreeStrList>>;  MSVBVM50.__vbaFreeStrList
0040837E      .  83C4 0C                  ADD ESP,0C
00408381      .  8D45 D8                  LEA EAX,DWORD PTR SS:[EBP-28]
00408384      .  8D4D DC                  LEA ECX,DWORD PTR SS:[EBP-24]
00408387      .  50                       PUSH EAX
00408388      .  51                       PUSH ECX
00408389      .  6A 02                    PUSH 2
0040838B      .  FF15 08B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaFreeObjList>>;  MSVBVM50.__vbaFreeObjList
00408391      .  8B95 40FFFFFF            MOV EDX,DWORD PTR SS:[EBP-C0]                   ;  CrackmeV.00409A68
00408397      .  83C4 0C                  ADD ESP,0C
0040839A      .  8B82 00030000            MOV EAX,DWORD PTR DS:[EDX+300]
004083A0      .  56                       PUSH ESI
004083A1      .  8985 30FFFFFF            MOV DWORD PTR SS:[EBP-D0],EAX
004083A7      .  FFD0                     CALL EAX
004083A9      .  50                       PUSH EAX
004083AA      .  8D45 D8                  LEA EAX,DWORD PTR SS:[EBP-28]
004083AD      .  50                       PUSH EAX
004083AE      .  FFD7                     CALL EDI                                        ;  MSVBVM50.__vbaObjSet
004083B0      .  56                       PUSH ESI
004083B1      .  8985 58FFFFFF            MOV DWORD PTR SS:[EBP-A8],EAX
004083B7      .  FF95 38FFFFFF            CALL DWORD PTR SS:[EBP-C8]                      ;  MSVBVM50.0F10C340
004083BD      .  8D4D DC                  LEA ECX,DWORD PTR SS:[EBP-24]
004083C0      .  50                       PUSH EAX
004083C1      .  51                       PUSH ECX
004083C2      .  FFD7                     CALL EDI                                        ;  MSVBVM50.__vbaObjSet
004083C4      .  8BD8                     MOV EBX,EAX
004083C6      .  8D45 E8                  LEA EAX,DWORD PTR SS:[EBP-18]
004083C9      .  50                       PUSH EAX
004083CA      .  53                       PUSH EBX
004083CB      .  8B13                     MOV EDX,DWORD PTR DS:[EBX]                      ;  MSVBVM50.0F025A95
004083CD      .  FF92 A0000000            CALL DWORD PTR DS:[EDX+A0]
004083D3      .  85C0                     TEST EAX,EAX
004083D5      .  7D 12                    JGE SHORT CrackmeV.004083E9
004083D7      .  68 A0000000              PUSH 0A0
004083DC      .  68 AC6F4000              PUSH CrackmeV.00406FAC
004083E1      .  53                       PUSH EBX
004083E2      .  50                       PUSH EAX
004083E3      .  FF15 18B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaHresultCheck>;  MSVBVM50.__vbaHresultCheckObj
004083E9      >  8B8D 58FFFFFF            MOV ECX,DWORD PTR SS:[EBP-A8]
004083EF      .  8B55 E8                  MOV EDX,DWORD PTR SS:[EBP-18]
004083F2      .  52                       PUSH EDX
004083F3      .  8B19                     MOV EBX,DWORD PTR DS:[ECX]
004083F5      .  FF15 74B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaR8Str>]      ;  MSVBVM50.__vbaR8Str
004083FB      .  DC0D 10104000            FMUL QWORD PTR DS:[401010]                      ;  *3
00408401      .  83EC 08                  SUB ESP,8                                       ;  -2
00408404      .  DC25 18104000            FSUB QWORD PTR DS:[401018]
0040840A      .  DFE0                     FSTSW AX
0040840C      .  A8 0D                    TEST AL,0D
0040840E      .  0F85 AB030000            JNZ CrackmeV.004087BF
00408414      .  DD1C24                   FSTP QWORD PTR SS:[ESP]
00408417      .  FF15 48B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaStrR8>]      ;  MSVBVM50.__vbaStrR8
0040841D      .  8BD0                     MOV EDX,EAX
0040841F      .  8D4D E4                  LEA ECX,DWORD PTR SS:[EBP-1C]
00408422      .  FF15 94B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaStrMove>]    ;  MSVBVM50.__vbaStrMove
00408428      .  899D 2CFFFFFF            MOV DWORD PTR SS:[EBP-D4],EBX
0040842E      .  8B9D 58FFFFFF            MOV EBX,DWORD PTR SS:[EBP-A8]
00408434      .  50                       PUSH EAX
00408435      .  8B85 2CFFFFFF            MOV EAX,DWORD PTR SS:[EBP-D4]
0040843B      .  53                       PUSH EBX
0040843C      .  FF90 A4000000            CALL DWORD PTR DS:[EAX+A4]
00408442      .  85C0                     TEST EAX,EAX
00408444      .  7D 12                    JGE SHORT CrackmeV.00408458
00408446      .  68 A4000000              PUSH 0A4
0040844B      .  68 AC6F4000              PUSH CrackmeV.00406FAC
00408450      .  53                       PUSH EBX
00408451      .  50                       PUSH EAX
00408452      .  FF15 18B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaHresultCheck>;  MSVBVM50.__vbaHresultCheckObj
00408458      >  8D4D E4                  LEA ECX,DWORD PTR SS:[EBP-1C]
0040845B      .  8D55 E8                  LEA EDX,DWORD PTR SS:[EBP-18]
0040845E      .  51                       PUSH ECX
0040845F      .  52                       PUSH EDX
00408460      .  6A 02                    PUSH 2
00408462      .  FF15 80B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaFreeStrList>>;  MSVBVM50.__vbaFreeStrList
00408468      .  83C4 0C                  ADD ESP,0C
0040846B      .  8D45 D8                  LEA EAX,DWORD PTR SS:[EBP-28]
0040846E      .  8D4D DC                  LEA ECX,DWORD PTR SS:[EBP-24]
00408471      .  50                       PUSH EAX
00408472      .  51                       PUSH ECX
00408473      .  6A 02                    PUSH 2
00408475      .  FF15 08B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaFreeObjList>>;  MSVBVM50.__vbaFreeObjList
0040847B      .  8B95 40FFFFFF            MOV EDX,DWORD PTR SS:[EBP-C0]                   ;  CrackmeV.00409A68
00408481      .  83C4 0C                  ADD ESP,0C
00408484      .  8B82 04030000            MOV EAX,DWORD PTR DS:[EDX+304]
0040848A      .  56                       PUSH ESI
0040848B      .  8985 28FFFFFF            MOV DWORD PTR SS:[EBP-D8],EAX
00408491      .  FFD0                     CALL EAX
00408493      .  50                       PUSH EAX
00408494      .  8D45 D8                  LEA EAX,DWORD PTR SS:[EBP-28]
00408497      .  50                       PUSH EAX
00408498      .  FFD7                     CALL EDI                                        ;  MSVBVM50.__vbaObjSet
0040849A      .  56                       PUSH ESI
0040849B      .  8985 58FFFFFF            MOV DWORD PTR SS:[EBP-A8],EAX
004084A1      .  FF95 30FFFFFF            CALL DWORD PTR SS:[EBP-D0]                      ;  MSVBVM50.0F10C348
004084A7      .  8D4D DC                  LEA ECX,DWORD PTR SS:[EBP-24]
004084AA      .  50                       PUSH EAX
004084AB      .  51                       PUSH ECX
004084AC      .  FFD7                     CALL EDI                                        ;  MSVBVM50.__vbaObjSet
004084AE      .  8BD8                     MOV EBX,EAX
004084B0      .  8D45 E8                  LEA EAX,DWORD PTR SS:[EBP-18]
004084B3      .  50                       PUSH EAX
004084B4      .  53                       PUSH EBX
004084B5      .  8B13                     MOV EDX,DWORD PTR DS:[EBX]                      ;  MSVBVM50.0F025A95
004084B7      .  FF92 A0000000            CALL DWORD PTR DS:[EDX+A0]
004084BD      .  85C0                     TEST EAX,EAX
004084BF      .  7D 12                    JGE SHORT CrackmeV.004084D3
004084C1      .  68 A0000000              PUSH 0A0
004084C6      .  68 AC6F4000              PUSH CrackmeV.00406FAC
004084CB      .  53                       PUSH EBX
004084CC      .  50                       PUSH EAX
004084CD      .  FF15 18B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaHresultCheck>;  MSVBVM50.__vbaHresultCheckObj
004084D3      >  8B8D 58FFFFFF            MOV ECX,DWORD PTR SS:[EBP-A8]
004084D9      .  8B55 E8                  MOV EDX,DWORD PTR SS:[EBP-18]
004084DC      .  52                       PUSH EDX
004084DD      .  8B19                     MOV EBX,DWORD PTR DS:[ECX]
004084DF      .  FF15 74B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaR8Str>]      ;  MSVBVM50.__vbaR8Str
004084E5      .  DC25 20104000            FSUB QWORD PTR DS:[401020]                      ;  TEMP -= -15
004084EB      .  83EC 08                  SUB ESP,8
004084EE      .  DFE0                     FSTSW AX
004084F0      .  A8 0D                    TEST AL,0D
004084F2      .  0F85 C7020000            JNZ CrackmeV.004087BF
........
00408677      . /74 62                    JE SHORT CrackmeV.004086DB
00408679      . |8B35 14B14000            MOV ESI,DWORD PTR DS:[<&MSVBVM50.__vbaStrCat>]  ;  MSVBVM50.__vbaStrCat
0040867F      . |68 C06F4000              PUSH CrackmeV.00406FC0                          ;  UNICODE "You Get It"
00408684      . |68 DC6F4000              PUSH CrackmeV.00406FDC                          ;  UNICODE "\r\n"
00408689      . |FFD6                     CALL ESI                                        ;  <&MSVBVM50.__vbaStrCat>
0040868B      . |8BD0                     MOV EDX,EAX
0040868D      . |8D4D E8                  LEA ECX,DWORD PTR SS:[EBP-18]
00408690      . |FF15 94B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaStrMove>]    ;  MSVBVM50.__vbaStrMove
00408696      . |50                       PUSH EAX
00408697      . |68 E86F4000              PUSH CrackmeV.00406FE8                          ;  UNICODE "KeyGen It Now"

Que se puede resumir en esto.

004081F5      .  FF15 F8B04000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaLenBstr>]    ;  MSVBVM50.__vbaLenBstr
004081FB      .  8BF8                     MOV EDI,EAX
004081FD      .  8B4D E8                  MOV ECX,DWORD PTR SS:[EBP-18]
00408200      .  69FF 385B0100            IMUL EDI,EDI,15B38                              ;  TEMP = Len(nombre) *15B38
00408206      .  51                       PUSH ECX
00408207      .  0F80 B7050000            JO CrackmeV.004087C4
0040820D      .  FF15 0CB14000            CALL DWORD PTR DS:[<&MSVBVM50.#516>]            ;  MSVBVM50.rtcAnsiValueBstr
00408213      .  0FBFD0                   MOVSX EDX,AX                                    ;  digito a ax
00408216      .  03FA                     ADD EDI,EDX                                     ;  TEMP +=1digito
00408218      .  0F80 A6050000            JO CrackmeV.004087C4
........
004082E9      .  FF15 74B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaR8Str>]      ;  MSVBVM50.__vbaR8Str
004082EF      .  D905 08104000            FLD DWORD PTR DS:[401008]
004082F5      .  833D 00904000 00         CMP DWORD PTR DS:[409000],0
004082FC      .  75 08                    JNZ SHORT CrackmeV.00408306
004082FE      .  D835 0C104000            FDIV DWORD PTR DS:[40100C]                      ;  10 / 5 = 2
00408304      .  EB 0B                    JMP SHORT CrackmeV.00408311
00408306      >  FF35 0C104000            PUSH DWORD PTR DS:[40100C]
0040830C      .  E8 578DFFFF              CALL <JMP.&MSVBVM50._adj_fdiv_m32>
00408311      >  83EC 08                  SUB ESP,8
00408314      .  DFE0                     FSTSW AX
00408316      .  A8 0D                    TEST AL,0D
00408318      .  0F85 A1040000            JNZ CrackmeV.004087BF
0040831E      .  DEC1                     FADDP ST(1),ST                                  ;  TEMP +=2
00408320      .  DFE0                     FSTSW AX
00408322      .  A8 0D                    TEST AL,0D
........
004083F5      .  FF15 74B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaR8Str>]      ;  MSVBVM50.__vbaR8Str
004083FB      .  DC0D 10104000            FMUL QWORD PTR DS:[401010]                      ;  TEMP *=3
00408401      .  83EC 08                  SUB ESP,8                                       ;  TEMP -=2
00408404      .  DC25 18104000            FSUB QWORD PTR DS:[401018]
0040840A      .  DFE0                     FSTSW AX
0040840C      .  A8 0D                    TEST AL,0D
........
004084DF      .  FF15 74B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaR8Str>]      ;  MSVBVM50.__vbaR8Str
004084E5      .  DC25 20104000            FSUB QWORD PTR DS:[401020]                      ;  TEMP -= -15
004084EB      .  83EC 08                  SUB ESP,8
004084EE      .  DFE0                     FSTSW AX
004084F0      .  A8 0D                    TEST AL,0D
004084F2      .  0F85 C7020000            JNZ CrackmeV.004087BF
........
00408677      . /74 62                    JE SHORT CrackmeV.004086DB
00408679      . |8B35 14B14000            MOV ESI,DWORD PTR DS:[<&MSVBVM50.__vbaStrCat>]  ;  MSVBVM50.__vbaStrCat
0040867F      . |68 C06F4000              PUSH CrackmeV.00406FC0                          ;  UNICODE "You Get It"
00408684      . |68 DC6F4000              PUSH CrackmeV.00406FDC                          ;  UNICODE "\r\n"
00408689      . |FFD6                     CALL ESI                                        ;  <&MSVBVM50.__vbaStrCat>
0040868B      . |8BD0                     MOV EDX,EAX
0040868D      . |8D4D E8                  LEA ECX,DWORD PTR SS:[EBP-18]
00408690      . |FF15 94B14000            CALL DWORD PTR DS:[<&MSVBVM50.__vbaStrMove>]    ;  MSVBVM50.__vbaStrMove
00408696      . |50                       PUSH EAX
00408697      . |68 E86F4000              PUSH CrackmeV.00406FE8                          ;  UNICODE "KeyGen It Now"

Y en esto:

TEMP = Len(nombre) *15B38
TEMP += 1ºdigitoascii
TEMP +=2
TEMP *=3
TEMP -=2
TEMP +=15

 Y el KeyGen nos ocupa una sola línea

txtserial.Text = (((((Len(txtnombre.Text) * 88888) + Asc(Mid(txtn.Text, 1, 1))) + 2) * 3) - 2) + 15

 Huevo de pascua (Easter egg)

Si nos fijamos en el VBReformer, en el formulario principal vemos muchas cajas de texto.

vbreformervistaproject

Las hacemos visibles, guardamos y ejecutamos haber que pasa.

textsvisibles

crackmebonus

Lo que pasa es que va guardando el resultado de las operaciones en ellas y en la de arriba concretamente está nuestro serial bueno, lo que nos hace poseedores de un KeyGen encubierto.

Links


Introducción Esta vez se trata de un crackme realizado en VC++ 5.0/6.0 y en sus entrañas utiliza RSA-24. En este
Introducción Herramientas disponibles CrkViz-1 (Serial a la vista) CrkViz-2 (Parcheando rutina aleatoria) CrkViz-3 (Nag+Keygen) CrkViz-4 (Límite de ejecuciones+Keygen) CrkViz-5 (Serial
Con The Ring inauguro una nueva sección llamada Blooper Tech Movie (BTM), algo así como pifias o tomas falsas tecnológicas
Intro Hoy tenemos aquí un crackme del 2009 originario de crackmes.de. El Crackme está hecho en VB6, sin empacar y

Introducción

Esta vez se trata de un crackme realizado en VC++ 5.0/6.0 y en sus entrañas utiliza RSA-24. En este caso la peculiaridad es que el nombre no interviene en la generación del serial siendo un resultado único.

Resumen RSA

Parámetros

p = Primer número primo
q = Segundo número primo
e = Exponente público que cumpla MCD(e,(p-1)*(q-1))==1
n = Módulo público siendo n=p*q
d = Exponente privado que cumpla d=e^(-1) mod ((p-1)*(q-1))

De este modo e y n son la parte pública de la clave y d y n la parte privada. Los número primos p y q se utilizan solo para generar los parámetros y de ahí en adelante se pueden desechar.

Funciones de Cifrado/Descifrado

cifrado = descifrado ^ e mod n
descifrado = cifrado ^ d mod n

OllyDbg

Nuestro primer vistazo con OllyDbg nos muestra cuatro números de los que podemos hacernos una idea de que 9901 es un buen candidato a ser el exponente público (e) y 12790891 el módulo n ya que casualmente es un número de 24 bits. Los otros dos números de momento no nos dicen nada.

Referencias de texto

A continuación de los números tenemos la rutina de comprobación en la que comprueba que nuestro serial tenga 14 dígitos y lo divide en dos partes de 7 dígitos. Interesante ya que los otros dos números que aparecían en las referencias de texto tienen 7 dígitos cada uno.

004029CD  |.  68 DC004200   PUSH    RSA24.004200DC                         ;  ASCII "9901"
004029D2  |.  8D8C24 E40000>LEA     ECX,[DWORD SS:ESP+E4]
004029D9  |.  E8 52E7FFFF   CALL    RSA24.00401130
004029DE  |.  68 D0004200   PUSH    RSA24.004200D0                         ;  ASCII "12790891"
004029E3  |.  8D4C24 1C     LEA     ECX,[DWORD SS:ESP+1C]
004029E7  |.  C78424 640600>MOV     [DWORD SS:ESP+664],0
004029F2  |.  E8 39E7FFFF   CALL    RSA24.00401130
004029F7  |.  68 C8004200   PUSH    RSA24.004200C8                         ;  ASCII "8483678"
004029FC  |.  8D8C24 740200>LEA     ECX,[DWORD SS:ESP+274]
00402A03  |.  C68424 640600>MOV     [BYTE SS:ESP+664],1
00402A0B  |.  E8 20E7FFFF   CALL    RSA24.00401130
00402A10  |.  68 C0004200   PUSH    RSA24.004200C0                         ;  ASCII "5666933"
00402A15  |.  8D8C24 AC0100>LEA     ECX,[DWORD SS:ESP+1AC]
00402A1C  |.  C68424 640600>MOV     [BYTE SS:ESP+664],2
00402A24  |.  E8 07E7FFFF   CALL    RSA24.00401130
00402A29  |.  8B9424 680600>MOV     EDX,[DWORD SS:ESP+668]
00402A30  |.  83CE FF       OR      ESI,FFFFFFFF
00402A33  |.  8BFA          MOV     EDI,EDX
00402A35  |.  8BCE          MOV     ECX,ESI
00402A37  |.  33C0          XOR     EAX,EAX
00402A39  |.  C68424 600600>MOV     [BYTE SS:ESP+660],3
00402A41  |.  F2:AE         REPNE   SCAS [BYTE ES:EDI]
00402A43  |.  F7D1          NOT     ECX
00402A45  |.  49            DEC     ECX
00402A46  |.  83F9 0E       CMP     ECX,0E                                 ;  serial 0xE chars -> 14 digitos
00402A49  |.  0F85 63010000 JNZ     RSA24.00402BB2
00402A4F  |.  33C9          XOR     ECX,ECX
00402A51  |>  8A0411        /MOV     AL,[BYTE DS:ECX+EDX]                  ;  {
00402A54  |.  3C 30         |CMP     AL,30
00402A56  |.  0F8C 56010000 |JL      RSA24.00402BB2
00402A5C  |.  3C 39         |CMP     AL,39                                 ;  comprueba que el serial sea numerico
00402A5E  |.  0F8F 4E010000 |JG      RSA24.00402BB2
00402A64  |.  41            |INC     ECX
00402A65  |.  83F9 0E       |CMP     ECX,0E
00402A68  |.^ 7C E7         \JL      SHORT RSA24.00402A51                  ;  }
00402A6A  |.  8BC2          MOV     EAX,EDX
00402A6C  |.  C64424 17 00  MOV     [BYTE SS:ESP+17],0                     ;  {
00402A71  |.  C64424 0F 00  MOV     [BYTE SS:ESP+F],0
00402A76  |.  8B08          MOV     ECX,[DWORD DS:EAX]
00402A78  |.  894C24 10     MOV     [DWORD SS:ESP+10],ECX
00402A7C  |.  66:8B48 04    MOV     CX,[WORD DS:EAX+4]
00402A80  |.  66:894C24 14  MOV     [WORD SS:ESP+14],CX
00402A85  |.  8B4A 07       MOV     ECX,[DWORD DS:EDX+7]
00402A88  |.  8A40 06       MOV     AL,[BYTE DS:EAX+6]                     ;  divide el serial en dos partes de 7 digitos
00402A8B  |.  894C24 08     MOV     [DWORD SS:ESP+8],ECX
00402A8F  |.  884424 16     MOV     [BYTE SS:ESP+16],AL
00402A93  |.  8D42 07       LEA     EAX,[DWORD DS:EDX+7]
00402A96  |.  8D4C24 10     LEA     ECX,[DWORD SS:ESP+10]
00402A9A  |.  66:8B50 04    MOV     DX,[WORD DS:EAX+4]
00402A9E  |.  8A40 06       MOV     AL,[BYTE DS:EAX+6]                     ;  }

A continuación hace una serie de operaciones matemáticas para finalmente comparar el resultado con 8483678 y con 5666933. Lo que está haciendo es cifrar con nuestro serial en dos partes para comprobar que tenemos el número descifrado. Veamos un ejemplo con el serial 12345678901234.

descifrado ^ e mod n = cifrado
x1 = 1234567 y x2 = 8901234
1º parte del serial
x1 ^ 9901 mod 12790891 != 8483678
2º parte del serial
x2 ^ 9901 mod 12790891 != 5666933

Obviamente el resultado de las operaciones anteriores no da ese resultado y el Crackme nos tira fuera de modo que no nos queda más que atacar a RSA para obtener los primos p y q y el módulo privado d. De este modo podremos obtener los números buenos.

Los primos p y q se obtienen factorizando (botón Factor N) y una vez que tenemos p y q hallamos d (botón Calc. D). Todo esto es coser y cantar con la ayuda de la herramienta RSA-Tool 2. El exponente público e se introduce en hexadecimal.

Obteniendo p, q y d

Una vez que tenemos d hallamos el serial de forma sencilla con la herramienta Big Integer Calculator.

cifrado ^ d mod n = descifrado
1º parte del serial
8483678 ^ 10961333 mod 12790891 = 7167622
2º parte del serial
5666933 ^ 10961333 mod 12790891 = 3196885

SERIAL = 71676223196885
1º parte del serial
2º parte del serial

Enlaces

Introducción

Esta vez vamos a analizar los CrackMes de un antiguo colaborador de Karpoff Spanish Tutor, CrkViZ. En estas cinco soluciones vamos a pelearnos con Visual Basic 5/6 nativo y Pcode, con el registro de Windows y tendremos que parchear algúna rutina antidebug. Los CrackMes son del año 2000 y aunque algunos estaban ya solucionados, los analizaremos igualmente para ver la diferencia que existe con los análisis realizados en aquellos años, sí, estamos hablando del Softice.

Herramientas disponibles

Cuando hablamos de Visual Basic 5/6, podemos destacar 3 herramientas que nos facilitan mucho la vida, VB Decompiler, VB Reformer y ExDec. Las dos primeras se defienden bien tanto con código nativo como pcode y ExDec solamente nos sirve para pcode. Aún así, si todo lo demás falla, Ollydbg nos sacará de apuros.

CrkViz-1

03-03-2015 13-16-27

03-03-2015 13-16-17

Este primer crackme está compilado en Pcode y hoy día, con las herramientas de que disponemos no supone ninguna dificultad. Tan solo debemos abrirlo con VB Decompiler y ya nos encontramos con el serial válido.

03-03-2015 13-14-18

Los opcodes obtenidos con ExDec se ven de la siguiente manera.

......
402F14: 04 FLdRfVar                local_008C
402F17: 21 FLdPrThis              
402F18: 0f VCallAd                 7b3fc340
402F1B: 19 FStAdFunc               local_0088
402F1E: 08 FLdPr                   local_0088
402F21: 0d VCallHresult            7b3fbe88
402F26: 6c ILdRf                   local_008C
402F29: 1b LitStr:                 57230198        <--------------
402F2C: Lead0/30 EqStr            
402F2E: 2f FFree1Str               local_008C
402F31: 1a FFree1Ad                local_0088
402F34: 1c BranchF:                403012
402F37: 21 FLdPrThis              
402F38: 0d VCallHresult            7b3fc2b0
402F3D: 3a LitVarStr:              ( local_00AC )  Gracias por Registrar!!      
402F42: Lead2/00 FStVarCopy       
402F46: 27 LitVar_Missing         
402F49: 27 LitVar_Missing         
402F4C: 3a LitVarStr:              ( local_00AC ) CrkViz
402F51: 4e FStVarCopyObj           local_00BC
402F54: 04 FLdRfVar                local_00BC
402F57: f5 LitI4:                  0x40  64  (...@)
402F5C: 04 FLdRfVar                local_009C
402F5F: 0a ImpAdCallFPR4:          _rtcMsgBox
402F64: 36 FFreeVar
402F6D: 27 LitVar_Missing         
402F70: 25 PopAdLdVar             
402F71: 27 LitVar_Missing
......

CrkViz-2

03-03-2015 13-18-32

Este segundo crackme también está compilado en pcode. La rutina del serial es muy sencilla pero al introducir un número aleatorio nos obliga a parchear. Cargamos el crackme en VB Decompiler y nos muestra esto:

03-03-2015 13-19-48

Básicamente vemos que genera un número aleatorio entre 1 y 999999999 y luego le suma 1. La forma de afrontar esto es parcheando. Nos fijamos en el offset aproximado (4037F2) y abrimos el crackme en un editor hexadecimal. La forma de convertir el offset que nos muestra VB Decompiler a lo que nos muestra un editor hexadecimal es la siguiente.

VBdec_offset - Image Base - VirtualOffset + RawOffset = Offset_Editor.H

4037F2 - 400000 - 1000 + 400 = 2BF2

03-03-2015 14-00-27

Una vez localizados los bytes, los cambiamos por ceros y guardamos.

01-03-2015 04-50-05 01-03-2015 04-52-10

Una vez parcheado, el serial correcto es 1.

CrkViz-3

11-03-2015 21-20-07

En esta tercera entrega, CrkViz aumentó la dificultad. El crackme está compilado en código nativo y nos enfrentamos a un serial asociado a un nombre y a una rutina antidebug que en realidad es una Nag, ya que se muestra siempre.

Afrontar la nag es muy sencillo, basta con localizarla y parchear la llamada.

CPU Disasm
Address   Hex dump          Command                                            Comments
004058E2    8D4D DC         LEA ECX,[EBP-24]
004058E5    C785 BCFDFFFF B MOV DWORD PTR SS:[EBP-244],CrkMeViz-3.004033B8     ; UNICODE "  Debugger detectado!!!   "
004058EF    C785 B4FDFFFF 0 MOV DWORD PTR SS:[EBP-24C],8
004058F9    FFD7            CALL EDI
004058FB    B9 04000280     MOV ECX,80020004
00405900    B8 0A000000     MOV EAX,0A
00405905    898D FCFDFFFF   MOV DWORD PTR SS:[EBP-204],ECX
0040590B    898D 0CFEFFFF   MOV DWORD PTR SS:[EBP-1F4],ECX
00405911    8D95 B4FDFFFF   LEA EDX,[EBP-24C]
00405917    8D8D 14FEFFFF   LEA ECX,[EBP-1EC]
0040591D    8985 F4FDFFFF   MOV DWORD PTR SS:[EBP-20C],EAX
00405923    8985 04FEFFFF   MOV DWORD PTR SS:[EBP-1FC],EAX
00405929    C785 BCFDFFFF 8 MOV DWORD PTR SS:[EBP-244],CrkMeViz-3.00403188     ; UNICODE "Error"
00405933    C785 B4FDFFFF 0 MOV DWORD PTR SS:[EBP-24C],8
0040593D    FF15 C8914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarDup>]
00405943    8D85 F4FDFFFF   LEA EAX,[EBP-20C]
00405949    8D8D 04FEFFFF   LEA ECX,[EBP-1FC]
0040594F    50              PUSH EAX
00405950    8D95 14FEFFFF   LEA EDX,[EBP-1EC]
00405956    51              PUSH ECX
00405957    52              PUSH EDX
00405958    8D45 DC         LEA EAX,[EBP-24]
0040595B    6A 10           PUSH 10
0040595D    50              PUSH EAX
0040595E    FF15 50914000   CALL DWORD PTR DS:[<&MSVBVM50.#595>]               ; rtcMsgBox - NOPear para evitar la NAG
00405964    8D8D F4FDFFFF   LEA ECX,[EBP-20C]

Antes de llegar al keygen vemos que realiza unas llamadas al registro de Windows, ponemos un breakpoint «bp RegOpenKeyW» y ejecutamos.

CPU Disasm
Address   Hex dump            Command                                  Comments
00405677  |.  8B8D B8FDFFFF   MOV ECX,DWORD PTR SS:[EBP-248]
0040567D  |.  B8 54334000     MOV EAX,CrkMeViz-3.00403354              ; UNICODE "<Unregister>"
00405682  |.  68 B4304000     PUSH CrkMeViz-3.004030B4                 ; UNICODE "Serial number"
00405687  |.  894A 04         MOV DWORD PTR DS:[EDX+4],ECX
0040568A  |.  8985 BCFDFFFF   MOV DWORD PTR SS:[EBP-244],EAX
00405690  |.  68 84304000     PUSH CrkMeViz-3.00403084                 ; UNICODE "Register"
00405695  |.  68 58304000     PUSH CrkMeViz-3.00403058                 ; UNICODE "CrkMeViz3"
0040569A  |.  8942 08         MOV DWORD PTR DS:[EDX+8],EAX
0040569D  |.  8B85 C0FDFFFF   MOV EAX,DWORD PTR SS:[EBP-240]
004056A3  |.  8942 0C         MOV DWORD PTR DS:[EDX+0C],EAX
004056A6  |.  FF15 C0914000   CALL DWORD PTR DS:[<&MSVBVM50.#689>] 	; rtcGetSetting - Lee el numero de serie del registro
........
0040574F  |.  68 9C304000     PUSH CrkMeViz-3.0040309C                  ; UNICODE "User Name"
00405754  |.  68 84304000     PUSH CrkMeViz-3.00403084                  ; UNICODE "Register"
00405759  |.  68 58304000     PUSH CrkMeViz-3.00403058                  ; UNICODE "CrkMeViz3"
0040575E  |.  8948 08         MOV DWORD PTR DS:[EAX+8],ECX
00405761  |.  8B8D C0FDFFFF   MOV ECX,DWORD PTR SS:[EBP-240]
00405767  |.  8948 0C         MOV DWORD PTR DS:[EAX+0C],ECX
0040576A  |.  FF15 C0914000   CALL DWORD PTR DS:[<&MSVBVM50.#689>]	; rtcGetSetting - Lee el Usuario del registro

 Reconstruyendo la llamada al registro vemos que lee de esta ruta: HKEY_CURRENT_USER\Software\VB and VBA Program Settings\CrkMeViz3\Register el contenido de User Name y del Serial number.

Quizá uno de los fallos de éste crackme, es que no comprueba la autenticidad de estos parámetros y si los modificas parece que estás registrado. Un ejemplo:

11-03-2015 22-23-28

La rutina de comprobación del serial no es para nada complicada pero recordemos que estamos tratando con VB y éste delega el trabajo duro en otras librerias de modo que tenemos que «meternos» a tracear las llamadas para ver los valores que multiplica y divide.

CPU Disasm
Address     Hex dump          Command                                            Comments
00405A86      FF15 3C914000   CALL DWORD PTR DS:[<&MSVBVM50.#518>]    ;MSVBVM50.rtcLowerCaseVar
00405A8C      8D95 14FEFFFF   LEA EDX,[EBP-1EC]
00405A92      8D8D ACFEFFFF   LEA ECX,[EBP-154]
00405A98      FFD6            CALL ESI
00405A9A      8D95 ACFEFFFF   LEA EDX,[EBP-154]
00405AA0      8D8D 4CFEFFFF   LEA ECX,[EBP-1B4]
00405AA6      FFD7            CALL EDI
00405AA8      8D95 4CFEFFFF   LEA EDX,[EBP-1B4]
00405AAE      8D8D 7CFFFFFF   LEA ECX,[EBP-84]
00405AB4      FFD7            CALL EDI
00405AB6      8D85 14FEFFFF   LEA EAX,[EBP-1EC]
00405ABC      8D8D 7CFFFFFF   LEA ECX,[EBP-84]
00405AC2      50              PUSH EAX
00405AC3      6A 01           PUSH 1
00405AC5      8D95 04FEFFFF   LEA EDX,[EBP-1FC]
00405ACB      51              PUSH ECX
00405ACC      52              PUSH EDX
00405ACD      C785 1CFEFFFF 0 MOV DWORD PTR SS:[EBP-1E4],1
00405AD7      C785 14FEFFFF 0 MOV DWORD PTR SS:[EBP-1EC],2
00405AE1      FF15 68914000   CALL DWORD PTR DS:[<&MSVBVM50.#632>]   ;MSVBVM50.rtcMidCharVar (Esto lo hace 6 veces, lo omito para abreviar.)
........
00405CE1      FF15 34914000   CALL DWORD PTR DS:[<&MSVBVM50.#516>]   ;MSVBVM50.rtcAnsiValueBstr (Lo mismo, otras 6)
........
00405E7C    C785 BCFDFFFF 2 MOV DWORD PTR SS:[EBP-244],52E
00405E86    C785 B4FDFFFF 0 MOV DWORD PTR SS:[EBP-24C],2
00405E90    50              PUSH EAX
00405E91    FF15 84914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>]
		|
		->MSVBVM50.__vbaVarMul
			........
			741C19D3      0FB745 FE       MOVZX EAX,WORD PTR SS:[EBP-2]       ;Valor1
			741C19D7      0FB74D F2       MOVZX ECX,WORD PTR SS:[EBP-0E]      ;Valor2
			741C19DB      6BC0 12         IMUL EAX,EAX,12                     ;Valor1*Valor2
			........
00405E97    8D8D 04FEFFFF   LEA ECX,[EBP-1FC]
00405E9D    50              PUSH EAX
00405E9E    51              PUSH ECX
00405E9F    FF15 84914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>]
00405EA5    8D95 F4FDFFFF   LEA EDX,[EBP-20C]
00405EAB    50              PUSH EAX
00405EAC    52              PUSH EDX
00405EAD    FF15 84914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>]
00405EB3    50              PUSH EAX
00405EB4    8D85 E4FDFFFF   LEA EAX,[EBP-21C]
00405EBA    50              PUSH EAX
00405EBB    FF15 84914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>]
00405EC1    8D8D D4FDFFFF   LEA ECX,[EBP-22C]
00405EC7    50              PUSH EAX
00405EC8    51              PUSH ECX
00405EC9    FF15 84914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>]
00405ECF    50              PUSH EAX
00405ED0    8D95 B4FDFFFF   LEA EDX,[EBP-24C]
00405ED6    8D85 C4FDFFFF   LEA EAX,[EBP-23C]
00405EDC    52              PUSH EDX
00405EDD    50              PUSH EAX
00405EDE    FF15 94914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarDiv>]
		|
		->MSVBVM50.__vbaVarDiv
			........
			741C8094      DD43 08         FLD QWORD PTR DS:[EBX+8]      ;Recupera el resultado de las multiplicaciones anteriores
			741C8097      0FBF47 08       MOVSX EAX,WORD PTR DS:[EDI+8] ;EAX = 1326 (52E)
			741C809B      8945 F8         MOV DWORD PTR SS:[EBP-8],EAX
			741C809E      DA75 F8         FIDIV DWORD PTR SS:[EBP-8]    ;Divide los dos resultados
			741C80A1      DD5E 08         FSTP QWORD PTR DS:[ESI+8]
			........
00405F44      FF15 24914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaLenBstr>]          ;Len(nombre)
........
00405F85      FF15 94914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarDiv>]           ;Resultado anterior / Len(nombre)
........

En resumen:

  • Pasa nuestro nombre a minúsculas.
  • Obtiene el valor ascii de los 6 primeros dígitos del nombre.
  • Los multiplica entre sí y divide el resultado acumulado entre 1326 (52E).
  • Divide el resultado anterior entre el tamaño del nombre.

Ejemplo para deurus

64*65*75*72*75*73 = 1A605D70EB8
1A605D70EB8 / 52E = 5179FBF4
5179FBF4 / 6 = D9454A9

11-03-2015 21-20-17

Al estar correctamente registrados desaparece el botón de registrar.

CrkViz-4

12-03-2015 23-09-07

El cuarto crackme es prácticamente igual que el tercero salvo que en vez de nag ahora contamos con limitación de ejecuciones. Del mismo modo utiliza el registro de Windows para guardar los datos de registro y las ejecuciones que llevamos.

Ponemos un breakpoint «bp RegOpenKeyW» y llegamos a la conclusión de que la ruta es HKEY_CURRENT_USER\Software\VB and VBA Program Settings\ODBC\Register y los valores se guardan en Counter, User Name y Serial number respectivamente. Este crackme hereda el fallo del anterior y si alteramos los valores el crackme nos muestra como usuarios autorizados, aunque sabemos que no estamos registrados ya que seguimos limitados por ejecuciones. Ni que decir tiene que lo mismo que modificamos el nombre y número de serie, podemos modificar el contador a nuestro favor. Crear un archivo «Reiniciar_contador.reg» con el siguiente contenido sería suficiente.

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\VB and VBA Program Settings\ODBC]

[HKEY_CURRENT_USER\Software\VB and VBA Program Settings\ODBC\Register]
"Counter"="0"
"User Name"="deurus"
"Serial number"="12345"

El keygen es prácticamente igual que en el crackme anterior, solo cambia el divisor.

CPU Disasm
Address   Hex dump          Command                                                   Comments
........
00404BD2    C785 BCFDFFFF C MOV DWORD PTR SS:[EBP-244],6C1
00404BDC    C785 B4FDFFFF 0 MOV DWORD PTR SS:[EBP-24C],2
00404BE6    FF15 A0914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>]
   |
    ->MSVBVM50.__vbaVarMul
	741C19F9    0FBF4F 08       MOVSX ECX,WORD PTR DS:[EDI+8]      ;Valor1
	741C19FD    0FBF43 08       MOVSX EAX,WORD PTR DS:[EBX+8]      ;Valor2
	741C1A01    0FAFC8          IMUL ECX,EAX                       ;Valor1*Valor2
........
00404BEC    8D8D 04FEFFFF   LEA ECX,[EBP-1FC]
00404BF2    50              PUSH EAX
00404BF3    51              PUSH ECX
00404BF4    FF15 A0914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>]
00404BFA    8D95 F4FDFFFF   LEA EDX,[EBP-20C]
00404C00    50              PUSH EAX
00404C01    52              PUSH EDX
00404C02    FF15 A0914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>]
00404C08    50              PUSH EAX
00404C09    8D85 E4FDFFFF   LEA EAX,[EBP-21C]
00404C0F    50              PUSH EAX
00404C10    FF15 A0914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>]
00404C16    8D8D D4FDFFFF   LEA ECX,[EBP-22C]
00404C1C    50              PUSH EAX
00404C1D    51              PUSH ECX
00404C1E    FF15 A0914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarMul>]
00404C24    50              PUSH EAX
00404C25    8D95 B4FDFFFF   LEA EDX,[EBP-24C]
00404C2B    8D85 C4FDFFFF   LEA EAX,[EBP-23C]
00404C31    52              PUSH EDX
00404C32    50              PUSH EAX
00404C33    FF15 B0914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarDiv>]
   |
    ->MSVBVM50.__vbaVarDiv
	741C8094    DD43 08         FLD QWORD PTR DS:[EBX+8]              ; Recupera el resultado de las multiplicaciones anteriores
	741C8097    0FBF47 08       MOVSX EAX,WORD PTR DS:[EDI+8]         ; EAX = 1729 (6C1)
	741C809B    8945 F8         MOV DWORD PTR SS:[EBP-8],EAX
	741C809E    DA75 F8         FIDIV DWORD PTR SS:[EBP-8]

00404C39    8BD0            MOV EDX,EAX
........
00404CA0    FF15 3C914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaLenBstr>]  ;Len(nombre)
........
00404CF1    FF15 B0914000   CALL DWORD PTR DS:[<&MSVBVM50.__vbaVarDiv>]   ;Resultado anterior / Len(nombre)

En resumen:

  • Pasa nuestro nombre a minúsculas.
  • Obtiene el valor ascii de los 6 primeros dígitos del nombre.
  • Los multiplica entre sí y divide el resultado acumulado entre 1729 (6C1).
  • Divide el resultado anterior entre el tamaño del nombre.

Ejemplo para deurus

64*65*75*72*75*73 = 1A605D70EB8
1A605D70EB8 / 6C1 = 3E7C594A
3E7C594A / 6 = A6A0EE2

CrkViz-5

11-03-2015 23-23-16

Este último crackme está compilado en código nativo y simplemente se trata de una comparación lineal. La única diferencia reside en que no hay botón de registro, la comprobación la gestiona un evento «On Change«, de modo que está comprobando el tamaño del serial que introducimos y cuando éste tiene 8 dígitos llegamos aquí.

........
0040A64F         .  C745 9C CDD4DD02    MOV DWORD PTR SS:[EBP-64],2DDD4CD      ;2DDD4CD = 48092365
0040A656         .  C745 94 03800000    MOV DWORD PTR SS:[EBP-6C],8003
0040A65D         .  FF15 08C14000       CALL DWORD PTR DS:[<&MSVBVM50.__vbaVa> ;MSVBVM50.__vbaVarTstEq
0040A663         .  66:85C0             TEST AX,AX
0040A666         .  0F84 BA000000       JE CrkMeViZ.0040A726                   ;Si salta BAD  BOY
........

Luego el serial correcto es 48092365.

Notas finales

¿Ha sido indoloro no?, claro que sí, Visual Basic es un coñazo de tracear pero hay que reconocer que con el tiempo las herramientas han mejorado mucho y nuestra vida es mucho más sencilla. Bueno, pués esto ha sido todo, como siempre os dejo todo el material utilizado y un Keygen.

12-03-2015 23-06-33

Enlaces

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.

vlcsnap-2015-11-22-01h10m04s660

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.

vlcsnap-2015-11-22-01h10m52s727

Imagen 1 – «C:\WIN98\Desktop\search.com\2_moesko_island_pt2.html»

vlcsnap-2015-11-22-01h11m25s822

Imagen 2 – «C:\WIN98\Desktop\search.com\restoration.html»

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!.

ring_sello

Enlaces


Se nos entrega el siguiente ELF: Extracción de la Flag Si nos fijamos en las líneas 41 a la 45
Introducción Desempacado Eliminar la NAG Password Nº serie asociado a un nombre Checkbox Trackbar Links Introducción Aquí tenemos un Crackme
Aquí os dejo un video tutorial. El crackme lo podeis encontrar en crackmes.de.
Hemos interceptado un mensaje secreto, pero ninguno de nuestros traductores lo sabe interpretar, ¿sabrías interpretarlo tú? Lo único que hemos

Se nos entrega el siguiente ELF:

/* 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);
void sub_1020();
// int printf(const char *format, ...);
// int getchar(void);
// int fflush(FILE *stream);
// __int64 __isoc99_scanf(const char *, ...); weak
// void __noreturn exit(int status);
// int __fastcall _cxa_finalize(void *);
void __fastcall __noreturn start(__int64 a1, __int64 a2, void (*a3)(void));
FILE **deregister_tm_clones();
__int64 register_tm_clones(); // weak
FILE **_do_global_dtors_aux();
__int64 __fastcall frame_dummy(_QWORD, _QWORD, _QWORD); // weak
int __fastcall main(int argc, const char **argv, const char **envp);
_BOOL8 __fastcall comprobacion(char a1, char a2, int a3);
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);
// int __fastcall __cxa_finalize(void *);
// __int64 _gmon_start__(void); weak

//-------------------------------------------------------------------------
// Data declarations

_UNKNOWN _libc_csu_init;
__int64 (__fastcall *_frame_dummy_init_array_entry)() = &frame_dummy; // weak
__int64 (__fastcall *_do_global_dtors_aux_fini_array_entry)() = &_do_global_dtors_aux; // weak
void *_dso_handle = &_dso_handle; // idb
char *a = "MdfnJk"; // weak
char *b = "jYx}"; // weak
char *c = "gWmfk"; // weak
char *d = "mlvpc"; // weak
char *f = "neU++w"; // weak
FILE *_bss_start; // idb
char completed_0; // weak


//----- (0000000000001000) ----------------------------------------------------
__int64 (**init_proc())(void)
{
  __int64 (**result)(void); // rax

  result = &_gmon_start__;
  if ( &_gmon_start__ )
    return (__int64 (**)(void))_gmon_start__();
  return result;
}
// 40D0: using guessed type __int64 _gmon_start__(void);

//----- (0000000000001020) ----------------------------------------------------
void sub_1020()
{
  JUMPOUT(0LL);
}
// 1026: control flows out of bounds to 0

//----- (0000000000001090) ----------------------------------------------------
// 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();
}
// 1096: positive sp value 8 has been found
// 109D: variable 'v3' is possibly undefined

//----- (00000000000010C0) ----------------------------------------------------
FILE **deregister_tm_clones()
{
  return &_bss_start;
}

//----- (00000000000010F0) ----------------------------------------------------
__int64 register_tm_clones()
{
  return 0LL;
}
// 10F0: using guessed type __int64 register_tm_clones();

//----- (0000000000001130) ----------------------------------------------------
FILE **_do_global_dtors_aux()
{
  FILE **result; // rax

  if ( !completed_0 )
  {
    if ( &__cxa_finalize )
      _cxa_finalize(_dso_handle);
    result = deregister_tm_clones();
    completed_0 = 1;
  }
  return result;
}
// 4080: using guessed type char completed_0;

//----- (0000000000001175) ----------------------------------------------------
int __fastcall main(int argc, const char **argv, const char **envp)
{
  char v4; // [rsp+7h] [rbp-9h] BYREF
  int v5; // [rsp+8h] [rbp-8h]
  bool v6; // [rsp+Fh] [rbp-1h]

  v6 = 1;
  v5 = 0;
  while ( v6 )
  {
    fflush(_bss_start);
    printf("\nIntroduce la letra correcta:\t");
    __isoc99_scanf("%c", &v4);
    getchar();
    if ( v5 > 5 )
    {
      if ( v5 > 9 )
      {
        if ( v5 > 14 )
        {
          if ( v5 > 19 )
            v6 = comprobacion(v4, f[v5 - 20], 10);
          else
            v6 = comprobacion(v4, d[v5 - 15], 2);
        }
        else
        {
          v6 = comprobacion(v4, c[v5 - 10], 8);
        }
      }
      else
      {
        v6 = comprobacion(v4, b[v5 - 6], 17);
      }
    }
    else
    {
      v6 = comprobacion(v4, a[v5], 5);
    }
    if ( !v6 )
    {
      printf("Incorrecta");
      exit(1);
    }
    printf("\n%c\n", (unsigned int)v4);
    if ( v5 == 25 )
    {
      printf("Ya tienes la flag!!");
      exit(1);
    }
    ++v5;
  }
  return 0;
}
// 1060: using guessed type __int64 __isoc99_scanf(const char *, ...);
// 4050: using guessed type char *a;
// 4058: using guessed type char *b;
// 4060: using guessed type char *c;
// 4068: using guessed type char *d;
// 4070: using guessed type char *f;

//----- (0000000000001352) ----------------------------------------------------
_BOOL8 __fastcall comprobacion(char a1, char a2, int a3)
{
  return a1 == (a3 ^ a2);
}

//----- (0000000000001390) ----------------------------------------------------
void __fastcall _libc_csu_init(unsigned int a1, __int64 a2, __int64 a3)
{
  signed __int64 v4; // rbp
  __int64 i; // rbx

  init_proc();
  v4 = &_do_global_dtors_aux_fini_array_entry - &_frame_dummy_init_array_entry;
  if ( v4 )
  {
    for ( i = 0LL; i != v4; ++i )
      ((void (__fastcall *)(_QWORD, __int64, __int64))*(&_frame_dummy_init_array_entry + i))(a1, a2, a3);
  }
}
// 1170: using guessed type __int64 __fastcall frame_dummy(_QWORD, _QWORD, _QWORD);
// 3DE8: using guessed type __int64 (__fastcall *_frame_dummy_init_array_entry)();
// 3DF0: using guessed type __int64 (__fastcall *_do_global_dtors_aux_fini_array_entry)();

//----- (00000000000013F4) ----------------------------------------------------
void term_proc()
{
  ;
}

Extracción de la Flag

Si nos fijamos en las líneas 41 a la 45 vemos las siguientes cadenas:

a = «MdfnJk»
b = «jYx}»
c = «gWmfk»
d = «mlvpc»
f = «neU++w»

Usaremos las cadenas y los valores XOR especificados para cada rango de v5 en el main (líneas 123 a 182) para determinar los caracteres correctos.

Para v5 de 0 a 5: v6 = comprobacion(v4, a[v5], 5);
Significa que: v4 debe ser igual a a[v5] ^ 5

Para v5 de 6 a 9: v6 = comprobacion(v4, b[v5 – 6], 17);
Significa que: v4 debe ser igual a b[v5 – 6] ^ 17

Para v5 de 10 a 14: v6 = comprobacion(v4, c[v5 – 10], 8);
Significa que: v4 debe ser igual a c[v5 – 10] ^ 8

Para v5 de 15 a 19: v6 = comprobacion(v4, d[v5 – 15], 2);
Significa que: v4 debe ser igual a d[v5 – 15] ^ 2

Para v5 de 20 a 25: v6 = comprobacion(v4, f[v5 – 20], 10);
Significa que: v4 debe ser igual a f[v5 – 20] ^ 10

Cálculo de los caracteres correctos:
Para v5 de 0 a 5:
a[0] = ‘M’, M ^ 5 = 0x4D ^ 0x05 = 0x48 -> ‘H’
a[1] = ‘d’, d ^ 5 = 0x64 ^ 0x05 = 0x61 -> ‘a’
a[2] = ‘f’, f ^ 5 = 0x66 ^ 0x05 = 0x63 -> ‘c’
a[3] = ‘n’, n ^ 5 = 0x6E ^ 0x05 = 0x6B -> ‘k’
a[4] = ‘J’, J ^ 5 = 0x4A ^ 0x05 = 0x4F -> ‘O’
a[5] = ‘k’, k ^ 5 = 0x6B ^ 0x05 = 0x6E -> ‘n’
Resulta en la cadena: HackOn

Para v5 de 6 a 9:
b[0] = ‘j’, j ^ 17 = 0x6A ^ 0x11 = 0x7B -> ‘{‘
b[1] = ‘Y’, Y ^ 17 = 0x59 ^ 0x11 = 0x48 -> ‘H’
b[2] = ‘x’, x ^ 17 = 0x78 ^ 0x11 = 0x69 -> ‘i’
b[3] = ‘}’, } ^ 17 = 0x7D ^ 0x11 = 0x6C -> ‘l’
Resulta en la cadena: {Hil

Para v5 de 10 a 14:
c[0] = ‘g’, g ^ 8 = 0x67 ^ 0x08 = 0x6F -> ‘o’
c[1] = ‘W’, W ^ 8 = 0x57 ^ 0x08 = 0x5F -> ‘_’
c[2] = ‘m’, m ^ 8 = 0x6D ^ 0x08 = 0x65 -> ‘e’
c[3] = ‘f’, f ^ 8 = 0x66 ^ 0x08 = 0x6E -> ‘n’
c[4] = ‘k’, k ^ 8 = 0x6B ^ 0x08 = 0x63 -> ‘c’
Resulta en la cadena: o_enc

Para v5 de 15 a 19:
d[0] = ‘m’, m ^ 2 = 0x6D ^ 0x02 = 0x6F -> ‘o’
d[1] = ‘l’, l ^ 2 = 0x6C ^ 0x02 = 0x6E -> ‘n’
d[2] = ‘v’, v ^ 2 = 0x76 ^ 0x02 = 0x74 -> ‘t’
d[3] = ‘p’, p ^ 2 = 0x70 ^ 0x02 = 0x72 -> ‘r’
d[4] = ‘c’, c ^ 2 = 0x63 ^ 0x02 = 0x61 -> ‘a’
Resulta en la cadena: ontra

Para v5 de 20 a 25:
f[0] = ‘n’, n ^ 10 = 0x6E ^ 0x0A = 0x64 -> ‘d’
f[1] = ‘e’, e ^ 10 = 0x65 ^ 0x0A = 0x6F -> ‘o’
f[2] = ‘U’, U ^ 10 = 0x55 ^ 0x0A = 0x5F -> ‘_
f[3] = ‘+’, + ^ 10 = 0x2B ^ 0x0A = 0x21 -> ‘!’
f[4] = ‘+’, + ^ 10 = 0x2B ^ 0x0A = 0x21 -> ‘!’
f[5] = ‘w’, w ^ 10 = 0x77 ^ 0x0A = 0x7D -> ‘}’
Resulta en la cadena: do_!!}

Uniendo todas las partes, obtenemos la flag completa: HackOn{Hilo_enc_ontrado_!!}

Introducción

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

17-02-2016 12-46-19_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 Reconstructor o 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«.

17-02-2016 13-21-14

Si hacemos doble click sobre el nos muestra el código que se muestra a continuación.

crack::TForm1.SpeedButton3Click
 0044C7F4    push       ebp
 0044C7F5    mov        ebp,esp
 0044C7F7    push       0
 0044C7F9    push       ebx
 0044C7FA    mov        ebx,eax
 0044C7FC    xor        eax,eax
 0044C7FE    push       ebp
 0044C7FF    push       44C920
 0044C804    push       dword ptr fs:[eax]
 0044C807    mov        dword ptr fs:[eax],esp
 0044C80A    mov        eax,dword ptr [ebx+324]; TForm1.cb3:TCheckBox
 0044C810    mov        edx,dword ptr [eax]
 0044C812    call       dword ptr [edx+0B8]; TCustomCheckBox.GetChecked
 0044C818    test       al,al
>0044C81A    je         0044C8ED
 0044C820    mov        eax,dword ptr [ebx+328]; TForm1.cb5:TCheckBox
 0044C826    mov        edx,dword ptr [eax]
 0044C828    call       dword ptr [edx+0B8]; TCustomCheckBox.GetChecked
 0044C82E    test       al,al
>0044C830    je         0044C8ED
 0044C836    mov        eax,dword ptr [ebx+32C]; TForm1.cb6:TCheckBox
 0044C83C    mov        edx,dword ptr [eax]
 0044C83E    call       dword ptr [edx+0B8]; TCustomCheckBox.GetChecked
 0044C844    test       al,al
>0044C846    je         0044C8ED
 0044C84C    mov        eax,dword ptr [ebx+358]; TForm1.cb12:TCheckBox
 0044C852    mov        edx,dword ptr [eax]
 0044C854    call       dword ptr [edx+0B8]; TCustomCheckBox.GetChecked
 0044C85A    test       al,al
>0044C85C    je         0044C8ED
 0044C862    mov        eax,dword ptr [ebx+364]; TForm1.cb15:TCheckBox
 0044C868    mov        edx,dword ptr [eax]
 0044C86A    call       dword ptr [edx+0B8]; TCustomCheckBox.GetChecked
 0044C870    test       al,al
>0044C872    je         0044C8ED
 0044C874    mov        eax,dword ptr [ebx+330]; TForm1.cb20:TCheckBox
 0044C87A    mov        edx,dword ptr [eax]
 0044C87C    call       dword ptr [edx+0B8]; TCustomCheckBox.GetChecked
 0044C882    test       al,al
>0044C884    je         0044C8ED
 0044C886    mov        eax,dword ptr [ebx+34C]; TForm1.cb9:TCheckBox
 0044C88C    mov        edx,dword ptr [eax]
 0044C88E    call       dword ptr [edx+0B8]; TCustomCheckBox.GetChecked
 0044C894    test       al,al
>0044C896    je         0044C8ED
 0044C898    mov        eax,dword ptr [ebx+354]; TForm1.cb11:TCheckBox
 0044C89E    mov        edx,dword ptr [eax]
 0044C8A0    call       dword ptr [edx+0B8]; TCustomCheckBox.GetChecked
 0044C8A6    test       al,al
>0044C8A8    je         0044C8ED
 0044C8AA    mov        eax,dword ptr [ebx+35C]; TForm1.cb13:TCheckBox
 0044C8B0    mov        edx,dword ptr [eax]
 0044C8B2    call       dword ptr [edx+0B8]; TCustomCheckBox.GetChecked
 0044C8B8    test       al,al
>0044C8BA    je         0044C8ED
 0044C8BC    mov        eax,dword ptr [ebx+33C]; TForm1.cb19:TCheckBox
 0044C8C2    mov        edx,dword ptr [eax]
 0044C8C4    call       dword ptr [edx+0B8]; TCustomCheckBox.GetChecked
 0044C8CA    test       al,al
>0044C8CC    je         0044C8ED
 0044C8CE    lea        eax,[ebp-4]
 0044C8D1    mov        edx,44C934; 'Ìõô¸ö÷ê¥ó¤ÉÚÀÆ²Äæââîàä¶¶'
 0044C8D6    call       @LStrLAsg
 0044C8DB    lea        eax,[ebp-4]
 0044C8DE    call       0044BF00
 0044C8E3    mov        eax,dword ptr [ebp-4]
 0044C8E6    call       ShowMessage
>0044C8EB    jmp        0044C90A
 0044C8ED    lea        eax,[ebp-4]
 0044C8F0    mov        edx,44C958; 'Åÿæò衦óàù¨ïêçð®øé¤íüàî诹'
 0044C8F5    call       @LStrLAsg
 0044C8FA    lea        eax,[ebp-4]
 0044C8FD    call       0044BF00
 0044C902    mov        eax,dword ptr [ebp-4]
 0044C905    call       ShowMessage
 0044C90A    xor        eax,eax
 0044C90C    pop        edx
 0044C90D    pop        ecx
 0044C90E    pop        ecx
 0044C90F    mov        dword ptr fs:[eax],edx
 0044C912    push       44C927
 0044C917    lea        eax,[ebp-4]
 0044C91A    call       @LStrClr
 0044C91F    ret
<0044C920    jmp        @HandleFinally
<0044C925    jmp        0044C917
 0044C927    pop        ebx
 0044C928    pop        ecx
 0044C929    pop        ebp
 0044C92A    ret

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.

17-02-2016 13-29-34

Veréis que aparece el formulario con todos los recursos, incluso los puedes modificar. Localizar los checkboxes ahora es un juego de niños.

17-02-2016 13-30-15

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.

17-02-2016 12-47-06_trackbar

El código de comprobación es el siguiente.

CPU Disasm
Address   Hex dump          Command                                  Comments
0044C1FF  |.  E8 ECF6FCFF   CALL 0041B8F0                            ; b^3
0044C204  |.  D805 50C34400 FADD DWORD PTR DS:[44C350]               ; b^3+5
0044C20A  |.  D9FA          FSQRT                                    ; sqrt(b^3+5)
0044C20C  |.  E8 F365FBFF   CALL 00402804                            ; Cos(sqrt(b^3+5)) = U
0044C211  |.  DB7D B8       FSTP TBYTE PTR SS:[EBP-48]
0044C214  |.  9B            WAIT
0044C215  |.  D905 54C34400 FLD DWORD PTR DS:[44C354]                ; Coje a
0044C21B  |.  DC45 E8       FADD QWORD PTR SS:[EBP-18]               ; a+1
0044C21E  |.  D9FA          FSQRT                                    ; sqrt(a+1)
0044C220  |.  D9E0          FCHS                                     ; -sqrt(a+1) = V
0044C222  |.  DB6D B8       FLD TBYTE PTR SS:[EBP-48]
0044C225  |.  DEC1          FADDP ST(1),ST
0044C227  |.  DB7D AC       FSTP TBYTE PTR SS:[EBP-54]
0044C22A  |.  9B            WAIT
0044C22B  |.  D905 58C34400 FLD DWORD PTR DS:[44C358]                ; coje c
0044C231  |.  DC4D D8       FMUL QWORD PTR SS:[EBP-28]               ; c*3
0044C234  |.  D805 54C34400 FADD DWORD PTR DS:[44C354]               ; c*3+1
0044C23A  |.  D9ED          FLDLN2                                   ; Ln(c*3+1) = X
0044C23C  |.  D9C9          FXCH ST(1)
0044C23E  |.  D9F1          FYL2X
0044C240  |.  DB6D AC       FLD TBYTE PTR SS:[EBP-54]
0044C243  |.  DEC1          FADDP ST(1),ST                           ; U+V+X
0044C245  |.  DB7D A0       FSTP TBYTE PTR SS:[EBP-60]
0044C248  |.  9B            WAIT
0044C249  |.  D905 5CC34400 FLD DWORD PTR DS:[44C35C]                ; coje d
0044C24F  |.  DC45 D0       FADD QWORD PTR SS:[EBP-30]               ; d+2
0044C252  |.  D9FA          FSQRT                                    ; sqrt(d+2) = Y
0044C254  |.  DB6D A0       FLD TBYTE PTR SS:[EBP-60]
0044C257  |.  DEE1          FSUBRP ST(1),ST                          ; U+V+X+(-Y)
0044C259  |.  D905 58C34400 FLD DWORD PTR DS:[44C358]                ; coje e
0044C25F  |.  DC4D C8       FMUL QWORD PTR SS:[EBP-38]               ; e*3
0044C262  |.  D835 5CC34400 FDIV DWORD PTR DS:[44C35C]               ; (e*3)/2 = Z
0044C268  |.  DEC1          FADDP ST(1),ST                           ; U+V+X+Y+Z
0044C26A  |.  DB2D 60C34400 FLD TBYTE PTR DS:[44C360]
0044C270  |.  DEC1          FADDP ST(1),ST                           ; U+V+X+Y+Z+0.37
0044C272  |.  D80D 6CC34400 FMUL DWORD PTR DS:[44C36C]               ; (U+V+X+Y+Z+0.37)*1000
0044C278  |.  DD5D F0       FSTP QWORD PTR SS:[EBP-10]
0044C27B  |.  9B            WAIT
0044C27C  |.  DD45 F0       FLD QWORD PTR SS:[EBP-10]
0044C27F  |.  E8 9065FBFF   CALL 00402814                            ; Redondea((U+V+X+Y+Z+0,37)*1000)
0044C284  |.  8945 98       MOV DWORD PTR SS:[EBP-68],EAX
0044C287  |.  8955 9C       MOV DWORD PTR SS:[EBP-64],EDX
0044C28A  |.  DF6D 98       FILD QWORD PTR SS:[EBP-68]
0044C28D  |.  83C4 F4       ADD ESP,-0C
0044C290  |.  DB3C24        FSTP TBYTE PTR SS:[LOCAL.33]             
0044C293  |.  9B            WAIT                                     
0044C294  |.  8D45 FC       LEA EAX,[EBP-4]                          
0044C297  |.  E8 68BFFBFF   CALL 00408204                            
0044C29C  |.  8D45 FC       LEA EAX,[EBP-4]
0044C29F  |.  E8 5CFCFFFF   CALL 0044BF00                            ; Llamada de generación de hash
........
0044BF04  |.  8BF0          MOV ESI,EAX
0044BF06  |.  8B06          MOV EAX,DWORD PTR DS:[ESI]               ; EAX = 5415
0044BF08  |.  E8 677BFBFF   CALL 00403A74
0044BF0D  |.  8B15 98EE4400 MOV EDX,DWORD PTR DS:[44EE98]
0044BF13  |.  8902          MOV DWORD PTR DS:[EDX],EAX
0044BF15  |.  8B06          MOV EAX,DWORD PTR DS:[ESI]
0044BF17  |.  E8 587BFBFF   CALL 00403A74
0044BF1C  |.  84C0          TEST AL,AL
0044BF1E  |.  76 38         JBE SHORT 0044BF58
0044BF20  |.  880424        MOV BYTE PTR SS:[LOCAL.3],AL
0044BF23  |.  B3 01         MOV BL,1
0044BF25  |>  B8 1C000000   /MOV EAX,1C
0044BF2A  |.  E8 516AFBFF   |CALL 00402980
0044BF2F  |.  0D 80000000   |OR EAX,00000080
0044BF34  |.  8BFB          |MOV EDI,EBX
0044BF36  |.  81E7 FF000000 |AND EDI,000000FF
0044BF3C  |.  8B16          |MOV EDX,DWORD PTR DS:[ESI]
0044BF3E  |.  0FB6543A FF   |MOVZX EDX,BYTE PTR DS:[EDI+EDX-1]       ; Coje dig a dig el hash, en este caso 5415
0044BF43  |.  33C2          |XOR EAX,EDX                             ; 1 dig XOR 83; 2 dig XOR 89; 3 dig XOR 86; 4 dig XOR 8D
0044BF45  |.  50            |PUSH EAX
0044BF46  |.  8BC6          |MOV EAX,ESI
0044BF48  |.  E8 F77CFBFF   |CALL 00403C44                           
0044BF4D  |.  5A            |POP EDX
0044BF4E  |.  885438 FF     |MOV BYTE PTR DS:[EDI+EAX-1],DL
0044BF52  |.  43            |INC EBX
0044BF53  |.  FE0C24        |DEC BYTE PTR SS:[LOCAL.3]
0044BF56  |.^ 75 CD         \JNZ SHORT 0044BF25
........
0044C2AC  |.  E8 D378FBFF   CALL 00403B84                            ; Llamada a comparación
........
00403BAD  |> /8B0E          /MOV ECX,DWORD PTR DS:[ESI]              ; ECX = nuestro Serial XOReado
00403BAF  |. |8B1F          |MOV EBX,DWORD PTR DS:[EDI]              ; EBX = Serial bueno
00403BB1  |. |39D9          |CMP ECX,EBX                             ; Compara
00403BB3  |. |75 58         |JNE SHORT 00403C0D                      ; Chico malo
00403BB5  |. |4A            |DEC EDX
00403BB6  |. |74 15         |JZ SHORT 00403BCD
00403BB8  |. |8B4E 04       |MOV ECX,DWORD PTR DS:[ESI+4]
00403BBB  |. |8B5F 04       |MOV EBX,DWORD PTR DS:[EDI+4]
00403BBE  |. |39D9          |CMP ECX,EBX
00403BC0  |. |75 4B         |JNE SHORT 00403C0D
00403BC2  |. |83C6 08       |ADD ESI,8
00403BC5  |. |83C7 08       |ADD EDI,8
00403BC8  |. |4A            |DEC EDX
00403BC9  |.^\75 E2         \JNZ SHORT 00403BAD

En resumen

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

17-02-2016 10-29-59_brute

Os dejo como siempre el crackme y el keygen en los enlaces.

Links


Intro Hoy nos enfrentamos a un crackme realizado en Delphi con un algoritmo bastante sencillo. Está empacado con UPX pero
Aquí tenemos un crackme fuera de lo común, más que nada por que está programado en Brainfuck, un lenguaje de
Intro Es un crackme realizado en ensamblador y en el que el objetivo es remover la NAG de la forma
Intro Hoy tenemos aquí un crackme del 2009 originario de crackmes.de. El Crackme está hecho en VB6, sin empacar y

El reto

Se nos proporciona la imagen anterior y se nos invita a resolver la ecuación para el menor entero positivo que representa cada fruta. La solución del reto es concatenar «Flag-» a la suma de los valores de las tres frutas.

Análisis inicial

El enunciado es breve pero ya nos adelanta que existen varias soluciones y que además sólo quieren los números más pequeños que podamos encontrar.

Las frutas están muy bien y son muy sanas pero a nosotros se nos hace más sencillo plantear la ecuación con letras.

\begin{align}
&  \frac{x}{y+z}+\frac{y}{x+z}+\frac{z}{x+y}=4\\
\end{align}

Para arrojar algo de luz veamos la representación gráfica en 2D y 3D con la ayuda de Desmos.

3D

Las gráficas más que luz nos traen oscuridad de modo que preguntemos a ChatGPT.

ChatGPT

resuelve: (x/y+z)+(y/x+z)+(z/x+y)=4 para enteros positivos

Dado que las variables x, y, z son enteros positivos, podemos intentar encontrar una solución para la ecuación bajo estas condiciones. Sin embargo, encontrar una solución exacta puede ser complejo debido a la naturaleza no lineal de la ecuación. Aun así, podemos intentar algunos enfoques:

  • Prueba y error: Podemos probar diferentes combinaciones de valores enteros positivos para x, y, z y ver si satisfacen la ecuación.
  • Análisis de casos específicos: Podemos comenzar analizando casos más simples, como cuando dos de las variables son iguales, y luego ampliar nuestra búsqueda desde allí.
  • Análisis gráfico o numérico: Utilizando herramientas gráficas o numéricas, podríamos identificar posibles soluciones y luego verificar si son enteros positivos.

Voy a realizar un análisis numérico con un rango limitado de valores para ver si encontramos alguna solución que cumpla con las condiciones. Vamos a probar con valores de 1 a 10 para cada variable.

El análisis numérico para valores de en el rango de 1 a 10 no ha encontrado ninguna solución que satisfaga la ecuación. Esto sugiere que, dentro de este rango, no existen combinaciones de enteros positivos que cumplan con la ecuación.

Dado que la ecuación es bastante compleja y no lineal, es posible que las soluciones, si existen, se encuentren fuera del rango considerado o que requieran un enfoque diferente para ser identificadas. Si tienes un rango específico de valores en mente o si hay alguna otra restricción o contexto relevante, por favor házmelo saber para poder ajustar el análisis en consecuencia.

Básicamente nos está invitando a utilizar prueba y error para encontrar una solución, y el prueba y error de las matemáticas no es más que la fuerza bruta en programación.

El código

Partiendo del problema anterior dame un código en python que realice una comprobación recursiva de todas las variables con un rango de 1 a 999.

soluciones = []
rango_valores_x = range(1, 999)
rango_valores_y = range(1, 999)
rango_valores_z = range(1, 999)

for x in rango_valores_x:
    for y in rango_valores_y:
        for z in rango_valores_z:
            # Calculamos el valor de la expresión para cada combinación de x, y, z
            valor = x / (y + z) + y / (x + z) + z / (x + y)
            # Comprobamos si el valor es igual a 4 y agregamos la solución a la lista
            if abs(valor - 4) < 1e-6:  # Usamos una pequeña tolerancia para evitar errores de precisión
                soluciones.append((x, y, z))

print(soluciones)

Dejo resaltada la línea 12 del código ya que en ella reside el problema. Está comprobando con un margen de tolerancia de 10-6 ya que el resultado de las diferentes fracciones no da como resultado exacto 4. Esto es un problema ya que nosotros necesitamos que de exactamente 4 para validar los valores enteros de x, y y z. Pongo un ejemplo para el que se haya perdido con una solución válida para la tolerancia 10-6 siendo x=2, y=264 y z=993.

\begin{align}
&  \frac{2}{264+993}+\frac{264}{2+993}+\frac{993}{2+264}=4.000000429\\
\end{align}

En otras palabras, ChatGPT nos ha brindado una solución aproximada que no sirve para nuestro propósito. Seguimos probando con el código anterior quitando la tolerancia y con rangos mayores hasta que en 106 paro. Me acaba de quedar claro que con la fuerza bruta no vamos a ninguna parte, o más bien, no tenemos capacidad de computación para resolverlo de ésta manera.

¿Qué está pasando?

Lo que pasa es que estamos ante una ecuación algebraica de 3 incógnitas que deben ser enteros positivos cuya solución se alcanza mediante la teoría de curvas elípticas.

Curvas elípticas

Las curvas elípticas son fundamentales en matemáticas avanzadas, representadas por la ecuación y2=x3+Ax+B, donde A y B son constantes. Estas curvas son un punto de encuentro entre la geometría, la teoría de números y el álgebra, ofreciendo un campo rico para la exploración y el análisis. En este CTF, nos enfocaremos en los puntos racionales de las curvas elípticas. Utilizando el método tangente-secante, un procedimiento geométrico iterativo, buscaremos ampliar un conjunto finito de soluciones conocidas a la ecuación de la curva. Este método nos permite indagar en la estructura de las soluciones racionales, que potencialmente pueden ser infinitas. Además, estableceremos una conexión entre las soluciones enteras de las ecuaciones diofánticas y los puntos racionales en las curvas elípticas partiendo de la ecuación (1) especificada en el análisis inicial. A pesar de su aparente simplicidad, esta ecuación es conocida por presentar soluciones mínimas de gran tamaño.

Adecuación

Antes de nada, necesitamos saber el grado de la ecuación, de modo que planteamos la ecuación en forma polinómica estándar deshaciéndonos de los denominadores.

\begin{align}
\begin{split}
n(a+b)(b+c)(c+a)=a(a+b)(c+a)+b(b+c)(a+b)+c(c+a)(b+c)
\end{split}
\end{align}

Ahora necesitamos expandir y simplificar para llegar a la conclusión de que estamos ante una ecuación diofántica de grado 3. Este proceso es engorroso por la cantidad de términos a manejar así que vamos a utilizar Mathematica como software de respaldo para finalmente obtener el polinomio en la forma de Weierstrass según la ecuación 4.

\begin{align}
&  y^2=x^3+109x^2+224x\\
\end{align}

donde:

\begin{align}
x = \frac{−28(a+b+2c)}{(6a+6b−c)}\\
y = \frac{364(a−b)}{(6a+6b−c)}
\end{align}

Las relación entre la ecuación 3 y los puntos de la curva elíptica se establecen mediante la ecuación 4. Las transformaciones entre las soluciones (a, b, c) y los puntos (x, y) en la curva elíptica vienen dados por las ecuaciones 5 y 6. Con estas transformaciones, cada solución de la ecuación diofántica se puede representar como un punto en la curva elíptica, y las operaciones de suma de puntos en la curva elíptica pueden usarse para encontrar nuevas soluciones de la ecuación diofántica.

Mathematica

El código que tenéis a continuación pertenece al gran trabajo de Aditi Kulkarni [7], que además nos da el resultado para cualquier valor de n. Ojo porque para n=4 el resultado tiene 81 dígitos, para n=6 tiene 134, para n=10 tiene 190 y para n=12 asciende a 2707 dígitos.

(* Asignar un valor numérico a n *)
n = 4;
(* Definir la ecuación de una curva elíptica en términos de n *)
curve4 = y^2 == x^3 + (4*n^2 + 12*n - 3)*x^2 + 32*(n + 3)*x;
(* Encontrar un punto racional en la curva que no sea (4,0) *)
P4 = {x, y} /. First[FindInstance[curve4 && x != 4 && y != 0, {x, y}, Integers]];
(* Función para calcular la pendiente entre dos puntos en la curva, 
   o la derivada en el punto si son iguales *)
Slope4[{x1_, y1_}, {x2_, y2_}] := 
  If[x1 == x2 && y1 == y2, 
     ImplicitD[curve4, y, x] /. {x -> x1, y -> y1}, 
     (y2 - y1)/(x2 - x1)];
(* Función para calcular la intersección en y de la línea entre dos puntos 
   o la tangente en el punto si son iguales *)
Intercept4[{x1_, y1_}, {x2_, y2_}] := y1 - Slope4[{x1, y1}, {x2, y2}]*x1; 
(* Función para encontrar el siguiente punto racional en la curva *)
nextRational4[{x1_, y1_}, {x2_, y2_}] := 
  {Slope4[{x1, y1}, {x2, y2}]^2 - CoefficientList[curve4[[2]], x][[3]] - x1 - x2, 
   -Slope4[{x1, y1}, {x2, y2}]^3 + Slope4[{x1, y1}, {x2, y2}]*(CoefficientList[curve4[[2]], x][[3]] + x1 + x2) - Intercept4[{x1, y1}, {x2, y2}]};
(* Función para convertir un punto en la curva elíptica a una solución diofántica *)
ellipticToDiophantine[n_, {x_, y_}] := 
  {(8*(n + 3) - x + y)/(2*(4 - x)*(n + 3)), 
   (8*(n + 3) - x - y)/(2*(4 - x)*(n + 3)), 
   (-4*(n + 3) - (n + 2)*x)/((4 - x)*(n + 3))};
(* Usar nextRational4 para iterar desde P4 hasta encontrar una solución 
   válida y positiva para la ecuación diofántica *)
sol4 = ellipticToDiophantine[n, 
   NestWhile[nextRational4[#, P4] &, P4, 
     ! AllTrue[ellipticToDiophantine[n, #], Function[item, item > 0]] &]];
(* Escalar la solución para obtener enteros mínimos *)
MinSol4 = sol4*(LCM @@ Denominator[sol4])
(* Suma de las tres variables*)
Total[MinSol4]

Solución

Concatenando Flag- con el resultado de Mathematica tenemos la ansiada flag.

Flag-195725546580804863527010379187516702463973843196699016314931210363268850137105614

Conclusiones

ChatGPT ha demostrado ser eficaz en el análisis y la resolución de problemas, siempre que se le proporcione el contexto adecuado. Sin embargo, es importante ser conscientes de que la respuesta proporcionada puede ser aproximada, especialmente si la solución requiere una gran cantidad de recursos computacionales. Por ejemplo, al trabajar con una ecuación diofántica y valores específicos para (x) e (y), ChatGPT puede ayudar a calcular puntos como (P), (2P), (3P), etc., pero hay que tener en cuenta que los resultados para estos puntos pueden ser estimaciones.

Finalmente, os invito a leer la solución de Mingliang Z. [4], en la que se resuelve el problema por completo y de forma muy detallada.

Enlaces

Intro

Se suele decir que para cada problema hay una solución. Si esto lo llevamos al terreno stego podemos decir que para cada reto hay una herramienta que nos da la solución. En la entrada anterior os comenté que mi fondo de armario son steganabara y stegsolve aunque cuando la imagen es PNG, una herramienta de uso obligatorio es TweakPNG.

La víctima

imagen original del reto

Nos enfrentamos a una imagen PNG de 112KB (115477 bytes) con una resolución de 300×225 píxeles. A priori llama la atención el elevado tamaño VS la baja resolución, lo que aviva nuestras sospechas de que esos KB extras se deban a que haya insertado otro archivo en su interior.

Chunk

Los archivos PNG tienen la peculiaridad de que están divididos en secciones (chunks) en la que algunas son críticas como IHDR (cabecera), IDAT (la imagen) e IEND (final) y otras muchas secundarias como por ejemplo tEXt (para insertar texto). Al explorar el archivo con TweakPNG vemos la cabecera, varios chunks de texto, muchos IDAT que he combinado en uno para mejorar el análisis y la sección final. Si os fijáis, al combinar los IDAT ha cambiado el tamaño del PNG de 115447 a 110893 bytes aunque en este caso sigue siendo un tamaño elevado.

aspecto original de los chunks
aspecto de los chunks tras combinar todos los IDAT en uno

Llama la atención el chunk cHRm de 12595 bytes del que TweakPNG ya nos avisa que no reconoce su contenido. Cargamos la imagen en un editor hexadecimal y buscamos la palabra «Great» que es el texto que hay justo antes del chunk cHRm que nos interesa.

detalle del chunk cHRm en editor hexadecimal

La búsqueda da sus frutos ya que el chunk parece que está formado por un archivo mp4. A partir de aquí tenemos varias opciones, para mí la más limpia es con un editor hexadecimal apuntar los offsets de inicio y fin del chunk y crear un archivo nuevo con el contenido. Otra opción es exportar el chunk desde TweakPNG con extensión mp4 y borrar los bytes del nombre del chunk con un editor hexadecimal, de lo contrario no podréis reproducir el mp4.

nombre del chunk a borrar para que funcione el mp4

Hecho esto, al escuchar el mp4 obtenemos la solución del reto.

Enlaces

Nota: si algo os pide clave es deurus.info

Introducción

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.

bucles

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.

 pasado1bucle2

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.

pasado2bucle

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.

pasado3bucle

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.

dump1letra

Nombre de tamaño >5 y <9

05-09-2014 00-06-19

Nombre de tamaño = 10

 04-09-2014 16-37-31

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));

Links


AVISO: Debido a que este reto está en activo no publicaré a donde pertenece. En este reto stego nos proporcionan
Introducción Esta es la tercera y última entrega de los crackmes de Cruehead. En esta ocasión nos enfrentamos a un
Intro We require your services once again. An employee from our company had recently been identified as a known criminal
En el BTM anterior nos remontábamos al año 2006 para ver un pequeño gazapo ocurrido en la serie Dexter. En

AVISO: Debido a que este reto está en activo no publicaré a donde pertenece.

En este reto stego nos proporcionan un archivo MP3 y nos dan una pequeña pista con el título.

Inicialmente lo pasé con GoldWave y me fijé en el la parte de control en el SPECtrogram y en el SPECtrum, pero no conseguí ver nada. A punto de rendirme di con un programa online llamado SPEK, que me dio la respuesta al instante.

SPECtrum mostrado por Spek

Se puede apreciar una palabra que escrita en Inglés nos da la solución al reto.

Introducción

Esta es la tercera y última entrega de los crackmes de Cruehead. En esta ocasión nos enfrentamos a un «keyfile«, un archivo llave para que nos entendamos. Tiene un poco más de dificultad que los anteriores pero es ideal para los que empiezan.

El algoritmo

Si iniciamos el crackme no pasa nada, lo único que vemos es la palabra «UNCRACKED» en el título. Abrimos el crackme con Olly y empezamos. En las «string references» vemos el nombre del archivo llave «crackme3.key«. Lo creamos y escribimos el serial 12345678 y empezamos a tracear.

El CMP EAX,-1 significa que está comprobando que el archivo no esté vacio, como no es nuestro caso continuamos.

07-09-2014 13-02-12

A continuación vemos que compara nuestra longitud de serial con 0x12 (18 en decimal). Nuestro serial tiene 8 dígitos así que nos tira fuera.

07-09-2014 13-07-59

Escribimos en el archivo llave el serial «deurus123456789012» y volvemos a tracear. Vemos que ahora si pasa los filtros iniciales y llegamos a la primera zona interesante. En la imágen está explicado pero os hago un resumen. En el bucle lo que hace es un XOR a los primeros 14 dígitos de nuestro serial con los valores del 41 al 4E (4F finaliza). El bucle solo se rompe si llegamos a 4F o si el resultado del XOR da 0. Además en EAX acumula la suma del resultado del XOR.

07-09-2014 17-13-57

Ejemplo:

d  e  u  r  u  s  1  2  3  4  5  6  7  8  9  0  1  2
64 65 75 72 75 73 31 32 33 34 35 36 37 38
                                          XOR
41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E
-----------------------------------------
25 27 36 36 30 35 76 7A 7A 7E 7E 7A 7A 76 = 4ED (Suma)

A continuación hace XOR entre 12345678 y 4ED, coge los 4 últimos dígitos de nuestro serial y los compara.

07-09-2014 17-23-45

Ejemplo:

12345678 XOR 4ED = 12345295
Compara 12345295 con 32313039
32313039 = 2109, nuestros 4 últimos dígitos al revés. Recordemos que nuestro serial era "deurus123456789012"

 El serial bueno para el nombre deurus12345678 serían los bytes correspondientes de «12345295», es decir, nuestro serial bueno sería:

Ejemplo:

Necesitamos 12345295 para la comparación.
12 34 52 95 hexadecimal
18 52 82 149 decimal
Tenemos que escribirlo al revés. Con Alt-Izq + 149 escribimos el primer caracter, el resto igual.
Nuestro serial quedaría: deurus12345678òR4↕

Metemos el serial y vemos que lo acepta pero que nos muestra un nombre extraño. Esto es por que nos está mostrando los bytes del nombre xoreados, tendremos que hacer un XOR antes al nombre que queramos para que lo muestre correctamente.

07-09-2014 18-15-19

Recapitulando

Con lo que sabemos ahora hay que empezar a coger el toro por los cuernos. Lo primero que queremos que muestre el nombre deurus y no deurus12345678. Para ello debemos cortar el bucle y eso solo lo podemos hacer forzando que el resultado del XOR sea 0. Ok pues para deurus el siguiente valor de BL, es decir el séptimo, en el bucle sería 47 lo que corresponde a la letra G. Pues si ponemos de serial deurusGxxxxxxxxxxx ya tendríamos la primera parte solucionada.

Pero recordemos que necesitamos XORear el nombre inicialmente, luego debemos escribir  el resultado del XOR.

Ejemplo:

d  e  u  r  u  s  
64 65 75 72 75 73
                  XOR
41 42 43 44 45 46
-----------------
25 27 36 36 30 35

25 27 36 36 30 35 ----- debemos meter esto en el archivo llave.
                  XOR
41 42 43 44 45 46
-----------------
64 65 75 72 75 73 ----- Al desencriptarlo el bucle se verá nuestro nombre correctamente.

En el archivo llave escribiriamos: %'6605

Ahora nos faltaría calcular el nuevo SUM. Como el resultado del XOR ahora es nuestro nombre, basta con sumar sus valores ascii (64+65+75+72+75+73 == 0x298)

0x12345678 XOR 0x298 == 0x123454E0

Luego nuestros 4 últimos dígitos deben ser lo correspondiente a los bytes E0, 54, 34, 12. Los pasamos a decimal y los escribimos en el archivo llave con el truco del ALT-Izq que hemos comentado antes.

El contenido final del archivo llave para el nombre deurus sería:

%’6605GxxxxxxxÓT4↕

07-09-2014 16-55-15

Aquí vemos el archivo llave normal.

keyfiletext

Y aquí lo vemos con un editor hexadecimal. Como veis se ven claramente los bytes E0, 54, 34, 12.

keyfilehex

Os dejo un keygen hecho en .Net para que probéis. Os genera el contenido del archivo y el archivo «crackme3.key».

keygen

Links


Los retos criptográficos son muy variados y muchas veces la dificultad está en saber a que te enfrentas. En este
https://www.youtube.com/watch?v=iOYAn4l4wco Lista de reproducción
Introducción Funcionamiento de RSA OllyDbg Calculando un serial válido Ejemplo operacional Keygen Links Introducción Empezamos con lo que espero que
AVISO: Debido a que este reto está en activo no publicaré a donde pertenece. En este pequeño CrackMe se nos

Los retos criptográficos son muy variados y muchas veces la dificultad está en saber a que te enfrentas. En este caso pasa eso, te dan un código y si no has visto algo parecido en la vida, no sabes por donde empezar. El título del autor da una pequeña pista pero para los desconocedores no es suficiente. La pista es el título y dice «WTF?!?» y el código a descifrar es el siguiente:

[-]>[-]<
>+++++++++++[<+++++++++++>-]<.
>+++[<--->-]<-.
>++[<++>-]<++.
+.
>++++[<---->-]<-.
---.
+++.
.
>+++[<+++>-]<.
>+++[<--->-]<+.
>++++[<++++>-]<-.
>++++[<---->-]<--.
>+++[<+++>-]<-.
>++[<-->-]<--.
-.

Si eres una persona con recursos, realizaras varias búsquedas por la red y al final llegarás a la conclusión de que te enfrentas a BRAINFUCK, un lenguaje de programación esotérico como ya vimos en el reto de Root-Me.

Enlaces

Introducción

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

  1. Inicialmente es necesario generar aleatoriamente dos números primos grandes, a los que llamaremos p y q.
  2. A continuación calcularemos n como producto de p y q:
    n = p * q
  3. Se calcula fi:
    fi(n)=(p-1)(q-1)
  4. 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.
  5. 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.
  6. El par de números (e,n) son la clave pública.
  7. El par de números (d,n) son la clave privada.
  8. Cifrado: La función de cifrado es.
    c = m^e mod n
  9. Descifrado: La función de descifrado es.
    m = c^d mod n

OllyDbg

Con OllyDbg analizamos la parte del código que nos interesa.

00401065  |>push    19                          ; /Count = 19 (25.)
00401067  |>push    00404330                    ; |Buffer = dihux_ke.00404330
0040106C  |>push    2711                        ; |ControlID = 2711 (10001.)
00401071  |>push    dword ptr [ebp+8]           ; |hWnd
00401074  |>call    <GetDlgItemTextA>           ; \GetDlgItemTextA
00401079  |>cmp     eax, 5                      ;  Tamaño nombre >= 5
0040107C  |>jb      00401214
00401082  |>cmp     eax, 14                     ;  Tamaño nombre <= 0x14
00401085  |>ja      00401214
0040108B  |>mov     [404429], eax
00401090  |>push    96                          ; /Count = 96 (150.)
00401095  |>push    00404349                    ; |Buffer = dihux_ke.00404349
0040109A  |>push    2712                        ; |ControlID = 2712 (10002.)
0040109F  |>push    dword ptr [ebp+8]           ; |hWnd
004010A2  |>call    <GetDlgItemTextA>           ; \GetDlgItemTextA
004010A7  |>test    al, al
........
004010D8  |>xor     ecx, ecx                    ;  Case 0 of switch 004010B6
004010DA  |>/push    0
004010DC  |>|call    <__BigCreate@4>
004010E1  |>|mov     [ecx*4+404411], eax
004010E8  |>|inc     ecx
004010E9  |>|cmp     ecx, 6
004010EC  |>\jnz     short 004010DA
004010EE  |>push    dword ptr [404411]          ; /Arg3 = 00B60000
004010F4  |>push    10                          ; |16??
004010F6  |>push    0040401F                    ; |Arg1 = 0040401F ASCII "8ACFB4D27CBC8C2024A30C9417BBCA41AF3FC3BD9BDFF97F89"
004010FB  |>call    <__BigIn@12>                ; \dihux_ke.004013F3
00401100  |>push    dword ptr [404415]          ; /Arg3 = 00C70000
00401106  |>push    10                          ; |Arg2 = 00000010
00401108  |>push    00404019                    ; |Arg1 = 00404019 ASCII "10001"
0040110D  |>call    <__BigIn@12>                ; \dihux_ke.004013F3
00401112  |>push    dword ptr [404425]          ; /Arg3 = 00CB0000
00401118  |>push    10                          ; |Arg2 = 00000010
0040111A  |>push    00404349                    ; |Arg1 = 00404349 ASCII "123456789123456789"
0040111F  |>call    <__BigIn@12>                ; \dihux_ke.004013F3
00401124  |>push    00404330                    ; /String = "deurus"
00401129  |>call    <lstrlenA>                  ; \lstrlenA
0040112E  |>push    dword ptr [404419]
00401134  |>push    eax
00401135  |>push    00404330                    ;  ASCII "deurus"
0040113A  |>call    <__BigInB256@12>
0040113F  |>push    dword ptr [404421]          ;  c
00401145  |>push    dword ptr [404411]          ;  n = 8ACFB4D27CBC8C2024A30C9417BBCA41AF3FC3BD9BDFF97F89
0040114B  |>push    dword ptr [404415]          ;  e = 10001
00401151  |>push    dword ptr [404425]          ;  serial
00401157  |>call    <__BigPowMod@16>            ;  c = serial^e (mod n)
0040115C  |>mov     eax, 1337
00401161  |>push    0                           ; /Arg4 = 00000000
00401163  |>push    dword ptr [40441D]          ; |x
00401169  |>push    eax                         ; |0x1337
0040116A  |>push    dword ptr [404421]          ; |c
00401170  |>call    <__BigDiv32@16>             ; \x = c/0x1337
00401175  |>push    dword ptr [40441D]          ;  x
0040117B  |>push    dword ptr [404419]          ;  nombre
00401181  |>call    <__BigCompare@8>            ; ¿x = nombre?
00401186  |>jnz     short 0040119C
00401188  |>push    0                           ; /Style = MB_OK|MB_APPLMODAL
0040118A  |>push    00404014                    ; |Title = "iNFO"
0040118F  |>push    00404004                    ; |Text = "Serial is valid"
00401194  |>push    dword ptr [ebp+8]           ; |hOwner
00401197  |>call    <MessageBoxA>               ; \MessageBoxA
0040119C  |>xor     ecx, ecx
0040119E  |>/push    dword ptr [ecx*4+404411]
004011A5  |>|call    <__BigDestroy@4>
004011AA  |>|inc     ecx
004011AB  |>|cmp     ecx, 6
004011AE  |>\jnz     short 0040119E

 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).

rsatool1

Hallados los primos p y q, hallamos d (Calc. D).

rsatool4

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.

bigint_1

bigint_2

crackme_dihux_solved

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.

dihux_keygenme1_keygen

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());
}
});

Links


Warning: This challenge is still active and therefore should not be resolved using this information.  Aviso: Este reto sigue en
En esta ocasión vamos a hablar de una película de culto de los años 90, Hackers - Piratas Informáticos. La
Intro Hoy tenemos aquí un crackme del 2009 originario de crackmes.de. El Crackme está hecho en VB6, sin empacar y
La esperada cuarta entrega de La Jungla de Cristal se metió de lleno en el mundo de los Hackers. Cuando

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.

Table of Contents

Intro

Few years ago, I made the tool ART (Android Reverse Engineering) for automate the process of reverse android program, but I have to admit that APK Studio is a great tool or just a great alternative. This crackme is for the challenge Mobile 1 of canyouhack.it.

Decompiling

The crackme is given at Google Play, so the first step is to install and recover the APK for decompiling. The latter, I leave to you. Open the victim with APK Studio and view the content of Mobile1.java
Analyzing the code, we view that the correct password is “The*********r”.

Links