【2022 网鼎杯】青龙组 crypto WriteUp

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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值