-
-
[原创]施耐德PLC蠕虫技术
-
发表于:
2020-10-14 17:31
18288
-
在前一段时间,国外的研究人员发现了施耐德的PLC代码注入漏洞(CVE-2020-7475),该漏洞可以使得施耐德PLC蠕虫化。如果成功利用该漏洞,可以让PLC充当一个小型PC机执行恶意的网络活动,充当内网跳板或者网络扫描器对工业系统进行隐蔽性更高的渗透活动。
该漏洞是很明显的设计缺陷,接下来会从西门子PLC和施耐德PLC对于组态程序的设计来阐述漏洞发生的根本原因。
西门子S7系列PLC提供了不同方式的PLC组态编程,例如原理图表示(LAD或FBD)、类似于Pascal的编程语言(SCL)以及类似于汇编的编程语言(STL)等。不管输入源的类型如何,PLC程序都将程序编译为MC7字节码(STL甚至是较低级的表示形式)。

当组态软件编译好工程文件(MC7文件格式)后,通过西门子的S7COMM/S7COMM-PLUS协议下装到PLC中,然后由PLC中的MC7 虚拟机进行调度并解释执行MC7字节码,由于虚拟机可以对程序所访问的资源进行限制,编译出的字节码无法直接操作硬件,只能访问虚拟机提供的资源,如通过FB块中TCON以及TDISCON去建立TCP连接发送接收数据,也就是说编译出的组态程序有进行恶意网络活动的能力。

西门子并没有对MC7字节码进行文档化,只能通过一些逆向手段去理解字节码中对应的汇编指令,好在有人已经做了这一部分工作(可以使用JEB的插件),只需要使用该工具就可以对MC7文件进行反汇编甚至反编译来理解组态程序中的代码逻辑,通过此方法在分析 Stuxnet这类西门子蠕虫病毒尤其有用。

在施耐德PLC中,无论是梯形图(LD),结构化文本(ST)还是功能块语言(FBD)都会被统一编译成ARM机器码,由ARM处理器直接执行的,所以可以完全访问PLC上的软硬件资源。

当施耐德的组态软件编译好工程后,可以直接通过施耐德的ModBus 90功能码(UMAS协议)下装到PLC中,PLC启动后会执行编译好的ARM机器码。如果ARM字节码中被攻击者注入恶意代码,那么攻击者便可以完全控制PLC,拥有对网络,文件系统,硬件IO等关键资源的访问控制权。

该漏洞出现的根本原因,主要是施耐德PLC把组态程序直接编译成ARM机器码,在执行时没有对其访问的资源进行限制,导致了针对施耐德PLC的蠕虫病毒可能具有更强的隐蔽性和更大的破坏力。
Unity Pro是施耐德PLC对应的组态编程软件,通过该软件可以对PLC进行编程。为了在编译后的ARM代码中注入代码,应该先找到实现代码编译的地方。如下图所示,asmarm.dll导出函数MyAsmArmStream就是负责将ARM汇编代码编译成ARM机器码。

在该函数第一个参数指向ARM汇编字符串,返回的是编译好的ARM的机器码数据:

为了定位用户编写的代码在整个ARM汇编中的位置,可以编写测试代码(如下图):

生成的代码肯定包含立即数1000(0x3e8),通过搜索该立即数,就可以快速定位到用户代码在组态程序中的位置,并获得相应的汇编代码。

只需要hook该函数,并修改传入的汇编代码,即可实现在施耐德PLC中执行任意代码。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课