作者: 启明星辰ADLab

一、分析背景

2017年6月12日,安全厂商 ESET 公布一款针对电力变电站系统进行恶意攻击的工控网络攻击武器 -win32/Industroyer (ESET命名), ESET 表示该攻击武器可以直接控制断路器,可导致变电站断电。 Industroyer 恶意软件目前支持四种工控协议:IEC 60870-5-101、IEC 60870-5-104、IEC 61850以及OLE for Process Control Data Access(简称OPC DA)。这些协议广泛应用在电力调度、发电控制系统以及需要对电力进行控制行业,例如轨道交通、石油石化等重要基础设施行业,尤其是 OPC 协议作为工控系统互通的通用接口更广泛应用在各工控行业。可以看出,攻击者对于工控系统尤其是电力系统相关的工控协议有着深厚的知识背景,并且具有目标工控环境下的各种工控设备,攻击者需要这些设备来实现恶意代码的编写和测试工作。

与2015年袭击乌克兰电网最终导致2015年12月23日断电的攻击者使用的工具集(BlackEnergy、KillDisk、以及其他攻击模块)相比,这款恶意软件的功能意义重大,它可以直接控制开关和断路器,Industroyer 身后的黑客团队无论从技术角度还是从对目标工控系统的研究深度都远远超过了2015年12月乌克兰电网攻击背后的黑客团队。

ESET 公布该恶意软件之前,曾经对 Dragos 公司做过相应通告,Dragos 根据通告的内容找到该恶意软件的样本并且通过他们对该批恶意软件的编译时间推测该恶意软件曾被利用来攻击乌克兰的变电站导致2016年12月那次半个小时的乌克兰停电事件。目前可以说 Industroyer 恶意软件是继 STUXNET、BLACKENERGY 2以及 HAVEX 之后第四款对针对工业控制系统进行攻击的工控武器。启明星辰ADLab根据 ESET 提供的HASH文件对这批样本进行了分析验证并在某些方面做了更加深入的分析。

二、Industroyer 恶意软件简要分析

Industroyer 恶意软件是由一系列的攻击模块组成,根据目前所公开的信息及 ESET 得到的模块就多达10多个。其中存在一个主后门模块,它被用于连接C&C下载另外一批模块执行,这些模块分别为:实现 DLL Payload 模块执行的加载器模块、实现数据及痕迹清理的 haslo 模块、实现IP端口扫描的 port 模块以及实现西门子 SIPROTEC 设备 DoS 攻击的 DoS 攻击模块。其中,DLL Payload 模块包含实现 IEC 101 工控协议的 101.dll 模块、实现 IEC 104 工控协议的 104.dll 模块、实现 IEC 61850 协议的61850.dll/61850.exe 模块以及实现 OPC DA 协议的 OPC.exe/OPCClientDemo.dll 模块等。以下我们列出了可以收到的样本及其功能。

值得注意的是,Main Backdoor 与 C&C 通信的时候是通过内网中的一台主机作为跳板连接到 C&C 上实施命令控制的,ESET 发现该模块是通过 Tor 网络实现与 C&C 的交互。因此根据目前所掌握的信息我们绘制了该恶意软件大致工作流程。

从恶意软件的攻击流程中我们可以推测该黑客可能的攻击路径:首先黑客可以通过电子邮件、办公网系统、外来运维终端、U盘等途径成功入侵一台主机(如:内网的10.15.1.69),并且在该主机联网时下载必要的模块执行比如 Tor 网络客户端或者代理服务模块等作为后续攻击的回连跳板,黑客接下来以该主机为跳板对系统局域网络进行探测扫描,当发现自己感兴趣的目标(是否为104从站、OPC服务器或者操作站等)后对其实施攻击,一旦攻击成功,黑客就将这台可以连接外网的主机 IP 配置为攻击模块 Main Backdoor 的代理IP,下发到该主机中,这台主机是可以直接与 RTUs 或者 PLCs 进行通信的,并且可以做直接的控制。

三、详细分析描述

1. Main Backdoor 模块分析

该模块主要用于实现与攻击者 C&C 通信, 由于工控系统内部的控制主机可能处于无法连接外网的内部局域网络中,所以黑客事先在进入被感染系统之前已经非常清楚该工控系统内部的网络结构,在入侵的跳板主机上安装了 Tor 客户端以及代理服务(代理服务开启3128端口接收数据进行转发)。并且在进行内部网络攻击过程中,黑客将根据该跳板机的 IP 来定制化相应的 Main Backdoor 程序下发到目标机上运行。因此,可以说该模块是在黑客攻击过程中实时根据黑客当前所掌握的资源信息进行定制的。

该模块的通信部分也是通过一个小时为单位的时间定制化任务来执行。也就是说,在黑客实时攻击过程中也是有可能的通过这个定制化功能在指定的时间里与 C&C 通信,比如深夜时间。如下图:

此外,该模块会创建一个匿名的互斥体,并且会在路径 %Common Documents% 的父目录创建一个标识文件 imapi ,只有这个文件存在的情况下才会执行与 C&C 通信的任务。

Main Backdoor 模块连接 C&C 是通过跳板机(10.15.1.69)来实现与 C&C 5.39.218.152 通信的,通信的端口为 443 端口,据 ESET 报告,与 C&C 通信的数据采用了 HTTPS 。

目前我们无法证实该情况,因为后门采用 443 端口通信但实际不为 HTTPS 的情况非常多。但是可以确定的是 Main Backdoor 与跳板机之间的通信是明文的。通信数据内容如下:

该后门收到控制命令数据后,会对数据做一定处理,最后创建一个线程来处理黑客端发来的控制请求。

其中,控制命令的前4个字节为命令 ID,接下来是单字节的控制命令,其值为 0-0xA 整形值,控制命令的控制命令参数位于第16个字节的偏移之后。控制命令分发以及处理功能代码如下:

其中控制命令以及相应的功能说明如下表所示:

从控制功能上可以看出该后门模块的主要任务是从C&C下载扩展模块执行以及做远程命令执行,并且提供了由账户凭证支持的权限控制。如果黑客获取了管理员权限就可以将已安装的后门升级到一个更高的权限版本,黑客可以选择一个现有的、非关键的 Windows 服务,在注册表中替换它的 ImagePath 键值为新后门的代码路径。

2. Launcher模块分析

该模块为 Main Backdoor 下载的众多模块之一,其实际上为黑客的进一步攻击提供一个统一的攻击接口,可以说是专门为运行 payload 模块而设计的。该模块在系统中以服务程序运行,运行时会创建一个定时器。定时器触发时该模块会创建新线程加载 hasio.dat 模块并调用 hasio.dat 模块的 Crash 函数(关于hasio.),并且执行 payload 模块的 Crash 函数。通过启动器模块,恶意代码可以在指定的时间根据命令行运行任意的 payload 。 该模块接受3个参数,格式为: %LAUNCHER%.exe‌ %WORKING_DIRECTORY% %PAYLOAD%.dll‌ %CONFIGURATION%.ini。 参数以及解释如下:

当模块启动运行时会将 workdirectory 设置为当前目录,然后加载 payload 模块。需要注意的是,此时加载 Payload 模块但是并没有执行模块的核心功能,这些功能实现在 Payload 模块的导出函数 Crash() 中,所以通过该 Launcher 运行的 Payload 模块都必须导出这么一个函数。

这个导出函数是通过定时器控制执行,定时器的触发时间为2016年12月17日22点。

历史上,乌克兰电力系统遭受了两次恶意网络攻击而引起的停电事故,其中一次便是2015年12月23号由恶意代码 BlackEnergy 攻击而导致大规模停电事故,第二次是在2016年12月17日遭受到未知恶意攻击而导致30分钟的停电事故。因而该恶意软件极有可能是第二次乌克兰停电事故的罪魁祸首。

3. 数据清除模块:haslo 模块分析

该模块为该恶意软件的数据擦除模块,与 KillDisk.DLL 模块具有类似的破坏性目的,它会删除注册表中服务对应的模块路径,并对磁盘上的文件进行改写,该模块对应的文件名为 haslo.dathaslo.exe ,其中 haslo.dat 随启动器模块执行,haslo.exe 可以作为单独工具执行。当该模块运行时会枚举HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services下的所有键,并设置该键的 ImagePath 为空,该操作会造成系统无法正常启动。

清理完注册表后,该模块会开始擦除文件,首先该模块枚举驱动器从C盘到Z盘中包含指定扩展名的文件,对发现的文件进行改写。其中会避免对 Windows 目录文件的改写。需要注意的是,在枚举的过程中该组件跳过了子路径中名称包含 Windows 的文件。该组件用从新分配内存中获得的随机数据来重写文件内容。为了达到彻底擦除数据使其无法恢复的目的,该组件会尝试重写两次。第一次是当文件在驱动器盘中被发现,如果第一次没有成功,该组件会尝试第二次。但是在此之前,该恶意软件会终止除了包含在关键系统列表中的所有进程。

该模块需要擦除的文件类型有:

此外,该擦除模块还存在一个白名单的进程列表,为了防止意外发生,其不会对这些进程进行强制关闭的操作。擦除模块内置的白名单进程列表如下。

4. 104.dll 模块分析

该模块实现了 IEC-104 规约中定义的协议,首先该模块读取配置文件,并根据配置文件中的指令进行指定操作。由于该模块主要实现了 IEC-104 的协议通信,所以有必要对 IEC-104 协议的格式和规约做一些背景介绍。

IEC-104 规约是厂站与调度主站间通讯的规约,以以太网为载体,采用平衡传输,TCP/IP 网络通信端口号为2404。IEC-104 规约以 0x68 为启动字符,紧接 APDU 长度和4个8位控制域,之后是用户数据。

名称解释:

启动字符 0x68 定义了数据流中的起点,APDU 的长度域定义了 APDU 体的长度,它包括 APCI 的四个控制域八位位组和 ASDU ,控制域定义了保护报文不至丢失和重复传送的控制信息、报文传输启动/停止、以及传输连接的监视等控制信息。

IEC-104规约帧分为三种类型:

a)可计数的信息传输功能的帧,简称I帧或者I格式帧。 b)可计数的确认功能的帧,简称S帧或者S格式帧。 c)启动、停止、测试功能的帧,简称U帧或者U格式帧。

I格式帧常常包含 APCI 和 ASDU 两个部分,其控制域第一个八位组的比特1=0,I帧包含特定信息,类型和内容较多。

S格式的帧只有 APCI,其控制域第一个八位组的比特 1=1 并且比特 2=0 。用于确认接收到对方的帧,但本身没有信息发送的情况。

U格式的帧也只有 APCI,其控制域第一个八位组的比特 1=1 并且比特 2=1 ,U帧仅有三种类型:启动帧、测试帧、停止帧。

IEC 60870-5-3 描述了远动系统传输帧中的基本应用数据单元,并定义了用于配套标准中的应用服务数据单元(ASDU)结构如图:

应用服务数据单元(ASDU)由数据单元标识符和一个或多个信息对象组成。类型标识定义了后续信息对象的结构、类型和格式。可变结构限定词定义了信息元素的数目和信息体地址类型,长度为一个字节。公共体地址即为 RTU 地址,长度2个字节,低位在前。

主站发送的类型标识列表:

从站返回信息帧的类型标识列表:

主站发送的传输原因:

从站发送的传输原因:

对该协议有一定了解后,我们继续对该模块做进一步分析。当该模块的 Crash 函数被 Launcher 加载运行时,会将配置文件读入到内存(配置文件由参数 Crash 参数指定)读取到内存的配置参数。

下表是配置文件中各域解释:

该模块首先会读取 stop_comm_service 域并判定其是否为1,如果为1,则结束 stop_comm_service_name 域所指定的进程。

执行完以上操作后,该模块会根据 IEC-104 规约构造数据包向配置文件中指定的目标主机IP端口发送启动帧。构造启动帧数据包代码如下:

该恶意模块(主站)连接从站(RTUs),并构造启动帧发送给从站(RTUs)。

恶意模块(主站)发送U帧启动帧:

从站(RTUs)会返回一个U帧确认帧:

当成功获取到从站(RTUs)返回的确认帧后,该模块会根据配置文件中 operation 域提供的操作方法操作RTU。

当前 operation 域支持三种方式,分别为range、sequence、shift。

range 模式即为攻击者指定信息对象地址范围,主站读取配置文件中 range 域填充攻击者指定的信息对象地址向从站发送单点遥控选择信息,从站(RTUs)返回单点遥控确认信息,然后恶意模块(主站)向从站(RTUs)发送单点遥控执行请求,根据返回的信息确认信息对象地址。当得到正确的信息对象地址后,该模块会循环向从站发送单点遥控选择及单点遥控确认请求。

构造单点遥控选择数据包:

恶意模块(主站)发送的数据为:
68(启动符)0E(长度)00 00(发送序号)00 00(接收序号)2D(类型标示)01(可变结构限定词)06 00(传输原因)00 00(公共地址即RTU地址)0A 00 00(信息体地址)81(遥控性质
当前类型标识为0x2d传输原因为0x06表示主站发送单点遥控,其中遥控性质为0x81表示向从站发送单点遥控选择

从站(RTUs)返回数据,
68(启动符)0E(长度)00 00(发送序号)02 00(接收序号)2D(类型标示)01(可变结构限定词)07 00(传输原因)01 00(公共地址即RTU地址)0A 00 00(信息体地址)81(遥控性质
当前类型标识为0x2d传输原因为0x07标识从站发送单点确认

恶意模块(主站)发送单点遥控执行合闸
68(启动符)0E(长度)02 00(发送序号)02 00(接收序号)2D(类型标示)01(可变结构限定词)06 00(传输原因)00 00(公共地址即RTU地址)0A 00 00(信息体地址)01(遥控性质
注释
遥控性质字段解释:
bit7 为1表示选择,等于0标识执行
bit1 bit0 为01表示合闸,为00表示分闸
bit65432 为1表示短脉冲,为2表示长脉冲,为3表示持续。

sequence 模式为当攻击者知道从站的信息对象地址值时,根据配置文件中的攻击指令,向从站(RTUs)循环发送单点遥控选择及单点遥控执行请求。

shift 模式与 range 模式类似,首先会枚举 range 域指定的信息对象地址范围,完成后,会通过 shift 域生成新的信息对象地址范围进行与 range 模式相同的操作。

当配置文件中的silence域为1时会开启命令行输出。

启动帧与确认帧:

单点遥控选择与确认:

单点遥控执行请求:

四、其他模块功能说明

该恶意软件在攻击过程中可以下发任何可能的攻击模块,根据 ESET 的报告,我们将其他的攻击模块以及其核心功能归纳如下(以下内容根据ESET的报告编译总结而成):

1. 101

这个 payload DLL 名为 101.dll ,以 IEC 101(即IEC 60870-5-101) 命名,这也是一种国际标准的用于监控和控制电力系统的协议。该协议常用于工业控制系统和远程终端单元(RTUs)之间的通信。实际通信是通过串行连接传输的。

101 payload 组件在一定程度上实现了 IEC 101 标准中所描述的协议,并且能够与 RTU 或者任何支持该协议的设备进行通信。一旦被执行,101 payload 组件解析存储在 ini 文件中的配置信息,配置信息可能包含:进程名、Windows 设备名称(通常是 COM 端口)、信息对象地址(IOA)的范围、以及IOA指定范围的开始和结束值。IOA 是一个数字,用于标识设备中一个特定的数据元素。

进程的名字被指定在配置文件中,该名字属于运行在受害者机器上的应用程序。该应用程序通过串行连接和 RTU通信。101 payload 试图终止指定的进程,并且开始使用 CreateFile、WriteFile 和 ReadFile 这些Windows API 函数和指定的设备通信。配置文件中的第一个 COM 口用于实际通信,另外两个端口用于防止其他进程访问。这样,101 组件能够接管和维护 RTU 设备的控制。

这个组件遍历所有被定义的 IOA 范围内的IOA。对于每一个IOA,构造两个“选择和执行”包,一个单命令(C_SC_NA_1)一个双命令(C_DC_NA_1),并且将它们发送到RTU设备。组件的主要目标是改变单命令类型IOA的开/关状态和双命令类型的IOA的开/关状态。具体来说,101 payload有三个阶段:在第一阶段,这个组件试图将IOA切换到它们的Off状态;第二阶段试图将IOA转换为On;最后阶段再将IOA状态切换回Off。

2. 61850 模块

与 101 和 104 payload 不同的是,61850 payload 是一个独立的恶意工具。它包含一个名字为 61850.exe 的可执行文件和一个名字为 DLL 61850.dll 的动态链接库。它们以 IEC 61850 标准来命名。该标准描述了用于实现变电站自动化系统保护、自动化测量、监控和控制的设备之间的多厂商通信协议。该协议非常复杂和健壮,而61850只是使用了该协议中一小部分来产生破坏性影响。

一旦被执行,61850 payload DLL 就会尝试读取配置文件,该配置文件路径由启动器组件提供。独立版本默认从 fromi.ini 文件读取它的配置文件。该配置文件包含一组设备的IP地址列表,这些设备通过IEC 61850描述的协议进行通信。

如果配置文件不存在,该组件枚举所有的网络适配器来确定它们的 TCP/IP 子网掩码。然后,61850 payload枚举每一个子网掩码下所有可能的IP地址,接着尝试连接每一 IP 地址的 102 端口。因此,该组件有能力在网络中自动发现相关设备。

相反,如果配置文件存在,并包含目标IP地址,该组件会连接该IP地址的102端口。并且这些IP地址也是被自动发现的。

一旦该组件连接到目标主机,它就会使用面向连接的传输协议发送连接请求包,如果目标设备有效回应,61850使用制造消息规范(MMS)发送初始请求包。如果收到预期的回应,则继续发送一个MMS名称列表请求。因此该组件在虚拟制造设备(VMD)中编译对象名称列表。接下来,该组件枚举了前面步骤中发现的对象,用每一对象名发送设备特定域对象列表请求,在一个特定域中枚举命名变量。

之后,从 61850 payload 这些请求的响应数据中搜索 包含以下字符串组合的变量:

字符串“CSW”是用于控制断路器和开关的逻辑节点的名称。

61850 payload为一些包含“Model“或”stVal“字符串的变量发送额外的MMS读取请求。该组件还可以发出一个可以改变其状态的MMS写请求。

61850 payload产生一个日志文件,它的操作包含IP地址、MMS域、命名变量和目标节点的状态(打开或关闭)。

3. OPC DA payload 组件

OPC DA payload 组件为 OPC 数据协议实现了客户端。访问规范 OPC(进程控制OLE)是一种基于微软技术的软件标准和规范。例如 OLE、COM和DCOM 。OPC 规范中的数据访问(DA)部分允许基于客户端-服务器模型的分布式组件之间的实时数据交换。该组件为独立的恶意工具,包含 OPC.exeh 和一个 DLL 。该组件同时实现了 61850 和 OPC DA payload 功能。该DLL在PE的导出表中被命名为 OPCClientDemo.dll ,表面该组件的代码可能是基于开源项目 OPC 客户端。

一旦被攻击者执行,OPC DA payload不需要任何配置文件。它会用 ICatInformation 枚举所有的 OPC 服务器。接下来该组件使用 IOPCBrowseServerAddressSpace 接口来枚举服务器上的所有 OPC 项目。特别是寻找包含下列字符串的项。

这些项目的名称表明攻击者对属于 ABB 解决方案的 OPC 服务器提供的 OPC 项非常感兴趣。攻击者在添加新的OPC组时使用字符串 “Abdul”,可能这个字符串被攻击者用作俚语,指的是 ABB 解决方案。

在最后一步,OPC DA payload 尝试使用 IOPCSyncIO 接口,写两次 ox01 值来改变已发现 OPC 项的状态。

该组件写 OPC 服务器名称、OPC 项状态、质量码和值到日志文件。日志值被下面的头所分割:

4. 辅助后门组件

ESET 还发现另外一个具有后门功能的恶意组件,这个恶意组件提供了另一种持久性机制,允许攻击者重新访问目标网络,以防主后门被检测到/或禁用。这个后门是一个 Windows 记事本应用的木马版本,它拥有记事本的完整功能。但是,恶意软件的作者已经插入了恶意代码,每次记事本启动,恶意代码都有被执行。一旦攻击者获得管理员权限,他们就会手动替换掉合法的记事本。

插入的恶意代码被严重混淆,但是,一旦代码解密,它连接到一个远程 C&C 服务器(这个服务器不同于主后门所连接的),下载一个 payload ,这个 payload 是一个 shellcode 形式的恶意代码,它直接被加载到内存执行。此外,插入的代码解密存储在文件末尾的原始 Windows 记事本,然后再执行该记事本,这样记事本程序就像预期那样工作。

5. 端口扫描器

攻击者的武器库包含一个端口扫描器,其可以被用来在网络中找到攻击相关的计算机。有趣的是,攻击者并没有使用外部软件,而是使用自己编写的端口扫描工具,攻击者可以定义用于扫描工具扫描的一系列 IP 地址和端口。

6. DoS工具

攻击者武器库中的另一工具是拒绝服务(DoS)工具,可以用来对付西门子 SIPROTEC 设备,该工具利用了 CVE-2015-5374 漏洞,目标是使设备无法响应。一旦漏洞被成功利用,目标机器将会停止任何命令响应,直到手动重启。

为了利用这个漏洞,攻击者将设备 IP 地址硬编码到该工具中。一旦工具被执行,就会使用 UDP 协议发送特定的精心设计的数据包到目标 IP 地址的 50000 端口。该 UDP 数据包包含18字节。

参考文章:
1. WIN32/INDUSTROYER A new threat for industrial control systerms Anton Cherepanov, ESET Version 2017-06-12

2.CRASHOVERRIDE Analysis of the Threat to Electric Grid Operations DRAGOS INC version 2.2017061

3.IEC870-05-104-传输规约-国电


启明星辰积极防御实验室(ADLab)

ADLab成立于1999年,是中国安全行业最早成立的攻防技术研究实验室之一,微软MAPP计划核心成员。截止目前,ADLab通过CVE发布Windows、Linux、Unix等操作系统安全或软件漏洞近300个,持续保持亚洲领先并确立了其在国际网络安全领域的核心地位。实验室研究方向涵盖操作系统与应用系统安全研究、移动智能终端安全研究、物联网智能设备安全研究、Web安全研究、工控系统安全研究、云安全研究。研究成果应用于产品核心技术研究、国家重点科技项目攻关、专业安全服务等。


源链接

Hacking more

...