H&NCTF2026 极少部分 Writeup,仅供参考
WEB
题目名称:prototype-preview
解题人:斥鸦666
解题过程 : 首先通过dirsearch扫描进行信息收集,扫描到/source,并访问到源码
通过代码审计,发现存在 deepMerge 函数和 renderTemplate 函数
通过 POST 到 /api/profile接口,在 JSON 中注入 __proto__字段,成功污染了 Object.prototype,设置了恶意的 escapeFunction属性
然后进行rce,当访问预览页面时, renderTemplate 从 options 中读取被污染的 escapeFunction ,通过new Function()执行了任意代码
最后执行env命令,从环境变量中读取到 flag,flag{d101c924-da5a-4dc7-99a0-d96f8a43533f}
PWN
题目名称 :ezstack
解题人:ShizukuAqua
解题过程 :
通过看vuln也知道是栈溢出。顺便还能执行stack。
那考虑一下shellcode?
对于x64,有一堆gadget是好事:
难点有很多,重复尝试发现用shellcode不太靠谱,毕竟这个逻辑很离谱。
先泄露PIE。
有了之后,可以ORW ROP chain,但是构造比较麻烦。
这样就能接收flag了,直接尝试清洗数据即可:
题目名称:expz1
解题人:ShizukuAqua
解题过程 :
嗯。
像是堆上操作能干出来的。
这个win不可错过,是好东西。
然后对main里面各个操作函数分析,不多说。
发现delete这里面有个useafterfree的操作,number_question可以减少。
set又多8字节出来。ask里面又可以改改新指针。
那么:create->delete->create->set->ask->win
这样,调试调试得到结果。
题目名称:expz2
解题人:ShizukuAqua
解题过程 :
呐,和上面差不多。
但是我找不到win了,呃呃。
uaf和堆溢出还在,能用用,那么我就用用libc好了。
但是这个puts硬是一次出不来完全,那只能分低高位出:
里面藏了一些截断导致的问题,但是能绕就绕,free利用起来。
构造libc,用free到system的方式进去,不然也进不去。
q6里面写sh,system取值。
差不多就出来了:
CRYPTO
题目名称 :rsapromax
解题人:ShizukuAqua
解题过程:
题目文件分析
chal.sage 实现了以下关键部分:
高斯整数运算
在 $\mathbb{Z}[i]$ 环上定义了基本运算:加法、减法、乘法、范数、除法、模运算和模幂运算。
密钥生成
PRIME_BITS = 128
p, np = random_gaussian_prime(PRIME_BITS)
q, nq = random_gaussian_prime(PRIME_BITS)
N = gmul(p, q)
每个高斯素数 $p = a + bi$ 的范数 $\mathrm{N}(p) = a^2 + b^2 = n_p$ 是一个满足 $n_p \equiv 1 \pmod{4}$ 的有理素数。
Flag 编码
K = 16
flag 被分为前后各 18 字节:
real = flag\[:18\], imag = flag\[18:\]
$$M = \Sigma(real[i] + imag[i]·i) · 256^i (在 Z[i] 中)$$
由于 $gi(256^i, 0)$ 是纯实数,$M$ 其实就是:
加密
E = 65537
C = gaussian_powmod(M, E, N)
已知输出
S = (72, 117) → flag[0]='H', flag[18]='u'
P = (97, 125) → flag\[17]='a', flag[35]='}'
N = (..., ...) → 高斯整数模数
C = (..., ...) → 密文
此外,flag 格式为 H&NCTF{...},即前 7 字节已知:[72, 38, 78, 67, 84, 70, 123]。
密码分析
高斯整数的范数是可乘的:$N(p.q)+N(p)N(q)$
因此:
其中 np, nq 各为 128 位素数,乘积约为 256 位。
256 位的 $\mathrm{N}(N)$ 可通过 ECM/SIQS 分解:
$$N(N) = 106431768171005195056578309153304963000625696907332359069222316936790857518201
= 315251866387752868275572700381099631229 × 337608685368087429339298615454500394669
= np × nq$$
计算私钥
题目中断言 assert gnorm(M) > gnorm(N),这意味着明文大于模数。
恢复原始 $M$
已知,我们需找到
flag
H&NCTF{y0u_kn0w_gaussian_rsa_pr0max}
题目名称:rsa
解题人:ShizukuAqua
解题过程:
首先恢复素数p
恢复素数r
恢复素数q
恢复小整数s
解密
最后 long_to_bytes(m) 即得 flag
结果
题目名称:lush foliage
解题人:ShizukuAqua
解题过程:
第一步: 从 product + XOR 恢复 hint1, hint2
已知
采用逐位 DP + 回溯算法:从 LSB 开始,利用 约束剪枝
第二步恢复IV,关键在于:对于正确的平方根符号,所有 范围内聚集
因子分解, 通常为合数(由 flag 字母表字节组成),需要完整分解:
- 用 Brent 算法(改进的 Pollard’s Rho)找因子
-
递归分解直到所有因子通过
isPrime验证
然后摸索数幂的平方根,全枚举,聚类,IV搜索
第三步AES加密
恢复出 key = long_to_bytes(hint1) 和 iv 后,直接 AES-CBC 解密
得出flag
H&NCTF{d7581e828d3f
RE
\
MISC
题目名称 签到
解题人:ShizukuAqua
解题过程 : 评论区看到base64编码
通过解码获取到flag
题目名称:寻找牢大之路
解题人:ShizukuAqua
解题过程: 首先根据指南针找到只剩鸡,发现可以对其进行攻击,在击毙只剩鸡之后会显示坠机。于是触发下一部分剧情,可以解锁锁甲和镐击,这时指南针告诉你应该攻击牢小,在对牢小造成大量伤害之后即可解锁铁甲和羽毛,此时解锁了去打击牢大的任务。之后利用地形和ai逻辑击杀牢大并打出足量伤害之后即可完成任务
OSINT:
题目名称:OSINT1
解题人:ShizukuAqua
解题过程:
图:
放Google里面搜一下
然后看看:
这个公司网站的内容很符合,可以找到大致位置:
再去地图里面看路面,即可解出:




























