.net assemblies checksum il binary-reproducibility

Determine si los ensamblados.NET se construyeron desde la misma fuente



assemblies checksum (7)

¿Alguien sabe de una manera de comparar dos ensamblados .NET para determinar si fueron construidos a partir de los "mismos" archivos fuente?

Soy consciente de que hay algunas utilidades de diferenciación disponibles, como el complemento para Reflector, pero no estoy interesado en ver las diferencias en una GUI, solo quiero una forma automática de comparar una colección de archivos binarios para ver si se crearon desde el mismos archivos fuente (o equivalente). Entiendo que varios archivos de origen diferentes pueden producir el mismo IL y me doy cuenta de que el proceso solo será sensible a las diferencias en el IL, no en el origen original.

El principal obstáculo para simplemente comparar los flujos de bytes para los dos ensamblajes es que .NET incluye un campo llamado "MVID" (Identificador de versión del módulo) del ensamblaje. Esto parece tener un valor diferente para cada compilación, por lo tanto, si construye el mismo código dos veces, el ensamblaje será diferente.

Una pregunta relacionada es, ¿alguien sabe cómo forzar el MVID para que sea el mismo para cada compilación? Esto evitaría que tuviéramos que tener un proceso de comparación que sea insensible a las diferencias en el valor del MVID. Sería preferible un MVID consistente, ya que esto significa que se podrían usar sumas de comprobación estándar.

El trasfondo de esto es que una empresa de terceros es responsable de revisar y aprobar nuestros lanzamientos de forma independiente, antes de que se nos permita publicar en Producción. Esto incluye revisar el código fuente. Quieren confirmar de forma independiente que el código fuente que les proporcionamos coincide con los binarios que compilamos, probamos y planeamos implementar actualmente. Estamos buscando un proceso que les permita construir independientemente el sistema desde la fuente que los suministramos, y comparar las sumas de verificación con las sumas de verificación de los binarios que hemos probado.

Por cierto. Tenga en cuenta que estamos utilizando integración continua, compilaciones automatizadas, control de origen, etc. El problema no está relacionado con una falta interna de control sobre qué archivos de origen se incluyeron en una compilación determinada. El problema es que un tercero es responsable de verificar que la fuente que les proporcionamos produce los mismos binarios que hemos probado y planeamos poner en producción. No deben confiar en ninguno de nuestros sistemas o controles internos, incluido el servidor de compilación o el sistema de control de código fuente. Lo único que les importa es obtener la fuente asociada con la compilación, realizar la compilación ellos mismos y verificar que las salidas coincidan con lo que decimos que estamos implementando.

La velocidad de ejecución de la solución de comparación no es particularmente importante.

Gracias


Al comparar las bibliotecas de clases con ILDasm v4.0.319.1, parece que la base de imágenes no está inicializada. Para evitar desajustes, use una solución revisada:

ildasm /all /text assembly.dll | find /v "// Time-date stamp:" | find /v "// MVID:" | find /v "// Checksum:" | find /v "// Image base:" > assembly.dasm

El punto de entrada (base de la imagen) es en realidad información interesante para ensamblajes ejecutables, y tendrá que verificarse cuidadosamente. Inyectar una nueva base de imágenes es una forma común de hacer que un programa haga algo completamente distinto. En mi caso, estoy tratando de verificar la consistencia de las compilaciones de subprocesos múltiples, por lo que es seguro saltear el punto de entrada.

Una nota sobre el rendimiento: Tomé una DLL de 8MB que fue construida para AnyCPU, y ejecuté ILDasm. El archivo resultante tenía un tamaño de 251 MB y tardó varios minutos en realizarse. Aproximadamente 32 veces el tamaño fue producido.


Hay algunas maneras de hacerlo dependiendo de la cantidad de trabajo que estés dispuesto a hacer y de la importancia del rendimiento y / o la precisión. Una forma en que Eric J. señaló es comparar los ensamblajes en binario, excluyendo las partes que cambian en cada compilación. Esta solución es fácil y rápida, pero podría darte muchos falsos negativos. Una forma mejor es profundizar usando la reflexión. Si el rendimiento es crítico, puede comenzar comparando los tipos y si coinciden, vaya a las definiciones de los miembros. Después de verificar las definiciones de tipo y miembro, y si todo es igual a ese punto, puede ir más allá al examinar el IL real de cada método al hacerlo a través del método GetILAsByteArray . Nuevamente, encontrarán diferencias incluso si todo es igual pero compilado con banderas un poco diferentes o una versión diferente del compilador. Yo diría que la mejor solución es usar una herramienta de integración continua que marque la compilación con el número de conjunto de cambios de su control de origen (usted está usando uno, ¿verdad?).

Un articulo relacionado


He utilizado la solución de Jerry Currry en ensamblajes de .Net 4 y descubrí que ahora hay un tercer elemento que variará en cada compilación: Suma de comprobación. ¿No es sorprendente encontrar una suma de comprobación dentro de un conjunto? Creo que agregar la suma de comprobación de un archivo dentro de ese archivo cambiará la suma de comprobación ...

De todos modos, el comando modificado es:

ildasm /all /text "assembly.dll" | find /v "// Time-date stamp:" | find /v "// MVID:" | find /v "// Checksum:" > assembly.dasm

Tenga en cuenta que también he cambiado un poco las cadenas de búsqueda agregando barras diagonales para evitar coincidencias involuntarias. Las líneas de este comando deben ejecutarse juntas en la misma línea, divididas para facilitar la lectura. Los nombres de los archivos necesitarán comillas dobles alrededor de ellos si contienen espacios.


No es demasiado doloroso usar herramientas de línea de comandos para filtrar MVID y sellos de fecha y hora de una representación de texto de la IL. Supongamos que file1.exe y file2.exe se crean a partir de las mismas fuentes:

c: / temp> ildasm / all / text file1.exe | buscar / v "sello de fecha y hora:" | encuentra / v "MVID"> file1.txt

c: / temp> ildasm / all / text file2.exe | buscar / v "sello de fecha y hora:" | buscar / v "MVID"> archivo2.txt

c: / temp> fc file1.txt file2.txt

Comparando archivos file1.txt y FILE2.TXT

FC: no se encontraron diferencias


Otra solución a tener en cuenta:

La información del código fuente se almacena cuando los archivos binarios se compilan en el modo de depuración. Luego puede verificar si pdb coincide con exe y si pdb lines coincide con el código fuente.


Puede utilizar el complemento Diff Reflector here .