En ocasiones… veo patrones…
Un día mientras analizaba un firmware me puse a hacer un pequeño script en python para convertir un archivo cualquiera a una imagen y así poder analizar «visualmente» un fichero para ver la entropía del mismo así como las diferentes partes de un archivo. Por ejemplo, visualizando un firmware, se puede ver fácilmente donde está el código del bootloader y donde está el código comprimido y/o cifrado, como en la siguiente imagen:
En esta imagen podemos ver como en la parte inicial donde se ven más «rayitas» y «coloritos» está el código del bootloader, una pequeña sección de datos con mucha entropía (código comprimido), una sección llena de carácteres FFh (la parte en negro) y el código real del firmware, comprimido (la mayor parte del archivo).
En el script lo único que hago es leer cada byte del archivo dado como entrada y convertir grupos de 3 bytes en colores RGB, es decir, el primer byte será el código para el «Red», el segundo byte para el «Green», el tercer byte para el «Blue» y así sucesivamente.
También es útil, por ejemplo, para ver ejecutables y sus secciones de recursos, como en la siguiente imagen del programa IceSword donde se ve perfectamente la espada:
Posibles usos
Uno de los usos interesantes, además de para ver ficheros y buscar patrones como si fuéramos enfermos mentales (soy un polvo borracho según mi madre 🙁 ) puede ser, por ejemplo, para codificar un fichero en una imagen, es decir, para esteganografía. El contenido del fichero, al completo, se codifica como una imagen ocultando (de un modo un poco txapuzas) la verdadera naturaleza del fichero a envíar.
Otro uso más, para el que ya se ha utilizado esto es para comprobar si un generador de números aleatorios es realmente aleatorio o no buscando patrones en la imagen que salga. Es decir, se pone a funcionar el generador de números aleatorios indicándole que nos devuelva «0» o «1» y nosotros dibujamos un pixel negro o un pixel blanco en función de que nos ha devuelto. Un ejemplo de uso real se muestra aquí, en el que se demuestra la debilidad de la función Rand() de PHP de versiones ya bastante viejas:
El código de este pequeño script en Python es el siguiente:
import os
import sys
from math import sqrt
from PIL import Image
def main(bin, filename):
buf = open(bin, "rb").read()
size = int(sqrt(len(buf))*0.5)
img = Image.new("RGB", (size, size), "red")
putpixel = img.putpixel
i = 0
for y in range(int(size)):
for x in range(int(size)):
if i > len(buf) or len(buf)-i <= 3:
break
value = (ord(buf[i:i+1]), ord(buf[i+1:i+2]), ord(buf[i+3:i+4]))
i += 3
putpixel((x, y), value)
img.save(filename)
os.system("start " + filename)
def usage():
print "Usage:", sys.argv[0], " "
if __name__ == "__main__":
if len(sys.argv) != 3:
usage()
else:
main(sys.argv[1], sys.argv[2])