ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

OT逆向工程实战:从固件提取到协议还原的完整路径

2026/10/2 13:06:53 拓冰建站 浏览量
OT逆向工程实战:从固件提取到协议还原的完整路径 1. 议题背景与核心需求解析1.1 为什么RSAC2022突然聚焦OT逆向工程RSAC2022的议题选题我倒不意外但OT逆向工程这个题目放在以往的主流安全会议上通常会被淹没在云安全、零信任和攻防演练的洪流里。这两年情况明显变了针对工业控制系统的攻击不再只是网络边界的渗透攻击者开始深入控制器固件本身甚至直接在PLC里植入持久化后门。安全研究圈对OT设备的关注也从“扫个端口、看个版本”升级到了“拆固件、逆协议、读内存”这种偏底层的逆向工程思维。在RSAC2022的相关议题中分享者给出的数据很有说服力越来越多的OT漏洞通报是由第三方安全研究员提交的而这些漏洞几乎全部来自固件层面的逆向分析而不是传统的网络扫描。我之前在工控安全项目里也有同样的感受。甲方通常更关心资产清单和漏洞扫描结果一旦遇到供应商不再维护的老旧控制器除了换设备几乎无计可施。只有把固件摊开搞清楚它的通信逻辑和运行机制才有机会在不更换硬件的前提下评估风险、修补问题。这个议题在线下最吸引人的地方不是某个0day的披露而是一整套可复用的方法论。RSAC2022上的分享没有停留在“我能破解某品牌PLC”这种表演式的结论上而是把从固件获取、静态分析、动态调试到协议还原这条完整链路拆开讲了一遍。对长期混在OT安全一线的人来说这套方法论比单独一个漏洞利用要有价值得多。1.2 这个议题要解决什么实际问题OT设备尤其是PLC、RTU、IED这些现场控制层设备长期存在一个尴尬的情况供应商代码不透明、协议文档不公开、固件更新不规律。从安全角度看这些设备就是一个黑盒。等到攻击者已经在利用某个协议漏洞或者固件后门的时候防守方才开始到处找资料往往只能被动挨打。OT逆向工程要解决的就是把这个黑盒打开。通过提取和分析固件你能够回答以下几个实际问题设备究竟实现了哪些功能除了官方文档之外还有没有隐藏功能通信协议的具体字段和状态转换是怎样的是否存在可以被伪造或者注入的薄弱点固件里有没有硬编码的凭证、调试后门或者其他供应商自己都不愿意披露的秘密以及当固件升级后功能和安全修复到底变了什么。在RSAC2022的议题语境里这些问题的答案最终都指向资产管理、威胁检测和漏洞研判这三件实际工作。比如通过逆向还原出某个私有协议的报文格式安全团队就可以在网关或者IDS上部署对应的检测规则而不是对所有流量一律手工分析。再比如发现某个老PLC的固件里带有官方调试后门很大概率就能解释生产网里那些来源不明的异常连接。1.3 哪类人群能从中直接受益我身边很多搞IT安全的同事对OT逆向工程的第一反应是“这东西跟我的日常工作有关系吗”实际上关系比想象中要大。如果你负责的是工业互联网平台、智慧园区或者能源监控系统的安全那么底层控制器设备的固件和协议迟早是你绕不开的话题。先说清楚这个议题适合的人群大概分三类。第一类是工控安全研究员和红队人员他们需要从固件层面挖掘漏洞或者为攻击模拟准备可信的payload。第二类是ICS安全运维工程师他们不一定要自己去逆一个完整固件但至少要理解逆向报告里的结论知道协议异常检测规则是怎么来的。第三类是自动化工程师和系统集成商他们关心的是兼容性、排障和协议互通逆向工程同样可以帮你从一个不透明的第三方设备里搞清楚它到底在网络的哪一层做了什么事情。基础要求方面建议有一定嵌入式或者固件分析经验至少得看得懂汇编指令和基本的协议抓包不然直接上手Ghidra和binwalk容易劝退。不过也不要有太大心理负担实际工作中大部分分析工作可以靠半自动化的工具完成真正需要手撕汇编的场景占比没有想象中高。2. OT逆向不同于IT逆向的核心方法论2.1 硬件资源限定与实时操作系统带来分析差异很多从IT逆向转过来的人第一件事就是把OT设备当成一个性能弱化版的嵌入式Linux设备来分析。实际上这是个误区。IT设备多数基于x86架构操作系统要么是Windows要么是Linux加载器、系统调用和库函数都比较规律逆向思维是自下而上的从指令到函数、从函数到模块、从模块到系统。OT设备的形态要复杂得多。我接触过的控制器里处理器有ARM、MIPS、PPC甚至还有几个老的8位MCU操作系统可能是VxWorks、uC/OS、FreeRTOS也可能是裸机程序。有些老PLC的逻辑根本不是传统意义上的C语言或者汇编程序而是梯形图、指令表这样的IEC 61131-3代码。这些代码在编译后往往被封装在固件的一个固定数据段里由解释器或者虚拟机执行。你在反汇编里看到的可能只是一层解释循环真正的业务逻辑又是另一套指令集。这就带来一个核心差异在IT逆向里你可以通过字符串引用、导入表、动态链接等信息快速还原程序结构但在OT固件里这些辅助信息经常不存在或者被供应商有意混淆。代码和数据混在一起中断向量表可能直接落在某个奇怪地址上外设寄存器映射也不标准。分析工作更像是考古先得根据蛛丝马迹确定整个固件的布局再去判断哪里是代码、哪里是数据、哪里是配置块。还有一个硬件上的约束很多OT设备的存储和内存都很小固件分析时必须留意设备本身的地址空间和数据宽度。比如某款PLC基于16位微控制器固件里地址计算和指针操作的方式就和32位环境完全不同你用常规的ELF分析思路去解很容易得到一堆错误的反汇编结果。这不是工具不给力而是分析者没有切换到目标硬件的逻辑里。2.2 工业协议状态机是逆向的主线OT逆向工程的另一个鲜明特征是协议分析在整体工作中的权重非常高。一个PLC或者RTU真正核心的价值在于它跟外部世界的通信能力——采集传感器数据、下发控制指令、上传状态信息、响应上位机的管理命令。这些功能绝大多数通过通信协议实现。所以只要逆清楚了协议基本就逆清楚了这个设备的行为边界。传统IT协议相对规整HTTP有RFCTCP/IP有标准状态转换图。工业协议则是一团乱麻。Modbus/TCP算是相对规范的功能码和寄存器地址有公开文档但到了PROFINET、EtherNet/IP、DNP3这种协议承载在不同网络层级上状态机复杂度高部分协议字段还是私有扩展。更麻烦的是大量国内厂商生产的控制器会基于Modbus自己做一套私有扩展只在自己的配置软件里能互通。RSAC2022议题分享中讲到一个很实用的观点把协议分析当成主线不要被固件里花里胡哨的应用代码带偏。实际操作顺序是先抓包了解设备上线后的通信行为确定协议承载方式和大致字段然后再到固件里寻找对应的协议处理函数通过报文数据反查代码逻辑。这种“从网络到固件”的路径比拿到固件直接开始反汇编要高效得多。做协议状态机还原的时候建议把状态转移表画出来。这个表是后续编写检测规则和漏洞利用的基础。举个例子很多私有协议在特定状态下会不对报文合法性做严格校验理解状态机你就能判断哪些状态存在这类逻辑缺陷。2.3 安全优先级可用性永远是第一位任何一个OT安全从业者都会反复听到一句话对OT系统来说可用性高于完整性完整性高于机密性。这句话不是口号而是直接决定逆向工程方向的分水岭。在IT领域逆向的最终目标经常是“拿到更高权限”或者“读取敏感数据”。但在OT领域你做逆向工程的时候第一条红线就是不能导致目标设备崩溃或者下线。一次不当的固件写入操作、一次不兼容的调试指令都可能让产线停止运行这在真实工厂里意味着巨大的经济损失和安全事故。所以RSAC2022这个议题里也反复强调了工作环境的问题所有动态调试都要在隔离的测试环境里进行不能在真实生产网络上随便对一个在运行PLC发送伪造报文。包括固件提取也要优先选择非侵入性的手段比如通过备份文件、维护软件接口获取而不是直接拿热风枪拆flash芯片。物理提取虽然信息最完整但风险也最高GPU很容易损坏设备或者丢失出厂校准数据。在实际分析中我倾向于对固件做“一次性镜像备份”然后把镜像当作虚拟目标去分析。这样即使后续分析过程中把某些数据结构搞乱了也可以随时回到原始状态而不需要重复拆设备。这种操作方式看似简单很多人却做不到因为他们舍不得花时间搭一套完整的镜像分析环境。3. 工具链选型与准备3.1 从网口到芯片级固件获取的四个层次固件获取是OT逆向工程的第一道门槛很多项目在这一步就卡住了。不要指望每台控制器都像家用路由器一样可以从官网直接下到固件升级包。工业控制器的固件获取手段大致可以分成四个层次根据设备的安全性和可接触性来选择。第一层是网络接口获取。很多支持远程维护的设备会在维护端口或者配置软件里提供固件备份功能。工控软件工程师在给PLC做程序升级的时候实际上就已经通过软件把固件拉了一遍。你可以从供应商的组态软件安装目录、升级工具的缓存目录里找到不少有价值的固件文件这种路径安全而且无侵入。第二层是调试接口获取。JTAG、SWD、UART串口这些调试接口在很多控制器主板上都保留着。通过调试接口可以读取flash内容或者内存映射比拆芯片风险低。但需要先找到接口定义和电平标准这需要一定的硬件基础。我见过有人直接用逻辑分析仪一根线一根线去点虽然慢但在没有原理图的情况下也是可行办法。第三层是物理提取。直接拆开设备把flash芯片或者SD卡取下来用编程器读镜像。这种做法获取的数据最完整能拿到包括Bootloader、配置区和用户程序在内的全部内容。缺点是风险高芯片焊接不良或者静电损伤都可能导致设备报废甚至丢失设备序列号等唯一标识。第四层是边界最模糊的“供应链获取”包括在二手交易平台采购同型号退役设备、联系代理商要维修手册等。这更多是情报收集层面的工作但在逆向工程前期的情报准备里非常有用。RSAC2022议题里也提到二手设备上的固件往往还保留着上家单位的网络配置痕迹本身就是一个很不错的分析素材。3.2 静态分析工具Ghidra、Radare2与IDA如何选固件拿到手之后第一件事永远是确认格式。binwalk是目前最常用也最好用的固件自动识别工具能够扫描出文件系统中的压缩包、文件签名和常见固件结构。遇到binwalk识别不出来的情况可以手动看十六进制头或者用熵分析工具判断固件是否经过加密或压缩。熵值接近1.0的区块基本可以确定是加密或高压缩这时候不要浪费时间硬解先想想密钥可能藏在哪。反汇编工具的选择上我个人的经验是Ghidra优先。理由并不是IDA不好而是Ghidra对嵌入式架构的支持越来越全面而且免费开源没有授权限制。很多OT固件是冷门架构IDA对某些老式MCU支持并不好Ghidra的处理器模块反而覆盖得很广。再加上Ghidra的脚本插件生态你可以把很多重复性的固件结构分析工作自动化。Radare2适合做更底层的手工分析尤其当你需要在命令行环境下快速搜索字节模式、修补二进制的时候。它比Ghidra轻量得多启动快、资源占用低在只做定点分析的时候效率极高。缺点是学习曲线比较陡命令体系跟主流工具有很大差异需要专门花时间来适应。还要提一下专门针对固件的工具比如Firmware Analysis Toolkit和QEMU。很多分析对象是嵌入式Linux系统直接把固件跑在QEMU模拟环境里能够省去大量纯静态分析的时间。不过这要求你先把文件系统解压出来并且确认内核镜像和外设模拟的参数。一旦模拟环境跑起来你就可以用GDB远程调试固件里的关键进程这种体验和原生硬件调试差别不大。3.3 动态调试环境搭建动态调试在OT逆向里是个相对高风险高回报的环节。建好环境可以大幅提高协议逆向的效率建不好则可能损伤目标硬件。我最常用的是一个简单的硬件在环方案一个可编程电源、一块目标设备、一个串口转USB模块、一个以太网交换机、一台抓包主机。整个环境放在一个隔离的物理网段内不连生产网。如果目标设备运行的是嵌入式Linux强烈建议优先尝试串口控制台。很多设备的串口输出会暴露内核启动信息甚至会直接给你一个root shell。有了shell之后你可以在设备内部执行命令直接读取进程列表、网络连接、开放端口甚至动态修改固件里的配置。这比外部盲打报文要高效得多。对PLC这类设备动态调试的重点则放在观察协议行为上。我会在设备正常启动后用上位机软件跟它做一次完整的通信从建立TCP连接到发送读写请求全程用Wireshark抓包记录。目的不是立即分析报文格式而是给后续固件静态分析中的协议代码定位提供参照。你能够从抓包里知道哪些功能码是合法的哪些请求会产生异常响应然后把异常响应对应到固件里的某个分支逻辑上。需要注意一个关键差异OT设备的通信循环周期非常短有些PLC的扫描周期甚至不到10毫秒。在动态调试中无论模拟什么报文都要尊重它的时序约束发送速度过快会导致设备丢掉请求过慢则影响效率。合适的做法是先用设备自己的配置软件建立基线了解正常通信的报文间隔再在这个基础上调整测试报文的频率。4. 实操拆解固件提取到协议还原4.1 第一阶段获取和识别固件用一个实际做过的案例来拆解整个流程。那是一台用于小型水处理系统的RTU供应商提供的固件升级文件是一个扩展名很奇特的专有格式文件。拿到文件后第一件事先扔进binwalk扫描。binwalk扫了半天只识别出一个明显的文件头后续的偏移和大小信息都不准。遇到这种情况不要慌先用十六进制编辑器打开文件观察开头几百字节。很多专有格式的文件其实就是标准文件前面加了一个自定义头或者做了一个简单的字节置换。我在那个RTU固件里看到前几个字节是一个类似魔数的固定值后面跟着一个CRC32校验码紧接着就是标准的压缩数据段标志。用了binwalk的熵分析模式发现整个文件熵值分段非常明显前0x200字节熵值较低之后突然跳到0.95以上说明文件确实经过压缩。这种情况下用binwalk的默认签名识别不准但手动找到压缩段起始偏移后把这一段提取出来重新用binwalk解压立刻就还原出一个完整的CramFS文件系统镜像。固件识别成功的标志不是反汇编窗口能显示多少代码而是你能从文件系统里看到设备跑的什么系统、有哪些可执行文件、配置文件和Web管理页面。这个阶段很有沉浸感因为你第一次真正看到设备的内部结构哪怕只是一个文件目录树也能给后续分析提供大量线索。4.2 第二阶段定位主逻辑与网络通信模块文件系统解开之后普通应用层的分析可以用常规思路来做先看启动脚本、看init进程、看有没有Web服务、看监听端口对应的进程。但真正的OT逆向难点在固件的控制逻辑部分也就是PLC运行时程序和协议栈。如果是裸机固件或者RTOS系统整个固件就是一个大的二进制镜像没有文件系统可言。这时候就要回到Ghidra里做手工定位。我的经验是先从向量表或者入口点开始梳理确定每个异常向量跳转到哪里找主函数然后沿着中断处理函数的线索找到通信相关的代码段。另一个技巧是利用固件中残留的字符串。虽然很多厂商会做字符串表混淆但总有一些漏网的比如错误日志、版本信息、调试信息。搜索“TCP”“UDP”“Modbus”“COM”这类关键词常常能直接定位到网络协议处理函数的附近。在我分析的那个RTU固件里一个调试字符串直接把我带到了协议解析主函数的入口省了大量时间。接下来要重点分析的是模块边界。一个设备的固件通常不会只有一个主程序而是由Bootloader、操作系统内核、应用层、协议栈、配置管理等多个逻辑模块组成。在Ghidra里把每个模块的内存范围标注出来后续的交叉引用分析会清晰很多。我习惯用书签功能把每个发现的重要函数地址记下来这个过程看着零碎实际是整个逆向项目中最关键的知识积累。4.3 第三阶段动态运行与协议还原静态分析确定了协议处理代码的位置之后动态调试的作用有两个一是验证你对代码逻辑的理解二是补全静态分析中无法确定的具体报文内容。拿Modbus/TCP为例我先在抓包里确认RTU在正常工作时使用了哪些功能码然后回到Ghidra里找对应功能码的分支处理代码。通过单步调试可以看到设备接收到一个包含功能码0x03读保持寄存器的报文后会先校验从站地址再检查寄存器地址范围最后进到数据读取逻辑。这个过程中涉及到的偏移量、边界检查、异常码返回都可以和抓包里的实际响应一一对应。协议还原不只是把报文结构画出来就完了还要建立字段级别的地图。我习惯用表格记录每个字段的偏移、长度、含义和取值范围。对于有CRC校验的协议还得确认校验的算法和初始值。很多工业协议用的是CRC-16但多项式、初值、字节序各家都不一样只看文档根本没法确定只能通过多个样本报文反推。如果协议里有加密或者签名机制那工作强度会上一个台阶。很多时候加密的目的是防止用户直接篡改配置数据而不是防逆向后门。碰到这种情况优先在固件里搜索硬编码密钥很多厂商会图省事把AES密钥直接写在固件常量区。找到密钥之后整个协议内容基本全部透明。4.4 第四阶段输出可落地的成果逆向工程做得再深如果不能转化成可落地的成果对安全团队和运维团队来说价值有限。我在实际项目里通常会要求最终输出四类成果。第一类是资产画像包括设备的处理器架构、操作系统、固件版本、存储布局、通信端口和协议清单。这份画像可以直接补充到资产管理系统里比Nmap扫描结果要丰富得多。第二类是协议说明文档以时间线或者字段表的形式描述设备的通信行为标注哪些报文字段是可以用作检测特征的。第三类是检测规则根据协议特征编写Suricata或者自定义IDS插件能够在已有流量上实时发现异常。第四类是漏洞分析报告如果逆向过程中发现了安全缺陷比如硬编码账号、未授权功能码、缓冲区溢出入口点需要按照漏洞报告的标准格式记录下来并附上利用条件和修复建议。很多初学者容易忽略成果整理这一步。RSAC2022议题分享中让我印象很深的一句话是“一个只能讲出过程的逆向分析跟一个能落地的逆向分析之间差距就在于你有没有把自己的发现变成别人也能利用的规则。”这句话我后来在项目里深有体会。交付检测规则的那周客户就能在流量监控平台上看到原本完全看不见的设备访问行为这个正反馈比任何技术实现都要强烈。5. 常见问题与坑位记录5.1 固件识别失败的几类典型原因先整理几个我在固件提取中反复踩过的坑。最常见的是binwalk识别不出任何签名白折腾。原因通常有三个固件经过了加密、固件是私有容器格式、或者目标处理器是多引导架构。加密的情况会上文提过先分析熵值再找密钥。私有容器格式则可以尝试手动解析文件头拿到未压缩段或者偏移表。多引导架构则需要先确定引导入口再分段提取不能指望一把梭。第二常见的问题是解压产物不完整文件系统只有一部分。这多半因为你提取固件时的偏移和大小字段设置错了或者固件本身做了分段存储。解决办法是回到原始文件仔细检查文件尾部的填充区很多厂商会用0x00对齐每个分段这些填充字节也是判断分段边界的重要线索。第三类问题是解开文件系统之后发现核心程序是加密的应用层文件都在但主程序跑不起来。这通常意味着厂商知道固件会被轻易解包所以把核心代码单独做了加密或者加壳。面对这种情况要么从Bootloader里找解密逻辑要么通过动态调试在设备内存中直接dump解密后的代码没有捷径。5.2 千万别在真实生产设备上直接调试这条经验值得用加粗字体写三遍。任何时候都不要在运行中的生产设备上做动态调试哪怕你觉得发送一个测试报文不会影响任何东西。工业控制器不是开发板一个看似无害的写寄存器操作可能直接改变现场设备的运行参数。轻则触发设备重启重置计数器重则导致执行机构误动作引发安全事故。搭建隔离测试环境的成本并不高一个二手PLC、一个可编程逻辑控制器模拟器、一个隔离交换机就够起步了。如果确实需要分析的是某个没有替代品的大型专用控制器也一定要通过品牌方或者集成商拿到测试许可在指定场地操作。RSAC2022议题分享中提到的行业事件很多就是因为研究人员在真实设备上做测试导致生产中断最终整个企业逆向工程能力受到质疑。顺带提一个很多人忽略的细节很多设备支持通过拨码开关或者跳线切换模式进入安全模式或者Bootloader模式。如果你在测试环境里这种模式就是你的好朋友因为它能绕开一些应用层的保护机制让你直接操作底层硬件。但如果在生产设备上不小心触发了这个模式基本上等于让这台设备离线所以在操作前一定要确认设备的模式和状态。5.3 对“专有协议”的高度怀疑OT逆向中最常听到的一句话是“我们这个协议是专有的不对外开放”。实际经验告诉我所谓“专有协议”往往并没有想象中那么神秘。很多厂商为了降低开发成本会在标准协议的基础上做局部扩展比如在Modbus报文头里加一个自定义魔数或者在数据字段里塞入私有状态位。只要你对标准协议有足够的熟悉程度很快就能在白纸上看出那些非标准的痕迹。判断一个协议是不是标准协议魔改有个很实用的方法抓包后把所有报文的共同字段提取出来和已知协议族的字段定义做对比。如果TCP端口是502大概率是Modbus/TCP如果报文里出现IEC 61850的ASN.1编码特征那就是另一套体系。这类对比工作不需要写复杂脚本Wireshark内置的协议解析器加上一些查找功能就能搞定。一旦确定是私有扩展逆向的重点就要放在扩展字段上。扩展字段通常承担设备厂商自己的管理功能比如远程配置、诊断或者固件更新。这些功能往往缺少严格的权限控制而且为了实现快速开发逻辑实现的严谨程度可能不如核心通信功能。从攻击面角度看这些扩展字段比标准功能码更值得投入精力分析。6. 一点个人体会6.1 我做OT逆向时的几个习惯在反复拆过几个不同厂商的控制器之后我养成了一个习惯每拿到一个陌生设备先做一张“三表”分别是数字量输入/输出表、模拟量输入/输出表、寄存器映射表。不管最终是要找漏洞还是做兼容这张表都是后续分析的索引。很多PLC固件表面上没有文档但它的寄存器地址表一定藏在某个配置文件里把它找出来整个设备的逻辑框架就清楚了。另一个习惯是每次都记录“死路”。分析过程中经常遇到解不出来的加密段、看不出用途的配置文件、识别不了的协处理器命令。我建议不要硬耗时间把它们记下来继续往前走。很多原本理解不了的结构在分析了更多代码和报文之后会突然变得明显。逆向工程本质上是一个信息不断积累的过程前期的死路往往都是后期豁然开朗的前提。还有一个心态上的建议不要把OT逆向工程看成“破解”而是看成“理解”。我们分析的每一段固件都是一家工业设备厂商多年工程经验的结晶。静下心来把它的逻辑理顺技术上获得的满足感比单纯秀一个漏洞利用要持久得多。6.2 给新入门者的三个建议很多人问过我怎么从零开始进入OT逆向工程这个方向。我的回答通常是三个建议。第一先从IT逆向的基础课补起x86汇编、ELF结构、C语言指针、缓冲区溢出这些基础不牢后面无论用什么工具都会心虚。第二多抓工业协议的包不需要有真实设备网上可以找到很多Modbus/DNP3的公开样本数据集先从协议上建立感觉。第三找一个简单的实物比如那种几十块钱的工业继电器或者智能电表自己动手拆一台走完一遍从固件提取到协议分析的全流程。千万不要一上来就挑战大型PLC或者高端运动控制器那个复杂度很容易让人失去信心。从简单的设备起步建立正向反馈比一开始追求“高大上”的目标要重要得多。工具只是一部分真正让你成长的是面对一个不透明设备时的判断力和耐心。这两样东西只有在一次次实际的逆向过程中才能慢慢磨出来。OT逆向工程这个方向在RSAC2022的议题里只是拉开了一个序幕。我个人的感受是随着工业设备联网程度越来越高控制和通信层被攻击的频次只会增不会减。无论你是做安全研究、做运维还是做自动化集成具备一点逆向思维都能让你在面对那些“不可描述”的设备和协议时多一份底气。