2020 CSICTF WriteUp
“csictf team” 是印度 VIT 大学(Vellore Institute of Technology)计算机学会(CSI)学生分部所运营的团队
Misc
Gradient sky(图片隐写)

查看字符串拿到 flag
1 | strings sky.jpg |
unseen(通道隐写 + Steghide 隐写 + Whitespace)
对 nyc.png 做 LSB 位平面分析,红色通道第 0 位平面左上角能看到数字

解 morse.wav 的摩斯电码,得到
1 | SEARCH-SOMEWHERE-ELSE |
这个提示说明还要继续在音频里找隐藏内容。用图片得到的数字作为 steghide 密码
1 | steghide extract -sf morse.wav -p 42845193 |
提取出 flag.txt。该文件表面上是空白,实际是 Whitespace 语言代码,解码后得到 flag
1 | csictf{7h47_15_h0w_y0u_c4n_83c0m3_1nv151813} |
Panda(ZIP 爆破)

爆破出密码是 2611,提取出两张图片
逐字节比较两张图拿到 flag
1 | from pathlib import Path |
1 | csictf{kung_fu_p4nd4} |
Crypto
little RSA(分解 n)
题目给了
1 | c=32949 |
分解 n 得到 p,q

1 | from Crypto.Util.number import long_to_bytes |
解出为 18429 解压密码
Rivest Shamir Adleman(分解 n)
和上题一样的方法

1 | from math import isqrt |
Modern Clueless Child(XOR)

题目给的是
1 | 52f41f58f51f47f57f49f48f5df46f6ef53f43f57f6cf50f6df53f53f40f58f51f6ef42f56f43f41f5ef5cf4e |
按 f 分割得到
1 | 52 41 58 51 47 57 49 48 5d 46 6e 53 43 57 6c 50 6d 53 53 40 58 51 6e 42 56 43 41 5e 5c 4e |
转成 ASCII 得到一段密文
1 | RAXQGWIH]FnSCWlPmSS@XQnBVCA^\N |
将题目给的 Key 转为 ASCII 字符
1 | '1' = 0x31 |
然后对密文循环进行 XOR
1 | cipher_hex = "52f41f58f51f47f57f49f48f5df46f6ef53f43f57f6cf50f6df53f53f40f58f51f6ef42f56f43f41f5ef5cf4e" |
得到 csictf{you_are_a_basic_person}
Quick Math(低指数广播攻击)

1 | from math import prod, gcd |
Mein Kampf(Enigma M4 参数残缺恢复)

题目给的文件内容核心是
1 | M4 UKW $ Gamma 2 4 $ 5 9 $ 14 3 $ 5 20 fv cd hu ik es op yl wq jm |
题目描述说:
1 | some data was corrupted during transmission |
所以里面的 $ 就是传输损坏的字段,需要我们恢复
根据内容基本可以判断是德国 Enigma M4
1 | M4 -> 四转子 Enigma |
Enigma M4 的薄反射器一般是
1 | UKW B |
普通转子可以从 I 到 VIII 里选 3 个,且顺序有影响
1 | I II III IV V VI VII VIII |
非常小,直接暴力破解即可
1 | from itertools import permutations |
得到 flag:csictf{no_shit_sherlock}
The Climb(希尔密码)

theclimb.java 里核心逻辑是矩阵加密,这是典型的希尔密码
1 | rmatrix[i] += kmatrix[i][j] * tmatrix[j]; |
源码里给了 key:gybnqkurp
长度是 9,所以是 3×3 矩阵
1 | g y b |
转换成数字,也就是 a=0, b=1, ..., z=25
1 | K = [ |
因为源码是加密程序,所以我们要反过来做解密
1 | C = K × P mod 26 |
求出矩阵 K 在模 26 下的逆矩阵
1 | K^-1 = [ |
然后把密文每 3 个字符一组解密,解出来是
1 | hillshaveeyesxx |
最后的 xx 是源码里自动补齐分组长度时加的 padding
得到 flag
1 | csictf{hillshaveeyes} |
Reverse
Esrever(算法破解)

esrever.py 里有四个加密函数
1 | enc1(text) # 随机 Caesar 偏移 |
加密流程是
1 | Encrypted Key = enc4(enc4(encryptedKey)) |
所以解密时要完全倒过来
1 | Encrypted Key -> inv_enc4 -> inv_enc4 -> 爆破 enc1 得到 key |
1 | from string import ascii_lowercase |
因为 enc1 会把 { 和 } 也映射成小写字母
在对应 Caesar 偏移下
1 | { -> a |
所以得到 flag
1 | csictfaesreverisjustreverseinreverserightc |
pydis2ctf(Python 反汇编)

C1cipher.txt 里面核心反汇编是
1 | LOAD_CONST 1 ('') |
翻译成看的 Python 代码就是
1 | def C1(text): |
所以 C1 的加密公式是
1 | cipher_char = chr(2 * ord(plain_char) - len(text)) |
反过来就是
1 | plain_char = chr((ord(cipher_char) + len(text)) / 2) |
C2cipher.txt 还原出来是
1 | def C2(inpString): |
也就是每个字符和 'S' 异或
但是实际解题时,对 encodedflag.txt 直接反 C1 就能得到 flag;C2 更像是干扰项
1 | import ast |
得到 flag:csictf{T#a+_wA5_g0oD_d155aSe^^bLy}