Como crackear todos los programas de Visual Basic (un Tutorial) por Razzia traducido por ^[G]oLe[E]^ ** Este Tutorial fue tomado 'prestado' de la página de fravia de Ingenieria Inversa de Código *** Cortesia de la página de Fravia de ingenieria inversa ~ Este Tutorial es EXTREMADAMENTE interesante: mas y mas programas han sido escrito en lenguajes sobreinflados como Visual Basic o Delphy, y como correctamente señala Razzia, esto hace que estos programas sean mas crackeables que las aplicaciones "normales"! Además encuentro sumamente inteligente el estilo de Razzia (los blocks "mas info acerca del programa" deberían ser usados por todos los crackers desde ahora, por ejemplo) y muy bien estructurado. Sigue su consejo y siempre "haz el punto" (considera tu aproximación) *ANTES* de saltar a la sesión de cracking! Otra técnica muy interesante, útil para esquemas de protección que cambian el algoritmo matemático cada vez que son instalados, es el parcheado de los dll de VB por si mismo, para MOSTRARTE (en un mesagebox que llamarás) que password deberías ingresar Disfruta! tutorial de razzia para el crackeo de vb Introduction Ultimamente mas y mas programas salen que son probramados en VB. Puesto que los programas en VB son material desconocido para la mayoria de los crackers, los ignoran y los tachan de 'incrackeables'. En este documento te mostraré que esto no es cierto por su protección basada en texto (serials/reg#'s). Como herramientas solo necesitaremos SoftICE y Hiew en un caso. Además, asumo que el lector está familiarizado con el cracking. Para principiantes, recomiendo los grandes tutoriales hechos por +orc y ed!son sobre crackeo en windows. Pero tratare de hacer el mejor esfuerzo para hacer este texto entendible para todos los que tienen un minimo conocimiento sobre cracking. Preparandonos Antes de empezar a bombardearte con listados en asm, tomemos un momento para pensar acerca de con que estamos tratando. Estamos tratando con exe's que no tiene código por si mismos, pero que en lugar, hacen llamadas a librerias con funciones standard. Qué significa esto? esto significa que hay una gran desventaja para proteger programas escritos en VB. Por qué? piensas que los escritores de dll de VB hacen 10 funciones diferentes que podrías usar para comparar 2 cadenas? No, por supuesto que no. Ellos hacen la dll para ser tan eficiente como sea posible y pequeña como sea posible. Por consiguiente una buena suposición es que solo habrá 1 (o 2) lugar(es) dentro de la dll donde las 2 cadenas pueden ser comparadas. Y este es el caso, como verás si terminas de leer este documento. Ya empezó a brillar la pequeña lampara en tu cabeza? ;--) No sería grandioso si supieramos en que parte de la dll, son comparadas 2 cadneas? Sí, sería grandioso. Esto reduciría el crackeo de VB a un aburrido trabajo de fijar un simple breakpoint en el lugar indicado. Continua leyendo para mas detalles. Estrategia Antes de continar, sería sabio fijar una estrategia (como deberias hacer siempre con todos los otros casos de cracking). Pensemos acerca de la protección ... Ingresas una cadena de texto, presionas enter u 'OK' o lo que sea. Luego windows pasa los dsatos ingresados en la dll VB. La dll VB hace lo que necesita para saber si los datos ingresados son correctos o incorrectos. Y obtienes un mensage, diciendote que ingresaste un buen/mal código. Así que donde estaría el eslabón débil en la cadena? la respuesta es donde windows pasa los datos que ingresaste a la dll VB. Ese es nuestro punto de entrada. Podemos hacer que SoftICE interrumpa aquí. Y entonces estaremos en la fuente de la cadena de protección. Con la ayuda de breakpoints podemos monitorear que pasa con nuestro texto. Pienso que ahora tenemos suficiente información de fondo para crackear un primer ejemplo. Case 1 : The Collector v2.1 The collector es una utilidad para crear y mantener tu colección de imagenes/fotos. No está mal para ser un programa VB. Mas info sobre el programa: Nombre : The Collector v2.1 Donde : http://intranet.ca/~logic/collectr.html Tamaño : collectr.exe = 246.047 bytes Protección : serial DLL : usa un dll VB3 <************** VB3.DLL Encuentro fácil explicar las cosas por pasos. Por lo tanto, dividiré el proceso de crackeo en pequeños pasos : Paso 1 : Ejecuta The Collector justo al inicio te pedirá el serial Paso 2: Ingresa un serial tonto como '9876543210'. Ahora presiona control-d para entrar a SoftICE. En SoftICE escribe 'bpx hmemcpy' para colocar un breakpoint en la función hmemcpy del kernel. (Intermezzo : Qué es hmemcpy? Windows usa mucho hmemcpy en operaciones concernientes a cadenzas. En este caso, será usado para copiar el buffer con el texto que ingresamos al espacio de memoria de la dll CV. Recuerdas cuando dije que ibamos a interrumpir cuando windows pasara nuestra cadena a la dll VB?) Paso 3 : Deja SoftICE con control-d. Y presiona 'OK". Esto hará que SoftICE interrumpa justo en el inicio de hmemcpy. Paso 4 : Ahora continuaremos rastreando mas en la memoria de la función hmemcpy para encontrar donde será almacenada la cadena que ingresamos. Mantente presionando F10 hasta que veas ::Memory_copying_snippet JMP 9E9F USH ECX CX,02 REPZ MOVSD POP ECX ND ECX,03 REPZ MOVSB XOR DX,DX ;Estas líneas copian el SHR ;cadenas en ds:si a es:di ;el REPZ MOVSD! ;el REPZ MOVSB! Paso 5: Justo antes de REPZ MOVSD has un 'ed si'. Verás el texto que ingresaste, en mi caso, muestra '0987654321'. Has un 'ed es:di' y no versa nada (aún). Pero si presionas F10 y pasas el REPZ MOVSB versa el texto siendo copiado a su nueva localidad, donde el dll VB puede accesarlo. Paso 6: ahora sabemos donde está localizado el texto. Revisemos nuestra estrategia aquí. Nuestro plan fue encontrar donde la dll VB mantuvo nuestro serial, entonces pon un breakpoint en esa localidad de memoria y encuentra con que es comparado. Así que fijemos un bpr (breakpoint en rango) en la localidad donde vive nuestra cadena. Ya que las instrucciones REPZ MOVS(D/B) incrementaron el puntero en di (ahora apunta al final de nuestra cadena) hacemos un 'bpr es:di-8 es:di-1 rw'. No presiones enter, lee el paso 7 antes. Paso 7: Antes de tocar enter, te dire que debes esperar. SoftICE romperá todo lugar donde el bloque de memoria con la cadena es leído o escrito. Por ejemplo romperas dentro de la función strlen donde la longitud de la cadena es calculada. Y romperas donde la cadena es copiada a otro lugar en memoria (por ejemplo con REPZ MOVSW). Cuando esto pasa, fija un nuevo bpr en la nueva localidad con la cadena. Tambien interrumpirá cuando la cadena o parte de ella es borrada. Si la cadena completa no es borrada completamente, no remuevas el bpr correspondiente. Solo remuévelo cuando la cadena completa sea escrita sobre algo mas. También romperás de Nuevo en hmemcpy. Hmemcpy leerá otro eco de la cadena en la memoria de la dll. Coloca un bpr allí también. Y finalmente romperás en la parte del código que hace la comparación (la instrucción que verás es REPZ CMPSB). Cuando alcancé esa parte de código, tuve 4 breakpoints fijados. Un breakpoint para hmemcpy y 3 bpr's en 3 ecos de la cadena (o partes de ella). Paso 8: Ahora hemos encontrado el código donde la dll VB3 hace la comparación, ahora podemso poner un breakpoint allí y desactivar los otros breakpoints. No los necesitaremos mas. HEMOS ENCONTRADO el lugar donde las cosas son comparadas en VB3. Lo que ves es esto: :The_VB3_compare_snippet : : 8BCA : F3A6 es:di : 7401 : 9F : 92 : 8D5E08 : E80E06 mov cx, dx repz cmpsb ;<- aquí las cadenas en ds:si y je 8CB6 ; son comparadas lahf xchg ax,dx lea bx, [bp+08] call 92CB Justo antes del REPZ CMPSB si haces un 'ed si' y un 'ed es:di', verás con que es comparado. En este caso, el segundo y tercer carácter de la cadena que ingresamos son comparados con 'V8'. Así que si reinicias el programa e ingresas 0V87654321 se registrará. Paso 9: aún no hemos terminado. Todo lo contrario! De verdad, la parte importante es lo que hacemos ahora. La proxima vez que conozcamos un programa en VB3 (y conoceremos muchos de ellos :) queremos colocar un breakpoint en la localidad con el código arriba y leemos el serial correcto. Como lo hacemos? Tratémoslo rápido con nuestro objetivo: The Collector. Inicia The Collector e ingresa un serial tonto. Entra a SoftICE y coloca un breakpoint en hmemcpy. Deja SoftIce y presiona 'OK', esto te regresará a SoftICE. Ahora, sal del kernel y entra al código de VBRUN300 (presiona F11 y F10 hasta que llegues allí) Ahora has una busqueda del partron: 8B,CA,F3,A6,74,01,9f,92,8D,5E,08,E8,0E,06 este es el "mov cx, dx" y el resto que hemos visto arriba, busca: s 0 l ffffffffff 8B,CA,F3,A6,74,01,9f,92,8D,5E,08,E8,0E,06 coloca un breakpoint en la dirección que es retornada (bpx <seg:offset>) -presiona F5 y aterrizaras en la mitad del código de comparación de arriba -solo queda algo por hacer y es chequear los punteros en es:di y ds:si Caso 2 : Minimize Magic 1.2.4 Minimize Magic es una utilidad que puedes usar para minimizar tus programas en la barra de tareas. Mas del programa: Nombre : Minimize Magic 1.2.4 Donde : http://www.genesoft.demon.co.uk/ Tamaño : minimagic.exe = 159.744 bytes Protección : password basado en una llave DLL : usa VB4 dll <************** VB4.DLL Para crackear este programa puedes proceder en la misma forma que usamos con The Collector. Comenzando con hmemcpy, trabajando a tu manera al código que compara las cadenas que ingresaste. Algo importante es saber que el dll VB4 siempre convierte las cadenas al formato WideChar antes de hacer algo con ellas. Así que en lugar de usar hmemcpy puedes fijar un breakpoint en MultiByteToWideChar para romper. Chequea tu referencia a las API’s de windows para aprender mas acerca de esta función. He hecho la parte dura del trabajo por ti y encontre el código de la dll VB4 que compara las 2 cadenas (en formato WideChar!). Aquí está el listado: : : : : : : : : : : : : : 56 57 8B7C2410 8B74240C 8B4C2414 33C0 F366A7 7405 1BC0 83D8FF 5F 5E C20C00 push esi push edi mov edi, [esp + 10] mov esi, [esp + 0C] mov ecx, [esp + 14] xor eax, eax repz cmpsw ;<aquí las cadenas en ds:esi je 0F79B362 ; y es:edi son comparadas sbb eax, eax sbb eax, FFFFFFFF pop edi pop esi ret 000C Ahora sabemos lo suficiente sobre la dll VB4, crackiemos Minimize Magic: Paso 1: inicia Minimize Magic y escoge registrar desde los menus. Te preguntará tu Nombre y un Password. Ingresa un nombre y password tonto. No presiones 'OK' aún, continua con el siguiente paso. Paso 2: entra a SoftICE y coloca un breakpoint en hmemcpy. Sal de softice y presiona 'OK'. Aterrizaras en SoftICE. Paso 3: Presiona F11 y F10 hasta que estes fuera del kernel y en el código de VB40032.dll. Ahora buscaremos el patron del código de arriba. Has 's 0 l fffffffff 56,57,8b,7c,24,10,8b,74,24,0c,8b,4c,24,14' y coloca un breakpoint en la dirección que es retornada. Paso 4: Presiona F5 para salir de SoftICE... romperas intermediamente de Nuevo en el objetivo, justo al inicio del código de arriba. Aquí el pass que ingresaste sera comparado con el pass correcto. Rastrea hasta justo antes de REPZ CMPSW y has un 'ed es:edi', esto mostrará el pass que ingresaste. Si haces 'ed esi' versa el pass correcto. (esta cadena sera en formato WideChar por ejemplo podrías ver A T G H D E H D. Esto significa que tu pass es ATGHDEHD) Okas, ahora encontramos un pass functional que trabajará solo para la versión instalada en tu compu. Si le das el pass a alguien mas, el programa no lo aceptará. El pass es calculado desde una llave (key) que es diferente en cada compu. Esta Key puede ser generada aleatoriamente en el setup o basado en la info de tu hd, o en la fecha, el tiempo o en algo. Cualquiera que sea, podría ser difícil de encontrar como es generado o donde es almacenado. Así que, como podemos hacer un crack general? Podríamos usar el truco 'Magic Window' aquí. 'Reprogramaremos' el VB40032.dll para mostrar el pass correcto. El código original en el VB40032.dll se ve como esto: :0F79B348 56 :0F79B349 57 :0F79B34A 8B7C2410 ingresaste :0F79B34E > pass correcto :0F79B352 8B4C2414 :0F79B356 33C0 :0F79B358 F366A7 :0F79B35B 7405 :0F79B35D 1BC0 :0F79B35F 83D8FF :0F79B362 5F :0F79B363 5E :0F79B364 C20C00 función :0F79B367 57 esta dirección :0F79B368 8B7C2408 pero :0F79B36C 8B4C2410 este espacio :0F79B370 8B44240C :0F79B374 0BE4 :0F79B376 F266AF :0F79B379 B800000000 :0F79B37E 7503 :0F79B380 8D47FE :0F79B383 5F :0F79B384 C20C00 push esi push edi mov edi, [esp + 10] ; es:edi> pass que 8B74240C mov esi, [esp + 0C] ; esi mov ecx, [esp + 14] xor eax, eax repz cmpsw ; los compara je 0F79B362 sbb eax, eax sbb eax, FFFFFFFF pop edi pop esi ret 000C ; final de esta push edi ; el código abajo de mov edi, [esp + 08] ;no es importante, mov ecx, [esp + 10] ;necesitaremos mov eax, [esp + 0C] or esp, esp repnz scasw mov eax, 00000000 jne 0F79B383 lea eax, [edi-02] pop edi ret 000C El código está localizado en el offset 7a748 en el archivo vb40032.dll. Así, para hacer que un crack general haga un parche que cambie el código de arriba: :0F79B348 56 :0F79B349 57 :0F79B34a 8B7C2410 que ingresate :0F79B34E 8B74240C correcto :0F79B352 813F70006300 'PC" ? :0F79B358 7527 push esi push edi mov edi, [esp + 10];es:edi -->texto mov esi, [esp + 0C] ;esi --> pass cmp dword ptr [edi], 00630070;edi -> jne 0F79B381 ;si no - salir :0F79B35A 803E00 líneas :0F79B35D 7410 espacios :0F79B35F 83C601 caracteres :0F79B362 C60620 :0F79B365 EB03 el ret :0F79B367 C20C00 :0F79B36A 83C601 :0F79B36D EBEB inicio :0F79B36F 8B3DDCC47B0F lineas :0F79B375 8B74240C función :0F79B379 6A00 :0F79B37B 56 :0F79B37C 56 :0F79B37D 6A00 :0F79B37F FFD7 :0F79B381 5F :0F79B382 5E :0F79B383 90 :0F79B384 C20C00 cmp byte ptr [esi], 00 |<- estas je 0F79B36F | ponen add esi, 00000001 | entre mov byte ptr [esi], 20 jmp 0F79B36A | |<--saltar ret 000C ;<-- esto previene un crash add esi, 00000001 | jmp 0F79B35A |<- al mov edi, [0F7BC4DC] *<-- estas mov esi, [esp + 0C] * llaman a la push 00000000 * MessageBoxA push esi * para mostrar push esi * el pass correcto push 00000000 * call edi * pop edi pop esi nop ret 000C Comentarios: usamos el espacio de 2 rutinas, para prevenir un crash tenemos que poner una función RET en el inicio de la segunda función (original) (ver línea 0F79B367). Esta parte del código de dll VB4 no es usada para chequear los passwords. Es usada por otras partes del programa. Por lo tanto, necesitamos hacer algo para que solo algo pueda ser mostrado cuando estamos tratando con una comparación de passwords. Esto es lo que el código en la línea 0F79B352 trata. Chequea para ver si EDI apunta al siguiente texto "PC". Así podemos usar esto para activar el crack. Para activar el crack, "PC" tiene que ser ingresado en la cadena por pass cuando te registras. Las líneas marcadas con | están allí para poner espacios entre caracteres de la cadena. Originalmente allí estaría una cadena en formato WideChar. Esto significa que en memoria habrán ceros entre los caracteres. Pero la función que hemos usado para mostrarnos el texto (MessageBoxA) convierte los 0 al final de la cadena. Así que obtendríamos solo 1 letra si no hiciéramos el reemplazo de los ceros con espacios. Las líneas marcadas con * están allí para llama a la función MessageBoxA para mostrar el pass correcto. Rasgué esos commandos del dll VB4. coloqué un breakpoint en MessageBoxA para ver como VB4 lo llamaba. Bien, esto es para Minimize Magic. Para hacer un crack general, un parche podría ser escrito para parchear el dll VB4 en offset 7a748 con el código de arriba. Para usarlo, minimagic.exe y vb40032.dll deberían estar en un directorio temporal y el parche ejecutarse allí. Luego iniciar minimize.exe desde ese directorio temporal y usar 'PC' por pass. Y voila, una ventana aparecerá con el pass correcto. Una vez el pass correcto es conocido, los archivos temporales serían borrados y el pass puede ser usado en el Minimize Magic original. Caso 3 : Sub Station Alpha 2.02 La mayoria de los programas VB4 pueden ser crackeados con el método descrito en el caso 2, pero he encontrado 2 programas que usan un método distinto de comparación. Uno de estos programas es Sub Station Alpha 2.02. Usa una protección que primero convierte un numero que ingresaste a su valor hex y luego lo compara con el numero correcto. Comencemos a crackear Sub Station Alpha ahora: las cosas se aclararán. Info acerca del programa: Nombre : Sub Station Alpha 2.02 Donde : http://www.eswat.demon.co.uk/index.html Tamaño : 629.248 bytes Protección : password basado en un user name DLL : Usa VB4 dll Primeramente mencioné que VB4 convierte cadenas al formato widechar antes de hacer algo con ellos. Por lo tanto usaremos esta función como punto de entrada. De nuevo lo haremos paso a paso ;--) Paso 1: inicia Sub Station Alpha y escoge register desde los menus. Ingres un nombre y un key de registro tonto. Paso 2: entra a SoftICE y coloca un breakpoint en MultiByteToWideChar (con el commando 'bpx multibytetowidechar') Paso 3: ahora, sal de SoftICE y presiona "Register". Paso 4: Softice interrumpirá en el inicio de MultiByteToWideChar, presiona F11 para salir. Verás: :FF1500C27B0F :8BD8 :83FEFF :7501 :4B :53 :6A00 :FF1518C97B0F :8BE8 :85ED :0F845B260100 :43 :53 :55 :56 :57 :6A00 :6A00 call [KERNEL32!MultiByteToWideChar] mov ebx, eax cmp esi, FFFFFFFF jne 0F738BCF dec ebx push ebx push 00 call dword ptr [0F7BC918] mov ebp, eax test ebp, ebp jz 0F74B23D inc ebx push ebx push ebp push esi push edi push 00 push 00 :FF1500C27B0F :8BC5 :5D :5F :5E call [KERNEL32!MultiByteToWideChar] mov eax, ebp ;<-- has 'ed ebp' aquí pop ebp pop edi pop esi El lugar importante está justo despues de la segunda llamada a MultiByteToWideChar. Desactiva el primer bp en MultiByteToWideChar y coloca un Nuevo bp despues de la segunda llamada a la función (en la línea con MOV EAX,EBP). En la línea EBP contendrá un puntero a una cadena en formato WideChar que fue procesado. No tiene que ser la cadena de la llave de registro. Por lo tanto, editaremos ese breakpoint para que trabaje solo interrumpiendo cuando este procesando la llave de registro. Como podemos hacerlo? Bien, la función MultiByteToWideChar retorna la longitud de la cadena que procesa mas 1 en EAX. Así agregaremos una declaración condicional en el breakpoint. Has 'bl' para encontrar que es el numero en ese breakpoint. Entonces has un 'bpe #' y agrega 'if al="=<lengthOfKeyString+1">' al breakpoint. Por ejemplo, si ingresas '212121', lenghtOfKeyString sería 6 :--). Paso 5: Ahora dejaremos corer el programa con F5. cuando SoftIce rompa has un 'ed edp' y ve la forma WideChar de la llave que encontraste. Colocamos un bpr en el bloque de memoria conteniendo la cadena y continuamos (F5). Lo que pasará es esto. Softice romperá en varios lugares. Lo que es importante es que rompera en el código de OLEAUT32. cuando esto pase, rastrea un poco mas para ver que está pasando. Las primeras veces saldrás de OLEAUT32 muy rápido. Pero eventualmente verás este código: ( listado de OLEAUT32.DLL) :6534B6B3 395C240C cmp [esp + 0C], ebx ; este es un loop que :6534B6B7 7E14 jle 6534B6CD ; va a través de :6534B6B9 33C9 xor ecx, ecx ; los caracteres de una :6534B6BB 8D0492 lea eax, [edx + 4*edx] ; cadena, en el final :6534B6BE 8A0E mov cl , [esi] ; edx tendrá el valor :6534B6C0 46 inc esi ; hex de la cadena :6534B6C1 4F dec edi :6534B6C2 FF4C240C dec [esp + 0C] :6534B6C6 8D1441 lea edx, [ecx + 2*eax] :6534B6C9 85FF test edi, edi :6534B6CB 7FE6 jg 6534B6B3 :6534B6CD 85FF test edi, edi :6534B6CF 7F4A jg 6534B71B ............. ............. :6534B6F2 8910 mov [eax], edx ; edx es guardado :6534B6F4 33C0 xor eax, eax :6534B6F6 83C424 :6534B6F9 C21000 add esp, 00000024 ret 0010 Paso 6: vimos que la llave es transformada en su valor hex y guardada en un lugar en memoria. Si monitoreas esta localidad de memoria, terminarás en el dll VB4 que la compara con otro valor: :0F7A2CE1 :0F7A2CE2 :0F7A2CE3 :0F7A2CE5 :0F7A2CE8 :0F7A2CEA :0F7A2CEB :0F7A2CEE :0F7A2CF1 :0F7A2CF8 5A 58 2BC2 83F801 1BC0 50 0FB706 83C602 FF2445F4997B0F E8BB000000 pop edx ; carga edx pop eax ; carga eax sub eax, edx ; los resta cmp eax, 00000001 sbb eax, eax push eax movzx word ptr eax, [esi] add esi, 00000002 jmp dword ptr [2*eax + 0F7B99F4] call 0F7A2DB8 Vemos que EDX y EAX son cargados desde la pila y luego son restados. Esto es una forma indirecta de comparar los 2 valores. Si revisas el contenido de EAX y EDX, versa que uno tiene el numero que ingresaste y el otro tendrá el numero de registro correcto. Paso 7: ahora encontramos esta localidad, es sabio notar los valores hex del código, para que puedas encontrarlos rápido cuando sospeches que otro programa VB4 usa esta protección. Notas Finales Bien, con las 3 técnicas de arriba he sido capaz de realmente crackear algunos programas VB3/4 que usan la protección basada en texto. Algunas veces cuando fijas un breakpoint en la rutina de comparación, SICE no interrumpira. Trata entonces de ingresar una cadena con una longitud diferente. Porque el programa podría ser chequeado por la longitud de la cadena que ingresas y entonces comparar los caracteres aislados, pero de nuevo ser comparados en las localidades declaradas en los ejemplos de arriba. Con programas VB5 no tengo mucha experiencia, solo he crackeado uno. Es el Hitlist Pro v3.0. Parcheando el dll VB5, pude remover su limitación de 30 días justo como un programa regular. Por supuesto, el dll VB5 tenia que ser colocado en el directorio principal de Hitlist Pro, esto para prevenir que otros programas VB5 usaran el DLL parcheado. Eso es todo amigos, pueden contactarme (si saben como ;--) en irc con retroalimentación y preguntas.