8.2 文件与目录——二进制文件分析¶
内容梗概¶
本节课以 BMP 图片为例,讲解如何分析一个二进制文件的格式。老师先说明了坚持训练二进制分析能力的原因(对应计算机/信息安全专业中"二进制安全"方向),随后详细拆解了 BMP 文件的三大组成部分:14 字节的文件头、40 字节的信息头和像素数据,并引入"魔术数字(magic number)"概念及其在安全分析中识别伪装文件的应用。课上还演示了用 VS Code 的 Hexdump 插件查看二进制文件,并现场编写 Python 程序、以纯手动方式(read + 字节倒序 + int 转换)解析 BMP 文件头,为下一节引入 struct 标准库做铺垫。
知识点详解¶
为什么执着于分析二进制(约 01:27 - 02:40)¶
- 计算机/信息安全专业有一个大方向叫**二进制安全**(系统安全、软件安全均属此范畴)。
- 能按格式、按数值把二进制文件的内容读出来并深入分析,是走这个方向必备的能力;提前练熟,后续专业课上手方便,还能直接用 Python 介入专业课操作。
用二进制方式打开文件(约 00:00 - 00:30)¶
open(filename, mode)中mode加字母b(Binary)即以二进制方式读取/写入,如'rb'。
BMP 文件格式总览(约 02:40 - 06:30)¶
- BMP 格式很简单,包含三个大部分:
- 文件头:14 字节;
- 信息头:包含图像格式信息,一般 40 字节;
- 像素数据:上节课已分析过,大部分情况下每 3 个字节为一组表示一个像素。
- 分析二进制数据的软件通常一行显示 16 字节(或 32 字节):偏移量 00 开始,第二行偏移为 10(十六进制的 10 = 十进制 16)。上学期的 WinHex 和本节课的 VS Code 插件都是这个模式。
文件头各字段(约 06:30 - 11:30)¶
- 表格中偏移值后的
H是类似 C 语言的记法,表示前面的字符是十六进制。 - 偏移 0,2 字节:魔术数字 magic number,内容为
BM(十六进制 0x42、0x4D),是 bitmap(位图)的首字母,表示这是一个 BMP 文件。 - magic number 指程序中"作者不解释就不知道什么意思"的魔数;
BM就是一种文件特征魔数。 - 安全应用(约 08:33):安全分析人员不会凭文件后缀判断类型——勒索软件常把 exe 伪装成图片。正确做法是读文件开头的特征字节:号称 BMP 但开头不是
BM而是MZ(exe 的特征),就是冒牌货。这与本次作业直接相关。 - 接下来 4 字节:整个 BMP 文件的大小。
- 再 2 字节 + 2 字节:保留字段,暂时用不上。
- 再 4 字节:位图数据(像素数据)开始的偏移,通常是 54(14 + 40)。
- 信息头前 4 字节是信息头自身长度(一般 40),随后 4 字节图片宽度、4 字节图片高度等,课上未逐一展开。
用 VS Code Hexdump 插件查看二进制(约 12:00 - 15:45)¶
- VS Code 直接打开二进制文件会提示"二进制数据无法打开",需在扩展中安装 Hexdump 插件(安装后无需重启)。
- 对准文件标签页右键 →
Show Hexdump,即可看到十六进制 dump 视图: - 左侧 offset 列显示行首偏移,上方显示列号,可定位任意字节的偏移(如第 8 行的 0x8B);
- 中间是十六进制数据,右侧是对应的 ASCII 字符——可打印字符直接显示(如 0x42 →
B),不可打印的显示为小点,逻辑与 8.1 节bytes字面值一致。
实读 BMP 文件验证(约 15:46 - 18:30)¶
- 小端存储:低位字节先存,读多字节数值时要"倒过来"理解(上学期已讲过)。
- 跳过
BM两个字节,框取随后 4 字节读得文件大小0001D4F6,用程序员计算器换算为十进制 120054,与文件右键属性中的大小完全一致。 - 位图数据偏移字段为 0x36 = 54,即第三行第六列开始是像素数据;开头三字节
FF FF FF表示白色(图片左下角是白色),全部对上。
手动写程序解析 BMP 文件头(约 18:30 - 23:50)¶
- 新建
analyzer.py,用最直觉的方式解析哆啦A梦图片cat.bmp: with open('cat.bmp', 'rb') as f:打开;magic_number = f.read(2)读出 2 字节的 bytes(显示为b'BM');用magic_number.decode()转成字符串(这里预告了下一小节字符编码的内容:二进制转字符串要解码,字符串转二进制要编码);size = f.read(4)读 4 字节文件大小,然后**手动转换**:先size[::-1]把字节序倒过来(小端),再.hex()得到十六进制字符串,最后int(..., base=16)转成整数。- 老师评价:这样每读一个字段都要手动思考如何转换,非常非常费劲——由此引出下一节的
struct标准库。
示例与演示¶
- 画图讲解 BMP 三段结构(文件头 14 字节 / 信息头 40 字节 / 像素数据),按一行 16 字节排布。
- 用 VS Code Hexdump 插件打开哆啦A梦 BMP,逐字段对照分析:
BM标识、文件大小 120054 字节(与文件属性核对一致)、位图数据偏移 0x36、首像素FFFFFF(白色)。 - 现场编写
analyzer.py:以'rb'方式打开 BMP,read(2)读 magic number 并decode();read(4)读文件大小后手动倒序、转 hex、int(x, 16)转换,最终得到正确的文件大小数值。
重点与难点¶
- magic number / 文件特征:判断文件真实类型要看文件头特征字节(如 BMP 的
BM、exe 的MZ),不能相信后缀名——这是安全分析的基本套路,也是本次作业的核心。 - 小端存储:多字节数值低位在前,解析时必须先颠倒字节序再换算,这是手动解析最容易出错的地方。
- Hexdump 视图与
bytes字面值的显示逻辑相同:可打印显示字符,不可打印显示点/十六进制。 - 手动逐字段解析二进制文件繁琐易错,为
struct库的引入提供了动机。
关联内容¶
- 直接承接 8.1 节
bytes/十六进制表示的知识;呼应第 7 章用 BMP 做 ASCII 艺术时跳过的"BMP 格式解析"部分,本节补上。 - 与上学期课程内容关联:WinHex 查看硬盘数据、小端存储概念、恶意代码伪装文件的安全话题。
- 手动解析的痛点引出 8.3 节
struct标准库;decode()的提及预告 8.4 节"字符集与编码"。 - 文件特征比对思想是 8.6 节作业"猫鼠游戏"(识别改过后缀的假文件)的理论基础。