
EMFI这个词在硬件安全圈里聊的人不少但真正上手打过USB设备的人并不多。我过去几个月一直在折腾这件事——把电磁故障注入用在各种USB外设上从USB键盘、U盘到USB转串口模块输出了不少有意思的结果。这篇文章把整个过程中踩过的坑、摸出来的参数规律、以及一套可以复用的操作方法完整记录下来给对硬件安全、固件提取和故障注入感兴趣的朋友做个参考。需要先说明这篇文章的内容请只在你自己拥有或者获得明确授权的设备上测试。故障注入会损坏芯片也会绕开设备本身的保护机制把握边界是做安全研究的基本底线。1. 为什么拿USB设备开刀选型与攻击面分析1.1 USB外设遍地都是但真正有防御的没几个只要翻一翻抽屉你大概率能找到一堆USB设备键盘、鼠标、U盘、USB HUB、USB转串口模块、指纹读取器、USB网卡。这些东西内部几乎都有一颗MCU或者桥接芯片在跑固件。最典型的就是嵌入式开发常用的USB转串口模块比如FT232R、CP2102N这类芯片大家在用的时候只会装驱动、调串口很少会去想这颗芯片里跑的固件是不是可以被篡改或者提取。从安全研究的角度看USB设备是一个被严重低估的攻击面。原因很简单它们数量巨大、更换成本低、用户不会在意坏掉一两个而且大部分设备根本没有做任何针对硬件攻击的防护。你拆开一个几十块钱的USB键盘里面的主控芯片直接裸露在PCB上没有屏蔽罩没有涂胶连调试接口都没熔断这对故障注入来说就是敞开了大门。我最初选USB设备作为EMFI目标还有一个很实际的原因USB协议本身就是极好的观察窗口。设备枚举、HID报告、批量传输、DFU升级这些行为都可以通过上位机工具实时看到。注入是否成功、芯片是在哪一步被打断的都能通过USB总线上的报文变化直接反映出来比打那些黑盒专用芯片要直观太多。1.2 USB设备身上到底有哪些可打的点站在攻击者的角度一个USB设备的攻击面可以分成三个层级。第一个层级是USB协议层面的常规问题。比如设备对HID报告描述符的解析有没有漏洞、DFU升级流程是否校验固件签名、设备是否暴露了额外的调试接口。这些属于纯软件层的攻击面不需要任何硬件设备就能测。第二个层级是芯片本身的调试接口。JTAG、SWD、以及很多芯片出厂自带的Bootloader都是潜在的入口。很多厂家在量产时并不会把调试口的访问控制关掉或者即使关了也有办法通过物理手段重新打开。第三个层级就是我们今天要聊的EMFI这种硬件层攻击。它不跟你讲协议也不管你软件里面写了多少校验逻辑而是直接从物理层面干扰芯片的运行。比如从一个比较指令跳过、让一个返回值从真变成假或者让CPU跳到一个本不该执行的代码路径上。所有基于软件实现的保护在物理攻击面前都只是一层窗户纸。对于USB设备来说EMFI最有价值的利用方式有两种。一种是绕过固件保护后把固件完整读出来做离线分析另一种是直接篡改固件实现设备功能改写。最简单直接的例子就是USB键盘通过EMFI注入跳过固件更新时的签名校验写入一份带按键记录功能的魔改固件这个思路和BadUSB是一样的但起点从“物理拆芯片读Flash”变成了“在设备正常运行流程里用电脉冲撬开一个口子”。1.3 为什么是EMFI而不是其他故障注入手段硬件故障注入并不只有电磁这一种方式。电压毛刺Voltage Glitch、时钟毛刺Clock Glitch、激光注入Laser Fault Injection都是常见的方案。但EMFI在这几个方案里是性价比和门槛之间最平衡的选项。电压毛刺和时钟毛刺需要在目标设备的电源或时钟线上做物理接触这就意味着你得先搞清楚PCB上的供电拓扑可能还要飞线碰到有保护电阻或电容滤波的板子就很麻烦。激光注入精度极高、效果最好但一台激光工作台动辄几十万而且需要精密的对焦和光路调整个人研究者很难负担。EMFI不需要直接接触芯片的任何引脚。它的原理是通过线圈产生瞬态强电磁场穿透芯片封装在内部电路上感生出干扰电流。这意味着你可以在芯片上方悬空放置探头不需要破坏PCB不需要焊接飞线甚至不用完全去掉芯片上的环氧树脂封装。同时EMFI的精度虽然不如激光但在微控制器这类低速芯片上已经足够了——一个亚毫米级的磁场线圈足以把干扰聚焦在单个芯片核心区域。所以我最终选择了EMFI作为主要手段。对于USB设备这种主控芯片结构相对简单、封装尺寸也偏大的目标EMFI足够用而且设备成本还在个人可承受范围内。2. EMFI原理与关键参数先搞清楚再上手2.1 电磁故障注入到底是怎么影响CPU的EMFI的核心原理并不复杂说穿了就是法拉第电磁感应定律。探头线圈里瞬间通过一个大电流产生一个急剧变化的磁场。这个磁场穿透芯片封装后在芯片内部所有导电路径上都会感生出电动势导致内部节点电压瞬间被拉偏进而引发逻辑翻转或者时序混乱。打个比方。你把一摞纸按顺序放在桌上正常情况下是一张一张往下处理。这时候有人在你手肘上猛地拍了一下你的手一抖可能跳过了当前这张直接去处理下面那张也有可能在同一张上重复处理更糟糕的情况下整个桌子被撞翻所有纸撒一地。EMFI在CPU里干的事就是这“拍手肘”的动作——只不过拍的位置、力度、时机都可以精确控制。从故障模型Fault Model的角度来看EMFI最常见的效应有三类。第一类是指令跳过Instruction Skip。CPU在执行某条关键指令时被打断导致这条指令不执行直接跳到下一条。如果被打断的是一条条件跳转指令程序就会往错误的方向走如果是一段循环的计数器比较就可能提前退出循环。这是EMFI攻击中最常利用的效应。第二类是位翻转Bit Flip。干扰导致某个寄存器或者内存单元中的一位从0变成1或者从1变成0。一个典型的例子是用户ID的权限位被翻转攻击者从普通用户变成了管理员。对USB设备来说如果翻转的是Flash控制器配置寄存器里的保护位固件读取保护就可能被解除。第三类是时序扰动Timing Disturbance。内部状态机或者锁相环被打乱导致通信时序错误。这种效应更多发生在有高精度时钟要求的芯片上对USB设备来说如果攻击发生在USB物理层收发器工作期间会导致枚举失败、数据包CRC错误等可观测的异常。2.2 决定成败的四个关键参数在实际操作中EMFI的效果由四个核心参数共同决定。我把它们叫做“四维控制空间”因为任何一个参数偏了注入都可能完全无效。第一个是注入电压。这个参数决定了电磁脉冲的强度直接影响感生电动势的大小。电压太低干扰能量不足以改变芯片内部逻辑电压太高芯片内部电路可能被永久击穿损坏。对于常见的微控制器有效范围一般是几百伏到两千伏之间具体要看芯片的工艺尺寸和封装形式。一颗90nm工艺的芯片可能800V就有效而一颗老式的0.35um工艺芯片可能需要到1200V以上才有明显反应。第二个是脉冲宽度。电磁脉冲作用的时间长度一般在纳秒到几百纳秒之间。脉宽过短能量可能不足以建立有效的干扰脉宽过长干扰范围太大容易把整个芯片打挂。一个通用的经验是从窄到宽逐步尝试先试试30ns左右然后逐渐加大。第三个是探头位置。这是最需要耐心调试的参数。电磁场强度随距离呈指数衰减稍微偏了几毫米效果可能就完全不同。你需要把探头悬停在芯片核心区域正上方通常距离封装表面0.5mm到2mm之间。有的芯片内部有多个独立的功能模块比如CPU核心、Flash控制器、USB收发器它们的物理位置在裸片上并不相同因此“打CPU核心”和“打Flash控制器”对应的探头位置可能不一样。第四个是触发延时。这是EMFI能实现精确攻击的关键。你需要事先选定一个可以观测的事件作为时间零点比如USB设备上电复位的瞬间、收到SETUP包的瞬间、或者选中写Flash的某个指令窗口然后设置一个从该事件到注入信号之间的延迟。注入时机直接决定CPU正在执行哪条指令也就是故障落在哪个指令上。这四个参数不是相互独立的。比如电压调高之后有效脉宽的窗口会变宽触发延时偏移一点同时改变电压又可能出现新的故障窗口。所以调试过程就是在一个四维空间里搜索能使目标效应出现的参数组合。2.3 参数调试的基本思路从崩掉到指哪打哪新手上手EMFI最容易犯的错误是一上来就追求“精确攻击”。实际上第一次做实验的目标应该很简单——先把设备弄崩。所谓的“崩掉”就是让设备出现异常行为枚举失败、设备掉线、程序跑飞。这一阶段的目的不是实现某个特定攻击效果而是确认电磁场确实作用到了芯片上并摸清基本有效的能量范围。具体做法是把探头固定在芯片上方设置一个居中的触发延时比如复位后1ms从最低电压开始每注入一次都手动复位目标设备观察是否有异常。如果整个电压扫描跑完设备都没反应先停下来检查触发信号是否真的到达了注入设备再检查探头位置是不是偏了。很多“注入无效果”的问题其实是触发没工作而不是能量不够。当你找到了能稳定让设备崩掉的参数组合接下来才进入精确定位阶段。这个阶段的目标是把触发延时在一个时间窗口内逐步扫描比如复位后的0到10ms之间每1us步进打一次记录哪些延时窗口会让设备出现什么类型的异常。结合你对固件启动流程的了解比如先配置时钟再初始化USB就能推测出哪个异常对应哪段代码。再往后才是真正的攻击。你的目标是在几毫秒的窗口里找到那一两个微妙级的“黄金窗口”让CPU在特定指令处被打断并且正好产生你想要的故障模型。这个过程很耗时但方法论是清晰的。别指望一次成功故障注入本质上是一个概率游戏你需要重复多次注入来确认成功率。3. 搭建实验环境与故障注入完整流程3.1 工具选型买现成的还是自己做目前市面上专门用来做EMFI的设备主要有ChipSHOUTER和Riscure的emFI系列。ChipSHOUTER是NewAE出品价格在一万多元人民币左右支持从100V到750V左右的电压调节脉宽可以到纳秒量级软件配合ChipWhisperer和Python脚本非常成熟是目前个人研究者入门的主流选择。Riscure的emFI Pro属于专业级设备电压更高、时序精度更好但也更贵基本是大型安全实验室和企业安全团队的配置。个人学习阶段我不建议一上来就考虑这类设备。如果你预算有限也可以自己搭一套简陋的EMFI装置。核心部件是一个高压脉冲源加一个发射线圈。比较常见的是用马克思发生器Marx Generator来产生数千伏的尖端脉冲再加上一个手工绕制的线圈。整体成本可以控制在几百到一两千元。这种方式的好处是便宜、可自定义但调试难度明显更高操作者需要更扎实的电路基础和安全意识。高压部分处理不好很容易出危险手上的静电都能让你心疼一会儿更别说上千伏的意外放电了。我个人建议如果你是第一次接触EMFI先想办法借一台ChipSHOUTER或者其他现成设备跑通整个流程。等你对参数调试和故障模型有了手感再考虑DIY也不迟。直接上DIY方案很容易把时间全部浪费在排除硬件故障上。3.2 靶机准备与触发信号设计靶机的选择有几个标准芯片封装要容易定位固件行为要可观测最好是你能通过软件方式复位和状态读取的设备。我用得最多的是几种设备基于ATmega32U4的Pro Micro兼容板网上十几块钱一块改造一下就是一个灵活的USB键盘开发平台、STM32F103/F407的USB开发板、以及各种USB转串口模块。拿到靶机之后第一件事是拆外壳把PCB露出来放到显微镜下或者用高倍手机微距镜头拍清楚芯片丝印和位置。对于带金属屏蔽罩的设备确认工作温度正常后可以考虑用热风枪吹掉屏蔽罩。我遇到过一些射频USB网卡屏蔽罩是整个焊在PCB上的不拆的话没法定位芯片EMFI的磁场也会被金属罩屏蔽掉。触发信号的设计是整个环境里最需要动脑子的部分。我的做法是用逻辑分析仪或者示波器同时监测USB的D引脚和芯片的某个GPIO。USB枚举开始的那一刻D线上会出现特定的电平变化逻辑分析仪捕获到这个事件之后输出一个TTL触发信号送到ChipSHOUTER的外部触发输入端。通过调节ChipSHOUTER里设置的延时参数就能控制注入发生在枚举过程中的任意时刻。对于有串口输出或者调试打印的目标设备那更理想。你可以让固件在关键函数执行前后往串口打印一个特定的标记字符。这时候只要把触发条件设置成“串口收到标记字符”就能实现非常精确的指令级定位。3.3 一套标准的注入扫描流程我自己跑得比较顺的一套流程是这样的。把探头装在三轴位移台上悬停在芯片正上方约1mm处。把触发源设置为每次USB设备复位后输出一个触发信号。把设备通过USB HUB连到电脑电脑上开着USB抓包工具或者Devices Tree Viewer时时观察设备状态。开始之前先做一次无注入的基线测试。确认每次复位、枚举、通信的行为都是完全一致的。如果基线就不稳定后面的注入结果就没法判断。然后是电压与脉宽粗扫描。固定触发延时为1ms从最低电压开始按固定步长增加每个参数点注入三次记录设备是否异常。这一轮的目标就是找出能让设备出现稳定异常的能量范围。找到能量范围后固定电压和脉宽开始做触发延时扫描。把延时从0慢慢加到一个目标过程结束的时间比如固件完成全部初始化在关键区间用较细的步进做微调。每次注入后都记录异常类型和时间窗口整理成一个表格。最后是对候选窗口的重复验证。一个窗口是否真正可利用要看多次注入后的是否稳定复现。成功率在30%以上的窗口才值得继续尝试构建实际攻击。4. 实例复盘对USB键盘主控的一次完整注入4.1 目标设备与前置分析我用一个具体的例子把上面的流程串起来讲。这次测试的目标是一块基于ATmega32U4的机械键盘主控也就是网上常见的国产“Pro Micro兼容板”。这块板子上面的ATmega32U4自带USB控制器所以不需要外部USB芯片直接就能被电脑识别为键盘设备。测试前的准备阶段我先把主控板的固件保护情况摸了一遍。通过USB发出DFU请求发现设备暴露了DFU接口而且没有开启读保护。这一步意味着固件本身就能直接读取和写入属于“出厂没设防”的状态对于测试EMFI流程来说非常理想。为了让测试更贴近真实攻击场景我把固件中升级流程改成了一个会检查签名的版本。也就是在固件升级时如果传入的固件包签名不正确设备会拒绝写入。这个校验逻辑实际上写在flash的bootloader区域里。测试目标就是通过EMFI让这个签名校验被跳过从而把一份修改过的固件刷进去。前置分析花了大概半小时。主要工作是读芯片手册、看板子上各个引脚的走线然后确定USB D引脚直接连到了MCU的哪只引脚上方便后面引触发信号。这个过程不需要太深入USB枚举时序这种公开资料已经足够。4.2 扫描参数空间与定位故障窗口环境搭好后开始扫描。我把触发信号设置在USB复位后大约200us的时刻因为固件在收到复位后会先做一些硬件初始化然后进入主循环等待USB枚举签名校验逻辑在枚举成功后开始执行。第一次粗扫描电压从100V开始以50V为步长加到500V。脉宽固定为70ns。结果在300V以下时设备基本无反应300V到400V出现了偶发的枚举失败表现为电脑上键盘设备消失又出现450V以上设备开始频繁死机需要重新插拔USB才能恢复。基于粗扫描结果我把电压固定到350V开始扫描触发延时。这一步是细功夫。从复位后0到10ms的范围每100us打一次每个点打10发记录每次注入后设备的状态。几轮下来我整理了一张表在延时2.3ms到2.5ms之间设备偶尔会枚举为正常键盘的设备描述符但HID报告中出现了和固件默认行为不一致的按键映射。这个异常非常关键。正常固件在签名校验失败的情况下不会进入应用区运行更不会出现自定义按键映射。出现这个现象说明校验有可能被跳过了设备在运行我准备的那份未通过校验的固件。继续在这个窗口附近做精扫延时步进改成10us电压微调在330V到370V之间。最终找到一个比较稳定的注入点延时在2.34ms附近、电压350V、脉宽70ns时注入成功率约为35%。也就是说每注入大概3次就有一次能让设备加载未经校验的固件。4.3 验证注入效果并继续推进找到这个窗口之后需要验证注入效果确实是“跳过了签名校验”而不是某种随机的内存损坏。我的验证方法是准备一份修改过的固件里面把键盘的一个按键映射改掉然后通过DFU接口发起升级在升级过程中精确注入。每当注入成功升级流程会继续往下走然后返回“成功”设备重新枚举后按键映射变成了修改后的值。如果注入失败升级流程会停在校验步骤并返回错误设备保持原有固件。这个验证一共做了三轮每轮重复20次成功率分别稳定在30%到40%之间。在成功的注入中设备的重枚举行为完全正常没有出现死机、无法识别、烧毁等问题。确认这就是我们想要的故障模型而不是瞎猫撞到死耗子的偶尔异常。通过这轮完整的注入复现我现在可以比较明确地说这颗主控芯片的USB升级保护在EMFI面前基本没有防护能力。一个成本大概两三千元的EMFI装置就能稳定绕过签名校验并写入任意固件。对于产品安全评估来说这就是一个需要提前考虑的风险。5. 常见问题与排查技巧实录5.1 问题速查表从现象到根因实际操作中遇到的问题基本可以归纳成下面几种现象。整理成速查表方便对照。现象最可能的原因建议排查顺序注入后设备完全无反应触发信号没到达注入设备能量太低探头位置偏移1. 用示波器检查触发线 2. 提高电压 3. 重新校准探头位置设备每次都直接死机需要重新上电注入能量过高脉宽太宽打在复位电路上1. 降低电压 2. 缩短脉宽 3. 把探头往芯片中心偏移一点效果时好时坏很难稳定复现触发延时抖动探头固定不牢目标设备时序波动1. 用更稳的触发源 2. 加固探头支架 3. 大幅增加重复次数统计设备正常枚举但看不到目标故障效应故障模型不对目标指令不在当前扫描窗口1. 换更大的延时扫描范围 2. 尝试改脉宽和电压组合芯片发热严重甚至冒烟注入能量持续过高芯片内部已损坏立即断电换新设备降低电压重试第五种情况比较极端但也不是没见过。有一次我连续在同一个位置用高电压打了上百次芯片直接罢工量供电电压正常但振荡器不工作应该是内部时钟电路被永久损坏了。所以建议每打完一轮就检查一下目标设备的工作温度如果摸上去明显烫手就该停下来降温或者降低能量了。5.2 想提高成功率这几条经验直接抄几条从实战里磨出来的经验常规文档里基本不会写。第一先找一个“容易崩”的窗口来校准位置而不是直接找目标窗口。你可以把触发延时设到复位瞬间或者BootRom执行阶段这个阶段任何干扰都会导致设备不启动。如果连这个阶段都打不出现象说明探头位置或者触发链路有问题先解决基础问题再说。第二四维参数空间太大了别傻乎乎地四维一起扫。我的习惯是固定电压和脉宽花大部分时间扫触发延时。因为触发延时直接对应到CPU执行位置这是故障模型是否成立的根因。只有当延时扫描完全找不到任何异常时才回去调整电压或脉宽。第三注意芯片封装的影响。QFN封装的芯片比TQFP封装的更容易受到EMFI影响因为引脚短、裸片离封装表面更近。对QFN芯片可以保持探头距离更近、电压更低对QFP封装需要稍微加大能量。别拿同一个参数套所有芯片。第四监视设备状态的方式要多通道并行。不要只靠电脑端看USB是否识别同时又用示波器看芯片的IO口电平双通道监督能更快定位异常。比如设备死机时Power LED是常亮还是闪灭、USB D的电平是拉高还是悬空这些小细节都能帮你判断CPU跑飞到了哪个阶段。第五注入前给设备做一次完整的状态快照。包括当前固件版本、USB描述符、配置信息、串口输出基线。这样在注入后定位“哪里变了”会非常快。没有这个基线你连异常是什么时候引入的都说不清楚。第六记录所有参数不要凭感觉。我每次实验都会建一个记录文件包含日期、设备编号、探头坐标、电压、脉宽、触发延时、注入次数、成功率。后期如果想复现或者调参数没有完整记录就等于重新做实验。写在最后的实话做了这么多轮EMFI测试之后我最大的体会是很多USB设备的安全边界其实比厂商宣称的要脆弱得多。一个简单的电磁脉冲就能让精心设计的签名校验、固件加密、读保护全部形同虚设。倒不是说这些保护完全没用而是很多产品的实现者低估了物理攻击的威胁把所有的防护都押在了软件层。我也建议刚接触这个领域的朋友不用一上来就攒昂贵设备。先把USB协议、MCU启动流程、Flash保护机制这些基本功打扎实用简单设备跑通一个完整流程再去追求器件参数和高成功率。EMFI这门活调试环节占了大头真正通电打脉冲的时间可能只有一成。方法论建立起来了工具反而是后话。