ESTUDIO COLECTIVO DE DESPROTECCIONES
Última Actualizacion: 25/10/2001

Programa Flash 32 v1.27 W95 / W98 / NT
Descripción Este programa sirve para capturar pantallas o secuencias de estas, acepta multitud de formatos incluso AVI y FLI y tambien puede capturar pantallas de programas en MS-DOS.
Tipo Trial de 30 días + special banner
Tipo de Tutorial [X]Original, []Adaptación, []Aplicación, []Traducción
Url http://perso.infonie.fr/chass/indexe.htm
Protección Nag Screen + Trial 30 días + banner
Dificultad 1) Principiante, 2) Amateur, 3) Aficionado, 4) Profesional, 5) Especialista
Herramientas SoftIce v4, W32dasm , UltraEdit
Objetivo Eliminar el banner y el límite de tiempo mediante parcheado del código.
Cracker Black Fenix
Grupo http://kickme.to/wkt
Fecha Mayo del 2000

INTRODUCCION

Bueno nuestro quinto tutorial sobre cracking, en esta entraga vamos a variar un poco dejando los keygenerators de lado y vamos a examinar un programa llamado Flash 32 v 1.27.

El programa es de evaluación y expira a los treinta dias , ademas en todas las pantallas que capturemos aparecerá el texto 'Flash - Evaluation' tapando con ello parte de la imagen. Nuestro proposito es eliminar el limite de tiempo (30 dias) el texto que imprime al salvar las capturas y el NAG que muestra al salir del programa. Como puedes ver este crack promete ser divertido y variado :)

El programa no permite introducir ningún numero de registro por lo que en este caso nuestra busqueda empezará de otra
manera y tendremos que modificar directamente el ejecutable.

AL ATAQUE

Instalar el programa, ejecutarlo y este funcionará normalmente, ahora salimos del programa (este queda instalado en la barra de tareas por lo que haremos click sobre su icono con el botón izquierdo y seleccionaremos 'Close Flash'. Nos aparecera una pantalla en la que se nos invita a registrarnos (aunque pulsemos register lo unico que saldrá es una ventana con un fichero de texto donde deberemos rellenar unos datos y enviarlos al autor para que nos envie la versión registrada) pulsaremos Ok y saldremos del programa.

- Ahora cambiamos la fecha del sistema y la avanzamos en más de treinta dias de la actual. Ejecutamos de nuevo el programa y nos aparece una ventana que dice: 'The evaluation period is finished bla bla bla...' bien, recordarla, Ahora hacemos una copia del ejecutable y lo renombramos a Flash32.exx abrimos el W32Dasm y desensamblamos dicha copia para no trabajar con el original.

- Una vez desensamblado, pulsamos sobre el icono 'Strn Ref' y buscamos la cadena 'The evaluation bla bla ...' una vez encontrada hacemos doble click sobre esta y el W32Dasm nos llevará a la unica parte del programa donde se hace referencia a esta cadena, veras algo así:

* Possible StringData Ref from Data Obj //"The evaluation period is finished."
:00407774 6858CF4300 push 0043CF58 // ESTA ES LA REFERENCIA A LA CADENA
* Possible StringData Ref from Data Obj //"%s"
:00407779 68A4C84300 push 0043C8A4
:0040777E 68409C4500 push 00459C40
* Reference To: USER32.wsprintfA, Ord:02ACh
:00407783 FF156C554300 Call dword ptr [0043556C]
:00407789 83C40C add esp, 0000000C
:0040778C 6A10 push 00000010
* Possible StringData Ref from Data Obj //"Flash"
:0040778E 68F4CE4300 push 0043CEF4 // Titulo de la ventana
:00407793 68409C4500 push 00459C40
:00407798 6A00 push 00000000
* Reference To: USER32.MessageBoxA, Ord:01BEh
:0040779A FF15E8544300 Call dword ptr [004354E8] // Muestra el cuadro de dialogo
:004077A0 5E pop esi
:004077A1 33C0 xor eax, eax
:004077A3 5B pop ebx
:004077A4 C21000 ret 0010

Como puedes comprobar este código prepara el cuadro de dialogo y lo muestra con MessageBox, esto quiere decir
que alguien tuvo que enviarnos aquí de alguna manera por lo que mirando los posibles saltos vemos que el primero
viene de 40775Ah

* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0040775A(C) * Possible StringData Ref from Data Obj //"The evaluation period is finished."
:00407774 6858CF4300 push 0043CF58 // ESTA ES LA REFERENCIA A LA CADENA

Esta dirección está justo por encima, si miramos el código superior encontraremos un salto en la dirección 407755A.

:00407732 C7053098450000010000 mov dword ptr [00459830], 00000100
:0040773C 8915A4954500 mov dword ptr [004595A4], edx
:00407742 A32C984500 mov dword ptr [0045982C], eax
:00407747 8915A4984500 mov dword ptr [004598A4], edx
:0040774D E81EC70100 call 00423E70
:00407752 83C430 add esp, 00000030
:00407755 48 dec eax
:00407756 5F pop edi
:00407757 744E je 004077A7
:00407759 48 dec eax
:0040775A 7418 je 00407774 // ESTE ES EL SALTO QUE NOS ENVIA AL CUADRO DE DIALOGO
:0040775C 6A00 push 00000000
:0040775E 6820614000 push 00406120
:00407763 6A00 push 00000000
* Possible Reference to Dialog: DialogID_009C
:00407765 689C000000 push 0000009C
:0040776A 56 push esi
:0040776B FFD3 call ebx
:0040776D 5E pop esi
:0040776E 33C0 xor eax, eax
:00407770 5B pop ebx
:00407771 C21000 ret 0010

Examinando este código podriamos suponer que EAX contiene algun tipo de flag que nos indica si el programa está o no registrado ya que si seguimos el flujo normal del programa vemos que este no llamaria a ningún cuadro de dialogo y volveria al proceso que lo llamo con un ret. Si suponemos lo anteriormente dicho, estamos en lo cierto (no es que sea adivino si no que lo he comprobado) ya que la función que es llamada en 4077D4 se encarga de leer la fecha de instalación del programa desde
el registro de windows y comprobar la diferencia de tiempo con la función GetSystemTimeAsFileTime, puedes comprobarlo tu mismo si miras el codigo a partir de la dirección 423E70 (No lo he incluido por ser muy extenso).

- Bueno pues ya sabemos que si cambiamos el salto por un par de NOPs (código 90h cada NOP) probablemente el programa funcionará aunque pasemos el límite de tiempo de 30 días. Para realizar esta modificación nos colocamos sobre la linea :0040775A asegurandomos que la linea azul del W32Dasm este sobre esta y ahora apuntamos el offset que nos marca en la barra de estado (este offset es la posición física del primer byte de la instrucción dentro del ejecutable) este valor debe ser 775Ah. Ahora nos vamos a nuestro editor hexadecimal favorito y abrimos el ejecutable original (Flash32.exe) nos vamos al offset 775Ah con las bunciones de busqueda de este (debe tenerlas) y cambiamos los bytes 74 18 por 90 90 salvamos los cambios y ejecutamos el programa. Sorpresa, funciona y han transcurrido más de 30 días
desde la fecha de instalación.

- Ahora vamos a capturar una porción del escritorio, click con el botón izquierdo sobre el icono de la barra de tareas Captures/Region, pulsamos OK y designamos un area rectangular de la pantalla con el mouse. El programa cogerá dicha porción y nos la presentará junto con una serie de menus. Vamos al menu Capture/Save as, le damos un nombre, seleccionamos los bpp de la imagen y la guardamos donde queramos, mientras se salva vemos que aparece la cadena 'Flash - Evaluation' sobreimpresa en la imagen y luego desaparece. si miramos la imagen que acabamos de salvar veremos que esta cadena a aparecido en ella, tapando con ello parte de nuestra captura, y esto no nos interesa.

Bien sabemos que mensaje muestra por lo que podriamos intentar el mismo metodo que usamos con la cadena anterior, pero no sirve ya que la cadena 'Flash - Evaluation' no aparece en la lista de cadenas del W32Dasm, por lo que debemos pensar en otra solución. Pensemos, el programa imprime una cadena, por lo tanto necesitará llamar a alguna función del GDI de windows para imprimirla en pantalla. ¿ Que funciones de dibujo de texto nos proporciona el GDI de windows ? Unas cuantas pero las siguientes son las más usadas.

TextOut,TextOutA
DrawText,DrawTextA
DrawTextEx,DrawTextExA

Nota: La A final indica que es de 32bits.

De estas tres funciones la más simple es la primera TextOut, podriamos suponer que el programador que hizo el Flash no quiso complicarse la vida y usó esta función para imprimir el texto. Recuerda, prueba primero lo más sencillo, suele funcionar el 90% de los casos. Pongamos el SoftIce en marcha.

Probemos, vayamos hasta el cuadro de dialogo que nos permite introducir el nombre, pongamos uno y activemos el SoftIce (Ctrl+D) ahora ponemos un bpx textouta y un bpx textout (el programa es de 32 bits) y pulsamos g para continuar con la ejecución normal. Pulsamos el boton de OK para salvar y Ops!! estamos de nuevo en SoftIce. La función TextOut tiene un inconveniente, y es que es muy usada por el propio windows para escribir los nombres de los botones y de los menus, por lo que ahora deberemos ir pulsando g unas cuantas veces hasta que desaparezca por completo el cuadro de dialogo, cuando este desaparezca, continuaremos pulsando g y veremos que los nombres de los menus se van escribiendo, cuando se escriba el último 'Help' pulsamos g de nuevo y la proxima vez que entremos en SoftIce será para imprimir la cadena 'Flash - Evaluation' ahora ulsamos F12 hasta que llegemos al codigo fuente de FLASH32.EXE veremos algo así:

 

* Reference To: GDI32.TextOutA, Ord:0205h
:0041626E FF1540524300 Call dword ptr [00435240] // Llama a TextOutA
:00416274 8B1518884500 mov edx, dword ptr [00458818] // Estamos aquí
:0041627A 8B442418 mov eax, dword ptr [esp+18]
:0041627E 8B4C2414 mov ecx, dword ptr [esp+14]
:00416282 50 push eax
:00416283 51 push ecx
:00416284 52 push edx
:00416285 56 push esi

Aquí está la llamada que imprime la cadena 'Flash - Evaluation', podriamos simplemente eliminarla con NOPs, pero esto no
funcionaria y recibiriamos un (Protection Fault ya que habria que nopear los pushes previos a la llamada) despues de
salvar la imagen (lo he comprobado).
Cual es la manera más sencilla de hacer que no se imprima la cadena ? Antes de nada miremos el funcionamiento de la función TextOut segun el API de Windows.

BOOL TextOut(
    HDC hdc, // handle del dispositivo de contexto
    int nXStart, // coordenada X del texto
    int nYStart, // coordenada Y del texto
    LPCTSTR lpString, // puntero a la cadena a imprimir
    int cbString // numero de caracteres a imprimir
);

Pues hay varias:

Una opción seria modificar las coordenadas del texto para que estuvieran fuera de la imagen, pero esto implica bastantes modificaciones en el código.

La siguiente más sencilla y rápida de ejecución es cambiar el numero de caracteres a imprimir y decirle que imprima 0 caracteres o sea ninguno, esta es la solución.

- Habiendo optado por la segunda opción debemos localizar donde se pasa (empuja) la longitud de la cadena como parametro para la función TextOut, como es una pila LIFO (último en entrar primo en salir) el numero de caracteres debera ser el primer PUSH de todos los que hay por encima de la función TextOut.
Ahora apuntamos a dirección 0041626E que es donde se llama a TextOut y salimos del SoftIce. Nos vamos al W32Dasm y desensamblamos la copia del archivo original (es el Flash32.exx) , vamos al menu Goto/Code Location e introducimos el offset que nos apuntamos anteriormente (41626E) pulsamos OK y veremos algo asi:.

:0041623C 8B442418 mov eax, dword ptr [esp+18]
:00416240 6A12 push 00000012 // Empuja longitud de la cadena para TextOut
:00416242 99 cdq
:00416243 2BC2 sub eax, edx
:00416245 8B1518884500 mov edx, dword ptr [00458818]
:0041624B D1F8 sar eax, 1
:0041624D 3BC2 cmp eax, edx
:0041624F 7D0B jge 0041625C
:00416251 8D8424B0010000 lea eax, dword ptr [esp+000001B0] // copia en eax puntero a 'Flash - Evaluation'
:00416258 50 push eax // empuja puntero a la cadena
:00416259 52 push edx // empuja coordenada X
:0041625A EB09 jmp 00416265
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0041624F(C)
:0041625C 8D9424B0010000 lea edx, dword ptr [esp+000001B0] // copia en eax puntero a 'Flash - Evaluation'
:00416263 52 push edx // empuja puntero a la cadena
:00416264 50 push eax // empuja coordenada X
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |:0041625A(U)
:00416265 51 push ecx // empuja coordenada Y
:00416266 56 push esi // este es para la función GetDC
* Reference To: USER32.GetDC, Ord:00FDh
:00416267 FF159C544300 Call dword ptr [0043549C]
:0041626D 50 push eax // Pasa el handle
:0041626E FF1540524300 Call dword ptr [00435240] // ESTAMOS AQUI !!!!! llama a TextOut
:00416274 8B1518884500 mov edx, dword ptr [00458818]
:0041627A 8B442418 mov eax, dword ptr [esp+18]
:0041627E 8B4C2414 mov ecx, dword ptr [esp+14]

Ahora buscaremos todos los los push que hay antes de la llamada al TextOut, sabemos que deben ser un máximo de cinco. En 41626E encontramos el primero.

   :0041626D 50 push eax -> Pasa el handle

el segundo en :


  :00416265 51 push ecx -> coordenada X

el tercero y el cuarto en:


    :00416258 50 push eax -> Puntero a 'Flash - Evaluation'
    :00416259 52 push edx -> coordenada Y

y el quinto que es el nuestro en:

   :00416240 6A12 push 00000012 -> 12h = 18 -> longitud de 'Flash - Evaluation'

Si no te aclaras examina de nuevo el código detalladamente y comprenderas su funcionamiento.

- Bueno ya esta claro lo que hay que hacer o no ? . Claro, reemplazar el push 12 por un push 0. Actuaremos igual que hicimos para modificar el salto anterior, apuntar el offset y sustituir el 6A12 por un 6A0 dentro del ejecutable.Vamos intentalo sólo, es fácil. Una vez hechas las modificaciones, no volveras a ver ningun texto sobre tus capturas.

- Como tarea adicional podriamos eliminar el cuadro de dialogo que aparece al salir del programa ya que es molesto y no sirve para nada. Para ello podriamos utilizar la técnica de buscar una referencia a las cadenas que este cuadro muestra, pero no encontrariamos ninguna. Bueno no te preocupes lo intentaremos de otro manera. Examina el cuadro de dialogo por un momento; no es un MessageBox convencional, por lo tanto debe ser un DialogBox, ademas este dialog box no retorna el control a la aplicación hasta que se sale de este. Piensa. Las funciones para la creación de cuadros de dialogos son las siguientes:

CreateDialog
CreateDialogIndirect
CreateDialogIndirectParam
CreateDialogParam
DialogBox
DialogBoxIndirect
DialogBoxIndirectParam
DialogBoxParam

Pero como hemos dicho que el cuadro de dialogo no pasa el control a la aplicación hasta su finalización por parte del usuario, las 4 primeras quedan anuladas. Sólo nos quedan las siguientes.

DialogBox
DialogBoxIndirect
DialogBoxIndirectParam
DialogBoxParam

Pues a que esperas, ejecuta el programa, activa el SoftIce y pon un bpx DialogBox, bpx DialogBoxIndirect, bpx GialogBoxIndirectParam, bpx DialogBoxParam, pulsa g y ahora sal del Flash32. Boom! el bpx DialogBoxIndirectParam ha surtido efecto, pulsamos F12 una vez y estaremos justo debajo de la llamada a este, veras algo así en el SoftIce:

:00406A3F A124A24500 mov eax, dword ptr [0045A224]
:00406A44 6A00 push 00000000
:00406A46 6830214200 push 00422130
:00406A4B 56 push esi
:00406A4C 6805010000 push 00000105
:00406A51 50 push eax
* Reference To: USER32.DialogBoxParamA, Ord:0093h
:00406A52 FF15A8544300 Call dword ptr [004354A8] // Muestra el cuadro de dialogo
:00406A58 85C0 test eax, eax // ESTAMOS AQUÍ
:00406A5A 0F8498080000 je 004072F8 // Si no se pulso OK (EAX=0) no saldrá del
:00406A60 56 push esi // programa
:00406A61 E88A360200 call 0042A0F0
:00406A66 A1FC904500 mov eax, dword ptr [004590FC]
:00406A6B 83C404 add esp, 00000004
:00406A6E 85C0 test eax, eax
:00406A70 7413 je 00406A85
:00406A72 56 push esi

Examina el código y veras que este es nuestro hombre, se empujan cinco argumentos a la pila se llama a la funcion que muestra el cuadro de dialogo y se comprueba el valor de EAX, si EAX=1 se pulsó el botón OK y se sale de la aplicación, si se pulsa el botón cancelar, EAX=0 y no se saldrá de la aplicación. Los cinco argumentos que se empujan a la pila son para la función DialogBoxParamA ,fijate que esta función usa la función DialogBoxIndirectParam para crear dicho cuadro. Aquí tienes una descripción del funcionamiento de la función DialogBoxParamA

int DialogBoxParam(
    HINSTANCE hInstance, // handle a la instancia de la aplicación
    LPCTSTR lpTemplateName, // identifica el cuadro de dialogo
    HWND hWndParent, // handle a la ventana propietaria
    DLGPROC lpDialogFunc, // puntero a una función que controla el cuadro de dialogo
    LPARAM dwInitParam // valor de inicialización
);

- Pues ahora se trata de eliminar el cuadro de dialogo pero, ¿ como ?, fácil primero hay que eliminar los 5 push previos ha la llamada a DialogBoxParamA , luego eliminar la llamada y hacer que EAX siempre valga 1. Aquí puedes ver el código modificado.

 

:00406A3F A124A24500 mov eax, dword ptr [0045A224]
:00406A44 90 nop
:00406A45 90 nop
:00406A46 90 nop
:00406A47 90 nop
:00406A48 90 nop
:00406A49 90 nop
:00406A4A 90 nop
:00406A4B 90 nop
:00406A4C 90 nop
:00406A4D 90 nop
:00406A4E 90 nop
:00406A4F 90 nop
:00406A50 90 nop
:00406A51 90 nop
:00406A52 B801000000 mov eax, 00000001 // Aquí estaba el Call
:00406A57 90 nop
:00406A58 85C0 test eax, eax // Fin de las modificaciones
:00406A5A 0F8498080000 je 004072F8
:00406A60 56 push esi
:00406A61 E88A360200 call 0042A0F0
:00406A66 A1FC904500 mov eax, dword ptr [004590FC]
:00406A6B 83C404 add esp, 00000004
:00406A6E 85C0 test eax, eax
:00406A70 7413 je 00406A85
:00406A72 56 push esi

- Bueno esto es todo, las modificaciones las dejo a tu cargo para que practiques, recuerda, buscar el offset del primer byte de la instrucción, apuntar las modificaciones desde esta posición y con el editor hexadecimal que prefieras realizar las modificaciones.

Que te ha parecido el tutorial ? Es cierto que podriamos haber atacado por otros puntos pero yo le he hecho de la manera que me ha sido más facil. Recuerda un programa puede hacerse de varias maneras, un crack tambien pero siempre es mejor usar la manera más corta y la que implique menos modificaciones.

[ Entrada | Documentos Genéricos | WkT! Web Site ]
[ Todo el ECD | x Tipo de Protección | x Fecha de Publicación | x Orden Alfabético ]
(c) Whiskey Kon Tekila [WkT!] - The Original Spanish Reversers.
Si necesitas contactar con
nosotros , lee esto antes e infórmate de cómo puedes ayudarnos