第三章:JTAG接口与调试——破解FPGA的第一道门

JTAG,说白了就是FPGA的“后门”。

我做了这么多年硬件安全,见过太多人把精力花在算法加密上,结果JTAG接口就那么敞开着。你想想看,这就像你家装了最贵的防盗门,结果窗户没关。JTAG就是那个窗户。

3.1 JTAG协议基础——别被那些引脚吓到

JTAG全称是Joint Test Action Group,最初是为了测试PCB板级连接用的。但后来,它成了FPGA调试和配置的标配接口。

标准的JTAG接口只需要4根线(加上地线就是5根):

信号 全称 方向 作用
TCK Test Clock 输入 时钟信号,所有操作同步于此
TMS Test Mode Select 输入 控制TAP状态机跳转
TDI Test Data In 输入 数据串行输入
TDO Test Data Out 输出 数据串行输出

嗯,这里要注意:TCK是独立的时钟,跟FPGA的主时钟没关系。我见过有人试图用FPGA内部时钟来驱动JTAG,结果死活连不上——这是两个完全独立的时钟域。

核心要点:JTAG是串行协议,所有数据都是一位一位通过TDI送进去,从TDO读出来的。速度不快,但足够用了。

3.2 TAP控制器状态机——JTAG的大脑

TAP(Test Access Port)控制器是一个16状态的状态机。你可能会问:为什么需要这么多状态?

其实很简单:JTAG要干三件事——扫描指令、扫描数据、还有复位。每个操作都需要对应的状态。

我习惯把TAP状态机分成三个功能区:

  • 指令扫描区:从Shift-IR到Update-IR,用来加载指令
  • 数据扫描区:从Shift-DR到Update-DR,用来读写数据
  • 复位区:Test-Logic-Reset,强制回到初始状态

记得有一次,我在逆向一个Xilinx的FPGA时,发现它的TAP状态机被修改过——某些状态跳转被硬件屏蔽了。这就是一种常见的防破解手段。但说实话,只要你能控制TCK和TMS,总能找到绕过的方法。

实战技巧:如果你用逻辑分析仪抓JTAG信号,重点关注TMS的跳变序列。只要摸清了TMS的规律,你就能复现任何JTAG操作。

3.3 通过JTAG读取/写入FPGA寄存器

这是JTAG逆向的核心操作。说白了,就是通过JTAG链访问FPGA内部的寄存器。

每个支持JTAG的器件内部都有一个指令寄存器(IR)和多个数据寄存器(DR)。你通过TDI送指令,告诉TAP你想操作哪个寄存器,然后再送数据。

常见的JTAG指令(以Xilinx为例):

指令 二进制码 功能
BYPASS 111111 旁路当前器件
SAMPLE/PRELOAD 000001 采样引脚状态
EXTEST 000000 外部测试
IDCODE 001001 读取器件ID
CFG_IN 000101 配置数据输入
JSTART 001100 启动FPGA

我曾经在破解一块Altera的Cyclone IV时,发现它的IDCODE被改成了全0。这明显是故意的——让你连器件都识别不了。但办法总比困难多,我直接暴力扫描所有可能的IDCODE,最终还是找到了正确的值。

警告:通过JTAG写入寄存器时,一定要确认当前状态。我曾经在Shift-DR状态下误发了TMS信号,导致状态机跳到了未知状态,FPGA直接死机了。解决办法?只能断电重启。

3.4 Xilinx iMPACT工具使用

iMPACT是Xilinx ISE套件里的老牌工具,虽然Vivado已经取代了ISE,但iMPACT在逆向分析中依然好用。

我个人习惯用命令行模式,因为GUI太慢了。常用的命令:

# 检测JTAG链上的器件
impact -batch detect

# 读取器件IDCODE
impact -batch getid

# 读取配置数据(bitstream)
impact -batch read -p 1 -o dump.bit

# 写入配置数据
impact -batch program -p 1 -f mybit.bit

嗯,这里有个坑:iMPACT默认只读取配置数据的前面一部分。如果你想完整dump整个bitstream,需要指定长度参数。我一般用0xFFFFFFF,反正读多了也没事,读少了就麻烦了。

逆向要点:用iMPACT读取bitstream时,注意观察TDO上的数据。如果发现数据全是0或全是1,说明器件可能被加密了,或者JTAG链被断开了。

3.5 Altera Quartus Programmer工具使用

Quartus Programmer是Altera(现在是Intel)的编程工具。跟iMPACT类似,它也支持命令行操作。

常用的命令:

# 检测JTAG链
quartus_pgm -c 1 --auto

# 读取器件信息
quartus_pgm -c 1 --read_csr

# 编程SRAM对象文件
quartus_pgm -c 1 -m jtag -o p;myfile.sof

# 读取配置数据
quartus_pgm -c 1 --read_data 0x000000 0x100000 -o dump.rpd

我记得有一次,客户拿来一块Altera的板子,说JTAG连不上。我一看,Quartus Programmer报错“No device detected”。用示波器量TCK和TMS,信号正常。最后发现是TDO引脚被拉低了——有人故意在TDO上接了个下拉电阻。去掉电阻后,一切正常。

避坑指南:我曾经在调试一块加密的Altera FPGA时,发现Quartus Programmer能识别器件,但无法读取配置数据。后来才知道,Altera的加密方案会把配置数据通过AES加密后再存储。即使你读出来了,没有密钥也是白搭。

3.6 JTAG安全防护与绕过思路

既然JTAG是后门,那厂商自然会想办法堵上。常见的防护手段有:

  • 熔丝位:烧断JTAG使能引脚,永久禁用JTAG
  • 密钥验证:JTAG操作前需要输入密码
  • 状态机修改:改变TAP状态机的跳转逻辑
  • 信号干扰:在TCK或TMS上叠加噪声

但说实话,没有绝对安全的防护。熔丝位可以用FIB(聚焦离子束)修复,密钥验证可以暴力破解或侧信道攻击,状态机修改可以通过逆向TAP逻辑来还原。

你想想看,只要物理上能接触到JTAG引脚,就总有办法。真正的安全,是把密钥和敏感数据放在FPGA内部,而不是依赖JTAG接口本身。

核心观点:JTAG是FPGA逆向的起点,但不是终点。掌握了JTAG,你就拿到了进入FPGA内部世界的钥匙。但门后面有什么,还得靠你的逆向功底。

JTAG接口与调试知识体系 JTAG接口与调试 JTAG协议基础 4线接口:TCK/TMS/TDI/TDO 串行协议,独立时钟域 边界扫描与配置功能 TAP控制器状态机 16状态状态机 指令扫描区/数据扫描区/复位区 TMS控制状态跳转 寄存器读写操作 指令寄存器(IR) + 数据寄存器(DR) BYPASS/IDCODE/CFG_IN等指令 串行数据移位操作 Xilinx iMPACT工具 命令行模式:detect/getid/read/program 读取/写入bitstream 注意加密检测与长度参数 Altera Quartus Programmer 命令行:auto/read_csr/program/read_data SRAM对象文件(.sof)编程 AES加密配置数据读取 JTAG是FPGA逆向的起点,但不是终点

个人经验:我建议你在做JTAG逆向时,先准备好逻辑分析仪和示波器。很多时候,工具报的错跟实际问题是两码事。亲眼看到波形,心里才有底。

专注资料整理