3、ChipWhisperer入门:架构、固件烧录与SPA基础
好,咱们今天来聊聊ChipWhisperer。这东西在硬件安全圈子里,基本算是人手一套的入门利器了。我当年第一次接触侧信道攻击,就是拿ChipWhisperer Lite开的刀。说实话,它把很多复杂的射频、模拟前端问题都给封装好了,让你能专注于攻击逻辑本身。
这一节,我会带你走一遍ChipWhisperer的核心架构、怎么给它烧固件、怎么捕获目标板的通信,最后再上手一个最简单的功耗分析——SPA。嗯,咱们一步步来。
3.1 ChipWhisperer架构:它到底是个啥?
ChipWhisperer本质上是一套开源的侧信道攻击与故障注入平台。它不是一个单一的工具,而是一个生态。核心硬件是那个带FPGA的板子,比如CW1173(Lite)或者CW1200(Pro)。
它的架构可以拆成三块:
- 目标板接口:用来连接你要攻击的芯片,比如AVR、ARM或者FPGA。它提供时钟、电源和通信引脚。
- 模拟采集前端:这是灵魂。它负责把目标芯片的功耗波动(通过串联电阻上的电压降)放大、滤波,然后送给ADC(模数转换器)。ChipWhisperer Lite用的是10位ADC,采样率能到20MS/s左右。
- FPGA与USB桥接:FPGA负责实时控制采样时序,把数据打包通过USB发给电脑。电脑上的Python库(cw库)再解析这些数据。
我个人习惯把ChipWhisperer理解成一个“示波器+逻辑分析仪+电源”的三合一设备,只不过它专门为侧信道攻击做了优化。
核心知识点: 你不需要自己搭运放电路,ChipWhisperer的模拟前端已经帮你做了信号调理。你只需要把目标板插上去,配置好采样率就行。
下面这张图是我画的ChipWhisperer与目标板交互的简化流程,你看一眼就明白了:
3.2 固件烧录:让目标板跑起来
拿到ChipWhisperer之后,第一件事不是抓数据,而是给目标板烧固件。ChipWhisperer套件里通常带一块目标板,比如XMEGA或者STM32F3。你得先把你的攻击代码(比如一个简单的AES加密程序)烧进去。
烧录方式有两种:
- 通过ChipWhisperer直接烧录:它自带一个编程接口,可以当调试器用。你只需要在Python脚本里调用
cw.program_target()就行。 - 用外部编程器:比如J-Link或者AVR ISP。我个人更推荐用ChipWhisperer自带的,省事。
举个例子,烧录一个AES固件到XMEGA目标板:
import chipwhisperer as cw
# 连接ChipWhisperer
scope = cw.scope()
target = cw.target(scope)
# 烧录固件
fw_path = "firmware/simpleserial-aes-CW303.hex"
cw.program_target(scope, cw.programmers.XMEGA, fw_path)
print("固件烧录完成!")
小提示: 烧录前记得检查目标板的跳线。XMEGA板子上有个VTarget跳线,如果没接好,烧录会失败。我曾经在这上面卡了半小时,后来发现是跳线帽松了。
烧录完成后,目标板就会开始运行你的程序。它通常会在串口上等待你的明文输入,然后返回密文。ChipWhisperer的Python库会自动处理这些握手协议。
3.3 捕获目标板通信:抓取功耗轨迹
固件跑起来了,接下来就是捕获。说白了,就是让ChipWhisperer在目标板执行加密操作时,同步采集它的功耗波动。
捕获流程大致如下:
- 配置采样参数:设置采样率(比如20MS/s)、采样点数(比如5000个点)、触发条件。
- 发送明文:通过串口把明文发给目标板。
- 等待触发:目标板收到明文后,会拉高一个GPIO引脚(触发信号)。ChipWhisperer检测到这个上升沿,就开始采集。
- 读取轨迹:采集完成后,把数据从FPGA的缓冲区读回电脑。
代码实现起来很简洁:
# 配置scope
scope.gain.gain = 45 # 放大倍数
scope.adc.samples = 5000 # 采样点数
scope.adc.offset = 0 # 偏移
scope.clock.clkgen_freq = 7.37e6 # 目标板时钟频率
# 捕获一条轨迹
target.simpleserial_write('p', plaintext) # 发送明文
scope.arm() # 准备触发
target.simpleserial_wait_ack() # 等待目标板响应
trace = scope.capture() # 捕获功耗轨迹
print(f"捕获到 {len(trace)} 个采样点")
注意: 触发信号的时序很关键。如果触发早了,你会抓到一堆空闲功耗;触发晚了,加密操作已经结束了。我建议你先用示波器看一下目标板的触发引脚,确认它在你想要的时间点拉高。
3.4 简单功耗分析(SPA)基础:一眼看穿操作
SPA,全称Simple Power Analysis,简单功耗分析。它不依赖统计,而是直接观察单条功耗轨迹的形状,来推断芯片内部执行了什么操作。
为什么能看出来?因为不同的指令消耗的电流不一样。比如:
- 乘法指令比加法指令功耗高。
- 条件跳转(if-else)会导致功耗轨迹出现明显的分叉。
- 查表操作(比如AES的S盒)会有一连串规律性的尖峰。
我举个例子。你看下面这条轨迹,是AES加密的第一轮:
# 绘制轨迹
import matplotlib.pyplot as plt
plt.plot(trace)
plt.xlabel("采样点")
plt.ylabel("功耗 (ADC值)")
plt.title("AES第一轮功耗轨迹")
plt.show()
你会看到一串重复的波形,每个波形对应一个字节的S盒查表操作。如果你数一下波峰的数量,正好是16个——对应AES的16字节状态矩阵。
实战经验: 我在一次测试中,发现目标芯片的SPA轨迹里多了一个波峰。后来排查发现,是固件里多了一个没必要的循环。你看,SPA不仅能用来攻击,还能用来逆向固件的执行流程。
SPA的局限性也很明显:它只能看到宏观的操作序列,看不到具体的数值。比如你能看出芯片在执行S盒查表,但看不出查的是哪个值。要提取密钥,还得靠DPA(差分功耗分析)或者CPA(相关功耗分析)。
不过,SPA是入门侧信道攻击的第一步。你想想看,如果你连功耗轨迹都抓不稳,后面的统计分析就更无从谈起了。
3.5 避坑指南:我踩过的几个坑
最后,分享几个我当年入门时踩过的坑:
- 采样率不够:如果目标板时钟是7.37MHz,你的采样率至少要到20MS/s,否则抓不到细节。我一开始用10MS/s,结果轨迹糊成一团。
- 触发信号没接:ChipWhisperer默认用目标板的触发引脚。如果你没接这根线,它永远不会开始采集。嗯,这个我犯过两次。
- 电源噪声干扰:目标板如果用USB供电,噪声会很大。我建议用外部稳压电源,或者加一个LC滤波器。
好了,这一节的内容就到这。你只要把ChipWhisperer的架构搞明白,固件烧录走一遍,再亲手抓几条轨迹看看,SPA的基础就算打牢了。