第3章:比特流逆向技术入门
各位同学,今天咱们聊点硬核的——比特流逆向。说实话,这玩意儿在FPGA安全领域里,属于那种「看着简单,做起来全是坑」的技术。我入行那会儿,第一次拿到一个加密的比特流文件,愣是盯着十六进制看了三天,啥也没看出来。后来才明白,方向不对,努力白费。
3.1 比特流抓取方法
想逆向,先得有数据。比特流怎么抓?主流就两条路:JTAG和SelectMAP。我个人的习惯是,能用JTAG就用JTAG,毕竟接口通用,调试方便。但有些场景下,SelectMAP才是王道。
3.4.1 JTAG抓取
JTAG这玩意儿,说白了就是IEEE 1149.1标准定义的边界扫描接口。FPGA上电后,通过TCK、TMS、TDI、TDO这四根线,就能把配置数据读出来。嗯,这里要注意:不是所有FPGA都允许你读配置存储器。
我曾经在某个项目里,遇到一块Xilinx的Kintex-7芯片。JTAG链路上明明能识别到器件,但读配置数据时总是返回全0。折腾了两天,最后发现是芯片的Security位被置1了。说白了,厂家把读保护打开了,JTAG接口被锁死。
JTAG抓取的基本流程是这样的:
- 连接JTAG调试器(比如Xilinx Platform Cable USB)
- 识别链路上的器件IDCODE
- 切换到配置数据读取模式
- 通过SHIFT-DR状态机逐位读出比特流
代码层面,用OpenOCD或者UrJTAG都能实现。我贴一段用UrJTAG抓取的小例子:
# 初始化JTAG链
jtag newtap xc7k325t tap -irlen 6
jtag tapenable xc7k325t.tap
# 切换到配置寄存器
irscan xc7k325t.tap 0x05
drscan xc7k325t.tap 32 0x00000000
# 读取配置数据
for {set i 0} {$i < 1000} {incr i} {
drscan xc7k325t.tap 32 0x00000000
puts [format "0x%08X" $drscan_result]
}
这段代码只是示意,实际项目中,比特流长度可能是几MB甚至几十MB。你想想看,逐位读出来再拼成文件,那效率...嗯,我建议用工具自动完成。
3.4.2 SelectMAP抓取
SelectMAP是另一种配置方式,说白了就是并行接口。它比JTAG快得多,但需要更多的引脚。我记得有一次,客户要求在不影响FPGA正常工作的前提下抓取比特流。JTAG被锁了,只能用SelectMAP。
SelectMAP抓取的核心思路是:利用FPGA的回读(Readback)功能。通过CCLK、D[0:7]、CS_B、RDWR_B这些信号,把配置数据从FPGA内部读出来。
两种抓取方式的对比,我整理了个表格:
| 特性 | JTAG | SelectMAP |
|---|---|---|
| 接口引脚数 | 4根 | 10-12根 |
| 最大速度 | ~30 MHz | ~100 MHz |
| 安全性 | 易被Security位锁定 | 依赖配置模式设置 |
| 适用场景 | 调试、小规模抓取 | 批量生产、高速抓取 |
3.2 比特流解析工具介绍
数据抓到了,接下来就是解析。说实话,早期做逆向全靠手撕二进制,那叫一个痛苦。现在好了,有现成的工具可以用。我个人最常用的是Project X-Ray和icestorm。
3.2.1 Project X-Ray
Project X-Ray是Xilinx 7系列FPGA的逆向工程工具集。它把比特流里的配置数据,映射回FPGA内部的资源(LUT、BRAM、DSP等)。说白了,就是帮你把比特流「翻译」成网表。
这个工具的核心是数据库(Database)。Xilinx的比特流格式是不公开的,Project X-Ray通过大量实验,逆向出了配置位的含义。我参与过这个项目的一些早期工作,那会儿为了确定一个LUT的配置位,要反复测试几百次。
使用Project X-Ray解析比特流,基本命令如下:
# 解压比特流
xray_bitstream -f design.bit -o design.xdc
# 提取配置数据
xray_fasm -f design.xdc -o design.fasm
# 生成网表
xray_netlist -f design.fasm -o design.net
输出的.fasm文件,就是FPGA汇编格式。它描述了每个配置位的具体含义。比如:
SLICE_X0Y0.LUT_A.INIT = 0x8000
SLICE_X0Y0.FF_A.SRINIT = 0
这表示在坐标(0,0)的SLICE里,LUT_A的初始值被设为0x8000。嗯,看到这里你应该明白了,逆向的本质就是把这些配置位还原成逻辑功能。
3.2.2 icestorm
icestorm是Lattice iCE40系列FPGA的逆向工具链。相比Project X-Ray,它更轻量,也更易上手。我建议初学者先从icestorm开始练手。
icestorm的核心工具是iceunpack和icebox。前者负责解包比特流,后者负责解析配置数据。
# 解包比特流
iceunpack design.bin design.txt
# 查看配置数据
icebox_vlog -p design.txt > design.v
输出的design.v,就是一个Verilog网表文件。虽然可读性一般,但已经能看出基本的逻辑结构了。
3.3 网表提取基础原理
网表提取,说白了就是把比特流里的配置位,还原成逻辑门和触发器的连接关系。这是逆向工程中最核心的一步。
为什么会这样?因为FPGA内部的结构是固定的——LUT、FF、BRAM、DSP这些资源,通过可编程互连网络连接。比特流的作用,就是配置这些资源的功能和连接关系。
网表提取的基本流程:
- 解析配置位:从比特流中提取每个配置位的值
- 映射资源:根据配置位,确定每个LUT的查找表内容、每个FF的初始值等
- 提取互连:分析配置位,确定资源之间的连接关系
- 生成网表:输出标准格式的网表文件(如EDIF、Verilog)
我举个例子。假设一个LUT6的配置位是0x8000,那它的真值表就是:
输入: A6 A5 A4 A3 A2 A1
输出: 只有A6=1且其他为0时,输出1
功能: 等价于一个6输入与门
你看,一个简单的配置位,就能还原出一个逻辑门。整个FPGA里,这样的LUT可能有几万个。把它们全部还原出来,再连起来,就是完整的网表。
最后,我画了一张图,帮你梳理本章的知识体系:
这张图把本章的三个核心环节串起来了。从数据获取,到工具解析,再到网表提取,每一步都有对应的技术和工具。你想想看,掌握了这些,你就能从比特流里「读」出FPGA的设计了。
好了,这一章的内容就到这里。比特流逆向是个实践性很强的领域,光看理论没用。我建议你找个开发板,自己动手抓一次比特流,再用工具解析看看。遇到问题很正常,我当年也是这么过来的。
公众号:蓝海资料掘金营,微信deep3321