Cimatron v10.6 - Tutorial por CrackZ

http://www.cimatron.com - Pagina Web.
Obtenga el release de RiSE del 26/11/99.
Emulador HASP de UCL incluyendo los codigos fuente.

Este tutorial marca el fin de mi actual serie sobre HASP y no esta recomendado para principiantes, tal como lo he discutido en muchos "reversings" bastante pesados. Un mensaje a los diseñadores de Cimatron si por casualidad leyeran esto, como se que lo hacen:-), esta sera la ultima version de sus productos que mostrare como crackear, no obstante dudo que puedan ustedes dormir facilmente sin embargo, como que inevitablemente algun otro esta preparado para tomar mi lugar y distribuir su bastante buen software libremente.

Hemos visto en tutoriales HASP anteriores como localizar facilmente la rutina principal HASP, El proceso de crackear la mayoria de estos era bastante simple, use su editor HEX para localizar la cadena HASPDOSDRV y cambie el proximo E9 (JMP) por E8 (CALL), luego emparche el punto de entrada a esto, varios F8's debajo de CALL [EBP+00] como ocurre muy cerca despues de una llamada CreateFileA a cualquiera de los dispositivos HASP. Obviamente todo lo que sus nuevas rutinas necesitaban era el codigo de servicio apropiado en BH, no describire esto nuevamente, alcance su haspman.pdf y eche una mirada a la seccion sobre ASM. Si usted es serio sobre el crakeo de HASP entoces codificar o convertir el generador HASP de UCL en ASM debe ser una prioridad, si es perezoso envieme un e-mail y yo le enviare un archivo de aproximadamente 600 bytes que utilizo para emular todas las funciones MemoHASP.

Por supuesto HASP no podia hacer esto facil y la version 6 vio la manifestacion de la 'cubierta' (envelope) que es un encriptador de PE que tiene algunos trucos bastante buenos, confiando en el dongle para hacer el desencriptado. Esto usualmente toma la forma de una llamada IsHasp() (service 1), luego HaspCode()(service 2) dos veces, luego decrementan el codigo "seed". Con respuestas conocidas todo lo que se necesitaba era emparchar los codigos requeridos como retorno y volcar el programa desencriptado con su "dumper" favorito (necesariamente recomiendo el IceDump).

La version 7 de la cubierta sin embargo muestra un marcado cambio. Principalmente, HASP comenzo a darse cuenta que ciertos "reversers" rusos estaban ganado dinero vendiendo vxd's HASP que eran activadas usando llaves de registro (vea el link de UCL al comienzo de este ensayo). Yo les mostrare ahora por primera vez como se hace esto. Los drivers HASP para Windows 95/98 consisten en 2 archivos, hasp95.vxd & hasp95dl.vxd, como usted ya podria haber supuesto hasp95.vxd es el driver estatico y hasp95dl.vxd esta dinamicamente cargado (dl). Es en el drive dinamico donde los rusos enfocaron su ataque:-(

Control_0
CMP EAX, 7
JZ loc_C0000000
CMP EAX, 9
JZ loc_C0000002
CMP EAX, 1Eh
JZ loc_C000000D
CMP EAX, 2
JZ loc_C000001A
CMP EAX, 23h <-- W32_DeviceIOControl.
JZ loc_C000009E
CLC <-- Sale del servicio limpiando CF.

El procedimiento Control realmente no es nada mas que un "switch statement", usted probablemente ha visto la misma cosa un millon de veces en C o lenguajes del mismo tipo. Por supuesto, HASP posee buenas vxd con ID de usuario, aprobadas por Microsoft tambien llamadas via DeviceIOControl, la interfase aprobada por Microsoft. Cuando EAX=23 es tiempo para alguna accion. La estructura en ESI es entonces la llave, especificamente el valor de [ESI+0C]. Cuando este es 2 tenemos un servicio de HASP en accion, Cuando [ESI+0C] es -1/0/1/3/4 otros trabajos son realizados, veanlo por si mismos cargando su blanco de HASP, ingresando en SoftICE y tipeando 'vxd hasp95dl' y luego posicionando un bpmb en la direccion del procedimiento de control. Todo lo que los "de-HASPers" hacen es re-escribir esta rutina de "dispatch", haciendo que desencripte los parametros del HASP (que a este nivel es XOR con AAh y ROR 4 veces), accionar el servicio es decir devolver las respuestas que quieren, realizar una VMMCall _RegOpenKey y RegQueryValueEx si fuera necesario y voila, re-encriptar los parametros y salir del servicio. Yo hice exactamente lo mismo usando los drivers v3.81 de HASP en alrededor de una hora y ahora tengo una fina seleccion de software que funciona. Muchos de los tipos rusos tambien guardan varios dongles simulados en hasp95dl.vxd.

HASP por supuesto cayo en la cuenta de esto y primero contra-ataco mediante la emision continua de drivers actualizados, esto por supuesto significo que los "de-HASPers" debian ponerse al dia permanentemente. Realmente esto no podia continuar indefinidamente y la gente de HASP cambio de tacticas y esto marca el punto donde la cubierta v7 despega. Ahora, usted puede comenzar con cualquiera de los programas Cimatron para este tutorial (conseguir el release de RiSE es probablemente la forma de hacerlo), muchos de los programas principales son solamente cargadores para las correspondientes DLL's. Yo elegi chkddf.exe/chkddf.DLL debido a que era comparativamente pequeña para desensamblarla (otros 31 archivos trabajaran exactamente igual que este).

La primera cosa que hice, un bpx en CreateFileA para ese driver, pero sin esperanzas, luego probe muchos otros breakpoints (incluso DeviceIOControl), el unico que pude conseguir que trabajara es MessageBoxA, usted puede rastrearlo ahora, pero dejeme hacer algo antes. Primero ponga un bpmb en el control de procedimientos de hasp95dl.vxd y corra chkddf.exe, no se dispara, por que?, bien la nueva cubierta ahora desencripta la propia rutina real de comunicaciones entonces los emuladores vxd por reemplazos de bajo nivel han terminado.

1C003CFC CALL 1C003C40 <-- Aqui.
1C003D01 TEST EAX, EAX
1C003D03 MOV DWORD PTR [1C0327F8], EAX
1C003D08 JZ 1C003D1F
1C003D1F PUSH 1C030054 <-- "Protection Device Not Found".

CALL 1C003CFC es aqui donde usted llegara con su primer break. Una pequeña intuicion de StringRef quizas :-)

1C003D40 SUB ESP, 100 <--Hace algun espacio en el stack.
1C003D46 PUSH ESI
1C003D47 PUSH EDI
1C003D48 XOR ESI, ESI <-- ESI=0.
1C003D4A CALL 1C008D60 <-- Puede haber mas debajo de esto.
1C003D4F TEST EAX, EAX
1C003D51 JZ 1C003D65
1C003D53 PUSH 1C03007C <-- "Your version of the HASP driver is too old".

Comprenda que nuestro problema era que no pudieramos encontrar donde la cubierta abrio las comunicaciones entre el HASP y el programa, una pequeña intuicion le dice que debe haber sido dentro de CALL 1C008D60 sino como puede determinar que la version es demasiado antigua.

1C008D60 PUSH 1C033DD0
1C008D65 PUSH 1C033DCC
1C008D6A PUSH 1C033DC8
1C008D6F PUSH 1C033DC4 <-- Esto por supuesto debe ser la direccion de retorno para la devolucion de parametros.
1C008D74 PUSH 0
1C008D76 PUSH 0
1C008D78 PUSH 0
1C008D7A PUSH 0
1C008D7C PUSH 1 <-- Servicio.
1C008D7E CALL 1C01E000 <-- Este es el inicio del la seccion .data!.
1C008D83 MOV ECX, DWORD PTR [1C033DCC]
1C008D89 XOR EAX, EAX <-- EAX=0.
1C008D8B ADD ESP, 24 <-- Puliendo el stack.
1C008D8E CMP ECX, FFFFFF99 <-- -103.
1C008D91 SETE AL <-- Flag AL.
1C008D94 RET

¡Ahora estamos llegando a alguna parte, montones de parametros puestos dentro (pushing) de CALL 1C01E000 que realmente es el inicio de la seccion .data! y no desensamblada para nada por W32Dasm. Esto es lo que debe estar pasando. Prepare un breakpoint al registro de debug para esto y veamos como procede el codigo. Bien, yo no voy a decirle todo, pero lo que si le dire en este trazado es como nadar a traves de la masa viscosa, mucho de este codigo es verdaderamente loco:-), en principio usted debe tratar de distinguir entre el ruido y la intencion real del codigo, hay un monton de basura, algo asi como 2 o 3 instrucciones que no hacen nada, considere lo siguiente:-(

:1C01E006 PUSHAD  <-- Salve todos los registros.
:1C01E007 ADD AL,00     <-- Basura.
:1C01E009 XCHG ESI,ESI  <-- Basura.
:1C01E00B MOV AH,AH     <-- Basura.
:1C01E00D CALL 1C0298D2 <-- CALL real.

:1C0298D4 MOV EDX,[ESP]  <-- Real.
:1C0298D7 JA 1C0298D9  <-- Basura.
:1C0298D9 SUB ESP,-04  <-- Preparado para la funcion.
:1C0298DC SHLD EBX,ECX,80  <-- Basura.
:1C0298E0 MOV EBP,ESP  <-- Preparado para la funcion.
:1C0298E2 XCHG BH,BH  <-- Basura.
:1C0298E4 ADD EBP,FFFFFFF4  <-- Prepara EBP.
:1C0298EA LEA EDI,[EDI]  <-- Basura.
:1C0298EC MOV EBX,1F8DFE10  <-- Basura.
:1C0298F1 XCHG BH,BH  <-- Basura.

Por que estoy mostrandole esto?, bien, este nuevo objeto encriptado esta seriamente bien codificado para obscurecer el debugging y hay mucho [there is a lot of leading of the cracker], vi montones de codigo que parecia notablemente familiar en la version 6 de la cubierta solo que no trabajaba como esperaba, e.g. :-(

:0072F067 PUSH 0072B6C6
:0072F06C CALL 00729D68  <-- haspreg().
:0072F071 MOV EDI,[ESP+3C]
:0072F075 MOV [EDI],EAX  <-- Retorna Par1.
:0072F077 MOV EDI,[ESP+40]
:0072F07B MOV [EDI],EBX  <-- Retorna Par2.
:0072F07D MOV EDI,[ESP+44]
:0072F081 MOV [EDI],ECX  <-- Retorna Par3.
:0072F083 MOV EDI,[ESP+48]
:0072F087 MOV [EDI],EDX  <-- Retorna Par4.
:0072F089 ADD ESP,04  <-- Corrige el stack.
:0072F08C POPAD  <-- Restaura los registros.

Dejando estas notas de lado usted por supuesto ya habra comprendido lo obvio. Esto es que simplemente no hay ninguna necesidad de estudiar la desencripcion debido a que nuestros codigos de retorno estan todos del lado de la aplicacion verificada (todos los parametros estan puestos dentro del stack del objeto encriptado listo para ser accionado). Aun veremos luego como esto hubiese causado problemas pero no lo eran para la sobrecarga de proteccion en el DLL principal (cimit.DLL). Todo lo que nosostros necesitamos hacer es insertar nuestra rutina de emulacion en el inicio de la seccion .data y accionar el servicio, nosotros sabemos desde los primeros "snippets" que las direcciones de retorno tambien son colocadas (pushed) en la cubierta :-).

Yo voy a apublicar aqui mi rutina completa de emulacion "tal como esta", esta puede ser pegada con su editor HEXadecimal en los otros 31 archivos protegidos (eventualmente tambien encontrara su camino dentro de cimit.DLL pero no todavia). Por supuesto los astutos entre ustedes habran notado rapidamente un problema. Cuando el servcio 2 es llamado el unico parametro pasado a traves del stack es el codigo "seed" (64) y no los passwords del desarrollo, por consiguiente siendo este un blanco totalmente desconocido podriamos tener un problema, afortunadamente yo supe que para la version 10 eran 2209/713D, de hecho podriamos haberlos descubierto para cimit.DLL tambien como usted a visto. Por lo tanto Cimatron, si usted esta leyendo esto, tome nota de estos 2 errores.

i) usted esta usando el codigo "seed" (64) solo una vez y sus passwords son conocidos.
ii) recuperar sus password hubiese sido tan facil como usando la version 6 de la cubierta para proteger cimit.DLL.

Obviamente podemos emparchar en los codigos de retorno correctos y no esmerarnos realmente.

PUSHAD (60) <-- Salva todos los registros.
CALL $+5 (E8 00 00 00 00) <-- Nuestro emulador.
POP EBP (5D) <-- Obtiene la direccion actual.
XOR EAX, EAX (33 C0) <-- EAX=0.
MOV EAX, [ESP+24] (8B 44 24 24) <-- Servicio.
CMP AX, 1 (66 3D 01 00) <-- Es el IsHasp().
JNE $+8 (75 08)  <-- Chequee el proximo servicio.
MOV EDI, [ESP+38] (8B 7C 24 38) <-- direccion de retorno de Par1.
MOV [EDI], EAX (89 07) <-- HASP encontrado.
POPAD (61) <-- Restaura todos los registros.
RET (C3) <-- // IsHasp().
CMP AX, 2h (66 3D 02 00) <-- Es el HaspCode().
JNE $+2A (75 2A) <-- Chequee el proximo servicio.
MOV AX, 3FA1 (66 B8 A1 3F) <-- Codigo de retorno 1.
MOV EDI, [ESP+38] (8B 7C 24 38)
MOV [EDI], EAX (89 07)
MOV AX, FF26 (66 B8 26 FF) <-- Codigo de retorno 2.
MOV EDI, [ESP+3C] (8B 7C 24 3C)
MOV [EDI], EAX (89 07)
MOV AX, 5EE7 (66 B8 E7 5E) <-- Codigo de retorno 3.
MOV EDI, [ESP+40] (8B 7C 24 40)
MOV [EDI], EAX (89 07)
MOV AX, 4955 (66 B8 55 49) <-- Codigo de retorno 4.
MOV EDI, [ESP+44] (8B 7C 24 44)
MOV [EDI], EAX (89 07)
POPAD (61)
RET (C3) <-- // HaspCode().
CMP AX, 4Bh (66 3D 4B 00)
JNE $+2D (75 2D) <-- Siempre un falso retorno exitoso.
MOV EDI, [ESP+38] (8B 7C 24 38) <-- Obtiene la direccion leida.
MOV EAX, [EDI] (8B 07) <-- En EAX.
LEA EDI, [EBP+68] (8D 7D 68) <-- Inicio de la memoria emulada (16 bytes).
ADD EDI, EAX  (03 F8) <-- Suma la direccion a leer.
MOV AL, BYTE PTR [EDI] (8A 07) <-- Colocado en AL.
MOV EDI, [ESP+3C] (8B 7C 24 3C) <-- Codigo de retorno 2.
MOV [EDI], EAX (89 07)
XOR EAX, EAX (33 C0) <-- EAX=0.
MOV EDI, [ESP+40] (8B 7C 24 40) <-- Codigo de retorno 3.
MOV [EDI], EAX (89 07)
POPAD (61)
RET (C3) // ReadByte().
db 16 (memoria emulada).
XOR EAX, EAX (33 C0) <-- EAX=0.
MOV EDI, [ESP+38] (8B 7C 24 38).
MOV [EDI], EAX (89 07).
MOV EDI, [ESP+3C] (8B 7C 24 3C).
MOV [EDI], EAX (89 07).
MOV EDI, [ESP+40] (8B 7C 24 40).
MOV [EDI], EAX (89 07).
MOV EDI, [ESP+44] (8B 7C 24 44).
MOV [EDI], EAX (89 07).
POPAD (61).
RET (C3).


Note que yo he emulado solo 3 servicios aqui (1,2 & 4B), si usted examina el listado del desemsamblador muy de cerca vera que muchos otros servicios son referenciados (4, 32, 46, 48, 49 & 4A), sin embargo el codigo nunca podra ser alcanzado, por supuesto con un programa como Cimatron y otros 31 DLL's para desproteger usted podria pensar que el tiempo que toma desensamblar cada DLL es inaceptable y entonces emular esos servicios no referenciados tambien. Con el servicio 4B 2 bytes son leidos, direcciones C & D, estos son entonces XORed con 8000h y deben igualar el ID de su dongle i.e. un ID 0614 requiere 8614 => word C = 14 & word D = 86. Dispare su recientemente emparchado chkddf.exe, bien sabe usted, esto funciona :-).

El DLL principal en Cimatron es cimit.DLL, este ejecuta el programa principal y esta protegido para reflejar eso. En vez de simplemente la version 7 de la cubierta, Cimatron ha aplicado la version 6 tambien. En vez de darle con cuchara esta "galleta" (cracker), yo solamente describire como lo hice, la aplicacion le queda a usted. En principio la cubierta v6 tiene que ser localizada, usted puede hacer esto con el usual bpx en FreeEnvironmentStringsA, el programa tambien verifica para el dongle de Cimagrafi's entonces busque esos passwords :-). Yo elegi hacer alguna redirecciones aqui, usted puede encontrar el JMP HASPDOSDRV bastante facilmente y redirigir el JMP a un CALL a su propia rutina - esto significa que usted debe encontrar donde es desencriptado el codigo para ese JMP (facil con bpr).

La cubierta v7 sin embargo es desencriptada por la cubierta v6 lo que significa que usted no puede simplemente pegar su emulador al comienzo de la seccion .data, usted tiene que encontrar donde es desencriptada (bpr nuevamente) - le advierto, esto probara su paciencia como que hay mucho 'copiar a' y 'copiar desde' para lidiar. Yo no pense que fuera practico trabajar todos los bytes desencriptados requeridos para generar mi rutina de emulacion completa (que para cimit.DLL alcanza los 672 bytes), por consiguiente desencripte solamente un "JMP long" a otra rutina que puse en el espacio libre al final de .reloc, recuerde que no tenemos cuidado actualmente si la cubierta v7 es desencriptada como basura, nosotros nunca vamos a llamar alli. En la version distribuida de este crack yo tuve que emular el servicio 3 y realize un trabajo muy torpe modificando las caracteristicas del header PE tambien podria escribir un JMP sobre un JNZ (esteticamente desagradable).

Aquellos de ustedes que usan la opcion RE_ENGE necesitan un numero de registro para poder salvar apropiadamente. Mi buen amigo prs emparcho un DLL para ustedes, yo recorri todavia la milla extra y force 00061E21 como un codigo valido.

Esto es real, no hay cracks terminados hechos para perdedores aqui, vayan y hagan algun trabajo ustedes mismos :-). Si cualquiera de Cimatron tiene bastante inquietud como para enviarme un e-mail entonces, quizas, una conversacion civilizada pueda estar proxima.


  Dongles Return to Main Index


&COPY; 1999 CrackZ. 18th December 1999.

www.000webhost.com