Karpoff Spanish Tutor 1999-2001

Programa:

HexWorkShop v3.02


 

PROTECCION: Aplicacion con limite de tiempo
Descripcion: Editor Hexadecimal
Dificultad: Novato
DOWNLOAD: http://bpsoft.com
Herramientas: Softice v4.0, W32dasm v8.93, Hex WorkShop v 2.20
CRACKER:

Fantomas:

  FECHA: 07/07/2001

 

 INTRODUCCION


En esta ocacion voy a analizar la version
v3.02, no puedo hablar sobre las ventajas o desventajas de esta aplicacion, ya que al momento de hacer uso de esta, ya estaba vencido el periodo de evaluacion, y bueno, algo habia que hacer

Un tanto ingenuo, volvi a instalar la aplicacion, para ver si en algo cambiaban las cosas, por aquello de que pudiese ser un error de instalacion o registro, y nada asi que

 

 AL ATAKE


Veamos primero que pasa, despues de correr la aplicacion, tenemos enfrente algo asi:

cerramos la aplicacion y ahora nos aparece esto:

noten que marca una fecha de expiracion el 8 de Agosto y apenas estamos en Julio, pero eso no importa

Nuevamente corremos la aplicacion, y ahora tenemos presente el siguiente mensage

valla que son especiales estas gentes de BreackPoint Software Inc. ya que insisto que tienen una mania por las cajas de texto o cajas de dialogo, bueno sigamos adelante, seleccionemos el boton Unlock y entraremos a la seccion de registro

sin embargo estos datos no son validos y el resultado es

Ahora carguemos la aplicacion con el W32dasm y busquemos la cadena de texto Invalid Key o la cadena de texto Please check your key and try again y para nuestra sorpresa, no vamos a enconrtrar ninguna, es mas si buscas las cadenas de texto de la caja de dialogo anterior Registration Information, Name, Company o Cancel no vamos a encontrar nada, entonces que pasa.

La respuesta la vamos a encontrar en el archivo
bpsregwd.dll,
carguemoslo con el
W32dasm y busquemos la cadena de texto Invalid Key

|
:10002E35 EB4E jmp 10002E85
|
* Referenced by a Conditional Jump at Address
:10002E09
|
* Possible Reference to String Resource ID=00014: "Please check your key and try again. If this problem persis"
|
:10002E37 6A0E push 0000000E
:10002E39 8D4DEC lea ecx, dword ptr [ebp-14]
:10002E3C E822C70000 call 1000F563
|
* Possible Reference to String Resource ID=00012: "Invalid Key"
|
:10002E41 6A0C push 0000000C
:10002E43 8D4DF0 lea ecx, dword ptr [ebp-10]
:10002E46 E818C70000 call 1000F563
:10002E4B 6A40 push 00000040
:10002E4D 8BCE mov ecx, esi
:10002E4F FF75F0 push [ebp-10]
:10002E52 FF75EC push [ebp-14]

|

vamonos entonces a ver quien llamo a esta rutina ( vamos a la direccion
:10002E09 )

|
:10002DFF E83BF4FFFF call 1000223F
:10002E04 83C418 add esp, 00000018
:10002E07 85C0 test eax, eax
:10002E09 752C jne
10002E37
|
* Possible Reference to String Resource ID=00013: "Thank you! Your product has been unlocked."
|
:10002E0B 6A0D push 0000000D
:10002E0D 8D4DEC lea ecx, dword ptr [ebp-14]
:10002E10 E84EC70000 call 1000F563
|


llegando aqui, es claro lo que vamos a hacer, sustituimos

:10002E07 852C TEST EAX, EAX por :10002E07 33C0 XOR EAX, EAX

o bien

:10002E09 752C JNE 10002E37 por :10002E09 752C JE 10002E37

corremos la aplicacion, en la ventana
Product Expiration le damos a Unlock en la siguiente caja llenamos los campos Name, Company y Key y le damos OK y obtendremos esto

sencillo no creen? y si creen que ya logramos 'crecer' la aplicacion. pues con mucha pena les digo que todo este teatro es una rutina 'caza-tontos', ya que una vez que le das a Aceptar se cierra la aplicacion y todo vuelve a empezar

Por lo tanto, empezamos a sospechar que esta aplicacion esta confeccionada de una forma diferente a las versiones anteriores, justo cuando me empezaba a aburrir esto de la Informatica Inversa, encuentro algo interesante, vamos a analizar mas a fondo la aplicacion.

Vamos
observar que la rutina

|
:10002D73 FF766C push [esi+6C]
:10002D76 8D850CFFFFFF lea eax, dword ptr [ebp+FFFFFF0C]
:10002D7C 50 push eax
:10002D7D E85E0A0000 call 100037E0
:10002D82 FF7664 push [esi+64]
:10002D85 8D855CFFFFFF lea eax, dword ptr [ebp+FFFFFF5C]
:10002D8B 50 push eax
:10002D8C E84F0A0000 call 100037E0
:10002D91 FF7668 push [esi+68]
:10002D94 8D45CC lea eax, dword ptr [ebp-34]
:10002D97 50 push eax
:10002D98 E8430A0000 call 100037E0
:10002D9D FF7670 push [esi+70]
:10002DA0 8D45AC lea eax, dword ptr [ebp-54]
:10002DA3 50 push eax
:10002DA4 E8370A0000 call 100037E0
|


copia desde la localidad de memoria
#0167:00C94250 hasta la localidad memoria #015F:0064EBA0, todos los datos que pusimos

Mas adelante nos volvemos a encontrar en la direccion
:10002DFF con siguiente instruccion

|
:
10002DFF E83BF4FFFF call 1000223F
|


y justo aqui, nos meternos a la rutina
:1000223F para ver que sucede ahi dentro

|
* Referenced by a CALL at Addresses :10002DFF
|
:
1000223F 55 push ebp
:10002240 8BEC mov ebp, esp
:10002242 81ECC8010000 sub esp, 000001C8
:10002248 53 push ebx
|
::::::::::::::::::::::::::::::::::::::::::::::
|
:10002272 50 push eax
:10002273 8D45EC lea eax, dword ptr [ebp-14]
:10002276 50 push eax
:10002277 FF751C push [ebp+1C]
:1000227A E896FCFFFF call
10001F15
|


podemos observar que no sucede nada imoportante hasta llegar a la direccion
:1000227A, vallamos ahora dentro de la rutina :10001F15
|
:
10001F15 55 push ebp
:10001F16 8BEC mov ebp, esp
:10001F18 81EC54010000 sub esp, 00000154
:10001F1E 53 push ebx
:10001F1F 56 push esi
:10001F20 8065FF00 and byte ptr [ebp-01], 00
:10001F24 57 push edi
:10001F25 6880000000 push 00000080
:10001F2A 8D85ACFEFFFF lea eax, dword ptr [ebp+FFFFFEAC]
:10001F30 FF7508 push [ebp+08]
:10001F33 50 push eax
:10001F34 E8E7240000 call
10004420
:10001F39 8D852CFFFFFF lea eax, dword ptr [ebp+FFFFFF2C]
:10001F3F 50 push eax
:10001F40 8D856CFFFFFF lea eax, dword ptr [ebp+FFFFFF6C]
:10001F46 50 push eax
:10001F47 8D45AC lea eax, dword ptr [ebp-54]
:10001F4A 50 push eax
:10001F4B 8D85ACFEFFFF lea eax, dword ptr [ebp+FFFFFEAC]
:10001F51 50 push eax
:10001F52 E838FFFFFF call
10001E8F
|

lo mas importante hasta aqui es la rutina
call 10004420, ya que copia la serie de numeros que pusimos como KEY
desde la localidad de memoria
0064EC60 hasta 0064E828 para empezar a checarla, para ello saltemos ahora hasta la rutina :10001E8F
|
* Referenced by a CALL at Address :10001F52
|
:10001E8F 55 push ebp
:10001E90 8BEC mov ebp, esp
:10001E92 53 push ebx
:10001E93 56 push esi
|
* Possible StringData Ref from Data Obj ->"-"
|
:10001E94 BEA4810110 mov esi, 100181A4
:10001E99 33DB xor ebx, ebx
:10001E9B 56 push esi
:10001E9C FF7508 push [ebp+08]
:10001E9F E8A4220000 call
10004148
:10001EA4 59 pop ecx
:10001EA5 3BC3 cmp eax, ebx
:10001EA7 59 pop ecx
:10001EA8 7465 je 10001F0F
:10001EAA 50 push eax
:10001EAB FF750C push [ebp+0C]
:10001EAE E82D190000 call
100037E0
:10001EB3 56 push esi
:10001EB4 53 push ebx
:10001EB5 E88E220000 call
10004148
:10001EBA 83C410 add esp, 00000010
:10001EBD 3BC3 cmp eax, ebx
:10001EBF 744E je 10001F0F
:10001EC1 50 push eax
:10001EC2 FF7510 push [ebp+10]
:10001EC5 E816190000 call
100037E0
:10001ECA 56 push esi
:10001ECB 53 push ebx
:10001ECC E877220000 call
10004148
:10001ED1 83C410 add esp, 00000010
:10001ED4 3BC3 cmp eax, ebx
:10001ED6 7437 je 10001F0F
:10001ED8 50 push eax
:10001ED9 FF7514 push [ebp+14]
:10001EDC E8FF180000 call
100037E0
|


lo primero que les voy a mencionar es que en la direccion
:10001F0F se encuentra la salida con error, asi que evitaremos caer ahi, y la salida con exito en :10001F0D asi que habra que saltar todos los obstaculos hasta llegar aqui.

Cada vez que entra a la rutina
:10004148, detecta donde estan los 'guiones' (-) 0x2Dh y los sustituye por 0x00h

y cada vez que entra a la rutina
:100037E0, copia cada seccion de la KEY en otras areas de la memoria ( :0064E928, :0064E908 y :0064E8E8 ), es claro que nosotros solo pusimos dos secciones, asi que la rutina nos sacara en la direccion :10001ED6 7437 je 10001F0F

en caso de haber puesto tres secciones, habriamos avanzado, para entonces toparnos con otro filtro

|
:10001EE1 FF7514 push [ebp+14]
:10001EE4 E8E7190000 call
100038D0
:10001EE9 83C40C add esp, 0000000C
:10001EEC 83F804 cmp eax,
00000004
:10001EEF 751E jne 10001F0F
:10001EF1 FF7510 push [ebp+10]
:10001EF4 E8D7190000 call
100038D0
:10001EF9 83F806 cmp eax,
00000006
:10001EFC 59 pop ecx
:10001EFD 7510 jne 10001F0F
:10001EFF FF750C push [ebp+0C]
:10001F02 E8C9190000 call
100038D0
:10001F07 83F805 cmp eax,
00000005
:10001F0A 59 pop ecx
:10001F0B 7202 jb 10001F0F
:10001F0D B301 mov bl, 01
|
* Referenced by a Conditional Jump at Addresses: :10001EA8, :10001EBF, :10001ED6, :10001EEF, :10001EFD, :10001F0B
|
:10001F0F 8AC3 mov al, bl
:10001F11 5E pop esi
:10001F12 5B pop ebx
:10001F13 5D pop ebp
:10001F14 C3 ret

|

observen que la longitud de cada seccion es otro factor a considerar (
5 , 6 y 4 caracteres ), asi que cambiamos de inmediato nuestro KEY por este otro 12345-678909-8765, esperamos que como minimo lleguemos a la direccion :10001F0D
con exito

Arrancamos de nuevo y regresamos de la rutina
call 10001E8F con la bandera a 1, o sea con el valor del acumulador igual a uno, a partir de este momento ( se supone que estamos en la direccion :10001F57 ), la salida por error es :100020B6 asi que evitaremos caer aqui, nos vamos hasta la direccion

|
:10001F52 E838FFFFFF call
10001E8F
:10001F57 83C41C add esp, 0000001C
:10001F5A 84C0 test al, al
:10001F5C 0F8454010000 je 100020B6
:10001F62 8D45AC lea eax, dword ptr [ebp-54]
:10001F65 50 push eax
:10001F66 E865190000 call 100038D0
:10001F6B 83F805 cmp eax, 00000005
:10001F6E 59 pop ecx
:10001F6F 0F8C41010000 jl 100020B6
:10001F75 8D7405A8 lea esi, dword ptr [ebp+eax-58]
:10001F79 8D45EC lea eax, dword ptr [ebp-14]
:10001F7C 56 push esi
:10001F7D 50 push eax
:10001F7E E85D180000 call 100037E0
:10001F83 802600 and byte ptr [esi], 00
:10001F86 807DAC2A cmp byte ptr [ebp-54], 2A
:10001F8A 59 pop ecx
:10001F8B 59 pop ecx
:10001F8C 7508 jne 10001F96
|


donde, una vez efectuado el salto, empieza el verdadero analisis de nuestra
KEY que de hecho es un tanto complicada, y aunque paresca mucho 'rollo', la voy a poner completa, ya que para eso estamos aqui, para aprender a analizar

|
:10001F96 8D45F8 lea eax, dword ptr [ebp-08]
:10001F99 6A0A push 0000000A
:10001F9B 50 push eax
:10001F9C 8D45AC lea eax, dword ptr [ebp-54]
:10001F9F 50 push eax
:10001FA0 E847220000 call
100041EC

veamos, la rutina
:100041EC analiza el primer digito ( nuestro caso es 12345-678909-8765 ), el resultado obtenido lo guarda en la localidad de memoria 0064EB5C = 00000001

:10001FA5 8B4D10 mov ecx, dword ptr [ebp+10]
:10001FA8 83C40C add esp, 0000000C
:10001FAB 8901 mov dword ptr [ecx], eax
:10001FAD 8A45EC mov al, byte ptr [ebp-14]
:10001FB0 80650A00 and byte ptr [ebp+0A], 00
:10001FB4 884508 mov byte ptr [ebp+08], al
:10001FB7 8A45ED mov al, byte ptr [ebp-13]
:10001FBA 884509 mov byte ptr [ebp+09], al
:10001FBD 8D45F8 lea eax, dword ptr [ebp-08]
:10001FC0 6A10 push 00000010
:10001FC2 50 push eax
:10001FC3 8D4508 lea eax, dword ptr [ebp+08]
:10001FC6 50 push eax
:10001FC7 E83C240000 call
10004408

la rutina
:10004408 analiza el segundo y tercer digito ( nuestro caso es 12345-678909-8765 ), el resultado obtenido lo guarda en la localidad de memoria 0064EB73 = 00000023

:10001FCC 8B4D14 mov ecx, dword ptr [ebp+14]
:10001FCF 83C40C add esp, 0000000C
:10001FD2 8801 mov byte ptr [ecx], al
:10001FD4 8B45F8 mov eax, dword ptr [ebp-08]
:10001FD7 803800 cmp byte ptr [eax], 00
:10001FDA 0F85D6000000 jne 100020B6
:10001FE0 8A45EE mov al, byte ptr [ebp-12]
:10001FE3 8065F600 and byte ptr [ebp-0A], 00
:10001FE7 8845F4 mov byte ptr [ebp-0C], al
:10001FEA 8A45EF mov al, byte ptr [ebp-11]
:10001FED 8845F5 mov byte ptr [ebp-0B], al
:10001FF0 8D45F8 lea eax, dword ptr [ebp-08]
:10001FF3 6A10 push 00000010
:10001FF5 50 push eax
:10001FF6 8D45F4 lea eax, dword ptr [ebp-0C]
:10001FF9 50 push eax
:10001FFA E809240000 call 10004408


la rutina
:10004408 analiza el cuarto y quinto digito ( nuestro caso es 12345-678909-8765 ), el resultado obtenido lo guarda en
la localidad de memoria
0064EB68 = 00000005 ( esto es igual al segundo digito de nuestro par )
la localidad de memoria
0064EB66 = 00000001 ( si el primer digito de nuestro par es 2 )
la localidad de memoria
0064EB72 = 00000001 ( si el primer digito de nuestro par es 4 )
la localidad de memoria
0064EB67 = 00000001 ( si el primer digito de nuestro par es 8 )

:10001FFF 8B4DF8 mov ecx, dword ptr [ebp-08]
:10002002 83C40C add esp, 0000000C
:10002005 803900 cmp byte ptr [ecx], 00
:10002008 0F85A8000000 jne 100020B6
:1000200E 8B7518 mov esi, dword ptr [ebp+18]
:10002011 8AC8 mov cl, al
:10002013 83E11F and ecx, 0000001F
:10002016 8B7D1C mov edi, dword ptr [ebp+1C]
:10002019 890E mov dword ptr [esi], ecx
:1000201B 8AC8 mov cl, al
:1000201D 80E120 and cl, 20
:10002020 8B5D20 mov ebx, dword ptr [ebp+20]
:10002023 80F920 cmp cl, 20
:10002026 6A0A push 0000000A
:10002028 0F94C1 sete cl
:1000202B 880F mov byte ptr [edi], cl
:1000202D 8AC8 mov cl, al
:1000202F 80E140 and cl, 40
:10002032 80F940 cmp cl, 40
:10002035 0F94C1 sete cl
:10002038 2480 and al, 80
:1000203A 880B mov byte ptr [ebx], cl
:1000203C 8B4D24 mov ecx, dword ptr [ebp+24]
:1000203F 3C80 cmp al, 80
:10002041 0F94C0 sete al
:10002044 8801 mov byte ptr [ecx], al
:10002046 8D45F8 lea eax, dword ptr [ebp-08]
:10002049 50 push eax
:1000204A 8D856CFFFFFF lea eax, dword ptr [ebp+FFFFFF6C]
:10002050 50 push eax
:10002051 E896210000 call
100041EC

la rutina
:100041EC analiza la segunda seccion ( nuestro caso es 12345-678909-8765 ), el resultado obtenido lo guarda en la localidad de memoria 0064EBFC = 000A5BFD este numero es el exadecimal del numero decimal 678909

:10002056 8B4D0C mov ecx, dword ptr [ebp+0C]
:10002059 83C40C add esp, 0000000C
:1000205C 8901 mov dword ptr [ecx], eax
:1000205E 8B45F8 mov eax, dword ptr [ebp-08]
:10002061 803800 cmp byte ptr [eax], 00
:10002064 7550 jne 100020B6
:10002066 8D45F8 lea eax, dword ptr [ebp-08]
:10002069 6A10 push 00000010
:1000206B 50 push eax
:1000206C 8D852CFFFFFF lea eax, dword ptr [ebp+FFFFFF2C]
:10002072 50 push eax
:10002073 E890230000 call 10004408

la rutina
:100041EC analiza la tercer seccion ( nuestro caso es 12345-678909-8765 ), el resultado obtenido lo guarda en la localidad de memoria 0064EA30 = 00008765

:10002078 894518 mov dword ptr [ebp+18], eax
:1000207B 8B45F8 mov eax, dword ptr [ebp-08]
:1000207E 83C40C add esp, 0000000C
:10002081 803800 cmp byte ptr [eax], 00
:10002084 7530 jne 100020B6

|

hasta aqui, la entrega se ha hecho sin error, ahora hay que ver que condiciones deben cumplir cada resultado obtenido, eso se desarrolla en la rutina siguiente

|
:10002086 8B4524 mov eax, dword ptr [ebp+24]
:10002089 8A00 mov al, byte ptr [eax]
:1000208B 50 push eax
:1000208C 8A03 mov al, byte ptr [ebx]
:1000208E 50 push eax
:1000208F 8A07 mov al, byte ptr [edi]
:10002091 50 push eax
:10002092 8B4514 mov eax, dword ptr [ebp+14]
:10002095 FF36 push dword ptr [esi]
:10002097 8A00 mov al, byte ptr [eax]
:10002099 50 push eax
:1000209A 8B4510 mov eax, dword ptr [ebp+10]
:1000209D FF30 push dword ptr [eax]
:1000209F 8B450C mov eax, dword ptr [ebp+0C]
:100020A2 FF30 push dword ptr [eax]
:100020A4 E884FDFFFF call
10001E2D
:100020A9 0FB7C0 movzx eax, ax
:100020AC 83C41C add esp, 0000001C
:100020AF 394518 cmp dword ptr [ebp+18], eax
:100020B2 0F9445FF sete byte ptr [ebp-01]
:100020B6 8A45FF mov al, byte ptr [ebp-01]
:100020B9 5F pop edi
:100020BA 5E pop esi
:100020BB 5B pop ebx
:100020BC C9 leave
:100020BD C3 ret
|


En la rutina
:10001E2D se juega un poco con los siguientes datos mediante 'algoritmos' un tanto inutiles

0167:0064E7D4 FD 5B 0A 00 02 A4 F5 FF-01 00 00 00 FE FF FF FF
0167:0064E7E4 23 00 00 00 05 00 00 00-00 00 00 00 01 00 00 00
0167:0064E7F4 00 00 00 00 7C E9 64 00-A9 20 00 10 FD 5B 0A 00
0167:0064E804 01 00 00 00 00 EB 64 00-05 00 00 00 00 EB 64 00

para asi poder obtener un numero 'magico' el cual es comparado con la tercer seccion de nuestra
KEY, de esta forma vamos a obtener el numero de serie correcto, en mi caso tendria que cambiar 8765 por A207, para que la aplicacion no rechace el KEY, si pones un BPX en 100020AF y checas el numero en [ebp+18] , veras la tercer seccion de tu KEY, y en el acumulador puedes obtener la tercer seccion correcta.


Hasta aqui ya podemos asegurar el triunfo, salvo un pequeño detalle que mencionare mas adelante, asi que vamos a concluir: la aplicacion sera registrada en dos pasos:

PRIMER PASO - Cambios en codigo muerto

Vamos a tener que efectuar ciertos cambios en el codigo de la aplicacion ( en realidad, los cambios deben ser efectuados en la libreria de la aplicacion bpsregwd.dll ), en algunos lugares estrategicos mediante algun editor hexagesimal

El primer cambio sera efectuado aqui

|
:1000228A 8B4D
0C mov ecx, dword ptr [ebp+0C]
:1000228D 384DFF cmp byte ptr [ebp-01], cl
:10002290 0F857F010000 jne 10002415
|

cambiarlo por

|
:1000228A 8B4D
FF mov ecx, dword ptr [ebp-01]
:1000228D 384DFF cmp byte ptr [ebp-01], cl
:10002290 0F857F010000 jne 10002415
|

no hay necesidad de explicarlo.

Este es el siguiente cambio

|
:100022B8
84C0 test al, al
:100022BA 7515 jne 100022D1
|


cambiarlo por

|
:100022B8
3AC0 cmp al, al
:100022BA 7515 jne 100022D1
|


este cambio tampoco hay porque explicarlo, a primera vista se ve porque hay que realizarlo.

El ultimo cambio en el codigo es el siguiente

|
:10002330
7470 je 100023A2
|


habra que cambiarlo por

|
:10002330
EB70 jmp 100023A2
|


tambien es logico el porque

Como pueden observar los cambio efectuados son para impedir que la aplicacion nos saque del camino correcto y termine con un letrerito 'Error en la Key...' o con este otro 'La aplicacion ha sido desbloqueada...' y al fin de cuentas no nos registre

SEGUNDO PASO - Cambios en caliente

Vamos a tener que correr la aplicacion con el SoftIce y hacer dos interrupciones en algunos lugares estrategicos, el primero ya lo mencionamos y sera para conocer la tercer seccion de nuestra KEY

Coloca un
BPX en 100020AF y checas el numero en EAX, dejas correr la aplicacion hasta que termine, corriges tu KEY y corres nuevamente la aplicacion, pero ahora con una interrupcion BPX 10001C75, aqui vamos a observar la localidad de memoria [EBP+0C] y le vamos a cambiar su valor a uno ( 0x01h )

|
:10001C75 55 push ebp
:10001C76 8BEC mov ebp, esp
:10001C78 53 push ebx
:10001C79 FF7514 push [ebp+14]
:10001C7C FF7510 push [ebp+10]
:10001C7F FF750C push [ebp+0C]
:10001C82 FF7508 push [ebp+08]
:10001C85 E81B000000 call 10001CA5
:10001C8A FF7514 push [ebp+14]
:10001C8D 8AD8 mov bl, al
:10001C8F FF7510 push [ebp+10]
|

de esta forma todo marchara bien y podremos asegurar que le quitamos los BUGS a esta aplicacion

 

*La amenaza elegante*

 

El presente documento, es una tarea cientifica de investigacion, con caracter docente, no pretende violar ninguna ley vigente, el autor no se hace responsable del uso, manejo o practicas inadecuadas del analisis presentado {:o)


Karpoff Spanish Tutor: Pagina dedicada a la divulgacion de informacion en Castellano, sobre Ingenieria Inversa y Programacion. Email "Colabora con tus Proyectos"
www.000webhost.com