2023中国工业互联网安全大赛总决赛部分题解

来旅游的,头次场景题0解(全场),运气太差抽的都是0解题。。。。

部分环境很糟糕(狗头保命),搞了个相册站,欢迎参观:https://photo.iloli.moe,头次打线下CTF(坐牢坐牢)

gigached

下载题目,010打开发现是一个mp4文件,加个后缀发现是gigached(Can you Feel My Heart~)

img

结合题目猜测是要让我们获取视频的LSB,ffmpeg简单分离一下视频帧

1
ffmpeg -i gigached.mp4 -o frames_%4b.png

img

然后写个脚本挨张提取PNG LSB通道数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# encoding=utf-8
from PIL import Image
def getlsb(f1, f2):
tmp = Image.open(f1)
w, h = tmp.size
cnt = 0
data = ""
for height in range(0, h):
for weight in range(0, w):
pixel = tmp.getpixel((weight, height))
# 处理三通道(RGB)
if cnt % 3 == 0:
cnt += 1
data += str((int(pixel[0]) % 2))
if cnt % 3 == 1:
cnt += 1
data += str((int(pixel[1]) % 2))
if cnt % 3 == 2:
cnt += 1
data += str((int(pixel[2]) % 2))
with open(f2, "wb") as file:
for i in range(0, len(data), 8):
t = int(data[i: i + 8], 2)
file.write(chr(t))
t = ""
file.close()
for i in range(1, 423):
filename = str("frames_" + str(i).zfill(5) + ".png")
new = filename
output = str("output_" + str(i).zfill(5) + ".txt")
out = output
getlsb(new, out)

结果得到

img

然后挨个查看txt文本数据,看了一圈后发现只有前几个文件有flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
./output_00002.txt: binary file matches
./output_00003.txt: binary file matches
./output_00004.txt: binary file matches
./output_00005.txt: binary file matches
./output_00006.txt: binary file matches
./output_00007.txt: binary file matches
./output_00008.txt: binary file matches
./output_00009.txt: binary file matches
./output_00010.txt: binary file matches
./output_00011.txt: binary file matches
./output_00012.txt: binary file matches
./output_00013.txt: binary file matches
./output_00014.txt: binary file matches
./output_00015.txt: binary file matches
./output_00016.txt: binary file matches

整理得到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
8:dp6UYHfO
8:NZhyAEYx
8:Js8o3024
8:l+je3k5k
8:aJmsL+Hx
8:w43oQ3oz
8:XjTT3/LQ
8:qF4fuu/w
8:MNqZVqiA
8:Q3vzixxY
8:QYbnuQ==
8: the key
8: isgYpt3
8:GvM7X1A1
3:CoT

根据上文,结合压缩包注释给出的代码,逆推一下即可解得flag(实际上就是某密码管理软件的加密过程,只不过脚本要上网才能搜到,结合比赛时选手开的热点很难不怀疑有人偷偷上网,小声说)

1
2
3
4
5
6
7
8
9
10
11
# 脚本给的,套,就嗯套
def encrypt(key, source):
source = source.encode()
key = key.encode()
key = SHA256.new(key).digest()
IV = Random.new().read(AES.block_size)
encryptor = AES.new(key, AES.MODE_CBC, IV)
padding = AES.block_size - len(source) % AES.block_size
source += bytes([padding]) * padding
data = IV + encryptor.encrypt(source)
return data

解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def decrypt(key, source):
source = base64.b64decode(source)
key = key.encode() # 转换为字节类型
key = SHA256.new(key).digest()
IV = source[:AES.block_size]
decryptor = AES.new(key, AES.MODE_CBC, IV)
data = decryptor.decrypt(source[AES.block_size:])
padding = data[-1]
if data[-padding:] != bytes([padding]) * padding:
raise ValueError("Invalid padding...")
return data[:-padding].decode()
key = "gYpt3GvM7X1A1CoT"
flag = "dp6UYHfONZhyAEYxJs8o3024l+je3k5kaJmsL+Hxw43oQ3ozXjTT3/LQqF4fuu/wMNqZVqiAQ3vzixxYQYbnuQ=="
print(decrypt(key, flag))

flag{d53dbf36-444a-471d-a663-91a9e6f400e0}

img断网试一下午是真难绷(),只能说自己知识储备量不太全()

DNS_Query

给了流量包,tshark提取流量,写脚本提取dns记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
11111110100111100100101111111
10000010011001100001101000001
10111010001011110011101011101
10111010000011000110101011101
10111010010100100011001011101
10000010001011000100101000001
11111110101010101010101111111
00000000101101101001000000000
11011010011100010101101000001
11011101110010011011100111100
01100111001101110110110011000
10101001011110111100110011011
11110011110110110011011100011
10001101010001010000101111001
01101011111111110001100100101
11001101111100111010011110101
10001110100001111001110001001
11100000111110111111010110000
11011011100101110111011110001
11011101101011100000000000101
11110011000010100101111111101
00000000101001011011100010100
11111110001010010101101011100
10000010010000100100100010000
10111010111001110011111110010
10111010111010110111100101001
10111010010000110001000010011
10000010101011111001011111101
11111110110110010000100010000

然后写脚本还原

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from PIL import Image
from zlib import *
MAX = 29
pic = Image.new("RGB",(MAX,MAX))
str ="1111111010011110010010111111110000010011001100001101000001101110100010111100111010111011011101000001100011010101110110111010010100100011001011101100000100010110001001010000011111111010101010101010111111100000000101101101001000000000110110100111000101011010000011101110111001001101110011110001100111001101110110110011000101010010111101111001100110111111001111011011001101110001110001101010001010000101111001011010111111111100011001001011100110111110011101001111010110001110100001111001110001001111000001111101111110101100001101101110010111011101111000111011101101011100000000000101111100110000101001011111111010000000010100101101110001010011111110001010010101101011100100000100100001001001000100001011101011100111001111111001010111010111010110111100101001101110100100001100010000100111000001010101111100101111110111111110110110010000100010000"
i=0
for y in range(0,MAX):
for x in range(0,MAX):
if(str[i] == '1'):
pic.putpixel([x,y],(0,0,0))
else:pic.putpixel([x,y],(255,255,255))
i = i+1
pic.show()
pic.save("flag.png")

img

…等待更新

Author

IceCliffs

Posted on

2023-07-05

Updated on

2024-11-19

Licensed under

Comments