MIFARE Classic 扇区转储:那些十六进制在说什么

2026-11-02 · 1202 词

卡片的转储,是唯一一种不必相信某个读卡器就能描述凭证的形态。其他每一种形态 —— 卡面上印的号、面板上显示的号、线上跑的帧 —— 都已经过了一次别人选定的转换。转储没有经过这一层,它就是卡片存储里的那些字节。

也正因为如此,它是被读错最多的一种形态:里面没有任何标注,而它有三处约定是反直觉的。

1K 的布局,一段话讲完

MIFARE Classic 1K 是 1024 字节,组织成 16 个扇区 × 4 块,每块 16 字节,块号从 0 到 63。每个扇区的最后一块是特殊的:扇区 0 的第 3 块、扇区 1 的第 7 块、扇区 2 的第 11 块,依此类推。数据放在每个扇区的前三块里,第四块存这个扇区的密钥与权限。

所以完整的转储是 64 行十六进制(如果工具按块换行),或者一整串 1024 字节的连续 hex(如果它不换行)。拿到一整串没有换行的转储时,第一件事是按 16 字节重新切分 —— 否则你后面算出的每一个偏移都是错的,而且错得还能算出看起来合理的数字。

扇区 0 的第 0 块不一样

第一个扇区的第一块是厂商块,只读。它的字节大致这样排:

由此有两个后果。第一,靠写入是改不了卡片 UID 的 —— 这一块拒绝写操作,所以所谓"可改 UID 卡"是另一种芯片的产品,不是一个设置项。第二,4 字节 UID 和 7 字节 UID 在同一块里的排布并不相同,写死"取 0 到 3"的脚本会把 7 字节卡的 UID 读成"前四个字节",然后安静地丢掉三个。

UID 是倒着存的

这一处最耗时间。MIFARE 存 UID 用的是低位字节在前,而多数读卡器、面板和打印出来的卡号是高位在前。一个转储开头是 E1 5A 3C 04 的卡,读卡器会把它叫作 043C5AE1。

对比过两个读卡器的人都从另一个方向见过这种失败 —— 十进制换算与 125 kHz 读卡器的字节翻转,在卡号形态那篇里已经讲过一遍。转储本身没有自己的一套约定,它只是如实保留芯片的字节序,而上面每一层都可能、也可能不翻转它。

BCC 在这里是个顺手的验算:把 UID 的各字节异或起来,与 UID 之后那个字节对比。对不上,说明要么 UID 长度不是你以为的那个,要么这份转储根本不是你以为的那一块。一行代码的检查,能挡住最常见的误读。

尾块是三个字段,不是一个

每个扇区的最后一块依次是:6 字节 Key A、4 字节访问位、1 个通用字节、6 字节 Key B。十六个字节里塞了远超十六个字节的含义,这也是"密钥"从来不是一个 16 字节的值的原因 —— 不管它被这样描述过多少次。

这里有三件事让人意外:

密钥读不出来。 卡片只会告诉你某个密钥对不对,除此之外什么都不说。所以转储从来不是"把密钥暴露出来"—— 出这份转储的工具要么本来就知道密钥,要么这个扇区还停在出厂默认值上。

访问位存了三份。 那四个字节里是权限位加上两份取反的副本,这样一个比特被翻动时能被发现,而不是被照着执行。所以几乎所有教程里的 FF 07 80 不是什么魔法常量,而是某一组具体权限被同时写进了三份副本。

出厂卡是能认出来的。 一个从未配置过的扇区,尾块通常还是 FF FF FF FF FF FF FF 07 80 69 FF FF FF FF FF FF。如果你预期在用的扇区读出了这一串,那说明这张卡没被个性化过 —— 或者被重置过;对凭证而言,后者比"号码错了"更糟。

4K 卡打破了这个规律

4K 不是"1K 乘四"。它是 4096 字节、40 个扇区:扇区 0–31 各 4 块,与 1K 完全一样;扇区 32–39 各 16 块。块号一直编到 63 之后而不是停在那里,而 16 块扇区的尾块是这个扇区的第 15 块,不是第 3 块。

任何假设"16 个扇区"或"尾块下标是 3"的代码,在它被测过的那张卡上完美工作,在另一张上给出安静的错误结果。这跟用 26 位解析器去读 34 位凭证是同一种失败形态:不报错,只是换成一个完全不同、且完全说得通的答案。

三种不值得相信的读数

与线上的那一侧怎么对上

转储是卡片这一侧,韦根帧是线路那一侧,两者不一致的地方恰恰是要紧的地方。面板常常只存 UID 的低几个字节,或者把它按一套为另一代卡片设计的设施码布局转换一遍。当一张卡"除了某扇门哪里都能用",真正有用的对比是转储字节对帧比特,而不是两块屏幕上的两个数字。

如果你手上还有一个只能靠前几个字节判断类型的文件,文件签名那篇讲的是同一种纪律用在另一类二进制上:前几个字节是证据,扩展名不是。

相关阅读

试用 Base64 转图片工具 →