今日やったこと(BMPファイルのヘッダ 解析)

最近やったことと言えば一人で深酒して二日酔いしたくらいの事ですが、そんなことを記事に書いてもどうしようもないので。


http://www.ece.ualberta.ca/~elliott/ee552/studentAppNotes/2003_w/misc/bmp_file_format/bmp_file_format.htm

https://algorithm.joho.info/image-processing/bmp-file-data-header/


以上のサイトを参考にして、プログラミングの勉強がてら、bmpファイル(Windows)のヘッダ内容を解析する簡単なPythonプログラムを作ってみました。

bmpファイルにはWindows, OS/2の2種類があるらしく、今回扱うWindowsのbmpヘッダサイズは54バイトの大きさです。プログラムのコードは以下の通りです。

ファイルシグネチャとかで検査してないので、jpgファイルとか突っ込むとバグります。

最近バイナリが楽しいです。CTFでpwnの問題解けるように勉強したいです。


import sys

def b2int(b: bytes) -> int:
   return int.from_bytes(b, byteorder='little')

def bmp(filename):
   # BMP Header size: 54 bytes
   
   file_binary = b''
   try:
       with open(filename, 'rb') as f:
           file_binary = f.read()
           
   except:
       print("Error! Cannot read the file : {}".format(filename))
       return
    #Header 
   #Signature 
   signature = file_binary[0:2]
   print("Signature(expected '424d'): {} ({})".format(signature.hex(), signature.decode()))
   
   #filesize 
   print("File size: {} bytes".format(b2int(file_binary[2:6])))
   
   #header  size
   print("Header size: {} bytes".format(b2int(file_binary[10:14]) ))
   
    #InfoHeader 
   #InfoHeader 
   print("InfoHeader (expected 40bytes) : {} bytes".format(b2int(file_binary[14:18])))
   
   #bmp  width and height
   print("Width: {}px, Height: {}px".format(b2int(file_binary[18:22]), b2int(file_binary[22:26]) ))
   
   #number  of plane
   print("Number of plane(constantly 1) : {}".format(b2int(file_binary[26:28])))
   
   #Bits  Per Pixel
   color = b2int(file_binary[28:30])
   if color == 24:
       print("24bit RGB colors: 16M colors")
   elif color == 16:
       print("16bit RGB colors: 65536 colors")
   elif color == 8:
       print("8bit palletized: 256 colors")
   elif color == 4:
       print("4bit palletized: 16 colors")
   elif color == 1:
       print("monochrome palette: 1 color")
   else:
       print("[Error] Bits per pixel: {}".format(color))
       
   # Compress format
   compression = b2int(file_binary[30:32])
   if compression == 0:
       print("Bl_RGB: no compression")
   elif compression == 1:
       print("Bl_RLE8 8bit RLE encoding")
   elif compression == 2:
       print("Bl_RLE4 4bit RLE encoding")
   else:
       print("[Error] Compress format")
      
   # Compressed size
   image_size = b2int(file_binary[34:38])
   if (image_size == 0) and (compression == 0):
       print("Image size: {} bytes".format(b2int(file_binary[2:6]) - 54))
   else:
       print("Image size: {} bytes".format(b2int(file_binary[34:38])))
   
   # Resolution
   print("Horizontal(X) resolution: {} pixels/m".format(b2int(file_binary[38:42])))
   print("Vertical(Y) resolution: {} pixels/m".format(b2int(file_binary[42:46])))
   
   # Used colors (if 0, all colors used)
   used_colors = b2int(file_binary[46:50])
   if used_colors == 0:
       print("All 16777216 colors used")
   else:
       print("{} colors used".format(used_colors))
       
   # Important colors (if 0, all colors)
   imp_colors = b2int(file_binary[50:54])
   if imp_colors == 0:
       print("Important colors : All colors")
   else:
       print("Important colors: {}".format(imp_colors))
   
   
def main():
   args = sys.argv

   if len(args) < 2:
       print("[Usage] python3 tools.py [filename]")
       exit()

   filename = args[1]
   print("Input filename: {}".format(filename))

   bmp(filename)
   
if __name__ == "__main__":
   main()

この記事が気に入ったらサポートをしてみませんか?