Esta entrada presenta un pequeño programa, llamado crackpkcs12, que será útil para quien quiera recuperar la contraseña de un archivo PKCS12 (extensiones p12 o pfx) recurriendo a un ataque de diccionario. Además, pretende ser un ejemplo práctico de cómo sacar partido a nuestras máquinas multinúcleo programando aplicaciones que usen hilos...



Cuando alguien me pidió intentar recuperar la contraseña de un archivo PKCS12 que albergaba su certificado Ceres de la FNMT en lo primero que pensé fue en un script en bash que realizara un ataque de diccionario usando openssl. El resultado fue el siguiente:
Sencillo. Tuve suerte y funcionó. Rompió la contraseña con un primer diccionario de pocas palabras, pero tardó cinco horas y media. El comando "time" dejaba claro que este tiempo tal alto para el relativamente bajo número de palabras que tuvo que probar (en torno a un millón) se debe a las tareas de sistema. Me propuse escribir algo más eficiente en C, que utilizara directamente la librería SSL, en lugar de la aplicación de consola. Descargué las fuentes de openssl para encontrar las funciones que leen un archivo PKCS12 y validan su contraseña (d2i_PKCS12_bio y PKCS12_verify_mac respectivamente) y las invoqué directamente desde este programa:
Para mostraros el enorme ahorro de tiempo voy a poner un ejemplo con un diccionario de dos millones y medio de palabras situando la contraseña correcta en la última fila del archivo. La prueba se realizó en mi equipo, un procesador "Intel(R) Core(TM)2 Quad CPU Q8300 @ 2.50GHz" con 4 GB de RAM y GNU/Linux de 64 bits como sistema operativo (concretamente Ubuntu 10.10).
Primero, veamos cuánto tiempo emplea el script:

> time ./crackpkcs12.sh diccionario.txt certificado.p12
real 833m20.804s
user 2m41.150s
sys 783m55.440s

Más de trece horas. Fijaos en cómo la mayoría del tiempo se pierde en labores de sistema y el tiempo real del proceso es muy pequeño, lo que confirma que la tarea en sí se puede realizar mucho más rápidamente.
Ahora, el programa. Para compilarlo, se debe tener instalada la librería de desarrollo de SSL (libssl-dev en Debian y derivados).

Después, simplemente copiar el código a un archivo crackpkcs12.c y compilarlo con:
gcc -O3 -lssl -lcrypto -o crackpkcs12 crackpkcs12.c

No la uso para el ejemplo, pero el programa tiene una opción -v que muestra mensajes a medida que se realiza cierto número de intentos y con -s podemos cambiar la frecuencia de estos mensajes (podéis lanzar el programa sin parámetros para ver un texto explicativo). Veamos cuanto tiempo emplea:

> time ./crackpkcs12 -d diccionario.txt certificado.p12
Password found: taller
real 0m37.236s
user 0m37.200s
sys 0m0.010s


Menos de 40 segundos. Apenas tiempo de sistema. El siguiente paso es aprovechar mejor mi máquina puesto que esta búsqueda utilizaba solamente uno de los 4 núcleos de mi equipo. Me puse manos a la obra y mejoré el programa para utilizar hilos. Si todo iba bien, aún debía poder reducir significativamente el tiempo. Aquí tenéis el resultado:
Esta versión final paralelizada es la contenida en el paquete .tar.gz que podéis descargar de la página de Sourceforge. Como en el caso anterior, para compilarla se debe tener instalada la librería de desarrollo de SSL. Podéis utilizar dicho paquete y recurrir al tradicional:

./configure
make

quedando el ejecutable en el directorio "src". La alternativa es copiar el código a un archivo crackpkcs12.c y ejecutar:

gcc -O3 -lpthread -lssl -lcrypto -o crackpkcs12 crackpkcs12.c

Sólo quedaba probarlo. Por defecto, el programa lanza un número de hilos igual al número de procesadores del equipo, en mi caso cuatro. Con el parámetro -t podemos lanzar el número de hilos que deseemos. Los números son los esperados, aproximadamente una cuarta parte que el script sin paralelizar:

> time ./crackpkcs12 -d diccionario.txt certificado.p12
Thread 1 - Password found: taller
real 0m9.605s
user 0m37.890s
sys 0m0.050s

De las más de 13 horas del tiempo inicial del script hemos llegado a menos de 10 segundos y, además, para la próxima vez que tenga que recuperar la contraseña de un archivo PKCS12 tendré la certeza de que estoy aprovechando mi equipo al máximo. Además, confirmé que usar bash para ruptura de contraseñas no es la mejor idea, aunque a veces sea lo más rápido de programar.
El siguiente paso será añadir la posibilidad de usar fuerza bruta sin diccionario.

Fuente: http://www.kriptopolis.org/crackpkcs12