crypto405-grasshopper(网鼎杯2022)

方程组求解,题目源码:

from Crypto.Util.number import *
from random import randrange
from grassfield import flag

p = getPrime(16)

k = [randrange(1,p) for i in range(5)]

for i in range(len(flag)):
    grasshopper = flag[i]
    for j in range(5):
        k[j] = grasshopper = grasshopper * k[j] % p
    print('Grasshopper#'+str(i).zfill(2)+':'+hex(grasshopper)[2:].zfill(4))

'''
Grasshopper#00:2066
Grasshopper#01:a222
Grasshopper#02:cbb1
Grasshopper#03:dbb4
Grasshopper#04:deb4
Grasshopper#05:b1c5
Grasshopper#06:33a4
Grasshopper#07:c051
Grasshopper#08:3b79
Grasshopper#09:6bf8
Grasshopper#10:2131
Grasshopper#11:2c40
Grasshopper#12:91ba
Grasshopper#13:7b44
Grasshopper#14:5f25
Grasshopper#15:0208
Grasshopper#16:7edb
Grasshopper#17:62b5
Grasshopper#18:cec5
Grasshopper#19:5ab3
Grasshopper#20:3c46
Grasshopper#21:c272
Grasshopper#22:714b
Grasshopper#23:9e0b
Grasshopper#24:48ee
Grasshopper#25:44cc
Grasshopper#26:05a0
Grasshopper#27:3da3
Grasshopper#28:11b1
Grasshopper#29:259f
Grasshopper#30:899d
Grasshopper#31:a130
Grasshopper#32:e58f
Grasshopper#33:23f3
Grasshopper#34:5829
Grasshopper#35:6beb
Grasshopper#36:3681
Grasshopper#37:0054
Grasshopper#38:a189
Grasshopper#39:2765
Grasshopper#40:c63d
Grasshopper#41:bc68

'''

大概的逻辑是p是16bit素数,k是5维向量,元素大小在1到p之间。
flag为长度为42的字符串。flag中每个字符会进行5次处理:
g r a s s h o p p e r = g r a s s h p p e r . k 0 . k 1 . k 2 . k 3 . k 4 grasshopper=grasshpper.k_0.k_1.k_2.k_3.k_4 grasshopper=grasshpper.k0.k1.k2.k3.k4

sage中模拟一下flag前几位的处理过程:

flag = b'flag{'
var('k0 k1 k2 k3 k4')
k = [k0, k1, k2, k3, k4]
res = []
for i in range(len(flag)):
    grasshopper = flag[i]
    for j in range(5):
        k[j] = grasshopper = grasshopper * k[j]
    res.append(grasshopper)
print(res)

'''
[102*k0*k1*k2*k3*k4, 
1192407267456*k0^5*k1^4*k2^3*k3^2*k4, 
1918196473060530916599580974905403195260928*k0^15*k1^10*k2^6*k3^3*k4, 
56112321905504104058889432264614118677688107359359075763851172322711550767834986156510191423865157053692191440896*k0^35*k1^20*k2^10*k3^4*k4, 
53396244662367707127856864007524389027579357260572582679744127850279999404450619312604004485139827409110793046460181646479623909080635340073160838110289140978788817626824929446784411034165296270303004366240008622426141394072733814130556872463873302593536*k0^70*k1^35*k2^15*k3^5*k4]
'''

实际上每轮k都在变化,可以看出计算过程为:
{ k 11 = o r d ( ′ f ′ ) k 01 , k 12 = o r d ( ′ f ′ ) k 01 k 02 ⋯ k 21 = o r d ( ′ l ′ ) k 11 , k 22 = o r d ( ′ l ′ ) k 11 k 12 ⋯ k 31 = o r d ( ′ a ′ ) k 21 , k 32 = o r d ( ′ a ′ ) k 21 k 22 ⋯ k 41 = o r d ( ′ g ′ ) k 31 , k 42 = o r d ( ′ g ′ ) k 31 k 32 ⋯ k 51 = o r d ( ′ { ′ ) k 41 , k 52 = o r d ( ′ { ′ ) k 41 k 42 ⋯ \left\{ \begin{aligned} k_{11}=ord('f')k_{01},k_{12}=ord('f')k_{01}k_{02} \cdots\\ k_{21}=ord('l')k_{11},k_{22}=ord('l')k_{11}k_{12} \cdots\\ k_{31}=ord('a')k_{21},k_{32}=ord('a')k_{21}k_{22} \cdots\\ k_{41}=ord('g')k_{31},k_{42}=ord('g')k_{31}k_{32} \cdots\\ k_{51}=ord('\{')k_{41},k_{52}=ord('\{')k_{41}k_{42} \cdots\\ \end{aligned} \right. k11=ord(f)k01,k12=ord(f)k01k02k21=ord(l)k11,k22=ord(l)k11k12k31=ord(a)k21,k32=ord(a)k21k22k41=ord(g)k31,k42=ord(g)k31k32k51=ord({)k41,k52=ord({)k41k42

{ o u t 1 = o r d ( ′ f ′ ) k 01 k 02 k 03 k 04 k 05 = k 15 o u t 2 = o r d ( ′ l ′ ) k 11 k 12 k 13 k 14 k 15 = k 25 = k 24 k 15 o u t 3 = o r d ( ′ a ′ ) k 21 k 22 k 23 k 24 k 25 = k 35 = k 34 k 25 = k 33 k 24 k 25 ⋯ \left\{ \begin{aligned} out_{1}=ord('f')k_{01}k_{02}k_{03}k_{04}k_{05}=k_{15} \\ out_{2}=ord('l')k_{11}k_{12}k_{13}k_{14}k_{15}=k_{25}=k_{24}k_{15} \\ out_{3}=ord('a')k_{21}k_{22}k_{23}k_{24}k_{25}=k_{35}=k_{34}k_{25}=k_{33}k_{24}k_{25} \\ \cdots\\ \end{aligned} \right. out1=ord(f)k01k02k03k04k05=k15out2=ord(l)k11k12k13k14k15=k25=k24k15out3=ord(a)k21k22k23k24k25=k35=k34k25=k33k24k25
最后推出mod p意义下
k 15 = o u t 1 , k 25 = o u t 2 , k 35 = o u t 3 ⋯ k 24 = o u t 2 k 15 − 1 , k 34 = o u t 3 k 25 − 1 , k 44 = o u t 4 k 15 − 1 ⋯ k 33 = o u t 3 ( k 24 k 25 ) − 1 , k 43 = o u t 4 ( k 34 k 35 ) − 1 , k 53 = o u t 5 ( k 44 k 45 ) − 1 ⋯ k_{15}=out_1,k_{25}=out_2,k_{35}=out_3 \cdots \\ k_{24}=out_2k_{15}^{-1},k_{34}=out_3k_{25}^{-1},k_{44}=out_4k_{15}^{-1} \cdots \\ k_{33}=out_3(k_{24}k_{25})^{-1},k_{43}=out_4(k_{34}k_{35})^{-1},k_{53}=out_5(k_{44}k_{45})^{-1} \cdots k15=out1,k25=out2,k35=out3k24=out2k151,k34=out3k251,k44=out4k151k33=out3(k24k25)1,k43=out4(k34k35)1,k53=out5(k44k45)1

借鉴了以下这位师傅的解法网鼎青龙组WP
sage exp:

from Crypto.Util.number import *
import gmpy2

out = [0x2066, 0xa222, 0xcbb1, 0xdbb4, 0xdeb4, 0xb1c5, 0x33a4, 0xc051, 0x3b79, 0x6bf8, 0x2131, 0x2c40,0x91ba, 0x7b44, 0x5f25, 0x0208, 0x7edb, 0x62b5, 0xcec5, 0x5ab3, 0x3c46,0xc272, 0x714b, 0x9e0b, 0x48ee, 0x44cc, 0x05a0, 0x3da3, 0x11b1, 0x259f, 0x899d, 0xa130, 0xe58f, 0x23f3, 0x5829, 0x6beb, 0x3681, 0x0054, 0xa189, 0x2765, 0xc63d, 0xbc68]
k = [0]*(50*5)

# Primes in range(max(output),1<<16)
ps = [i for i in range(max(out),1<<16) if isPrime(i)]

for p in ps:
    # 循环求解至最后一个字符,判断是否为"}"
    flag = 'flag{'
    for i in range(0, 42):
        k[(i+1)*5+5] = out[i]
    for i in range(1, 42):
        k[(i+1)*5+4] = out[i] * gmpy2.invert(k[i*5+5], p) % p
    for i in range(2, 42):
        k[(i+1)*5+3] = out[i] * gmpy2.invert(k[i*5+4]*k[i*5+5], p) % p
    for i in range(3, 42):
        k[(i+1)*5+2] = out[i] * gmpy2.invert(k[i*5+3]*k[i*5+4]*k[i*5+5], p) % p
    for i in range(4, 42):
        k[(i+1)*5+1] = out[i] * gmpy2.invert(k[i*5+2]* k[i*5+3]*k[i*5+4]*k[i*5+5], p) % p
    for i in range(5, 42):
        x = out[i] * gmpy2.invert(k[i*5+1]*k[i*5+2]* k[i*5+3]*k[i*5+4]*k[i*5+5], p) % p
        flag = flag + chr(x)
    if x == 125:
        print(p)
        print(flag)
        break

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值