BMP Signature Format: Documentation & Recovery Example

BMP Signature Format: Documentation & Recovery Example

BMP (bitmap image) files start with a signature BM and next 4 bytes contain file length.

Let's examine the example

When inspecting example.bmp file's binary data using any Hex Viewer, like Active@ Disk Editor we can see it starts with a signature BM and next 4 bytes (hex: F6 04 00 00) when converted to decimal format using little endian (low byte first) order give us length of file 1,270 bytes. Thus reading of all 1,270 consecutive bytes starting from the position of detected BM header provide us with all BMP file data.

BMP Signature format inspection

More info:

Windows BMP files header:

offset size description
0 2 signature, must be 4D42 hex ("BM")
2 4 size of BMP file in bytes (unreliable)
6 2 reserved, must be zero
8 2 reserved, must be zero
10 4 offset to start of image data in bytes
14 4 size of BITMAPINFOHEADER structure, must be 40
18 4 image width in pixels
22 4 image height in pixels
26 2 number of planes in the image, must be 1
28 2 number of bits per pixel (1, 4, 8, or 24)
30 4 compression type (0=none, 1=RLE-8, 2=RLE-4)
34 4 size of image data in bytes (including padding)
38 4 horizontal resolution in pixels per meter (unreliable)
42 4 vertical resolution in pixels per meter (unreliable)
46 4 number of colors in image, or zero
50 4 number of important colors, or zero

Active@ File Recovery Custom Scripting Example

This example does some validation calculations for critical BMP header's parameters beyond simple file size extraction.
Syntax of the signature definition language you can read here.

[BMP_HEADER]
DESCRIPTION=Bitmap Images BMP
EXTENSION=bmp
BEGIN=BMP_BEGIN
SCRIPT=BMP_SCRIPT

[BMP_BEGIN]
BM=0|0

[BMP_SCRIPT]
	width = read(dword, 12h)
	if (width == 0) goto exit
	height = read(dword, 16h)
	if (height == 0) goto exit
	pixel = read(word, 1ch)
	if (pixel == 1) goto valid
	if (pixel == 4) goto valid
	if (pixel == 8) goto valid
	if (pixel == 16) goto valid
	if (pixel == 24) goto valid
	if (pixel != 32) goto exit
valid:
	pixel = mul(pixel, width)
	pixel = mul(pixel, height)
	pixel = div(pixel, 1000b)
	rastr_size = read(dword, 22h)
	if (rastr_size < pixel) goto exit
	rastr_offset = read(dword, 0Ah)
	if (rastr_offset < 38) goto exit
	rastr_offset = sum(rastr_offset, rastr_size)
	size = read(dword, 2)
	if (size >= rastr_offset) goto exit
	size = 0