比赛记录
[Week 2] Fault!Fault!
题目描述:
1 | 机缘巧合之下,小Z意外获得了一张用于身份认证的加密芯片,这块芯片可以输入一定的信息,并输出签名后的结果。经过一段时间的逆向工作之后,小Z得到了其中的签名逻辑。 |
题目:
1 | from Crypto.Util.number import * |
梳理一下题目加密流程:
- 连接上靶机后,计时开始,限时300s(这么长的限时就暗示可能需要不断交互)
- 先通过一个proof_of_work,具体为通过哈希值,爆破四位十六进制串
- 通过proof后,生成RSA加密所需的p,q,e,n,phi,d等参数,然后可以有如下选项:
- 输入”S”,可以对任意明文m进行加密,并返回密文c及公钥对(n,e)
- 输入”F”,可以对任意密文进行故障解密,故障解密具体是什么意思一会儿讲
- 输入”C”,可以输入一个值,如果该值与d相等,则获得flag
其中,故障解密的代码如下:
1 | def decrypt(c,d,n,index): |
可以看到,相比于常规的RSA解密指数,用在故障解密中的指数d的index这一比特位发生了翻转,也就是第index比特位的0变成1,或1变成0。而这种翻转其实可以写成如下简单形式:
0变成1:
1变成0:
我们用这个指数对RSA解密,就得到:
而具体是加号还是减号,就取决于d的那一bit原本是0还是1,因此,我们就有了判别d的某一比特位的方法:
如果d的第index比特位是0,则:
也就是:
而如果d的第index比特位为1,则正好相反,以下式子成立:
因此,通过反复更改index并令其解密,我们就能得到d的所有比特位,然后就可以还原出d并上交得到flag。但是对于我的电脑来说,300s限制有点紧张,所以要不断掐掉proof过的慢的交互,不然很难完整复原d的所有比特位。不过之后发现,其实该容器的p,q,n,e都不会变,因此d也不会变,所以完全可以分两次攻击得到不同比特位,然后组合一下就好。
exp:
1 | from Crypto.Util.number import * |
[Week 2] EzLFSR
题目描述:
1 | 暂无 |
题目:
1 | from Crypto.Util.number import * |
老样子,先梳理题目加密流程:
- 题目把secret变为二进制列表后,作为掩码mask,flag由固定flag头尾及secret组成
- 给定LFSR的初始序列initState,与mask一样是一个长度为128的二进制列表
- 用LFSR生成256比特的流密码,并给出。要求我们反推出mask列表,从而求出secret
其中,LFSR的生成逻辑如下:
1 | def lfsr(state, mask): |
乍一看可能觉得不太好想,但是再一看,这不就是个GF(2)下的线性方程吗!这是因为:
- state[i] & mask[i],可以写成 state[i] * mask[i]
- output = output ^ (state[i] & mask[i]) ,其实就是把128个乘积在GF(2)下求和
那么这样一来就好做了,把mask当作128个变量组成的列向量,取128个output,就能求解一个满秩的矩阵方程如下:
求完后转回字符串,再套上flag头尾即可。
exp:
1 | from Crypto.Util.number import * |
[Week 2] What’s CRT?
题目描述:
1 | 先穿袜子后穿鞋,先当**后当爷 |
题目:
1 | from Crypto.Util.number import * |
不管是题目标题CRT,还是题目描述暗示孙子定理,都是告诉我们这题要用中国剩余定理。
首先,根据题目给的条件,能够很轻松的求出p、q、p‘、q’几个参数。那么由于:
1 | mq_ = pow(m,4,q_) |
可以先用中国剩余定理试一试。但是不行,那应该flag超长了,所以必须把p、q也用上。
而这个e是个偶数,是肯定和p-1,q-1都不互素的,又因为e比较小,所以扔上facrotdb上分解一下:
正好,他与phi的公因数也是4,因此把e拆开:
然后求e/4对phi的逆元d,正常RSA解密就能得到:
此时,我们就拥有了关于m^4的三个等式:
中国剩余定理组合,开四次根就能得到flag。
exp:
1 | from Crypto.Util.number import * |
有一个小细节需要注意,如果你按这个方式一直出不来,那么可以检查一下p’、q’是否求反了,是有这个可能性的。
[Week 2] 中间的那个人
题目描述:
1 | 小爱(Alice)和小爆(Bob)现在在神秘的幻想乡中需要进行远程通话,但是他们又不希望中间传递的信息被心怀不轨的人窃取——很显然,他们的通话需要加密。但是在双方并未事先沟通好的情况下,他们要如何协商好密钥呢? |
题目:
1 | from secret import flag |
一个典型的Diffie-Hellman密钥交换协议,其困难性依赖于离散对数在某些有限域下难以求解。但是观察题目生成有限域用的p较小而且较光滑,因此可以直接求解出离散对数,进而得到公用密钥key,然后AES解密即可。
exp:
1 | from Crypto.Util.number import * |
[Week 2] EzRSA
题目描述:
1 | 三个小问题。一个定理、一个常见的分解方式、一个不太常见的连分数分解(啥事连分数?) |
题目:
1 | from challenges.challenge1 import RSAServe as challenge1 |
一个交互题,要实现的目标就是分别通过他的三个challenge,就可以拿到flag。
那么接下来就一个一个challenge分析。
challenge1
题目:
1 | from Crypto.Util.number import * |
题目会给出一个gift,如下:
那么先同余性质转到模p下,然后费马小定理即可:
所以求gcd(gift-1,n)就能得到p,分解n后解密即可。
challenge2
题目:
1 | from Crypto.Util.number import * |
可以看出是p-1光滑,不多说了。
challenge3
1 | from Crypto.Util.number import * |
可以发现,题目的两个公钥n1、n2是按如下方式生成的:
可以看到,n1、n2有一个因数非常相近,几乎相等。那么我们把上面两式写成分式形式:
所以有:
因此将n1/n2进行连分数展开,就很有可能找到q1/q2这个收敛子。
完整交互
最后还需要把以上求解步骤全部写作交互下的(当然手动也行),exp:
1 | from Crypto.Util.number import * |