CASMate-Pro v6.52

http://www.scanvec.com/ 20Mb aproximadamente.

Es un programa medianamente establecido el cual no parece tener una protección muy buena, CASMate es un objetivo ideal. Como ahora verás es un programa con una protección bastante buena para practicar, incluye además un ejemplo de legado de protección HASP . Lo primero que debes hacer es arrancar el programa ; P(cas_win.exe),para estos difíciles objetivos no pienses en usar siempre el W32Dasm, arranca el IDA y desensamblalo. Verás rápidamente muchos errores diciendo, "can't disassemble" y "execution flows beyond limits". Además no encontrarás la cadena de error que ves al principio porque ha sido desencriptado en durante la ejecución.

Como Cas_win.exe es de 16-bit utilizaremos Wldr.exe para conseguir algún entry point, comenzaremos a trazar, pero primero una palabras acerca de los breakpoints. CASMate utiliza un código de anti-debugging que detecta los breakpoints del SoftICE (recuerda que esto en realidad cambia el código) y terminarás con GPF(¿?)en algunos sitios, la solución es muy fácil entonces,sólo coloca un 'bpmb dirección x' que es funcionalmente equivalente y descrito ya en otro sitio.

Comenzamos la llamadas del programa AllocCStoDSAlias que usa un selector de segmento de código y regresa al selector segmento de datos que se suele utilizar para ejecutar el código en el segmento de código. El INT 21h/AX=3306h obtiene la version real del sistema operativo, INT 2Fh/AX=1600h es llamado para comprobar si estamos usando el modo mejorado de windows(ah, pero tiene?). Pronto llegamos a la acción:-

3127:065E E8130B CALL 1174 <-- Traza hasta aquí.
3127:0661 E8D81A CALL 213C <-- Desencripta y reencripta.
3127:0664 E8BE00 CALL 0725 <-- ejecuta el código de desencriptación.

Antes de que traces hasta el CALL 213C echa un vistazo a cs:0725, está encriptado ahora y si te entretienes en buscar con el Hiew verás que empieza en el offset 3AB25. Trazamos hasta 213C es dónde la rutina HASP comienza sus trucos, en primer lugar vamos a hacer una preparación antes de llamar la rutina de desencriptación la cual frustra todos los inententos de usar herramientas para crackear.

75B7:208C  83C0BF  ADD AX,-41
75B7:208F  FFE0    JMP AX
75B7:2091  83C33C  ADD BX,3C
75B7:2094  FFE3    JMP BX
75B7:2096  83C10F  ADD CX,0F
75B7:2099  FFE1    JMP CX

Esta magnífica estructura de código tienes 2 propósitos principales, en primer lugar desencripta verdadero código de desencriptación y después inhibe cualquier posibilidad de funcionamiento de los debuggers, por supuesto no necesitas trazarlo, como sabes dónde está escrito el código de desencriptación un Bpr hará el resto :-), si lo trazas con el F10 necesitarás tener a mano una buena bebida y mucha paciencia mientras esperas, en cs:2150 es donde en realidad continúa con la desencriptación.

2AB7:2154 STI <-- Re-activar todas las interrupciones.
2AB7:2181 MOV CX,088A <-- Número de bytes a desencriptar.
2AB7:2184 SUB CX,06 <-- Decrese en 3 words.
2AB7:2187 ADD SI,CX <-- Recupera el final.
2AB7:2189 MOV DI,06D3 <-- Empezamos desde aquí.
2AB7:2193 MOV AX,CS:[DI] <-- obtiene word.
2AB7:2196 ADD AX,BX <-- .....
2AB7:2198 MOV BX,AX <-- .....
2AB7:219A ROR AX,1 <-- .....
2AB7:219C AND AX,8000 <-- Lo desencripta.
2AB7:219F ADD AX,BX <-- .....
2AB7:21A1 ADD AH,AL <-- .....
2AB7:21A3 MOV BX,AX <-- .....
2AB7:21A5 MOV [DI],AX <-- escribe la primera word desencriptada.
2AB7:21A7 ADD [DI+02],BX <-- Escribe la segunda word desencriptada.
2AB7:21AA ADD [DI+04],BX <-- escribe la tercera.
2AB7:21AD ADD DI,06 <-- preparado para la siguiente ronda.
2AB7:21B0 CMP DI,SI <-- Comprueba si se alcanza el final.
2AB7:21B2 JB 2193 <-- Loop de desencriptación.

Éste es el código en el que estamos interesados, porque para crackear el entorno necesitamos los bytes de desencriptación de aquí. Vamos a movernos desde aquí y vamos a observar que necesitamos cambiar.

60C7:072F CMP WORD PTR [C7C3],00 <-- Flag decisiva.
60C7:0734 JNZ 0739 <-- Salta al entorno de hasta luego(¿?).
60C7:0736 CALL 06D3 <-- No llama a esto.
60C7:0739 MOV WORD PTR [C7C3],0001 <-- Mueve la flag conveniente para nosotros.

Obviamente lo que necesitamos es hacer unos cuantos cambios de bytes, parcheando el JNZ 75 03 por JMP EB 03 parece ser que es la opción más fácil, pero lo que nosotros necesitamos para producir esto es desencriptar ésto. Trazando el código después de 5 ó 6 rondas de desencriptación (todas idénticas). Después de que fuerces el entorno de comprobación, coloca un bpm en cs:0725 y observa como el entorno vuelva a encriptar este código.

Parcheando la encriptación

El problema que parece que tenemos aquí es que cambiar un byte afectará a la subsiguiente desencriptación, de hecho esto es sólo cierto en un punto:-

39 74 03 73 9A 8A C7 4A <-- Bytes actuales alimenta dos por el loop de encriptación.
00 75 03 E8 9A FF C7 06 <-- Resultado actual de la desencriptación.
00 EB 03 E8 9A FF C7 06 <-- Resultado deseado.

   ^^    ^^    ^^    ^^

Si tu comienzas trazando la desencriptación léntamente cuando el DI señala cs:0733 podrás ver como se genera el 75, el cuál seguramente te gustaría cambiar a EB :-). Ahora sigamos el código léntamente (durante un buen rato), mira como se utiliza ADD con nuestra corriente de byte para generar las 2 siguientes words y entonces parchear al final para obtener todo de nuevo preparados para la tercera ronda de word, hasta nunca entorno XD.

HASP API

Lo que nos queda ahora de nuevo es la API, supongo que tienes tu viejo haspman.pdf. En la antigua HASP de 16 bytes que hemos visto, PrestoChangoSelector era un buen bpx para localizar el código justo antes del entry point del HASP, CASMate tiene una rápida dirección de las llamadas INT utilizando una antigua alternativa(FreeSelector). Es muy fácil encontrar esta dirección con un edito HEX, sólo localiza 'HASPDOSDRV' y cambia el siguiente JMP E9 a E8 (siempre es un entry point del API).

Primero está (Service 1), no hay problema,parcheamos en AX=1 y seguimos, entonces tenemos 6 posibilidades en el HaspCode (Service 2), hacer creer que CX/DX son los passwords para los dongles específicos.

239F:C863 PUSH DS
239F:C864 PUSH ES
239F:C865 PUSH SI
239F:C866 PUSH DI
239F:C867 PUSH BP <-- Los parámetros deben de ser apuntados aquí.
239F:C868 JMP 0D2D <-- HASP entry point.
239F:C86B POP BP
239F:C86C POP DI
239F:C86D POP SI
239F:C86E POP ES
239F:C86F POP DS
239F:C870 POP BP
239F:C871 RETF

Parejas de Passwords: 5804/30B4 3EB5/5C72 EE5A/C764 3EBD/5A5B
                 FC73/1164 13D5/23EF

Ya casi al final de esto CASMate una séptima comprobación de Service 2 comprobando la duplicación del segundo par de passwords(CX=3EB5, DX=5C72). Mi mejor teoría apunta a que cada código controla una forma específica de dongle así que yo tengo que recurrir a la confirmación de que soy un usuario registrado con el cuarto par aunque yo no veo ninguna otra razón por la que deba ser posible forzar los otros para que funcionen.

F519h - Regresa al código 4232, D2B3, F168 y 665A.
BF21h - Regresa al código D65F, 6AED, 1EDC y 9D0E.

Emulación Finalizada

En primer lugar cambia el entry point del Hasp JMP en el offset (E9 --> E8), esto nos proporciona una manera fácil de regresar de nuestro emulador. Estoy casi seguro de que CASMate utiliza un MemoHASP nosotros emularemos los siguientes services (1, 2, 3, 4, 5, 6, 32 y 33). Os muestro el código más abajo:-

:120D2D CALL $+5 (E8 00 00)
:120D30 POP BP (5D)
:120D31 OR BH, BH (0A FF)
:120D33 JZ 120D6D (74 38) <-- Falsificación correcta del service.
:120D35 CMP BH, 1 (80 FF 01) <-- IsHasp().
:120D38 JNZ 120D3E (75 04) <-- Comprueba el siguiente service.
:120D3A MOV AX, 1 (B8 01 00) <-- HASP found.
:120D3D RET (C3) <-- Regresa del emulador.
:120D3E CMP BH, 2 (80 FF 02) <-- HaspCode().
:120D41 JNZ 120D76 (75 33) <-- Comprueba el siguiente service.
:120D43 CMP CX, 03EBD (81 F9 BD 3E) <-- Comprueba si el password es correcto 1.
:120D47 JNZ 120D6D (75 24) <-- Password incorrecto.
:120D49 CMP AX, 0F519 (3D 19 F5) <-- Comprueba el código.
:120D4C JNZ 120D5B (75 0D)
:120D4E MOV AX, 04232 (B8 32 42) <-- Regreso 1.
:120D51 MOV BX, 0D2B3 (BB B3 D2) <-- Regreso 2.
:120D54 MOV CX, 0F168 (B9 68 F1) <-- Regreso 3.
:120D57 MOV DX, 0665A (BA 5A 66) <-- Regreso 4.
:120D5A RET (C3)
:120D5B CMP AX, 0BF21 (3D 21 BF) <-- este es el código.
:120D5E JNZ 120D6D (75 0D)
:120D60 MOV AX, 0D65F (B8 5F D6) <-- Regreso 1.
:120D63 MOV BX, 06AED (BB ED 6A) <-- Regreso 2.
:120D66 MOV CX, 01EDC (B9 DC 1E) <-- Regreso 3.
:120D69 MOV DX, 09D0E (BA 0E 9D) <-- Regreso 4.
:120D6C RET (C3)
:120D6D XOR AX, AX (33 C0) <-- Vacía AX.
:120D6F XOR BX, BX (33 DB) <-- Vacía BX.
:120D71 XOR CX, CX (33 C9) <-- Vacía CX.
:120D73 XOR DX, DX (33 D2) <-- Vacía DX.
:120D75 RET (C3) <-- El Service 4 también regresa aquí.
:120D76 CMP BH, 3 (80 FF 03) <-- Lee Word.
:120D79 JNZ 120D8A (75 0F)
:120D7B LEA BX, [BP+009B] (8D 9E 9B 00) <-- Comienza la simulación del Dongle en memoria.
:120D7F SHL DI, 1 (D1 E7)
:120D81 MOV BX, [BX+DI] (8B 19) <-- Lee word.
:120D83 SHR DI, 1 (D1 EF) <-- Restaura DI.
:120D85 MOV AX, DI (8B C7) <-- Coloca la word leida en AX.
:120D87 XOR CX, CX (33 C9) <-- Vacía CX para finalizar.
:120D89 RET (C3)
:120D8A CMP BH, 4 (80 FF 04) <-- Escribe la Word.
:120D8D JZ 120D6D (74 DE) <-- Todo correcto.
:120D8F CMP BH, 5 (80 FF 05) <-- Estado del HASP .
:120D92 JNZ 120D9C (75 08) <-- Comprueba el service siguiente.
:120D94 MOV AX, 1 (B8 01 00)
:120D97 MOV BX, AX (8B D8)
:120D99 MOV CX, AX (8B C8) <-- MemoHASP conectado.
:120D9B RET (C3) :120D9C CMP BH, 6 (80 FF 06) <-- HASPId.
:120D9F JNZ 120DAA (75 09)
:120DA1 MOV AX, 0 (B8 00 00) <-- ID bajo.
:120DA4 MOV BX, 0 (BB 00 00) <-- ID superior.
:120DA7 XOR CX, CX (33 C9) <-- Finaliza CX=0.
:120DA9 RET (C3)
:120DAA CMP BH, 33 (80 FF 33) <-- Escribe el bloque.
:120DAD JNZ 120DB2 (75 03)
:120DAF XOR CX, CX (33 C9) <-- Finaliza CX=0.
:120DB1 RET (C3)
:120DB2 CMP BH, 32 (80 FF 32) <-- Lee el bloque.
:120DB5 JNZ 120D6D (75 B6) <-- Falsifica el éxito del proceso.
:120DB7 LEA BX, [BP+009B] (8D 9E 9B 00) <-- Inicia el principio de la memoria Dongle.
:120DBB MOV CX, SI (8B CE) <-- Número de words a mover.
:120DBD SHL DI, 1 (D1 E7)
:120DBF LEA SI, [BX+DI] (8D 31) <-- lee de aquí.
:120DC1 SHR DI, 1 (D1 EF)
:120DC3 XCHG DI, AX (97) <-- lo mueve hacia aquí.
:120DC4 REPZ MOVSW (F3 A5) <-- Mueve las words.
:120DC6 XCHG DI, AX (97) <-- Restaura AX.
:120DC7 XOR CX, CX (33 C9) <-- Finaliza CX=0.
:120DC9 RET (C3) <-- Fín de la rutina de emulación.
:120DCB DB dup 112(0) <-- Comienzo de la memoria de emulación.

El código que se observa aquí es el service 32h (50) el cuál lee 38h words del dongle. Después de la primera lectura del Service 6 le la ID del dongle y después de una lejana llamada al service 32h se utiliza para comprobar áreas de memoria del dongle (De hecho en el HASPId es almacenado en las words 3 y 4 de nuestra memoria de simulación), así que vamos a asegurarnos de que corresponde con el anteriormente citado service 6 parcheado en la citada emulación.

Las opciones son controladas por varias words, recomiendo colocar un bpr en el área completa, un buen truco es etiquetar tu memoria emulada consecutivamente por ejemplo: 00, 01, 02, 03, esto debería hacer más fácil de ver las posiciones que están siendo usadas. Hay 3 comprobaciones de DWORD que deben ser corregidas.

cs:0B48 CMP EAX,ES:[BX+02] <-- primera comprobación (bytes 0,1,2,3).
cs:0B4D JZ 0B53 <-- Salto Bueno.

Shaman's crack (¿?)

Se que el site de Fravia ya alberga un ensayo de CASMate todavía puede ser que tenga algunos errores estéticos, por ejemplo Shaman en verdad no regresa todos los códigos correctos con el Service 2, el además confunde los parámetros de regreso del Service 5 y del Service 3 (también tiene algunas erratas que también yo debo tener). Si tu eres propietario de CASMate, debería serte posible utilizar tu editor Hex para parchear en los bytes que yo te he mostrado y entonces eliminar cualquier dongle existente y copiar su contenido a la memoria de simulación.


© 1999 CrackZ. 21st October 1999.

Traducido por John Keeper 2.000 JKEEPER@CORREO.DE
www.000webhost.com