当前位置: 首页 > news >正文

[GHCTF 2025 新生赛公开赛道] Crypto

新生赛公开赛道,本不想参与,不过还是经不住诱惑。上来也下一跳,Crypto差点没AK

第1批5题

baby_factor

给了phi 直接解密即可

babysignin

给了p,q直接求phi然后解密

baby_factor_revenge

phi = (p-1)(q-1)(r-1)但n=pq 用函数分解出p,q,r再用p,q解密

共享一下模板

#根据n,phi 分解 n 
from math import gcd
from random import randrange
def factorize_multi_prime(N, phi):
    """
    Recovers the prime factors from a modulus if Euler's totient is known.
    This method works for a modulus consisting of any number of primes, but is considerably be slower than factorize.
    More information: Hinek M. J., Low M. K., Teske E., "On Some Attacks on Multi-prime RSA" (Section 3)
    :param N: the modulus
    :param phi: Euler's totient, the order of the multiplicative group modulo N
    :return: a tuple containing the prime factors
    """
    prime_factors = set()
    factors = [N]
    while len(factors) > 0:
        # Element to factorize.
        N = factors[0]
        w = randrange(2, N - 1)
        i = 1
        while phi % (2 ** i) == 0:
            sqrt_1 = pow(w, phi // (2 ** i), N)
            if sqrt_1 > 1 and sqrt_1 != N - 1:
                # We can remove the element to factorize now, because we have a factorization.
                factors = factors[1:]
                p = gcd(N, sqrt_1 + 1)
                q = N // p
                if is_prime(p):
                    prime_factors.add(p)
                elif p > 1:
                    factors.append(p)
                if is_prime(q):
                    prime_factors.add(q)
                elif q > 1:
                    factors.append(q)
                # Continue in the outer loop
                break
            i += 1
    return list(prime_factors)

n_factors = factorize_multi_prime(n,phi)
n_factors = sorted(n_factors)

EZ_Fermat

前边3个可以略过。难度从此开始。

from Crypto.Util.number import getPrime, bytes_to_long
from secret import f

flag = b'NSSCTF{test_flag}'
p = getPrime(512)
q = getPrime(512)
n = p*q

m = bytes_to_long(flag)
e = 65537
c = pow(m,e,n)

R.<x> = ZZ[]
f = R(str(f))

w = pow(2,f(p),n)


print(f'{n = }\n')
print(f'{e = }\n')
print(f'{c = }\n')
print(f'{f = }\n')
print(f'{w = }\n')

'''
n = 101780569941880865465631942473186578520071435753163950944409148606282910806650879176280021512435190682009749926285674412651435782567149633130455645157688819845748439487113261739503325065997835517112163014056297017874761742768297646567397770742374004940360061700285170103292360590891188591132054903101398360047
e = 65537
c = 77538275949900942020886849496162539665323546686749270705418870515132296087721218282974435210763225488530925782158331269160555819622551413648073293857866671421886753377970220838141826468831099375757481041897142546760492813343115244448184595644585857978116766199800311200819967057790401213156560742779242511746
f = 2*x^332 - x^331 + x^329 + 3*x^328 - x^327 - 3*x^325 + x^323 - 3*x^322 - x^321 - 3*x^320 + x^319 + 2*x^318 - 4*x^317 - 3*x^315 - 2*x^314 + x^313 + x^312 + 2*x^311 + 2*x^309 + 2*x^308 + 5*x^307 + 2*x^306 + 3*x^305 + 5*x^304 + 4*x^303 + x^302 - x^301 - x^300 - 2*x^299 - 2*x^298 + x^297 + 3*x^296 - x^295 - 4*x^292 - x^290 + 4*x^289 - x^287 - 3*x^286 + x^285 - 2*x^284 + x^283 - x^282 - 2*x^281 + x^280 - 2*x^279 + x^278 + 2*x^277 - 3*x^276 - x^275 - 4*x^274 - 3*x^273 - 5*x^272 - 2*x^271 - 3*x^270 + 2*x^269 + 2*x^268 - x^267 - 2*x^266 + x^265 + x^264 - 3*x^262 - 3*x^259 + 2*x^258 - x^257 + 2*x^256 + 2*x^255 - x^254 - 2*x^253 - x^252 + 2*x^251 - x^250 + x^249 + 2*x^247 + 2*x^246 + 2*x^245 - 2*x^244 - 3*x^243 + 2*x^242 - 3*x^241 - x^240 - 3*x^239 - x^236 - 3*x^235 - 2*x^234 - x^233 - 2*x^232 - x^231 - 3*x^230 - 2*x^229 - 4*x^228 - 2*x^227 - 3*x^226 + 2*x^225 + x^224 - x^223 - 2*x^221 + 3*x^219 - x^217 - 2*x^216 + x^215 + 2*x^213 - x^212 + 3*x^211 + x^210 + 4*x^209 + x^208 - x^206 - x^205 - x^204 + 2*x^203 - 3*x^202 + 2*x^199 - x^198 + 2*x^196 - 2*x^195 + 3*x^194 + 3*x^193 - x^192 + 4*x^191 + 2*x^189 + x^186 - x^185 - x^184 + 3*x^183 + x^182 + 2*x^181 - 2*x^180 + x^177 + x^175 - x^173 + 3*x^172 + x^170 + x^169 - x^167 - 2*x^166 - x^165 - 4*x^164 - 2*x^163 + 2*x^162 + 4*x^161 - 2*x^160 - 3*x^159 - 2*x^158 - 2*x^157 + x^156 - x^155 + 3*x^154 - 4*x^153 + x^151 + 2*x^150 + x^149 - x^148 + 2*x^147 + 3*x^146 + 2*x^145 - 4*x^144 - 4*x^143 + x^142 - 2*x^140 - 2*x^139 + 2*x^138 + 3*x^137 + 3*x^136 + 3*x^135 + x^134 - x^133 + 2*x^132 + 3*x^130 - 3*x^129 - 2*x^128 - x^127 - 2*x^126 + x^125 + x^124 - 2*x^123 + x^122 - x^121 + 3*x^120 - x^119 - 2*x^118 - x^117 - x^116 - 2*x^115 + 2*x^114 + 2*x^113 - 3*x^112 - x^111 - 4*x^110 + x^109 + x^108 + x^106 - 4*x^105 + x^104 - x^103 - x^101 + x^100 - 2*x^99 + x^98 - x^97 + 3*x^96 + 3*x^94 - x^93 - x^92 + x^91 - 2*x^90 + x^89 - x^88 + x^87 - x^86 + x^85 + x^84 - x^83 + x^79 - 3*x^78 - 2*x^77 + x^74 + 3*x^73 - x^72 - 3*x^71 - 2*x^70 + x^69 - 3*x^66 + x^65 + x^64 - 4*x^62 - x^61 + x^60 - x^59 + 3*x^58 - x^57 - x^54 + 3*x^53 + x^51 - 3*x^50 - x^49 + 2*x^47 - x^46 - x^44 + x^43 - x^42 - 4*x^41 - 3*x^39 - x^37 - x^36 - 3*x^35 + x^34 + x^33 - 2*x^32 + 2*x^31 - x^30 + 2*x^29 - 2*x^28 - 2*x^27 - x^24 + x^22 - 5*x^21 + 3*x^20 + 2*x^19 - x^18 + 2*x^17 + x^16 - 2*x^15 - 2*x^14 + x^13 + x^12 + 2*x^11 - 3*x^10 + 3*x^9 + 2*x^8 - 4*x^6 - 2*x^5 - 4*x^4 + x^3 - x^2 - 1
w = 32824596080441735190523997982799829197530203904568086251690542244969244071312854874746142497647579310192994177896837383837384405062036521829088599595750902976191010000575697075792720479387771945760107268598283406893094243282498381006464103080551366587157561686900620059394693185990788592220509670478190685244
'''

定义了一个多项式f,然后给出2**f(p) mod n 这里p是n的因子,所以模p也成立,对f(x)%(x-1)可以得到-57,也就是在模p时f(p) = k*(p-1)-57 = -57 那么 gcd(w-2^-57,n)==p 求出p来就直接解密就行了。

f%(x-1)
-57
p = gcd(w-pow(2,-57,n),n)

MITM_rsa

MITM中间人攻击,提示过于明了。这里的key未知,但只有36位,可以看成key = k1*k2 如果存在k1,k2都在20位以内就很容易办了。

from Crypto.Util.number import *
from hashlib import md5
from secret import KEY, flag  


assert int(KEY).bit_length() == 36
assert not isPrime(KEY)

p = getPrime(1024)
q = getPrime(1024)
n = p * q
e = 0x10001

ck = pow(KEY, e, n)


assert flag == b'NSSCTF{' + md5(str(KEY).encode()).hexdigest().encode() + b'}'

print(f"{n = }")
print(f"{e = }")
print(f"{ck = }")


n = 26563847822899403123579768059987758748518109506340688366937229057385768563897579939399589878779201509595131302887212371556759550226965583832707699167542469352676806103999861576255689028708092007726895892953065618536676788020023461249303717579266840903337614272894749021562443472322941868357046500507962652585875038973455411548683247853955371839865042918531636085668780924020410159272977805762814306445393524647460775620243065858710021030314398928537847762167177417552351157872682037902372485985979513934517709478252552309280270916202653365726591219198063597536812483568301622917160509027075508471349507817295226801011
e = 65537
ck = 8371316287078036479056771367631991220353236851470185127168826270131149168993253524332451231708758763231051593801540258044681874144589595532078353953294719353350061853623495168005196486200144643168051115479293775329183635187974365652867387949378467702492757863040766745765841802577850659614528558282832995416523310220159445712674390202765601817050315773584214422244200409445854102170875265289152628311393710624256106528871400593480435083264403949059237446948467480548680533474642869718029551240453665446328781616706968352290100705279838871524562305806920722372815812982124238074246044446213460443693473663239594932076

ct = KEY^e = (k1*k2)^e = k1^e* k2^e =>  k1^e = k2^-e*ct

dic = {}
for i in trange(1, 1<<20):
    dic[pow(i,e,n)]=i

for i in trange(1,1<<20):
  try:
    v = ck*pow(i,-e,n)%n
    if v in dic:
      print(dic[v],i,dic[v]*i)
  except:
    pass

KEY = 62495925932
b'NSSCTF{' + md5(str(KEY).encode()).hexdigest().encode() + b'}'
#NSSCTF{14369380f677abec84ed8b6d0e3a0ba9}

第2批3题

baby_lattice

说是格基础也没错,更确切的是个隐含数问题。

from Crypto.Util.number import *
from Crypto.Cipher import AES
import os
from Crypto.Util.Padding import pad
from secret import flag
miku = 30
p = getPrime(512)
key = getPrime(512)
while key> p:
    key= getPrime(512)
ts = []
gs = []
zs = []
for i in range(miku):
    t = getPrime(512)
    z = getPrime(400)
    g= (t * key + z) % p
    ts.append(t)
    gs.append(g)
    zs.append(z)
print(f'p = {p}')
print(f'ts = {ts}')
print(f'gs = {gs}')
iv= os.urandom(16)
cipher = AES.new(str(key).encode()[:16], AES.MODE_CBC,iv)
ciphertext=cipher.encrypt(pad(flag.encode(),16))
print(f'iv={iv}')
print(f'ciphertext={ciphertext}')

直接用个函数,这个自己写不了的。lattice-based-cryptanalysis 可以下载用,里边有一批函数。

hnp(p, ts, gs, 2^400, verbose=True)
key = 8822339647694935089915197969905863773289879929485897803998091330537213988642290800374856766322959957004685197416863851570012301749195861223023504873219753
cipher = AES.new(str(key).encode()[:16], AES.MODE_CBC,iv)
cipher.decrypt(ciphertext)
#NSSCTF{F@@@un7_L4444t1c3333!!}

EZ_fermat_bag_PRO

与第1批题里的Fermat相似,只是不能直接约出数来

from Crypto.Util.number import getPrime, bytes_to_long
from random import *
from secret import f, flag

assert len(flag) == 88
assert flag.startswith(b'NSSCTF{')
assert flag.endswith(b'}')

p = getPrime(512)
q = getPrime(512)
n = p*q

P.<x,y> = ZZ[]
f = P(str(f))

w = pow(2,f(p,q),n)
assert all(chr(i) in ''.join(list(set(str(p)))) for i in flag[7:-1:])
c = bytes_to_long(flag) % p

print(f'{n = }\n')
print(f'{f = }\n')
print(f'{w = }\n')
print(f'{c = }\n')

'''
n = 95656952327201449381426394713246214670537600365883923624876350719801926817916514429721785287844335184715049179879891389941974481490433975689601829920289485889138252888029716516069912637121531561601839948367426922036690701168975937162280451323099126372019216020898338909808577022618554997063496690156977790629
f = x^31 - x^30*y - 2*x^29*y^2 + 7*x^28*y^3 + 2*x^27*y^4 - 4*x^24*y^7 + 3*x^23*y^8 - x^20*y^11 - 4*x^19*y^12 + x^18*y^13 - 5*x^17*y^14 - 4*x^16*y^15 - x^15*y^16 + x^14*y^17 + x^13*y^18 + x^12*y^19 - 2*x^11*y^20 - 3*x^9*y^22 + 5*x^7*y^24 + x^6*y^25 + 6*x^4*y^27 + x^3*y^28 + 2*x*y^30 + y^31 - 2*x^30 - 3*x^29*y + 2*x^28*y^2 + 2*x^27*y^3 - x^26*y^4 - x^25*y^5 - 2*x^24*y^6 - 3*x^23*y^7 - 3*x^22*y^8 - 3*x^20*y^10 - 4*x^19*y^11 + 2*x^18*y^12 + x^15*y^15 - x^14*y^16 - 2*x^12*y^18 - 3*x^11*y^19 - x^10*y^20 + x^9*y^21 + 2*x^8*y^22 + x^7*y^23 + x^5*y^25 - x^4*y^26 - 2*x^3*y^27 - 2*x^2*y^28 - y^30 - 2*x^29 - x^28*y + 3*x^26*y^3 - x^25*y^4 - 2*x^24*y^5 + x^23*y^6 - x^22*y^7 - x^20*y^9 + 2*x^19*y^10 + 2*x^18*y^11 + x^16*y^13 + x^15*y^14 + x^14*y^15 + x^13*y^16 + x^12*y^17 + 5*x^11*y^18 - x^9*y^20 - 2*x^8*y^21 - 5*x^7*y^22 - 2*x^6*y^23 + 3*x^5*y^24 - 5*x^3*y^26 - x^2*y^27 + 2*x*y^28 - y^29 + 3*x^28 + 3*x^27*y - 2*x^26*y^2 + x^25*y^3 + 2*x^24*y^4 - x^23*y^5 - 2*x^22*y^6 - 3*x^20*y^8 - 3*x^19*y^9 + 4*x^17*y^11 - x^16*y^12 - 3*x^15*y^13 - 2*x^14*y^14 + x^13*y^15 + 2*x^12*y^16 - 2*x^11*y^17 + x^10*y^18 - 2*x^9*y^19 + x^8*y^20 - 2*x^7*y^21 - x^6*y^22 + x^5*y^23 - x^4*y^24 + x^3*y^25 + x^2*y^26 - x*y^27 - y^28 + x^27 + x^26*y - 2*x^24*y^3 + x^23*y^4 - 3*x^22*y^5 - 2*x^21*y^6 - 2*x^20*y^7 - 5*x^19*y^8 + 2*x^18*y^9 - 5*x^17*y^10 + x^16*y^11 - 3*x^15*y^12 - 4*x^14*y^13 - x^13*y^14 + x^12*y^15 + 3*x^11*y^16 + 2*x^10*y^17 - 4*x^9*y^18 - 2*x^6*y^21 + x^5*y^22 + 4*x^3*y^24 + 2*x^2*y^25 + 2*x*y^26 - 2*y^27 + x^25*y + x^24*y^2 + x^23*y^3 + 5*x^22*y^4 + x^20*y^6 - 3*x^19*y^7 + x^18*y^8 - x^17*y^9 + 2*x^15*y^11 - x^14*y^12 + 2*x^13*y^13 - x^12*y^14 + 4*x^11*y^15 - x^10*y^16 - 2*x^6*y^20 - x^5*y^21 + 3*x^3*y^23 + x^2*y^24 - 3*x*y^25 - 3*y^26 + 3*x^25 - 2*x^23*y^2 - x^21*y^4 + x^17*y^8 + 2*x^16*y^9 - x^15*y^10 - 2*x^14*y^11 - x^13*y^12 + 2*x^12*y^13 - 2*x^11*y^14 - x^9*y^16 - x^8*y^17 - x^6*y^19 - x^5*y^20 + x^4*y^21 + x^3*y^22 + 5*x*y^24 - 2*y^25 - x^24 + 2*x^23*y + x^22*y^2 - x^21*y^3 - x^19*y^5 + x^18*y^6 - x^17*y^7 + 2*x^16*y^8 - 4*x^15*y^9 - x^14*y^10 - x^13*y^11 - x^12*y^12 + 4*x^10*y^14 + 2*x^9*y^15 - x^8*y^16 - 2*x^7*y^17 - 2*x^6*y^18 + 4*x^5*y^19 + x^4*y^20 + 2*x^2*y^22 - 5*x*y^23 - y^24 + x^23 - x^22*y + 2*x^21*y^2 - x^20*y^3 - x^18*y^5 - x^17*y^6 - 5*x^15*y^8 + x^14*y^9 - 3*x^13*y^10 + 3*x^12*y^11 + 2*x^11*y^12 - 2*x^10*y^13 - 2*x^9*y^14 - x^8*y^15 + 2*x^7*y^16 - 2*x^6*y^17 - 4*x^5*y^18 - 5*x^3*y^20 - x^2*y^21 - x*y^22 - 4*y^23 - x^22 + 2*x^21*y - 2*x^20*y^2 - 2*x^19*y^3 - 3*x^17*y^5 - x^16*y^6 - x^15*y^7 + 4*x^13*y^9 + 2*x^12*y^10 + 3*x^11*y^11 + 2*x^10*y^12 - x^9*y^13 - x^7*y^15 + 2*x^6*y^16 + x^3*y^19 + 2*x^2*y^20 + 2*x*y^21 + 3*y^22 - 3*x^21 - x^20*y - x^19*y^2 + 2*x^17*y^4 - x^16*y^5 - x^15*y^6 + x^14*y^7 - 5*x^12*y^9 - 2*x^11*y^10 + x^10*y^11 + x^6*y^15 + x^5*y^16 + x^4*y^17 - 3*x^2*y^19 - 2*x*y^20 - 2*y^21 + x^20 + 2*x^19*y - 2*x^17*y^3 + 2*x^16*y^4 - 3*x^15*y^5 + 4*x^14*y^6 + 2*x^13*y^7 - x^12*y^8 - 2*x^11*y^9 + x^10*y^10 + 6*x^9*y^11 + x^8*y^12 + x^7*y^13 + 2*x^5*y^15 + 4*x^4*y^16 + x^3*y^17 - x^2*y^18 + 3*x*y^19 - x^17*y^2 + 2*x^16*y^3 + 3*x^14*y^5 - x^13*y^6 + 2*x^11*y^8 + x^10*y^9 + 3*x^9*y^10 - x^7*y^12 - x^6*y^13 + 3*x^5*y^14 - 4*x^4*y^15 + x^2*y^17 + 2*y^19 - x^18 - x^16*y^2 - 2*x^14*y^4 - 2*x^13*y^5 - 2*x^12*y^6 + 2*x^11*y^7 + 3*x^9*y^9 + 3*x^8*y^10 + x^6*y^12 - x^4*y^14 + 2*x^3*y^15 + 2*x^2*y^16 - 2*x*y^17 - x^17 - 4*x^16*y - 2*x^15*y^2 + 2*x^14*y^3 - x^13*y^4 + x^12*y^5 - 2*x^11*y^6 - 3*x^10*y^7 - x^9*y^8 - 5*x^8*y^9 + 2*x^7*y^10 + 2*x^6*y^11 - x^5*y^12 + x^4*y^13 - 3*x^2*y^15 + x*y^16 - 3*x^16 + x^15*y - 3*x^14*y^2 - x^13*y^3 - x^12*y^4 + 2*x^11*y^5 - x^10*y^6 + 5*x^8*y^8 + 3*x^7*y^9 + 3*x^6*y^10 + 2*x^5*y^11 + 4*x^4*y^12 + 2*x^3*y^13 + x^2*y^14 - 3*x*y^15 - x^15 + 3*x^14*y + x^13*y^2 - x^12*y^3 - 3*x^11*y^4 + x^10*y^5 - x^9*y^6 + 2*x^8*y^7 - x^7*y^8 + 4*x^5*y^10 - 2*x^4*y^11 + x^3*y^12 - x^14 + x^13*y + 2*x^12*y^2 + x^11*y^3 - 5*x^10*y^4 - x^9*y^5 - 3*x^8*y^6 - 2*x^7*y^7 + x^6*y^8 + 3*x^5*y^9 + x^4*y^10 + 2*x^3*y^11 - x^2*y^12 - 4*x*y^13 + 3*y^14 + x^12*y - 2*x^11*y^2 - x^9*y^4 - x^8*y^5 + 5*x^7*y^6 - 4*x^6*y^7 + 3*x^5*y^8 + 4*x^4*y^9 - 3*x^3*y^10 - x^2*y^11 - 2*x*y^12 - 3*y^13 + 3*x^12 + x^11*y + x^10*y^2 + x^9*y^3 + x^8*y^4 - x^6*y^6 - x^5*y^7 - 4*x^3*y^9 - x^2*y^10 - 3*x*y^11 - 2*y^12 + x^10*y + 5*x^9*y^2 + x^8*y^3 + 3*x^5*y^6 + x^4*y^7 + 2*x^3*y^8 - 4*x^2*y^9 + 2*x*y^10 + 3*y^11 - x^10 - 2*x^9*y - 2*x^7*y^3 - x^6*y^4 + x^5*y^5 + 3*x^4*y^6 - 2*x^2*y^8 - x*y^9 + 4*x^9 - 3*x^8*y - 3*x^6*y^3 + x^5*y^4 - x^4*y^5 - 2*x^3*y^6 - 2*x^2*y^7 + x*y^8 + 4*y^9 + 2*x^8 - x^7*y - 2*x^5*y^3 - 4*x^4*y^4 + 3*x^3*y^5 + 4*x^2*y^6 + 2*x*y^7 - 2*y^8 + 2*x^7 + 3*x^5*y^2 + 3*x^2*y^5 - x*y^6 - 4*x^6 + 6*x^3*y^3 + 2*x^2*y^4 - 2*x*y^5 - 3*y^6 + x^5 - 3*x^4*y + x^3*y^2 + x^2*y^3 - 2*x*y^4 + 2*x^4 - 2*x^3*y + 6*x^2*y^2 - 3*x*y^3 - 2*y^4 - 5*x^3 - 2*x^2*y - 2*x*y^2 + 3*y^3 + 2*x^2 - x*y + y^2 - 2*x + 2*y - 2
w = 12796020294902567574981427270787776254781813995526831579805652479456168245098217943847166109912113827479436654134179666391771173421469188197935460525521295192736123648410762964187396897298542198935971755852754544978564521188423737649175136194386664628304164316905741781089536713701674793641345344818309314224
c = 10266913434526071998707605266130137733134248608585146234981245806763995653822203763396430876254213500327272952979577138542487120755771047170064775346450942
'''

第1步当然还是求分解,这里f还是在幂的位置上,而x,y分别对应p,q先模phi作个简化得到f2。当然不简化也可。另外一个等式是x*y==n

然后将两式约掉y就得到一个x的多项式,这里可以再用x-1去约。就跟上题一样了。

第2步是个easy_mod也就是c = flag%p这里flag大于p,直接造个简单的格。由于flag中间部分都是数字,所以取中间值4作为基减掉,格的结果为-4到5之间的小量。

#求p
f2 = f%((x-1)*(y-1)) #对f简化
f3 = x*y - n
h = f2.sylvester_matrix(f3, y).det() #利用p*q==n消掉y
k = h%(x-1) #转成模p  w = 2^-k mod p =>  w-2^-k|n 
p = gcd(n,int(w-pow(2,-k,n)%n))
#12887845651556262230127533819087214645114299622757184262163859030601366568025020416006528177186367994745018858915213064803349065489849643880676026721892753

#c = flag %p => flag -c == k*p 
base = b'NSSCTF{'+b'4'*80+b'}' #由于flag中心全为数字,取中心值,使每个小量都只有3位
A = [int(pow(256,80-i,p)) for i in range(80)] + [int((bytes_to_long(base)-c)%p)]
M = block_matrix(ZZ,[[1,matrix(ZZ,A).T],[0,p]])

L = M.LLL()

for l in L:
    if l[-2] != 1: continue
    if not all([-4<=i<=5 for i in l[:-2]]): continue
    print(b'NSSCTF{'+ bytes([0x34+i for i in l[:-2]]) +b'}')

#b'NSSCTF{38886172735077060750460332815973614272222523052135584902884007925985948919714862}'

river

这个估计好多人都没作出来。先看题

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from hashlib import md5
from secret import flag, seed, mask


class ccb:
    def __init__(self, n, seed, mask, lfsr=None):
        self.state = [int(b) for b in f"{seed:0{n}b}"]
        self.mask_bits = [int(b) for b in f"{mask:0{n}b}"]
        self.n = n
        self.lfsr = lfsr
    
    def update(self):
        s = sum([self.state[i] * self.mask_bits[i] for i in range(self.n)]) & 1
        self.state = self.state[1:] + [s]
    
    def __call__(self):
        if self.lfsr:
            if self.lfsr():  #两个相同的序列,当第1个为1时输出第2个1位,为0时重复输出上一位
                self.update()
            return self.state[-1]
        else:
            self.update()
            return self.state[-1]


class nl(ccb):
    def __init__(self, n, seed, mask):
        super().__init__(n, seed, mask, lfsr=None)


n = 64
assert seed.bit_length == mask.bit_length == n
lfsr1 = nl(n, seed, mask)
lfsr2 = ccb(n, seed, mask, lfsr1)
print(f"mask = {mask}")
print(f"output = {sum(lfsr2() << (n - 1 - i) for i in range(n))}")
print(f"enc = {AES.new(key=md5(str(seed).encode()).digest(), mode=AES.MODE_ECB).encrypt(pad(flag, 16))}")
# mask = 9494051593829874780
# output = 13799267741689921474
# enc = b'\x03\xd1#\xb9\xaa5\xff3y\xba\xcb\x91`\x9d4p~9r\xf6i\r\xca\x03dW\xdb\x9a\xd2\xa6\xc6\x85\xfa\x19=b\xb2)5>]\x05,\xeb\xa0\x12\xa9\x1e' 

对于lfrs可以用矩阵直接求解,关键是先得到输出序列。

这里结人输出序列是两个相同序列操作的结果。序列1和序列2,并且序列1==序列2。

先看序列1,当序列1的值为1时输出序列2 一位,当为0时则重复上一样(序列2不动),从output的结果看就是当1变0或者0变1时对应的是1

这个值在爆破序列1的时候会对递归形成剪枝。使64位的爆破可以继续。当然由于这里边有些位比较如说输出是1但序列2恰好也是1,所以无法判断,得到的结果会比较多。经过爆破有1万个。最后再用这1万个爆破下flag

n = 64
output = '1011111110000000110110001110011000111111111011110011111111000010'
last = '1'
pos = ''
for i in range(n):
    if output[i] != last:
        last = output[i]
        pos+= '1'
    else:
        pos+= '.'

def check(v,idx):
    j = 0
    last = '1'
    for i in range(idx):
        if v[i] == '1':
            if output[i] != v[j]: return False
            last = v[j]
            j+=1
        else:
            if output[i] != last: return False
    return True


end = []
def dfs(head,idx):
    if len(head)==64:
        print(head)
        end.append(head) #保存可能正确的值
        return
    if not check(head,idx): return
    if pos[idx] == '.':
        dfs(head+'0',idx+1)
        dfs(head+'1',idx+1)
    else:
        dfs(head+'1',idx+1)

dfs('',0)

利用10089个可能的结果,用mask造矩阵,直接解,爆破flag

mask = 9494051593829874780
mask = [int(i) for i in bin(mask)[2:]]

M = matrix(GF(2),n,n)
for i in range(n-1):
    M[i+1,i]=1

for i in range(n):
    M[i,-1]=mask[i]

M2 = M^64

#遍历10089个可能的结果
for idx in trange(len(end)):
    vs = [int(i) for i in end[idx]]
    tmp = M2.solve_left(vector(GF(2),vs))
    tseed = int(''.join([str(i) for i in tmp]),2)
    tmp = AES.new(key=md5(str(tseed).encode()).digest(), mode=AES.MODE_ECB).decrypt(enc)
    if all([i<0x7f for i in tmp]):
        print(tmp)

#flag{5b322a2b-8d15-43b3-88f0-ee1586f1cf4f}
#NSSCTF{5b322a2b-8d15-43b3-88f0-ee1586f1cf4f}

第3批2题

最后一批明显就白送了

RSA_and_DSA

from random import getrandbits, randint
from secrets import randbelow
from Crypto.Util.number import*
from Crypto.Util.Padding import pad
from Crypto.Cipher import AES
import hashlib
import random
import gmpy2
ink=getPrime(20)
p1= getPrime(512)
q1= getPrime(512)
N = p1* q1
phi = (p1-1) * (q1-1)
while True:
    d1= getRandomNBitInteger(200)
    if GCD(d1, phi) == 1:
        e = inverse(d1, phi)
        break
c_ink = pow(ink, e, N)
print(f'c_ink=',c_ink)
print(f'e=',e)
print(f'N=',N)  #ink 20位可求

k= getPrime(64)
q = getPrime(160)
def sign(msg, pub, pri, k):
    (p,q,g,y) = pub
    x = pri
    r = int(pow(g, k, p) % q)
    h = int(hashlib.sha256(msg).digest().hex(),16)
    s = int((h + x * r) * gmpy2.invert(k, q) % q)
    return (r, s)

while True:
    temp = q * getrandbits(864)
    if isPrime(temp + 1):
        p = temp + 1
        break
assert p % q == 1
h = randint(1, p - 1)
g = pow(h, (p - 1) // q, p)
y = pow(g, k, p)
pub = (p,q,g,y)
pri = random.randint(1, q-1)
print(f"(r1,s1)=",sign(b'GHCTF-2025', pub, pri, k))
print(f"(r2,s2)=",sign(b'GHCTF-2025', pub, pri, k+ink))
print(f"{g= }")
print(f"{q= }")
print(f"{p= }")
print(f"{y= }")
key = hashlib.sha1(str(pri).encode()).digest()[:16]
cipher = AES.new(key, AES.MODE_ECB)
flag="NSSCTF{xxxxxxxx}"
ciphertext = cipher.encrypt(pad(flag.encode(), 16))
print(f"{ciphertext = }")
'''
c_ink= 75517502692097831363443739147565176367247985201143975453326891807623085586665800338505194812511215986799510259417486636115714543892322380908775898968005967267154089356401466517827082639942650711458196552847137272733225451581167527549711435805194039361007506436462393605949663173972848316802086005675594122447
e= 97127528017076464922170978933159739328499830874876612140194720448608536284451056980759925228574802703400503852897647806707933102198339936307176078592550748707182506634151382952065240918923594664309561466538540752851827183955776181255541306419282376724578231110985180090748520497985751591062886932254909959583
N= 131342286566556880877092331187418465653855813425966929864425381510875531237549624989644814104311810243468058174748867544024292263674725375273146689145421426693384862215460097683187892351130513429928063652701077721570140977719823754701988835199434602294597102748436781125528389125846980183998136743830655746063
(r1,s1)= (116607429176396769010327954525649019081679807573, 242024511677350537268048640408155954695100314686)
(r2,s2)= (282969697665204582571637561594660002955972273916, 233488943967710383661411268886726155900968304282)
g= 113752591438136097752416877421595518178059067044406008965947486693591255247711343925741016027611310257564826355221058212913879375956265361413159461801130112690842862767232535007802294944943540511148985219047761964228666223605898858379133610079745082176804146052086680551043775640630819062323009071190616231206
q= 1010682595723348988315901923086844563134854720501
p= 117574623402990360322255542120443410701206393780334500865748478770699335257408652117586356058603035930256320433146236288486738066821845146885689024168044244453298677322763816219621376364185484753693835156465778487436550070788009331605135011517651578548403565196930955818239577581944709384126001757349228062611
y= 114719310327856435690312712426667059528255758467780345974417610618467568889317865434557927492426543544900066735337367408842750916882737134575812646864528120528284507025781167314123831868039617392195979751697057669675359335622753482920688147222344801914086866640706838774098397923450797553056502975678740968481
ciphertext = b'\x10\xbcL|\xcb\xe5W\x1e0\xa3\x83\x85vr^SmU\xac\xe3L\x93"#\xb4\x81\xd0\xf0S\x05\xb7\xc7'
'''

题目有点长,可以看成两部分,第1部分求ink,对一只有20位的ink直接爆力更快。

#1,爆破20位的ink
for i in range(1<<20):
    if pow(i,e,N) == c_ink:
        print(i)
        break

#ink = 261641

第2部分是个签名 k*s = H + x*r 这里k,x是两个未知数。用两组先消掉x就能得到k(初中数学)

#2,列方程,消掉x求k
'''
k*s1 = H + x*r1 
(k+ink)*s2 = H + x*r2

k = (r2H-r1H +r1*s2*ink)/(r2*s1-r1*s2)
'''
msg = b'GHCTF-2025'
H = int(hashlib.sha256(msg).digest().hex(),16)
k = (r2H-r1H +r1*s2*ink)*inverse_mod(r2*s1-r1*s2, q)%q
#14231879199290385691

然后代入1式求x

pri = (k*s1 - H)*inverse_mod(r1,q)%q

#4
key = hashlib.sha1(str(pri).encode()).digest()[:16]
cipher = AES.new(key, AES.MODE_ECB)
cipher.decrypt(ciphertext)
#NSSCTF{n0_RRRrs4_or_DDDS4????}

sin

估计大学生都已经忘了高中生的恶梦了。关于三解函数。

from Crypto.Util.number import bytes_to_long; print((2 * sin((m := bytes_to_long(b'NSSCTF{test_flag}'))) - 2 * sin(m) * cos(2 * m)).n(1024))

'''
m的值即为flag
0.002127416739298073705574696200593072466561264659902471755875472082922378713642526659977748539883974700909790177123989603377522367935117269828845667662846262538383970611125421928502514023071134249606638896732927126986577684281168953404180429353050907281796771238578083386883803332963268109308622153680934466412
'''

先对式子cos(2m)用半解公式得到

原式=2 * sin(m) - 2 * sin(m) * cos(2 * m) = 4*sin(m)^3

用给出的结果除4再开3次根得到sin(m)再求arcsin得到m

然后是一个格的模板,其实大意跟前边的格一样 flag = m + k*2pi。

由于不知道flag的长度,先定个50字节,不够再加。这里爆破的位数不从1开始,太小肯定不出结果,直接拿大的,或者是差不多的开始就行。

#求sin(m)
RR = RealField(1024)
P.<x> = RR[]
f = 4*x^3 - n
v = f.roots()[0][0]

#造格求m
asin = arcsin(v)
pi = RR(pi)
for x in range(800,801):
    K = 2^x 
    L = Matrix(QQ,[[1,0,K],[0,2^(50*8),K*asin],[0,0,K*2*pi]]) #这题并不知道flag长度,暂用50
    m = abs(L.LLL()[0][0])
    m = long_to_bytes(int(m))
    if b'{' and b'}' in m:
        print(x,m)

#NSSCTF{just_make_a_latter_and_LLL_is_OK_padpad}

相关文章:

  • Ollama开启GPU加速与NVIDIA驱动安装
  • 51单片机Proteus仿真速成教程——P1-软件与配置+Proteus绘制51单片机最小系统+新建程序模版
  • mac系统安装
  • 前端之超好使的canvas的场景应用
  • 黄金贵金属行情
  • 【学习方法一】
  • 【面试】Zookeeper
  • uniapp 自定义地图组件(根据经纬度展示地图地理位置)
  • 【Git】合并冲突
  • MySQL-MVCC
  • MPPT与PWM充电原理及区别详解
  • 使用 Vue 3 + TypeScript + Vant 4 构建现代移动端应用
  • 小米智能音箱Pro搭载“超级小爱”,支持远程控车
  • 2025科技项目申报预测月历来啦!
  • C++程序设计语言笔记——基本功能:指针、数组与引用
  • Grafana Loki
  • 深度学习实战车辆目标跟踪与计数
  • 全栈网络安全|渗透测试-1
  • 网络初级复习作业
  • react+ts+eslint+prettier 配置教程
  • 幼儿园教师拍打孩子额头,新疆库尔勒教育局:涉事教师已被辞退
  • 国防部:中方愿与俄方不断增强两军关系良好发展势头
  • 赖清德为“临阵脱逃”作准备,国台办:绝不会任“台独”祸首逍遥法外
  • 美国明尼苏达州发生山火,过火面积超80平方公里
  • 马上评丨岂能为流量拿自己的生命开玩笑
  • 习近平致电祝贺阿尔巴尼斯当选连任澳大利亚总理