CISCN2023复现
第一次打国赛,四个人没凑齐凑了三个人,不过打的还行,孩子打的很开心,明年还来(
Crypto
基于国密SM2算法的密钥密文分发
开靶机,nc 123.57.248.214 26759
下载附件,提供了一个SM2的介绍,阅读了解SM2算法以及本题的交互方式和流程:
用户建立连接,将个人信息上报服务器,并获取id;
用户使用SM2算法生成密钥对A(公钥A_Public_Key、私钥A_Private_Key),将密钥对A的公钥(A_Public_Key)传输给服务器;
服务器使用国SM2算法生成密钥对B(公钥B_Public_Key、私钥B_Private_Key)、同时产生16字节随机数C;服务器首先使用16字节随机数C对私钥B_Private_Key采用SM4ECB算法加密得到私钥B_Private_Key密文,然后使用A_Public_Key对16字节随机数C进行SM2加密得到随机数C密文;
服务器将公钥B_Public_Key明文、私钥B_Private_Key密文、随机数C密文传输给用户;用户向服务器请求密钥,服务器使用公钥B_Public_Key明文,对密钥D(16字节)采用SM2算法加密,将密钥D密文传输给用户;
用户想办法得到密钥D明文,将D上报验证。
先用命令行验证一下个人信息(名字,学校都经过url加密):
1 | curl -d "name=%E7%8E%8B%E7%90%9B&school=%E5%B1%B1%E4%B8%9C%E7%A7%91%E6%8A%80%E5%A4%A7%E5%AD%A6&phone=18769999317" http://123.57.248.214:26759/api/login |
返回自己的ID:
1 | { |
这里使用SM2算法生成一对公私钥:
1 | from random import SystemRandom |
并发送publicKey:
1 | curl -d "id=8a0cbcd0-d8c6-4f53-a324-881dfd90eb41&publicKey=bb58b25650dafa605ae7e6438d5bee1e3f1ac09a8f72db7ab20757bccecf9161675fd9ab6290a8735002223ed4904e328c404cac6916bcadcb64ac3ec2fed42d" http://123.57.248.214:26759/api/allkey |
得到返回的公钥B_Public_Key明文、私钥B_Private_Key密文、随机数C密文:
1 | { |
获取一下quantum:
1 | curl -d "id=8a0cbcd0-d8c6-4f53-a324-881dfd90eb41" http://123.57.248.214:26759/api/quantum |
得到quantumString:
1 | { |
在阅读附件时,了解选手信息的返回值,发现存在一个名为quantumStringServer的值,这是服务器使用公钥B_Public_Key明文,对密钥D(16字节)采用SM2算法加密的原始明文:
查看个人信息,找到quantumStringServer:
1 | curl -d "id=8a0cbcd0-d8c6-4f53-a324-881dfd90eb41" http://123.57.248.214:26759/api/search |
得到quantumStringServer:
1 | { |
发送刚刚获得的quantumStringServer:
1 | curl -d "id=8a0cbcd0-d8c6-4f53-a324-881dfd90eb41&quantumString=a57119343fe30a4dfe3f9e89f4cf7fe9" http://123.57.248.214:26759/api/check |
1 | { |
再查看个人信息,得到flag:
1 | { |
感觉是非预期(
Sign_in_passwd
下载附件打开解压,得到两串字符串:
1 | j2rXjx8yjd=YRZWyTIuwRdbyQdbqR3R9iZmsScutj2iqj3/tidj1jd=D |
看起来像自定义base64加密,第二行的编码表有几个url编码的字符,url解码一下,得到:
1 | GHI3KLMNJOPQRSTUb%253DcdefghijklmnopWXYZ%252F12%252B406789VaqrstuvwxyzABCDEF5 |
进行自定义base64解码:
1 | import base64 |
badkey(赛后)
第二天研究了一阵子这个题,不懂怎么构造ValueError就弄了个工作量证明就干不动了,赛后在NSSCTF上复现一下。
附件代码:
1 | from Crypto.Util.number import * |
看完代码,首先发现解RSA前有一个工作量证明的操作,比较简单,先给做了:
1 | import itertools |
然后需要发送一个所谓的badkey,首先需要符合:
1 | assert p > 0 |
然后会把几个参数用RSA库还原密钥,如果构造出现了ValueError,就会返回flag:
1 | try: |
比赛时就卡在这里不知道如何让还原的密钥出现ValueError的同时还要满足上面所有assert
条件,赛后看wp才看明白。
可以通过查看RSA库的源码去发现如何使其ValueError:pycryptodome/RSA.py at master · Legrandin/pycryptodome · GitHub
直接打开网站后全局搜索ValueError,挨个找,找到# Verify consistency of the key
这一大部分,这里用了很多种方法详细验证了密钥的一致性,如果不满足会返回ValueError:
1 | # Verify consistency of the key |
因为有前面assert
的限制,前几种方法直接被排除了,发现一个可以利用的:
1 | if Integer(n).gcd(d) != 1: |
这里需要:
$$
gcd(n,d)≠1
$$
由于n只有两个因子,所以也就有$d=ap$。
要想办法求出a,对于ed,我们知道$ed\equiv 1(\bmod p-1)$,可以尝试通过化简式子构造模逆运算得到a,变换一下:
$$
d=a+a(p-1)
$$
$$
ed=ea+ea(p-1)
$$
对上面的等式也进行模运算,得到:
$$
ea\equiv 1(\bmod p-1)
$$
a可以通过模逆运算求出,接下来把对应的q求出来,如果q为素数就说明生成了一组满足条件的数。
$$
ed-1=k(p-1)(q-1)
$$
变换,得到:
$$
\frac{eap-1}{p-1}=k(q-1)
$$
由于$a=inverse(e,p-1)$运算得到,e比较小,a应该和p-1位数接近,所以等式左边$\frac{eap-1}{p-1}$的位数应该比右边的位数稍大一点点,通过爆破k来得到q-1,验证q是否为素数,如果为素数就符合条件:
1 | import gmpy2 |
跑了一段时间得到了一对符合要求的p和q,发送pq得到flag:
1 | import itertools |
misc
签到卡
打开靶机,进入网站,看到一个python打字机,python输入,随便输一些东西测试,如果出现报错会提供提示:
python3打印文件内容:print(open('/etc/passwd').read())
直接打印flag即可:
print(open('/flag').read())
被加密的生产流量
下载附件wireshark打开流量包,追踪TCP流直接看到几段断断续续的编码,手动打一下:
MMYWMX3GNEYWOXZRGAYDA===
这是base32,直接解码得到flag。
国粹(赛后)
提供了三张全是麻将图片,有一张是很有顺序的类似于全图鉴一样的麻将表,另外两张非常长,有很多的麻将图片。
那个麻将表不知道为什么给了两排,还多了一个一萬,忽略即可。
题目的做法是根据顺序表对麻将进行数字编码,然后将对应两张图片的麻将依次解码,得到的两个图片转化成数组可以绘制一个坐标图,上面就能显示出flag:
1 | from PIL import Image |
Reverse
babyRE
给了xml文件,用记事本打开,第一行看到:
1 | <project name="re4baby22" app="Snap! 8.2, https://snap.berkeley.edu" version="2"><notes></notes> |
看到一个网址,打开,简单了解了一下这个网站:
Snap.berkeley 是一种基于块编程语言,旨在引导儿童和青少年学习编程的编程环境。它是由加州大学伯克利分校开发的免费软件,已成为全球许多学校和机构的教育工具。Snap.berkeley 提供了大量的模块和工具,以帮助学生构建他们自己的程序,从简单的图形和动画到更复杂的计算机游戏和应用程序。它还具有类似于传统文本编程的基本编程概念,例如变量、循环和条件语句,因此可以帮助学生建立对计算机科学的基本理解。
类似于Scratch编程,用网站给的在线交互打开xml文件,看到程序:
简单跑了一下程序没有发现什么有用信息,查找程序的这几个对象,在lock里发现了加密代码,用了secret数组,进行了简单的异或运算,连续两个数挨个异或:
手打一下题目的secret数组,python异或回去,得到flag:
1 | list=[102, 10, 13, 6, 28, 74, 3, 1, 3, 7, 85, 0, 4, 75, 20, 92, 92, 8, 28, 25, 81, 83, 7, 28, 76, 88, 9, 0, 29, 73, 0, 86, 4, 87, 87, 82, 84, 85, 4, 85, 87, 30] |