Documento Análisis y Reparación de una imagen PNG corrompida

Anuncio
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
[email protected]
@hecky (Twitter)
Dedicado:
#UniversIT
Course: Digital Forensics Fundamental Skills
Descargar