您的位置:首页 > 理论基础 > 计算机网络

2020年第二届“网鼎杯”网络安全大赛青龙组题目“虚幻2”的一种解法

2020-06-03 06:01 309 查看

题干


附件下载 备用下载

解答

下载下来之后是一个名叫 file 的文件,用文本编辑器打开能看到 PNG 文件头和文件尾,用 pngcheck 读一遍没发现异常。

搜了下2018年“网鼎杯”题目“虚幻”的题解,发现是把图片拼成了汉信码。用 Python 的 PIL 库读出 file 文件各像素的 RGB 值可以发现它们总是取 0 或 255,那么就把图片的 RGB 通道分开,并且去掉白边(这里贴的图片为了易于查看放大了10倍):

G通道

R通道

B通道

根据 GBT 21049-2007,汉信码应该长这样:


观察可知应该将 RGB 通道分开得到的图片按 G, R, B 的顺序逐行拼接(拼接用的脚本是队友给的),拼完之后逆时针旋转 90 度,再把左下角的 7*7 的寻像标志旋转180度,似乎效果不错(这里贴的图片为了易于查看放大了10倍):

这张码扫不出来。然后因为题干提示要暴力修复,就写个脚本对图上 7*9 的空白区域(不是 7*10,因为寻像标志边上的格子本来就是空白的)进行随机填充,每个像素都有50%的概率被涂黑,如此生成了 1000 张图片,用中国编码手机客户端手动扫描(汉信码在线识别网站比赛时出错了…也许是提交的人太多了吧)发现一张也扫不出来,然后整个比赛过程中也没扫出来。

比赛结束后看网上别人的正确答案,得知需要把图像以右上到左下的对角线为轴作轴对称。轴对称后又随机填充生成了几张图片,大约有 50% 的图片可以扫描出 flag,结果如图:


处理图片用的脚本(包括轴对称)如下:

from PIL import Image
from random import randint

for k in range(5):
# 用到的三张图片就是上面说的 RGB 通道分开的图片(未放大10倍)
R = Image.open('solved_r.bmp')
G = Image.open('solved_g.bmp')
B = Image.open('solved_b.bmp')
GBR = Image.new('RGB', (31, 31))
TMP = Image.new('RGB', (7, 7))
GBRReadble = Image.new('RGB', (372, 372))

n_r = 0
n_g = 0
n_b = 0
p_r = R.load()
p_g = G.load()
p_b = B.load()
pim = GBR.load()
pimr = GBRReadble.load()
tmp = TMP.load()

for i in range(31):
if i%3 == 0:
for j in range(31):
pim[i, j] = p_g[j, n_g]
n_g = n_g + 1
elif i%3 == 1:
for j in range(31):
pim[i, j] = p_b[j, n_b]
n_b = n_b + 1
elif i%3 == 2:
for j in range(31):
pim[i, j] = p_r[j, n_r]
n_r = n_r + 1

for i in range(0, 7):
for j in range(0, 7):
tmp[i, j] = pim[i, j]

TMP = TMP.rotate(180)
tmp = TMP.load()

for i in range(0, 7):
for j in range(0, 7):
pim[i, j] = tmp[i, j]

for i in range(14, 23):
for j in range(24, 31):
if (randint(0, 1) == 0):
pim[i, j] = (0,0,0)

for i in range(372):
for j in range(372):
pimr[j, i] = (255,255,255)

for i in range(31,341):
for j in range(31,341):
pimr[j, i] = pim[(j-31)//10, (i-31)//10]

GBRReadble = GBRReadble.rotate(90)

filename = "gbr"+ str(k) + ".png"
GBRReadble.save(filename)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: