CPS v1.16 - Tutorial

Saludos nuevamente y ¡bienvenido a otro 'dongle tutorial' solicitado por ustedes! De hecho CPS v1.16 se ajusta perfectamente a mi site ya que usa un Sentinel parecido a GeoPatch Power CAD/CAM, con la única diferencia de la librería 'SCW32.DLL' de 32 bits en lugar de la librería 'SCW16.DLL'. El desensamblado del '.EXE' principal lleva un buen rato, aunque merece la pena esperar; un rápido filtrado de las funciones 'import' nos proporcionará algo de código con el que poder empezar.

Nos aventuramos dentro de SoftICE; un 'BPIO -h 378 RW' funcionará; el primer break es el que se produce dentro de la 'DLL' de la mochila, por lo que desactivamos el breakpoint y empezamos a pulsar F12 para regresar al código de la aplicación. Llegaremos al punto de entrada a éste código:

:00419082 CALL 0056859B <-- Aterrizaremos justo después de ésto (RNBOcplusInitialize).
:00419087 MOV WORD PTR [EBP-1C], AX <-- Guarda AX
:0041908B MOV EDX, DWORD PTR [EBP-1C] <-- Ahora pone ésto en EDX
:0041908E AND EDX, 0000FFFF <-- Lo limpia
:00419094 TEST EDX,EDX <-- Comprueba EDX
:00419096 JZ 004190C5 <-- Puede que no sea un 'bad jump'

Este código puede que no funcione tal como su su intuición pueda sugerirle; el 'JZ' parece que debiera ser el 'bad jump', pero si continuamos con la ejecución del código veremos que nos lleva a un rápido 'RET', con lo que de éste modo nos saltamos ambos 'CALL' a RNBOcplusRead (que debemos suponer acceden a la mochila). Sin tener que echar un vistazo a la guía API para éste viejo Sentinel suponemos que RNBOcplusInitialize hacer realmente éso; podríamos tracear y buscar signos delatadores (ie., 378 en un registro), lo que sería indicativo de que se está obteniendo la dirección del puerto paralelo. Vamos a suponer que esto es correcto u continuemos.

:004190C5 MOV WORD PTR [0075F5F4], 0000 <-- Pone éste flag a 0
:004190E2 XOR EDX,EDX <-- EDX=0 (¿Quizás innecesario)
:004190E4 MOV DX, WORD PTR [0075F5F4] <-- Mueve el flag a DX
:004190EB CMP EDX, DWORD PTR [EBP-18] <-- Otra comprobación del flag
:004190EE JGE 00419159 <-- Salta y se prepara para leer la mochila

Este código es interesante; '[EBP-18]' es el flag crítico y obviamente es activado en algún sitio por el código de la 'DLL' de la mochila; todo el tiempo he podido observar que el flag es puesto a '5'; casi con certeza puedo decir que ésto es un código de error API que quiere decir "Mochila no presente" o algo parecido; probablemente el único código bueno de '[EBP-18]' sea '0'; pero observe que se hace un 'CALL' a RNBOcplusRead si éste salto no se produce; ésto símplemente es un bucle para comprobar nuevamente la presencia de mochilas. También sabemos que el código 'XOR EDX,EDX' y 'MOV DX' ponen 'EDX=0', aunque ésto ya estaba en el anterior trozo de código; con lo cual podemos usar ése espacio de direcciones aquí para poner '[EBP-18]' a '0' que es lo que necesitamos.

Parche

:004190E4 MOV WORD PTR [EBP-18], 0000 <-- Poner bien el flag de memoria (66, C7, 45, E8, 00, 00, 90).

Este parche nos garantiza que nuestro mochila ya existe y pone '[EBP-18]' de acuerdo a éllo por si se dá el caso de que sea comprobado posteriormente. Seguimos con el siguiente trozo de código.

:00419159 MOV WORD PTR [0075F5F4], 003F <-- Sabido: cantidad de datos de la mochila a leer
:00419162 PUSH 0075F1E8 <-- Guardar paquete
:00419167 MOV DX, WORD PTR [0075F5F4] <-- Guarda '3F' en 'DX'
:00419174 CALL 00568595 <-- RNBOcplusRead.
:00419179 MOV WORD PTR [EBP-1C], AX <-- Usa 'AX' para código de retorno de estado y lo guarda
:0041917D MOV WORD PTR [0075F5F4], 0005 <-- Lo guarda de nuevo
:00419186 XOR EAX,EAX <-- Borra EAX.
:00419188 MOV AX, WORD PTR [0075F1E8] <-- Vuelve de la mochila (¡es FFFF!).
:0041918E XOR ECX,ECX <-- Borra ECX
:00419190 MOV CX, WORD PTR [0075F5F4] <-- Conocemos éste valor
:00419197 XOR EDX,EDX <-- Borra EDX
:00419199 MOV DX, WORD PTR [EBP+2*ECX-28] <-- DX=valor de retorno "correcto" (5460h)
:0041919E CMP EAX,EDX <-- Comparación
:004191A0 JZ 004191CC <-- Salto correcto y pone los flags adecadamente [EBP-40]

Esta es la rutina principal de comprobación de la mochila; cuando la traceamos y vemos que 'AX' retorna con 'FFFF' ('-1'), la palabra error debe presentarse inmediatamente en nuestro cerebro; el valor correcto '5460h' queda desgraciadamente en el registro 'DX' para la comparación; obviamente tenemos tres modos de parchear ésto; la mejor opción es, probablemente, cambiar la instrucción de la posición '00419188' a 'MOV AX,5460h' y rellenar lo sobrante con los apropiados 'NOPs'; (ie., 66, B8, 60, 54, 40, 48).

Una vez más vemos una vulnerabilidad inherente a éste tipo de Sentinel; la estructura del API nos da a entender que cualquier 'Reverse Engineer' reflexionando un poco puede fácilmente encontrar el camino hacia el código. Cualquier esquema decente debería en realidad usar una respuesta d ela mochila para desencriptar parte de código cargado y, obviamente, comprobar la presencia del a mochila más de una vez. Aunque no demostrado cómo, debería ser posible el parcheo genérico de la 'DLL'; en lugar de devolver 'FFFF' como un error, debería ser posible incrustar código dentro de la 'DLL' para que recupere el código de retorno correcto.


© 1998 CrackZ. 1st November
Traducción: MeGaBiTe
www.000webhost.com