2024江西省振兴杯工控CTF
协议分析
被攻击的电机
思路:
过滤一下 modbus 协议,看 func_code == 5 时,Data 的 10 进制数据是大于 3000 的,但是提交 hex 数据错误
modbus.func_code == 5

然后看 func_code == 6 刚好,Data 为 5000 很可疑,提交一下正常,其实就是硬找

flag:flag{c90a00000006030600721388}
omron
思路:
过滤 omron 协议。然后追踪一下 tcp 流


然后在第二个流发现 base64 字符,尝试解码,就是 flag


flag: flag{guoqingcdgl923}
应急处置
工程被加密了
思路:
下载 组态王7.5SP1软件,打开后发现要密码

猜测为弱密码,123456,进去

然后点击操作记录就能看到 flag

flag: flag{fujka8899}
时间炸弹
题目:
产线中运行的PLC程序中被供应商埋入了“时间炸弹”,时间条件满足后触发,PLC的自动运行功能被锁定从而致使生产停摆,只能通过手动进行简单操作,生产效率将大幅降低,需要输入密码进行程序解锁。请分析找出解锁密码,密码即为flag。提交格式:flag{xxxxxxxx}。
固件分析
固件后门分析
思路:
解压文件后找到 tmp 目录打开

看到了 runs.py 和 ce.pyc,将 ce.pyc 反编译一下

flag: flag{www.1sdfa4sdfdsgbnm098d8342kflgb.com:38209}
组态编程
西门子组态分析
题目:
请对西门子组态程序进行分析:按照原来的设计思路,按下启动按钮A后设备运行指示灯C应该点亮,但是C并没有亮,请根据程序,判断出还需要按下X(按钮)持续D(秒)以上得到F(点位)=G(数值)才能使得C亮。flag格式为flag{X_D_F_G}。题目同时提供了组态源程序的附件和程序代码段的截图。
思路:

从prog.png可以看到完整的PLC梯形图程序,包含4个程序段,如下
程序段1:主控逻辑
%M10.0 ——| |—— %M10.4 ——| |—— ( %M10.3 )
A D C
- 逻辑:A AND D → C
- 含义:启动按钮A 且 条件D 同时满足时,指示灯C点亮
程序段2:备用控制
%M10.1 ——| |—— ( %M10.3 )
B C
- 逻辑:B → C
- 含义:按钮B可以直接控制指示灯C
程序段3:定时器1
%M10.1 ——| |—— [TON] —— ( %M10.4 )
B %DB2 T#12S D
- 逻辑:B触发12秒定时器,输出到D
- 含义:按下B按钮12秒后,D条件满足
程序段4:定时器2(关键)
%M10.3 ——|/|—— %M10.2 ——| |—— [TON] —— ( %M10.4 )
C E %DB1 T#10S D
- 逻辑:NOT C AND E 触发10秒定时器,输出到D
- 含义:当C未点亮且E按钮按下时,10秒后D条件满足
问题分析如下:
题目描述中提到"按下启动按钮A后设备运行指示灯C应该点亮,但是C并没有亮"。
从程序段1可以看出,要使C点亮需要满足:A AND D
- A = %M10.0(启动按钮)✓ 已按下
- D = %M10.4(某个条件)✗ 未满足
问题核心:D条件不满足,导致C无法点亮。
payload:
要使D (%M10.4) 为真,有两种方式:
- 方式1(程序段3) :按下B按钮12秒
- 方式2(程序段4) :按下E按钮10秒(推荐)
选择方式2的原因:
- 初始状态下C=0,所以NOT C = 1(条件已满足)
- 只需要按下E按钮即可触发定时器
- 定时时间更短(10秒 vs 12秒)
操作步骤:
- 按下E按钮 (%M10.2) 并保持
- 等待10秒 定时器完成
- D条件满足 (%M10.4 = 1)
- 按下A按钮 (%M10.0)
- 指示灯C点亮 (%M10.3 = 1)
逻辑验证:
- 初始状态:A=0, B=0, C=0, D=0, E=0
- 按下E按钮:E=1, 触发程序段4条件 (NOT C AND E = 1 AND 1 = 1)
- 定时器运行:%DB1定时器开始计时10秒
- 10秒后:D=1 (%M10.4 = 1)
- 按下A按钮:A=1, 满足程序段1条件 (A AND D = 1 AND 1 = 1)
- 结果:C=1 (%M10.3 = 1) 指示灯点亮
flag:flag{E_10_D_1}
Smart
题目:
黑客在桌面上留下一个工程文件,经检查发现是西门子200smart plc程序,打开发现可能是一个计算程序,经分析,需要置位v22.0寄存器,获取最终VD716数值,flag为{VW502_VW600_VD716}的最终值。
思路:
使用 STEP7MicroWINSMARTV2.7.0.0 打开发现流程图,
奇怪的文件
题目:
某企业的SCADA系统主机被黑客入侵,管理员小申发现黑客上传了一个文件,我们需要帮助小申分析文件内的蛛丝马迹,找到FLAG,flag形式为 flag{}。
思路:
使用 binwalk 123.jpg 发现图片里面有个压缩包,使用 foremost 分离出来即可,观察压缩包很明显利用 crc32 进行工具,

然后使用 20251114_151839.dic 生成的字典进行字典爆破

爆破得到密码 kfoudgclum5r9gx0Sv

解压得到一个 123 文件,然后 010 观察发现是一个 zip 文件,改完后缀后,观察一下,是一个力控的文件格式,可以先解压出来只有下面那个 xml 文件被加密了

然后搜索 flag 可以发现 flag

然后使用力控软件(forcecontrol v7.2)恢复一下

然后选择恢复的工程,运行一下,点击用户管理

然后使用 Admin/123 登入一下,在点击修改用户

可以发现有个 flag 用户,估计后半段 flag 就这里

可以使用 AsteriskPassword-星号密码查看器 查看一下密码,得到后半段 flag

flag:flag{ES8-A05A-CB78-XST78-dgk8tvm9}
梯形图分析1
题目:
小朱在进行设备调试时,编写了一段模拟量转换的程序,已知IW2的值为2100,V10为2.23606801,V27为6429,请计算出V100和V200的值帮助小朱进一步分析,flag为V100与V200之和。flag格式为flag{}
思路:
给了 11.jpg ,使用 010 打开一下,发现图片尾部有个 rar 文件,

搜索一下发现是一个 AutoThink 项目文件,使用 FA-AutoThinkV3.1.9Beta1和利时PLC 这个工具打开即可

现在就是求V100与V200之和,已知IW2的值为2100,V10为2.23606801,V27为6429

不会计算,后面都改 ai 分析的不知道对不对
网络 0001 - 基础运算与模运算
功能: 进行基础的算术运算,为后续计算准备中间变量
运算流程:
第一个SUB块: V2 = 88 - 23 = 65
第二个SUB块: V3 = V3 - V2 (这里V3的初值影响结果,但不影响最终目标)
第三个SUB块: V4 = %IW2 - 56 = 2100 - 56 = 2044
MUL块: V5 = %IW2 × V4 = 2100 × 2044 = 4,292,400
MOD块: V6 = V5 MOD V4 = 4,292,400 MOD 2044 = 0
关键分析:
- V4 = 2044
- V5 = 4,292,400
- V6 = 0 (重要!因为V5 = %IW2 × V4,所以V5是V4的整数倍,取模结果为0)
网络 0002 - 除法与开方运算
功能: 进行除法运算、开方运算和数据类型转换
运算流程:
DIV块: V8 = V6 ÷ V7 = 0 ÷ V7 = 0 (只要V7≠0)
SQRT块: V10 = √V8 = √0 = 0 (理论计算)
REAL_TO_INT块: V30 = INT(V10) = INT(2.23606801) = 2
关键分析:
- V8 = 0 (因为V6=0,所以无论V7为何值,V8都等于0)
- 题目给出V10 = 2.23606801,这可能是程序运行中的实际值
- V30 = 2 (对V10进行向零取整)
网络 0003 - 计算V100
功能: 通过减法、开方和幂运算计算目标变量V100
运算流程:
SUB块: V28 = V7 - V8 = V7 - 0 = V7
SQRT块: V29 = √V28 = √V7
EXPT块: V100 = V29^V8 = (√V7)^0 = 1
关键分析:
- V28 = V7 (但V7的具体值不影响最终结果)
- V29 = √V7
- V100 = 1 (任何非零数的0次方都等于1,0^0在大多数PLC中也定义为1)
网络 0004 - 计算V200
功能: 通过模运算、幂运算和三角函数计算目标变量V200
运算流程:
MOD块: V36 = V27 MOD V30 = 6429 MOD 2 = 1
SUB块: V31 = V8 - V7 = 0 - V7 = -V7
EXPT块: V37 = V31^V36 = (-V7)^1 = -V7
COS块: V200 = COS(V37) = COS(-V7) = COS(V7)
关键分析:
- V36 = 6429 MOD 2 = 1 (6429是奇数)
- V31 = -V7
- V37 = -V7 (因为指数为1)
- 由于题目未给出V7的值,且程序中未对V7进行赋值,按PLC变量初始化规则,V7 = 0
- V200 = COS(0) = 1
数学计算验证
关键计算步骤
-
模运算验证:
V5 = 2100 × 2044 = 4,292,400 V6 = 4,292,400 MOD 2044 = 0 证明: 4,292,400 ÷ 2044 = 2100 (整除) -
实数取整验证:
V10 = 2.23606801 V30 = REAL_TO_INT(2.23606801) = 2 -
幂运算验证:
V100 = (任意数)^0 = 1 V200 = COS(0) = 1
最终结果计算
- V100 = 1
- V200 = 1
- Flag = V100 + V200 = 1 + 1 = 2
exp:
import math
def solve_plc_problem():
# 已知条件
IW2 = 2100
V10 = 2.23606801
V27 = 6429
V7 = 0 # 默认初始值
print("=== 工控梯形图分析求解过程 ===")
print(f"已知: IW2={IW2}, V10={V10}, V27={V27}")
# 网络0001
print("\n--- 网络0001 ---")
V4 = IW2 - 56
V5 = IW2 * V4
V6 = V5 % V4
print(f"V4 = {IW2} - 56 = {V4}")
print(f"V5 = {IW2} × {V4} = {V5}")
print(f"V6 = {V5} MOD {V4} = {V6}")
# 网络0002
print("\n--- 网络0002 ---")
V8 = V6 // V7 if V7 != 0 else 0 # 避免除零
V30 = int(V10)
print(f"V8 = {V6} ÷ {V7} = {V8}")
print(f"V30 = INT({V10}) = {V30}")
# 网络0003
print("\n--- 网络0003 ---")
V28 = V7 - V8
V29 = math.sqrt(abs(V28)) if V28 >= 0 else 0
V100 = V29 ** V8 if V8 != 0 else 1
print(f"V28 = {V7} - {V8} = {V28}")
print(f"V29 = √{V28} = {V29}")
print(f"V100 = {V29}^{V8} = {V100}")
# 网络0004
print("\n--- 网络0004 ---")
V36 = V27 % V30
V31 = V8 - V7
V37 = V31 ** V36
V200 = math.cos(V37)
print(f"V36 = {V27} MOD {V30} = {V36}")
print(f"V31 = {V8} - {V7} = {V31}")
print(f"V37 = {V31}^{V36} = {V37}")
print(f"V200 = COS({V37}) = {V200}")
# 最终结果
print("\n=== 最终结果 ===")
print(f"V100 = {V100}")
print(f"V200 = {V200}")
flag_value = V100 + V200
print(f"Flag = V100 + V200 = {flag_value}")
print(f"答案: flag{{{int(flag_value)}}}")
return int(flag_value)
if __name__ == "__main__":
result = solve_plc_problem()
flag:flag{2}
扫雷
题目:
自动化专家老吴通过PLC编程开发了一款小游戏——扫雷,通关后可获得flag,flag格式为:flag{}。
思路:
想让我通关不可以的,解压出来是 扫雷_V16.ap16 文件,很明显的用S7-1200 博途软件V16 打开,然后 crtl + f 搜索 flag,发现如下

双击文件定位到关键位置,就能发现密文

密文如下,根据 U2FsdG 头知道这是一个用 js 前端加密库解密的密文,一般都需要 key,看到这个文件名猜测就是密钥,jdgf
U2FsdGVkX1/MRLx94+KHoo9xb0iO9g2swJLVNYD38y7yMYhDpciH6pK0F5HHMY+Qj4XACALNZBY=
解密一下,得到 flag

在线Triple DES加密 | Triple DES解密- 在线工具 用在线的也许,就是要多试一下解密方式

flag:flag{Revitalization_Cup@578790336}
恶意程序分析
勒索病毒分析
枢网智盾线上赛Writeup - FreeBuf网络安全行业门户
题目:
客团伙利用工控系统的RCE漏洞投递了一款勒索病毒,导致系统重大量重要文件被加密,管理员经过排查已修复相关漏洞,并找到了勒索病毒样本,但无法恢复被加密的文件。你能通过分析恶意样本,协助管理员解密被加密的文件吗?请解密flag.txt.encrypt文件,获取flag。
思路:
ida 反汇编报错

可以发现 401D48 这个位置失败,先双击跟进一下这个函数,然后按 f5 ,可以发现这个函数可以反汇编,然后再回到 mian 函数 f5 也能反汇编了


exp:
# coding: utf-8
"""
勒索病毒解密脚本 - ChaCha20 算法
"""
from Crypto.Cipher import ChaCha20
# 加密数据(明文标记之前的部分)
data = bytes([
0x0B, 0xB0, 0xB5, 0x4E, 0x89, 0x4E, 0x9D, 0x03, 0x93, 0x1D, 0x5B, 0xE5,
0x10, 0xE2, 0xEA, 0x13, 0x10, 0xBE, 0x60, 0x09, 0xD8, 0x16, 0x4A, 0xF0,
0x4B, 0xF8, 0xCB, 0xC6, 0x49, 0x39, 0x88, 0x10, 0x72, 0x00, 0x28, 0xB6,
0x0D, 0x5A, 0xCB, 0x49, 0xFB, 0x3D
])
# ChaCha20 密钥和 Nonce
key = bytes([
0x75, 0x2b, 0xcb, 0x44, 0x8b, 0xd1, 0x70, 0x53, 0xe6, 0xb5, 0x5c, 0xc4,
0xe6, 0xba, 0x1b, 0xe8, 0x75, 0x6d, 0x2d, 0xbb, 0x03, 0x89, 0x9e, 0xb6,
0x5e, 0xf5, 0xa7, 0xef, 0xf6, 0xde, 0x5e, 0xe7
])
nonce = bytes([
0x4b, 0xf6, 0x5b, 0x44, 0xe2, 0x79, 0x81, 0x1c, 0x36, 0x7f, 0x94, 0xcc
])
# 初始化 ChaCha20 并设置计数器为 1(偏移 64 字节)
cipher = ChaCha20.new(key=key, nonce=nonce)
cipher.seek(64)
# 解密并输出
decrypted = cipher.decrypt(data)
print(decrypted.decode('utf-8'))
# FLAG: flag{e26e86af-bb71-4bf5-9dec-e845b4f7b1c3}

浙公网安备 33010602011771号