CTF(Capture The Flag)中文一般译作夺旗赛,在网络安全领域中指的是网络安全技术人员之间进行技术竞技的一种比赛形式。CTF起源于1996年DEFCON全球黑客大会,以代替之前黑客们通过互相发起真实攻击进行技术比拼的方式。已经成为全球范围网络安全圈流行的竞赛形式。——百度百科

如主办方所言,本次MoeCTF2022面向全国全体准大学生举办,题目难度不高且坡度平缓,0基础新生可以通过本次比赛对信息安全夺旗赛有一个基础且全面的认识。但由于我水平有限,仅对本次比赛的一小部分题目做部分赏析。

计算机技术基础

run me (25’)

下载得runme.exe文件,双击打开闪退。将文件拖入cmd回车运行得Flag。

CCCCC (25’)

下载得CCCCC.c文件,配置C语言环境运行得Flag。

Python (25’)

同上,配置Python环境运行得Flag。

run me 2 (25’)

配置虚拟机安装Linux系统运行文件,我选择了VMware Station。
安装虚拟机费了我老大劲儿,参考了一下CSDN上的野生安装文档
联网运行程序得Flag。

古典密码

ABCDEFG~ (25’)

题目描述:字母儿歌你会倒着唱吗?(大写)
下载解压得密文:
moectf{18 24 26 13 08 18 13 20 26 15 11 19 26 25 22 07 08 12 13 20}
对照倒序字母表数数or写脚本破解得Flag。

小小凯撒 (50’)

密文:kqEftuEUEftqOADDqoFRxmsOAzsDmFGxmFuAzE
写脚本枚举得Flag。
值得注意的是它的hint2:*每个单词首字母大写,其余小写,无分隔。*结合脚本与Flag可知,此处的凯撒密码如果由Z->A,则大小写改变。

凯撒变异了 (50’)

题目描述:神秘的变异人凯撒来自track曾经的出发地:114514市。
密文:ZpyLfxGmelDeftewJwFbwDGssZszbliileadaa
移位为1、1、4、5、1、4……循环。
大小写改变同上。

Vigenere (100’)

凑了半天结果网上有破解这类密码的脚本。
请面向搜索引擎。
附:维吉尼亚密码——CTF Wiki

现代密码学

密码学之入门指北 (25’)

运行程序得Flag。

隐写等杂项

Hide-and-seek (25’)

(笑)

Misc杂项之入门指北 (25’)

密文:.-- . .-… …— — – . …–.- …- — …–.- – … …-- -.-. …–.- .---- …- -.-. -.- -.-- -.-.–
摩斯密码解码得Flag。

Rabbit (50’)

小兔子能有什么坏心思呢?
查看十六进制编码,得到加在文件末尾的神秘字符:

1
2
########(=^-^=)###U2FsdGVkX1+EPlLmNvaJK4Pe06nW0eLquWsUpdyv3fjXM2PcDBDKlXeKupnnWlFH
ewFEGmqpGyC1VdX8

Base64破解,无果,得到有意义的前缀 Salted__。放入搜索引擎,得到AES加密等花里胡哨的加密方法,其中有Rabbit加密。使用Rabbit加密解码后得Flag。
为什么会固定出现Salted__前缀,具体原因未知。

想听点啥? (200’)

文件内容:
whatdoyouliketohear.zip
|-- whatdoyouliketohear.mp3
|-- whatdoyouliketohear.mscz
|-- mister.7z
    |-- flag.txt
    |-- qaq.py
这是本次CTF为数不多的一道音频隐写题。我本以为这题和图片隐写差不多,因为音频也可以采取LSB等隐写方式,甚至可以把信息藏入频谱图。然而我还是小了,在一遍又一遍地欣赏了MP3文件里的美妙阴乐后,方才意识到附带的.mscz文件可能有玄机。面向搜索引擎发现这是个乐谱文件,使用MuseScore打开后,我不得不佩服出题人的艺术创作能力。

抽象的艺术。
在经历了几十遍尝试后,我放弃了。因为我不理解这个圈是大写字母O还是数字0,这条线是大写字母I还是小写字母l(最后友人试出密码证明它是数字1)。
抽象,太抽象了。
更抽象的是这个名为Flag实际又不是Flag的文本文件:

1
2

,6+,C]:2Al2BR\B

打开py文件:

1
2
3
4
5
6
7
8
# this is not flag, but real flag will be encrypted in same algorithm.
flag = 'moectf{xxxxxxxxxxxxxxxxxxxxx}'

def encrypt(src: str) -> bytes:
return bytes([ord(src[i]) ^ ord(src[i-1]) for i in range(1, len(src))])

with open('flag.txt', 'wb') as out:
out.write(encrypt(flag))

仔细阅读代码,发现是“已知加密算法与密文求明文”的套路。研究加密算法,encrypt函数输入string类型src形参,输出bytes类型。return后跟的括号有点多,外层是bytes([]),即将一个列表转化为字节串。内层是字符串遍历,从第二位开始,src的每一位字符的ASCII码与其前一位字符的ASCII码做按位异或运算。最后调用函数,传入实参flag,将密文写入flag.txt。
异或运算可逆,可以采取a^b^b=a的方式得出答案。但是本题计算量不大懒得研究逻辑,我决定采用爆破的方式。
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
f1 = open("flag.txt")
target = bytes(f1.read(), encoding="UTF-8")
f1.close()

testflag = list(flag)
for i in range(7, 28):
for k in range(32, 127):
testflag[i] = chr(k)
if (ord(testflag[i]) ^ ord(testflag[i-1])) == target[i-1]:
break
flag = ''.join(testflag)
print(flag)

易得flag.txt文本内容长度为28,与上文flag字符串的长度差一,刚好是两两按位异或后的结果长度.除去前面的"moectf{“和末尾的”}",得出爆破范围为7~28。采用ASCII可显示字符逐位尝试,与前一位进行加密运算后和target对应位的值进行比较,如此反复后得出Flag。
需要注意的是字符串与字节串的转换。

写在最后

截至2022/8/26/19:00,笔者共在本次比赛中获得1050分,排名73位。
由于时间有限,仅写出以上几道题的wp。