May 29, 2023

ciscn2023 密码部分WP

密码1-基于国密SM2算法的密钥密文分发 按照附件写exp # 自动发包 import requests import json import base64 import binascii import urllib.parse as parse from gmssl import sm2, func from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT # curl -d "name=%E5%93%88%E5%93%88&school=%E5%AE%89%E5%BE%BD%E5%A4%A7%E5%AD%A6&phone=15958198820" http://192.168.31.153:3000/api/login url = 'http://39.105.187.49:16435' data = { 'name': '1', 'school': '1', 'phone': '1' } # 对data进行url编码 data = parse.urlencode(data) # import urllib.parse as parse # print(data) 接口 = '/api/login' res = requests.post(url + 接口, data=data) json_data = json.loads(res.text) data = json_data['data'] # print(data) id = data['id'] print(id) # 1,登录选手信息获取唯一id # 把id发给 /api/allkey 接口 = '/api/allkey' res = requests.post(url + 接口, data={'id': id}) # print(res.text) json_data = json.loads(res.text) data = json_data['data'] publicKey = data['publicKey'] # 选手SM2公钥 privateKey = data['privateKey'] # 选手SM2私钥 randomString = data['randomString'] # print('publicKey\n', publicKey) # print('privateKey\n', privateKey) # print('randomString\n', randomString) # 将公钥传回 接口 = '/api/allkey' # 2,发送选手SM2公钥到服务端,并获取服务端加密后的随机数密文、私钥密文和公钥明文 # 服务器使用国密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密文; res = requests.post(url + 接口, data={'id': id, 'publicKey': publicKey}) # print(res.text) B公钥明文 = json.loads(res.text)['data']['publicKey'] 随机数C对私钥B_Private_Key采用SM4ECB算法加密得到私钥B_Private_Key密文 = json.loads(res.text)[ 'data']['privateKey'] 量子随机数发生器产生16字节随机数C密文 = json.loads(res.text)['data']['randomString'] # print('serverPublicKey\n', serverPublicKey) # 用户使用私钥A_Private_Key,对随机数C密文进行SM2解密,获取16字节随机数C明文; sm2_crypt = sm2.CryptSM2( public_key=publicKey, private_key=privateKey) print('sm4密文_\n', 量子随机数发生器产生16字节随机数C密文) # print(' # AttributeError: 'str' object has no attribute 'hex' 量子随机数发生器产生16字节随机数C密文 = binascii.a2b_hex(量子随机数发生器产生16字节随机数C密文) 量子随机数发生器产生16字节随机数C明文 = sm2_crypt.decrypt(量子随机数发生器产生16字节随机数C密文) # 量子随机数发生器产生16字节随机数C明文 转为字节 量子随机数发生器产生16字节随机数C明文 = binascii.b2a_hex(量子随机数发生器产生16字节随机数C明文) # 用户使用16字节随机数C明文,对私钥B_Private_Key密文,采用SM4ECB算法解密,得到私钥B_Private_Key明文; print('量子c\n', 量子随机数发生器产生16字节随机数C明文) sm4_crypt = CryptSM4() sm4_crypt.set_key(量子随机数发生器产生16字节随机数C明文, SM4_DECRYPT) 私钥B_Private_Key明文 = sm4_crypt.crypt_ecb( 随机数C对私钥B_Private_Key采用SM4ECB算法加密得到私钥B_Private_Key密文.encode('utf-8')) 私钥B_Private = binascii.b2a_hex(私钥B_Private_Key明文) print('私钥B_Private\n', 私钥B_Private) # 这里发现解出的私钥有问题 有可能为空 猜想是否解密错误 # 用户向服务器请求密钥,服务器使用公钥B_Public_Key明文,对密钥D(16字节)采用SM2算法加密,将密钥D密文传输给用户; check接口 = '/api/check' # 不过在这里check的时候发现一直check错误。。。 # 尝试找漏洞 后面有的注释是第一次按文件写的时候写的 接口 = '/api/quantum' res = requests.post(url + 接口, data={'id': id}) # print(res.text) quantumString = json.loads(res.text)['data']['quantumString'] res = requests.post(url + check接口, data={'id': id, 'quantumString': quantumString}) # print('quantumString\n', quantumString) # 用户使用私钥B_Private_Key明文,对密钥D密文进行解密,得到密钥D明文; sm2_crypt2 = sm2.CryptSM2( public_key=B公钥明文, private_key=私钥B_Private) quantumString = binascii.a2b_hex(quantumString) quantumString = sm2_crypt2.decrypt(quantumString) quantumString = binascii.b2a_hex(quantumString) print('quantumString\n', quantumString) # 用户将密钥D明文,上报至服务器进行验证,服务器返回参赛结果;用户可向服务器查询个人信息及参赛结果。 # 尝试非预期 quantumString = quantumString.decode('utf-8') res = requests.post(url + 接口, data={'id': id, 'quantumString': quantumString}) print(res.text) res = requests.post(url + 接口, data={'id': id, 'quantumString': quantumString}) print(res.text) 接口 = '/api/search' res = requests.post(url + 接口, data={'id': id}) print(res.text) quantumStringServer = json.loads(res.text)['data']['quantumStringServer'] print('quantumStringServer\n', quantumStringServer) res = requests.post(url + check接口, data={'id': id, 'quantumString': quantumStringServer}) res = requests.post(url + 接口, data={'id': id}) print(res.text) 密码2-可信度量 在根目录下递归搜索包含字符串"flag"的文件,并将结果输出到标准输出,并过滤掉无权访问的行 grep -ra "flag" / 2>&1 | grep -v "Permission denied" | grep -v "denied$" --line-buffered 密码3-Sign_in_passwd 文件后缀改txt后(方便查阅) url解码第二行信息后base64换表 第一行作为密文 第二行作为表来解 密码4-badkey1 题面 from Crypto.Util.number import * from Crypto.PublicKey import RSA from hashlib import sha256 import random, os, signal, string def proof_of_work(): random.seed(os.urandom(8)) proof = ''.join([random.choice(string.ascii_letters+string.digits) for _ in range(20)]) _hexdigest = sha256(proof.encode()).hexdigest() print(f"sha256(XXXX+{proof[4:]}) == {_hexdigest}") print('Give me XXXX: ') x = input() if len(x) != 4 or sha256(x.encode()+proof[4:].encode()).hexdigest() != _hexdigest: print('Wrong PoW') return False return True if not proof_of_work(): exit(1) signal.alarm(10) print("Give me a bad RSA keypair.") try: p = int(input('p = ')) q = int(input('q = ')) assert p > 0 assert q > 0 assert p != q assert p.bit_length() == 512 assert q.bit_length() == 512 assert isPrime(p) assert isPrime(q) n = p * q e = 65537 assert p % e != 1 assert q % e != 1 d = inverse(e, (p-1)*(q-1)) except: print("Invalid params") exit(2) try: key = RSA.construct([n,e,d,p,q]) print("This is not a bad RSA keypair.") exit(3) except KeyboardInterrupt: print("Hacker detected.") exit(4) except ValueError: print("How could this happen?") from secret import flag print(flag) 按照 brealid 师傅的推导过程自己推了一遍 工作量证明 模板 import hashlib import string import itertools from tqdm import tqdm from pwn import * # 遍历所有的XXXX,找到符合条件的XXXX b = string.digits + string.ascii_letters + string.punctuation strL = itertools.product(b, repeat=4) ip = '47.93.187.243' port = 39092 io = remote(ip, port, level='debug') data = io.recvline() # print(data) # b'sha256(XXXX+2ywKnEOsDsVMJXvP) == f8ffb979f1819dba9905c67b9b85874c681807f6e3cb2953901785764f5e8db8\n' 残缺的sha = data.split(b'+')[1].split(b')')[0] sha256后的值 = data.split(b'== ')[1].strip() hash_object = hashlib.sha256() for i in strL: a = i[0] + i[1] + i[2] + i[3] sha = a + 残缺的sha.decode() # print(sha) hash_object.update(sha.encode()) digest = hash_object.digest() hex_digest = digest.hex() if hex_digest == sha256后的值.decode(): print(a) io.sendline(a.encode()) break io.interactive() 推导
Read more
May 22, 2023

NSSCTF 流密码工坊

LCG 流密码介绍 [公式] LCG代码实现 Python 实现 class LCG: def __init__(self, seed, a, b, m): self.seed = seed # 初始种子 self.a = a # 乘数 self.b = b # 增量 self.m = m # 模数 def generate(self): self.seed = (self.a * self.seed + self.b) % self.m return self.seed 题面 from Crypto.Util.number import * flag = b'NSSCTF{******}' class LCG: def __init__(self, seed, a, b, m): self.seed = seed # 初始种子 self.a = a # 乘数 self.b = b # 增量 self.m = m # 模数 def generate(self): self.seed = (self.a * self.seed + self.b) % self.m return self.seed lcg = LCG(bytes_to_long(flag), getPrime(256), getPrime(256), getPrime(256)) for i in range(getPrime(16)): lcg.generate() print(f'a = {lcg.a}') print(f'b = {lcg.b}') print(f'm = {lcg.m}') print(lcg.generate()) ''' a = 113439939100914101419354202285461590291215238896870692949311811932229780896397 b = 72690056717043801599061138120661051737492950240498432137862769084012701248181 m = 72097313349570386649549374079845053721904511050364850556329251464748004927777 9772191239287471628073298955242262680551177666345371468122081567252276480156 ''' 本题给出了LCG的各个参数,然后给出了一次密文,而初始种子便是我们的flag 现在我们拥有 $X_{n+1}$ , $a$ , $b$ , $m$ , 我们进行如下操作 对第一个式子(LCG递推式) [公式] 进行移项后如下 [公式] 这样我们便得到了一个从下一项逆向递推上一项的式子。 那么在题目中我们要逆向多少项呢?我们并不知道,因为中间迭代的次数是一个随机数,但是我们不用关心,因为我们知道flag的格式,所以只需要不断的逆向,直到找到符合格式的flag为止。 exp from Crypto.Util.number import * a = 113439939100914101419354202285461590291215238896870692949311811932229780896397 b = 72690056717043801599061138120661051737492950240498432137862769084012701248181 m = 72097313349570386649549374079845053721904511050364850556329251464748004927777 x = 9772191239287471628073298955242262680551177666345371468122081567252276480156 inva = inverse(a, m) for i in range(2**16): x = (x-b)*inva % m flag = long_to_bytes(x) if b'NSSCTF' in flag: print(flag) 从这里也可以看出,一旦LCG的参数遭到了泄露,我们便可以向前恢复或者向后预测出其他的随机数(或者专业点叫做流密钥)。
Read more
May 13, 2023

LitCTF2023

小小小 Background 源码星球上有一种有趣的游戏「小,小小小」。 / Description 给你 $n$ 张卡片,第 $i$ 张卡片上写着 $a_i$。 / 定义一个包含 $n$ 张卡片的卡片组分值为: / [公式] 其中 $a_{n+1} = a_1$。
Read more
May 2, 2023

CryptoHack Wp

1.2 XOR 挑战 1.2.4 XOR -> You either know, XOR you don’t 发现之前做了点了 隐藏一下已经解决的 from pwn import xor from Crypto.Util.number import long_to_bytes as l2b c = "0e0b213f26041e480b26217f27342e175d0e070a3c5b103e2526217f27342e175d0e077e263451150104" c = l2b(int(c, 16)) # hex to int to bytes # 已知flag 前几位为crypto{ 于是与这几位结果对应密文xor即可得出key flag_begin_format = b"crypto{" flag_end_format = b"}" key = xor(c[:7], flag_begin_format) + xor(c[-1:], flag_end_format) print(xor(c, key))
Read more
March 24, 2023

侧信道和嵌入式访问控制

侧信道 / flag{The_rotten_measurement_channel}
March 4, 2023

RSA中的个人奇思妙想

公钥加密就私钥解密 私钥加密就公钥解密
Read more
February 27, 2023

证书链

证书链是一系列数字证书的集合,用于验证和建立信任关系。在公钥基础设施(PKI)中,证书链用于验证服务器证书的有效性和可信任性。 证书链由多个证书组成,每个证书都被签发者(颁发者)签名。链的顶部是服务器证书,也称为终端证书或服务器端证书。该证书包含了公钥和与之相关的信息,如域名、组织名称等。 证书链的底部是根证书,也称为根CA证书或根证书颁发机构(Root CA)。根证书是最高级别的信任锚点,它的公钥用于验证链中的其他证书。 中间证书也被包含在证书链中,它们是由根证书颁发机构签发的,并用于连接终端证书和根证书。中间证书的作用是构建信任链,确保终端证书的有效性。 验证证书链的过程是逐级验证每个证书的签名,直到达到根证书。如果每个证书的签名都有效,并且根证书是受信任的,那么整个证书链就被视为有效和可信任的。 通过验证证书链,客户端可以确保与服务器之间的通信是安全的,并且可以信任服务器的身份。这对于建立安全的网络连接和进行加密通信至关重要,尤其在涉及敏感信息的场景下,如在线银行、电子商务等。
Read more
February 23, 2023

Diffie-Hellman

CMU 18-631 S23 U2L2 感谢:Generate
Read more
February 22, 2023

VNctf2023 Crypto方向赛题复现

挖一个坑
February 22, 2023

Coppersmith -- 相关消息攻击

NUS_CS2107-CTF 感谢:hash_hash
Read more