Karpoff Spanish Tutor

Programa: AllWebMenus v 1.3 Build #354


 

PROTECCION: Unlock Code
Descripcion: Crea menus flotantes taco de chulos para páginas web
Dificultad: Facililla
DOWNLOAD: http://www.alwebmenus.com
Herramientas: Softice, W32dasm,Hex WorkShop, RegMon, Topo.
CRACKER: AuspeX   FECHA: 01/03/2002

 

 INTRODUCCION

Este soft digamos que fue el que, en cierto modo, me inicio en este mundo del cracking, pero es una historia muy larga para explicarla ahora. El programa que vamos a tratar esta escrito en lenguaje Visual Basic 6 y utiliza la librería MSVBVM60.DLL con los problemas que llevan estos programas para encontrar el código correcto mediante traceo (lo digo por experiencia con otros programas escritos en dicho lenguaje), aunque, algunas veces, son incluso más faciles de crackear de lo que parecen. Nos vamos a ayudar de las funciones que utiliza dicha librería para encontrar el code correcto.

 

 AL ATAKE

Abrimos el programa, lo ejecutamos. Le echamos un vistazo, y nos vamos directamente al menú de Help para ver que es lo que tenemos ahí. Podemos observar la opción Register AllWebMenus. Pues nada, picamos e intentamos registrarnos metiéndole cualquier chorrada que se nos ocurra, ¿me apuesto 1000 duros a que no acertais a la primera? (si por casualidad alguien acertó de primera, retiro la apuesta, xD).

Bueno, pues ante esto, lo primero que a mi se me ocurrió (por que soy muy flojo) fue abrir el W32Dasm y mirar a ver si por casualidad encontraba la referencia a esta cadena, y de hecho tuve suerte y la encontré cuando desensamblé el ejecutable del programa. Os pondré el código más o menos resumido (lo más importante) de lo que me fui encontrando en los alrededores de la referencia:

:005474CE FF154C104000 Call dword ptr [0040104C]
:005474D4 83C418 add esp, 00000018
:005474D7 663BF3 cmp si, bx
:005474DA 0F8486000000 je 00547566
<-----Ahora veremos que nos manda a la zona de chico bueno saltandose la zona de chico malo que está aquí, mas abajo.

* Reference To: MSVBVM60.__vbaVarDup, Ord:0000h
|
:005474E0 8B3570124000 mov esi, dword ptr [00401270]
:005474E6 B904000280 mov ecx, 80020004
:005474EB 894D9C mov dword ptr [ebp-64], ecx

............

............

* Possible StringData Ref from Code Obj ->"Failed to register" <-----titulo de la ventana de error
|
:0054750A C7857CFFFFFFBCFE4100 mov dword ptr [ebp+FFFFFF7C], 0041FEBC
:00547514 899D74FFFFFF mov dword ptr [ebp+FFFFFF74], ebx
:0054751A FFD6 call esi
:0054751C 8D5584 lea edx, dword ptr [ebp-7C]
:0054751F 8D4DC4 lea ecx, dword ptr [ebp-3C]

* Possible StringData Ref from Code Obj ->"The password you entered is not " <-----nuestro mensaje de error
->"correct"
|
:00547522 C7458CE8FE4100 mov [ebp-74], 0041FEE8
:00547529 895D84 mov dword ptr [ebp-7C], ebx
:0054752C FFD6 call esi

............

............

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:005474DA(C)
|
:00547566 391D785D5500 cmp dword ptr [00555D78], ebx
<-----Comienza la supuesta zona de chico bueno
:0054756C 7510 jne 0054757E
:0054756E 68785D5500 push 00555D78
:00547573 68784E4100 push 00414E78

............

............

* Possible StringData Ref from Code Obj ->"pwd" <-----luego veremos que es esto
|
:00547609 68C84E4100 push 00414EC8

* Possible StringData Ref from Code Obj ->"Settings"
|
:0054760E 689C4E4100 push 00414E9C
:00547613 52 push edx

...........

...........

* Possible StringData Ref from Code Obj ->"Registration Completed" <----- ¡ Chico buenooooo !
|
:00547667 C7857CFFFFFF90FF4100 mov dword ptr [ebp+FFFFFF7C], 0041FF90
:00547671 899D74FFFFFF mov dword ptr [ebp+FFFFFF74], ebx
:00547677 FFD6 call esi
:00547679 8D5584 lea edx, dword ptr [ebp-7C]
:0054767C 8D4DC4 lea ecx, dword ptr [ebp-3C]

* Possible StringData Ref from Code Obj ->"Thank you for registering AllWebMenus!" <-----gracias tio, ajaja
|

Bueno, una vez visto este pequeñito resumen, se ves más o menos que es lo que se puedría intentar cambiar aquí para que nos registre el programa, no?, y es ese salto primero que nos mandría a la zona de chico bueno. Pués nada, lo cambiamos el je a jne para que salte si la clave no es la correcta (creo que sería más fácil acertar la clave incorrecta que la correcta, verdad?), ya sabeis, se busca el desplazamiento con el W32Dasm y con el editor hexadecimal, en este caso, cambiar un 84 por un 85). Volvemos a probar ahora. Metemos la clave que nos da la gana y que es lo que nos sale?...

¡Mirad, nos da las gracias y todo!, pero que bueno es el infeliz. Muy bien, aparentemente todo ha salido de puta madre (jeje, yo ya sé que no es así), pero cuando por ejemplo nos metemos en el menú Help y picamos en About nos damos cuenta de que ahí sigue poniendo: This is an Unregistered Copy, ¡jur!, ¿pero si nos ha dado las gracias y todo?, ¿que habrá pasado?. volvemos a registrarnos (ya tenemos el salto cambiado), nos sigue dando las gracias, pero la cosa sigue sin funcionar. Bueno, esto es uno de los muchos programas que te demuestran que no basta con cambiar el salto que te lleva a la zona de chico bueno. En este caso le hemos metido una clave, que aparentemente es la correcta, pero que en realidad no nos registra, simplemente hacemos que nos salga el mensajito de que todo va de muy bien. Pero hay algo más, y fue como el plan B una vez fallado el plan A. ¿Os acordais de la referencia a una cadena pwd que vimos en el código anterior? (mirad otra vez si no os acordais), pues investigué eso un poquito a ver si me podría dar una pista. Resulta que aparecía más de una vez en el código desensamblado. ¿pero que era eso?...

Bueno, la experiencia con otros programas del mismo tipo me hizo intentar observarlo con el programa RegMonitor con el cual podemos ver los movimientos que existen en el registro de Windows mientras estamos corriendo programas. Una vez arrancado RegMon ejecutamos el programa y observamos las entradas de registro que este toca, mirad la sorpresa que me llevé:

¿Veis?, pwd es un valor que nos encontarmos en el registro. Picamos dos veces en anguna línea de estas para que nos lleve a esta dirección en el registro y ahí podemos ver muchos valores, parámetros, etc... que utiliza el programa para funcionar. El valor pwd tiene como información la clave que le metimos y se tragó por to la cara. Hay otra que me llama mucho la atención y es pid que tiene el ID del software. Parece que ya tenemos una pista más o menos clara de lo que sucede aquí. Posiblemente a alguno ya se le ha ocurrido algo ¿verdad?. Nosotros cuando le metimos la clave, se la tragó, y la grabó en el registro, pero una vez que intentamos ver si estamos registrados o no, nos dice que nanai de la china, y ¿por que? porque esa no es la verdadera clave, porque cuando intenta ver si estamos registrados o no, de alguna manera vuelve a mirar en el registro, genera la verdadera clave y la compara con esta que tenemos aquí, y claro no es la buena. Eso fue fácil deducirlo cuando arranqué el programa, me metí en el menu Help y pique en About, y todo esto con RegMon cargado. Pasó que volvía a mirar los valores de PID y PWD. Pues entonces ya está, aunque se trage las claves que le metamos eso no nos sirve de nada, pues siempre mirará en el registro y pillará la clave de ahí. pid posiblemente lo utilice para generar la clave clave correcta, pues cada vez que va a comparar le mete mano en el registro. ¿Y ahora qué?, pués lo que a mi se me ocurrió fue lo siguiente: ya sabemos como trabaja, es decir, tanto cuando arranca, como cuando se mira en About y en otras funciones más del programa, este genera internamente la clave, luego le mete mano a la que se supone que hay guardada en el registro, y las compara de alguna manera, pues entonces por que no probar la función __VBASTRCMP, que utiliza Visual Basic para comparar cadenas?, recordad que el programa está hecho en Visual Basic 6. Probemos a poner un punto de ruptura en dicha función y sacar de nuevo la ventanita de About. Para ello debemos de tener arrancado Soft-Ice y meternos dentro con CTRL+D, poner: bpx __vbastrcmp y pulsamos intro, luego F5 para seguir, y entonces sacamos la ventanita. ¡Plass! el sice revienta como era de esperar. Una vez dentro, intenté mirar en las direcciones que indicaban los registros, para ver si por casualidad veia la clave correcta, tenía que estar por ahí. La primera vez sólo vi mi clave, y digo la primera vez por que saltó varias veces en dicha función, concretamente 3 veces. Una cosa importante, esto sucede cuando tienes un pwd en el registro, si no lo tienes sólo saltará 1 vez (todo esto lo probé). Pués eso, me lie a mirar las direcciones a donde aputaban los registros y entonces es cuando pezqué la clave correcta paseándose por la memoria. No había más que verla para darse cuenta de que se trataba de una clave: CCU-94H-J6E, ¡joder no me digais que no tiene to la pinta!. Siempre que veais cosas así os la apuntais y la probais a ver si furula. Pues ya está, la probé y furuló a las mil maravillas. Ahora en About aparecía: Registered Copy, ya estaba realmente registrado el programa.

RETOMANDO EL TUTORIAL

Llegado este punto habría terminado el tutorial, sino fuese por que acabo de leer uno sobre WinZip, escrito por CKENER, y que me ha dado una idea estupenda para este programa. Fijaos, a CKENER se le ocurrió redirigir en cierto modo la dirección del mensaje de error de forma que en vez de sacar dicho mensaje, sacase la clave correcta. ¿Os dais cuenta?, es como crearse el KeyGen pero utilizando el propio código del programa (para que implementarlo si ya viene en dicho programilla, jeje). Bueno, pues yo más o menos intenté hacer lo mismo, pero no sabía como pasarle a la función RTCMSGBOX la dirección del código correcto, lo intenté, pero es que realmente cuando estudié la forma en que pasaba el mensaje de error, cambié la dirección para que saliese la clave, pero salía el mensajito en blanco. Bueno, en resumidas cuentas, que tuve problemas para hacer esto mismo con esta función de Visual Basic, asi que se me ocurrió otra cosa, quizas más rápida aún. ¿Recordais que cuando le cambiábamos ese saltopara llevarnos a la zona de chico bueno, nos grababa la clave que le habíamos metido en el registro, aunque fuese la errónea?, bueno, pués lo que vamos a hace es que en vez de que nos grabe la chorra de password, nos meta diréctamente la pass correcta, de esta manera nosotros mismos hacemos que nos registre con la clave correcta que pezcamos (nosotros se la quitamos y luego se la vendemos, jeje). ¿Y como hacemos eso?, pués lo primero de todo es estudiar la forma en que graba el código en el registro. Veamos este trozo de programa desensamblado:

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:005475EE(C)
|

:00547602 8B4DE4 mov ecx, dword ptr [ebp-1C] <-----en ecx la dirección de nuestra clave pachanguera
:00547605 8B55E8 mov edx, dword ptr [ebp-18] <-----la dirección de la cadena "AllWebMenus"
:00547608 51 push ecx <-----pushea nuestra clave

* Possible StringData Ref from Code Obj ->"pwd"
|

:00547609 68C84E4100 push 00414EC8 <-----"pwd"

* Possible StringData Ref from Code Obj ->"Settings"
|

:0054760E 689C4E4100 push 00414E9C <-----"Setting"
:00547613 52 push edx <-----ya sabemos que pushea

* Reference To: MSVBVM60.rtcSaveSetting, Ord:02B2h
|

:00547614 FF1508104000 Call dword ptr [00401008]
<-----a guardar se ha dicho, jeje

Pués lo que yo hice fue lo siguiente: Hice un injerto de código utilizando un programa que se llama Topo, programado por MrCrimson, vesión 1.2, ¿pero para que ese injerto?, pués muy sencillo, lo que pretendía era mandar como parámetro, en vez de mi falsa clave, la clave correcta quenerada internamente, pero había el problema de que la clave era destruida antes de llegar aquí y también se perdía la dirección. Luego el injerto de cógido era para guardar la verdadera pass en alguna zona de memoria libre que no fuese modificada y luego mandar esa dirección como paramáetro de la función RTCSAVESETTING. Y este fue mi código injertado:

INICIO:

----------push ecx ;salvamos registros
----------push edi
----------push esi
----------mov cl,b ;longitud de la clave -> 12
----------mov edi,555360 ;dirección que elegí para guardar la clave buena
----------mov esi,[ebp-14] ;aquí tenemos nuestro tesoro

ETIQ1:

----------mov al,[esi] ;transladamos la pass
----------mov [edi],al
----------inc esi ;incrementamos dos veces por el tema del formato widechar: a u s p e x ,¿veis? formato VB
----------inc esi
----------inc edi
----------inc edi
----------dec cl
----------cmp cl,0
----------jnz ETIQ1 ;bucle tantas veces como caracteres tenga la clave
----------pop esi ;recuperamos valores
----------pop edi
----------pop ecx
----------jmp RETORNO ;retorna

Ahora sólo quedaba pasarle la dirección 555360: en vez de hacer mov ecx,[ebp-1C], hacer mov ecx,555360. Pero cuando lo probé la cosa no funcionó del todo, y digo que no funcionó del todo por que sólo guardó la primera letra de la pass correcta. ¿Que podría pasar?, pues muy sencillo, estudiando el código interno de la llamada RTCSAVESETTING, observé que también pasaba un número a un registro, haciéndole un desplazamiento hacia la derecha y convirtiéndolo en otro que coincidía con el número de caracteres que tenía la clave, por lo tanto aquí estaba el problema, también tenía que pasar dicho número que se encontraba a 4 bytes por debajo de la clave y era 16, que al desplazarlo un bits hacia la derecha se convierte en B que equivale a 11. Recordad la clave que obtuvimos al principio CCU-94H-J6E, tiene 11 caracteres, ¿veis?, pues ya está, sólo quedaba insertar un poco de más código que hiciera algo como esto:

INICIO:

----------push eax ;salvamos registros
----------push esi
----------mov esi,555360 ;colocamos la dirección donde guardamos la clave correcta
----------mov al,16
----------mov [esi-4],al ;colocamos aquí este numerito
;---------------------------
----------mov ecx,555360 ;esta es la línea modificada dentro del códifo, cambiada por: mov ecx,[ebp-1c]
----------mov edx,[ebp-18] ;todo lo que sigue no ha sido modificado
----------push 00414ec8
----------push 00414e9c
----------push edx
----------call RTCSAVESETTING

Y se acabó lo que se daba. Ahora, con todos estos cambios, si le metemos cualquier tontería, genera internamente la clave correcta (hace la comparación), la pezcamos, la guardamos en un sitio seguro y más tarde la pasamos como parámetro en la función que escribe en el registro, y el solito nos registra el programa.

NOTAS FINALES

Sólo quería comentar una cosa, y es que seguramente todo esto puede parecer algo engorroso para crackear el programa ¿verdad?, pero para mi es bastante más divertido, y a la vez educativo, que un simple cambio de salto. El hecho de conseguir comprender el código es lo que me hace seguir en este mundillo tan apasionante, por eso no lo dejo en un simple saltito. En mi opinión, siempre hay que buscar la manera de crackear un programa, no de la forma más complicada posible como podría parecer este caso, sino de aquella de la que puedas aprender más.

Por último, quiero dedicar este Tutorial a un amigo, Cesalv, quien de un modo indirecto, me inició en este arte del Cracking, y bueno, tambien a todos mis profesores, y estos son todo aquél que escribe tutos para las páginas de KFOR y Karpoff incluidos ellos mismos, por supuesto.

CORREO DEL MENDA: auspex@wanadoo.es

 

Karpoff Spanish Tutor: Pagina dedicada a la divulgacion de informacion en Castellano, sobre Ingenieria Inversa y Programacion. Email "Colabora con tus Proyectos"
www.000webhost.com