Análisis y Reparación de una imagen PNG corrompida (Aprendiendo a estudiar un formato desconocido) “Buscar una aguja en un pajar no es tan dificil cuando se conoce el pajar (hecky)” Escenario: Se nos proporciona una Imagen png corrompida, en algunos visores se puede ver parte de ella y en otros no se abre. La imagen forma parte de un reto de un wargame (El cual no mencionare para no aurrinar dicho reto) Objetivos: .-Demostrar como iniciarse con el analisis de un formato desconocido. .-Documentarse y aprender aspectos basicos del formato PNG .-Reparar la imagen para que sea completamente visible. Abordaje: .-Se mostrara como es posible realizarlo bajo entornos Windows y Linux (Es indistinto ya que el formato no cambia) .-Se mostraran herramientas similares en ambos entornos y diferentes maneras de realizarlo. Imagen: Se puede descargar de http://neobits.org/retos/analizapng/reto.png Como se alcanza a apreciar solo se ve una parte y este visor (gwenview en linux) toma lo demas como transparencia. En windows por ejemplo el icono “preview” de la imagen igualmente se ve esa transparencia, y el visor por defecto de windows lo muestra asi: Pero algunos visores no lo pueden abrir ya que identifican error en el formato, Ej (totem en linux) Por ejemplo internet explorer tampoco muestra parte de la imagen ya que lo toma como error. Google chrome y firefox si nos muestra una parte de esa imagen. Totem nos arrojó informacion de donde esta el error. “PNG: IDAT: CRC error” esto poco a poco lo iremos entendiendo. Pero ahora que hacer? Necesitamos documentarnos!! El PNG es un formato bastante conocido y muy bien documentado en Internet, sin embargo para mi la mejor documentación sobre este formato que podria haber encontrado esta en: http://www.w3.org/TR/PNG/ Aqui encontraremos una INMENSA cantidad de información de como trabaja el PNG. Como esta no es una guia del formato PNG, sino una resolución al problema plateado, resumire rapidamente cuestiones básicas que necesitaremos saber, • • • • Todo PNG comienza con su firma (0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A ) Los PNG tienen la característica de poseer chunks (Fragmento de información caracteristica de formatos multimedia) El PNG tiene 18 diferentes tipos de chunks cada uno con su especificación El chunk IDAT es la que contiene la información de la imagen en si. Parte importante es saber la estructura de los chunks y es el siguiente apartado se explica perfectamente http://www.w3.org/TR/PNG/#5Chunk-layout Todo chunk sigue esta especificacion: El chunk IDAT trabaja con la primera especificación. Pero ahora veamos cuantos bytes ocupa esta especificación. 1. 4 bytes para el tamaño de dicho chunk. El tamaño que se especifica SOLO ES PARA LA INFORMACION DEL CHUNK (no incluye los 4 bytes del tamaño, 4 bytes del tipo de chunk y 4 bytes del CRC) 2. 4 bytes para el tipo de chunk que estan en texto plano y se pueden consultar los 18 tipos aqui (http://www.w3.org/TR/PNG/#4Concepts.FormatTypes) 3. La información del chunk ocupa el numero de bytes que se indico en el LENGTH 4. El CRC ocupa 4 bytes y calcula el crc32sum del CHUNK TYPE y del CHUNK DATA Vale mucha teoria? La verdad no, se los deje de lo mejor resumido y con los ejemplos quedara entendido perfectamente. Veamos un ejemplo: Esta es la forma que se ve hexadecimalmente el png. El editor hexadecimal aqui usado es Winhex bajo Windows, Winhex tiene la opcion de colorear ciertas partes para hacerlo mas identificable. En el ejemplo vemos 4 colores que corresponden a; • • • • • Amarillo Verde Rojo Blanco Azul -> -> -> -> -> Firma PNG (Solo una vez y en todo png) Longitud de la información del chunk Tipo/Nombre del chunk Información del chunk CRC calculado del chunk (crc32sum de Rojo+Blanco) Calcular Longitud: Para calcular la longitud se debe pasar de hexadecimal a decimal para saber cuantos bytes. Se puede hacer con la calculadora en linux, windows o la fisica. Simplemente elegir el modo programador y listo. Yo lo hice mas rapido con php y la funcion hexdec(); Vemos las longitudes respectivamente y asi sabemos la longitud de información que tiene cada chunk: • • • • IHDR 13 bytes de información tEXt 71 bytes de información sRGB 1 byte de información IDAT 8192 bytes de información (Primer IDAT) Calcular CRC: Ahora hare uso de otro excelente editor hexadecimal, ahora en linux (OKTETA) Por su facilidad de calcular el crc32sum y mostrarme numero de bytes seleccionados es mi preferido para esta tarea en especifico. Recordemos que para realizar el calculo del CRC del chunk se debe seleccionar los bytes de informacion del chunk mas el nombre del chunk. Y al final de la información del chunk estaran los 4 bytes que son el CRC. Veamos un ejemplo de como se calcularia ERRONEAMENTE EL CRC. En el siguiente ejemplo solo se seleccionan los 13 bytes de informacion del chunk IHDR, lo cual al calcular el CRC nos da diferente a lo que debiamos Ahora veamos como seria lo correcto para el calculo del CRC del chunk IHDR Ya en este caso elegimos los 13 bytes de la informacion + 4 bytes del nombre del chunk y nos da el CRC correcto =). Lo mismo lo podemos hacer para los demas. Ahora rapidamente con winhex se selccionan los bytes tambien y nos dirigimos a “Tools>Compute Hash” (Herramientas>Calcular Hash) seleccionamos CRC32 y nos lo calculara de la misma manera. Ya entendimos (espero) como esta conformado esto pero ahora donde buscamos el error? Bueno lo podemos hacer de varias maneras. 1.- La teoria dice que los chunks IDAT son los que contiene la información de la imagen en si. Asi que si un pedazo no se ve, podemos decir que el problema esta en este chunk. 2.-Esta ya la hicimos de hecho. Al abrirlo con totem en linux no dio el error: “PNG: IDAT: CRC error” Lo mismo pasa con el visor Irfanview en windows. Asi que aqui ya nos dice que el error esta en el chunk IDAT y que el crc32sum calculado para ese chunk no corresponde, osease alteraron una parte (bytes) dentro de este chunk. 3.-En windows existe un programa llamado “Tweakpng.exe” que nos ayuda a identificar errores en los PNG Aqui Tweakpng nos identifica el mismo error que en los anteriores casos dedujimos y nos dice que CRC tiene y cual DEBERIA tener. 4.- Por ultimo tenemos ahora una utilidad para linux llamada “Pngcrush” que igualmente nos puede identificar error y corregirlo (si le es posible) Bastara con correr el siguiente comando. $pngcrush -fix reto.png out Y esto repararia si es posible, en esta caso no lo fue, pero nos ayudo a identificar el problema tambien. PreConclusión: Hay un chunk IDAT que esta dañado y por ello no concuerda el CRC. Y ahora? Alguien hasta ahorita que han leido este manual se preguntó ¿Cuantos chunks IDAT puede tener un PNG? R = No hay limite. Osease que aqui nosotros estamos con el primer chunk IDAT que vemos. Pero veamos cuantos tiene nuestro archivo. En Winhex busquemos la cadena “IDAT” con CTRL+F y activando “Count Occurrences” o en linux con el comando; $strings reto.png|grep IDAT -c Bueno tenemos 96 IDATS ¿Cual es? Esta parte seria de todas la tardada. Lo que hice fue ir checando el CRC de cada IDAT. Por ejemplo el del primer IDAT si recuendan eran (0x00 0x00 0x20 0x00) 8192 bytes de información + 4 del nombre IDAT = 8196 Asi que el CRC de ese IDAT es: Este IDAT Esta correcto, asi que tendremos que hacer esto con todos los demas, y el que este incorrecto analizar por que esta incorrecto y corregirlo. Afortunadamente el error (les puedo adelantar) esta dentro de los primeros 10 IDAT (no digo cual para animarlos a que lo hagan) Veamos este IDAT: El nombre del chunk esta bien y la longitud dice que es; (0x00 0x00 0x10 0x00) == 4096 Ahora yo rapidamente analizando los IDAT vi que habia 3 valores en longitud nada mas. 0x00002000 == 8192 (94 IDAT) 0x00001000 == 4096 ( 1 IDAT) 0x000014BF == 5311 ( 1 IDAT) Cabe aclarar que la longitud 5311 corresponde al ultimo IDAT por lo que este si es posible que cambie, sin embargo el IDAT de longitud 4096 no deberia estar asi, es sospechoso. Todos los IDAT's deben de estar iguales (con excepcion del ultimo en dado caso) Asi que analizaremos ese IDAT. Si la longitud es de 4096 y el nombre del IDAT ocupa 4 bytes. 4096+4 = 5000. Osea despues de 5000 bytes debe comenzar el otro IDAT. Sin embargo despues de 5000 bytes no se encuentra el IDAT. Aqui esta el error!!! Si partimos de la premisa de que todos los IDAT deben ser del mismo tamaño entonces vemos que la longitud de este IDAT esta mal. El siguiente IDAT se encuentra 4096 bytes despues de los 4096(o 5000 contando el nombre del chunk) entonces 4096+4096= 8192 Y 819210 == 0x0000200016 Ya lo tenemos!!! Tenemos que corregir la longitud de ese chunk. Osea nada mas cambiar el byte 0x10 por 0x20 Lo guardamos!!! Y....... Perfecto reto pasado!! (Borro la respuesta del reto para no aurrinarlo) Muy dificil? Yo no sabia mucho de este formato y me tuve que documentar todo lo que les explique aqui, la verdad fuera de lo facil,dificil y las 2 horas que me tomo hacer esto, fue muy INSTRUCTIVO. Diran, TANTO PARA ESTO? Un solo numerito? Quiero terminar con un cuento clasico (mi resumen =P) en estas ocasiones: “Un señor tiene la mejor computadora del mundo, un dia deja de funcionar, llama al técnico y le dice que la repare. El técnico la revisa y dice...Ya se que tiene!! Va a su maletin y saca un desarmador, aprieta un tornillo que estaba flojo y la computadora funciono. Se acerca al dueño y le dice son $1000 USD? >Mil dolares? Por apretar un tornillo, eso yo lo pude hacer. Quiero me de una factura de sus servicios. Apretar un Tornillo Saber que tornillo apretar $1 USD $999 USD” En este caso un solo cambiamos un byte. Pero lo que aprendimos fue que byte de 784844 bytes. Y considerando que valor deberia tener ya que podia tener 256 valores. Asi que creo aprendimos bastante en esto. Pero lo mas importante que un formato desconocido no nos va a detener y documentandonos bien podemos lograr cosas CHULAS!!! Esto es todo, espero les agradara el manual y ya saben cualquier duda decirmelo. Atte. • • • Hecky de Neobits.org hecky@neobtits.org @hecky (Twitter) Dedicado: #UniversIT Course: Digital Forensics Fundamental Skills