捐赠者配置与影子配置空间
从寄存器层面看捐赠者身份到底是什么:厂商 ID 和设备 ID、子系统 ID、BAR 大小和能力列表。并说明为什么一个可信的捐赠者胜过通用捐赠者。
简短回答
捐赠者配置就是一台真实 PCIe 设备的身份。你的板卡把它写进影子配置空间,再以这个身份呈现给主机。它包含厂商 ID、设备 ID、子系统 ID、BAR 布局和能力列表。一个可信的捐赠者读起来就像正常硬件;而一个通用的、或被许多板卡共用的捐赠者,则是任何人都能枚举出来的固定特征。
本页内容10
任何程序最先读取的都是配置空间
每台 PCIe 设备都带着一小块寄存器,叫做配置空间。主机在枚举时读取它,回答三个问题:你是谁、你属于哪一类设备、你想要多大的地址空间。Windows 根据这些答案挑选驱动。而这台机器上运行的其他任何程序,也能读到同样的寄存器。这些答案是你板卡的固件提供的。所以配置空间就是板卡的公开身份——不管这些内容是你有意选定的,还是无意间留下的。
影子配置空间,以及它为什么可写
在未经修改的常规 FPGA 设计里,PCIe 硬核用综合时固定下来的数值来回应配置读取。DMA 固件在它前面用块 RAM 放了一层可写的 4 KB 覆盖层——也就是影子配置空间——改由这一层来回应。在公开的 pcileech-fpga 系列工程里,这层内容存在一个被编译进比特流的系数文件里。所以板卡的身份是数据,而不是硅片。这正是为什么固件可以围绕不同的捐赠者重新编译,而不需要换硬件。
各个字段,以及每个字段透露给观察者什么
偏移量从设备配置空间的起始处算起。最后一列才是重点。它说的不是这个字段的用途,而是别人读到它能看出什么。
| 偏移量 | 字段 | 内容 | 透露给观察者什么 |
|---|---|---|---|
| 0x00 | 厂商 ID(Vendor ID) | PCI-SIG 分配给制造商的 16 位代码 | 号称是哪家公司做的。如果是未分配的数值,或者一块自称是网卡的板子却报出某个已知 FPGA 厂商,那就是当场露馅的矛盾 |
| 0x02 | 设备 ID(Device ID) | 厂商分配给某款具体产品的 16 位代码 | 确切声称自己是哪款产品。与厂商 ID 组合起来,就对应一个具体型号——这个型号要么真实存在,要么根本没有 |
| 0x08 | 修订 ID(Revision ID) | 该型号的硅片修订版本 | 这个修订版本是否真的随该设备 ID 出货过。一个从未有产品用过的修订版本,单凭这一点就对不上 |
| 0x09-0x0B | 类代码(Class Code) | 基类、子类和编程接口 | 这属于哪一类设备。核对类代码和设备 ID 是否一致,是谁都能做的最省事的检查之一 |
| 0x10-0x27 | BAR0 至 BAR5 | 基址寄存器:设备想要几块区域、每块多大、是内存还是 I/O、是否可预取 | 真实型号会申请的内存占用量。一个 BAR0 是 4 KB 的捐赠者,配上申请其他大小的固件,就不再和它自称的型号对得上了 |
| 0x2C | 子系统厂商 ID(Subsystem Vendor ID) | 把这颗芯片做成板卡的是谁 | 这块卡是参考设计,还是某个 OEM 特定型号。在芯片厂商自家出品的板卡上,往往与厂商 ID 相同 |
| 0x2E | 子系统 ID(Subsystem ID) | 该集成商的哪个板卡变体 | 劣质固件里最常被漏抄的字段。一颗真实芯片配上空白或毫无意义的子系统 ID 组合,单凭这一点就是很强的信号 |
| 0x34 | 能力指针(Capabilities Pointer) | 能力链表中第一个条目的偏移量 | 说明设备到底有没有能力项。指针指向空处属于格式错误,正常硬件不会出现这种情况 |
| 0x40+ | 能力列表(Capability List) | 链表:电源管理、MSI 或 MSI-X、PCI Express 能力本身、厂商自定义条目 | 该型号支持哪些特性。真实设备的列表有一组特定的条目、按特定顺序排列,列表偏短或顺序错乱都对不上 |
| 0x100+ | 扩展能力(Extended Capabilities) | PCIe 扩展空间:高级错误报告、L1 电源子状态、设备序列号 | 第二块更大的暴露面,大多数人从不填写。真实型号会报出条目的地方一片空白,这本身就是差异 |
| Ext cap 0x0003 | 设备序列号(Device Serial Number) | 一个 64 位只读序列号,唯一标识一台物理设备 | 一个能给板卡打指纹的单一数值。如果两块卡报出相同的序列号,就能证明它们用的是同一份配置 |
这些行里没有哪一行本身就是一种检测手段。它们只是观察者可以免费读取的字段。一份配置的水平,取决于其中最不自洽的那个字段。
为什么可信胜过冷门
买固件的人常常要求尽可能冷门的捐赠者,理由是没人见过它。这个思路恰恰反了。没人见过的设备很惹眼,而惹眼正是你最不想要的。目标是找一个放进你这台具体机器里不会显眼的型号。采集卡适合用来直播的机器,网卡适合多接了一路网络的机器,存储类设备适合还有空闲插槽的机器。当有人翻看设备列表时没理由多看一眼,这个捐赠者才算可信。
什么样的捐赠者才可信
五点,大致按出错频率从高到低排列。只要捐赠者是一个真实型号并且被完整复制,这五点自然都能满足。
- 内部自洽
- 厂商 ID、设备 ID、修订版本、类代码和子系统 ID 组合,描述的都是同一款真实出货的产品
- 完整
- BAR 大小和能力列表与真实型号一致,而不是从模板里带出来的默认值
- 符合使用场景
- 是那种本就该出现在这类机器、这类插槽里的卡
- 不共用
- 这份配置没有同时跑在大量其他板卡上
- 仍在出货
- 是一个如今市面上还在的型号,而不是几年前就停产的
警告
为什么两个人共用一个捐赠者,比各自用一个普通的还糟
捐赠者配置只有在与众不同时才算得上指纹。而被许多板卡共用的配置,恰恰非常容易与众不同。不是因为哪个字段看起来不对,而是因为字段的这套确切组合反复出现。一旦某套组合和什么东西挂上了钩,每块带着它的卡都会继承这层关联——那些什么都没做的卡也一样。一份普通、复制完整、独一无二的配置,反而比一份被整批共用的冷门配置更难成为目标。前者是成千上万台真实设备中的一台;后者则是一个成员已知的集合。
警告
捐赠者配置做不到什么
它改变的是板卡身份在 PCIe 层的读取结果。你其余的暴露面丝毫未动。这包括辅助软件的行为、输入设备移动光标的方式,也包括显示链路、账号本身的历史,以及审核人员看一份举报报告时会看到什么。固件质量消除的只是被注意到的某一种具体方式。它不等于安全。这个领域里没人能向你保证安全,任何说能保证的卖家,只是在说你爱听的话。
买配置之前值得问的问题
这些问题的答案,比任何档位名称都更能说明问题。
- 这个捐赠者是一个真实出货过的型号,还是一组手工编辑出来的数值?
- 现在还有多少块其他卡在跑这同一份配置?
- BAR 大小和能力列表是从捐赠者那里抄来的,还是留在模板默认值上?
- 子系统 ID 组合是填好的,还是清零的?
- 这份配置是否适合它将要待的那台机器,还是只是少见而已?
- 如果这份配置将来和什么东西挂上了钩,它会怎么样——有没有重建的途径?
捐赠者常见问题
我能自己提供捐赠者设备吗?
别急着下结论,先问客服。读取一个捐赠者的配置空间需要那块实物卡,以及一台能读取它的机器。有用的是一份完整、准确的转储,而不是从商品页上抄来的三个数值。
捐赠者必须和我实际拥有的硬件一致吗?
不用,而且通常也不一致。它只需要是一个放进你这类机器里不会让人意外的型号。你是否拥有那台真实设备,对板卡怎么被读取毫无影响。
冷门的捐赠者是不是比常见的好?
本身并不是。冷门又被共用,是最糟的组合。常见又复制完整,就是个不错的选择。独一无二正是那些按订单定制的捐赠者档位存在的意义。
不重新刷写能改配置空间吗?
不能。影子空间是编译进比特流的,所以换一份配置就是换一个镜像、重新刷一次。这也是为什么改配置属于重建请求,而不是拨一下设置开关。
一份好的捐赠者配置是不是就代表我的方案安全了?
不是。它只解决一个暴露面——板卡身份在 PCIe 层的读取。软件行为、输入、显示链路和账号历史都不受它影响。
资料来源
什么样的捐赠者才算可信,是我们自己的判断。「共用配置比常见配置更糟」这个论点,同样是我们自己的判断。
- 01
- 02
继续阅读
仍然没有解决?在 Discord 提交工单
全部指南