REA驱动的某川PLC私有协议-逆向分析实战"

admin 2026-10-16 13:37:14 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

REA驱动的某川PLC私有协议-逆向分析实战

原创

ic3blac4
ic3blac4

ChaMd5安全团队

2026年10月14日 08:00
辽宁

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

诚招web、re、crypto、pwn、misc、合约方向的师傅,长期招新IOT+Car+工控+样本分析多个组招人有意向的师傅请联系邮箱 [email protected](带上简历和想加入的小组)

1 前言

PLC是工业控制系统的\"大脑\",而上位机编程软件,是攻击者攻击控制器的第一要素。要评估风险,第一步就是把它与控制器之间的通信面摸清楚——尤其是那种没有文档、没有 SDK、没有编程语言绑定的私有协议。

本文的研究对象,是国产某川新发布的中大型PLC的上位机软件IFA与配套仿真控制器之间的私有通信协议。它承载着工程下载、状态查询、运行控制等敏感操作。

笔者此前在CODESYS生态做过较长研究:自2021年起分析CODESYS V2相关产品并发现数十个漏洞,提交厂商后经修复发布;此后又系统梳理 CODESYS V3通信协议的授权机制与漏洞挖掘方法。这些工作沉淀出一条经验:工业协议里的\"私有\",往往只是包装。

而这一次多了一个新变量——REA(Reverse Engineer Anything)。2026年10月,它登上GitHub Trending榜首,公开报道记录其单日新增约3万star,版本号一周内由v4.0连发至v6.0。但它的公开演示大多集中在可自由运行、可反复试错的软目标(Electron 应用、老游戏逻辑重建)。

于是问题被推到台前:把这类工具用到\"不能随意试错、符号常被剥离、且带商业保护\"的工业上位机上,它还能干活吗?

本文给出的答案是:能,而且干得比预想的多。 从\"不知道这是什么协议\"到\"能把它停掉再拉起来\",这套协议的逆向工作几乎全部由 REA 完成;人唯一不可替代的动作,是在组态软件里按了一下\"停止\"、再按了一下\"启动\"。

2 REA是什么

REA 是一层基于 MCP(Model Context Protocol) 的逆向工程编排层。它本身不做反汇编,而是把Ghidra、IDA、Hopper、JADX、Binwalk 等分析引擎统一封装为133个可编排工具,覆盖原生PE/ELF、.NET 托管程序集、Electron/JavaScript、Android APK、固件镜像与各类归档包。

对本文而言,它的两条纪律最关键:

  1. 定性优先——先回答\"这是什么东西\",而不是一头扎进字节;
  2. 证据分级——每条结论区分observation(观察)/ inference(推断)/ unknown(未知),保留证据与不确定性边界。

后者与笔者一贯坚持的\"诚实分级\"(CONFIRMED / INFERRED / OPEN)天然一致。文中每个结论也都按此标注。

3. REA干了哪些

与其罗列\"工具能做什么\",不如把研究拆成环节,逐条核对谁在做。如下表所示。

研究环节 REA 做了什么 人类做了什么
协议栈身份识别 检索符号,秒级命中 Cmp\* 组件名与 .cpp 源码路径 —
报文格式还原 反编译 PDU 解析逻辑,读出四层嵌套与逐字段偏移 —
载荷编码识别 顺符号链定点反编译,确认 IBTag = LEB128 变长编码 —
会话流程还原 静态还原帧构造顺序,与真实抓包逐帧对照 提供抓包环境
命令字表提取 扫34个 sendRequest 调用点,全量导出命令字 —
校验字段推导 定位CRC32调用位置与输入范围,导出待验证假设 脚本暴力拟合验证
启停方向裁决 从命令字表抽出候选命令对 cmd=0x11 / 0x10 按一下\"停止\"、再按一下\"启动\"
客户端实现 依结论产出纯 Python 启停客户端,实测生效 —

一句话结论:读懂这套私有协议,REA承担了全部逆向工作;人唯一不可替代的贡献,是提供真实流量、并按几下启停按钮给出真值。

第一步:协议栈身份识别

传统做法是\"对着字节猜格式\"。笔者的做法是先解决一个更便宜的问题:这到底是什么协议栈?

用REA打开上位机的原生PE后,检索通信相关符号,直接命中如下特征串:

CmpGwClientImpl.cpp
CmpGateway / CmpChannelClient / CmpRouter / CmpBlkDrvTcp
<厂商>CommDriver::<协议>ChannelConnect

以及一个版本字符串:1.2.heads/V2R1C00B18

这些不是\"推测出来的格式\",而是反编译后直接读到的符号名与源码路径——连原始工程的 .cpp 文件名都没有抹除。

结论已经清晰:该PL 的通信栈并非自研私有协议,而是基于CODESYS通信栈构建,厂商在其上做了一层适配封装。证据等级:CONFIRMED(静态观察,符号名与源码路径直接命中)。

这一步带来两个直接收益:

其一,攻击面从\"未知\"变成\"已知\"。 CODESYS通信栈是被公开研究多年的对象,其服务组划分、认证机制与已知漏洞类型都有公开资料。确认同源后,分析可以站在既有研究之上。

其二,既有认知可以直接迁移。 笔者对CODESYS V3 通信流程的掌握,在后续章节的会话流程还原中几乎逐条对上。

从安全设计角度看,这里也暴露一个常见误区:许多厂商把\"没公开文档\"等同于\"安全\"。 若底层复用的是公开协议栈,那么\"私有\"只是包装——真正的安全边界并没有因为\"不公开\"而扩大一丝。

第二步:协议格式

REA 反编译PDU解析逻辑后,一个完整数据包(剥离 TCP 头)呈现出清晰的四层嵌套。如下图为以一条状态查询帧为例的完整报文格式与字节偏移。

报文格式四层嵌套

  • 第一层 Frame:u32 LE magic = 0xE8170100(线路字节 00 01 17 E8)+ 整帧总长;
  • 第二层 Envelope:外层固定头 + 路由标签(请求方 / 响应方的端口 + IP)+ ftype / ctrl + 会话模式号 mode(由服务器分配)+ seq / ack + inner\_len + nonce;
  • 第三层 InnerPDU:16字节定长头,svc位于inner+6、cmd位于 inner+8、handle位于 inner+10;
  • 第四层 IBTag:[tag\_id][len][data]依次排列的键值流。

其中有两个关键点,都是靠REA定点反编译坐实的:

① svc / cmd 的偏移不能凭直觉。 svc在 inner+6、cmd 在inner+8,不是 +8 与 +10。偏移写错一个,服务号与命令号会整体错位,方向判断与命令语义全部混乱。笔者的做法是用已知语义的帧(如登录帧)反推偏移。

② 载荷是LEB128变长编码。顺符号链下钻到 IBTagReaderMoveNext的解码循环,and 0x7F / shl 7 / or 正是 LEB128(varint)的标准实现指纹。据此确认tag\_id与len均为变长编码。若按定长解析,服务器会直接返回\"坏参数\"——这正是许多逆向\"看起来对、真机不认\"的典型原因。

信封尾部的 4 字节 nonce 字段,第一眼像是完整性校验。经暴力拟合确认nonce = CRC32(inner),并且用对照实验验证——修改内层字段、重算CRC32后回填,服务器照收。结论明确:它只防传输错误,不防篡改。 顺带一条方法论提醒:该字段名为 \"nonce\",容易被误认为承担抗重放职责;把字段名当作功能说明,是协议逆向中最常见的误判来源之一。

第三步:完整通信流程

工业协议中\"先建立会话、再进行业务操作\"是通用设计。在分析一套新协议时,第一步不是急着发业务命令,而是把真实客户端的会话起始帧逐帧列全。整理后得到下图所示的五个阶段。

私有协议完整通信流程

  1. 链路协商:客户端发送 ftype=0xC3 协商帧,服务器回复 ftype=0x83,其中携带服务器分配的会话模式号mode;
  2. 会话注册与登录:svc=1 cmd=1 建立初始上下文 → cmd=9 交换运行参数 → cmd=2 登录,服务器在响应尾部返回会话句柄 handle;
  3. 参数协商循环:svc=1 cmd=1 + cmd=9 重复三轮;
  4. 应用附着:svc=2 cmd=0x59,附着到应用服务;
  5. 业务阶段:至此才可发送svc=2 的业务命令(状态查询、启停控制)。

把这条流程与笔者前作写过的CODESYS V3流程对照,两者在阶段划分与令牌传递方式上高度对应:

阶段 CODESYS V3(笔者前作) 本协议
① 通道建立 CHOPEN → channel\_id ftype=0xC3 / 0x83 协商 → mode
② 会话创建 创建会话 → session\_id svc=1 cmd=1 会话注册
③ 参数 / 挑战 获取 challenge svc=1 cmd=9 参数协商
④ 身份登录 授权登录(用户名 + 密码) svc=1 cmd=2 登录 → handle
⑤ 应用登录 应用登录 → op\_key svc=2 cmd=0x59 附着应用服务
⑥ 业务报文 业务服务组报文 svc=2 业务命令

这个\"五阶段\"并非本文的新发现,而是CODESYS通信栈的标准会话流程;它的价值在于印证——一套被包装成\"私有\"的协议,其会话模型与公开协议栈几乎逐条对应。前序章节底层是CODESYS V3协议栈的判断,在这里得到了流程级的印证。

顺带记一个坑:中途跳过第 3、4 步直接发 svc=2 业务命令,服务器会统一返回错误码28并踢掉会话。笔者曾排除多个方向——命令码写错、需要双会话、Tag编码不对、乃至需要加密升级(全量抓包中 0 条升级帧)。真因是最简单的那个:会话前置没有走完。 当出现\"参数都对、却整族被拒\"时,问题通常不在命令本身,而在前置流程。

第四步:启停攻击

拿到应用层访问权后,剩下一个必须靠真值裁决的问题:哪个命令是\"启动\"、哪个是\"停止\"?

REA已经把答案的一半摆到桌面上:扫过上位机里34个 sendRequest 调用点后,命令字表里有一对高度可疑的候选——载荷逐字节完全相同、仅命令码不同:

svc=2 cmd=0x11   payload = 81 01 88 00 11 84 80 00 f8 b4 ef af   → 停止
svc=2 cmd=0x10   payload = 81 01 88 00 11 84 80 00 f8 b4 ef af   → 启动

典型的 Start / Stop 命令对。证据等级:CONFIRMED(抓包观察,载荷一致仅命令码不同)。

此步骤需要人类介入告知REA操作,REA抓取报文即可做全面分析:

整理后见下表所示。

命令 svc cmd(十六进制 / 十进制) 旁证
停止 2 0x11 / 17 点击后状态字节 01 → 02
启动 2 0x10 / 16 点击后状态字节 02 → 01
状态查询 2 0x14 / 20 应答 Tag 0x82 第 4 字节

这一步,就是人类在这项研究里不可替代贡献。 其余功夫——包括找出这一对候选命令——都由REA完成。

第五步:实测验证

按上述结论,笔者用纯Python标准库写了一个单文件客户端:构造帧 → 正确重算 nonce → 按序完成会话建立 → 发送业务命令。全程不引用厂商任何DLL / SDK。在授权仿真环境中实测,输出如下所示。

从协议身份识别到控制器启停控制的完整闭环,到此打通。 证据等级:CONFIRMED(动态验证,仿真环境实测)。

需要说明的是,本实现仅用于授权环境下的安全验证,旨在验证协议是否存在未授权控制风险,不作为攻击工具。

IFA\_PLC\_ATTACK

协议安全风险分析

综合静态分析与动态验证,该协议在设计上存在如下风险,整理后见下表所示。

# 风险 具体表现
1 会话建立无认证 无凭据、无证书,\"登录\"仅为固定字节握手动作,重放即可获得合法会话
2 握手可重放 协商帧载荷逐字节恒定,\"认证\"退化为\"知道模板\"
3 完整性校验无效 nonce = CRC32(inner),无密钥,改帧后重算即通过(已实测)
4 全流量明文 未观察到任何加密升级帧;工程文件明文传输,可嗅探、可替换
5 控制命令无授权分级 只读查询与写操作(启停)同权限,一旦建立会话即\"一权通吃\"
6 无速率 / 并发限制 未观察到对连接数或请求频率的任何限制
7 二进制指纹泄露 符号名、源码路径、版本串未剥离,直接暴露底层协议栈身份

在攻击路径上,这些风险并非孤立点,而是一条链:端口可达 → 建立会话(无需认证)→ 完成应用附着 → 发送启停命令。任何能访问业务端口的主体,都可以在不持有任何凭据的情况下,完成对控制器运行状态的控制。

需要特别指出的是:上述问题并非该厂商独有。由于协议底层复用CODESYS通信栈,同类问题在CODESYS生态的其他产品中同样需要关注;更广义地看,Modbus、S7Comm等经典工业协议也普遍建立在\"网络可达即可信\"的假设之上。这更多是一个行业性的历史遗留问题。

防护建议

厂商层面:

  • 会话认证:在会话建立阶段引入随机挑战值(challenge)与凭据校验,避免\"固定模板即认证\"的可重放设计;
  • 完整性校验:将无密钥的CRC32替换为带密钥的HMAC-SHA256;
  • 通信加密:CODESYS通信栈本身具备加密通道能力,但默认未启用——建议出厂配置中强制开启;
  • 授权分级:只读查询与控制类写操作权限分离,避免一权通吃;
  • 二进制瘦身:发布前剥离符号名与源码路径,减少协议栈指纹泄露。

用户层面:

  • 网络隔离:工控网络与办公网、互联网严格隔离,做好纵深防御;
  • 最小可达:通过防火墙/访问控制仅放行必要主机访问业务端口;
  • 远程访问加固:确需远程时采用安全VPN,并做好访问审计;
  • 关注补丁:关注厂商安全通告,测试后升级受影响产品。

REA在工控安全研究中的价值

一句话:这次研究里,读懂私有协议的活儿几乎全是REA干的,人类只按了几个按钮。

它能用在哪些地方:

  • 上位机 PE(组态软件、通信客户端、授权模块)是REA的舒适区——协议栈识别、报文格式还原、命令字提取、调用契约发现,基本都在数条编排内完成;
  • 尤其值得注意的是黑盒抓包摸不到的\"调用契约\":隐藏参数、返回值为void、运行模式标志、结构体的精确偏移——这些只有静态反编译能给出,而REA把它们的获取成本压得很低。这也是\"能调通/调不通\"的分水岭;
  • 它同时是\"定性加速器\":本次第一步就命中Cmp\* 符号,\"这是什么协议栈\"这个最贵的问题被一次检索解决,后续分析直接站在既有研究之上。

边界也要说清楚:

  1. REA不是反汇编器,能力取决于所接入的引擎(本次为 Windows Ghidra,仅支持 PE 目标);对非PE的OT固件无能为力,那属于ICS专用工具链的范畴;
  2. 它不降低认知门槛——本次识别之所以快,前提是笔者熟悉CODESYS组件命名;它压缩的是机械检索成本,而非判断力成本;
  3. 它替代不了\"观察真实流量 + 真值裁决\"——这正是本次按下那两次启停按钮的意义所在。

所以正确用法是:以REA建立假设,以真机抓包与人工裁决坐实结论。 而人类的价值,恰恰集中在后者那几次\"按键\"上,在于对业务的理解上。

结束

招新小广告

ChaMd5 Venom 招收大佬入圈

新成立组IOT+工控+样本分析 长期招新

欢迎联系[email protected]

REA驱动的某川PLC私有协议-逆向分析实战" 网络安全文章

REA驱动的某川PLC私有协议-逆向分析实战"

本文实战逆向某川PLC上位机私有协议,利用rea工具完成协议栈识别、报文格式还原、会话流程分析及启停控制,发现会话无认证、完整性校验无效等风险,并提出防护建议。研究证明rea在工控安全中高效可用,人类仅需提供真实流量与操作验证。
AI开始“拆软件”了:你装的软件,到底在干什么?" 网络安全文章

AI开始“拆软件”了:你装的软件,到底在干什么?"

本文介绍Rea开源项目,其利用AI辅助逆向分析软件行为,通过Windows计算器百分号规则和Notion复制操作追踪等案例,展示如何追踪软件内部逻辑。文章强调AI分析能力对安全研究的意义,同时指出密钥保护、云端模型数据路径及AI解释局限性等安全边界,建议安全不能仅靠隐藏代码。
UBBF2026|华为新一代运营商安全目标网架构解决方案,构筑分层纵深防护体系,护航运营商新增长" 网络安全文章

UBBF2026|华为新一代运营商安全目标网架构解决方案,构筑分层纵深防护体系,护航运营商新增长"

华为在UBBF2026发布新一代运营商安全目标网架构解决方案,从网络、终端、运营三大维度构筑分层纵深韧性防护体系。网络层通过路由与安全协同联动实现DDoS秒级防御,终端层利用威胁溯源图引擎精准识别隐蔽威胁,运营层依托AI智能研判将威胁闭环处置时长缩短至30分钟内,全方位护航运营商AI时代新增长。
亚信发布信矛SpearTrust:让企业拥有一支可持续运行的AI红队" 网络安全文章

亚信发布信矛SpearTrust:让企业拥有一支可持续运行的AI红队"

亚信安全发布信矛SpearTrust,一款AI原生持续渗透验证平台,将传统年度项目制渗透测试升级为可随时发起、专家管控、证据可复现的常态化安全验证。该平台面向企业Web应用与API,模拟真实攻击路径,验证漏洞可利用性,已在600余个项目验证并发现5782个高危漏洞,旨在应对监管远程检测与业务日级迭代带来的安全挑战。
评论:0   参与:  0