引言
2021 全国大学生信息安全竞赛创新实践能力赛 (CISCN)
比赛时间: 2021-05-15 09:00 ~ 2021-05-16 09:00
比赛官网: http://www.ciscn.cn/
一年一度的国赛又来了,连续打 24h 太难受啦!
今年国赛正好碰上咱 ddl,打完国赛又去赶 ddl 去了,太难顶了。
于是一直也没时间来整理 WriteUp,今天摸鱼,就来写几道 misc 题目好了。
第一阶段
tiny traffic
抓包文件导出 http 对象
192.168.2.1 是路由器,192.168.2.193 是台 NAS,5000端口开了个 python web 服务。看上去最后的是个 rpc
flag_wrapper
导出内容,解压之后得到
test
和 secret
用 brotli 解压
import brotli
with open('test', 'rb') as fin:
s = fin.read()
x = brotli.decompress(s).decode()
print(x)
with open('secret', 'rb') as fin:
s2 = fin.read()
y = brotli.decompress(s2)
print(y)
with open('secret1', 'wb') as fout:
fout.write(y)
发现 test
是 Protocol Buffzers
syntax = "proto3";
message PBResponse {
int32 code = 1;
int64 flag_part_convert_to_hex_plz = 2;
message data {
string junk_data = 2;
string flag_part = 1;
}
repeated data dataList = 3;
int32 flag_part_plz_convert_to_hex = 4;
string flag_last_part = 5;
}
message PBRequest {
string cate_id = 1;
int32 page = 2;
int32 pageSize = 3;
}
里面定义了传输中的格式。
而secret
是序列化后的密文。
先下载 Protobuf 编译器和调用编译器的接口,这里直接用 python 了
https://github.com/protocolbuffers/protobuf/releases/
解码得到
1: 200
2: 15100450
3 {
1 {
12: 0x35343332
}
2: "7af2c"
}
3 {
1: "7889b0"
2: "82bc0"
}
4: 16453958
5: "d172a38dc"
发现并不是很清楚,先生成 python 代码
protoc.exe test.proto --python_out=.
然后写个脚本解码
import test_pb2
r = test_pb2.PBResponse()
with open('secret1', 'rb') as fin:
s = fin.read()
r.ParseFromString(s)
print(r)
得到
code: 200
flag_part_convert_to_hex_plz: 15100450
dataList {
flag_part: "e2345"
junk_data: "7af2c"
}
dataList {
flag_part: "7889b0"
junk_data: "82bc0"
}
flag_part_plz_convert_to_hex: 16453958
flag_last_part: "d172a38dc"
拼成 flag,其中 junk_data
是垃圾数据不要
CISCN{e66a22e23457889b0fb1146d172a38dc}
running_pixel
开局一张动图
一共有 382 帧,逐帧查看,导出每一帧。
import os
from PIL import Image, ImageSequence
def parseGIF(gifname):
# 将gif解析为图片
# 读取GIF
im = Image.open(gifname)
# GIF图片流的迭代器
iter = ImageSequence.Iterator(im)
# 获取文件名
file_name = gifname.split(".")[0]
index = 1
# 判断目录是否存在
pic_dirct = "imgs/{0}".format(file_name)
def mkdirlambda(x): return os.makedirs(
x) if not os.path.exists(x) else True # 目录是否存在,不存在则创建
mkdirlambda(pic_dirct)
# 遍历图片流的每一帧
for frame in iter:
print("image %d: mode %s, size %s" % (index, frame.mode, frame.size))
frame.save("imgs/%s/frame%d.png" % (file_name, index))
index += 1
if __name__ == "__main__":
parseGIF("running_pixel.gif")
随意看前几帧,放大来看,发现有个像素点在动。
所以题目名称中的跑动的像素应该就是这个了。
提取得到这个像素点颜色 RGB 为 (233, 233, 233),而背景色是 (247, 247, 247)
另外发现每隔一定帧数,这个像素点会消失,然后在另一个地方出现。
于是写个脚本跑所有的帧,把这个像素点的轨迹画出来,每消失一次保存一张图片。
"""
MiaoTony
"""
import cv2
import os
from PIL import Image, ImageOps
import numpy as np
im2 = Image.new('RGB', (400, 400))
last_cnt = 0
# list(os.walk('imgs'))[0][2]
for cnt in range(1, 383):
img_name = f'imgs/frame{cnt}.png'
im = Image.open(img_name)
rgb_im = im.convert('RGB')
# print(rgb_im.size)
# (400, 400)
width = rgb_im.width
height = rgb_im.height
for j in range(height):
for i in range(width):
r, g, b = rgb_im.getpixel((i, j))
if (r, g, b) == (233, 233, 233):
# print('cnt', cnt)
# print(i, j)
if cnt != last_cnt + 1:
print(cnt)
im2.save(f'cnt{cnt}.png')
im2.putpixel((j, i), (255, 255, 255))
last_cnt = cnt
im2.show()
im2.save('final.png')
最后的图是这样的。
手动按顺序把出来的图片各个字母提取出来。
(其实更好的思路是每次像素点消失的时候新建一张图的……看的要眼瞎了
出来是个 UUID 的格式。
12504D0F-9DE1-4B00-87A5-A5FDD0986A00
裹上 CISCN,然后发现 19:00,草,交不上去了!
心态炸了!!!
(后来看大佬 wp 说这里还要转成小写再交上去
CISCN{12504d0f-9de1-4b00-87a5-a5fdd0986a00}
第二阶段
隔空传话
题目描述:Alice 和 Bob 进行隔空传话的时候被我“偷听”到了,你能帮我分析分析他们在交流什么吗?
注意:flag形式:CISCN{XXXXX}
你们又在加密通信!!!
(这题复现的,然而过去有一段时间了,当时找的资料忘记记录了,现在又懒得再找了,就佛系写一写8
(还是去找了下资料 唉
开局给了一堆格式类似的数据。
查了一下发现是 SMS 短信里用的 PDU 编码。
还找到了 在线 PDU 格式编码/解码的网站
https://tool.letmetellyou.xyz/pdu/ 或者 http://www.sendsms.cn/pdu/
在 pypi 找到了一个 python 的 module: smspdu
手动解码前几条
发现是
hello,bob!what is the flag?
the first part of the flag is the first 8 digits of your phone number
那其他部分呢
看看你能从这些数据里发现什么?w465
5b4c4ce7b6d5edd6d5cb961fca84f193ca71471db155b62c9df5ea1ebed933929de07bebcdb7853ddaf6303ac6fbaaa0fff6bb23cbfefbecd716028173e1259796fbeebf3f12f43ea54fcfeee54f11c8
f5a91d7cb54fd0b83e927bbfbe7d6a121d32649748f453ca0fbffe56162c5e5c4e3f757804e9aeb17a8b441513c78591c43c9493bb2567c6a475e69c59912c9e2f0785fe43761a523efa7c7479effdbf
...
flag 的第一部分是号码的前8位,+8615030442000,那就是 15030442
。
之后就一堆 hex 编码。
写个脚本提取并导出到文件。
from smspdu.codecs import GSM, UCS2
from smspdu.easy import easy_sms
from binascii import unhexlify
# x = easy_sms('04910180F6040D91685130402400F0000012405291443408A0E65A381723DFC6E21ACD4C868971B3724E76138BCDE2F28D6C0BC76431F24C66A3E56E349C99569B8DC330B3D86C2ED76C319B6C5C2BD7C6B4F2CC7CABDD70305A39172E8B63B7304E4CA3C56AB1D9F886ABE56263DA6C9CA3E56662B1AC66BB8D6D61DAAD56B6E5C6B55C2E261BE7CA3233EC86AB99CBB4D9CD160BD764B3B2397C1BDF68B75CD96C268BCD')
# print(x)
with open('data.txt', 'r', encoding='utf-8') as fin:
s = fin.read()
l = s.strip().split('\n')
l1 = l[4:]
x = ''
for i in l1:
tmp = easy_sms(i)['content']
print(tmp)
x += tmp
print(x)
# x.encode()
y = unhexlify(x)
with open('decode.dat', 'wb') as fout:
fout.write(y)
binwalk 一下发现有张 png 图片,提取出来。
然而发现打不开……
然后比赛的时候试了用 PCRT 来修复,但没成功。网上找了个工具然后要收钱,气死喵喵了!!!
后来发现需要按照时间顺序排序。
唉好烦(
"""
MiaoTony
"""
from smspdu.codecs import GSM, UCS2
from smspdu.easy import easy_sms
from binascii import unhexlify
with open('data.txt', 'r', encoding='utf-8') as fin:
s = fin.read()
l = s.strip().split('\n')
l1 = l[4:]
x = []
ts = []
for i in l1:
tmp = easy_sms(i)
content = tmp['content']
t = tmp['date']
x.append(content)
ts.append(t)
l2 = sorted(zip(x, ts), key=lambda x: x[1])
l3 = list(zip(*l2))[0]
info = ''.join(l3)
# type(info)
# str
y = unhexlify(info)
with open('decode2.dat', 'wb') as fout:
fout.write(y)
得到一张图,终于能打开了,而且整个数据就是一整张图片。然而还是没思路。
看了大佬们的 wp 才发现,w465
是宽度为 465 的意思……草!
改了之后得到
于是 flag 就是
CISCN{15030442_b586_4c9e_b436_26def12293e4}
第三阶段
robot
题目描述:分析给出的机器人仿真程序和流量包,提取机器人控制程序控制机器人写出的字符串,flag为”CISCN{md5(机器人绘制的字符串)}”(md5值小写)
Robot.rspag
是 RobotStudio 文件,cap.pcapng
是网络流量抓包,Control
目录下是一个图形化的基于 C# 写的一个图形化上位机,以及对应的 dll 文件。
用 ILSPY 反汇编 exe,发现其实都是调用底层 dll 提供的 SDK 接口,并没有自己去实现网络通信相关的功能。
参考相关的资料也是如此。
https://blog.csdn.net/weixin_39090239/article/details/81275759
https://blog.csdn.net/weixin_42837024/article/details/100542204
https://zhuanlan.zhihu.com/p/62390089?ivk_sa=1024320u
https://developercenter.robotstudio.com/
之后在流量里发现有一系列设置坐标的,盲猜这个就是机器人画的东西了。
于是写个脚本提取一下,画张图。
"""
MiaoTony
"""
import re
import cv2
import os
from PIL import Image
import numpy as np
im = Image.new('RGB', (400, 400))
width = im.width
height = im.height
with open('test.dat', 'r', encoding='utf-8') as fin:
s = fin.read()
re_pos = re.compile(r'tgPos{(\d+)}\.Value\.(\[\d+,\d+,\d+\])')
l = re_pos.findall(s, re.M)
with open('data.dat', 'w', encoding='utf-8') as fout:
fout.write(str(l))
points = [eval(x[1])[:2] for x in l]
# l = [[27, 36, 0], [28, 35, 0], [29, 35, 0], [31, 35, 0], [32, 35, 0], [33, 35, 0], [35, 35, 0],
# [36, 35, 0], [37, 35, 0], [39, 34, 0]]
for i in points:
im.putpixel(i, (255, 255, 255))
im.show()
im.save('info.png')
# easy_robo_xx
还原出来机器人绘制的字符串为 easy_robo_xx
md5 d4f1fb80bc11ffd722861367747c0f10
CISCN{d4f1fb80bc11ffd722861367747c0f10}
小结
感谢 360 首次将 CTF 靶场变成了考场。
初赛就这么肝也太顶了,打不动了 Orz
华东北赛区也太卷了吧,喵呜呜呜。
唉,不过咱没进复赛,喵呜呜呜呜。
害,问题不大,可能也是最后一次国赛了吧,难得大师傅们带咱玩,也非常感谢队友一起打。
之后大佬们好好玩,咱溜了溜了喵。