Misay's blog

Back

写在前面#

第一次参加学校认可度比较高的的比赛 解决了Crypto的两道赛题 以及Misc的一道赛题 明年继续加油~

check-little#

加密指数ee很小 但是由于明文key非常大导致无法对穷举kk对c+knc+kn开三次方

经过数据检查发现cc与NN不互素 且公因数为1024位 故得到 p = gcd(N,c)

分解NN 进行RSA解密

ezran#

考察python random库中getrandbits相关mt算法的攻击

源题2024-同济大学第二届网络安全新生赛CatCTF-wp-crypto | 糖醋小鸡块的blog (tangcuxiaojikuai.xyz) ↗

对于mt算法 其存在一个state初态,其为624个32bits数字 每轮调用getrandbits都会生成32位比特 同时更新state 而后续的shuffle也会调用环境下的state生成伪随机的位序下标,故而本题的思路为

从gift获取足够的关于state的位数信息 接着调用shuffle预测下标 从密文c中恢复flag

首先分析如何从3108轮中拿到getrandbits的部分位数

对于624 * 32的state 我们把它展开为长19968的向量ss对于我们由ss生成的任意一位bb (0或1) 都存在一个向量tt 满足

t⋅s=bt\cdot s=b

我们需要收集至少19968组方程 凑成满秩的空间 即可解出ss

r1r_1是8位的随机数 进行(pow(r1, 2i, 257) & 0xff)计算后得到的还是8位 与16位的随机数r2r_2进行异或 我们能直接取到r2r_2高8位

特别的 因为257=28+1257=2^8 + 1所以说当我们的指数幂2i2i为282^8的倍数的时候 由欧拉定理能够得到 (pow(r1, 2i, 257) & 0xff)=1

此时能得到r2r_2的高15位

综上 我们能获得的总位数是

3108×8+15×(3108−31088)×15=30684>>199683108 \times 8 + 15 \times(3108 - \frac{3108}{8})\times 15 = 30684 >> 19968

信息完全够我们恢复

参考源题的exp

但获取比特更分散 同时获取的noise更多 对脚本进行修改同时在s的解空间中进行一个穷举,能找到我们的解

*sk#

task.py

基于线性系统的非对称加密

简而言之就是基于两组私钥矩阵P$$Q进行多项式卷积加密 同时对公钥的矩阵进行

Ppub=R1⋅Pmod  S1P_{pub}=R_1\cdot P\mod S_1 Qpub=R2⋅Pmod  S2Q_{pub}=R_2\cdot P\mod S_2

的掩码混淆 加密用公钥 解密用私钥 这些都不是很重要

交互有两次 一次能进行一次选择明文Oracle 另一次需要你构造特殊的密文 和 私钥 来调用decrypt解出ticket 如果解出来就给你flag

我们每次加密的时候会进行一个带噪声u混淆 随机生成4个 解不了一点

而且encrypt接口也没有泄露任何有关原始密钥的任何信息 我们想解出(R,S)(R,S)也是不可能的

赛中就卡死在这了

赛后看到了NowayBack ↗战队师傅的复盘 发现利用我们这里enc pk p ticket的数量级差异 可以尝试直接打格子 尝试把ticket格出来 我们看看

数量级几乎是倍数的差距 我们可以尝试去看看有没有线性关系

我们把ticket记为tt 对tt的加密过程可以看成以下操作

先给你已知的公钥矩阵

P2×3′    Q2×3′P^{'}_{2\times3}\;\;Q^{'}_{2\times3}

随后进行一个计算

PP=∑i=01(∑j=02Pi,j(uitj    mod    p))PP=\sum^{1}_{i=0}(\sum^{2}_{j=0}P_{i,j}(u_it^{j}\;\;mod\;\;p)) QQ=∑i=01(∑j=02Qi,j(uitj    mod    p))QQ=\sum^{1}_{i=0}(\sum^{2}_{j=0}Q_{i,j}(u_it^{j}\;\;mod\;\;p))

外圈决定uu 内圈决定这个指数幂 随后我们也注意到P    QP\;\;Q里面都是比较大的量

未知量都是很小的

t    u0    u1    k1    k2    ⋯t\;\;u_0\;\;u_1\;\;k_1\;\;k_2\;\;\cdots

我们把它放在向量里面

我们以上面的计算式为例子 展开可以得到,因为 当j=0j=0时候 我们的u<pu<p 此时我们能刚好让一个u  mod  p=uu\;mod\;p=u暴露出来

PP=P0,0u0+⋯+P1,0u1+⋯PP=P_{0,0}u_0+\cdots+P_{1,0}u_1+\cdots

所以我们左短向量处这里就可以对应上u0    u1u_0\;\;u_1

我们很直白的展开

PP=P0,0u0+P0,1(u0t    mod    p)+P0,2(u0t2    mod    p)+P1,0u1+P1,1(u1t    mod    p)+P1,2(u1t2    mod    p)PP=P_{0,0}u_0+P_{0,1}(u_0t\;\;mod\;\;p)+P_{0,2}(u_0t^2\;\;mod\;\;p)+P_{1,0}u_1+P_{1,1}(u_1t\;\;mod\;\;p)+P_{1,2}(u_1t^2\;\;mod\;\;p)

另一边同理

QQ=Q0,0u0+Q0,1(u0t    mod    p)+Q0,2(u0t2    mod    p)+Q1,0u1+Q1,1(u1t    mod    p)+Q1,2(u1t2    mod    p)QQ=Q_{0,0}u_0+Q_{0,1}(u_0t\;\;mod\;\;p)+Q_{0,2}(u_0t^2\;\;mod\;\;p)+Q_{1,0}u_1+Q_{1,1}(u_1t\;\;mod\;\;p)+Q_{1,2}(u_1t^2\;\;mod\;\;p)

就很直接.. 构造

v=(u0,u0t    mod    p,u0t2    mod    p,u1,u1t    mod    p,u1t2    mod    p,−1)v=(u_0,u_0t\;\;mod\;\;p,u_0t^2\;\;mod\;\;p,u_1,u_1t\;\;mod\;\;p,u_1t^2\;\;mod\;\;p,-1)

对应矩阵也是很直白的

L=(100000P0,0Q0,00010000P0,1Q0,10001000P0,2Q0,20000100P1,0Q1,00000010P1,1Q1,10000001P1,2Q1,20000000PPQQ1)L=\begin{pmatrix}1&0&0&0&0&0&P_{0,0}&Q_{0,0}&0\\0&1&0&0&0&0&P_{0,1}&Q_{0,1}&0\\0&0&1&0&0&0&P_{0,2}&Q_{0,2}&0\\0&0&0&1&0&0&P_{1,0}&Q_{1,0}&0\\0&0&0&0&1&0&P_{1,1}&Q_{1,1}&0\\0&0&0&0&0&1&P_{1,2}&Q_{1,2}&0\\0&0&0&0&0&0&PP&QQ&1\\\end{pmatrix}

有

vL=(u0,u0t    mod    p,u0t2    mod    p,u1,u1t    mod    p,u1t2    mod    p  ,0,0,−1)vL=(u_0,u_0t\;\;mod\;\;p,u_0t^2\;\;mod\;\;p,u_1,u_1t\;\;mod\;\;p,u_1t^2\;\;mod\;\;p\;,0,0,-1)

我们取有-1的那一行yy 把y0y_0也就是uu提出来 就可以和第二个一起来解tt了 可以给后两行多一些权重 让这边更容易规约到0

对LL格基规约 然后取末尾为-1的行 取uu解tt

多打几次就出了

exp

*blurred#

task.py

一个oracle游戏 当你输入c = 1的时候 会抛硬币,即抽取随机1个比特的变量coin 如果coin是0 就给你返回一组NTRU类下的数据 否则给你一组随机的变量

我们分析一下这里的GenNTRU类

先随机构造三个多项式 f    g1    g2f\;\;g_1\;\;g_2 再计算

h1≡g1⋅f−1mod  (xn+1)(1)h_1\equiv g_1\cdot f^{-1}\mod (x^n+1) \tag{1} h2≡g2⋅f−1mod  (xn+1)(2)h_2\equiv g_2\cdot f^{-1}\mod (x^n+1) \tag{2}

由多项式带余除法可得

f(x)=Q(x)(x+1)+Rf(x)=Q(x)(x+1)+R

即

f(−1)=R≡f(x)mod  (x+1)f(-1)=R\equiv f(x)\mod (x+1)

也就是说对1 2两个式子 我们对其转化到模x+1x+1上进行 那么此时转移到更小的模域下 就会体现

h1(−1)≡g1(−1)⋅f−1(−1)mod  (x+1)h_1(-1)\equiv g_1(-1)\cdot f^{-1}(-1)\mod (x+1) h2(−1)≡g2(−1)⋅f−1(−1)mod  (x+1)h_2(-1)\equiv g_2(-1)\cdot f^{-1}(-1)\mod (x+1)

那么在这个时候 我们关注到此时的h1h_1 h2h_2 在模x+1x+1下都涉及到一个共通的f−1(−1)f^{-1}(-1)元素 相较于我们随机变量 更能被格基规约找到一个小的量,那么我们思路就比较明确了

  • 多次输入c=1,获取大量h1  h2h_1\;h_2的信息
  • 造格子 利用LLL判断哪些h1    h2h_1\;\;h_2来自NTRU,猜出coin
  • 猜出足够的coin 恢复我们的mt19937状态库state
  • 预测AES密钥 求出flag

NowayBack的师傅们给出的格子如下

L=(1h1(−1)h2(−1)0p000p)L=\begin{pmatrix}1&h_1(-1)&h_2(-1)\\0&p&0\\0&0&p\end{pmatrix}

一般来说我们求解的短向量的范数如果比较小 我们就可以认为数据来自NTRU 否则是随机的

后续根据区分出的coin还原MT求解flag即可

强网杯2025
https://www.zt2misay2.cn/blog/qwb2025
Author Misay
Published at 2025年10月20日