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