题目3:目标板设置——SimpleSerial协议、固件烧录、通信验证

好,到了第三个题目。前面我们把ChipWhisperer开发环境搭好了,也跑通了第一个捕获脚本。但说实话,那会儿你手里的目标板可能还是个“裸板”——没烧固件,也没确认通信是否正常。

这一章,我们就来解决这个问题。我会带你走一遍目标板的设置流程:先搞懂SimpleSerial协议是怎么回事,然后把固件烧进去,最后验证通信是否畅通。嗯,这三步走完,你的目标板才算真正“活”了。

3.1 SimpleSerial协议——侧信道攻击的“通用语言”

先聊聊SimpleSerial协议。你可能会问:为什么ChipWhisperer要用一个自己的协议?直接用UART不行吗?

其实说白了,SimpleSerial就是一套轻量级的通信约定。它定义了三件事:

  • 命令格式:主机怎么发指令给目标板
  • 响应格式:目标板怎么回数据给主机
  • 同步机制:如何保证收发双方步调一致

我个人习惯把SimpleSerial理解成“侧信道攻击的通用语言”。不管目标板是AVR、ARM还是RISC-V,只要它支持SimpleSerial,ChipWhisperer就能跟它对话。

核心命令格式:

主机发送:p\x00\x01\x02...\n(p开头,后面跟明文数据,换行结束)

目标板回复:r\x00\x01\x02...\n(r开头,后面跟密文数据,换行结束)

举个例子。假设我们要加密一个16字节的明文:

# 主机发送
p\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\n

# 目标板回复
r\x3c\x4d\x5e\x6f...\n

你看,格式非常简单。p代表“plaintext”(明文),r代表“response”(响应)。换行符\n是结束标志。

小技巧:我在项目中遇到过一个问题——目标板回复总是丢字节。后来发现是换行符没处理好。SimpleSerial要求必须用\n(0x0A),不能用\r\n。这个坑我踩过,你注意一下。

3.2 固件烧录——让目标板“开口说话”

协议搞懂了,接下来就是把支持SimpleSerial的固件烧进目标板。ChipWhisperer官方提供了现成的固件,我们直接用就行。

3.2.1 选择正确的固件

ChipWhisperer的固件放在chipwhisperer/hardware/victims/firmware/目录下。针对不同的目标板,有不同的子目录:

目标板型号 固件目录 说明
CW308T-AVR avr/ ATmega328P,最常用
CW308T-STM32F stm32f/ STM32F303,ARM Cortex-M4
CW308T-XMEGA xmega/ ATxmega128D4

我建议初学者先用AVR版本。为什么?因为AVR的SimpleSerial固件最成熟,文档也最全。我自己第一次做侧信道攻击时,就是用AVR起步的。

3.2.2 烧录步骤

烧录固件有两种方式:

  1. 通过ChipWhisperer的编程器(推荐)
  2. 通过外部编程器(比如AVR ISP)

这里我重点讲第一种,因为最方便。

# 1. 连接目标板到ChipWhisperer
# 确保跳线设置正确:VTarget、GND、编程接口

# 2. 打开ChipWhisperer的编程工具
import chipwhisperer as cw
scope = cw.scope()
target = cw.target(scope)

# 3. 烧录固件
cw.program_target(scope, cw.programmers.AVRProgrammer, 
                  "chipwhisperer/hardware/victims/firmware/avr/simpleserial-aes.hex")

烧录过程中,你会看到LED闪烁。如果一切顺利,终端会打印“Programming successful”。

注意:烧录前一定要确认目标板的供电电压。ChipWhisperer默认输出3.3V,但有些目标板需要5V。我曾经因为电压不匹配,烧坏过一块AVR芯片。嗯,从那以后我每次都会先量一下VTarget。

3.3 通信验证——确认目标板“在线”

固件烧好了,怎么知道它真的在工作?我们需要做一次通信验证。

3.3.1 手动发送测试命令

最简单的验证方式:用Python脚本发一条SimpleSerial命令,看目标板是否回复。

import chipwhisperer as cw

scope = cw.scope()
target = cw.target(scope)

# 设置通信参数
scope.io.hw_baud = 38400  # 波特率,与固件一致
target.baud = 38400

# 发送测试命令
test_plaintext = b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f'
target.simpleserial_write('p', test_plaintext)

# 读取回复
resp = target.simpleserial_read('r', 16)
print(f"收到回复: {resp.hex()}")

如果输出类似收到回复: 3c4d5e6f...,说明通信正常。如果超时或报错,那就得排查问题了。

3.3.2 常见问题排查

通信失败时,别慌。我列几个最常见的坑:

  • 波特率不匹配:固件默认38400,但有些修改过的固件可能用115200。检查一下。
  • 接线松动:TX/RX/GND三根线,缺一不可。我遇到过GND没接好,数据全乱码。
  • 固件版本不对:确认你烧的是SimpleSerial固件,不是其他测试固件。
  • 目标板没上电:这个听起来很蠢,但我真的犯过。检查LED是否亮起。

调试技巧:如果通信不稳定,可以用示波器看TX/RX引脚的波形。正常的数据帧应该清晰可见,波特率误差不超过2%。我习惯先用逻辑分析仪抓一下,确认物理层没问题,再查软件层。

3.4 本章知识体系

为了让你更直观地理解本章内容,我画了一张流程图:

目标板设置流程 理解SimpleSerial协议 烧录固件 通信验证 命令格式:p + 明文 响应格式:r + 密文 同步机制:\n结束 验证通过 → 目标板就绪 验证失败 → 排查问题

这张图把本章的三个核心环节串起来了。从左到右,先理解协议,再烧固件,最后验证通信。验证通过,目标板就绪;验证失败,回到排查环节。

3.5 实战小结

这一章的内容,说白了就是三件事:

  • SimpleSerial协议:p发明文,r收密文,\n结尾。记住这个格式就行。
  • 固件烧录:选对固件,接好线,跑program_target。注意电压和波特率。
  • 通信验证:发一条命令,看回复。不行就查接线、波特率、固件版本。

我个人觉得,通信验证这一步最容易出问题,但也最容易解决。你只要记住:先查物理层(接线、电压),再查协议层(波特率、格式),最后查固件层(版本、配置)。按这个顺序排查,90%的问题都能搞定。

嗯,目标板设置好了,接下来就可以真正开始捕获电磁辐射信号了。不过那是下一章的事,咱们先把眼前这步走扎实。


专注资料整理