|
|
 |
ESTUDIO COLECTIVO DE DESPROTECCIONES
Última Actualizacion:
25/10/2001
|
 |
|
Programa |
Cualquiera con protección de password Package For The Web v2.1 |
W95 / W98 / NT |
Descripción |
Breve Introducción a la Criptografía |
Tipo |
Package For The Web v2.1 |
Tipo de Tutorial |
[X]Original, []Adaptación, []Aplicación, []Traducción |
Url |
http://www.installshield.com |
Protección |
Criptografía de Clave Secreta |
Dificultad |
1) Principiante, 2) Amateur, 3) Aficionado, 4) Profesional, 5) Especialista |
Herramientas |
Uedit + Softice |
Objetivo |
Obtención de la clave secreta que permite la instalación |
Cracker |
Mr.Crimson |
Grupo |
Whiskey Kon Tekila |
Fecha |
20 de Febrero de 2000 |
INTRODUCCION
|
Este tutorial explica detalladamente cómo extraer la clave secreta
que protege la instalación de algunos programas distribuidos con
PackageForTheWeb (en adelante, PFTW).
He comprobado que hay cierta confusión entre los newbies acerca
de PFTW e InstallShield.
Ambos programas pertenecen a InstallShield
Software Corporation y tienen funciones diferentes:
-
InstallShield: Ejecuta la instalación
de software. Copia ficheros, actualiza el registro, crea iconos en el escritorio,
etc.
-
PFTW: Un set de instalación InstallShield
es una colección de ficheros (scripts, CABs, setup.exe, etc). Para
empaquetarlos y distribuirlos en un fichero único puede usarse PFTW.
Así, PFTW, es un paso previo a la instalación, momento que
aprovechan algunos programadores para pedir una clave secreta. El motivo
fundamental debe ser el poder trazar los downloads de sus programas (la
clave se envía por e-mail después de haber cumplimentado
un formulario) o simplemente desautorizar al gran público a usar
la demo.
Para seguir este tutorial sería interesante disponer de una app
protegida de esta manera. Debería haber una, creada para la ocasión,
aquí: test.zip
(237 Kb).
He implementado el método explicado en este tute en una pequeña
utilidad. Úsala a tu discreción: PFTW
Password Recovery v1.0 (Bugs report appreciated).
Ponte tus gafas de culo de botella, alísate el flequillo con
saliva y pon carita de alienado porque entramos a saco en el retorcido
mundo del criptoanálisis.
|
LA REFLEXION CASPOSA
|
El cracker nace, crece, se reproduce y se convierte en programador
a sueldo.
Obviando la reproducción, la etapa más interesante es
la del crecimiento porque en ella tiene lugar un cambio de actitud.
Los primeros cracks suelen ser parches, 74h/EBh, EBh/90h. Cambiar instrucciones
de bifurcación , NOPear bytes, borrar claves del registro. La característica
común está en que se intenta ELIMINAR
aquello que protege el programa.
Conforme vamos evolucionando, empezamos a tratar con programas que piden
la APORTACIÓN de algo, ya se trate
de números de serie, discos/ficheros llave, passwords, dongles...
Pero esto lleva su tiempo y muchas veces no disponemos del necesario.
Con esta casposa reflexión quiero decir que una protección
incrementa sus posibilidades de éxito cuando se basa en un elemento
externo que NO PUEDE DEDUCIRSE de la propia aplicación. Más
aún, cuando ese elemento externo forma parte activa de la aplicación
en sí.
Un esquema clásico de número de serie, por ejemplo, hace
aguas en dos puntos:
-
El algoritmo puede ser muy complejo, pero está en el código.
En caso de ser invertible siempre podemos averiguar la clave correcta puesto
que sabemos como debe ser el resultado final (validación)
-
El resultado mismo de la validación puede ser falseado.
Un método más potente encriptaría la propia aplicación
con una clave secreta:
-
Podemos acceder al algoritmo de cifrado en el código pero no sirve
de nada puesto que no conocemos ni la clave ni el resultado de la transformación
-
La validación no puede falsearse porque es en sí mismo el
funcionamiento de la aplicación.
Estas disquisiciones quedarán claras al lector avejentado,
que no aventajado, conforme avance en la lectura de este ameno tute.
|
TRAZANDO APLICACIONES 'Packaged For The Web' v2.1
|
Escribí este tute pensando en la versión 2.1.13.000 de
PFTW. Puede que siga siendo válido en versiones futuras y puede
que no. No me escribais para decirme que los offsets no coinciden o que
el método no funciona con versiones posteriores... simplemente resolvedlo.
Empezamos, como es usual por arrancar SoftICE con la aplicacion empaquetada
con PFTW. (En este tute usaré la demo que os he preparado: test.zip
(237 Kb)
Avanzando sobre los sucesivos cuadros de diálogo llegamos a
donde se pide el password:

CTRL-D para regresar a SoftICE y establecer un breakpoint en la función
'GetWindowText'. Regresando a la ventana tecleamos cualquier cosa y tenemos
el debugger activado.
Cada vez que tecleamos un carácter, el total es leído
y sometido a la validación como posible password. El botón
finalizar se habilita cuando esta validación se ha completado con
éxito.
La cosa tiene lugar así:
:00404A80 call GetWindowTextA
;Lee passwd tecleado
:00404A86 mov eax, dword ptr [0041A8F4]
:00404A8B push eax
;pasa passwd a función
:00404A8C call 00406E83
;funcion encriptado passwd
:00404A91 add esp, 00000004
:00404A94 mov dword ptr [ebp-04], eax ;Resultado en
eax
:00404A97 mov ecx, dword ptr [ebp-04] ;Copiado a ecx
:00404A9A cmp ecx, dword ptr [0041933C] ;Comparado con el correcto
:00404AA0 jne 00404AA9
;No coincide---> Fuckoff!
:00404AA2 mov eax, 00000001
:00404AA7 jmp 00404AAF
;Ok, prueba superada...!
Ooops... esto parece tan sencillo....
Vamos a falsear la comparación en :404AA0 y para ello tecleamos
"R FL=Z" en SoftICE (activa la bandera Z, comparación exitosa).
F5 para proseguir la ejecución y volvemos a la ventana original,
esta vez con el botón "Finalizar" habilitado.
Pulsando el botón aterrizamos en una segunda comprobación
en el mismo sitio anterior. Resolvemos de la misma manera y llegamos hasta
el siguiente cuadro de diálogo:

Esto tiene muy buen color... pulsamos "Continue".
Crash...! Obtenemos un mensaje de error que puede variar pero será
algo del estilo de:
-
"invalid command line"
-
"Not enough free space in disk"
-
"Error running xxxx.exe"
con el cual se abortará la instalación.
Pero, cómo es posible...? Si habíamos conseguido "engañar"
al código responsable de validar el password. Quizá tiene
lugar alguna otra comparación que hemos pasado por alto...?
Veamoslo.
|
CIENTOS DE CLAVES
|
El lector interesado puede detenerse a analizar la 'validación'
que tiene lugar en la llamada a la función:
:00404A8B push eax
;pasa passwd a función
:00404A8C call 00406E83
;funcion encriptado passwd
La cadena que introducimos como presunto password es transformada después
de algunas operaciones en una doble palabra que será comparada con
el valor correcto.
Si atacamos este esquema por fuerza bruta quizá podamos averiguar
algo. Teniendo presente las limitaciones de esta 'tecnica' (ver tute "AZPR
Cracking Multitarea!") podemos escribir un programa 'copiando' la
rutina :406E83 que permita comprobar la validez de un elevado número
de presuntos passwords.
El resultado es relativamente sorprendente: Con cualquier longitud,
hay CIENTOS de passwords que habilitan el botón "Finalizar". Sin
embargo después de probar unos cuantos observé que todos
reportaban el mismo error al desempaquetar el programa. La fuerza bruta
no resuelve el problema en este caso.
Lo que sucede está claro ahora. Existe una comprobación
preliminar de validez del password que simplemente nos permite seguir adelante
con el proceso. Sin embargo hay un momento en que sólo la AUTENTICA
clave será capaz de desencriptar el paquete.
|
EL METODO DE Vigenère
|
El encriptado del paquete se basa en una variante del método
de Vigenère (1.586). Durante mucho tiempo se consideró la
forma más segura de guardar datos aunque ha llovido bastante desde
eso.
El método consiste en lo siguiente:
-
Se elige un password.
-
Se encripta cada carácter del mensaje con cada uno del password.
-
Cuando se acaban los caracteres del password se vuelve al primero.
Veamos un ejemplo sencillo:
Mensaje original: |
Mr Crimson |
4D 72 20 43 72 69 6D 73 6F 6E |
Clave: wkt |
wk twktwkt |
77 6B 74 77 6B 74 77 6B 74 77 |
Encriptado (XOR): |
:......... |
3A 19 54 34 19 1D 1A 18 1B 19 |
Que tal...? Cómo extraeríais el mensaje original de:
3A 19 54 34 19 1D 1A 18 1B 19
si no sabeis siquiera la longitud del password...?
La potencia de esta sencilla técnica aumenta considerablemente
si los datos a encriptar han sido a su vez previamente encriptados o comprimidos.
Hay mucho que contar sobre esto, por eso lo mejor será dejarlo
y volver al tema que nos ocupa, PFTW
|
EL ALGORITMO EN PFTW
|
Vamos a ver como se implementa esta variante psicodélica del
método de Vigenère en PFTW.
Primero hay que decir que el bloque encriptado que contiene la instalación
protegida se vuelca en tiempo de ejecución a un fichero externo
alojado en:
\windows\temp\pftXXXX~TMP\pft1.pkg
En estado puro tiene este aspecto:
Una vez creado se mapea en memoria y se procede a deshacer el cifrado.
Cuando la desencriptación se completa con éxito, proporciona
a la instalación información necesaria acerca de los ficheros
de programa, las ubicaciones y sus contenidos.
Un password falso (o un falseo de las validaciones comentadas anteriormente)
da lugar a un pft1.pkg sin sentido y es por esto que se obtenien errores
del mismo tipo
El comienzo del proceso tiene lugar en :40744A donde se procede al encriptado
del propio password para reforzar un poco el esquema. Este cifrado se realiza
por el mismo método comentado antes y utiliza una llave fija
(usada incluso en otras versiones):
13h-35h-86h-07h
Entonces un password introducido como 'MrCrimson' se encriptaría
así:
Password original: |
Mr Crimson |
4D 72 20 43 72 69 6D 73 6F 6E |
Clave: 13358607h |
|
13 35 86 07 13 35 86 07 13 35 |
|
|
5E 47 A6 44 61 5C EB 74 7C 5B |
Puedes ver que esto es así analizando este bucle de código:
:00407448 33C9
xor ecx, ecx
:0040744A 8A08
mov cl, byte ptr [eax]
:0040744C 8B45F8
mov eax, dword ptr [ebp-08]
:0040744F 99
cdq
:00407450 F77D14
idiv [ebp+14]
:00407453 8B4510
mov eax, dword ptr [ebp+10]
:00407456 33DB
xor ebx, ebx
:00407458 8A1C10
mov bl, byte ptr [eax+edx]
:0040745B 33CB
xor ecx, ebx
:0040745D 8B55FC
mov edx, dword ptr [ebp-04]
:00407460 0355F8
add edx, dword ptr [ebp-08]
:00407463 880A
mov byte ptr [edx], cl
:00407465 EBCA
jmp 00407431
Ahora, con este password cifrado se procede
al desencriptado del fichero mencionado.
El algoritmo es sólo un poquito más complejo aunque mantiene
la analogía:
-
Se toma el 1er byte del fichero y se rota (i.e. ECh cambia a CEh)
-
Se hace XOR con el 1er byte del password cifrado.
-
Se niega con NOT
-
Siguiente byte del fichero / Siguiente byte del passwd
-
Cuando se acaban los bytes del passwd se vuelve al primero
Esto sucede en un bucle al total de bytes del fichero:
:004072FA mov al, byte ptr [edx+eax]
;i-esimo byte del password
:004072FD push eax
:004072FE mov ecx, dword ptr [ebp-38]
:00407301 mov edx, dword ptr [ebp-3C]
:00407304 mov al, byte ptr [edx+ecx]
;i-ésimo byte del fichero :00407307 push eax
:00407308 call 004073CF
;Rotacion/Xor/Not
:0040730D add esp, 00000008
:00407310 mov ecx, dword ptr [ebp-38]
:00407313 mov edx, dword ptr [ebp-3C]
:00407316 mov byte ptr [edx+ecx], al
;Nuevo valor al fichero.
Hasta aquí hemos llegado. Y ahora..?
Sabemos cómo se desencriptaría el bloque de datos si
tuviéramos el password correcto.
Sin embargo no sabemos nada acerca del propio password.
Puede intentarse la fuerza bruta en este caso...? dificilmente dado
que tampoco disponemos de un método de validación viable.
En definitiva, NO SABRÍAMOS distinguir un fichero bien
descifrado de otro erroneo....!!! Ambos son enormes streams de bytes
aunque sólo uno de ellos permite completar la instalación
con éxito...
|
COMETIERON 2 ERRORES
|
Cual podría ser el punto débil de este esquema....? Hay
alguna manera de averiguar el password correcto...?
Si que la hay y es absolutamente sorprendente pues puede ser considerado
como un error en el diseño de la protección entera.
Echemos un vistazo a uno de estos ficheros 'pftw1.pkg' una vez desencriptado:
Las preguntas que debemos hacernos son:
-
¿Que es común a todos los ficheros ?
-
¿ Hay algo que tenga que estar presente en TODOS los casos y
que nos pueda servir de referencia para analizar el origen del cifrado?
La respuesta es..... La cabecera!.
En efecto examinando otros PFTW descubrí que en todos los casos
se encontraba esta cabecera. Investigando un poco encontré que la
estructura de los primeros 28 bytes parecía obedecer lo siguiente:
Tipo de dato |
Significado |
Valor |
DWORD |
ID de tipo de fichero |
"MSCF" |
DWORD |
Desconocido |
00000000h |
DWORD |
Tamaño de fichero |
0002CDC1h |
DWORD |
Desconocido |
00000000h |
DWORD |
Desconocido |
0000002Ch |
DWORD |
Desconocido |
00000000h |
DWORD |
Desconocido |
03010100h |
Lo que queda no precisa de mucha explicación. Determinando el
tamaño del fichero podemos "reconstruir" sus primeros 28 bytes dado
que aparentemente la estrucutura se mantiene en todos los casos. Siguiendo
el ejemplo propuesto los primeros 28 bytes para nuestra 'victima' deberían
ser:
4D 53 43 46 00 00 00 00 C1 CD 02 00 00 00
00 00
2C 00 00 00 00 00 00 00 03 01 01 00
El tamaño de fichero lo podemos obtener en la llamada a GetFileSize
que tiene lugar en :4071f4 (este dato se necesita para habilitar memoria
para el mapeo)
Tambien puede mirarse directamente el tamaño de "pftw1.pkg".
Puesto que conocemos el proceso que se lleva a cabo en el cifrado (*)
procedemos al revés:
a) NOT de cada byte del fichero sin encriptar
B2 AC BC B9 FF FF FF FF 3E 32 FD FF FF FF
FF FF
D3 FF FF FF FF FF FF FF FC FE FE FF
b) Rotación de cada byte del fichero encriptado
ED F8 49 9E 96 AB 17 99 45 68 09 91 8D B9
59 9D
B3 BE 18 96 CC A9 16 9B 86 AF 19 8B
c) XOR entre bytes de a) y b)
5f 54 f5 27 69 54 E8 66 7B 5A F4 6E 72 46
A6 62
60 41 E7 69 33 56 E9 64 7A 51 E7 74
d) XOR con los bytes de la llave fija 13358607h
4C 61 73 20 7A 61 6E 61 68 6F 72 69 61 73
20 65
73 74 61 6E 20 63 6F 63 69 64 61 73
Esta última colección de bytes es precisamente la clave
secreta: "Las zanahorias estan cocidas".
Como sabemos cual es la longitud real del password ? Muy fácil,
tecleamos los caracteres obtenidos hasta que se habilite el botón
"finalizar".Una opción mas fina sería usar directamente aquella
primera rutina de validación. Cuando el número de caracteres
sea el correcto devolverá el valor apropiado.
Con esto se resuelve el problema en la infinita mayoría de los
casos (son inusuales los passwords tan largos, lo más común
es que no excedan de 10-12 caracteres.)
Como decía al comienzo, cometieron dos errores:
-
Basar un sistema de cifrado en un método tan añejo
-
Aplicar el cifrado a un fichero altamente formateado, con cabeceras y estructuras
fijas
|
CONCLUSION
|
Lo que hemos visto hoy es un caso muy sencillo de criptografía
aplicada a la protección de software.
La tendencia de los ultimos tiempos apunta a un incremento del uso de
esquemas potentes basados en clave publica. En estos casos los métodos
se vuelven difíciles de seguir sin una base matemática sólida.
No obstante les pondremos un ojo encima en cuanto sea posible.
Eso es todo por esta vez, espero que hayais disfrutado leyendo lo mismo
que yo escribiendo.
Up The Hammer!
Mr.Crimson
|
[ Entrada | Documentos Genéricos | WkT! Web Site ]
|
[ Todo el ECD | x Tipo de Protección | x Fecha de Publicación | x Orden Alfabético ]
|
|
(c)
Whiskey Kon Tekila [WkT!] - The Original Spanish Reversers.
Si necesitas contactar con
nosotros
, lee
esto
antes e infórmate de cómo puedes
ayudarnos |
|
|
|
|
|