今日やったこと(BMPファイルのヘッダ 解析)
最近やったことと言えば一人で深酒して二日酔いしたくらいの事ですが、そんなことを記事に書いてもどうしようもないので。
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()