2019 工业信息安全技能大赛-哈尔滨站 WriteUp
📝 赛事概况
参赛规模:比赛共吸引了来自全国的 24 支队伍参加
比赛项目:大赛设有 PLC 漏洞挖掘和 SCADA 漏洞挖掘两个比赛项目
🏛️ 组织架构
指导单位:国家工业信息安全发展研究中心、黑龙江省工业和信息化厅
主办单位:黑龙江省电子技术研究所、哈尔滨工程大学
🏆 比赛结果
- 第一名:冀信安队
Misc
异常的 S7 数据(S7comm 协议)
大概看了一下,全是 0x05 功能码

绝大多数写入数据都以 ffff 开头

右键作为过滤器应用

WireShark 生成的语法是 s7comm.resp.data == ff:ff:96:e7:8f:51:c4:d0:3a:2b
我们更改为 s7comm.resp.data[0:2] != ff:ff,筛选出数据包

所以 flag 是 flag{FFAD28A0CE69DB34751F}
神奇的数据(S7 符号访问服务)

查看文本文件是一大堆 ASCII 码(十进制),用 | 间隔

搜索 flag 66|6c|61|67|,有两段结果

分析第一段是请求包
以太网帧
| 字段 | 值 |
|---|---|
| 目标 MAC | 08:ac:7d:01:e1:83 |
| 源 MAC | 00:05:b7:da:72:57 |
| EtherType | 0x0800 (IPv4) |
IPv4 首部
| 字段 | 值 |
|---|---|
| 版本 / IHL | 4 / 5 (20 字节) |
| DSCP / ECN | 0x00 |
| 总长度 | 91 (0x005b) |
| 标识 | 0x987e |
| 标志 / 片偏移 | DF (不分片), 0 |
| TTL | 64 |
| 协议 | 6 (TCP) |
| 校验和 | 0x10a1 |
| 源 IP | 100.100.100.21 |
| 目的 IP | 100.100.100.160 |
TCP 首部
| 字段 | 值 |
|---|---|
| 源端口 | 57632 (0xe120) |
| 目的端口 | 102 (ISO-TSAP) |
| 序列号 | 0xbdcc6ad5 |
| 确认号 | 0x86f7846e |
| 数据偏移 | 32 字节 (8) |
| 标志 | ACK + PSH (0x18) |
| 窗口 | 501 (0x01f5) |
| 校验和 | 0x5744 |
| 紧急指针 | 0 |
| 选项 | NOP, NOP, Timestamp (TSval=0x7d8a8100, TSecr=0x09ad3958) |
| 负载长度 | 39 字节 |
TPKT (RFC1006)
| 字段 | 值 |
|---|---|
| 版本 | 3 |
| 保留 | 0 |
| 长度 | 39 (0x0027) |
COTP (ISO 8073)
| 字段 | 值 |
|---|---|
| 头长度 | 2 字节 |
| PDU 类型 | DT (0x0f) |
| EOT / TPDU-NR | 0x80 (EOT, NR=0) |
S7 符号访问服务(请求)
| 字段 | 值 |
|---|---|
| 固定头 | 01 00 01 00 |
| 应用构造标签 | 0x61 (Application 1) |
| 长度 | 26 (0x1a) |
| SEQUENCE 长度 | 24 (0x18) |
| 协议版本 (INTEGER) | 3 |
| Context[0] 长度 | 19 (0x13) |
| Context[0] 内容长度 | 17 (0x11) |
| 符号 ID (INTEGER) | 0x666c6167 (“flag”) |
| Context[1] 长度 | 9 |
| ↳ Context[0] (参数1) | 80 01 09 (原始, 值 0x09) |
| ↳ Context[1] (参数2) | 80 00 (原始, 空) |
很明显,目的端口 102 → 典型的西门子 PLC ISO-TSAP 端口
接下来再来看响应包
以太网帧 (802.1Q)
| 字段 | 值 |
|---|---|
| 目标 MAC | 00:05:b7:da:72:57 |
| 源 MAC | 08:ac:7d:01:e1:83 |
| 802.1Q TPID | 0x8100 |
| 优先级 / CFI / VLAN ID | 0 / 0 / 1 |
| EtherType | 0x0800 (IPv4) |
IPv4 首部
| 字段 | 值 |
|---|---|
| 版本 / IHL | 4 / 5 |
| 总长度 | 145 (0x0091) |
| 标识 | 0x15f4 |
| 标志 / 片偏移 | DF, 0 |
| TTL | 64 |
| 协议 | 6 (TCP) |
| 校验和 | 0x92f5 |
| 源 IP | 100.100.100.160 |
| 目的 IP | 100.100.100.21 |
TCP 首部
| 字段 | 值 |
|---|---|
| 源端口 | 102 |
| 目的端口 | 57632 |
| 序列号 | 0x86f7846e |
| 确认号 | 0xbdcc6afc (确认增加 39) |
| 数据偏移 | 32 字节 |
| 标志 | ACK + PSH (0x18) |
| 窗口 | 15000 (0x3a98) |
| 校验和 | 0x56e2 |
| 紧急指针 | 0 |
| 选项 | NOP, NOP, Timestamp (TSval=0x09ad3958, TSecr=0x7d8a8100) |
| 负载长度 | 93 字节 |
TPKT (RFC1006)
| 字段 | 值 |
|---|---|
| 版本 | 3 |
| 保留 | 0 |
| 长度 | 93 (0x005d) |
COTP (ISO 8073)
| 字段 | 值 |
|---|---|
| 头长度 | 2 字节 |
| PDU 类型 | DT |
| EOT / TPDU-NR | 0x80 |
S7 符号访问服务(响应)
| 字段 | 值 |
|---|---|
| 固定头 | 01 00 01 00 |
| 应用构造标签 | 0x61 |
| 长度 | 80 (0x50) |
| SEQUENCE 长度 | 78 (0x4e) |
| 协议版本 | 3 |
| Context[0] 长度 | 73 (0x49) |
| Context[1] 长度 | 71 (0x47) |
| Invoke ID (符号 ID) | 0x666c6167 (“flag”) |
| 变量列表容器 | Context[1] (长度 63) |
| 返回状态 | 0x00 (成功) |
变量列表(VisibleString)
| 序号 | 变量符号名 |
|---|---|
| 1 | PL1012{ROT |
| 2 | PL1012CTRL |
| 3 | PL1012LD0 |
| 4 | PL1012MEAS |
| 5 | PL1012RC |
看上面的变量列表结构,删除掉 PL1012,flag 就出来了
1 | flag{ROTCTRLLD0MEASRC} |
智能变电站设备异常诊断(SCD 文件)

010 打开发现文件头被颠倒了

改回来后打开就是一个 dcs.dcs 文件

初步查看文件类型
1 | file dcs.dcs |
可以看到文件不是普通 XML
1 | dcs.dcs: data |
但文件头附近有明显标识
1 | $KEMOV-SCD-FILE$ |
继续查看十六进制
1 | od -Ax -tx1z -N 128 dcs.dcs |
对应了 $KEMOV-SCD-FILE$
同时后面出现了类似
1 | 20 31 20 31 20 30 20 6b 20 76 20 2e 20 73 20 63 20 64 |
这种结构解出来是
1 | 110kv.scd |
说明这个文件本质上保存的是一个变电站 SCD 配置信息,只是被厂商工具二进制化了
观察文件里的 ASCII 字符串会发现它不是正常连续保存的
1 | 20 49 20 4c 20 31 20 31 20 30 20 31 |
这不是普通 ASCII,而是类似
1 | 0x20 + ASCII 字符 |
所以
1 | 20 49 -> I |
解出来是
1 | IL1101 |
中文部分则基本可以按 UTF-16BE 理解
也就是说,文件里的大量字段是 1 字节长度 + 2 字节字符序列
编写脚本来恢复
1 | from pathlib import Path |
脚本首先能恢复出原始 SCD 文件名
1 | [+] header: $KEMOV-SCD-FILE$ |
接着筛选 110kV 线路智能终端,可以看到
1 | [+] 110kV line intelligent terminals: |
题目说问题可能来源于线路智能终端,所以重点检查
1 | IL1101 |
然后分析 IED_GOCB 记录,即 GOOSE Control Block 配置,异常输出为
1 | [+] duplicated IED_GOCB: |
这里的异常点非常明确:
1 | IL1101 / RPIT / LLN0 / gocb5 |
被重复配置了 10 次
在 IEC 61850/SCD 配置里,同一个 IED、同一个逻辑节点下的 GOOSE 控制块名称应该唯一。重复的 gocb5 会导致控制块引用冲突、GOOSE 配置异常,从而引发运行异常
题目问的是 “分析存在问题根源”
真正的问题是 “变电站基础配置文件 SCD 存在错误”
所以 flag 是 flag{scdisbad}
黑客的大意(信息收集)

识别出是 PNG 图片,修改后缀再打开

GitHub 上搜索到源码,里面就有邮箱

窃取数据的黑客(MMS 协议)

查看会话可以看到一直在跟 192.168.51.34:102 通信
所以 192.168.51.34 就是服务器

按照长度排列,第 3096 包没有 info 信息有点可疑(3022、3059 也一样)

展开后可以看到 flag.7z 以及 flag.txt

按照最先发包顺序,从 3022 之后看攻击者 IP 192.168.51.33 请求操作
在 3066 包中可以看到访问了 flag.7z

编写脚本去响应中找到这个压缩文件
1 | import struct |

解压后拿到 flag 值

flag 在哪(文件附件隐写 + 像素隐写)

使用 foremost 分离出一个 PNG 图片和压缩包
图片发现存在残缺的条形码图文

使用 PS 工具将其修复完整,发现熊猫的颜色颠倒过来,因此对图片进行反相处理

扫描可得到字符串:This_n0t_fl4g
使用该字符串解压刚才的压缩包,得到 3.jpg 文件,使用 binwalk 查看依旧存在 ZIP 文件,于是继续分离出来
最终得到两个一模一样的图片,使用 Stegsolve 工具进行图片对比

发现出现很多像素点,确定是像素隐写,保存该图片为:solved.bmp,发现和原图对比数据杂乱因此尝试使用像素隐写解密工具进行解密
GitHub 搜索尝试几个工具后,最终发现此工具可以成功解密:https://github.com/HFO4/HideByPixel

md5 解密拿到 flag:flag{this_is_fl4g_icsc-^_^}
Reverse
简单的 APK 分析(签到)

解包 APK 得到 multiprotocol.tesla.scada 文件
反编译该文件通过对比正版软件,很容易得到 flag(为混淆前的类名)
