[Tutorial] Crackme de ESET para Ekoparty 2011

Iniciado por PeterPunk77, 23 Noviembre 2011, 14:25 PM

0 Miembros y 3 Visitantes están viendo este tema.

PeterPunk77

Buenas a todos. Lo cierto es que no suelo escribir ningún tutorial porque cuando lo hago tardo muchísimo más en crearlo que lo que he tardado en saltarme una protección y crear un parche/keygen. Y eso me desespera. Pero el siguiente lo he escrito por deferencia al autor.
El crackme en cuestión fue un desafío publicado a mediados de Agosto con motivo de la Ekoparty de este año:
http://blogs.eset-la.com/laboratorio/2011/08/15/crackme-de-eset-para-ekoparty-2011/
Los que lo hayáis estudiado o los que lo hagáis sin leer el tutorial veréis que se trata de un crackme muy simple y que resulta obvio de "keygenear" (inventando palabras desde ...). Pero tal vez no os deis cuenta de lo bien programado que está el manejador de excepciones, así que publico este tutorial (previamente publicado en otros foros) porque espero que sea instructivo para cualquier persona que comienza en este apasionante mundo de la ingeniería inversa.

Saludos.

PeterPunk77

Tutorial del sencillo pero interesante crackme de ESET

Primero debería haber abierto el crackme con el PEiD o cualquier otro programa, pero confiando en la experiencia lo abrí sin más con el OllyDbg. Bien, parecía programado en MASM32, así que seguro que iba a estar todo bastante claro, además es el lenguaje que normalmente utilizo para mis crackmes y keygens.

Veo que no tiene mensaje de "chico bueno" y en seguida aprecio que lo primero que hace tras pulsar el botón OK es poner un controlador de errores. Supongo el error que busca pero por el momento no le hago caso. Luego lee el nombre introducido (mínimo 4 letras, máximo 19) y entra en un procedimiento 0x401000 que parece la inicialización de un MD5, así que paso de las dos siguientes llamadas y compruebo lo que hizo. Pues tenía razón, veo en el dump el hash MD5 de mi nick "PeterPunk" (empieza por 8D y acaba en 9D). A continuación suma los 16 bytes (más exactamente conjuntos de 8 bits) que componen el hash, y multiplica el resultado por 3. Así que para "PeterPunk" obtengo 0x163E.

Unas imágenes para aclarar esto:


Vemos como el PEiD coincide conmigo tanto en el lenguaje de programación como en el uso del hash MD5.


Esta es la parte de código que acabo de comentar.


Y en ésta apreciamos como en 0x404344 se encuentra el MD5 de "PeterPunk".

Lo siguiente que hace el crackme es leer el serial (número entero con signo). Al número introducido como serial se le suma el resultado del cálculo anterior y se le resta 0x42B8. Luego divide 1 entre el resultado anterior y muestra el mensaje de "Chico malo".

Obviamente y aunque el cracker en cuestión no entienda de excepciones va a suponer que lo único a lo que aspira es a que esa división sea entre 0, y a ver que pasa. Así que probamos

17080 (0x42B8) - 5694 (0x163E) = 11386 (qué número más bonito, acaba en 386). Probamos con la dupla "PeterPunk", "11386" y por arte de magia obtengo un mensaje de "chico bueno".

Otra tanda de imágenes:


Aquí vemos la parte de código que acabo de comentar y apreciamos que no hay comparación posible del serial introducido.  Y aparentemente obligatoriedad de mostrar el mensaje de "Chico malo". Por lo que sólo parece posible forzar una división por 0.


Esta es mi dupla típica. "PeterPunk" y "81818181" que irremediablemente siempre me devuelve el mensaje de error.


Si meto el valor que fuerza una división por 0 me muestra un mensajito de que soy bueno.

Por tanto vemos que cualquier persona que comience con el maravilloso mundo de la ingeniería inversa va a poder resolver el crackme, pero igual no se dan cuenta de lo verdaderamente interesante del mismo, el procedimiento programado para el control de excepciones.

Como he comentado con anterioridad en el primer vistazo del crackme reparé en que existía un procedimiento para controlar las posibles excepciones. Está definido en:
00402353   |.  BE 62224000        MOV ESI,00402262
00402358   |.  56                 PUSH ESI
00402359   |.  64:FF35 00000000   PUSH DWORD PTR FS:[0]
00402360   |.  64:8925 00000000   MOV FS:[0],ESP
y vemos que, por tanto, ese manejador está en 0x402262.

Lo voy a ir despiezando para comentar que es lo que hace cada cosa:

00402265   |.  8B5C24 08            MOV EBX,[ESP+8]Con lo que logramos que EBX señale a la estructura EXCEPTION_RECORD (http://msdn.microsoft.com/en-us/library/aa363082(v=VS.85).aspx).

A continuación:
00402269   |.  813B 940000C0        CMP DWORD PTR [EBX],C0000094
0040226F   |.  75 43                JNZ SHORT 004022B4
00402271   |.  E8 D6FFFFFF          CALL 0040224C
Si el código de la excepción es 0xC0000094 (EXCEPTION_INT_DIVIDE_BY_ZERO) llamamos al procedimiento 0x40224C que simplemente cambia el mensaje de "Bad boy!" por "Good boy" por medio de unos xor.

00402276   |.  8B7B 0C              MOV EDI,[EBX+C]
00402279   |.  83C7 16              ADD EDI,16
Aquí, lo que hacemos es que EDI apunte a la instrucción 0x40241B (por si no os coinciden las derecciones, va a ser siempre la siguiente a la llamada del MessageBox de "chico bueno", y ¿por qué?, porque [EBX+C] (EXCEPTION_RECORD + 0Ch) apunta a la dirección que produjo el error (la de DIV EBX) que en mi caso se trata de 0x402405, así que al sumarle 0x16 bytes vamos a apuntar siempre a la instrucción siguiente al MessageBox.

0040227C   |.  8B4424 10            MOV EAX,[ESP+10]Con esto logramos que EAX apunte a la estructura CONTEXT que contiene muchísima información (http://msdn.microsoft.com/en-us/library/ms679284(v=VS.85).aspx).

00402280   |.  C700 10000100        MOV DWORD PTR [EAX],10010
00402286   |.  8108 07000100        OR DWORD PTR [EAX],10007
Esto nos cambia las banderas de la estructura (ContextFlags) que controlan la información que guarda la estructura. Particularmente creo que no hace falta ya que por defecto nos va a aparecer con un valor de 0x1003F (información de todo) pero el crackme lo cambia a 0x10017 (CONTEXT_CONTROL or CONTEXT_INTEGER or CONTEXT_EGMENTS or DEBUG_REGISTERS).

0040228C   |.  8978 04              MOV [EAX+4],EDI
0040228F   |.  C740 18 01010000     MOV DWORD PTR [EAX+18],101
Aquí empieza lo bueno. Recordamos que EDI apuntaba a la instrucción siguiente al MessageBox. Bien, pues ahora lo guardamos en [EAX+4] (CONTEXT + 4h) que es el Debug Register #0, y en [EAX+18] (CONTEXT + 18h) que es el Debug Register 7, más conocido como DR7 o Debug Control, guardamos 0x101. Pues lo que acabamos de hacer es poner un BreakPoint eXecution en la dirección a la que apunta EDI. Si bajáis los PDFs de los manuales de desarrolladores de software para arquitecturas Intel 64 e IA-32 de la web de Intel, veréis que de el Debug Register #0 al #3 hacen referencia a las direcciones de los 4 breakpoints que se pueden usar y el Debug Control Register (DR7) controla la activación o desactivación de los mismos así como de sus condiciones. En este caso en este DR7 sólo hemos marcado el bit #0 (bp local activado en el primer breakpoint, que es el DR0) y el #8 (activado bp local exacto, que según Intel no está soportado desde el P6 pero recomiendan su uso por retrocompatibilidad o futura reimplementación).

00402296   |.  83EF 12              SUB EDI,12
00402299   |.  89B8 B8000000        MOV [EAX+B8],EDI
Vale, ahora hacemos que EDI apunte en mi caso a 0x402409 que para todos va a ser tercer parámetro del MessageBox (el título) y lo guardamos en [EAX+B8] (CONTEXT + 0B8h) que es el EIP, bueno exactamente el EIP en el momento que se produjo la excepción, así que si os fijáis, el valor que tiene [EAX+B8] antes de volcarle la nueva es el DIV EBX que produjo la división por 0. ¿Y para qué se cambia este valor? para que cuando se salga de este controlador de errores y el sistema operativo devuelva el control del programa a su rutina normal siga ejecutándose desde aquí. ¡Pero nos comemos el primer parámetro del MessageBox (uType) que controla los botones e iconos del mismo!. Tranquilos, el programador sabía lo que hacía:

0040229F   |.  83A8 C4000000 04     SUB DWORD PTR [EAX+C4],4
004022A6   |.  8B90 C4000000        MOV EDX,[EAX+C4]
004022AC   |.  C702 40000000        MOV DWORD PTR [EDX],40
Le resta 4 a [EAX+C4] (CONTEXT + 0C4h) que es el valor del ESP en el momento de la excepción. O sea, que modificamos el valor de la pila, como si hubiésemos hecho un "push dword" más y en esa dirección de la pila guardamos el valor 0x40 (MB_ICONINFORMATION) ya que lo que estamos es creando el parámetro que nos faltaba para el MessageBox y ahora el programa cuando siga su curso, ya no va a ejecutar el "PUSH 10h" como 4º parámetro del mensaje, que le otorgaría el MB_ICONERROR, sino que ha sido sustituido por un ficticio "PUSH 40h" (decrementando el valor de ESP y copiando ahí directamente el parámetro que queríamos).

Todo esto está muy bien, pero ¿para qué hemos creado un punto de ruptura en la instrucción siguiente al mensaje? Pues porque al llegar a esa instrucción, va a saltar la excepción STATUS_SINGLE_STEP (0x80000004) que también está controlada en el código manejador de excepciones:
004022B4   |> \813B 04000080        CMP DWORD PTR [EBX],80000004
004022BA   |.  75 37                JNZ SHORT 004022F3
004022BC   |.  E8 8BFFFFFF          CALL 0040224C
004022C1   |.  8B4424 10            MOV EAX,[ESP+10]
004022C5   |.  C700 07000100        MOV DWORD PTR [EAX],10007
004022CB   |.  8108 10000100        OR DWORD PTR [EAX],10010
004022D1   |.  C740 04 00000000     MOV DWORD PTR [EAX+4],0
004022D8   |.  C740 18 00000000     MOV DWORD PTR [EAX+18],0
004022DF   |.  8348 18 00           OR DWORD PTR [EAX+18],0
004022E3   |.  8148 18 00040000     OR DWORD PTR [EAX+18],400


O sea, como hemos puesto el breakpoint, cuando el código llega a esa instrucción (tras mostrar el mensaje de "Chico bueno"), nos salta una excepción, y con nuestro controlador de excepciones volvemos al procedimiento 0x402262.Ahí primero va a comprobar, como hemos visto antes, que el error sea 0xC0000094 (EXCEPTION_INT_DIVIDE_BY_ZERO) y como no lo es ya nos salta a la parte de código que acabo de pegar.

Al igual que antes vemos que EAX va a apuntar a la estructura CONTEXT.

Después vuelve a llamar al procedimiento que cambia el mensaje (esta vez el de "Chico bueno" por el de "Chico malo") para que no quede el bueno fijo ya que sino, aunque a continuación metiésemos un serial malo nos mostraría el bueno (eso sí, con el icono de error en el mensaje).

También vuelve a cambiar las banderas (ContextFlags) aunque sigo convencido de que esto no hace falta y esta vez borra el contenido de [EAX+4] (Debug Register #0) y cambia el valor de [EAX+18] (Debug Control o DR7) por 0x400. O sea que elimina el BPX que antes había puesto. Realmente para esto bastaría con poner a 0 el bit #0 del DR7, pero de todas formas lo normal para eliminar los breakpoints es poner a 0 ese DR7. Aquí, el crackme activa el bit #10 (0x400 = 100 0000 0000) pero lo cierto es qué no sé el motivo ya que en el manual de Intel, los bits #10, #11, #12, #14 y #15 de este Debug Control Register no están descritos, lo cual me hace suponer que no tienen ninguna utilidad si bien es cierto que en la figura 16.1 de dicho manual el bit #10 aparece con un 1 mientras que los otros cuatro con 0.


Este es el código del manejador de excepciones que realmente es el corazón del crackme.

Y eso es todo amigos, para cualquier duda u observación dejen un comentario a continuación.

Gracias a todos por leer este "ladrillo" y sobre todo gracias al programador del crackme por tomarse su tiempo en la construcción del manejador de excepciones.

Saludos.

.:UND3R:.

Excelente tutorial :D, genial que hayas tocado detalladamente el uso que le da el crackme SEH instalado.

Saludos  ;-)

Solicitudes de crack, keygen, serial solo a través de mensajes privados (PM)

karmany

Excelente trabajo PeterPunk77.

Cierto, como dices, es que hacer un tutorial completo como has hecho requiere mucho tiempo.

¿Tú no estás entre los cinco ganadores?

Shamaroot

Este tema de Cracking o Ingenieria Inversa lo encuentro super interesante pero aún no se programar y eso es clave. . . si, por mientras observare de lejos (pero sin perder distancia) ya que el tema me queda grande.

Saludos !!
El conocimiento es libre.

PeterPunk77

Cita de: karmany en 26 Noviembre 2011, 18:23 PM¿Tú no estás entre los cinco ganadores?
Buenas karmany, no estoy entre los ganadores porque antes del sorteo se pusieron en contacto con todos nosotros para ver quien podría asistir. Y como el asunto era en Argentina y yo estoy al otro lado del charco rapidamente me desvinculé de todo.
Lo cierto es que cuando lo solucioné ya sabía que no iba a ir, pero me gustó cómo estaba programado el manejador de excepciones del crackme y envié la solución para felicitar al programador. Un chico, muy majo por cierto, que me envió un correo para agradecerme las felicitaciones que le envié por el crackme.

.:UND3R:.

Cita de: Shama|TwoH en 26 Noviembre 2011, 19:12 PM
Este tema de Cracking o Ingenieria Inversa lo encuentro super interesante pero aún no se programar y eso es clave. . . si, por mientras observare de lejos (pero sin perder distancia) ya que el tema me queda grande.

Saludos !!

ERROR no requieres tener conocimientos de programación para iniciarte con Ingeniería inversa, pásate por el F.A.Q que te esperaremos, inmediatamente comienza con introducción al cracking desde cero, esperamos verte seguido, Saludos

Solicitudes de crack, keygen, serial solo a través de mensajes privados (PM)

Shamaroot

CitarERROR no requieres tener conocimientos de programación para iniciarte con Ingeniería inversa, pásate por el F.A.Q que te esperaremos, inmediatamente comienza con introducción al cracking desde cero, esperamos verte seguido, Saludos

Ehh mas bien, no quiero ir saltando etapas de momento primero me gustaria aprender a programar. . .
Pero este tema lo tendre entre ceja y ceja :P (me pasare por lo me mencionas, gracias)

Saludos !!
El conocimiento es libre.

Иōҳ

No te estás saltando nada, la ing. inversa es muy independiente a que sepas programar o no....

Salu2
Eres adicto a la Ing. Inversa? -> www.noxsoft.net

.:UND3R:.

Cita de: Shama|TwoH en 27 Noviembre 2011, 05:45 AM
Ehh mas bien, no quiero ir saltando etapas de momento primero me gustaria aprender a programar. . .
Pero este tema lo tendre entre ceja y ceja :P (me pasare por lo me mencionas, gracias)

Saludos !!

Tal como comenta NOX. necesitamos gente y el requisito para empezar es leerse una introducción al cracking desde cero

Saludos y cuentas con todo el subforo

Solicitudes de crack, keygen, serial solo a través de mensajes privados (PM)