La envoltura HASP y Técnicas para desproteger la mochila HASP

Objetivo :- Trace.exe (incluído en Cimagrafi v5.07+).
La técnica DLL.

Si ya conoces las protecciones HASP sabrás que esta protección se presenta de dos formas, la API a través de la cual los servicios hasp() son activados y el encriptador de ejecutables PE conocido como la envoltura (envelope) el cual depende de las respuestas que le envía la mochila para realizar la descriptación. He elegido Trace.exe por dos razones, primero, es un objetivo 'envuelto' tan bueno como cualquier otro, y en segundo lugar estamos aquí para aprender sobre ingeniería inversa, al contrario que a robar Cimagrafi (un program de diseño bastante bueno según mi humilde opinión, protegido tristemente por una HASP). El envoltorio de la HASP comprueba la prensecia de SoftICE utilizando un truco muy común, CreateFileA buscando el controlador de video //./SIWVID, sin embargo, antes de empezar a explorar en inmensas cantidades de codigo recomiendo que utilices PEDump sobre el objetivo simplemente para hacerte una idea sobre a que te enfrentas.

Fíjate en _TEXT_HA que es la sección de la API HASP, que veremos más adelante, y .protect, la envoltura, en algunas ocasiones estas secciones tienen otros nombres (p.e. .protectzz) no obstante la envoltura Win32 siempre tiene un tamaño aproximado de de 160k. Como puedes prever la envoltura está fuertemente encriptada (desensamblarla te da 300h de la ronda inicial de descriptación que funciona con el método de deslizar una llave XOR sobre muchos pequeños trozos de código y luego llamando a las nuevas rutinas descriptadas, como puedes imaginar, estudiar esto no es para personas con problemas de corazón.

La descriptación es bastante complicada y no hay nada realmente interesante en su estudio, de hecho, al trazarlo a demasiado bajo nivel con SoftICE provoca un horrible cuelge (creo que esto está relacionado con SEH). Lo que la envoltura hace posteriormente es llamar su propia rutina hasp() descriptada para comprobar la existencia de una determinada mochila antes de usar los códigos de respuesta para descriptar y devolver el control al programa original. El primer paso es eliminar la rutina anti-SoftICE descrita arriba, después de lo cual deberíamos hacer un bpx a FreeEnvironmentStringsA que es llamdo en la mayoría de las protecciónes HASP de 32 bits inmediatamente después de la llamada a la rutina principal hasp(). Así aparece :-

:00546AC5 CALL [EBP+00] <-- Esto es hasp().
:00546AC8 PUSHAD <-- Salva todos los registros.
:00546AC9 LEA ESI,[0054A395]
:00546ACF PUSH DWORD PTR [ESI]
:00546AD1 LEA ESI,[KERNEL32!FreeEnvironmentStringsA]
:00546AD7 CALL [ESI]
:00546AD9 ESI,[KERNEL32!FreeEnvironmentStringsA]
:00546AD7 CALL [ESI]
:00546AD9 POPAD <-- Restablece los registros (aquí paras tú).
:00546ADA RET

:005449C4 PUSH EBP <-- Coloca un bpx aquí.
:005449C5 CALL 0054691F <-- hasp() de alto nivel.
:005449CA POP EBP

Cuando vuelves de la rutina, la rutina de la cobertura hasp() acaba de ser ejecutada por primera vez, la cual es siempre IsHasp(), así que pon EAX=1 y un bpx para el siguiente servicio. Con seguridad el siguiente servicio es 2 (en BH), ECX contiene el valor de la contraseña 1 del fabricante, EDX la contraseña 2 del fabricante y EAX el código de la semilla. En este caso tenemos EAX=512, ECX=2459 & EDX=2CFX, después de la llamada a hasp() de nuevo de EAX a EDX = 0, deberían contener los codigos de respuesta requeridos para la semilla dada. En todos las coberturas Win32 que he visto, ha sido posible recuperar estas respuestas siguiendo la ejecución del código (no es que realmente lo necesitemos).

Utilizando el algoritmo HaspCode podemos encontrar las respuestas deseadas, así que parchea en EB0E, 6D3B, 19FA & BF33, ahora F5 y encontrarás la comprobación repetida, parchea en las respuestas de nuevo. La tercera comprobación disminuye el valor de la semilla en 1 así que necesitarás parchear en 904C, 5CD5, DAEE & 30BE (devuelve como semilla 512C, estas respuestas no pueden recuperarse sin conocer el algoritmo HaspCode(). Son estos valores los que usaremos para la descriptación después de la función hash, claro :-). Recomiendo que deshabilites todos los breakpoints y bpx en VirtualAlloc, en otras versiones de la cobertura WriteProcess Memory también se usa extensamente. Después de estos breakpoints, coloca la ventana de datos en la RVA de la primera sección (normalmente en 401000) y mira con atención, hay probablemente dos técnicas rápidas para encontrar el punto de entrada original.

Una de las mejoras formas es usar combinaciones de bpx's en VirtualAlloc/WriteProcessMemory y GetProcAddress, y luego probar y seguir el código intuitivamente, otra forma (quizás más sencilla), sea hacer un map32 y obtener el rango de direcciones de la primera sección, luego poner un bpr para toda el rango de la sección, con lo cual acabarás aquí en el trascurso de algunos 'fixups' o en OEP :-). En el caso de Trace.exe, dos breakpoints en VirtualAlloc y el bpr que he descrito arriba te permitirán encontrar el O.E.P (RVA 0xAF790), tan pronto en cuanto llegues aquí, copia el contenido de todas las secciones, puede que incluso tu puedas usar ProcDump Bhrama, IceDump o TRW para obtener un PE válido :-).

Aquí tienes los detalles si eliges hacer esto a mano :-<

Sección     RVA     Tamaño   Localización    Tamaño en bytes
----------------------------------------------------------
.text     x401000   xAE9E4       x1000          715,236
.data     x4B0000   x112AC      xAEE00           70,316
.reloc    x4CA000    xB6FC      xC2A00           46,844

Ahora puedes pegar estas secciones de código sobre los bytes originales, pero se muy muy cuidadoso a la hora de convertir la RVA en la dirección correspondiente en el fichero (esta parte la he hecho yo por tí), fíjate también en que .rsrc no está encriptada en este ejemplo por la cobertura HASP. Si estás realizando esta parte con UltraEdit, te recomiendo que lo hagas sin prisas para evitar errores, también date cuenta de que puedes destruir la sección .protect puesto que ya no la vamos a necesitar más.

Corrección el PE

Esta será la etapa más importante antes de que podamos ejecutar el fichero reconstruido. En el desplazamiento 0x128 necesitamos actualizar nuestro punto de entrada (0xAF790 como identificamos antes) Después necesitamos corregir la RVA de importación y su tamaño (redondea el tamaño con el alineamiento del fichero), ésto, de nuevo, es fácil de encontrar (coloca un breakpoint a GetProcAddress y un bpr a cualquier lugar de la sección de .idata) aquí está el código :-

:bpr 004c5000 004c5000+250c rw
Break debido a BPR #0167:004C5000 #0167:004C750C RW

:0053C800 MOV EAX,[EBP-0C] <-- VA de la tabla de importaciones (4C5000).
:0053C803 CMP DWORD PTR [EAX+0C],00
:0053C807 JZ 0053C860

Finalmente corrige las entradas del tamaño de la BASELOC y en el directorio de datos, 0xCA000 (RVD de .reloc) y B800 (tamaño) en este caso. ¿He mencionado que puedes borrar la sección .protect de la cabecera PE y actualizar el número de secciones?. Ahora, por supuesto, puedes desproteger la mochila HASP de Cimagrafi en la forma usual :-).

Técnica DLL de desprotección de la mochila HASP

¿Debería señalar que yo no soy el pionero en el uso de esta técnica y que sólo mejor en el caso que haya muchos ficheros protegidos con HASP y quieres bpx sólo un lugar para examinar todos las comprobaciones, también es una técnica que puede llevarse a cabo con movimientos de dedo en tu editor hexadecimal. Se incluye ahora en el archivo HASP (prueba en la página herramientas) Te he dejado un hasp.dll (esta es en realidad una dll HASP para desarrolladores que ha sido editada un tanto para nuestros propósitos). Por favor, ten cuidado ya que esta dll no funciona siempre y cuando no lo hace tu sistema será probablemente destruido .... ciertamente no funciona tal cual con Cimagrafi, la pila necesita ser corregida). No voy a extenderme más en como ésta funciona (la he probado sólo con MAYA Fusion v2.51b), los seguidores de la HASP se figurarán el resto por sí solos :-

1. Localiza la marca HASP 'cmp bh, 32' en tu objetivo.

2. Sigue el código por debajo de la siguiente CALL. Cambia las cuatro lineas PUSHAD en la llamada (p.e. la segunda instancia) en un NOP y anota la dirección a la que apunta ESI también (dos líneas por encima).

3. Cambia el CALL GetModuleHandleA (alrededor de diez líneas más abajo) a CALL LoadLIbraryA.

4. Localiza el siguiente CALL que llame a GetModuleHandleA y sigue el código que hay por debajo. El primer CALL GetProcAddress debería salvar EAX a la ubicación de ESI que anotaste en el punto 2. Cambia la línea inmediatamente después para que apunte a ESI en esta dirección.

5. Localiza la cadena 'KERNEL32.DLL' y sustitúyela con el nombre de tu nueva dll, Asegúrate de cambiar sólo la refencia HASP (busca nombres HASP próximos como HASPUT16.DLL).

6. Carga tu programa, bpx la referencia 'cmp bh, 32', ejecuta paso a paso el programa y haz tus propias averiguaciones, edita la dll según lo que necesites.


Mochilas greenball.gif (835 bytes) Menú principal


© 1998, 1999, 2000 CrackZ. Updated 24th April 2000.
www.000webhost.com