第四章:比特流嗅探与重放攻击
各位同学,今天我们来聊一个非常刺激的话题——比特流嗅探与重放攻击。说白了,就是怎么用逻辑分析仪把FPGA的配置数据抓下来,然后原封不动地再发一遍,让芯片乖乖听话。
我刚开始接触这个方向时,也觉得挺不可思议的。你想想看,FPGA上电后从外部存储器读配置数据,这个过程就像在公开场合念密码——谁听到了都能记下来。嗯,这就是问题的根源。
4.1 配置数据的传输本质
FPGA的配置过程,本质上是一个串行数据流从外部存储器流向FPGA内部。以Xilinx的SPI配置模式为例,配置时钟(CCLK)和数据线(DIN)都是明文的。我用逻辑分析仪一抓,波形清清楚楚。
为什么会这样?因为FPGA厂商在设计时,优先考虑的是兼容性和配置速度。加密功能是后来才加上去的,而且很多低端型号压根不支持。我在一个物联网项目里就遇到过这种情况——客户要求低成本,选了某款国产FPGA,结果发现配置数据完全裸奔。
核心要点:只要配置数据是明文传输,嗅探和重放就是可行的。这不是漏洞,而是设计取舍。
4.2 逻辑分析仪捕获配置数据
要抓配置数据,你需要准备三样东西:
- 逻辑分析仪——采样率至少50MHz,我推荐用Saleae Logic 8或国产的梦源
- 测试夹或飞线——直接焊在FPGA的配置引脚上
- 触发条件设置——一般用CS(片选)下降沿触发
具体操作步骤是这样的:
- 找到FPGA的配置引脚:CCLK、DIN、CS、DONE等
- 用逻辑分析仪的通道夹住这些引脚
- 设置采样率为CCLK频率的4倍以上(比如CCLK是25MHz,采样率设100MHz)
- 触发条件设为CS下降沿,捕获长度设为10MB左右
- 给FPGA重新上电,开始捕获
我曾经在一个客户现场调试时,发现他们的配置时钟居然有50MHz。逻辑分析仪采样率不够,抓出来的波形全是毛刺。后来换了台200MHz的才搞定。所以这里提醒一句:采样率一定要留够余量。
小技巧:如果配置数据量太大,可以只捕获CS有效期间的数据。一般FPGA的配置比特流在几百KB到几MB之间,10MB的捕获深度足够用了。
4.3 配置时序分析
抓下来的波形怎么分析?我一般用逻辑分析仪自带的协议解析功能。以SPI模式为例,你需要关注这几个时序参数:
| 参数 | 说明 | 典型值 |
|---|---|---|
| CCLK频率 | 配置时钟速度 | 25-50 MHz |
| CS有效时间 | 片选信号低电平持续时间 | 整个配置过程 |
| 数据建立时间 | DIN相对CCLK的建立时间 | ≥ 5 ns |
| 帧头同步字 | 用于识别配置数据起始 | 0xAA995566(Xilinx) |
嗯,这里要注意。不同厂商的帧头同步字不一样。Xilinx是0xAA995566,Altera(现Intel)是0xFFFFFFFF。我当年第一次抓Altera的配置数据时,对着波形看了半天没找到同步字,后来查手册才发现人家用的是全1。
分析时序时,我习惯先把波形放大到能看到每个bit的程度,确认数据采样点是否正确。然后用协议解析器自动解码,把二进制数据导出成文件。这一步很关键——导出的数据就是完整的比特流。
4.4 比特流重放攻击原理
重放攻击的原理非常简单:你把抓下来的比特流,通过同样的配置接口再发一遍,FPGA就会重新配置成原来的逻辑功能。
你想想看,这意味着什么?
- 如果你抓到了别人的比特流,就可以复制出完全一样的FPGA功能
- 如果配置过程中有密钥交换,重放攻击可以绕过密钥验证
- 甚至可以用重放来实现"克隆"——把A设备的配置复制到B设备上
警告:重放攻击只对明文配置有效。如果比特流是加密的,重放后FPGA无法解密,配置会失败。但加密本身也有弱点,我们后面会讲到。
我在做安全评估时,曾经帮一家公司测试他们的FPGA产品。他们用了加密配置,但密钥是硬编码在代码里的。我直接抓了配置数据,然后用逻辑分析仪自带的SPI发送功能,把数据原封不动地发回去——结果FPGA正常工作了。这说明什么?说明他们的加密形同虚设,因为密钥和配置数据一起被重放了。
4.5 重放攻击实验
下面我们做一个完整的实验。假设你已经用逻辑分析仪抓到了比特流文件(比如叫capture.hex),现在要把它重放给FPGA。
实验环境:
- FPGA开发板(支持SPI配置模式)
- 逻辑分析仪(带信号发生器功能)
- PC端软件(Saleae Logic或PulseView)
实验步骤:
- 将逻辑分析仪的通道连接到FPGA的配置引脚(CCLK、DIN、CS)
- 在软件中导入capture.hex文件
- 设置信号发生器模式:CS拉低,然后按原时序发送CCLK和DIN数据
- 发送完成后拉高CS,等待DONE引脚变高
- 观察FPGA是否正常启动
代码示例(使用Saleae的Python API):
import saleae
import time
# 连接逻辑分析仪
s = saleae.Saleae()
# 读取捕获的比特流
with open('capture.hex', 'r') as f:
data = f.read().strip()
# 配置输出引脚
s.set_output('channel0', 'CCLK')
s.set_output('channel1', 'DIN')
s.set_output('channel2', 'CS')
# 发送配置数据
s.digital_write('CS', 0) # 拉低片选
time.sleep(0.001)
for bit in data:
s.digital_write('CCLK', 0)
s.digital_write('DIN', int(bit))
time.sleep(0.00002) # 50MHz时钟周期
s.digital_write('CCLK', 1)
time.sleep(0.00002)
s.digital_write('CS', 1) # 拉高片选
print("重放完成,检查DONE引脚状态")
这个代码很简单,但实际使用时要注意时序精度。逻辑分析仪的软件延时可能不够准,我建议用硬件定时器或者直接写一个简单的状态机来实现。
4.6 防御思路
讲完了攻击,我们聊聊怎么防。说实话,完全防住重放攻击很难,但可以增加攻击成本:
- 使用加密比特流——这是最直接的方法,但密钥管理要做好
- 加入设备唯一ID——配置过程中验证ID,重放的比特流ID不匹配
- 使用动态密钥——每次配置都生成不同的会话密钥
- 物理防护——用环氧树脂封装配置引脚,增加嗅探难度
我曾经帮一个客户设计过动态密钥方案:FPGA和外部存储器之间用一次一密的密钥协商,每次上电都重新生成密钥。这样即使攻击者抓到了某次配置数据,也无法用于下一次配置。嗯,这个方案成本高一些,但对于高安全要求的场景是值得的。
个人建议:如果你的产品对安全要求不高,用加密比特流就足够了。别为了追求绝对安全而过度设计,成本和复杂度往往会失控。
4.7 本章小结
比特流嗅探与重放攻击,说白了就是利用了FPGA配置过程的公开性。逻辑分析仪是主要工具,时序分析是核心技能。掌握了这些,你就能理解为什么很多FPGA产品需要加密保护。
下一章我们会深入讨论加密比特流的破解方法,包括密钥提取和侧信道分析。嗯,那才是真正有意思的部分。
公众号:蓝海资料掘金营,微信deep3321