Una mirada técnica (y curiosa) al sistema Authenticode (II)

jueves, 11 de julio de 2013

En esta segunda parte seguiremos viendo cómo se firma realmente un archivo, y la (poca) documentación existente. También comprobaremos que si bien se especifica que sólo se puede usar el algoritmo SHA1 para firmar, no es difícil encontrar ficheros firmados con MD5 e incluso SHA256

¿Cómo calcular el hash Aunthenticode?

Se supone que el hash Authenticode no es más que un SHA-1 selectivo sobre algunas partes del binario. Está documentado (de aquella manera) por Microsoft, sin embargo no hay muchas herramientas que lo calculen y muestren. Existen varias formas de saber el hash Authenticode de un binario. Una fórmula sencilla es mirándolo en el propio código, puesto que está incrustado. Normalmente en el offset 0x85 de la dirección virtual relativa marcada por Security Directory (en la cabecera). Por ejemplo el programa PE Explorer lo toma de ahí para mostrarlo. Por supuesto es modificable... a costa de la validez de la firma. Tomamos de nuevo el ejemplo del binario de Opera. Mirando las cabeceras y haciendo una pequeña suma, sacamos su hash SHA1 Autenticode.

El SHA1 Authenticode incrustado en una dirección relativa y cómo calcularlo
Podemos confirmar que es correcto con otros programas, como PE Explorer.

PE Explorer muestra el hash correctamente. Es más, lo toma directamente del binario de la dirección anteriormente descrita
También se puede calcular con cathash.exe. Esta pequeña herramienta calcula tanto el hash "normal" como el SHA1 de Authenticode especial (sin algunas cabeceras). 

Esta herramienta muestra los dos hashes, el "real" y el de Authenticode
Para implementarlo nosotros mismos, deberíamos usar la función CryptCATAdminCalcHashFromFileHandle de la DLL Wintrust.dll, que devuelve ese SHA1 especial. Pero existe también CryptCATAdminCalcHashFromFileHandle2, que permite especificar qué hash usar: SHA1 o SHA2 (256 bits). Esta función solo es válida en Windows 8 y 2012. Existen por tanto programas ya firmados con SHA2 y lo veremos en las siguiente entrada. Incluso con MD5. El problema con este último algoritmo es que ya se han hecho experimentos para intercambiar la firma entre binarios con colisiones.

¿Se puede "desfirmar" un binario?

Para estos experimentos con colisiones, es necesario "arrancar" la firma de un binario. ¿Se puede eliminar la firma electrónica? Sí. Se han desarrollado varias herramientas sencillas que permiten "desfirmar" un binario. Por ejemplo, delcert.exe. O un script en Python (solo funciona con la rama 2.7) de Didier Stevens mucho más completo que permite otras acciones sobre los ficheros. Eliminar la firma, extraerla, ponérsela a otro binario... etc. El resultado de eliminar una firma no suele ser exactamente igual al fichero original firmado, por una sencilla razón. Estas herramientas que eliminan certificados también machacan las cabeceras. Por ejemplo, ponen a cero la cabecera "Security Directory RVA" (dirección virtual relativa) y elimina el resto de bytes (unos 4k). Dejan el ejecutable "útil" pero no coincidirá exactamente byte por byte con el original. Lo que sí seguirá coincidiendo, lógicamente, es el hash Autenticode. En la siguiente imagen se observa cómo he arrancado el certificado a Opera, (y lo he convertido en Opera15unsig.exe) con la herramienta de Didier.

Se elimina la firma con disitool y luego se calcula el hash Authenticode del original y del sin firmar. Coinciden.
Al pasarle luego la herramienta cathash tanto al original como al nuevo, el hash oficial cambia, pero el hash SHA1 usado para Authenticode, no.

En la siguiente entrega, veremos cuántos ficheros firmados con MD5, SHA1 y SHA256 hay en un Windows XP, 7 y 8, gracias a un pequeño programa que hemos desarrollado.

* Una mirada técnica (y curiosa) al sistema Authenticode (I)
* Una mirada técnica (y curiosa) al sistema Authenticode (y III)

Sergio de los Santos
ssantos@11paths.com
@ssantosv


No hay comentarios:

Publicar un comentario en la entrada