1. 从"锁"的思维看PLC程序保护:为什么加密不是单一动作
很多人第一次接触PLC加密,脑子里浮现的画面是给文件设个密码,就像给压缩包加个锁。但实际在工业现场待久了就会发现,PLC的程序保护更像是一套"门禁系统"——不同的人该看到什么、能改什么、能下载什么,层次分得很细。你不可能给一个操作工和给一个设备厂商的调试工程师同样的权限,也不可能让产线维护人员随便把整段工艺逻辑导出去。
PLC加密手段的核心目标其实有三个:防止程序被非法读取、防止程序被非法修改、防止程序被非法复制到其他硬件上运行。这三个目标对应的技术手段完全不同,很多新手会把它们混为一谈,结果就是"我明明设了密码,怎么程序还是被人读走了"。
先说一个我早期踩过的坑。当时给一个包装机械项目做程序,用的是某日系品牌的小型PLC,我在软件里设了一个"程序读取密码",觉得万事大吉。结果客户那边的电气主管直接打电话过来,说他们的设备厂商用另一套编程软件把程序读出来了,问我怎么回事。我一查才发现,那个密码只保护了"通过该软件在线读取"这一条路径,而存储卡里的程序备份文件根本没有被保护。这就是典型的"只锁了前门,窗户还开着"。
所以理解PLC加密,第一步不是去记某个品牌的操作步骤,而是先搞清楚攻击面在哪里。PLC的程序可能存在于哪些地方?至少有这么几个位置:
- PLC本体的用户程序存储区(RAM/Flash)
- 编程软件工程文件(本地电脑上的项目文件)
- 存储卡或U盘中的备份文件
- 触摸屏HMI里的配方和参数
- 上位机SCADA系统中的逻辑脚本
- 设备出厂时厂家留存的源程序
每一个位置都需要对应的保护手段,而不同品牌PLC提供的加密能力差异非常大。有的品牌只支持简单的读取密码,有的品牌支持基于硬件的绑定加密,还有的品牌支持程序块级别的加密和授权管理。如果你在选型阶段没有考虑清楚,后期想补加密方案会非常被动。
还有一个容易被忽略的点:加密和可维护性是一对矛盾。你把程序锁得越死,现场出故障时排查就越困难。我见过一个项目,程序被前一家集成商加了密,设备运行两年后出了逻辑问题,原厂家联系不上,新来的工程师拿着PLC干瞪眼,最后只能把整个程序推倒重写。所以加密方案的设计必须考虑"钥匙托管"和"应急解锁"机制,不能为了安全把后路全堵死。
下面这张表可以先帮你建立一个整体认知,不同保护目标对应的常见手段和典型局限:
| 保护目标 | 常见手段 | 典型局限 |
|---|---|---|
| 防止在线读取 | 读取密码、访问级别 | 存储卡备份可能不受保护 |
| 防止程序修改 | 写保护、下载密码 | 有密码的人仍可改 |
| 防止复制到其他硬件 | 硬件绑定、序列号校验 | 硬件损坏后程序无法迁移 |
| 防止逆向分析 | 程序块加密、编译后下载 | 调试和故障排查变困难 |
| 防止备份泄露 | 工程文件加密、存储卡加密 | 密钥管理成为新问题 |
理解了这张表,你就知道为什么我说"加密不是单一动作"。接下来我会按实际操作的顺序,把几种主流手段逐一拆开讲,包括它们背后的原理、具体怎么配置、以及我在现场遇到的真实情况。
2. 访问级别与密码体系:最基础也最容易配错的一层
几乎所有主流PLC品牌都提供某种形式的访问级别控制。这个机制的本质是:在PLC的固件里维护一张权限表,不同密码对应不同的操作权限。当你从编程软件连接PLC时,软件会先请求一个访问级别,PLC根据你输入的密码判断是否放行。
听起来很简单,但实际配置时有几个关键细节决定了这套机制到底有没有用。
2.1 访问级别的典型分层逻辑
以常见的几种实现方式为例,访问级别通常分为这么几档:
- 最高级(管理员/制造商):可以读取程序、修改程序、下载程序、清除PLC、修改硬件配置、管理其他密码。这个级别一般留给设备制造商或系统集成商。
- 调试级:可以读取程序、在线监控、修改部分参数,但不能下载新程序或清除PLC。适合现场调试工程师。
- 操作级:只能监控数据、修改配方参数,不能查看程序逻辑。适合产线操作人员。
- 只读级:只能看不能改,甚至连程序都读不出来,只能看HMI上的数据。
不同品牌的叫法不一样,但逻辑大同小异。关键在于:你要根据现场人员的实际职责来分配级别,而不是所有人都给最高级。我见过太多项目,调试的时候为了方便,所有人用的都是同一个最高权限密码,结果设备交付后密码在操作工之间传了个遍,加密形同虚设。
2.2 密码设置中最容易犯的三个错误
第一个错误是密码强度不够且从不更换。很多现场用的密码就是"1234"、"0000"或者设备型号。这种密码在防君子不防小人的层面上有点用,但稍微懂行的人试几次就进去了。更麻烦的是,一旦这个密码在行业圈子里流传开,同型号设备全都处于裸奔状态。
第二个错误是只设了读取密码,没设写保护。有些PLC的读取密码和写入密码是分开设置的。如果你只设了读取密码,别人虽然读不出程序,但仍然可以在线修改数据、强制IO点、甚至下载一个空程序把原有逻辑覆盖掉。这种破坏比读取程序更直接。
第三个错误是密码丢失后没有恢复路径。几乎所有PLC的密码保护都设计成"忘记密码就只能清除PLC重新来过"。这意味着如果你把最高级密码忘了,程序就取不出来了。我建议在设备交付时,把最高级密码用密封信封交给客户设备管理部门存档,同时在项目文档里记录密码策略,而不是把密码写在PLC柜门内侧——那是所有人都能看到的地方。
2.3 一个真实的权限配置案例
之前做过一个水处理项目,现场有三类人:操作工、厂内电气维护、我们作为集成商。我的配置是这样的:
- 操作工:只给操作级密码,能通过HMI修改加药量、反洗周期等参数,但连编程软件都连不上PLC的程序区。
- 厂内电气维护:给调试级密码,能在线监控、能改参数、能看程序逻辑,但不能下载新程序。这样他们日常排查I/O故障够用了。
- 我们集成商:保留最高级密码,用于程序升级和重大修改。
同时,我在程序里做了一个"参数修改日志"功能,任何通过HMI修改的关键参数都会记录时间和修改值。这样即使操作级密码泄露,也能追溯是谁改了什么。这个日志功能不需要额外的加密硬件,只是在程序里划出一块保持寄存器区域做记录,成本几乎为零,但事后追溯非常有用。
注意:访问级别密码通常存储在PLC的掉电保持区,电池没电或超级电容失效可能导致密码丢失。如果你的设备会长期断电存放,交付前要确认密码存储机制是否依赖电池。
3. 程序块加密与编译下载:让逻辑"看不见"的进阶手段
访问级别密码解决的是"能不能连上"的问题,但如果别人拿到了最高级密码,或者通过存储卡直接读取,程序逻辑仍然是暴露的。这时候就需要程序块加密或编译后下载这类更彻底的手段。
3.1 程序块加密的工作原理
程序块加密的思路是:PLC里存储的不是源代码,而是经过加密的编译代码。编程软件在下载时对指定的程序块(如功能块FB、函数FC、组织块OB)进行加密,PLC运行时由固件解密执行。即使有人把PLC里的程序上传到电脑,看到的也是乱码或无法打开的加密块。
这种机制在不同品牌里的实现程度不同。有的品牌只支持对特定类型的块加密,有的品牌支持对整个项目加密,还有的品牌需要配合特定的硬件加密狗才能下载和运行。
我实际用过的一种方案是:把核心工艺算法放在一个加密的功能块里,这个块可以被其他程序调用,但无法被查看和修改。外围的逻辑(如IO处理、报警、HMI通信)不加密,方便现场维护。这样既保护了核心Know-how,又保留了可维护性。
3.2 编译下载与源代码分离
另一种常见做法是只下载编译后的机器码,不下载源代码。很多PLC编程软件支持"编译并下载"选项,下载到PLC里的是编译后的目标代码,上传时无法还原成梯形图或结构化文本。
这种方式的保护强度取决于编译器的优化程度。如果编译器只是简单地把梯形图转成指令表,那有经验的人还是能反推逻辑。但如果编译器做了混淆和优化,反推难度就会大很多。
这里有一个实操中的权衡:编译下载后,你自己也无法在线修改程序了。任何逻辑调整都需要回到源工程文件,重新编译再下载。所以这种方式适合程序已经稳定、不需要频繁修改的场景。如果设备还在调试阶段,千万别用编译下载,否则每次改一个定时器都要重新走一遍完整流程,效率极低。
3.3 硬件绑定:把程序锁死在特定设备上
硬件绑定是防止程序被复制到其他PLC上运行的手段。原理是程序在运行时校验PLC的硬件序列号或特定加密芯片的ID,如果不匹配就停止运行或进入受限模式。
这种机制在设备制造商中很常见,目的是防止客户把程序复制到同型号的廉价PLC上,绕过设备采购。但它的副作用也很明显:一旦原PLC损坏,程序无法直接迁移到备件上。如果没有预留解锁机制,设备制造商自己也修不了。
我见过一个比较聪明的做法:程序在启动时校验硬件ID,如果不匹配,不是直接停机,而是进入一个"演示模式"——所有输出被禁用,但HMI上显示一个提示,告诉维护人员需要联系厂家获取授权码。授权码是根据新PLC的硬件ID计算出来的,厂家可以远程提供。这样既保护了程序,又保留了应急恢复的通道。
3.4 几种保护手段的强度对比
| 手段 | 防读取 | 防修改 | 防复制 | 可维护性 | 实现成本 |
|---|---|---|---|---|---|
| 访问级别密码 | 中 | 中 | 低 | 高 | 低 |
| 程序块加密 | 高 | 高 | 中 | 中 | 中 |
| 编译下载 | 高 | 高 | 低 | 低 | 低 |
| 硬件绑定 | 中 | 中 | 高 | 低 | 中 |
| 综合方案 | 高 | 高 | 高 | 中 | 高 |
实际项目中,我通常建议采用组合方案:访问级别密码做第一道门,程序块加密保护核心算法,硬件绑定防止非法复制,同时预留应急解锁通道。没有哪一种手段是万能的,但组合起来可以让攻击成本远高于收益。
4. 存储卡与工程文件:被忽视的泄露通道
聊PLC加密,大多数人只盯着PLC本体,但我在现场遇到的程序泄露事件里,超过一半是从存储卡或工程文件流出去的。
4.1 存储卡里的程序备份
很多PLC支持把程序备份到存储卡,方便批量生产或快速恢复。这个功能本身很好用,但如果存储卡没有加密,任何拿到卡的人都可以把程序读出来。更麻烦的是,有些品牌的存储卡备份是自动进行的——每次下载程序时都会同步更新卡里的备份,而工程师可能根本不知道卡里已经有了一份完整的程序副本。
我处理过一个案例:某设备厂的电气工程师离职后,用之前项目留下的存储卡把程序读出来,直接复制到了竞争对手的设备上。后来查原因,发现那张存储卡是设备出厂时随机器附带的,里面一直保留着完整的程序备份,而设备厂从来没有清理过。
防范措施其实不复杂:
- 设备交付前,清除或加密存储卡中的程序备份
- 如果必须保留备份,使用带加密功能的存储卡,或把备份文件加密后再存入
- 建立存储卡管理制度,谁领用、谁归还、卡里有什么内容,都要有记录
4.2 工程文件的加密与权限管理
编程软件里的工程文件是另一个大漏洞。很多工程师习惯把工程文件放在共享盘或U盘里,文件本身没有任何加密。一旦电脑丢失或U盘借给别人,整个项目的源代码就全泄露了。
对工程文件的保护,我通常建议这么做:
- 使用编程软件自带的工程加密功能(如果有的话),给工程文件设打开密码
- 把工程文件存放在加密磁盘或加密容器里,不要裸放在文件系统中
- 对工程文件做版本管理,但版本库本身要加密,且访问权限要严格控制
- 交付给客户的工程文件,考虑只给编译后的版本,源文件留在自己手里
这里有一个现实问题:客户通常要求拿到源程序,否则设备出问题时他们无法自主维护。这种情况下,可以在合同里约定源程序的交付条件和保密义务,同时把源程序加密后交付,密码在设备验收后一段时间再提供。这样既满足了客户的合理需求,又给自己留了一定的保护窗口。
4.3 HMI和上位机里的间接泄露
PLC程序加密做得再好,如果HMI或上位机里暴露了太多信息,攻击者仍然可以间接推断出PLC的逻辑。比如HMI上显示了所有内部变量的地址和当前值,或者上位机脚本里包含了PLC的通信协议细节和寄存器映射表,这些信息组合起来,足以让一个有经验的人还原出大部分控制逻辑。
我的做法是:HMI上只显示操作人员需要看到的信息,内部变量和中间状态不暴露;上位机与PLC的通信尽量走标准协议,寄存器映射表不写在脚本注释里;如果必须做数据采集,用单独的通信接口,与编程接口隔离。
5. 加密之后:可维护性与应急恢复的平衡
把程序锁死很容易,但设备是要运行十年的。这十年里,PLC可能损坏、程序可能需要升级、工艺可能需要调整。如果加密方案没有考虑这些,最终受害的是设备所有者和维护人员。
5.1 密钥托管与分级授权
我在做加密方案时,一定会设计一套密钥托管机制。具体来说:
- 最高级密码分成两部分,分别由设备制造商和客户设备管理部门保管,单独一方无法解锁
- 或者使用"主密码+恢复密码"的双密码机制,主密码日常使用,恢复密码密封存档
- 对于硬件绑定的程序,预留一个基于时间或次数的临时授权机制,用于硬件更换后的程序迁移
这些机制不需要多复杂的技术,关键是在项目初期就设计好,而不是等出了问题再想办法。
5.2 加密对故障排查的影响
程序加密后,现场排查故障的难度会显著增加。原本可以通过在线监控看到的内部逻辑,现在可能因为程序块加密而无法查看。这时候需要提前准备一些辅助手段:
- 在非加密区域保留关键状态的监控变量,方便判断故障位置
- 设计完善的报警和事件日志系统,即使看不到逻辑,也能通过日志推断问题
- 保留一份"调试版本"的程序,在需要深度排查时临时下载使用,排查完再恢复加密版本
我通常会在程序里做一个"维护模式",通过特定的操作序列(如HMI上的隐藏按钮组合)可以临时解除部分加密限制,但会记录操作日志。这样既保证了日常运行时的安全性,又给维护人员留了一个可控的入口。
5.3 一个关于"锁与钥匙"的教训
最后分享一个我亲身经历的教训。早期做一个出口设备项目,程序做了比较严格的加密,包括硬件绑定。设备运行三年后,PLC本体故障,客户从当地买了一个同型号的新PLC,但程序无法迁移。由于设备已经过了质保期,原厂技术支持需要收费,而且流程走了两周。这两周里,整条产线停产,损失远超程序加密带来的价值。
从那以后,我在所有加密方案里都会加入一个应急恢复流程,并在设备交付文档里明确写清楚:如果PLC损坏,如何获取临时授权、需要提供哪些信息、预计多长时间可以恢复。这个流程本身也是加密方案的一部分,不能等到出事才想。
PLC加密的本质不是"把门锁死",而是"控制谁能进、什么时候进、进去能做什么"。好的加密方案应该像一套完善的门禁系统:日常运行安全可靠,紧急情况下有章可循,而不是把所有人都挡在外面,包括你自己。