Group of Software Security In Progress

GoSSIP @ LoCCS.Shanghai Jiao Tong University

ICSREF: A Framework for Automated Reverse Engineering of Industrial Control Systems Binaries

作者: Anastasis Keliris (NYU); Michail Maniatakos (NYU Abu Dhabi)

单位: NYU

出处: NDSS’19

原文: https://arxiv.org/abs/1812.03478

源码: https://github.com/momalab/ICSREF


INTRODUCTION

过去几年工业控制系统(ICS)的安全性受到越来越多的关注,尽管如此,对PLC二进制文件的逆向分析仍然是一个开放的问题,考虑到PLC二进制文件不同于传统的二进制文件,作者提出了一种结构化的方法来实现自动化逆向。作者选择CODESYS平台编译的PLC文件作为研究的目标,通过解析该平台生成的所有二进制文件的相关信息,然后执行自动二进制分析,生成CFG图,用r2反汇编,用angr确定运行时的函数参数,最终通过修改代码实现修改任意函数的参数。

为了评估该框架,作者创建了一个样本数据库,这些包括从公共代码存储库收集的PLC二进制文件,以及内部开发的二进制文件。结果证明了ICSREF可以成功分析各种不同的PLC二进制文件。最后,作者在Nexus 5上测试了ICSREF,使用它自动化的攻击一个化学过程的试验台。该攻击过程通过逆向分析PRG文件,动态提取PID算法函数的参数,并修改其参数达到破坏工控系统稳定运行的目的。

PRELIMINARIES

### A. Industrial Control Systems

ICS用于监控和控制工业配置的流程,可以被抽象为一组通过传感器测量物理变量并计算测量值的算法。这些控制的结果算法反过来用于调节受控的物理环境。ICS的一个比较重要的概念是扫描周期,它包括3个部分,从传感器读取数据,执行程序,向执行器写数据。PLC可以看做是一个坚固耐用的实时嵌入式系统,它们被部署到环境比较恶劣的工业环境中。既然是嵌入式系统,它通常包括一个或多个微处理器,易失性和非易失性存储器,模拟和数字I/O以及网络能力。

B. Software development of PLC programs

PLC是专为工业控制而开发的装置,为了适应传统习惯和掌握能力,通常PLC不采用微机的编程语言,而常常采用面向控制过程、面向问题的“自然语言”编程。国际电工委员会(IEC) 1994年5月 公布的IEC1131-3 (可编程控制器语言标准)详细地说明了句法、语义和下述5种编程语言:

  • 功能表图 Sequential Function Chart (SFC)
  • 梯形图 Ladder Diagram (LD)
  • 功能块图 Function Block Diagram (FBD)
  • 指令表 Instruction List (IL)
  • 结构文本 Structured Text (ST)

梯形图和功能块图为图形语言,指令表和结构文本为文字语言,功能表图是一种结构块控制流程图。

C. PLC binaries vs. conventional binaries

PLC和传统的二进制逆向分析在技术上有相同点,但在具体的实现方面,又因为特性不同,导致分析方法略有差异,这些差异体现在以下几点

Execution model

PLC二进制文件执行时会根据状态执行某些过程,这就导致动态分析时,无法分析整个PLC二进制文件。

I/O operations

PLC二进制文件对I/O操作的依赖更高,占据其扫描周期的三分之二。 PLC通过读写I/O实现与传感器和执行器的交互。

File format

通过由专有的加载器(例如,CODESYS运行时)处理PLC二进制文件的加载,PLC二进制文件的文件格式是自定义和未知的。

Optimization

由于PLC程序对实时性的要求,PLC二进制文件的编译器通常只进行非常保守的优化。

PROPOSED METHODOLOGY FOR REVERSE ENGINEERING PLC BINARIES

考虑到对PLC二进制文件的特殊性,作者提出了一种结构化的方法来实现典型 自动化逆向工程任务和目标,包括两个阶段:

1)特定于某个平台的阶段,每个平台执行一次(例如,STEP7,Studio 5000或CODESYS)。在此阶段,提取通过那个平台生成的所有二进制文件的相关信息。

2)执行自动二进制分析阶段。利用特定于平台的结果,自动从PLC二进制文件中提取信息。

A. Platform-specific phase

该阶段旨在提取有关的信息平台的细节。 这一阶段分解为两个步骤:逆向理解使用该平台编译的PLC二进制文件的格式和创建包含一般信息的知识数据库。

1) Binary format reverse engineering

一般来说,二进制格式的结果是逆向工程步骤应包括文件头的信息,如何分隔函数,进而反汇编代码,识别符号表和动态链接的函数,以及如何区别代码和数据部分。

2) Knowledge Databases 需要创建两个知识数据库。一个是二进制文件中执行的I/O操作,一个是识别库函数和代码片段。

B. Automated binary analysis

第一个核心步骤是利用上一阶段的文件格式信息解析二进制。在这一步中,所有函数必须分隔和反汇编,并且区分代码/数据部分。第二个核心步骤是尽可能完整地重建CFG。第三个核心步骤是利用知识数据库确定I/O操作和识别库函数。

补充步骤包括使用动态二进制分析技术自动提取函数参数。另一个补充步骤考虑修改二进制文件,实现插入动态有效负载生成。进一步的步骤应提供CFG可视化的表示。

THE ICSREF FRAMEWORK

本节主要介绍了ICSREF模块化自动化逆向工程框架的技术细节。作者选择CODESYS平台编译的PLC文件作为研究的目标,CODESYS是一款工业自动化领域的一款开发编程系统。下图列出了主要的自动化公司是否使用CODESYS软件开发平台。作者保守估计全球至少有20%的PLC开发使用CODESYS平台。

A. Platform-specific phase: CODESYS

首先需要对已知的二进制文件进行逆向分析来理解CODESYS的PLC二进制文件的格式。这样就可以得到两种知识:PLC的I/O内存映射和已知库函数的签名。利用这些知识对WAGO 750-881进行研究。750-881采用ARM微处理器并使用CODESYS v2.3。研究的结果的应用不限于WAGO PLC,但只适用于使用CODESYS编译的二进制文件。

1) Binary format reverse engineering

首先是了解CODESYS PLC二进制文件的格式,作者开发了一些执行简单任务的程序。对内部生成的PRG文件进行逆向工程。下图总结了文件格式和代码函数结构。

PRG二进制文件的前80个字节为header。 例如,偏移量为0x20的4字节值 加上0x18即为程序的入口点,也是Memory INIT函数的位置。 这里仅对header的进行逆向分析就足够实现自动分析。

函数分隔符

序言 结尾

精确定位函数序言和结语,这样可以分隔包含在二进制文件中的函数。

全局变量和通用函数的初始

第一个函数(Global INIT)在header后面,从偏移量0x50开始,开发者使用这块内存来定义一些常数(例如,缩放因子,PID增益,定时常数)。 之后是全局初始化函数(Sub 1-3),存在于每个二进制文件中。 然后是调试器处理程序(SYSDEBUG)用于IDE的动态调试。

静态链接的库代码和用户定义的函数

在调试器处理代码之后是静态链接的库代码和用户定义的函数。每个F/FB包含两个函数:一个执行其主要功能,一个负责初始化本地内存。倒数第二个函数是主函数,在CODESYS中命名为PLC_PRG。

符号表

一些简单的标准功能,如对实数类型变量的运算是动态链接的。符号表中包含有关这些功能的信息。

2) CODESYS Knowledge Databases:

在了解了文件格式之后,接着是通过逆向提取知识。这些知识包括

I/O database

为了与其他硬件模块交换信息,CODESYS把PLC的I/O模块映射到内存中的特定地址 空间。 如图所示,在CODESYS IDE中,对于WAGO 750-881,当读写传感器的值时,等价于从内存地址0x28CFEC00-0x28CFF7F8范围内读写内存。

在IDE的目录里,每一个PLC硬件的选项都保存在TRG文件中。通过解析TRG文件并提取PLC模型的I/O内存映射,以自动方式填充I/O数据库。

Known functions database

为静态链接的库函数创造指纹。签名使用SHA-256计算操作码助记符序列。作者选择操作码并丢弃指令参数,因为参数可能包含可变信息(例如,绝对分支目标,使用不同的寄存器)。 库函数的操作码序列都是唯一的,不受CODESYS提供的最小编译选项的影响。

最后,作者从CODESYS IDE的212个库中分析并创建了1704个F/FB及其签名。一共花了11个小时44分钟。这是一个耗时的步骤,但它只需要做一次。 在数据库构建期间没有发现任何冲突。通过自动化此过程,可以轻松扩展数据库包含新库的F/FB签名。

B. Automated binary analysis: ICSREF

通过以上知识,ICSREF可以对PRG二进制文件自动进行逆向工程。ICSREF的设计目标是: * 准确性:通过应用ICSREF获得的结果PLC二进制文件应该是准确的,尽可能重建CFG。 * 可扩展性:ICSREF的设计和结构应该能够轻松扩展到新的PLC目标,微体系结构, 和IEC 61131-3开发平台。 * 可用性:ICSREF的使用应该很简单,并且为逆向工程师提供直观的界面。

为实现这些设计目标,采用了模块化方法

1) Core module

##### Comprising components 首先,解析header和提取它包含的信息。 然后扫描二进制搜索函数分隔符,并使用它们来分割所有函数,并使用radare2生成它们的反汇编代码。最后,提取符号表并进行标识任何动态链接的功能。

CFG reconstruction

对于每个二进制分析,重建其CFG对自动化来说至关重要。比较麻烦的是间接分支目标。不过这里PRG二进制文件中所有的跳转目标都自包含在该二进制文件中。 基本上可以提取并解析所有间接分支,从而产生一个完整的CFG图。

在CODESYS二进制文件中,这个跳转可以完全重建。 因为所有的跳转目标(SUB_OFFSET)都存在在Memory INIT中。 这个函数也是二进制的入口点。 在初始化阶段,它计算所有函数所需的索引偏移,并创建相应的跳转表。

通过利用angr符号执行来实现执行特定的部分,因为angr不支持PROG文件,这部分作者自己实现了一下。通过解析生成的符号状态的内存,有效地重建所需的跳转表。

I/O operations and known functions matching

通过I/O数据库帮助识别读写I/O的指令。 用angr对每个函数执行符号执行,检测映射I/O范围内读写内存的操作,并注释协助逆向工程师识别二进制文件与其他设备的交互代码。

计算每个函数的签名,并查询已知函数的匹配数据库。 每当有匹配时,在ICSREF结果中修改函数的名称以反映其函数每个库定义的功能。

2) Function call arguments module

典型的动态分析中,需要提取传递给调用函数的参数。作者以Proportional-Integral-Derivative (PID)功能块作为PoC,验证提取传递的参数的模块。 用angr重建函数栈,确定了函数在栈上的参数。考虑到参数也可能是全局变量/常量,首先执行一下Global INIT函数,其中的值被初始化。然后将执行转移到 调用者函数并执行它直到我们达到调用感兴趣的函数(比如PID)。最后,查询 在栈上生成的符号内存值,有效地提取传递给PID的参数。该模块可以很容易地实现 扩展为提取对任何函数的调用的参数列表及其数据类型。

3) Binary modification module

二进制修改模块是对ICSREF的具体应用,该模块可以覆盖PLC二进制文件中的任何位置,比如修补机器代码指令,修改分支目标,通过覆盖“dead code”来注入可执行代码,并修改关键函数的调用参数等等。

CODESYS使用了校验算法确保二进制文件的完整性,为了保证修改后的代码的完整性,通过识别校验算法,重新计算新PRG二进制文件的校验和。

4) Visualization module

如图所示,使用DOT图创建图表描述语言,每个子函数和动态链接函数是一个节点,它们之间的调用是边。在边缘添加权重,表示从调用者到被调用者的调用次数。使用不同的颜色区分二进制和动态链接代码中包含的代码。

EXPERIMENTAL EVALUATION

实验主要是从准确性和性能两方面考虑。数据一部分是自己编译的,一部分是从github上收集的。

A. Correctness evaluation

这里的正确性测试只测试了函数的调用关系,对参数识别的准确性未做讨论。

1) In-house binaries

初步评估了1704 PRG二进制文件的ICSREF的正确性。通过交叉验证的方法验证平台特定阶段和自动二进制分析阶段的正确性。因为有源码,可以逐行比较ICSREF生成的CFG和源代码中的函数调用关系是否一致。

2) Binaries from public code repositories

从GitHub的55个用户的127个仓库中下载了471个项目文件。其中471个里有69个包含编译好的PRG文件。通过项目文件里的字符串,对厂商和目标PLC模型进行分类。如下表所示,发现68%的是为WAGO开发的。然后对下载的项目进行编译,最后由于各种原因,只得到了266个PRG文件。

B. Performance evaluation

性能分析主要是为了证明ICSREF能够处理任意大小的PLC二进制文件。这里作者选择了从github上下载编译的266个PRG文件作为评估目标。实验环境是Intel i7-7500U CPU和16 GB RAM,运行Ubuntu 16.04。

实验结果如下图所示,实验主要是为了说明各个模块的分析时间和文件的大小基本保持线性关系。举个例子,大小为310KB的二进制文件,其总分析时间是58.1s,解析需要16.0s,重建跳转表需要41.4s和其他时间0.7s。

CASE-STUDY: AUTOMATED ATTACK FORMULATION AND DEPLOYMENT

本小节中,作者演示了在事先对某个工业控制系统一无所知的情况下,利用自动化的逆向系统ICSREF对工控系统实施攻击的例子。

威胁模型

考虑威胁模型中由两个角色组成:攻击的策划者和实施者。假设策划者可以设计并计划整个攻击,但不能物理接触目标设施。而实施者具有物理接触设施的能力(例如,是一个低级别员工),但缺乏发展攻击的技术技能。攻击策划者将攻击代码捆绑在一个不起眼的设备中,例如智能手机,然后交给部署人员。部署人员在目标环境中使用攻击设备,部署并执行自动生成的攻击代码。

攻击的目标是Tennessee Eastman (TE) chemical process, 可以理解为一个benchmark process, 已被广泛用于多个过程控制和ICS安全研究。为了自动攻击TE过程,作者根据威胁模型在Nexus 5上部署了ICSREF系统,运行Ubuntu Touch操作系统,系统伪装成一个简单的“按下按钮”的应用程序。攻击部署者只需要在现场网络建立连接并启动应用程序。

在实验中,对手机进行编程执行一系列步骤,如上图所示。手机扫描网络中的工业设备,通过指纹识别他们的型号,并下载他们包含的二进制文件,这大约需要90s的时间。随后,ICSREF系统自动自动分析二进制文件,需要250秒。 在这个步骤,ICSREF识别二进制文件是否包含PID函数,如果包含就提取其参数并更改它们,生成修改后的二进制文件。最后,修改了的二进制文件被上传回PLC,通过复位强制PLC重启执行恶意代码。 最后一步需要大约60秒。 总的来说,整个攻击链从头到尾执行的时间不超过5分钟。

最后,作者通过分析函数调用并提取PID的Kp参数的值,生成一个修改它的新二进制文件,导致反应堆压力稳定在较低水平压力设定值(2350 kPa左右)而不是最佳值2800kPa。对反应堆压力的影响是如上图所示,较低的反应堆压力会产生负面影响导致经济损失。