Cruehead’s Crackme 1.0 Keygen [1/3]

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


Aviso: Este crackme forma parte de una serie de pruebas de Yoire.com que todavía está en activo. Lo ético si
Introducción Aquí tenemos un CrackMe diferente a lo que estamos acostumbrados, ya que en vez del típico número de serie
Intro Hoy vamos a hacer algo diferente, vamos a hacer un keygen con la propia víctima. El término anglosajón para

CoSH’s Crackme 3 KeyGen

Intro

Hoy tenemos un crackme realizado en Visual C++ 6. Es el típico serial asociado a un nombre.

El algoritmo

Localizamos con Olly la rutina de comprobación del serial y empezamos a analizar. Vemos una serie de Calls que lo único que hacen es comprobar el tamaño de nuestro nombre y serial y si es <5 dígitos nos tira afuera.

saltos_iniciales

Una vez pasada la traba anterior procede con un bucle para el nombre y otro para el serial. Yo he metido deurus y 123456. El bucle del nombre hace xor al los dígitos ascii con un valor incremental a partir de 1. Reconvierte el valor resultante en su caracter correspondiente y lo almacena.

00401576     |.  B9 01000000   MOV ECX,1                         ; ECX = 1
0040157B     |.  33D2          XOR EDX,EDX
0040157D     |.  8B45 E4       MOV EAX,[LOCAL.7]                 ; EAX = Nombre
00401580     |>  8A18          /MOV BL,BYTE PTR DS:[EAX]         ; BL = digito que toque  <--
00401582     |.  32D9          |XOR BL,CL                        ; digito XOR ECX
00401584     |.  8818          |MOV BYTE PTR DS:[EAX],BL         ; sustituye el digito nombre por el resultante del xor
00401586     |.  41            |INC ECX                          ; ECX++
00401587     |.  40            |INC EAX                          ; Siguiente digito
00401588     |.  8038 00       |CMP BYTE PTR DS:[EAX],0
0040158B     |.^ 75 F3         \JNZ SHORT crackme3.00401580      ; Bucle -->

 Ejemplo:

d  e  u  r  u  s
64 65 75 72 75 73

(d)64 xor 1 = 65(e)
(e)65 xor 2 = 67(g)
(u)75 xor 3 = 76(v)
(r)72 xor 4 = 76(v)
(u)75 xor 5 = 70(p)
(s)73 xor 6 = 75(u)

Nombre:    deurus
Resultado: egvvpu

Hace lo mismo con el serial pero con el valor incremental a partir de 0xA (10).

00401593     |.  B9 0A000000    MOV ECX,0A                      ; ECX = A
00401598     |.  33D2           XOR EDX,EDX
0040159A     |.  8B45 F0        MOV EAX,[LOCAL.4]               ; EAX = Serial
0040159D     |>  8A18           /MOV BL,BYTE PTR DS:[EAX]       ; BL = digito que toque  <--
0040159F     |.  32D9           |XOR BL,CL                      ; BL XOR CL
004015A1     |.  8818           |MOV BYTE PTR DS:[EAX],BL       ; sustituye el digito serial por el resultante del xor
004015A3     |.  41             |INC ECX                        ; ECX++
004015A4     |.  40             |INC EAX                        ; Siguiente digito
004015A5     |.  8038 00        |CMP BYTE PTR DS:[EAX],0
004015A8     |.^ 75 F3          \JNZ SHORT crackme3.0040159D    ; Bucle -->

Ejemplo:

1  2  3  4  5  6
31 32 33 34 35 35

(1)31 xor A = 3B(;)
(2)32 xor B = 39(9)
(3)33 xor C = 3F(?)
(4)34 xor D = 39(9)
(5)35 xor E = 3B(;)
(6)36 xor F = 39(9)

Serial:    123456
Resultado: ;9?9;9

A continuación compara «egvvpu» con «;9?9;9» byte a byte.

KeyGen

El KeyGen quedaría así

for(int i = 0; i <= strlen(Nombre); i = i + 1)
                {
                        Serial[i] = (Nombre[i]^(i+1))^(0xA + i);
                }

 Links


Introducción Esta es la primera entrega de tres en las que vamos a  ver tres crackmes que todo reverser debería
Introducción Recién rescatados del inframundo que es mi disco duro, os traigo un paquete de seis crackmes facilones para vuestro
Warning: This challenge is still active and therefore should not be resolved using this information. Aviso: Este reto sigue en
Hace unos años cuando empecé a trastear con Android y animado por mi afición a la Ingeniería Inversa, decidí realizar

Andy’s Keygenme Keygen (AutoIt)

Introducción

 Hoy vamos a ver como extraer el script de un ejecutable compilado por Autoit, modificarlo y recompilarlo como nuestro keygen. Como comprobareis si no se ofusca o se toman otro tipo de medidas recuperar información sensible es muy sencillo.

AutoIt es un lenguaje freeware multiproposito y de automatización para Microsoft Windows. Es un Visual Basic Killer, ya que mejora las características de los ejecutables (entre otras portabilidad, velocidad y peso, no fat-coding), y facilitan la programación con un buen repertorio de funciones «pre-diseñadas», y usando un Basic de fácil aprendizaje. Se ha expandido desde sus comienzos de automatización incluyendo muchas mejoras en el diseño del lenguaje de programación y sobre todo en nuevas funcionalidades.

El Script

Func CHECKKEY($USER, $PASS)
Local $OPKEY = "", $SIG = ""
Local $USER_LEN = StringLen($USER)
Local $PASS_LEN = StringLen($PASS)
If $USER_LEN < $PASS_LEN Then
MsgBox(0, "ERROR", "Invalid username or key.")
Exit
ElseIf $USER_LEN < 4 Then
MsgBox(0, "ERROR", "Invalid username or key.")
Exit
EndIf
$PASS_INT = Int($USER_LEN / $PASS_LEN)
$PASS_MOD = Mod($USER_LEN, $PASS_LEN)
$OPKEY = _STRINGREPEAT($PASS, $PASS_INT) & StringLeft($PASS, $PASS_MOD)
For $INDEX = 1 To $USER_LEN
$SIG &= Chr(BitXOR(Asc(StringMid($USER, $INDEX, 1)), Asc(StringMid($OPKEY, $USER_LEN - $INDEX + 1, 1))))
Next
If $SIG = _STRINGREPEAT(Chr(32), $USER_LEN) Then
MsgBox(0, "INFO", "Your key was registered.")
Exit
Else
MsgBox(0, "INFO", "Your key is invalid.")
EndIf
EndFunc

 El Algoritmo

El algoritmo es tremendamente sencillo ya que es nuestro nombre al revés y en mayúsculas.

 Modificando el script para generar nuestro propio keygen

El decompilador se llama myAut2exe y tiene este aspecto.

01-09-2014 11-56-37

Programar en AutoIt es muy sencillo e intuitivo. Nuestro keygen quedaría así.

$MAIN = GUICreate("Another keygen by deurus", 300, 80, -1, -1, 382205952, 385)
$NAME_LBL = GUICtrlCreateLabel("Username", 5, 5, 60, 20, BitOR(4096, 1))
$NAME_INP = GUICtrlCreateInput("", 70, 5, 225, 20, 1)
$PASS_LBL = GUICtrlCreateLabel("Key", 5, 30, 60, 20, BitOR(4096, 1))
$PASS_INP = GUICtrlCreateInput("", 70, 30, 225, 20, 1)
$REGISTER = GUICtrlCreateButton("Register", 5, 55, 60, 20)
$GIVE_UP = GUICtrlCreateButton("Generate", 70, 55, 60, 20)    <- Change name of button, Give Up by Generate
$TASK = GUICtrlCreateButton("?", 140, 55, 20, 20)
$AUTHOR = GUICtrlCreateLabel("keygen by deurus", 165, 55, 130, 20, BitOR(4096, 1))
GUISetState(@SW_SHOW, $MAIN)
While True
    $MSG = GUIGetMsg()
    Switch $MSG
        Case $REGISTER
            Call("CHECKKEY", GUICtrlRead($NAME_INP), GUICtrlRead($PASS_INP))
        Case $GIVE_UP
            Call("GETKEY", GUICtrlRead($NAME_INP), GUICtrlRead($PASS_INP))    <- Add the function to the button
        Case $TASK
            MsgBox(0, "Info", "keygen by deurus")
        Case - 3
            Exit
    EndSwitch
    Sleep(15)
WEnd

Func GETKEY($USER, $PASS)        <- this is our keygen function
    Local $OPKEY = "", $SIG = ""
    Local $USER_LEN = StringLen($USER)
    Local $PASS_LEN = StringLen($USER)
    If $USER_LEN < 4 Then
        GUICtrlSetData($PASS_INP  ,"min 4 chars");
    Else
    For $INDEX = 1 To $USER_LEN
        $SIG = Chr(BitXOR(Asc(StringMid($USER, $INDEX, 1)), 32)) & $SIG
    Next
        GUICtrlSetData($PASS_INP  ,$SIG);
    EndIf
EndFunc

Func CHECKKEY($USER, $PASS)        <- check function, the original
    Local $OPKEY = "", $SIG = ""
    Local $USER_LEN = StringLen($USER)
    Local $PASS_LEN = StringLen($PASS)
    If $USER_LEN < $PASS_LEN Then
        MsgBox(0, "ERROR", "Invalid username or key.")
    ElseIf $USER_LEN < 4 Then
        MsgBox(0, "ERROR", "Invalid username or key.")
        Exit
    EndIf
    $PASS_INT = Int($USER_LEN / $PASS_LEN)
    $PASS_MOD = Mod($USER_LEN, $PASS_LEN)
    $OPKEY = _STRINGREPEAT($PASS, $PASS_INT) & StringLeft($PASS, $PASS_MOD)
    For $INDEX = 1 To $USER_LEN
        $SIG &= Chr(BitXOR(Asc(StringMid($USER, $INDEX, 1)), Asc(StringMid($OPKEY, $USER_LEN - $INDEX + 1, 1))))
    Next
    If $SIG = _STRINGREPEAT(Chr(32), $USER_LEN) Then
        MsgBox(0, "INFO", "Your key was registered.")
    Else
        MsgBox(0, "INFO", "Your key is invalid.")
    EndIf
EndFunc

Este es el resultado.

01-09-2014 12-18-28

Links


Intro Antes que nada, es importante saber que un archivo ELF en Linux es equivalente a un archivo EXE en
Introducción Este es un crackme de la web de Karpoff programado por Sotanez y realizado en Delphi. Como máximo nos
Se nos entrega un ELF que decompilado presenta este aspecto: Para resolver el juego y obtener una licencia válida, nos
El reto Se nos proporciona la imagen anterior y se nos invita a resolver la ecuación para el menor entero

Reversing – Nosotros y ChatGPT contra un ELF desde Windows

Table of Contents

Intro

Antes que nada, es importante saber que un archivo ELF en Linux es equivalente a un archivo EXE en Windows. Dicho esto, es bastante común encontrarnos con ejecutables ELF en diversos CTFs (Capture The Flag), y a menudo representan un desafío para aquellos no familiarizados con el uso cotidiano de Linux. Sin embargo, tengo una buena noticia si no eres aficionado de Linux: existen herramientas que permiten realizar un análisis preliminar para determinar si es necesario abordar el problema desde Linux o si podemos resolverlo directamente desde Windows. Estas herramientas facilitan una transición más cómoda para los usuarios de Windows, permitiéndoles interactuar eficazmente con archivos ELF.

ELF

Un archivo ELF (Executable and Linkable Format) es un formato común de archivo para archivos ejecutables, código objeto, bibliotecas compartidas y volcados de memoria en sistemas basados en Unix, como Linux. Es el estándar de formato de archivo para programas compilados y enlazados en este tipo de sistemas operativos.

La cabecera de un archivo ELF es una estructura de datos al comienzo del archivo que proporciona información esencial sobre el contenido y la forma de procesar el archivo. Esta cabecera es fundamental para que el sistema operativo y otros programas puedan interpretar correctamente el archivo ELF. Aquí están los componentes clave de la cabecera de un archivo ELF:

  1. Identificación (e_ident): Esta sección incluye la magia del archivo ELF, representada por los primeros cuatro bytes 0x7F 'E' 'L' 'F'. También incluye información como la clase del archivo (32 o 64 bits), la codificación de datos (endianness), y la versión del formato ELF.
  2. Tipo (e_type): Indica el tipo de archivo ELF, como EXEC (ejecutable), DYN (biblioteca compartida), REL (relocalizable), entre otros.
  3. Máquina (e_machine): Especifica la arquitectura de hardware para la cual se diseñó el archivo, por ejemplo, x86, ARM.
  4. Versión (e_version): La versión del formato ELF, generalmente establecida en 1.
  5. Punto de Entrada (e_entry): La dirección de memoria virtual donde comienza la ejecución del proceso.
  6. Desplazamiento del Program Header (e_phoff): Indica dónde comienza el encabezado del programa en el archivo.
  7. Desplazamiento del Section Header (e_shoff): Indica dónde comienza el encabezado de la sección en el archivo.
  8. Flags (e_flags): Banderas específicas del procesador.
  9. Tamaño de esta cabecera (e_ehsize): El tamaño de la cabecera ELF.
  10. Tamaño del Program Header (e_phentsize): El tamaño de una entrada del encabezado del programa.
  11. Número de entradas del Program Header (e_phnum): El número total de entradas en el encabezado del programa.
  12. Tamaño del Section Header (e_shentsize): El tamaño de una entrada del encabezado de la sección.
  13. Número de entradas del Section Header (e_shnum): El número total de entradas en el encabezado de la sección.
  14. Índice del Section Header Table (e_shstrndx): El índice del encabezado de la sección que contiene los nombres de las secciones.

El reto

Se nos proporciona un fichero de 20KB que rápidamente catalogamos como ELF.

Para realizar un análisis preliminar siempre uso DogBolt, que no es más que un decompilador online con la ventaja de que usa varios motores y de esta forma casi siempre te da una decompilación aceptable. La versión actual tiene disponibles 11 motores y además es open source, ¿Qué más se puede pedir?

Echamos un vistazo y enseguida encontramos algo interesante.

La flag parece codificada de modo que vamos a indagar acerca de la función FUN_0010285d

Dentro de la función FUN_0010285d vemos que nuestra flag codificada la procesa la función FUN_00102752

Aquí os diría que depende de vuestra experiencia en programación veríais que se está procesando byte a byte la cadena de entrada (param_1) y haciendo a cada byte un XOR (^) con el param_3 (que es 1 según vemos en la llamada de la función FUN_00102752), pero en estos tiempos que corren vamos a preguntar a ChatGPT que opina.

ChatGPT

Le pido a ChapGPT que me analice el código y me responde:

Este código en C define una función llamada FUN_00102752 que realiza una operación de XOR (exclusivo OR) byte a byte sobre un bloque de memoria. La función toma tres parámetros:

  1. long param_1: Este parámetro es tratado como una dirección de memoria. Se utiliza como la base de un bloque de memoria sobre el que se realizará la operación.
  2. ulong param_2: Este parámetro especifica el tamaño del bloque de memoria que será afectado por la operación.
  3. byte param_3: Este es el valor de un solo byte que se utilizará en la operación XOR.

El cuerpo de la función consiste en un bucle for que itera sobre el bloque de memoria:

  • int local_c se declara como una variable local y se inicializa en 0. Esta variable actúa como un contador para el bucle.
  • La condición del bucle (ulong)(long)local_c < param_2 asegura que el bucle se ejecute sobre el rango completo del bloque de memoria especificado por param_2.
  • Dentro del bucle, *(byte *)(param_1 + local_c) = *(byte *)(param_1 + local_c) ^ param_3; realiza la operación XOR. Aquí, *(byte *)(param_1 + local_c) accede al byte actual en el bloque de memoria. Este byte se modifica aplicándole un XOR con param_3. La operación XOR se realiza entre el byte actual en la memoria y el valor de param_3, y el resultado se escribe de nuevo en la misma ubicación de memoria.

En resumen, la función FUN_00102752 modifica un bloque de memoria aplicando una operación XOR con un valor dado (param_3) a cada byte dentro del rango de memoria especificado desde param_1 hasta param_1 + param_2. Este tipo de operación es común en tareas como la manipulación de datos para cifrado/descifrado o para la generación de patrones específicos en un bloque de datos.

by ChatGPT

Ahora imaginad que no sois muy dados a programar o simplemente estáis vagos de modo que volvemos a recurrir a ChatGPT con el promt «Haz un XOR 1 con javascript a la cadena: gmfzuihr^vr^o^drx^nod^shfiu|» a lo que responde:

function xorString(str) {
return Array.from(str).map(char => String.fromCharCode(char.charCodeAt(0) ^ 1)).join(»);
}

console.log(xorString(‘gmfzuihr^vr^o^drx^nod^shfiu|’));

by ChatGPT

Copiamos el código y lo pegamos en un entorno online como por ejemplo playcode.io.

Este es un ejemplo simple, pero ¿percibís su potencial?


La imagen de portada de esta entrada ha sido generada con ChatGPT.

Sotanez’s Crackme1 Keygen

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


Warning: This challenge is still active and therefore should not be resolved using this information. Aviso: Este reto sigue en
Introducción Activar un botón en memoria Activar el botón de forma permanente Serial Hardcodeado Links Introducción Este crackme pertenece a
Warning: This challenge is still active and therefore should not be resolved using this information. Aviso: Este reto sigue en
Intro Aquí tenemos un crackme clásico realizado en Visual C++. La única particularidad que tiene es que no muestra MessageBox

ThisIsLegal.com – User Challenge 1 (Javascript)

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

 Este es el típico reto de Javascript, no tiene mucha complicación pero he decidido dedicarle una entrada por que me llamó la atención lo que utiliza de usuario y clave.

El Script

function getStyle(el,styleProp)
{
    var x = document.getElementById(el);
    if (x.currentStyle)
        var y = x.currentStyle[styleProp];
    else if (window.getComputedStyle)
        var y = document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp);

if (y.substr(0, 1) == "#"){ return y; } else {
    
var value = y.split(',');

var R = value[0].substr(4);
var G = value[1];
var B = value[2].substr(0, value[2].length-1);

var RGB =  "#" + toHex(R)+ toHex(G)+toHex(B);

return RGB;

 }
}

function toHex(N) {
 if (N==null) return "00";
 N=parseInt(N); if (N==0 || isNaN(N)) return "00";
 N=Math.max(0,N); N=Math.min(N,255); N=Math.round(N);
 return "0123456789ABCDEF".charAt((N-N%16)/16)
      + "0123456789ABCDEF".charAt(N%16);
}

function pw (form)
{

   var d1, d2, d3;

if (navigator.appName == "Netscape"){
   d1= getStyle('content', 'background-color');
} else {
   d1= getStyle('content', 'backgroundColor');
}

     d2=form.Name.value;
     d3=form.Password.value;

  if (d2==d1.length) {
    if (d3==d1) {
      window.open ("../" + d1.substr(1, 10), "_self")
    } else {
      alert("Muhaha! Wrong!")
    }
  } else {
    alert("Muhaha! Wrong!")
  }
}

El Formulario

<div class="chal_box" style="padding:10px;">
<form name="form" action="" method="post">
        Username<br />
        <input id="inputd2" type="text" name="Name" value="" size="30" maxlength="30"><br />
        Password<br />
        <input id="inputd1" type="text" name="Password" value="" size="30" maxlength="30"><br /><br />

         <input type="button" name="Only a button" value="Enter Site" id="Only a button" class="btn" onclick="pw(this.form)">
</form>
</div>

Interpretando el Script

En el formulario vemos que llama a la función «pw» y ésta a su vez llama a la función «getStyle«, bueno, pués es tan simple como poner un «alert();» dentro de la función «pw» para cazar la clave. Con éste método podemos cazar la clave del 90% de este tipo de pruebas.

29-08-2014 01-21-17alert

Con esto ya tenemos la clave. El usuario responde a la siguiente sentencia «d2==d1.length«, es decir, es el número de dígitos de la clave.

¿Fácil no?

Links

Solución al Crackme 3 de Sotanez

Introducción

Este crackme pertenece a la página de Karpoff Spanish Tutor. Data del año 2000 y está realizado en «Borland Delphi 6.0 – 7.0», además, para resolverlo deberemos activar un botón y conseguir la clave de registro. La principal dificultad proviene a la hora de activar el botón ya que el serial es en realidad un serial hardcodeado muy sencillo.

Activar un botón en memoria

Existen numerosas herramientas para facilitarnos esta tarea, una de las más conocidas en el entorno del Cracking es «Veoveo» realizado por Crack el Destripador & Marmota hace ya unos añitos. Con el crackme ejecutado, ejecutamos VeoVeo y nos aparece el icono en la barra de tareas, hacemos click derecho y elegimos Activar Botones (manual) y ya tenemos el botón activado. Claro está que en cada ejecución del Crackme debemos de Re-activarlo.

17-02-2015 17-34-16

Activar el botón de forma permanente

Lo que siempre nos interesa es que el botón esté activado de forma permanente y eso nos exige un poco más de atención. En este caso nos enfrentamos a Delphi y no nos sirve ni Resource Hacker ni Dede. Cuando nos encontramos en un punto muerto el último recurso siempre es realizar un programa en Delphi con un botón activado y otro desactivado y compararlos con un editor hexadecimal para saber que cambia. Si hacemos esto llegaremos a la conclusión de que en Delphi el bit que equivale a desactivado es 8 y ha activado es 9. Con este simple cambio ya tenemos el crackme parcheado. Comentar que en este caso el crackme no tiene ningún timer ni ninguna rutina que desactive el botón de forma periódica, este es el caso más simple.

16-02-2015 05-22-40

16-02-2015 05-23-45

Serial Hardcodeado

Abrimos Ollydbg y en las «String references» encontramos los mensajes de versión registrada, pinchamos sobre ellos y vemos a simple vista la zona de comprobación del serial. Como podéis observar, el serial se vé a simple vista.

0045811A   |.  B8 10824500         MOV EAX,CrackMe3.00458210                 ;  ASCII "ESCRIBE ALGO JOER"
0045811F   |.  E8 D889FDFF         CALL CrackMe3.00430AFC
00458124   |.  EB 5C               JMP SHORT CrackMe3.00458182
00458126   |>  807D FF 4F          CMP BYTE PTR SS:[EBP-1],4F - O
0045812A   |.  75 56               JNZ SHORT CrackMe3.00458182
0045812C   |.  807D FE 41          CMP BYTE PTR SS:[EBP-2],41 - A
00458130   |.  75 50               JNZ SHORT CrackMe3.00458182
00458132   |.  807D FD 45          CMP BYTE PTR SS:[EBP-3],45 - E
00458136   |.  75 4A               JNZ SHORT CrackMe3.00458182
00458138   |.  807D FC 4B          CMP BYTE PTR SS:[EBP-4],4B - K
0045813C   |.  75 44               JNZ SHORT CrackMe3.00458182
0045813E   |.  807D FB 43          CMP BYTE PTR SS:[EBP-5],43 - C
00458142   |.  75 3E               JNZ SHORT CrackMe3.00458182
00458144   |.  807D FA 41          CMP BYTE PTR SS:[EBP-6],41 - A
00458148   |.  75 38               JNZ SHORT CrackMe3.00458182
0045814A   |.  807D F9 52          CMP BYTE PTR SS:[EBP-7],52 - R
0045814E   |.  75 32               JNZ SHORT CrackMe3.00458182
00458150   |.  807D F8 4B          CMP BYTE PTR SS:[EBP-8],4B - K
00458154   |.  75 2C               JNZ SHORT CrackMe3.00458182
00458156   |.  807D F7 20          CMP BYTE PTR SS:[EBP-9],20 - 
0045815A   |.  75 26               JNZ SHORT CrackMe3.00458182
0045815C   |.  807D F6 49          CMP BYTE PTR SS:[EBP-A],49 - I
00458160   |.  75 20               JNZ SHORT CrackMe3.00458182
00458162   |.  807D F5 4F          CMP BYTE PTR SS:[EBP-B],4F - O
00458166   |.  75 1A               JNZ SHORT CrackMe3.00458182
00458168   |.  807D F4 54          CMP BYTE PTR SS:[EBP-C],54 - T
0045816C   |.  75 14               JNZ SHORT CrackMe3.00458182
0045816E   |.  807D F3 20          CMP BYTE PTR SS:[EBP-D],20 - 
00458172   |.  75 0E               JNZ SHORT CrackMe3.00458182
00458174   |.  807D F2 41          CMP BYTE PTR SS:[EBP-E],41 - A
00458178   |.  75 08               JNZ SHORT CrackMe3.00458182
0045817A   |.  807D F1 59          CMP BYTE PTR SS:[EBP-F],59 - Y
0045817E   |.  75 02               JNZ SHORT CrackMe3.00458182
00458180   |.  B3 01               MOV BL,1
00458182   |>  80FB 01             CMP BL,1
00458185   |.  75 4C               JNZ SHORT CrackMe3.004581D3
00458187   |.  BA 2C824500         MOV EDX,CrackMe3.0045822C
0045818C   |.  8B86 F4020000       MOV EAX,DWORD PTR DS:[ESI+2F4]
00458192   |.  E8 B5EBFDFF         CALL CrackMe3.00436D4C
00458197   |.  BA 48824500         MOV EDX,CrackMe3.00458248                 ;  ASCII "VERSION REGISTRADA :)"

Serial = YA TOI KRACKEAO

16-02-2015 05-25-23

16-02-2015 05-25-38

Links


En el BTM anterior nos remontábamos al año 2006 para ver un pequeño gazapo ocurrido en la serie Dexter. En
Sinopsis Enemigo público (Enemy of the State) es una película de acción y suspense dirigida por Tony Scott, estrenada en
Introducción Este es un crackme de la web de Karpoff programado por Sotanez y realizado en Delphi. Como máximo nos
https://www.youtube.com/watch?v=iOYAn4l4wco Lista de reproducción

Blooper Tech Movie VII – Absentia 1×06 (S01E06)

En el BTM anterior nos remontábamos al año 2006 para ver un pequeño gazapo ocurrido en la serie Dexter. En esta ocasión vamos a hablar sobre un pequeño detalle de una serie actual, Absentia. No es un gazapo, pero es algo bastante poco creíble hoy día.

Hide me

La escena la protagoniza Emily Byrne (Stana Katic) y en ella se ve a Emily buscar algo sospechoso en un portátil.

Primer detalle

En la primera imagen y antes de que Emily haga clic en Documents, se puede apreciar un acceso directo que reza Browser con un icono de la bola del mundo y una lupa. Muy chulo pero para darle más credibilidad a la escena se podía mostrar un acceso directo de Chrome, Firefox o Internet Explorer que son los navegadores más usados.

Where is my Browser?

Where is my Browser?

Para rematar…

A lo que vamos. Emily decide mirar en la carpeta Documents > Videos y para su sorpresa está vacía. Pero como Emily es una mujer de recursos decide comprobar si hay archivos ocultos y para ello retoca las opciones de carpeta.

¡Tachán!, como por arte de magia aparecen todas las carpetas del supuesto asesino con todo tipo de vídeos incriminatorios. Como he comentado anteriormente, parece poco creíble pensar que algo que te puede llevar a la cárcel de por vida sea protegido de forma tan pobre.

Enlaces

Blooper Tech Movie XII – Enemigo público

Sinopsis

Enemigo público (Enemy of the State) es una película de acción y suspense dirigida por Tony Scott, estrenada en 1998. La historia sigue a Robert Clayton Dean (Will Smith), un abogado de Washington D.C. que se ve atrapado en una conspiración de vigilancia masiva cuando recibe, sin saberlo, una cinta de video que documenta el asesinato de un congresista a manos de un alto funcionario de la Agencia de Seguridad Nacional (NSA), interpretado por Jon Voight. La situación se complica cuando la NSA utiliza toda su tecnología de espionaje para seguir y neutralizar a Dean.

Dean encuentra ayuda en Edward «Brill» Lyle (Gene Hackman), un exanalista de la NSA convertido en un experto en vigilancia que vive en el anonimato. Juntos intentan descubrir la verdad y exponer la conspiración, mientras son perseguidos por la propia NSA. Un papel crucial también lo desempeña el personaje de Daniel Zavitz, interpretado por Jason Lee, un joven investigador que graba accidentalmente el asesinato y termina transmitiendo la evidencia a Dean. El elenco incluye además a Lisa Bonet, Regina King, Jack Black, Barry Pepper, y Seth Green.

Tecnología utilizada

En Enemigo Público, la tecnología juega un papel crucial no solo en la trama sino también en la ambientación de la película. La precisión y el realismo de los equipos informáticos utilizados contribuyen a la atmósfera de paranoia y vigilancia que define la narrativa.

El PC de Daniel Zavitz (Jason Lee)

Jason Lee, en su papel de Daniel Zavitz, utiliza un PC clónico, claramente identificado por el logo de Sun Microsystems en la torre del ordenador. Sin embargo, el sistema operativo que corre en esta máquina es Windows 3.1, una versión que, para 1998, ya estaba obsoleta, habiendo sido lanzada en 1992. Esta elección subraya el hecho de que Zavitz utiliza equipamiento más económico y anticuado, en contraste con la tecnología más avanzada de otros personajes.

Zavitz también utiliza Media Player, un reproductor de video básico integrado en Windows 3.1. Durante la reproducción del archivo de video crucial para la trama, se puede observar que la extensión del archivo es .CAM. Este tipo de archivo podría implicar un video capturado por una cámara, pero también sugiere (por otros fotogramas de la película) que el codec utilizado para comprimir el video podría ser QuickTime, permitiendo una reproducción cruzada entre diferentes sistemas operativos.

Además, Zavitz utiliza un reproductor portátil NEC Turbo Express, un dispositivo de videojuegos portátil de la época. En la película, este dispositivo es empleado de manera innovadora para reproducir y transferir datos, algo poco realista pero que añade dramatismo a la escena. La tarjeta PCMCIA de 200MB que Zavitz utiliza para almacenar el video es otro ejemplo de la tecnología de la época, reflejando la capacidad de almacenamiento portátil antes de la popularización de los dispositivos USB.

El Equipo de Edward «Brill» Lyle (Gene Hackman)

Por su parte, Gene Hackman, en su papel de Brill, maneja un sistema considerablemente más avanzado, utilizando Windows 98. Este sistema operativo, lanzado también en 1998, representaba lo más avanzado en términos de compatibilidad y usabilidad en ese momento, lo que refuerza la imagen de Brill como un experto en tecnología con acceso a mejores recursos.

Aunque en la película no se detalla el hardware específico de Brill, el hecho de que use Windows 98, junto con las capacidades de manipulación y decodificación de video que se muestran, sugiere que tiene acceso a tecnología de alta gama para la época. En una escena clave, se observa cómo Brill decodifica el video utilizando una interfaz gráfica llamativa, diseñada claramente para atraer la atención del espectador, más que para reflejar la realidad de la tecnología disponible en ese momento.

Conclusión

La producción de Enemigo Público es destacable por su atención al detalle en lo referente al equipamiento tecnológico de los personajes. El contraste entre el equipo más antiguo y económico utilizado por Daniel Zavitz (Jason Lee) y el sistema más avanzado de Edward Lyle (Gene Hackman) refleja de manera efectiva el trasfondo de los personajes. Zavitz, como investigador freelance, se maneja con recursos limitados, mientras que Lyle, con su pasado en la NSA y mayor poder adquisitivo, tiene acceso a tecnología más avanzada.

Otro detalle interesante es la diferenciación en el equipamiento dentro de la central de la NSA. Mientras los empleados comunes utilizan monitores CRT, que eran estándar en la época, el personaje de Thomas Reynolds (Jon Voight) dispone de una pantalla plana, lo que subraya su estatus superior dentro de la agencia. Estos detalles de producción contribuyen a la autenticidad y la profundidad visual de la película.

Sin embargo, la película no está exenta de licencias creativas que sacrifican el realismo tecnológico en favor del impacto visual. Un ejemplo claro es cuando un técnico de la NSA, a partir de un fotograma de un vídeo de seguridad, rota la imagen en 3D para simular lo que Zavitz podría haber introducido en la bolsa de Dean. Aunque esta secuencia añade dramatismo, carece de una base tecnológica realista.

Del mismo modo, la escena donde Brill decodifica el vídeo utilizando una interfaz visualmente llamativa es un claro ejemplo de cómo la película opta por elementos más glamurosos para captar la atención del espectador, alejándose de la realidad técnica, donde estos procesos serían mucho menos espectaculares y más funcionales. Además se pueden observar las siguientes curiosidades:

  • Se ve el escritorio de Windows 98 con fondo negro y tres aplicaciones abiertas, QuickTime for Windows, una carpeta y una imagen.
  • Una carpeta abierta con cuatro archivos DIR y nombres que nos hacen creer que uno está encriptado y otro no. Dos archivos de imagen con extensión TIF y dos archivos de vídeo con extensión MOV. Ojo porque DIR es la extensión de proyectos de Adobe Director, ahí lo dejo.
  • La animación muestra el 100% antes que la barra de progreso llegue al final.
  • Una vez decodificado se nos muestra el vídeo pero como se nos mostró anteriormente con el media player de Windows 3.1. Incluso se ve el icono de minimizar típico de Windows 3.1 en la parte superior izquierda (última imagen).

En resumen, Enemigo Público logra un equilibrio eficaz entre el realismo tecnológico y las exigencias dramáticas del cine. A pesar de algunas exageraciones en la representación de la tecnología, la atención al detalle en los aspectos técnicos y la diferenciación de equipos según los personajes y sus circunstancias es un testimonio del buen trabajo de producción que hace que la película siga siendo entretenida, incluso más de dos décadas después de su estreno.

Sotanez’s Crackme1 Keygen

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


AperiSolve es un conjunto de herramientas de análisis esteganográfico que nos ayuda a echar un primer vistazo cuando sospechamos que
Introducción Hoy tenemos aquí un bonito crackme matemático realizado por Spider. El crackme está realizado en ensamblador y precisamente por
AVISO: Debido a que este reto está en activo no publicaré a donde pertenece. Ya sabéis que los retos stego
Warning: This challenge is still active and therefore should not be resolved using this information. Aviso: Este reto sigue en

AperiSolve (Zsteg)

AperiSolve es un conjunto de herramientas de análisis esteganográfico que nos ayuda a echar un primer vistazo cuando sospechamos que una imagen esconde algo.

Zsteg es una herramienta especializada en la detección y extracción de información oculta en imágenes, especialmente en formatos PNG y BMP. Está orientada a la esteganografía basada en bit-planes y es muy popular en entornos CTF y análisis forense, gracias a su capacidad para automatizar búsquedas exhaustivas de datos escondidos en los bits menos significativos (LSB) y en configuraciones de color poco habituales. Su principal fortaleza es que no se limita a examinar un único plano: prueba sistemáticamente combinaciones de canales (R, G, B, A), número de bits, orden de lectura y posicionamiento, detectando patrones que podrían pasar inadvertidos en una revisión manual.

Entre sus características más destacadas se encuentran la identificación automática de firmas de archivos (ZIP, PNG, texto ASCII, GZIP, etc.), la extracción directa de bitstreams reconstruidos y el soporte para diferentes rutas de exploración, como b1,rgb,lsb,xy, que describen exactamente cómo se han recuperado los datos. Esta capacidad de correlacionar parámetros técnicos con resultados concretos convierte a zsteg en una herramienta muy eficiente tanto para localizar contenido oculto como para entender la técnica esteganográfica aplicada.

En AperiSolve se utiliza únicamente la parte de Zsteg encargada de ejecutar el análisis automático y devolver todas las detecciones posibles de esteganografía LSB en imágenes PNG y BMP. Concretamente, AperiSolve llama al comando zsteg <imagen> tal como está implementado en el módulo analyze_zsteg , y captura la salida completa línea por línea. Esta salida incluye todas las combinaciones probadas de bit-planes (b1, b2…), canales (r, g, b, a), orden de bits (lsb/msb) y métodos de recorrido (xy), junto con cualquier coincidencia que zsteg reconozca como firma de archivo o texto. Es decir, AperiSolve no aplica filtros ni interpretación adicional: muestra exactamente lo que zsteg detecta y lo organiza para que el usuario pueda identificar rápidamente si existe un archivo embebido, contenido ASCII, o algún patrón de interés.

En AperiSolve veremos algo como esto:

... 
b1,a,lsb,xy         .. 
b1,a,msb,xy         .. 
b1,rgb,lsb,xy       .. file: Zip archive data, at least v1.0 to extract, compression method=store
b1,rgb,msb,xy       .. 
b1,bgr,lsb,xy       .. 
b1,bgr,msb,xy       .. 
b1,rgba,lsb,xy      .. 
b1,rgba,msb,xy      .. file: OpenPGP Public Key
b1,abgr,lsb,xy      .. 
b1,abgr,msb,xy      .. file: OpenPGP Secret Key
b2,r,lsb,xy         .. 
b2,r,msb,xy         .. text: "P@UPUUPAAUU@"
b2,g,lsb,xy         .. text: "(ahOFyIS!"
...

Para entender mejor a que se refiere todo esto vamos a repasar lo básico.

¿Qué es LSB y qué es MSB?

Cuando hablamos de esteganografía en imágenes PNG/BMP, nos referimos a manipular bits dentro de los canales de color (R, G, B, A). Cada canal tiene un valor de 0–255, es decir, 8 bits:

R = 11001010
G = 00110101
B = 11100001

LSB Least Significant Bit (bit menos significativo). Es el bit más débil, el de la derecha:

1100101[0]   ← LSB

Modificarlo cambia muy poco el color, por eso se usa en esteganografía.
Ejemplo: cambiar 11001010 ↦ 11001011 no cambia el color perceptible.

MSB Most Significant Bit (bit más significativo). Es el bit más importante, el de la izquierda:

[1]1001010   ← MSB

Modificarlo sí altera mucho el color. A veces se usa pero suele ser detectable.

Cuando Zsteg muestra una línea del estilo b1,rgb,lsb,xy .. file: Zip archive data, está indicando que ha analizado la imagen extrayendo bits según la ruta especificada —en este caso, 1 bit por píxel (b1), combinando los canales rojo, verde y azul (rgb), utilizando el bit menos significativo (lsb) y recorriendo los píxeles en orden normal de lectura (xy)— y que, tras recomponer esos bits, el resultado coincide con la cabecera reconocible de un tipo de archivo real. Por eso aparece “file: Zip archive data”: significa que los bits ocultos forman un flujo válido cuya firma corresponde a un archivo ZIP. En otras ocasiones puede detectar texto ASCII, PNG, JPEG u otros formatos. En resumen, cuando Zsteg muestra esta línea no solo indica dónde se ocultan los datos, sino que confirma que lo recuperado es un archivo auténtico y probablemente extraíble, ya que la estructura binaria coincide con un formato conocido.

Si vemos que Zsteg nos ofrece algo interesante, podemos extraerlo mediante el comando:

zsteg -E b1,rgb,lsb,xy imagen.png > dump.bin

También es habitual usar herramientas como StegSolve. En este caso debemos dirigirnos a Analyse > Data extract para comprobar lo encontrado por zsteg y extraerlo mediante Save Bin.

Zsteg> Significado <StegSolve
b1Extrae 1 bit por canal (bit plano 0, el menos significativo).En Bit Planes, marca Red 0, Green 0, Blue 0. Solo esos.
rgbUsa R + G + B en ese orden para reconstruir los bytes.En Bit Plane Order, selecciona RGB.
lsbLee los bits empezando por el LSB (bit 0) antes que el MSB.En Bit Order, selecciona LSB First.
xyRecorre la imagen por filas (izquierda → derecha, arriba → abajo).En Extract By, elige Row.

Más allá de este caso concreto, conviene recordar que la esteganografía no se limita a los LSB: existen métodos basados en paletas, metadatos, manipulación de PNG chunks, secuencias alfa, audio incrustado o capas completas en formatos no comprimidos. Por ello, un análisis completo debería combinar la búsqueda clásica de LSB con herramientas complementarias como binwalk, foremost, exiftool, strings, o incluso análisis manual de cabeceras hexadecimales.

Keygen para el CrackMe Pythagoras de Spider

Introducción

Hoy tenemos aquí un bonito crackme matemático realizado por Spider. El crackme está realizado en ensamblador y precisamente por eso, vamos a tener que lidiar con ciertas peculiaridades al realizar el keygen con un lenguaje de bajo nivel.

Al inicio comprueba la longitud del nombre y de el número de serie. El nombre debe tener al menos 6 caracteres y el número de serie debe tener 10. Os adelanto ya que la asignación de memoria del nombre es de 9 caracteres, es decir, da igual la longitud del nombre que solo va a usar 9.

004014AD | E8 1A 02 00 00           | call <pythagoras.GetWindowTextA>        | ;Lee el nombre
004014B2 | 83 F8 06                 | cmp eax,6                               | ;Nombre >=6 caracteres
004014B5 | 0F 82 03 01 00 00        | jb pythagoras.4015BE                    |
004014BB | 6A 14                    | push 14                                 |
004014BD | 68 D9 31 40 00           | push pythagoras.4031D9                  | ;004031D9:"1234567890"
004014C2 | FF 35 10 32 40 00        | push dword ptr ds:[403210]              |
004014C8 | E8 FF 01 00 00           | call <pythagoras.GetWindowTextA>        | ;Lee el serial
004014CD | 83 F8 0A                 | cmp eax,A                               | ;Serial debe tener 10 (A) caracteres
004014D0 | 0F 85 E8 00 00 00        | jne pythagoras.4015BE                   |

Sabiendo esto introducimos Nombre: deurus y Serial: 1234567890

A continuación chequea que nuestro serial tenga caracteres hexadecimales.

004014DA | 8A 81 D9 31 40 00        | mov al,byte ptr ds:[ecx+4031D9]         | ; ecx+004031D9:"1234567890"
004014E0 | 3C 00                    | cmp al,0                                | ; contador del bucle
004014E2 | 74 1F                    | je pythagoras.401503                    | ; fin del bucle
004014E4 | 3C 30                    | cmp al,30                               | ; 0x30 = número 1
004014E6 | 0F 82 D2 00 00 00        | jb pythagoras.4015BE                    | ; < 30 bad boy
004014EC | 3C 46                    | cmp al,46                               | ; 0x46 = letra F
004014EE | 0F 87 CA 00 00 00        | ja pythagoras.4015BE                    | ; > 46 bad boy
004014F4 | 3C 39                    | cmp al,39                               | ; 0x39 = número 9
004014F6 | 76 08                    | jbe pythagoras.401500                   | ; <=39 ok continua el bucle
004014F8 | 3C 41                    | cmp al,41                               | ; 0x41 = letra A
004014FA | 0F 82 BE 00 00 00        | jb pythagoras.4015BE                    | ; <41 bad boy
00401500 | 41                       | inc ecx                                 | ; contador += 1
00401501 | EB D7                    | jmp pythagoras.4014DA                   | ; bucle

Continua realizando un sumatorio con nuestro nombre, pero tenemos que tener especial cuidado al tratamiento de los datos, ya que el crackme al estar hecho en ensamblador puede jugar con los registros como quiere y eso nos puede inducir a error.

0040150B | 3C 00                    | cmp al,0                                | ; ¿Fin bucle?
0040150D | 74 05                    | je pythagoras.401514                    | ; Salta fuera del bucle si procede
0040150F | 02 D8                    | add bl,al                               | ; bl = bl + al
00401511 | 41                       | inc ecx                                 | ; contador +=1
00401512 | EB F1                    | jmp pythagoras.401505                   | ; bucle

Si os fijáis utiliza registros de 8 bits como son AL y BL. Debajo os dejo una explicación de EAX pero para EBX es lo mismo.

               EAX
-----------------------------------
                         AX
                  -----------------
                     AH       AL
                  -------- --------
00000000 00000000 00000000 00000000
 (8bit)   (8bit)   (8bit)   (8bit)
 

  EAX     (32 bit)
--------
     AX   (16 bit)
    ----
    AHAL  (AH y AL 8 bit)
--------
00000000

El uso de registros de 8 bits nos implica tomar precauciones al realizar el Keygen debido a que por ejemplo, en .Net no tenemos la capacidad de decirle que haga una suma y que nos devuelva solamente 8 bits del resultado. Veamos como ejemplo para el nombre «deurus». La suma de los caracteres hexadecimales quedaría:

64+65+75+72+75+73 = 298, es decir, EAX = 00000298

Pero recordad que el crackme solo cogerá el 98 que es lo correspondiente al registro AL. De momento nos quedamos con nuestro SUMNOMBRE = 98.

Primera condición

A continuación coge los dos primeros caracteres del serial y les resta nuestro SUMNOMBRE y comprueba que el resultado esté entre 4 (0x4) y -4 (0xFC).

0040154B | 0F B6 05 F3 31 40 00     | movzx eax,byte ptr ds:[4031F3]          |
00401552 | 8A C8                    | mov cl,al                               |
00401554 | 2A CB                    | sub cl,bl                               | ; CL = CL - BL | CL = 12 - 98 = 7A
00401556 | 80 F9 04                 | cmp cl,4                                | ; Compara CL con 4
00401559 | 7F 63                    | jg pythagoras.4015BE                    | ; Salta si es mayor
0040155B | 80 F9 FC                 | cmp cl,FC                               | ; Compara CL con FC (-4)
0040155E | 7C 5E                    | jl pythagoras.4015BE                    | ; Salta si es menor

Como veis, el resultado de la resta da 7A (122) que al ser mayor que 4 nos echa vilmente. Aquí de nuevo utiliza registros de 8 bits por lo que debemos tener cuidado con las operaciones matemáticas para no cometer errores, veamos un ejemplo para clarificar de aquí en adelante.

Utilizando 8 bits
-----------------
12 - 98 = 7A que en decimal es 122

Utilizando 16 bits
------------------
0012 - 0098 = FF7A que en decimal es -134

Ahora ya veis la diferencia entre FC (252) y FFFC (-4). Estrictamente, el crackme comprueba el rango entre 4 (4) y FC (122) al trabajar con registros de 8 bits pero nosotros, como veremos más adelante tomaremos el rango entre 4 y -4. De momento, para poder continuar depurando cambiamos los dos primeros caracteres del serial de 12 a 98, ya que 98 – 98 = 0 y cumple la condición anterior.

Introducimos Nombre: deurus y Serial: 9834567890

Segunda condición

Analicemos el siguiente código.

00401560 | F7 E0                    | mul eax                                 | ; EAX = EAX * EAX
00401562 | 8B D8                    | mov ebx,eax                             | ; EBX = EAX
00401564 | 0F B7 05 F4 31 40 00     | movzx eax,word ptr ds:[4031F4]          | ; EAX = 3456 (4 dígitos siguientes del serial)
0040156B | F7 E0                    | mul eax                                 | ; EAX = EAX * EAX
0040156D | 03 D8                    | add ebx,eax                             | ; EBX = EBX + EAX
0040156F | 0F B7 05 F6 31 40 00     | movzx eax,word ptr ds:[4031F6]          | ; EAX = 7890 (4 últimos dígitos del serial)
00401576 | F7 E0                    | mul eax                                 | ; EAX = EAX * EAX
00401578 | 33 C3                    | xor eax,ebx                             | ; EAX
0040157A | 75 42                    | jne pythagoras.4015BE                   | ; Salta si el flag ZF no se activa

En resumen:

  • 98 * 98 = 5A40 (98²)
  • 3456 * 3456 = 0AB30CE4 (3456²)
  • 0AB36724 + 5A40 = 0AB36724
  • 7890 * 7890 = 38C75100 (7890²)
  • 38C75100 XOR 0AB36724 = 32743624
  • Si el resultado del XOR no es cero nuestro serial no pasa la comprobación.

Es decir, Pitágoras entra en escena -> 7890² = 98² + 3456²

Serial = aabbbbcccc

Tercera condición

Finalmente comprueba lo siguiente:

0040157C | 66 A1 F6 31 40 00        | mov ax,word ptr ds:[4031F6]             | ; AX = 7890
00401582 | 66 2B 05 F4 31 40 00     | sub ax,word ptr ds:[4031F4]             | ; AX = 7890 - 3456 = 443A
00401589 | 2C 08                    | sub al,8                                | ; AL = 3A - 8 = 32
0040158B | 75 31                    | jne pythagoras.4015BE                   | ; Si el resultado de la resta no ha sido cero, serial no válido
0040158D | 6A 30                    | push 30                                 |
0040158F | 68 B0 31 40 00           | push pythagoras.4031B0                  | ;004031B0:":-) Well done!!!"
00401594 | 68 7F 31 40 00           | push pythagoras.40317F                  | ;0040317F:"Bravo, hai trovato il seriale di questo CrackMe!"
00401599 | FF 75 08                 | push dword ptr ds:[ebp+8]               |

En resumen:

  • 7890 – 3456 – 8 = 0

Creación del Keygen

Nuestro serial tiene que cumplir tres condiciones para ser válido.

  • a – SUMNOMBRE debe estar entre 4 y -4
  • c² = a² + b²
  • c – b – 8 = 0

Como hemos dicho anteriormente, tomaremos el SUMNOMBRE y le sumaremos y restaremos valores siempre y cuando el resultado esté entre 4 y -4. Para deurus hemos dicho que el SUMNOMBRE es 98 por lo que los posibles valores de «a» se pueden ver debajo. Además debemos tener en cuenta que el crackme solo lee los 9 primeros dígitos del nombre.

98-4 = 94		
98-3 = 95		
98-2 = 96		
98-1 = 97		
98-0 = 98		
98+1 = 99		
98+2 = 9A		
98+3 = 9B		
98+4 = 9C

Es evidente que para encontrar el valor de «c» vamos a tener que utilizar fuerza bruta chequeando todos los valores  de «b» comprendidos entre 0 y FFFF (65535). Además, como trabajaremos en un lenguaje de alto nivel, debemos descartar los resultados decimales. Esto nos limitará los seriales válidos asociados a un determinado nombre. Si realizáramos el keygen en ensamblador obtendríamos bastantes más seriales válidos.

Una vez encontrados los valores enteros de la operación «c² = a² + b²», se debe cumplir que «c – b – 8 = 0», lo que nos limitará bastante los resultados.

    Private Sub btn_generar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_generar.Click
        Try
            If txt_nombre.TextLength > 5 Then
                lst_serials.Items.Clear()
                Dim tmp, c, cx As String
                Dim sumanombre, tmp2 As Integer
                If txt_nombre.TextLength > 9 Then tmp2 = 8 Else tmp2 = txt_nombre.TextLength - 1
                'Calculo el SUMNOMBRE
                For i = 0 To tmp2
                    sumanombre += Asc(Mid(txt_nombre.Text, i + 1, 1)) 'Acumulo suma
                    tmp = Strings.Right(Hex(sumanombre).ToString, 2)  'Solo 8 bits (Registro AL)
                    sumanombre = Val("&H" & tmp) 'Paso a decimal
                Next
                tmp = Strings.Right(Hex(sumanombre).ToString, 2)
                sumanombre = CInt("&H" & tmp)
                txtdebug.Text = "- SumNombre = " & Hex(sumanombre) & vbCrLf
                txtdebug.Text &= "----------------------------------------------" & vbCrLf
                Dim a(8) As Integer
                '
                'a - sumanombre >=4 y <=4
                '
                a(0) = sumanombre - 4
                a(1) = sumanombre - 3
                a(2) = sumanombre - 2
                a(3) = sumanombre - 1
                a(4) = sumanombre
                a(5) = sumanombre + 1
                a(6) = sumanombre + 2
                a(7) = sumanombre + 3
                a(8) = sumanombre + 4
                txtdebug.Text &= "- Posibles valores de 'a'" & vbCrLf
                For i = 0 To a.Length - 1
                    txtdebug.Text &= Hex(a(i)) & " "
                Next
                txtdebug.Text &= "----------------------------------------------" & vbCrLf
                txtdebug.Text &= "- Buscando valores de b y c" & vbCrLf
                txtdebug.Text &= "Serial = aabbbbcccc" & vbCrLf
                '
                'c = sqr(a^2 + b^2)
                '
                txtdebug.Text &= "(1) c = raiz(a^2 + b^2)" & vbCrLf
                txtdebug.Text &= "(2) c - b - 8 = 0" & vbCrLf
                For i = 0 To a.Length - 1 ' todas las posibilidades de a
                    For b = 0 To 65535 'b -> 0000 - FFFF
                        c = Math.Sqrt(a(i) ^ 2 + b ^ 2)
                        If c.Contains(".") Then 'busco enteros
                        Else
                            cx = c - b - 8
                            cx = Hex(cx).PadLeft(4, "0"c)
                            lbl_info.Text = cx
                            If cx = "0000" Then
                                txtdebug.Text &= " (1) " & Hex(c).PadLeft(4, "0"c) & " = raiz(" & Hex(a(i)).PadLeft(2, "0"c) & "^2 + " & Hex(b).PadLeft(4, "0"c) & "^2)" & vbCrLf
                                lst_serials.Items.Add(Hex(a(i)).PadLeft(2, "0"c) & Hex(b).PadLeft(4, "0"c) & Hex(c).PadLeft(4, "0"c))
                                txtdebug.Text &= " (2) " & Hex(c).PadLeft(4, "0"c) & " - " & Hex(b).PadLeft(4, "0"c) & " - 8 = 0" & vbCrLf
                            End If
                        End If
                        Application.DoEvents()
                    Next
                Next
                lbl_info.Text = "Búsqueda finalizada"
            End If
        Catch ex As Exception
            MsgBox(ex.ToString)
        End Try

Enlaces

QR Stego Challenge

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

Ya sabéis que los retos stego son muy variopintos. El otro día me encontré con uno que parecía que iba a ser complejo pero en realidad era bastante sencillo.

Tras varias pruebas complejas infructuosas, se me ocurrió descomponer por canales y efectivamente ese era el camino. Para ello yo utilicé la herramienta StegSolve de mi querido Caesum, pero podéis resolverlo incluso online con Pinetools.

Descomposición RGB

ThisIsLegal.com – Realistic Challenge 2

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 2: You have heard about people being targeted by a new religion called Egitology. Another hacker infiltrated the group and discovered that the list of people they target is stored on the site but he doesn’t know where.

Break into the site, find the file and remove it. Also leave no evidence that you was ever there so they wont realise until its too late!

El enunciado del reto nos dice que tenemos que localizar la lista de objetivos y eliminarla sin dejar evidencias.

Analizando la seguridad de la víctima

Echamos un vistazo y vemos que tienen un Login para usuarios registrados, este será nuestro primer testeo.
Lo primero que se no viene a la cabeza con un formulario de este tipo es Inyección SQL, probamos varios métodos y tenemos suerte.
User: admin
Pass: ‘ or 1=1–‘;
 
 Vemos que hemos entrado como admin y enseguida nos llama la atención «Back up Database«. Pulsamos a ver que pasa.
 Obtenemos el hash de las claves de los usuarios Admin y SuperAdmin. Por suerte son hashes MD5. Obtenemos la clave de SuperAdmin y nos loguemos.

Solo nos queda borrar la lista de objetivos y nuestras huellas. Para ello borramos los siguientes archivos y reto superado.

Lista de objetivos: root/misc/targets
Logs: root/images/logs

Links