Misay's blog

Back

写在前面#

和DAWN的师傅们一起打了WMCTF2025 主要参与并负责了密码方向 SplitMaster&IshowSplit 两道以及 MISC方向 Pishing Mail的解出,各位学长都很给力,最终DAWN也是打进了前10,本文主要复现Crypto方向的5道赛题,以及MISC方向的两道赛题

Crypto#

SplitMaster#

task.py

函数split_master会根据接收的数组以及数字返回有关传入数字的比特的信息 保证总比特数不超过30 且连续比特长不超过24

我们需要利用20组已知的a和我们能得到的有关b的比特泄露gift求出私钥b

赛中想到利用构造 segment_bits = [10, 160, 10, 161, 10, 161],我们能将b比较均匀的拆成6个部分 拥有离散的10*3的比特泄露

转化为随机位置泄露的HNP问题 我们参考Tover师傅的博客板子 ↗

造格子然后去打即可,exp

格的参数还可以进一步优化 大概有1/3的概率能找到key,本地出了后交给 Ramoor师傅 ↗用代码打远程成功出了,拿下二血

赛后看到别的师傅找到一个Trick

构造 -257 513 -257 513的序列

Welcome to WMCTF2025
q:9861430895025459477553092372852393541874339091269599286733236011532282532345396778429343483337130529182773612573595360674235802007820723008241118435213327
> -257 513 -257 513
a:10311738079985788524348250930378887840235618248819905021512068084058439869758091860311941760876644520871282741083309749114892507621255837856268626603123599
gift:[30524567771060486261423907587778820949788903093067527468240286198675156055398, 45779902845695456433368637342563313580177390291673538250967582387199430778996]
bash

能拿到510位b的比特 那就很好做了 多取几组打格子即可

IshowSplit#

task.py

类似上题 是给定chunk泄露的HNP问题

通用的是造格子打的方法,这里关于noise的信息是

si≡ri,0ki,0+ri,1ki,1+ri,2ki,2mod  ps_i\equiv r_{i,0}k_{i,0}+r_{i,1}k_{i,1}+r_{i,2}k_{i,2}\mod p

我们知道ri,jr_{i,j}以及ki,jk_{i,j}的范围上界,就不难想到把ri,jr_{i,j}放到格子里面,用系数去配平ki,jk_{i,j},貌似这样就能出了,Polaris ↗的师傅就是这样做的 再用gift来验证

详细说就是

Bi≡Ai×key+simod  pB_i\equiv A_i\times key + s_i\mod p

消去keykey,得到

AiB0−A0Bi≡Ai(r0,0k0,0+r0,1k0,1+r0,2k0,2)−A0(ri,0ki,0+ri,1ki,1+ri,2ki,2)mod  pA_iB_0-A_0B_i\equiv A_i(r_{0,0}k_{0,0}+r_{0,1}k_{0,1}+r_{0,2}k_{0,2})-A_0(r_{i,0}k_{i,0}+r_{i,1}k_{i,1}+r_{i,2}k_{i,2})\mod p

左边是已知量,记为CiC_i,那么也就是

Ai(r0,0k0,0+r0,1k0,1+r0,2k0,2)−A0(ri,0ki,0+ri,1ki,1+ri,2ki,2)−Ci−tip=0    (i=1,⋯ ,9)A_i(r_{0,0}k_{0,0}+r_{0,1}k_{0,1}+r_{0,2}k_{0,2})-A_0(r_{i,0}k_{i,0}+r_{i,1}k_{i,1}+r_{i,2}k_{i,2})-C_i-t_ip=0\;\;(i=1,\cdots,9)

我们想随便求出一组ki,0,ki,1,ki,2k_{i,0},k_{i,1},k_{i,2}来恢复keykey,那就把这里的

9个等于0的方程放在格子里面 然后kk给放在右边,式子如下

[k0,3k1,1k1,2k1,3k2,1k2,2k2,3…k9,1k9,2k9,3−1][p0…000000000…0000p…000000000…000⋮⋮⋱⋮⋮⋮⋮⋮⋮⋮⋮⋮⋱00000…p00000000…000A1r0,1A2r0,1…A9r0,121920000000…000A1r0,2A2r0,2…A9r0,202128000000…000A1r0,3A2r0,3…A9r0,300100000…000−A0r1,10…000021920000…000−A0r1,20…000002128000…000−A0r1,30…000000100…0000−A0r2,1…000000021920…0000−A0r2,2…000000002128…0000−A0r2,3…000000000…000⋮⋮⋱⋮⋮⋮⋮⋮⋮⋮⋮⋮⋱00000…−A0r9,100000000…21920000…−A0r9,200000000…02128000…−A0r9,300000000…001C1C2…C900000000…00K]=[00…0k0,1×2192k0,2×2128k0,3k1,1×2192k1,2×2128k1,3k2,1×2192k2,2×2128k2,3…k9,1×2192k9,2×2128k9,3K]\begin{bmatrix} k_{0,3} & k_{1,1} & k_{1,2} & k_{1,3} & k_{2,1} & k_{2,2} & k_{2,3} & \dots & k_{9,1} & k_{9,2} & k_{9,3} & -1 \end{bmatrix} \begin{bmatrix} p & 0 & \dots & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & \dots & 0 & 0 & 0 \\ 0 & p & \dots & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & \dots & 0 & 0 & 0 \\ \vdots & \vdots & \ddots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \ddots & 0 & 0 & 0 \\ 0 & 0 & \dots & p & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & \dots & 0 & 0 & 0 \\ A_1 r_{0,1} & A_2 r_{0,1} & \dots & A_9 r_{0,1} & 2^{192} & 0 & 0 & 0 & 0 & 0 & 0 & 0 & \dots & 0 & 0 & 0 \\ A_1 r_{0,2} & A_2 r_{0,2} & \dots & A_9 r_{0,2} & 0 & 2^{128} & 0 & 0 & 0 & 0 & 0 & 0 & \dots & 0 & 0 & 0 \\ A_1 r_{0,3} & A_2 r_{0,3} & \dots & A_9 r_{0,3} & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & \dots & 0 & 0 & 0 \\ -A_0 r_{1,1} & 0 & \dots & 0 & 0 & 0 & 0 & 2^{192} & 0 & 0 & 0 & 0 & \dots & 0 & 0 & 0 \\ -A_0 r_{1,2} & 0 & \dots & 0 & 0 & 0 & 0 & 0 & 2^{128} & 0 & 0 & 0 & \dots & 0 & 0 & 0 \\ -A_0 r_{1,3} & 0 & \dots & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & \dots & 0 & 0 & 0 \\ 0 & -A_0 r_{2,1} & \dots & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 2^{192} & 0 & \dots & 0 & 0 & 0 \\ 0 & -A_0 r_{2,2} & \dots & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 2^{128} & \dots & 0 & 0 & 0 \\ 0 & -A_0 r_{2,3} & \dots & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & \dots & 0 & 0 & 0 \\ \vdots & \vdots & \ddots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \vdots & \ddots & 0 & 0 & 0 \\ 0 & 0 & \dots & -A_0 r_{9,1} & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & \dots & 2^{192} & 0 & 0 \\ 0 & 0 & \dots & -A_0 r_{9,2} & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & \dots & 0 & 2^{128} & 0 \\ 0 & 0 & \dots & -A_0 r_{9,3} & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & \dots & 0 & 0 & 1 \\ C_1 & C_2 & \dots & C_9 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & \dots & 0 & 0 & K \end{bmatrix} = \begin{bmatrix} 0 & 0 & \dots & 0 & k_{0,1} \times 2^{192} & k_{0,2} \times 2^{128} & k_{0,3} & k_{1,1} \times 2^{192} & k_{1,2} \times 2^{128} & k_{1,3} & k_{2,1} \times 2^{192} & k_{2,2} \times 2^{128} & k_{2,3} & \dots & k_{9,1} \times 2^{192} & k_{9,2} \times 2^{128} & k_{9,3} & K \end{bmatrix}

真的是很自然但又非常有效的思路 感谢星盟的师傅们!

后续有参考官方的wp

给出了命题paperExtended Hidden Number Problem and Its Cryptanalytic Applications | SpringerLink ↗

命题的情景是

Definition1 即

αix+ρiki≡βimod  p\alpha_ix+\rho_ik_i\equiv\beta_i\mod p

的情况 其中αi  βi  ρi\alpha_i\;\beta_i\;\rho_i我们都已知 kik_i知道一个上界 完美契合

在GPT师傅的帮助下实现了一个复现 思路大致如下给定 ((αi,βi,ρi)i=1d)({(\alpha_i,\beta_i,\rho_i)}_{i=1}^d)、(N=p)(N=p)、上界 (2μi)({2^{\mu_i}})

设 (ν=⌈log⁡2N⌉)(\nu=\lceil\log_2 N\rceil),取 (δ>0)(\delta>0) 使 (κDδ<1),(D=2d+1)(\kappa_D\delta<1),(D=2d+1)。

组装基矩阵

B=(NId00(α1,…,αd)δ/2ν0diag(ρ1,…,ρd)0diag(δ/2μ1,…,δ/2μd))B=\begin{pmatrix}N I_d & 0 & 0\\(\alpha_1,\dots,\alpha_d) & \delta/2^{\nu} & 0\\\mathrm{diag}(\rho_1,\dots,\rho_d) & 0 & \mathrm{diag}(\delta/2^{\mu_1},\dots,\delta/2^{\mu_d})\end{pmatrix}

目标向量

v=(β1 mod N,…,βd mod N,;δ/2,;δ/2,…,δ/2⏟d)v=\big(\beta_1\bmod N,\dots,\beta_d\bmod N,;\delta/2,;\underbrace{\delta/2,\dots,\delta/2}_{d}\big)

用 LLL(+Babai) 在格子 L=zB:z∈ZDL={zB:z\in\mathbb Z^D} 中找W≈vW\approx v。

解码

x′=round(Wd+1,2ν/δ),k′∗i=round(W∗d+1+i,2μi/δ)x'=\mathrm{round}\left(W_{d+1},2^{\nu}/\delta\right),\quad\\k'*i=\mathrm{round}\left(W*{d+1+i},2^{\mu_i}/\delta\right)

输出 (z≡x′(modN))(z\equiv x'\pmod N) 作为 xx。

这相对是这种限阶HNP的通用处理思路 造一个有放缩的格子 通过调整数据使得问题规划为CVP下BaBai可解的

最后再学习了一下鸡块师傅的造格方法 也是受益匪浅,我们来看看

既然

si≡ri,0ki,0+ri,1ki,1+ri,2ki,2mod  pBi≡Ai×key+simod  ps_i\equiv r_{i,0}k_{i,0}+r_{i,1}k_{i,1}+r_{i,2}k_{i,2}\mod p\\B_i\equiv A_i\times key + s_i\mod p

还给了keykey的已知位 我们展开一下不难得到

d=2100⋅gift1+2310⋅gift0key=d+u1+2110u2+2330u3d=2^{100}\cdot gift_1+2^{310}\cdot gift_0\\key=d+u_1+2^{110}u_2+2^{330}u_3

要求keykey实际上也就是求u1,2,3u_{1,2,3}

我们当时对于

Bi≡Ai×key+ri,0ki,0+ri,1ki,1+ri,2ki,2mod  pB_i\equiv A_i\times key + r_{i,0}k_{i,0}+r_{i,1}k_{i,1}+r_{i,2}k_{i,2}\mod p

不好造格子的主要原因就是我们右边没有一个可以暴露出来放到目标向量的一个”常量”,这里鸡块师傅的处理方式是手动乘已知系数的逆元,把最大的ki,2k_{i,2}给暴露出来,也就是

ri,2−1(Ai⋅key−Bi)≡ri,0ri,2−1ki,0+ri,1ri,2−1ki,1+ki,2mod  pr_{i,2}^{-1}(A_i\cdot key-B_i)\equiv r_{i,0}r_{i,2}^{-1}k_{i,0}+r_{i,1}r_{i,2}^{-1}k_{i,1}+k_{i,2}\mod p

这样子我们就能把ki,2k_{i,2}放到我们想要去规约的目标向量里面,然后带入上面关于keykey的等式,即

ri,2−1(Ai⋅(d+u1+2110u2+2330u3)−Bi)≡ri,0ri,2−1ki,0+ri,1ri,2−1ki,1+ki,2mod  pr_{i,2}^{-1}(A_i\cdot (d+u_1+2^{110}u_2+2^{330}u_3)-B_i)\equiv r_{i,0}r_{i,2}^{-1}k_{i,0}+r_{i,1}r_{i,2}^{-1}k_{i,1}+k_{i,2}\mod p

已知量全部先算好,令

Ci≡ri,2−1(Aid−Bi)mod  pai,0=ri,2−1Aimod  pai,1=ri,2−1Ai⋅2110mod  pai,2=ri,2−1Ai⋅2330mod  pbi,0=ri,2−1ri,0mod  pbi,1=ri,2−1ri,1mod  pC_i\equiv r_{i,2}^{-1}(A_id-B_i)\mod p\\a_{i,0}=r_{i,2}^{-1}A_i\mod p\\a_{i,1}=r_{i,2}^{-1}A_i\cdot2^{110}\mod p\\a_{i,2}=r_{i,2}^{-1}A_i\cdot2^{330}\mod p\\b_{i,0}=r_{i,2}^{-1}r_{i,0}\mod p\\b_{i,1}=r_{i,2}^{-1}r_{i,1}\mod p

问题就变为

Ci+ai,0u1+ai,1u2+ai,2u3≡bi,0ki,0+bi,1ki,1+ki,2mod  pC_i+a_{i,0}u_1+a_{i,1}u_2+a_{i,2}u_3\equiv b_{i,0}k_{i,0}+b_{i,1}k_{i,1}+k_{i,2}\mod p

写成等式

ki,2−(Ci+ai,0u1+ai,1u2+ai,2u3−bi,0ki,0−bi,1ki,1)=tip(1)k_{i,2}-(C_i+a_{i,0}u_1+a_{i,1}u_2+a_{i,2}u_3-b_{i,0}k_{i,0}-b_{i,1}k_{i,1})=t_ip\tag{1}

我们希望找到这样的短向量

s:=(u1,u2,u3,k0,0,k0,1,k1,0,k1,1,…,k9,0,k9,1)∈Z4+2∗10s:=(u_1,u_2,u_3,k_{0,0},k_{0,1},k_{1,0},k_{1,1},\dots,k_{9,0},k_{9,1})\in Z^{4+2*10}

我们由1式 也就是线性约束 能构造约束矩阵

C⋅,i=(Ci,ai,0,ai,1,ai,2,0,0,⋯ ,bi,0,bi,1,⋯ ,0,0)TC_{\cdot,i}=(C_i,a_{i,0},a_{i,1},a_{i,2},0,0,\cdots,b_{i,0},b_{i,1},\cdots,0,0)^{T}

这里我们每列的系数bi,jb_{i,j}都是两两对齐ki,0    ki,1k_{i,0}\;\;k_{i,1}的,构造的矩阵

Cd,4d+2C_{d,4d+2}

我们理想的格子长这样

L=(I4+2dC0P)L=\begin{pmatrix}I_{4+2d}&C\\0&P\end{pmatrix}

右侧是我们尝试用来落实的线性规划,左侧的单位阵用来承接我们期望的短向量,最后

L2d×(8+4d)L_{2d\times (8+4d)}

我们期望构造的运算是

L(ts)=(s+Ctpt)L\begin{pmatrix}t\\s\end{pmatrix}=\begin{pmatrix}s+Ct\\pt\end{pmatrix}

既然ss就是理想的目标向量,而CtCt的tt我们其实很可控,不妨想想 何时,有

Ct≈(k0,2k1,2⋮kd,2)Ct\approx\begin{pmatrix}k_{0,2}\\k_{1,2}\\\vdots\\k_{d,2}\end{pmatrix}

再次看回1式 就很自然 只要我们的tt恰好是线性方程中的tit_i自然就配上了,所以最后方程形似

w≈(u1u2u3k0,0k0,1k1,0k1,1⋮kd,0kd,1k0,2k1,2⋮kd,2t1pt2p⋮tdp)w\approx\begin{pmatrix}u_1\\u_2\\u_3\\k_{0,0}\\k_{0,1}\\k_{1,0}\\k_{1,1}\\\vdots\\k_{d,0}\\k_{d,1}\\k_{0,2}\\k_{1,2}\\\vdots\\k_{d,2}\\t_1p\\t_2p\\\vdots\\t_dp\end{pmatrix}

这里我们通过构造格子 让我们LLL/BKZ找到的tt就是1式线性方程组中的tt 这一步就叫做“吃掉p” 其实之前2 3个方程的格算法也有这种思路的体现 当时就理所当然的接受了,我们已知u1,2,3u_{1,2,3}是具备一个线性关系的 藏在10组方程中 那么我们即使给u1,2,3u_{1,2,3}乘上一个大系数 线性关系还是在 而且当变量越大 方程组对应欧氏范数中其权重就会更大 算法会更多的去保留大权值变量的线性关系 把它做小 故而这就实现了我们能去格出u1,2,3u_{1,2,3}而尽可能的少受到无关变量ki,2k_{i,2}的影响,这就是我们常说的”配平”

lw3&lw5#

都是类似的思路 放在一起 题面

给定的是一个LWE系统

bm×1=Am×nsn×1+em×1b_{m\times1}=A_{m\times n}s_{n\times 1}+e_{m\times1} (m,n)=(90,64)(m,n)=(90,64)

ee是在给出的集合EE中选择的,我们已知b    Ab\;\;A,想求ss

我们可以如下抽象一个LWE系统

nn组随机变量ss,mm组有限制的变量ee,mm组由上述m+nm+n组变量得到的线性等式

LWE中的ee也就是error,往往会有各种限制 比如二项分布 残差标准差关系等等

不难很直接地构造得到一个规约的式子

L=(I0−A01b00pI)L=\begin{pmatrix}I&0&-A\\0&1&b\\0&0&pI\end{pmatrix}

自然

(s,1,k)L=(s,1,e)(s,1,k)L=(s,1,e)

我们对于这个格的优化思路是利用已知的ee的约束 尝试只规约ee而不规约ss,同时提升规约速度 增加规约出ee的几率,从而解方程得到ss

抽象上来说就是

原本m+nm+n个变量 mm个方程,变成mm个变量 m−nm-n个方程,我们构造的是

L=(−AbpI)L=\begin{pmatrix}-A\\b\\pI\\\end{pmatrix}

有

(s,1,k)L=(e)(s,1,k)L=(e)

而且我们是可以对LL进行行阶梯标准化的 不影响我们的乘算

OK 攻击的思路大致如上 接下来看题

一般来说如果是构造的选取ee的区间EE,我们总是期望能找到一组线性变换 即

E′=kE+t(1,1,1)mod  pE^{'}=kE+t(1,1,1)\mod p

其中E′E^{'}三个值都很小 我们e′e^{'}在其中选的时候值也小 很好规约出来,也就是我们用一个矩阵H3×90H_{3\times90}描述我们是如何选取ee的,那么方程组

B=AS+EHB=AS+EH

可以写成

kB+t=kAS+kEH+tHkB+t=kAS+kEH+tH

即

B′=A′S+E′HB^{'}=A^{'}S+E^{'}H

这里的E′E^{'}会比较小 好规约

那么我在这道题中试一下 发现

L = block_matrix(ZZ, [
    [Matrix(ZZ, E)],
    [Matrix(ZZ, [1]*len(E))],
    [p]
])
E_ = L.LLL()[3]
k, t = Matrix(Zmod(p), L).solve_left(E_)[:2]
assert k*vector(GF(p), E) + t*vector(GF(p), [1,1,1]) == vector(GF(p), E_)

print(E_)

# (-298, 582, -285)
py

并不够小~

这里我们参照鸡块师傅的预期解法

我们知道从EE中选出ee可以如下抽象

ei=(xi,yi,zi)(E1E2E3)e_i=(x_i,y_i,z_i)\begin{pmatrix}E_1\\E_2\\E_3\end{pmatrix}

而且我们的(xi,yi,zi)(x_i,y_i,z_i)实际上只有(0,0,1)  (0,1,0)  (1,0,0)(0,0,1)\;(0,1,0)\;(1,0,0)三种取法 我们可以降一个维度

ei=E1+(xi,yi)(E2−E1E3−E1)e_i=E_1+(x_i,y_i)\begin{pmatrix}E_2-E_1\\E_3-E_1\end{pmatrix}

其中(xi,yi)(x_i,y_i)的取法只有(1,0)(1,0)或者(0,1)(0,1)或者(0,0)(0,0)

这个我们就可以试着去规约一下

此时

ss是nn组随机变量

ee是2m2m组随机变量 但是有0,1的限制

mm个包含2m+n2m+n的方程

再套用前面的思路 尝试消去ss

得到m−nm-n组包含2m2m个01变量的线性方程,在后续就是考虑如何优化来解决这里的规约问题,预期使用的是blaster

这里关于具体格子怎么造不做一个深入的分析 主要是概述一下解决这种LWE的共通思路

也就是从无限制的随机变量ss脱离出来 找到便于规约的 有限制关系的变量ee,利用大小/线性/空间选择的有限性 来使我们能够去规约出来 尝试找到解

官方wp中提及2023SEKAICTF中的noise_crc 2024NKCTF Ez_random 好像也涉及了这一个点 用更多的变量换取更强的限制关系,同时做好对变量的降维,增加我们去规约出来的可行性


LW5#

做了两个优化 首先是完全不让你去找到能映射到短error的EE 随后是EE的维度拓展到5 你就算用01去降维 后续还是4m+14m+1维的变量格要处理 规约不了一点

不过我们参照前面的思路 找一组基 使得消去随机变量ss后 我们的线性方程仍然是变量可规约的

也就是

X5×1g1×1+t5×1=e5×1X_{5\times1}g_{1\times1}+t_{5\times1}=e_{5\times1}

X5×1X_{5\times1}是上述用格基归约找到的5个短分量式,如果考虑用”选取”的二进制展开思路,则是

X5×5g5×1+t5×1=e5×1t:=0X_{5\times5}g_{5\times1}+t_{5\times1}=e_{5\times1}\\t:=0

可以降一个维度

X5×4g4×1+t5×1=e5×1t:=e1X_{5\times4}g_{4\times1}+t_{5\times1}=e_{5\times1}\\t:=e_1

搓一个小的XX一直生成 直到通过检测 后续思路同lw3


总结#

强度比较高的比赛 题目质量也非常棒 很多问题有了更高维度的看法 感谢命题师傅以及其他给出解答的师傅 非常宝贵的学习机会!

WMCTF2025
https://www.zt2misay2.cn/blog/wmctf2025
Author Misay
Published at 2025年9月22日