-[ 0x02 ]--------------------------------------------------------------------
-[ Crackear usando WINE ]----------------------------------------------------
-[ by FCA00000 ]-----------------------------------------------------SET-35--


CRACKEAR usando...

==        == == ===  == =====
 \\      //  || ||\\ || |___
  \\ /\ //   || || \\|| |
   ==  ==    == ==  === ===== (wine)

------------------------------------------------------------------.-----------.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% by FCA00000
-----------------------------------------------------------------------------

Uno de los problemas que se encuentran los usuarios de Linux es que
ocasionalmente necesitan usar algn programa disponible slo para Windows.
Aparte de usar 2 ordenadores o 2 particiones, la solucin ms cmoda es usar
un programa que emule Windows. Esta solucin existe desde hace tiempo y se
llama "Wine".



&&&_____________________________&&&
||| ALGO Y MUCHO MS SOBRE WINE |||
&&&_____________________________&&&

Es un proyecto open-source y se puede obtener desde:

   -> http://www.winehq.org

Instalarlo a partir de los fuentes es cosa de 10 minutos.

Wine acta como una capa entre un programa de Windows y el sistema Linux.
Por ejemplo, si el programa quiere dibujar un punto, la llamada Windows a
la rutina de dibujar se intercepta y Wine invoca a su equivalente en X-Window.
Otro ejemplo: si el programa abre un fichero, Wine llama a las correspondientes
rutinas de Linux.

Qu pasa si no hay un equivalente? Pues se intenta apaar lo mejor posible.

Por ejemplo, el sistema de archivos: Windows permite que un fichero tenga
3 fechas: creacin, modificacin, y ltimo acceso. Sin embargo Linux no usa la
fecha de acceso. Para emularlo, guarda en un fichero interno, una lista con los
ficheros, y su fecha de acceso. Cuando algn programa quiere saber la fecha de
acceso, Wine la saca de este fichero interno.

Dado que Windows contiene muchas libreras con muchas funciones, traducir todas
es una tarea enorme. Por eso Wine trabaja con 2 tipos de rutinas:

   1 -> emuladas: alguien ha analizado la rutina original de Windows y la ha
        programado en Wine. Por ejemplo, abrir un fichero.

   2 -> directa: se ejecuta 'tal cual', es decir, que llama a la rutina
        original. Esto tiene el inconveniente de que no se sabe exactamente
        lo que hace, por lo que puede que no funcione bien.

Vamos a ver un ejemplo. Supongamos un programa hecho para windows que consta
del programa principal, y una librera que cifra datos.
Cuando lo ejecutamos en Wine, este programa llamar a:
-rutinas tpicas de Windows: mostrar GUI, iniciar mens, pedir datos, obtener
nombre de usuario... Todas estas rutinas han sido analizadas por la gente de
Wine y estn traducidas. Es decir, que las libreras originales han sido
reemplazadas por equivalentes en Wine.
-rutinas de la librera para cifrar datos. Como esta librera no es estndar
de Windows, nadie se ha molestado en traducirla a Wine. Por tanto hay que
ejecutarla directamente, sin interceptarla.

Vamos a ver un ejemplo de cmo se emulan las rutinas.

En windows existe una funcin llamada GetTempFileNameW que sirve para obtener
un nombre nico de fichero. Esto se usa cuando necesitas generar un fichero
temporalmente. Cualquier programa puede invocar a esta funcin, que est
incluida en la librera "kernel23.dll". El cdigo fuente est en:
"wine/dlls/kernel32/path.c" y se declara como:

o---------------------------------------------------------------o
|   UINT WINAPI GetTempFileNameW( LPCWSTR path, LPCWSTR prefix, |
|                                 UINT unique, LPWSTR buffer )  |
o---------------------------------------------------------------o

Es decir, que tiene 4 parmetros.

Cmo han sabido el nombre de la rutina, y el nmero de parmetros?

En este caso, es una rutina disponible para todo programador de Windows, por
lo que su API (Application Programming Interface) est documentado en el SDK
de Windows.

Los chicos de Wine no tienen acceso al cdigo fuente de Windows, por lo que
simplemente pueden imaginar cmo funciona internamente esta rutina. As que lo
han traducido a algo as:

   1.- toma el nombre del directorio path
   2.- si no acaba en '\' , adela.
   3.- si se ha pasado el argumento  prefix , adelo.
   4.- toma un nmero aleatorio y convirtelo en un  string. Adelo.
   5.- ahora tenemos un nombre de fichero.
   6.- intenta abrir el fichero. Si ya existe, intenta otro nmero aleatorio
       hasta que funcione.

Es esto exactamente lo mismo que hace Windows en su cdigo original?
Slo lo pueden decir los programadores originales de Windows. Pero parece
funcionar.

Esto es el mayor reto de la gente de Wine: quizs Windows hace algo parecido,
pero no exactamente lo mismo.
Por otro lado, est la paradoja de que un bug de Windows quizs no exista en
Wine, y viceversa.

Esto es lo que se hace para funciones emuladas, pero algunas no lo estn;
algunas por falta de tiempo, otras por falta de inters. Para qu molestarse
en emular una funcin que no se usa nunca?
Por ejemplo, la funcin InvalidateNLSCache de kernel23.dll , no-emulada en
wine/dlls/kernel32/locale.c

Su cdigo en Wine es simplemente:

o----------------------------------------o
|   BOOL WINAPI InvalidateNLSCache(void) |
|   {                                    |
|     FIXME("() stub\n");                |
|     return FALSE;                      |
|   }                                    |
o----------------------------------------o

O sea, que cuando un programa invoca a InvalidateNLSCache en Windows,
seguramente pasa algo.
Pero al ejecutarlo en Wine, no hace nada. Slo muestra un error en la
consola, y devuelve el valor False.

En el cdigo fuente de Wine no se dan detalles de la razn de no emularla,
pero seguramente es porque no afecta a la funcionalidad de Windows.

Cuando se compila Wine, hay unos ficheros que indican cuales libreras estn
completamente emuladas, cuales lo estn parcialmente, y cuales son ejecutadas
directamente.
Estos ficheros tambin indican cuales son las rutinas emuladas, y cuales no lo
estn.
Si una rutina no est emulada, lo normal es hacer que invoque a la original.
Esto se hace usando:

o--------------------------------------------------o
|   __wine_stub_InvalidateNLSCache(void) {         |
|      __wine_unimplemented("InvalidateNLSCache"); |
|   }                                              |
o--------------------------------------------------o

Por eso, Wine necesita que Windows est instalado. Si un programa llama a una
funcin emulada tal como GetTempFileNameW, llamar a la librera kernel32.dll
de Wine.
Si no lo est, como en el caso de InvalidateNLSCache, entonces llamar a
kernel32.dll original de Windows.

Cmo hacen los programadores de Wine para saber lo que hace Windows?

Lo primero es mirar la documentacin del SDK de Windows. Luego hacen un programa
que prueba la rutina una y otra vez, con distintos parmetros. Miran el
resultado.
Entonces escriben el cdigo para simularla. Prueban a ver si la rutina emulada
acta igual que la original.
Notar que no pueden desensamblar el cdigo de Windows porque est prohibido.
Tampoco pueden leer el cdigo fuente original de Windows (en caso de que lo
tengan) porque esto va en contra del copyright. Quizs a ti no te importe,
pero si Microsoft encuentra parte de su cdigo dentro de Wine, les puede meter
en un gran apuro.

Despus de esta larga introduccin, vamos a ver cmo usarlo en nuestro provecho.
Mi objetivo es crackear un programa llamado VPOM1510-SB_1.0_Installer.exe , que
es un emulador de telfonos Symbian, pero esto no es importante.
Este programa tiene una limitacin de 7 das de uso.

As que tras compilar wine-1.1.4 e instalarlo, ejecuto:

   $ wine VPOM1510-SB_1.0_Installer.exe

que me presenta el programa de instalacin de VPOM1510-SB_1.0_Installer.exe
Notar que VPOM1510-SB_1.0_Installer.exe es un binario de Windows, lo que
demuestra que Wine funciona. Tras unas cuantas pantallas de presentacin, el
programa se instala.

Al usar Linux, obviamente yo no tengo un disco C: pero Wine lo ha simulado en
el directorio "$HOME/.wine/drive_c/" en particular, tengo:

   $HOME/.wine/drive_c/Virtio/Softboards/VPOM1510-SB-SYMB/bin/vrelaunch.exe

O sea, que est instalado correctamente.

Al intentar ejecutarlo, me da el siguiente error:

o-----------------------------------------------------------------------------o
|err:module:import_dll Library MFC42.DLL (which is needed by L"$HOME\\.wine\\ |
|drive_c\\Virtio\\Softboards\\VPOM1510-SB-SYMB\\bin\\vrelaunch.exe") not found|
o-----------------------------------------------------------------------------o

Esto es fcil de arreglar: busco "MFC42.DLL" en mi instalacin de Windows y lo
copio a:

   $HOME/.wine/drive_c/windows/system32/MFC42.DLL

lo intento de nuevo, y ahora arranca correctamente el programa vrelaunch.exe

Lo primero es que me presenta una pantalla para configurar VPOM1510-SB-SYMB
pero esto no es lo importante. Una vez configurado intento ver cmo afecta la
limitacin de 7 das. Para ello adelanto la fecha de mi sistema y observo que
VPOM1510-SB-SYMB dice que ha caducado, y sale. Cierro el programa, retraso la
fecha, pero el programa detecta que ha expirado anteriormente.

No hay problema: borro $HOME/.wine/drive_c/ y arranco de nuevo el instalador:

   $wine VPOM1510-SB_1.0_Installer.exe

Una vez instalado, hago una copia de "$HOME/.wine/drive_c" y la llamo:
"$HOME/.wine/drive_c_tras_instalacion".

o-_NOTA_-----------------------------------------------------------------o
|                                                                        |
| 1.- Esto es una de las cosas buenas de Wine. Me permitir volver a una |
|configuracin anterior. Ya s que hay herramientas de Windows que hacen |
|lo mismo, pero es una cosa til.                                        |
o------------------------------------------------------------------------o

As que arranco el programa instalado y cuando lo tengo configurado, hago otra
copia en "$HOME/.wine/drive_c_tras_configuracion".
Comparo los directorios y veo que se han generado varios archivos nuevos. Uno
es el de configuracin, y otro se llama:

   "$HOME/.wine/drive_c/windows/system32/2222NPR11QW.oc"

Tras instalar el programa un par de veces en un entorno 'limpio', aprendo
que este es un fichero que se crea en cuanto el programa se ejecuta por
primera vez.

Si el programa expira y lo desinstalas, este fichero "2222NPR11QW.oc" no
desaparece. Cuando re-instalo el programa, verifica este fichero, y sabe que
anteriormente estaba instalado y caducado, por lo que rehsa instalarse de
nuevo. No es una proteccin muy sofisticada, pero algo es algo.

No slo eso, sino que hay un archivo que ha cambiado, llamado:

   "$HOME/.wine/system.reg"

Este fichero es de tipo texto, as que lo cargo en mi editor favorito y veo que
es el equivalente al registro de Windows. Esto dice mucho a favor de la gente de
Wine. En el Windows original, el registro es un fichero binario accesible a
travs del API GetRegKey y similares. En Wine han traducido esta funcin en otra
que hace lo mismo, usando un fichero de texto.

As que puedo comparar los ficheros:

      $HOME/.wine/drive_c_tras_instalacion/system.reg
   y
      $HOME/.wine/drive_c_tras_configuracion/system.reg

Con esto veo que el instalador crea unas entradas en el registro de Windows, en
la clave: [Software\\Classes\\vdsp]

Al caducar o desinstalarse, estas entradas no desaparecen, por lo que una
reinstalacin posterior se queja de que haba caducado anteriormente.

Por tanto ya s en qu consiste la proteccin de re-instalacin: un fichero y el
registro. As puedo instalarlo una y otra vez, sin ms que borrar el fichero
"2222NPR11QW.oc" y las entradas del registro.



&&&________________________&&&
||| A CRACKEAR SE HA DICHO |||
&&&________________________&&&

Ahora viene la parte de crackeo tpico: en algn lugar debe de haber una
verificacin de fechas. Podra desensamblarlo con IDA o ejecutarlo paso a
paso con OllyDBG, pero voy a usar el poder de Wine.

Segn la documentacin es posible poner un traceador usando la variable de
entorno:

   WINEDEBUG=warn+all

que pondr el nivel mximo de traceado.

As que ejecuto:

   $env WINEDEBUG=warn+all wine vrelaunch.exe 2>trace.txt

y genera un listado de 500 lneas.

Esta traza incluye todos los avisos (warning) que suceden en Wine. Estos avisos
se producen porque algo no funciona como se espera. Por ejemplo algn archivo
que no existe, o alguna rutina que no se sabe si est bien emulada.
Estos avisos deben de haber sido previstos por el programador, usando la lnea:

   WARN( "algo va mal porque valor=%x\n", value );

Por ejemplo, la rutina "LocaleNameToLCID" incluye:

o--------------------------------------------------------------------o
|   LCID WINAPI LocaleNameToLCID( LPCWSTR name, DWORD flags )        |
|   {                                                                |
|      ...                                                           |
|      if (!locale_name.matches)                                     |
|         WARN( "locale %s not recognized, defaulting to English\n", |
|                debugstr_w(name) );                                 |
|      ...                                                           |
|   }                                                                |
o--------------------------------------------------------------------o

es decir, que si el idioma (locale) elegido no es correcto, lo pone en ingls.
El programador no sabe si esto es adecuado o no; por eso avisa.

En esta misma rutina encontramos

o--------------------------------------------------------o
|   if (flags) FIXME( "unsupported flags %x\n", flags ); |
o--------------------------------------------------------o

o sea, que esta rutina funciona correctamente, excepto si se usa el parmetro
"flags" . En este caso genera un error de tipo 'fixme', en lugar de 'warning'.

Aun existe otro tipo de notificacin usada por los programadores:

o--------------------------------------------------------------o
| TRACE("setting %x (%s) to %s\n", lctype, debugstr_w(value),  |
|                                          debugstr_w(data) ); |
o--------------------------------------------------------------o

esto permite saber los valores que se le han mandado a esta rutina.
Dado que Wine es capaz de ejecutar cualquier programa de Windows, no es seguro
que usen los parmetros correctos. Con este tipo de traza es posible analizar
un programa en modo off-line, cuando ya se ha ejecutado.

Para que se muestre una traza ms completa, se usa: "WINEDEBUG=trace+all".
Para verlo ms claro, os dir que una de las lneas que sale en trace.txt es

   0009:trace:reg:NtOpenKey (0x10,L"Environment",f003f,0xbfc1bc68)

y viene del fichero "wine/dlls/ntdll/reg.c" en la lnea:

o-----------------------------------------------------------------------------o
|  NTSTATUS WINAPI NtOpenKey( PHANDLE retkey, ACCESS_MASK access,             |
|                                             const OBJECT_ATTRIBUTES *attr ) |
|  {                                                                          |
|     ...                                                                     |
|     TRACE("(%p,%s,%x,%p)\n", attr->RootDirectory,                           |
|                              debugstr_us(attr->ObjectName),access,retkey ); |
|     ...                                                                     |
|  }                                                                          |
o-----------------------------------------------------------------------------o

o sea, que la funcin NtOpenKey muestra una traza de 4 argumentos:

   1) attr->RootDirectory
   2) debugstr_us(attr->ObjectName)
   3) access
   4) retkey

No slo eso, sino que esta funcin NtOpenKey incluye al final la lnea:

o----------------------------o
| TRACE("<- %p\n", *retkey); |
o----------------------------o

que imprimir el valor que se va a devolver.

Por eso en la traza encontramos: 0009:trace:reg:NtOpenKey <- (nil)

Para completar, vemos que la traza incluye "0009:trace:reg:NtOpenKey" que
significa que el nivel de debug es 'trace' , que el mdulo es 'reg', y que
la rutina invocada es 'NtOpenKey'.

Dado que Wine es un proyecto bastante grande, se divide en mdulos.
Por ejemplo la funcin "NtOpenKey" est incluida en el mdulo 'reg'.
Esto permite debugear slo los mdulos que te interesan.

En este caso, yo buscaba las funciones que sirven para saber la hora y
fecha actual, que se obtienen en:

o-------------------------------------------------------------------o
|   NTSTATUS WINAPI NtQuerySystemTime( PLARGE_INTEGER Time )        |
|   {                                                               |
|      struct timeval now;                                          |
|                                                                   |
|      gettimeofday( &now, 0 );                                     |
|      Time->QuadPart = now.tv_sec * (ULONGLONG)TICKSPERSEC +       |
|                                               TICKS_1601_TO_1970; |
|      Time->QuadPart += now.tv_usec * 10;                          |
|      return STATUS_SUCCESS;                                       |
|   }                                                               |
o-------------------------------------------------------------------o

Vaya, esta funcin no tiene un TRACE adecuado, as que yo se lo pongo:

o-----------------------------------o
| TRACE("<- %x\n", Time->QuadPart); |
o-----------------------------------o

Pongo en marcha el programa, y espero a que llegue a esta lnea.
Observo que se llama desde:

   1 - KERNEL32.GetTimeZoneInformation
   2 - KERNEL32.GetSystemTimeAsFileTime

as que pongo otra traza ah.

Ahora puedo usar el mtodo tpico de poner un breakpoint y ver dnde
"vrelaunch.exe" llama a "NtQuerySystemTime" y calcula los 7 das, pero
voy a seguir usando Wine.

La estrategia es que sea el propio Wine el que salte la limitacin.
Para ello, recordar que el lmite es 7 das, as que tengo que modificar
"NtQuerySystemTime" para que siempre me devuelva la misma fecha:

o------------------------------------------------------------------------o
|   NTSTATUS WINAPI NtQuerySystemTime( PLARGE_INTEGER Time )             |
|   {                                                                    |
|      // 100 segundos despus del ao 1601                              |
|      Time->QuadPart = 100*(ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970; |	
|      return STATUS_SUCCESS;                                            |
|   }                                                                    |
o------------------------------------------------------------------------o

Las primeras pruebas demuestran que esto est mal, porque hace que el tiempo
sea constante y descoordina todo lo que se base en alarmas, intervalos, y
fechas de modificacin. As que hay que ser ms inteligente:

o---------------------------------------------------------------------------o
|   NTSTATUS WINAPI NtQuerySystemTime( PLARGE_INTEGER Time )                |
|   {                                                                       |
|      struct timeval now;                                                  |
|                                                                           |
|      gettimeofday( &now, 0 );                                             |
|      now.tv_sec %= 7*24*60*60;     //nmero de segundos que hay en 7 dias |
|      Time->QuadPart = now.tv_sec * (ULONGLONG)TICKSPERSEC +               |
|                                               TICKS_1601_TO_1970;         |
|      Time->QuadPart += now.tv_usec * 10;                                  |
|      return STATUS_SUCCESS;                                               |
|   }                                                                       |
o---------------------------------------------------------------------------o

o sea, que devuelve el tiempo correcto, pero siempre referido a la primera
semana del ao 1601. De otra manera: el tiempo avanza como siempre, pero el
domingo vuelve a ser el lunes de la semana anterior. Por eso parece que
nunca pasan ms de 7 das.

Con esto se consigue engaar al programa para que nunca caduque.

No es el crack perfecto porque necesita Wine y puede fastidiar a otros
programas, pero a m me sirve; sobre todo para ilustrar el poder de Wine.



&&&_________________________&&&
||| Y AHORA LLEGO EL POSTRE |||
&&&_________________________&&&

Como parece que ha quedado corto, voy a profundizar un poco ms.

Cuando se desarrolla un emulador y se prueban programas, a veces fallan.
En este caso es necesario analizar si el programa original tambin falla.
Para ello Wine cuenta con un debuger llamado winedbg que acta como cualquier
debuger tpico de windows, con el aliciente de que se integra en Wine.

Entre las opciones que ms inters tiene, estn:

   (*) "info share"  -> para ver las libreras que estn cargadas
   (*) "info maps"   -> para que muestre las zonas de memoria del programa
   (*) "info locals" -> para ver las variables locales

Por supuesto tambin son fundamentales las instrucciones para poner breakpoints.

Vamos a verlo con un ejemplo.

   $winedbg vrelaunch.exe

nos deja en el nuevo prompt:

   Wine-dbg>

que se detiene en cuanto el proceso est cargado.

Para continuar, hacemos:

   >finish

y el programa empieza. Podemos detenerlo con Control-C.

Para ver los registros:

   >info all-reg
   Register dump:
   CS:0073 SS:007b DS:007b ES:007b FS:0033 GS:003b
   EIP:ffffe410 ESP:0033f998 EBP:0033fa40 EFLAGS:00200246(   - 00      - IZP1)
   EAX:00000000 EBX:00000002 ECX:0033fa64 EDX:00000000
   ESI:00000008 EDI:b7dbbff4

Para desensamblar cdigo:

   >disassemble 0xffffe410
   0xffffe410: popl        %ebp
   0xffffe411: popl        %edx
   0xffffe412: popl        %ecx

Para ejecutar la siguiente instruccion:

   >n

Y para las siguientes, pulsar ENTER.

Por ejemplo, se detiene en:
 
   GetActiveWindow () at /home/curro/wine-1.1.4/dlls/user32/../../
include/wine/server.h:62
62          if (res) SetLastError( RtlNtStatusToDosError(res) );

Si ahora queremos poner un breakpoint, se hace:

   >break NtQuerySystemTime
   Breakpoint 1 at 0x7efcb170 NtQuerySystemTime
   [/home/curro/wine-1.1.4/dlls/ntdll/time.c:449] in ntdll

y hala, a esperar a que se dispare.

A partir de este momento obtenemos una traza de este tipo:

   =>1 0x7efcb170 stub_entry_point+0x4c(dll="ntdll.dll", name="")
       [/home/curro/wine-1.1.4/dlls/ntdll/time.c:449] in ntdll (0x0033e8a0)
     2 0x1000aed0 in vrelaunch (+0xaed0) (0x0033e8d0)
     3 0x1000b1c9 in vrelaunch (+0xb1c9) (0x0033e8f8)
     4 0x10029cf5 in vrelaunch (+0x29cf5) (0x0033e910)

y se puede desensamblar:

   >disassemble 0x1000aed0

A partir de este punto a m me gusta usar un desensamblador off-line como IDA.
Pero no resulta difcil ver que habra que parchear la rutina de "vrelaunch.exe"
que est alrededor de 0x1000b1c9.

Ms informacin en:

   -> http://www.winehq.org/site/docs/winedev-guide/wine-debugger


o-_NOTAS_----------------------------------------------------------------o
|                                                                        |
| 1.- A todos aquellos que estn interesados en pasarse a Linux pero     |
|     necesitan usar aplicaciones Windows, les recomiendo que usen Wine. |
|                                                                        |
| 2.- Para los que quieren investigar sobre emulacin de sistemas, que   |
|     miren el cdigo fuente.                                            |
|                                                                        |
| 3.- Y para los que quieren aprender otra tcnica sobre ingeniera      |
|     inversa, esta es una gran herramienta fcil de adaptar a tus       |
|     necesidades.                                                       |
o------------------------------------------------------------------------o

*EOF*