使用PLC作为payload/shellcode分发系统
这个周末,我一直在鼓捣Modbus,并利用汇编语言开发了一个stager,它可以从PLC的保持寄存器中下载payload。由于有大量的PLC都暴露在互联网上,我情不自禁地想到,是否可以利用它们提供的处理能力和内存来存储某些payload,以便以后(从stager)下载它们。
所以,我们不妨考虑下面的场景:
1. 攻击者从互联网上寻找一个具有足够的空间来存储payload的PLC。实际上,带有几十KB内存的Modbus设备是很容易找到的。
2. 攻击者将payload上传到PLC的内存。
3. 攻击者用dropper感染一个主机,然后利用stager与Modbus进行“交流”,从PLC中下载并执行该stage。
采用PLC保持寄存器存储Payload的优点
由于使用了第三方PLC,所以具有很好的匿名性,跟踪的难度非常大。无需将payload上传到服务器。
由于payload存放在PLC的内存中,所以加大了取证分析的难度。此外,一旦payload被取出,其内容可以被容易地覆盖(甚至stager自身就能做到这一点)。
此外,我认为Modbus Stager在某些ICS环境中也是非常有用的,因为这些环境下Modbus之外的协议会引起人们的警觉,并且WinHTTP / WinInet stager也不是最适用的。所以,在这种情况下,你只需要一个Modbus处理程序或者只是使用一个仿真器,在stager连接它时,由其提供stage即可。此外我们还发现,许多网络上都有可以远程管理的Modbus设备,所以它们也是这种stager的用武之地。
重要说明:请不要对任何第三方PLC执行这些操作。PLC寄存器上的任何写操作都可能毁坏原来的过程控制策略。
活跃在互联网上采用Modbus协议的PLC数量
为了弄清楚暴露在互联网中、使用Modbus协议的PLC的数量,我使用Censys API写了一个小脚本。如果你的网卡性能不错的话,你可以利用masscan或Zmap等工具来扫描互联网,寻找在502端口上运行Modbus协议的设备。
从以下输出可以看出,至少有5500个PLC可供利用。
在这些IP中,许多只是些蜜罐,这很容易看出来;例如,Conpot以及托管在云服务中的其他服务。就本文来说,即使蜜罐也无所谓,只要它们的内存足够大就行了。
如何将Payload上传至PLC保持寄存器
好了,为了将payload上传到PLC中,我编写了一个名为plcInjectPayload.py的python脚本。根据加载的控制策略的不同,对PLC可用内存大小的要求也有所变化,因此该脚本首先检查它们是否有足够的内存空间来存放相应的payload。为了检测内存的大小,可以发送操作ID为03(读取保持寄存器)的Modbus请求,尝试从某个地址读取特定记录(每个记录长度为16比特)。如果收到一个0x83异常,那么说明这个PLC对于我们来说是无法使用的。
要上传payload,请使用-upload选项,具体如下所示。该选项允许使用参数-addr规定起始地址,也就是说,从这个保持寄存器编号(如果未指定,则为地址0)开始加载payload。
如果payload的字节数为奇数,就需要用“0x90”来进行填充,以避免在读取时出现一些问题。在前面的示例中,大小为1536字节; 为了检查加载操作是否成功,我们可以利用选项-download从地址0处下载同样数量的字节。
很明显,该脚本不仅可以上传payload,实际上还可以上传任何类型的文件。所以,我们觉得这是一个泄露和共享信息的有趣方法。设想一下,有谁会怀疑某个公共PLC的保存寄存器会存有.docx或.zip文件呢?
需要格外注意的是,存放payload的记录可能会被PLC所改变。由于我们不清楚PLC I / O及其过程控制策略,所以需要寻找一个通常不会被修改到的内存范围。为此,我们可以将payload加载到某个范围,然后在一段时间内,payload经多次检查未发现任何变化的话,这就是我们要找的内存区域。为了达到这个目的,我们可以借助于plcInjectPayload.py以及另外几个bash指令即可。
在受控主机中读取PLC中存储的Payload
payload上传到PLC之后,还必须从受害者的计算机中读取它。为此,我建立了一个基于Modbus协议的stager;它的大小还不到500字节(我会设法让它变得更小)。其中,它的reverse_tcp和block_api代码取自Metasploit(https://github.com/rapid7/metasploit-framework/tree/master/external/source/shellcode/windows/x86/src/block)。下图展示的是block_recv_modbus.asm的asm代码,它的一部分职责是通过Modbus协议获取payload。因此,这段代码需要通过Modbus协议与PLC通信,以下相应的payload。这里的代码会利用前4个字节来了解该stage大小,并通过VirtualAlloc分配必要的内存。然后,通过不断发送“read holding”请求(功能代码03)来获取payload。根据协议规定,对于每个读请求,PLC最多可以返回250个字节(125个保持寄存器),因此,stager可以以它为单位,逐步下载payload。
实例解析
下面我们来看一个实际的例子。最近,我在www.exploit-db.com网站上发现一个用于Windows系统的键盘记录shellcode,大小只有600字节;虽然它的尺寸很小,但是对于一个只有几个MODBUS请求(记住,每个请求的最大字节数为250字节)的POC来说已经足够了。shellcode在执行后,会把按键敲击动作写入到用户的%TEMP%目录下的“log.bin”文件中。
因此,我们首先把该payload放到一个二进制文件中,并在它的前面放上其长度,这里是以小端字节表示的长度(4字节)。
现在,让我们从地址0开始将其上传到PLC:
这个stager一旦运行,就会通过3个请求下载该payload:250 + 250 + 102 = 602字节。下图详细描述了Modbus通信过程。
下图展示了Wireshark对上述通信过程的跟踪情况。进程监视器窗口表明,该stage在成功运行(检查log.bin文件就能看到保存的击键)
我已经通过Modbus仿真器和实际PLC对这个代码进行了验证,结果一切正常,但是如前所述,我认为该shellcode还可以进一步优化。为了进行第一个测试,我在python(plcModbusHandler.py)中创建了一个Modbus处理程序,用来把该payload发送给stager。
我正在设法把这个处理程序移植到Metasploit。更多详情,请观看下面的视频。
参考链接:http://bobao.360.cn/learning/detail/3311.html
原文链接:http://www.shelliscoming.com/2016/12/modbus-stager-using-plcs-as.html
使用PLC作为payload/shellcode分发系统的更多相关文章
- 使用 expect 命令执行自动分发系统
一.命令 except 实例详解 1. 介绍 expect 使用场景 expect可以让我们实现自动登录远程机器,并且可以实现自动远程执行命令.当然若是使用不带密码的密钥验证同样可以实现自动登录和自动 ...
- 基于BT协议的文件分发系统
基于BT协议的文件分发系统构成: 1.一个Web服务器:保存着种子文件 2.一个种子文件:保存共享文件的一些信息(文件名,文件大小 ,Tracker服务器地址,torrent为后缀) ...
- 任务分发系统gearman
1 Gearman是什么 Gearman Job Server@http://gearman.org/. Gearman 是一个任务分发系统,它提供了一个分发框架,能够分发某类任务到更适合处理这类任务 ...
- Django之路由分发系统
web的基本工作流程 首先,我们先来思考一下我们平常在上网浏览网页时候的场景,大致就是打开一个web浏览器,输入某一个网站的地址,然后转到该网址,在浏览器中得到该网址的页面.从这个场景中我们可以抽象出 ...
- 关于LT分发系统的设计构想
git地址 https://github.com/cxyxd/LtDistribution 背景 对tomcat做集群,在多机多tomcat的情况下,如果要更新代码,只能手动的将代码复制,粘贴,然后下 ...
- 深度解读阿里巴巴云原生镜像分发系统 Dragonfly
Dragonfly 是一个由阿里巴巴开源的云原生镜像分发系统,主要解决以 Kubernetes 为核心的分布式应用编排系统的镜像分发难题.随着企业数字化大潮的席卷,行业应用纷纷朝微服务架构演进,并通过 ...
- expect脚本同步文件 expect脚本指定host和要同步的文件 构建文件分发系统 批量远程执行命令
自动同步文件 #!/usr/bin/expect set " spawn rsync -av root@.txt /tmp/ expect { "yes/no" { se ...
- centos shell编程4【分发系统】 服务器标准化 mkpasswd 生成密码的工具 expect讲解 expect传递参数 expect自动同步文件 expect指定host和要同步的文件 expect文件分发系统 expect自动发送密钥脚本 Linux脚本执行方式 第三十八节课
centos shell编程4[分发系统] 服务器标准化 mkpasswd 生成密码的工具 expect讲解 expect传递参数 expect自动同步文件 expect指定host和要 ...
- 第四部分shell编程5项目二分发系统
第一部分:expect讲解expect可以让我们实现自动登录远程机器,并且可以实现自动远程执行命令.当然若是使用不带密码的密钥验证同样可以实现自动登录和自动远程执行命令.但当不能使用密钥验证的时候,我 ...
随机推荐
- Metaspace 之一:Metaspace整体介绍(永久代被替换原因、元空间特点、元空间内存查看分析方法)
回顾 根据JVM内存区域的划分,简单的画了下方的这个示意图.区域主要分为两大块,一块是堆区(Heap),我们所New出的对象都会在堆区进行分配,在C语言中的malloc所分配的方法就是从Heap区获取 ...
- BZOJ4196[Noi2015]软件包管理器——树链剖分+线段树
题目描述 Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个 ...
- C# SFTP
最近需要通过SFTP来获取文件. 下面是我整理的相关信息. 以下只是大致代码,大家看看就行了. 我的是window service.每天会去下载文件. 1 下载 Renci.SshNet 通过 nu ...
- HDU - 1160 (FatMouse's Speed )最长上升子序列
题意:一个元素有两个属性 w 和 sp 求在w严格递增的情况下 sp严格递减 用结构体 定义三个参数 w sp ix , ix是在输入时的顺序 因为我们要排序 之后把结构体数组 按从小到大排序 ...
- 自学Linux Shell12.4-for命令
点击返回 自学Linux命令行与Shell脚本之路 12.4-for命令 1. for命令 格式一 for var in list do commands done 格式二 for var in li ...
- 监控(3)进程通用shell
#! /bin/bash proc_name="beam.smp" #进程名 proc_num() #查询进程数{ num=`ps -ef | grep $proc_name | ...
- python多线程用法及与单线程耗时比较
下面,通过一个简单的例子,来把多线程和单线程执行任务的耗时做个比较 import time import threading # 音乐播放器 def music(func, loop): for i ...
- Java -- JDBC 学习--通过 ResultSet 执行查询操作
ResultSet: 结果集. 封装了使用 JDBC 进行查询的结果. 1. 调用 Statement 对象的 executeQuery(sql) 可以得到结果集. 2. ResultSet 返回的实 ...
- jar的打包与共享
做成jar包的,有个弊处,打包apk时会暴露源码,当然也有解决方案,放在最后讲. 先来解释如何生成jar: 新建工程,将工程编译至无错,右键工程Export... 在弹出的提示框中选择Java文件夹下 ...
- 「loj3057」「hnoi2019」校园旅行
题目 一个n个点m条边的无向图,每个点有0 / 1 的标号; 有q个询问,每次询问(u,v)直接是否存在回文路径(可以经过重复的点和边); $1 \le n \le 5 \times 10^3 , ...