电磁故障注入EMFI原理、设备选型与实战调参指南 📅 2026/8/26 3:10:02 电磁故障注入英文全称Electromagnetic Fault Injection圈子里一般直接叫EMFI。我在硬件安全评估、嵌入式安全验证这块干了十多年前几年大家谈得更多的是侧信道、远程漏洞但这几年EMFI在安全报告里的出镜率越来越高车规芯片、安全MCU、可信启动方案的评估项里基本都少不了它。一句话讲清楚EMFI在芯片运行到某个敏感操作的时候用一个瞬态的电磁脉冲去干扰芯片内部的电气状态让CPU在某个瞬间算错一步于是安全检查被跳过、固件被读出来、密钥被打出来。这个技术适合三类人一是做安全评估和渗透测试的硬件安全工程师二是在产品里做了安全防护想验证防护是否靠谱的嵌入式开发者三是对硬件攻防感兴趣、手里正好有示波器和开发板的玩家。这篇文章我把自己的实际经验原原本本走一遍从原理到设备选型从面扫描定位到参数调节最后再聊几个踩过的坑。1. 电磁故障注入的本质与适用场景1.1 为什么选电磁而不用别的注入方式先说清楚一个背景故障注入不是只有电磁一种方式。常见的还有电压毛刺Power Glitch、时钟毛刺Clock Glitch和激光注入Laser Fault Injection。这几种方法各有各的脾气做安全评估的时候不可能一把梭得看目标的情况选。电压毛刺是最早成熟的方案原理是在芯片供电管脚上叠加一个快速的电压跌落或抬升让内部逻辑在某个瞬间满足不了建立时间。问题在于它要求你能碰到目标板的电源管脚很多产品在电源走线上加了滤波电容、磁珠甚至把整体灌胶处理你根本找不到一个干净的注入点。时钟毛刺类似需要能操作时钟源或者时钟走线对现代MCU来说也是越来越难。激光注入精度最高能把故障打进芯片内部非常小的区域但设备成本高得离谱而且现在很多芯片在封装层面对激光做了防护设计。EMFI正好补了这个空档电磁脉冲能穿透普通的塑料封装和薄屏蔽层不需要物理接触只要把线圈靠近芯片就能注入。配合定位平台注入位置能做到亚毫米级实际测试中已经足够覆盖大部分目标。缺点也很明显能量转化效率低需要高压源打底而且效果受线圈设计和耦合环境影响比较大需要耐心调参。1.2 故障模型注入之后到底发生了啥很多刚开始接触EMFI的朋友会以为故障注入就是把芯片打坏其实完全不是。理想的故障注入是让芯片在一个特定的时钟边沿上算错一次然后继续运行这样安全校验的逻辑就乱了而系统本身还活着。EMFI在芯片内部做的事情有两层。物理层面脉冲电流在线圈里产生瞬态强磁场芯片内部的金属互连线在这个磁场中会感应出涡流和电动势结果就是芯片局部区域的供电电压在极短时间内被拉低或者抬升也可能直接在某个逻辑门的输出端引入一个毛刺让触发器采到错误电平。这个过程持续几十到几百纳秒非常快。数字层面最经典的故障效果是指令跳过。CPU正常执行的时候每条指令在特定的时钟周期被内核识别并执行注入产生的毛刺可能导致某个指令的识别过程发生错误于是这条指令就像从来没有存在过一样被跳过。如果跳过的指令恰好是分支判断、比较跳转这类关键指令整个控制流就完全变了。我常用的一个比喻是你弹琴的时候某个音被强行消掉后面的旋律全变样但琴本身一点没坏。理解这一点非常重要因为后面所有调参目的都是要让故障落在正确的那一条指令上而不是把整个芯片打复位。1.3 典型应用场景与评估目标我把实际评估中遇到最多的EMFI场景分成四类大家可以根据自己的需求对照。第一类是安全启动绕过。MCU或者SoC上电以后Boot ROM里的代码会先校验外部固件签名签名不对就拒绝启动。EMFI可以在签名校验那一条分支指令上打一个故障让CPU认为校验已经通过直接跳进未签名的固件。这类场景在车机、T-Box、POS机里非常常见。第二类是Flash读保护降级。很多MCU提供了RDPRead Protection之类的保护等级保护启用以后调试器无法直接读Flash。EMFI能让CPU在判断读保护等级的逻辑上出错从而绕过保护把内部固件导出来。拿到固件以后还能继续做逆向、找后门这是固件提取的前置步骤。第三类是直接固件提取。在UART bootloader或者DFU模式下注入故障跳过一些限制比如跳过等待合法握手或者校验Flash起始地址的逻辑然后通过合法下载通道把内部Flash全部读出来。第四类是密码算法的控制流绕过。比如让RSA/ECDSA验签被跳过或者让椭圆曲线点校验逻辑失效。这一场景在TEE、安全支付、车规V2X领域比较典型。实际评估当中EMFI很少单独用通常会和侧信道分析、调试接口分析、协议分析组合成一套完整方案。EMFI负责让系统出现不该出现的状态侧信道负责把密钥等秘密信息从功耗、电磁辐射里捞出来两者配合能覆盖大多数安全目标。2. 实验环境搭建与设备选型2.1 核心器件清单与选型思路先给一张最小可用平台的选型表入门阶段不用堆太多设备能把流程跑通最重要。组件作用入门推荐备注高压脉冲源产生纳秒级前沿的高压脉冲NewAE EMFA模块或自制高压MOSFET开关最关键器件决定脉冲质量电磁探针/线圈把电流转换为局部磁场1-2mm内径环形线圈2-3匝可以手工绕制定位平台移动探针到指定坐标手动三轴位移台要做自动扫描就上步进电机触发同步精确控制注入时机示波器脉冲发生器或ChipWhisperer决定成功率上限目标板被测对象STM32F407、LPC4088等开发板优先选可恢复的MCU示波器观测注入波形和触发信号100MHz带宽以上即可建议四通道高压脉冲源是整个系统的核心本质是一个高压开关用高压MOSFET把电容上充好的几百伏电压在纳秒级时间内加到线圈上。自己做的话我建议从隔离式高压模块加一颗专用高压MOSFET开始比如DE150系列这样的管子di/dt能力和耐压都要达标。成品方案里我用得最多的是ChipWhisperer-Husky的扩展FPGA控制触发时序和多路IO非常方便和示波器联动省去自己搭逻辑电路的功夫。探针方面入门阶段不需要买昂贵的磁场微探针手工绕线反而更容易理解原理。后面我专门讲线圈设计。定位平台决定了扫描效率和重复性手动三轴台几百块就能买到适合入门验证如果想做自动面扫描改成步进电机配合步进驱动器就行控制方面可以用GRBL板卡或者直接用MCU发脉冲这部分我并不建议一开始就投入太多。触发同步是决定成败的关键环节后面在3.2节展开讲。2.2 探针与线圈的设计要点线圈是EMFI里面最容易被忽视、又最影响效果的部件。同一个高压源配上不同线圈效果可能一个天一个地。我自己的入门建议是内径1.5mm左右的环形线圈用直径0.2-0.3mm的耐高压漆包线绕2-3匝引脚尽量短。绕的时候保持线圈形状稳定不要一会儿松一会儿紧。绕好之后用万用表量一下电感同一批次的线圈电感应该非常接近如果差异超过5%重新绕。线圈的口径和芯片Die的大小、封装结构有关系。口径越小磁场越集中定位精度越高但耦合效率也越低需要把高压源的输出电压提上去口径大了容易覆盖太多区域故障效果不够精确可能只产生随机复位。实际操作中我会准备几个不同口径的线圈1.0mm、1.5mm、2.0mm各绕一个先粗扫定位再用最合适的口径精打。线圈的方向同样重要。环形线圈的磁场方向沿线圈轴向而芯片内部互连线的走向是复杂分布的线圈平面平行于芯片表面还是垂直于芯片表面耦合到的敏感区域会很不一样。我会在固定的电压和延时下把线圈分别按水平和垂直方向扫一遍记录成功率选效果好的方向继续。线圈表面一定要做好绝缘高压脉冲在几百伏级别虽然能量不大但线圈和芯片距离很近的时候有放电风险。我习惯在线圈表面涂一层绝缘漆或者贴一层Kapton胶带既保护芯片也保护你的设备。2.3 定位平台与同步控制的设计定位平台看起来不起眼但直接影响重复性。手动三轴台操作简单适合单点调整但要大幅面扫描的时候手指会累到怀疑人生。我的做法是搭了一个GRBL控制的简易三轴龙门架步进电机带丝杆XY平面重复定位精度能到0.05mm左右Z轴上放探针支架。控制代码很简单发GCode坐标指令就行但要注意回程差扫描方向尽量单向不要来回往返扫。同步控制是整个EMFI系统的灵魂。故障注入窗口往往只有微秒甚至几百纳秒级别注入时机必须和目标软件运行状态对齐否则就是瞎打。最简单的同步方案是在目标固件的关键校验函数入口处拉高一个GPIO引脚把GPIO信号接到示波器和脉冲发生器的外部触发输入脉冲发生器收到上升沿后延时预设的时间然后触发高压开关。这段延时的作用是把注入点精确推进到目标指令上。实际使用中触发信号本身的抖动必须非常小。用GPIO翻转做触发要注意翻转指令到目标指令之间的指令周期是固定的不要有中断、DMA等干扰事件插进来。我见过很多新手一上来就把GPIO翻转放在安全校验代码的前一行出发点是好的但忘了关中断结果触发信号到了CPU却在处理中断注入点全乱套。更稳定一点的做法是直接在启动流程里关掉所有中断再执行一个固定时延的等待循环然后在循环末尾做GPIO翻转这样触发基准就稳定了。3. 实操流程与核心环节实现3.1 目标设备准备与预处理我把实际测试中目标板的准备流程总结成几个固定步骤你们可以直接照着操作。第一拆掉外壳和屏蔽罩确认芯片型号、封装类型找到Die中心的大概范围。QFP封装的Die通常位于封装中心偏下QFN封装的Die在封装中心位置BGA封装则在正中心。不需要做太精确定位后面面扫描会让探针自己找敏感点。第二在目标板上找出稳定的地线测试点电源管脚附近如果有电容可以在电容两端并联一个短引线测试点方便示波器观测。不要直接去戳芯片引脚容易短路。第三刷入测试固件。我常用的是一个模拟安全解锁的程序系统等待串口输入密码密码正确才进入普通功能模式同时在密码校验前把GPIO翻转作为触发信号。目标固件里会打印解锁成功或者解锁失败的串口信息用于后续判断注入效果。第四关闭看门狗把CPU主频固定关闭动态调频、动态掉电等省电机制。这些机制会引入时序抖动严重影响注入时机的一致性。第五做一个复位控制线。通过一颗小MOS管控制目标板的供电通断或者直接接复位引脚。自动重试场景下每次注入完要把目标恢复到初始状态手动按复位键完全不现实所以这一步要提前做好。3.2 面扫描快速定位芯片上的敏感区域面扫描是EMFI最有效的起步手段先用低分辨率扫一遍把芯片表面那些打了会出错的区域全部标出来然后再对感兴趣的区域加密扫描。扫描前先固定一组基础参数触发延时设在目标函数执行到一半的位置脉宽300ns左右高压80V起步探针高度0.5mm。记住扫描的目的是找敏感区域不是追求单点最优。扫描的伪代码过程大致是这样for x in x_min to x_max step 0.3mm: for y in y_min to y_max step 0.3mm: move_probe(x, y) for trial in range(10): reset_target() wait_for_trigger() # 等待目标GPIO触发 inject(delay, width, hv) # 延时后注入 output read_serial() classify(output) # 无反应/复位/失败/成功 record_map(x, y, result)分类规则我是这样定义的无反应指串口完全没有任何输出大概率是脉冲没有真正耦合进芯片复位指目标重新开始跑启动流程说明能量过猛把复位逻辑触发了解锁失败指程序跑到密码校验正常输出了失败信息说明注入没打中关键窗口成功指输出了解锁成功这是我们要的结果。把成功点记录在坐标图上理论上会看到某些区域的成功率明显高于其他地方。坐标图在脑子里生成热力图成功率高的区域往往对应芯片内部逻辑最密集、走线最靠近表面的地方。对QFP64封装的STM32来说通常Die中心侧面会有一个比较灵敏的条状区域这位置其实就是CPU核心或者总线区域。找到之后用0.1mm步进做二次细扫把敏感区域边界确定下来。3.3 参数优化注入时机、脉宽与输出电压区域找到之后接下来就是花时间最多的参数优化环节。四个最关键的参数是按重要性排序的注入时机、输出电压、脉宽、探针高度。参数典型范围初值建议详细说明注入时机延时0-2000us在目标函数执行区间内扫最敏感的参数误差容忍度往往只有几us甚至更小输出电压HV80-400V80-120V起步电压太高容易导致整个芯片复位而不是精确故障脉宽50-500ns200-300ns太宽容易重启太窄达不到干扰阈值探针高度0.2-1.5mm0.5mm越低耦合越强但放电风险也随之增加先说注入时机。把GPIO触发点放在密码校验函数入口然后用一个很细的步进去扫延时。比如从触发点开始先每5us扫一遍找到有反应的时间窗口再改成每1us甚至0.2us细扫。大多数目标在注入时机上都有一个几十微秒的敏感窗口窗口内的成功率高低起伏通常会有比较明显的一个尖峰。找到这个尖峰就成功了一半。脉宽和电压是配合使用的。我一般先用固定300ns脉宽从80V开始每次加20V看目标的行为变化。理想状态下电压从某个阈值开始出现一些指令被跳过的现象如果直接一步加大到200V以上经常会看到目标直接复位这反而说明你打得太糙。正确的思路是找到刚好能干扰、又不至于复位的最小能量点稳定性和精确性两个目标之间取平衡。探针高度也要纳入调参范围。低一些耦合效果好但低过头可能碰到芯片表面同时放电风险增加。多数情况下0.3-0.5mm是比较好的工作区间这个距离容易漂移所以机械平台一定要锁紧。3.4 故障效果判定与结果利用单次成功不算成功EMFI的复现率是一个概率问题。在参数确定之后目标成功率通常在10%-50%之间波动少数幸运的情况能到80%。这个概率已经足够支撑攻击脚本利用了思路很简单循环重试每次复位目标在同一个时间点注入然后检查是否出现成功标志。就像在一个中奖率1/10的抽奖池里反复抽只要你一直抽中奖只是时间问题。真正要提升的是把成功率从1e-6提升到10%以上剩下的事情交给自动化循环。判断成功的标准要定得很严格。我一般要求目标同时满足三个条件串口输出成功提示系统进入正常功能分支并能持续运行后续还能重复进入该状态至少一次。只看到一条串口输出就兴奋很可能只是一个偶发的概率事件后面没法利用。还有一种情况是目标在注入后进入了某种僵尸状态看起来有输出但系统不再响应任何操作这种也要排除在外。利用环节建议写一个Python脚本使用串口控制复位、触发注入、读取输出。脚本里对每次注入的结果打tag遇到成功就记录下来并停止如果连续几十次都失败可以自动调整延时参数做小范围搜索让脚本能自己爬山找最优窗口。有了这套自动循环你晚上回去睡觉第二天早上来看结果成功率数据都能导出成表。4. 常见问题与排查技巧实录4.1 触发同步问题触发同步问题是我碰到最多、也最隐蔽的问题。典型症状是成功率忽高忽低今天调好的参数明天完全失效或者在同一个参数下连续打十次前三次成功后面七次全失败。排查思路按顺序来先看触发信号本身。用示波器长时间观察GPIO触发波形看有没有毛刺、抖动、回落。如果触发信号的上升沿不干净脉冲发生器的触发点就会漂移注入窗口自然对不齐。这时候可以给触发引脚加一个RC滤波或者用逻辑分析仪内部触发代替模拟触发电平。再看目标固件的时序稳定性。中断、DMA、USB或者以太网控制器都会在后台插入大量操作这些操作会导致目标程序执行到触发点的时刻不一致进而导致固定延时对应的指令位置漂移。我之前测一个带网络协议栈的板子故障注入成功率死活上不去最后发现是网卡中断在后台反复触发关掉网络接口之后成功率立刻从3%跑到接近30%。这个坑一定要提前避开测试固件务必精简中断能关就关。4.2 重复性差、线圈老化与定位漂移重复性差的问题是硬件故障注入实验最烦人的一个。参数没变、位置没变昨天成功率高得离谱今天却一次都打不出来。我自己踩过的原因主要有三个。第一线圈老化。高压脉冲对漆包线的绝缘层是一种慢性损伤线圈工作久了之后漆包线表面会出现细微碳化、氧化导致电感量漂移和击穿电压下降。我一般会在每次实验前用LCR表量一下线圈电感和初始值对比偏差超过10%就换一只新线圈。线圈是耗材不要舍不得换。第二定位平台的机械漂移。手动平台锁紧之后用手摸一下可能就会有微小位移温度变化也会让导轨和支架产生热胀冷缩。做长时间扫描的时候我会每隔一段时间就移动探针到一个校准标记点检查坐标是否偏移。如果偏移超过0.05mm重新归零后再继续。第三目标芯片的状态问题。同一块芯片反复被故障注入内部逻辑可能出现老化或者局部损伤导致敏感区域漂移。所以实验时最好准备两三块完全相同的目标板一旦发现某块板子的成功率持续下降就换一块板子验证排除芯片个体差异造成的假象。4.3 实验安全与设备保护最后聊安全这部分容易被忽略但必须认真对待。EMFI系统里有几百伏高压电容里存储的能量虽然不大但瞬态电流很强操作不当会有触电风险。我的习惯是工作台必须绝缘操作时手上不戴金属饰品桌面不放螺丝刀等裸露金属工具高压电容在断电之后仍然可能存有电荷测试结束至少要等一分钟再碰电路最好用带放电电阻的放电棒主动放掉。目标板那边也要做保护。故障注入可能让MCU进入异常状态比如短路、过流、发热。我给目标板供电加了一个限流的直流电源把限流值设置为正常工作电流的1.5倍一旦异常就能快速断电。如果目标设备自带电池比如手表、手机主板这类测试前尽量把电池拆掉改用外部稳压电源供电电池被打坏或者鼓包会非常麻烦。另一个经验是目标板要多备几块。反复注入同一位置一定会加速芯片老化尤其是大电压和高脉宽组合长期测试之后芯片会变得迟钝敏感区域变得模糊。把一块板子当作主力调优再留一块验证板用于确认结果可以有效避免调参调了一整天最后发现目标芯片已经半废了的尴尬情况。最后分享一点我个人的体会。EMFI这套东西设备投入其实不是最大的门槛真正的门槛是建立一套稳定、可重复的触发与观测机制。很多新手一上手就追求高压、大线圈觉得能量越猛效果越好结果目标一直被复位什么信号都拿不到。我自己走了不少弯路之后才想明白精确故障注入的本质是在正确的时间、正确的地点施加刚好足够的干扰多一分是复位少一分是无用功。建议你先从低电压、窄脉宽、粗扫描开始耐心找到一个能稳定复现的故障点再围绕这个点反复打磨参数。另外现在很多研究团队把EMFI和自动搜索算法结合让程序自己去扫描延时、电压、位置组成的多维参数空间效率比手工调参高一个量级这块我后续可以单独写一篇展开聊。