| ESTUDIO COLECTIVO DE DESPROTECCIONES Última Actualizacion: 25/10/2001 |
Programa | FrontPage 2000 & PhotoDraw 2000 (II) | W95 / W98 / NT
Descripción | Aplicaciones de la familia Office 2000.
Tipo | Trial de 30 dias
Tipo de Tutorial | [X]Original, []Adaptación, []Aplicación, []Traducción
Url | http://www.microsoft.com
Protección | Nag Screen. Time Limit 30 Dias
Dificultad | 1) Principiante, 2) Amateur, 3) Aficionado, 4) Profesional, 5) Especialista
Herramientas | SoftIce, RegMon
Objetivo | Extender el periodo de evaluación... ;-)
Cracker | Mr.Blue
Grupo | WkT!
Fecha | 29 de Julio de 2.000
INTRODUCCION
La familia Office 2000 de Microsoft está constituída por una serie de aplicaciones con un alto grado de compatibilidad entre ellas. Ejemplos de la "suite" del Office 2000 son las dos aplicaciones que nos ocupan. FrontPage 2000, mas que un editor de páginas HTML aisladas, es un completo editor de sitios web completos. Por su parte, PhotoDraw 2000 incluye todo lo necesario para el retoque de imágenes o incluso el retoque fotográfico. En el presente tutorial nos encargaremos de las versiones castellanas de ambos, la versión v4.0.1.2629 del FrontPage 2000 y la v2.0.0.0915 del PhotoDraw 2000. Para el desarrollo del tutorial nos limitaremos al FrontPage 2000, indicando las diferencias que pudieran existir con el PhotoDraw 2000. Que nadie espere grandes cosas de este tutorial, ya que el esquema de protección de ambas aplicaciones no introduce nada nuevo desde el punto de vista de la ingeniería inversa. Este tutorial puede ser más útil para los que empiezan en este mundo ya que muestra como grandes y complejas aplicaciones del tamaño del FrontPage y del PhotoDraw pueden venir con esquemas de protección a nivel de parvulario. Se ha dividido en dos partes para facilitar su lectura y descarga. Esta segunda parte está indicada para los novatos pero con conocimientos de SoftIce. En la primera parte se mostró como localizar los escondites donde las aplicaciones "víctima" escondían las fechas de instalación y de última ejecución. En este tutorial vamos a tirar con el SoftIce del hilo que encontramos con ayuda del RegMon a ver si sacamos el ovillo de la protección... ;-) Aparte de a los novatos de la ingeniería inversa este tutorial está dedicado a los chicos de Microsoft, de los que sabemos que viven pendientes de lo que hacemos en WkT!. Quizás la lectura de este tutorial les permita mejorar la protección de futuras versiones de evaluación de sus aplicaciones dificultando en lo posible la aparición de esos ¿dañinos? cracks.
AL ATAQUE
La pista de aterrizaje. En el anterior tutorial se localizaron sin demasiado trabajo los valores del registro en donde ambas aplicaciones almacenan las fechas de instalación y última ejecución. La tarea que nos queda por hacer es más rutinaria que otra cosa. Las opciones son variadas. Inicialmente lo más sencillo puede ser localizar el punto del programa donde se verifica si se ha encontrado el valor en el registro o no. Si conseguimos hacer creer al programa de que no ha encontrado el valor, simularemos que el registro se encuentra limpio, por lo que como se vio anteriormente el programa se limitará a crear el valor en el registro sin hacer ninguna verificación de la caducidad de la licencia. Otra opción es colocar un punto de ruptura en los accesos de lectura a la zona de memoria en la que la aplicación guarda los datos leídos del registro para "pescar" al código encargado de desencriptar los datos leídos y calcular los días restantes de evaluación. Una vez localizado el objetivo no queda más que desenfundar el editor hexadecimal y disparar... Pero lo primero es localizar en dónde carga la aplicación los datos cargados del registro. La solución lógica es colocar un breakpoint de ejecución en la función RegQueryValueEx que haga saltar el SoftIce para ver que valor se está consultando y dónde se almacena el resultado. Esta opción sería válida para otros programas, pero no para los que nos ocupan, con cientos de accesos al registro antes de arrancar la aplicación. Tenemos que limitar el breakpoint para que solo salte cuando a nosotros nos interesa, es decir, cuando lea el valor del registro que contiene la fecha de instalación y de última ejecución. Para ello el SoftIce permite la introducción de breakpoints condicionales, que solo salten cuando se cumplan las condiciones que se especifican. La mayoría de los lectores sabrán a lo que me refiero aunque para otros puede resultar una novedad. Consultando la ayuda de la función RegQueryValueEx no encontramos la siguiente cabecera:
`LONG RegQueryValueEx (` |
`HKEY hKey,` | // handle de la clave a consultar
`LPTSTR lpszValueName,` | // puntero al nombre del valor
`LPDWORD lpdwReserved,` | // reservado (NULL)
`LPDWORD lpdwType,` | // puntero al tipo de valor
`LPBYTE lpbData,` | // puntero al buffer de recepción
`LPDWORD lpcbData );` | // puntero al tamaño del buffer
De todos estos parámetros los que nos interesan son lpszValueName que apuntará al nombre del valor, en nuestro caso debe apuntar a 'MiscStatus', y lpbData que apuntará a la zona de memoria en la que la función devolverá el valor leído en el registro de Windows. En esa zona es donde colocaremos nuestro breakpoint de acceso de lectura para ver qué código es el que accede a él. El punto de ruptura será de la forma: `BPX RegQueryValueExA IF **(esp+8)=='Misc' DO "d*(esp+14)"` Este punto de ruptura se divide en tres partes:
`BPX RegQueryValueEx` | `Definimos donde queremos colocar el breakpoint.`
`IF **(esp+8)=='Misc'` | `Definimos la condición de disparo del breakpoint.`
`DO "d*(esp+14)"` | `Definimos las acciones a realizar cuando salte el breakpoint.`
En la condición de disparo referenciamos a la DWORD apuntada por el contenido de ESP+8. Para los que no lo sepan, el sistema de paso de parámetros utilizado en las llamadas en las funciones de la API se basa en la pila. En ella se vuelcan todos los parámetros, comenzando por el último y terminando con el primero. Cuando se produce una llamada a una función mediante la instrucción 'CALL' se añade a la pila la dirección de retorno a utilizar cuando finalice la función invocada con la instrucción 'RET'. Esta dirección será la de la siguiente instrucción al 'CALL'. Así, el contenido de la pila justo en la entrada de la función RegQueryValueEx será el siguiente:
`*(ESP) ------>` | `Dirección de retorno.`
`*(ESP+4) ---->` | `Primer parámetro: hKey`
`*(ESP+8) ---->` | `Segundo parámetro: lpszValueName`
`*(ESP+C) ---->` | `Tercer parámetro: lpdwReserved`
`*(ESP+10) --->` | `Cuarto parámetro: lpdwType`
`*(ESP+14) --->` | `Quinto parámetro: lpbData`
`*(ESP+18) --->` | `Sexto parámetro: lpcbData`
Por lo tanto, si `*(ESP+8) es el puntero al nombre del valor, **(ESP+8)` será el nombre del valor. Puesto que por defecto el SoftIce trabaja con DWORD, la DWORD apuntada por `**(ESP+8)` serán los cuatro primeros caracteres del nombre del valor, en este caso `'Misc'`. Las acciones a realizar en caso de activación del punto de ruptura se especifican tras la instrucción `DO` indicando entre comillas dobles los comandos queremos que ejecute el SoftIce, separados por ';'. En este caso sencillo solo vamos a mostrar el contenido de la zona de memoria donde la función va a devolver lo que ha leído del registro, aunque podría completarse con más cosas como un `'G *SS:ESP',` que equivale a ejecutar hasta el final de la función y parar en la instrucción siguiente al 'CALL' que invocó a la función. Lógicamente esto funcionará si el primer valor que lee el FrontPage que comienza por `'Misc'` es el que a nosotros nos interesa. En caso contrario nos saltará el breakpoint en momentos que a nosotros no nos interesa... `BPX RegQueryValueExA IF **(esp+8)=='Misc' DO "d*(esp+14);g *SS:ESP"` Este será el breakpoint que usaremos como pista de aterrizaje en el código del FrontPage. En el caso del PhotoDraw usaríamos, según lo que vimos en la primera parte del tutorial: `BPX RegQueryValueExA IF **(esp+8)=='Hand' DO "d*(esp+14);g *SS:ESP"` Lo colocamos en el SoftIce, y desde Windows arrancamos al conejillo de indias... ... y acción. Como era de esperar el breakpoint condicional nos ha dejado justo donde queríamos. Hemos aterrizado en la dirección 6782A528 (en el PhotoDraw 300B3F31), perteneciente al código de la librería 'FPCUTL.DLL' (archivo 'PHOTODRW.EXE' del PhotoDraw). Además en la ventana de datos tenemos los datos leídos del registro, a partir de la dirección 6784B0A8 (30146140 en el PhotoDraw), perteneciente a la sección de datos de la misma librería. Primero vamos a intentar localizar en que lugar del programa se verifica si se ha leído algo del registro o no. Empezamos a ejecutar paso a paso... Lo primero que hace la aplicación tras haber leído el valor del registro es ver si ha ocurrido un error, en cuyo caso el contenido del registro EAX será 2. Independientemente de que se haya producido el error o no, la aplicación cierra el manejador a la clave del registro con `RegCloseKey`. Una vez finalizada la función actual, justo después del 'CALL' de la rutina encargada de leer el registro nos encontramos lo siguiente: `6782A6BF: CMP [6784B0A8], EBX` `y en el caso del PhotoDraw:` `300B41CE: CMP [30146140], EBX` Lo que está haciendo el programa es comparar la primera DWORD leída del registro de Windows con el contenido de EBX, que en este caso es cero. Está es la comprobación que realiza el programa para ver si existía o no el valor en el registro. Si repetimos la operación pero borrando previamente el valor del registro comprobaremos que tras la lectura fallida esa zona de memoria se encuentra a cero. En caso de que se haya leído correctamente el valor del registro el salto condicional situado a continuación de la comparación se producirá. Para confundir al programa podemos hacer dos cosas: anular el salto para que nunca se produzca o bien modificar la comparación para que compare el registro EBX con alguna zona de memoria que esté siempre a cero. Para ser un poquito originales vamos a olvidarnos de la opción de nopear el salto. La zona de memoria que sigue al final de los valores leídos del registro se mantiene a cero. El valor leído del registro tiene un tamaño de 80 bytes, por lo que la zona de memoria situada a partir de 6784B0F8 (30146190 en el PhotoDraw) se mantiene a cero cuando el programa realiza estas verificaciones. Para realizar este cambio no tenemos más que sustituir el byte A8 (situado en el offset 0x5B6C1 de 'FPCUTL.DLL') por F8. Con esto obtenemos la siguiente instrucción: `6782A6BF: CMP [6784B0F8], EBX` Para el PhotoDraw sustituiremos el byte 40h (situado en el offset 0x0B41D0 de 'PHOTODRW.EXE') por 90h obteniendo la siguiente instrucción: `300B41CE: CMP [30146190], EBX` A partir de ahora la aplicación, a pesar de leer correctamente el valor del registro, interpretará que éste no se ha encontrado por lo que volverá a crearlo (más bien lo sobreescribirá) sin realizar ninguna comprobación sobre la caducidad de la versión de evaluación. Conclusiones. Existe la tendencia a pensar que una aplicación cuanto más grande y compleja es, más difícil es derribar las protecciones que trae. Esto no es cierto en todos los casos, como en estos dos ejemplos de Microsoft. Ambas aplicaciones basan su protección en unos datos guardados en el registro que, si no se encuentran, son inicializados ya que los programadores han supuesto que si dichos datos no se encuentran presentes es porque la aplicación se acaba de instalar. Estas aplicaciones no son las únicas cuyo periodo de evaluación de reinicializa mediante el borrado de una determinada clave del registro. Este "truco" funciona en muchas otras aplicaciones que basan su control de caducidad de la licencia en la fecha de instalación almacenada en el registro de Windows. El problema se reduce en hallar qué valor de los que se acceden del registro es el que guarda dicha información. Una vez hallada puede explotarse tal y como se ha mostrado en la segunda parte del tutorial, haciendo creer al programa que la clave de registro no existe. Para los más curiosos puede complicarse el asunto, llegando a descubrirse cosas interesantes. Por ejemplo, si en los dos ejemplos tratados seguimos el flujo del programa controlando los accesos de lectura a los bytes leídos del registro podremos descubrir que tanto en el FrontPage como en el PhotoDraw existen unos bytes que controlan la duración del periodo de evaluación, a partir de cuantos días comienza a aparecer la nag avisando de que quedan X días de evaluación e incluso un byte que indica si se debe controlar la caducidad del periodo de evaluación o no... En el caso del FrontPage estos bytes se encuentran en el fichero 'FPCUTL.DLL': `RVA 678312C0 OFFSET 0x622C0: 01 2D 00 00 00 0E` El último byte indica a partir de cuándo debe avisarse al usuario de que quedan X días de evaluación. En el caso del FrontPage es a partir de que resten 15 días de evaluación. El segundo byte indica cuántos días dura el periodo de evalaución, 45 en el FrontPage. Y el primer byte indica si debe controlarse la caducidad (01) o no (00). En caso de que no se controle (00), la aplicación niiquiera accede a la fecha de instalación almacenada en el registro. En el PhotoDraw estos bytes se encuentran en el fichero 'PHOTODRW.EXE': `RVA 301412FC OFFSET 0x1412FC: 01 1E 00 00 00 05` Con estos datos y un editor hexadecimal os podreis construir un periodo de evaluación a medida y de acuerdo con vuestras necesidades: más o menos días de evaluación, avisos de caducidad más o menos cerca del fin del periodo, evaluación indefinida... ;-) Por supuesto, estas modificaciones del periodo de evaluación debéis consultarlas antes con Microsoft, que es la empresa a la que pertenecen los derechos de ambos programas... no vayais a hacer nada ilegal... XDD Mr. Blue / [WkT ! 2000]
[ 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