La desprotección de este programa la voy
a ir realizando por fases, que no van a seguir el orden
de aparición en escena. PERIODO DE EVALUACIÓN
Evitar que el programa caduque
se puede conseguir al menos por dos procedimientos.
Primer método
Como casi siempre en estos casos
lo primero que queremos encontrar son los avisos que los
programas envían cuando no se dan las condiciones de
evaluación. Adelentamos el reloj del sistema e
inmediatamente después de la 'nag' inicial aparece el
siguiente mensaje:

Lo siguiente es desensamblar el
programa y buscar la cadena de caracteres de la ventana:

La línea 42D397 je 42D3C3 es un
salto condicional justo antes de la presentación del
mensaje. Anotamos el offset de esta instrucción, hacemos
una copia del original y mediante un editor hexadecimal
cambiamos el valor 74 por un 75. Guardamos, probamos y....
funciona nuevamente.
Ya se puede disfrutar de los días
de evaluación que deeeemos.
Segundo método
Aunque realmente por el
procedimiento anterior hayamos conseguido el objetivo, no
debemos desechar la posibilidad de intentar cosas nuevas
que en su día nos puedan resultar útiles.
El hecho de que una vez caducado
el programa no deje volver a emplearlo aún retrasando la
fecha, puede estar relacionado con la lectura o escritura
de datos en el registro de Windows.
Empezamos buscando en el
registro por si hay alguna clave que busque nuestro
programa. Abrimos Regmon y filtramos las salidas de sr32.exe
(en NT conviene emplear sr32*).
Observamos que una vez que sale
la 'nag' inicial el programa arranca y obtiene una clave
llamada 'Num Chars'situada en la rama "Current User":

Si antes de efectuar ningún adelanto al reloj del
sistema copiamos el valor de 'Num Chars', podemos
variarlo manualmente, o borrarlo, y luego restaurar también
manualmente el valor.
Si hacemos esto veremos que el programa nos vuelve a
mostrar la pantalla de final de evaluación. Por simple lógica
este elemento de valor debe controlar la fecha codificada
de instalación del programa. Si restauramos el valor que
copiamos, el programa funciona normalmente.
Al cerrarlo, nuevamente accede al registro y escribe
la misma clave codificada actualizada a la fecha del día.
Esto nos abre la posibilidad de entrar en el programa
a través de las funciones de la API:
RegQueryValueExa:
obtención de datos del registro.
GetSystemTime:
obtención de la fecha del sistema.
Abrimos SoftIce con el "simbol loader" y
colocamos las siguientes breakpoints:
Bpx GetSystemTime
Bpx RegQueryValueExa if *(esp->8)=='Num ' do "d
*(esp+14)"
Ahora explicaré esta última línea.
La función RegQueryValue tiene la siguiente
estructura:
RegQueryValueEx(
HKEY hKey, // handle del
elemento de valor que se busca
LPTSTR lpValueName, // dirección
del elemento de valor que se busca
LPDWORD lpReserved, // reservada
LPDWORD lpType, //dirección del
buffer del elemento de valor buscado
LPBYTE lpData, //dirección de
retorno del elemento de valor buscado
LPDWORD lpcbData //dirección
del tamaño del buffer de datos
);
Es decir, teniendo en cuenta que los
parámetros se pasan a las funciones a través de la pila
y en orden inverso:
En [ESP+00] estará la dirección de
retorno
En [ESP+08] se pasará el nombre del elemento de valor a
buscar, en nuestro caso 'Num '
En [ESP+14] se pasará la dirección de retorno en la que
se colocará el valor buscado.
El hecho de colocar solo los cuatro
primeros caracteres de 'Num Chars' se debe a que el
comando de SoftIce *, nos devuelve valores del tipo DWORD
o doble palabra (32 bits) que es equivalente a 4 octetos.
Un octeto se representa en Hexadecimal
por ejemplo de la forma FF (la primera F es 15d o 1111b)
por tanto FF sería en binario 1111 1111.
Los cuatro octetos de 'Num 'tendrán
por tanto la forma:
4E 75 6D 20.
Hecho este inciso y con las breakpoints
establecidas, pulsamos F5 aparecerá la 'nag'
inicial. Aceptamos y nuevamente entramos en SICE. Si nos
hemos fijado en el listado completo que nos proporcionó
Regmon veremos que SR32.exe realiza varias solicitudes de
datos al registro con el valor 'Num Chars', pero nosotros
las saltaremos con F5 hasta que en nuestra ventana de
datos aparezca el valor 'Num Chars' que ya conocemos.

En la línea 46EC5B almacena en ECX el elemento de
valor de 'Num Chars'
Una vez que el programa lo recoge es claro que debe
obtener la fecha de sistema, con lo que al siguiente F5
nos aparecerá la funcion GetSystemTime. Pulsamos F12 y
volvemos al programa. Mediante F10 podemos trazar
instrucciones y veremos como va colocando en los
registros los valores de día, mes y año actuales (el
resto no nos interesan). Como guía para los pocos
iniciados 2000 en hexa es 7D0.
Cuando llegamos a la instrucción 4483A0 el programa
ha guardado el día en EDX, el mes en EAX y el año en
ECX-
A partir de aquí vienen una serie de instrucciones
que codifican la fecha actual para pasarla a formato de
'Num Chars' y enseguida se llega a esta zona de código:

Si trabajamos con el programa original y no hemos
sobrepasado el periodo de evaluación, veremos que los
saltos en 42FCCB, 42FCE7 y 42FCEB (todos a la dirección
42FCF6) no se realizan, pero si realizamos lo mismo con
la fecha excediendo los días de evaluación o
modificando manualmente el valor de 'Num Chars' veremos
que se realiza alguno de los saltos a 42FCF6 e
inmediatamente nos aparece la ventana de fin de evaluación.
Una de las posibles maneras para siempre evitar que se
produzca el salto es hacer un JMP a la siguiente
instrucción. Como todos los saltos mencionados son
cortos debemos emplear la expresión "corta"
para JMP que es EB.
Nos quedarían 7C29, 7F0D y 7C09 como EB00
Y nuevamente queda desprotegido el programa del final
de evaluación.
'NAG'
RECORDATORIA DEL NÚMERO DE CAMBIOS POR SESIÓN
Cuando se inicia el programa y se seleccionan ficheros
en los que realizar cambios, una vez efectuados dichos
cambios aparece una ventana que nos recuerda las
limitaciones de uso del programa:

Mediante Wdasm se busca la cadena de caracteres
anterior apareciendo en:

Vemos que hay dos saltos condicionales por encima del
mensaje. Comprobamos con SICE cual de los dos hay que
invertir.
Nos fijamos en los contenidos de [EBP+08] y [EBP-64],
en ambos casos es 1; y EBX es 0, ninguno de los dos
saltos se producirá y siempre no aparecerá la 'nag'.
Modificando cualquiera de ellos se evitará.
Cambiamos JZ 43C570 por JMP 43C570 (EB 26) y queda
solucionado.
LIMITACIÓN
DEL NÚMERO DE CAMBIOS POR SESIÓN
Como señalé al principio, una de las molestias de
este programa es la imposibilidad de efectuar más de un
cambio a más de cinco ficheros simultaneamente, por lo
que hay que cerrar y abrir nuevamente el programa para
conseguir poco a poco realizar las modificaciones (¡¡vaya
sistema de evaluación!!).
Cuando se intenta realizar una modificación por
segunda vez salta la siguiente ventana:

Mediante Wdasm buscamos la cadena de texto de arriba:

Vemos que a ella se puede acceder desde 5 saltos, si
ponemos breakpoints con SoftIce veremos que el código
llega desde 439DB6.
A primera vista parece el asunto de siempre, una
inversión de los saltos y solucionado... pero no.
Podemos hacer la prueba y siempre nos aparecerá la
fastidiosa ventana.
No nos queda más remedio que emplear nuestro
depurador SoftIce y pararnos en las cercanías del salto.
Bpx 439E36
Entramos en el programa utilizamos 7 u 8 ficheros de
prueba y empezamos a realizar cambios, rápidamente
aparece nuestro amigo SICE.
en 439E36 compara [EBP+08] con EBX. En EBP+8 siempre
hay el valor 1 y en EBX siempre llegamos con el valor 0.
Luego el salto en 439E39 siempre se producirá.
En 439E3F compara el contenido de la variable global 4B357C
con BX. En esta primera vez 4B357C contiene el valor 0.
Luego el salto en 439E46 se efectua esta vez ya que
EBX es 0.
Pulsamos F5 y salimos nuevamente al programa, en la
ventana confirmar remplazo. Si pulsamos en 'Replace this'
vemos que SoftIce no salta y nos permite efectuar el
segundo y sucesivos cambios, justo hasta que se ha
realizado el quinto y nos aparece nuevamente la 'nag'
recordatoria.
En este momento si volvemos a intentar efectuar alguna
sustitución nuevamente entramos en el código de SoftIce.
[EBP+08] sigue siendo 1 y EBX continua con el valor 0,
pero la variable global 4B357C contiene ahora el valor 5,
los cinco cambios como máximo permitidos, por lo que el
salto en 439E46 no se efectuará y ahora directamente nos
aparece la pesadita 'nag' sin haber realizado ni un solo
cambio.
No quedaría más remedio que cerrar el programa y
volverlo a abrir para poder seguir evaluándolo, de esta
manera se inicializará la variable 4B357C a 0 y nos
permitirá nuevamente un solo cambio en un máximo de 5
ficheros.
El camino a seguir parece claro, localizar el punto en
el que se va incrementando la variable global y anularlo.
Esto se puede conseguir en SICE mediante una interrrupción
en la ejecución del programa en el momento en que éste
acceda a la mencionada dirección de memoria para leerla
o escribirla:
Bpm 4B357C RW
o también mediante Bpr
4B357C 4B357F
Cargamos nuevamente el programa en el "simbol
loader" de Softice y establecemos una de las dos
interrupciones de arriba.
Pulsamos F5, obtenemos la 'nag' inicial y nos
disponemos a efectuar cambios en los ficheros de prueba,
en cuanto aceptemos realizar el primer cambio saltará
SICE en 439E46, esto ya lo habíamos visto, es la primera
comparación de la variable global inicializada a 0.
Pulsamos F5 otra vez y aparecemos en:

Comparación de nuestra variable con 6. Seguimos, F5 y:

Aquí hay algo interesante, se mueve el contenido de
la variable global a la parte inferior del registro EAX,
se incrementa, se comprueba el nuevo valor con otra
variable global 491E18, cuyo valor es 5, y finalmente
coloca el valor incrementado de nuevo en 4B357C.
No hay que ser un genio para deducir que aquí es
donde se "cocina" el número máximo de
ficheros en los que se puede realizar cambios y por añadidura
el límite de una única sustitución.
Si anulamos con NOP's la instrucción 43BFC0 inc EAX,
cuando el programa alcance la instrucción 439E46

el salto siempre se realizará ya que la variable
global siempre estará a 0. Habremos eliminado las
limitaciones de funcionalidad y la molesta 'nag'.
'NAG'
INICIAL
He dejado para el final lo que en realidad aparece al
principio, debe ser por que fué lo que más me costó, o
donde menos espabilado estuve, que todo es posible.
Como casi siempre que aparece una 'nag' de este tipo
solemos pensar en la función del API DialogParamA y
poner, mediante SoftIce, una interrupción en ella. Eso
mismo hice yo sin lograr nada.
Probé también la función ShowWindow y mediante ella
si que lograba la "aparición" de SoftIce, pero
comprobando con Wdasm desde dónde se llamaba aprecié,
con horror, que esta función se invocaba desde 15 puntos.
Intentar seguir este camino es imposible, entre otras
cosas porque la función ShowWindow se emplea también
para mostrar la pantalla principal del programa.
Desesperanzado abandoné y decidir utilizar el
programa quitanag que, por otra parte, realizaba su
trabajo con total diligencia.
Pero no sé qué tiene esto que como lo pruebes te
engancha. Una buena actitud en estos casos es descansar y
dedicarse a otra cosa. Así se fijan ideas y se suele
acometer con mayor prestancia el trabajo.
Cuando uno se cree meter en un callejón sin salida
merece la pena pararse a pensar, solo a pensar. Tanto ir
y venir por el código del programa solo nos hace ver números
y de vez en cuando conviene recapacitar:
Cuando adelantábamos el reloj del sistema, al
principio de todo, antes de aparecer la ventana que nos
indicaba el final del periodo de evaluación se dejaba
ver la 'nag' inicial. Volvamos pues al código del final
de evaluación:

¿Podrá ser que alguna de las 2 Call por encima del
mensaje genere la 'nag' inicial?
Probemos con SoftIce
Bpx 42D37F y a continuación r eip=42D384 para saltarnos esa Call,
pulsamos F5 y ¿¡Bingo!? LA 'NAG' NO APARECE, todo listo.
Muchas veces un
programa se deja de examinar cuando uno cree haber
conseguido algo, lo he visto en varios tutoriales.
La paciencia es una
buena virtud. Probemos a seguir con el programa,
intentemos realizar cambios. No funciona correctamente...
aparecen unos mensajes de error entre los tamaños del
fichero a remplazar.
¿Estamos donde estábamos?,
no, algo hemos conseguido y algo sabemos con rotundidad:
NO HEMOS TERMINADO.
Habrá que examinar la
Call 45E448.
Esta rutina discurre
entre las instrucciones 45E448 y 45E55C, habrá que estar
al tanto y probar con F4 donde estamos.
Voy trazando con F10 y
antes de cada Call compruebo los argumentos que se envían
a ella por si pudiera obtener una pista.
En la línea
45E4FE PUSH DWORD PTR [EBP-14]
se envía una dirección a la pila y muy cerquita se ve
el texto del encabezado de la 'nag' "About Search...."
Seguimos con F10 y en
45E529 Call 45DBB7 aparece la 'nag'. Si "nopeamos"
esta Call el programa produce un error. Ahora podemos o
bien entrar dentro de esta Call o bien evitar llegar a
ella.

Encima de nuestra Call
hay 3 saltos: en 45E50C, 45E512 y 45E521, los dos
primeros evitan la Call, el tercero no, luego en
principio este lo desechamos.
Si seguimos el salto
hasta 45E530 llegamos a una instrucción 45E546 JMP 45E565
(fuera de la imagen); el mismo destino que el salto en 45E50C.
Obligamos por tanto el
salto en 45E512, saltamos a 45E530, pulsamos F5 y
FUNCIONA.
Como la variación la
hicimos con el SoftIce debemos fijarla con el editor
hexadecimal, anotamos el offset, invertimos el salto y
nuevo ERROR. AAAAAAARRRRGGGGGGG!!!!!.
Si ponemos un
breakpoint en 45E512 vemos que antes de salir la 'nag' el
programa pasa dos veces por aquí, la primera vez debe
saltar para no presentar la 'nag' pero la segunda vez no
debe saltarse para presentar la pantalla principal del
programa.
Si intentamos invertir
en 45E50C el problema es el mismo, la primera vez debe
saltar pero la segunda vez no.
Se pueden comprobar los
registros en la primera y segunda pasada y se ven que
difieren, pero no he sido capaz de conseguir que se
igualen en ambas.
Solo me quedaba la
posibilidad de modificar el código. Esto me costó.
Primero tenía que buscar allí mismo el sitio en el que
eliminar instrucciones e introducir en ese mismo espacio
el nuevo código, sin pasarme un byte.
Desde la instrucción
45E50A a la 45E512, ambas inclusives, solo hay
comparaciones y saltos, sería un buen lugar y dispongo
de espacio para 10 bytes.
El sistema será:
1º elegir una variable
que se encuentre a 0
2º saltar la primera vez
3º incrementar esta variable de manera que no se salten
las sucesivas.
Pongo una interrupción
en SoftIce en 45E50A y miro el valor de los registros en
las dos pasadas, todos varían a excepción de EDX.
Realizo d EDX y miro a ver si en sus
alrededores hay un espacio de 4 bytes que estén a 00 00
00 00 para utilizarlo de variable a incrementar.
Parece que hay varios
lugares y elijo EDX+10 ya que la trascripción a código
máquina ocupa menos bytes que por ejemplo EDX+90; y aquí
andamos justos de espacio.
Salgo de SoftIce y
vuelvo a entrar con la misma interrupción. Antes de la
primera pasada EDX+10 esta a cero y antes de la segunda
¡también! ¡¡QUE SUERTE!!
El código que
introduzco es el siguiente:
45E508 |
33DB |
XOR EBX,EBX |
|
45E508 |
33DB |
XOR EBX,EBX |
45E50A |
3BC3 |
CMP
EAX,EBX |
|
45E50A |
3B5A10 |
CMP
EBX,[EDX+10] |
45E50C |
7457 |
JZ
45E565 |
|
45E50D |
FE4210 |
INC
BYTE PTR[EDX+10] |
45E50E |
F6462410 |
TEST
BYTE PTR[ESI+24],10 |
|
45E510 |
7353 |
JAE
45E565 |
45E512 |
741C |
JZ
45E530 |
|
45E512 |
90 |
NOP |
45E514 |
6A04 |
PUSH
04 |
|
45E513 |
90 |
NOP |
|
|
|
|
45E514 |
6A04 |
PUSH
04 |
He resaltado en azul la parte que
modifico, a la izquierda el código del programa y a la
derecha la modificación introducida.
De lo que se trata fundamentalmente es de ocupar el
mismo "espacio" empleando la instrucción NOP
las veces que resulte necesario.
En la instrucción nueva 45E50A efectuamos la
comparación de EBX con [EDX+10] como ambos son cero el
salto en 45E510 se producirá, antes habremos
incrementado el valor contenido en [EDX+10] a 1 por lo
que en la siguiente pasada EBX no será mayor o igual que
[EDX+10] y el salto no se producirá; habiendo logrado
saltar en la primera pasada y no en las sucesivas.
Probamos y ahora si F U N C I O N A.
Todas las protecciones y limitaciones del programa se
han superado.... con paciencia.
Ahora, como no somos unos mangutas, borramos nuestro
fichero modificado y si nos interesa el programa lo
compramos.
|