2022 网鼎杯 青龙组 crypto WriteUp
crypto091 crypto405 crypto162
crypto091
根据提示,搜索得知手机号前4位为1709,两位国家代码盲猜86
直接爆破即可
verify = "c22a563acc2a587afbfaaaa6d67bc6e628872b00bd7e998873881f7c6fdc62fc"
from hashlib import sha256
for pwd in range(10**7):
s = str(pwd).zfill(7)
if sha256(b'861709' + s.encode()).hexdigest() == verify:
print('861709' + s)
crypto405
根据output.txt
得知 flag 长度为 42
k 的长度为 5
i=0 时,变换的过程就是将 flag[0]
与 k[0]
相乘,然后从k[1]
开始将每一个k[j]
与k[j-1]
相乘,得到(i = 0 时的)k[4]
。此时的k[4]
,手推出来为
k
0
k
1
k
2
k
3
k
4
f
0
k_0k_1k_2k_3k_4f_0
k0k1k2k3k4f0,记为
k
01234
f
0
k_{01234}f_0
k01234f0
i=1 时, 5 个 k
不变,用 flag[1]
进行相同的步骤,得到(i=1 时的)k[4]
,手推出来为
k
000001111222334
f
00001
k_{000001111222334}f_{00001}
k000001111222334f00001
以此类推,维护一个二维矩阵,得到42个k[4]
的表达式,(初始5位 k 和 42 位 flag 组成的多项式)
把这个 47*42 的矩阵丢进 LLL 里面去,结果如图
很明显这就是flag
于是通过LLL后的矩阵求出变换矩阵
此时发现p未知
但是p的范围并不大,在output中的最大值和 65535 之间的素数一共有 597 个,遍历即可
使用变换矩阵,对output中的值进行计算,在候选结果中找到flag
完整代码
from Crypto.Util.number import *
from random import randrange
# Extract from output.txt
a = [8294, 41506, 52145, 56244, 57012, 45509, 13220, 49233, 15225, 27640, 8497, 11328, 37306, 31556, 24357, 520, 32475, 25269, 52933, 23219, 15430, 49778, 29003, 40459, 18670, 17612, 1440, 15779, 4529, 9631, 35229, 41264, 58767, 9203, 22569, 27627, 13953, 84, 41353, 10085, 50749, 48232]
# Primes in range(max(output),1<<16)
pp = [i for i in range(max(a),1<<16) if isPrime(i)]
# Table
k = [[-1 for i in range(6)] for j in range(43)]
f = [[-1 for i in range(6)] for j in range(43)]
gk = lambda : [0 for i in range(5)]
gf = lambda : [0 for i in range(42)]
# Init
for i in range(43):
for j in range(6):
k[i][j] = gk()
f[i][j] = gf()
for i in range(1,6):
k[0][i][i-1] = 1
for i in range(1,43):
f[i][0][i-1] = 1
# Calc
for i in range(43):
for j in range(6):
if not i*j:continue
k[i][j] = [k[i-1][j][t] + k[i][j-1][t] for t in range(len(gk()))]
f[i][j] = [f[i-1][j][t] + f[i][j-1][t] for t in range(len(gf()))]
# Combine
mm = []
for i in range(1,43):
mm.append(k[i][-1])
mm[-1].extend(f[i][-1])
# Find flag
flag = []
for p in pp:
flag.append([])
for i in range(37):
cc = inverse(a[i],p)
cc *= a[i+1]**5
cc *= inverse(a[i+2],p)**10
cc *= a[i+3]**10
cc *= inverse(a[i+4],p)**5
cc *= a[i+5]
flag[-1].append((cc)%p)
maxx = [max(i) for i in flag]
'''
>>> min(maxx)
125
>>> maxx.index(125)
63
>>> flag[63]
[55, 52, 57, 100, 51, 57, 100, 52, 45, 55, 56, 100, 98, 45, 52, 99, 53, 53, 45, 98, 52, 102, 102, 45, 98, 99, 97, 56, 55, 51, 100, 48, 102, 49, 56, 101, 125]
>>> ''.join([chr(i) for i in flag[63]])
'749d39d4-78db-4c55-b4ff-bca873d0f18e}'
>>>
'''
crypto162
打表就行,很简单的题但是解不多,可能是放得比较晚。
因为最后取str(s)[-2000:-1000]
,所以计算过程中可以对
1
0
2000
10^{2000}
102000 取模
有一个坑是需要python2,否则verify那一步过不去
# Python 2
cof_t = [...]
from time import time
from tqdm import trange
from hashlib import *
M = 10**2010
s = 0
t_start = time()
t_step = time()
for xx in range(100):
t = {}
cof = cof_t[xx]
def cal(i):
if i <3:
return i+1
elif i in t:
return t[i]
else:
t[i] = cof[2]*cal(i-3)%M + cof[1]*cal(i-2)%M + cof[0]*cal(i-1)%M
return t[i]%M
for j in range(0,200000,2):
cal(j)
#print(f'{xx} , ok. {time() - t_step}s')
t_step = time()
s += cal(200000)
print(f'over, {time() - t_start}s')
print(f's = {s}')
# s='8365222366127410597598169954399481033882921410074214649102398062373189165630613993923060190128768377015697889610969869189338768501949778819512483009804114510646333513147157016729806311717181191848898389803672575716843797638777123435881498143998689577186959772296072473194533856870919617472555638920296793205581043222881816090693269730028856738454951305575065708823347157677411074157254186955326531403441609073128679935513392779152628590893913048822608749327034655805831509883357484164977115164240733564895591006693108254829407400850621646091808483228634435805213269066211974452289769022399418497986464430356041737753404266468993201044272042844144895601296459104534111416147795404108912440106970848660340526207025880755825643455720871621993251258247195860214917957713359490024807893442884343732717743882154397539800059579470352302688717025991780505564794824908605015195865226780305658376169579983423732703921876787723921599023795922881747318116849413935343800909756656082327558085457335537828343666748'
from Crypto.Cipher import AES
from hashlib import *
s = str(s)[-2000:-1000]
key = md5(s).hexdigest().decode('hex')
check = sha256(key).hexdigest()
verify = '2cf44ec396e3bb9ed0f2f3bdbe4fab6325ae9d9ec3107881308156069452a6d5'
assert(check == verify)
aes = AES.new(key,AES.MODE_ECB)
# data = flag + (16-len(flag)%16)*"\x00"
data = b'4f12b3a3eadc4146386f4732266f02bd03114a404ba4cb2dabae213ecec451c9d52c70dc3d25154b5af8a304afafed87'
flag = aes.decrypt(data.decode('hex'))
print(flag)