Week1
InfantRSA 50pt
|  |  | 
Affine 75pt
Affine_task.py
|  |  | 
exp.py
|  |  | 
not_One-time 150pt
not_One-time_task.py
|  |  | 
Flag重用可还行。
- 
可以获取任意数量密文 
- 
key space仅 26*2+10=62
这里用了一个统计方法。
先获取很多个密文c,将其他密文和第一个密文异或,消去flag,得到的就只有ki = key0 ^ keyi。
我们的目标是要获得这个key0。
长度都是43。
考虑key0的第i位字母,只能是string.ascii_letters+string.digits中的某一个ch。
那么这个特定的ch与其他keyi对应位置的字母异或得到的结果,就只有62种可能,将其看作一个集合set_ch。
且不同的ch得到的结果集合set_ch中至少是会有几个元素是不同的,即不同的ch得到的结果集合不相同。
那么,(当我们掌握足够多的数据时)我们就可以通过每一位字母得到的结果集合,去反推这个字母是什么。
例如:如果key0第i位字母是a,那么ki = key0 ^ keyi的所有62种可能的结果就是set_a = {a^a, a^b, ..., a^A, a^B, ..., a^0, ..., a^9};如果key0第i位字母是b,那么ki = key0 ^ keyi的所有62种可能的结果就是set_b = {b^a, b^b, ..., b^A, b^B, ..., b^0, ..., b^9};。。。。。。
且这些set_a != set_b != ... !=set_9。
在第i位,如果我们得到的结果集合是set_a,那么我们就可以推断出这一位的字母一定是a。
可能画图会更清晰一些。
算一些没用的:1000组数据,这个结果集合的长度不满62的概率。
也就是说有一个位置,1000次都没选中。 $$ P = C_{62}^{1} (1 - \frac{1}{62})^{1000} \approx 5 \times 10^{-6} $$ 所以1000组数据足够了
|  |  | 
Reorder 75pt
Input: hgame{ABCDEFGHIJKLMNOPQRSTUVWXY}
Output: {hHDCFABGemEaJIgPKXTSVQRWONUM}YL
Encrypted flag: {hmt$5jUIem+aLpgm3!TA0uTnReiP}!_
|  |  | 
Week2
Verification_code 125pt
Verification_code.py
|  |  | 
exp.py
|  |  | 
Remainder 150pt
Remainder_task.py
|  |  | 
关键在于assert 256 < len(msg) < 384,也就是说m在2048~3072bit之间。
但是p, q, r只有1024bit,显然只用其中一个是算不出来m的,需要把模数扩大下。
exp.sage
|  |  | 
Inv 175pt
有点意思,Subs也能当作一个运算。
|  |  | 
notRC4 200pt
notRC4_task.py
|  |  | 
逆一下fun2
exp.py
|  |  | 
Week3
RSA? 150pt
RSA_task.py
|  |  | 
n = p*q + r迷惑行为。
看了一下,n是一个素数,GF(n)上开平方根。
exp.sage
|  |  | 
ToyCipher_XorShift 175pt
task.py
|  |  | 
就逆一个xor shift
exp.py
|  |  | 
Exchange 150pt
中间人攻击,就是写脚本费时间。
|  |  | 
Feedback 150pt
task.py
|  |  | 
看图解题。
   
   
exp.py
|  |  | 
Week4
CBCBC 150pt
task.py
|  |  | 
没图?那就自己画一个。
   
考虑第一段M1,即flag[:16]。
解密完了会unpad,unpad成功后会返回Decryption done,否则返回sth must be wrong。
可以在这边操作下。
   
对mid_1(即IV1)异或上一些东西,来逐字节爆破。
例如,如果解密出来的m满足???????????????\x01,那么就会显示Decryption done,所以我们可以在mid_1的最后一字节异或上某个东西i(尝试所有256种可能),使它回显Decryption done,那么原来的m的最后一位就肯定是i ^ 1;如果解密出来的m满足``??????????????\x02\x02,也会显示Decryption done,可以把mid_1的最后一位设置成\x02(我们已经知道什么时候会是\x01了,所以再异或一下1^2就能把它给设置成\x02),在倒数第二位处尝试256种可能i,使它回显Decryption done,那么原来的m的倒数第二位肯定就是i ^ 2 。一直这样下去,可以通过平均256/2 * 16 = 2048 次尝试爆破出flag[:16]`。
考虑第二段M2,即flag[16:32]。
   
同样的思路,可以对mid_2(即IV_2)异或上一些东西,逐字节爆破M2。
后面2段M3, M4也是一样,分别对C1, C2异或上一些东西,逐字节爆破M3, M4。
exp.py
|  |  | 
ToyCipher_Linear 175pt
整个加密过程可以用一个$32 \times 224$的矩阵来表示,以前也出过一道基本一样的题目。
太费时间了,懒得写了。
|  |  | 
   
  