没打比赛,持续复现更新ing
Easy
blue office
题目:
#!/usr/bin/enc python3
import binascii
from secret import seed, flag
def gen_seed(s):
i, j, k = 0, len(s), 0
while i < j:
k = k + ord(s[i])
i += 1
i = 0
while i < j:
if (i % 2) != 0:
k = k - (ord(s[i]) * (j - i + 1))
else:
k = k + (ord(s[i]) * (j - i + 1))
k = k % 2147483647
i += 1
k = (k * j) % 2147483647
return k
def reseed(s):
return s * 214013 + 2531011
def encrypt(s, msg):
assert s <= 2**32
c, d = 0, s
enc, l = b'', len(msg)
while c < l:
d = reseed(d)
enc += (msg[c] ^ ((d >> 16) & 0xff)).to_bytes(1, 'big')
c += 1
return enc
enc = encrypt(seed, flag)
print(f'enc = {binascii.hexlify(enc)}')
enc = b'b0cb631639f8a5ab20ff7385926383f89a71bbc4ed2d57142e05f39d434fce'
爆破seed
即可
解题代码:
from tqdm import *
from binascii import *
def encrypt(s, msg):
assert s <= 2**32
c, d = 0, s
enc, l = b'', len(msg)
while c < l:
d = reseed(d)
enc += (msg[c] ^ ((d >> 16) & 0xff)).to_bytes(1, 'big')
c += 1
return enc
def reseed(s):
return s * 214013 + 2531011
enc = b'b0cb631639f8a5ab20ff7385926383f89a71bbc4ed2d57142e05f39d434fce'
enc = unhexlify(enc)
for d in trange(2**32):
if encrypt(d,b'CCTF')==enc[:4]:
break
#d = 10364460
flag = b''
for i in range(len(enc)):
d = reseed(d)
flag += (enc[i]^((d>>16) & 0xff)).to_bytes(1,'big')
print(flag)
flag:
CCTF{__B4ck_0r!F1c3__C1pHeR_!!}
Suction
题目:
#!/usr/bin/env python3
from Crypto.Util.number import *
from flag import flag
def keygen(nbit, r):
while True:
p, q = [getPrime(nbit) for _ in '__']
e, n = getPrime(16), p * q
phi = (p - 1) * (q - 1)
if GCD(e, phi) == 1:
N = bin(n)[2:-r]
E = bin(e)[2:-r]
PKEY = N + E
pkey = (n, e)
return PKEY, pkey
def encrypt(msg, pkey, r):
m = bytes_to_long(msg)
n, e = pkey
c = pow(m, e, n)
C = bin(c)[2:-r]
return C
r, nbit = 8, 128
PKEY, pkey = keygen(nbit, r)
print(f'PKEY = {int(PKEY, 2)}')
FLAG = flag.lstrip(b'CCTF{').rstrip(b'}')
enc = encrypt(FLAG, pkey, r)
print(f'enc = {int(enc, 2)}')
n、e、c
的低8bit
均未知,所以我们得先爆破n
的低8bit
,然后分解n
得到p q
。这题最麻烦的一点在于爆破n以及分解
,刚开始想在sage
中用factor()
去分解,但是有点慢。接下来想在python中直接用命令调用本地的yafu
去分解,但是测试了一下,对于分解的n不好获取数据。最后选择用factordb的api
进行分解,对于无法分解的n它也会返回当前的n,对于可以分解的n我们只需要判断是否只存在两个因子,以及每个因子是否都是128bit的素数
即可找到符合条件的n。
PS:由于flag
的内容不是CCTF{}
格式,所以在最后爆破c
和e
的时候还需要判断m
的字符串格式是否都是可打印字符
解题代码:
from Crypto.Util.number import *
import gmpy2
import requests
from tqdm import *
PKEY = 55208723145458976481271800608918815438075571763947979755496510859604544396672
ENC = 127194641882350916936065994389482700479720132804140137082316257506737630761
c_high = ENC<<8
n_high = (PKEY>>8)<<8
e_high = (PKEY & (2**8-1))<<8
def factor_n(n):
url = "http://factordb.com/api?query={}".format(str(n))
try:
response = requests.get(url)
fac = response.json()['factors']
fac_data = [int(i[0]) for i in fac]
return fac_data
except:
pass
p_q = []
for i in trange(2**8):
n = n_high+i
fac_data = factor_n(n)
if len(fac_data)==2:
if fac_data[0].bit_length()==128 and fac_data[1].bit_length()==128 and isPrime(fac_data[0]) and isPrime(fac_data[1]):
p_q = fac_data
break
p,q = int(fac_data[0]),int(fac_data[1])
n = p*q
phi = (p-1)*(q-1)
for i in range(2**8):
for j in range(2**8):
c = c_high + i
e = e_high + j
if isPrime(e):
try:
d = gmpy2.invert(e, phi)
m = pow(c,d,n)
flag = long_to_bytes(m)
if all(k<=127 and k >=33 for k in flag):
print(b"CCTF{"+flag+b"}")
break
except:
pass
flag:
CCTF{6oRYGy&Dc$G2ZS}
Medium
Insights
题目:
#!/usr/bin/env sage
from Crypto.Util.number import *
from flag import flag
def getRandomNBits(n):
nb = '1' + ''.join([str(randint(0, 1)) for _ in range(n - 1)])
return nb
def getLeader(L, n):
nb = L + getRandomNBits(n)
return int(nb, 2)
def genPrime(L, nbit):
l = len(L)
assert nbit >= l
while True:
p = getLeader(L, nbit - l)
if is_prime(p):
return p
def genKey(L, nbit):
p, q = [genPrime(L, nbit) for _ in '__']
n = p * q
d = next_prime(pow(n, 0.2919))
phi = (p - 1) * (q - 1)
e = inverse(d, phi)
pubkey, privkey = (n, e), (p, q)
return pubkey, privkey
def encrypt(msg, pubkey):
n, e = pubkey
m = bytes_to_long(msg)
c = pow(m, e, n)
return c
nbit = 1024
L = bin(bytes_to_long(b'Practical'))[2:]
pubkey, privkey = genKey(L, nbit)
p, q = privkey
c = encrypt(flag, pubkey)
print('Information:')
print('-' * 85)
print(f'n = {p * q}')
print(f'e = {pubkey[1]}')
print(f'c = {c}')
print(f'p = {bin(p)[2:len(L)]}...[REDACTED]')
print(f'q = {bin(q)[2:len(L)]}...[REDACTED]')
print('-' * 85)
关键代码d = next_prime(pow(n, 0.2919))
,我们已知n,那么直接可以求出d,然后RSA解密即可得到flag
解题代码:
from Crypto.Util.number import *
import gmpy2
n = gmpy2.mpz(12765231982257032754070342601068819788671760506321816381988340379929052646067454855779362773785313297204165444163623633335057895252608396010414744222572161530653104640020689896882490979790275711854268113058363186249545193245142912930804650114934761299016468156185416083682476142929968501395899099376750415294540156026131156551291971922076435528869024742993840057342092865203064721826362149723366381892539617642364692012936270150691803063945919154346756726869466855557344213050973081755499746750276623648407677639812809665472258655462846021403503851719008687214848550916999977775070011121527941755954255781343103086789)
e = 459650454686946706615371845737527916539205656667844780634386049268800615782964920944229084502752167395446158290854047696006034750210758341744841762479191173017773034647739346927390580848998121830029134542880713409306092967282675122699586503684943407535067216738556403169403622104762516293879994387324370835718056251706150557820106296417750402984941838652433642298378976899556042987560946508887315484380807248331504458640857234708123277403252632993828101306072382329879857946191508782246793011691530554606521701055094223574951862129713872918021549814674387049788995785872980320871421550616327471735316980754238323013
c = 10992248752412909788626396175372747713079469256270100576886987393986576680666320383209810005318254336440105142571546847427454822405793626080251363454531982746373841267986148332456716023293306870382809568309620264499225135226626560298741596462262513921032733814032790312163314776421380481083058518893602887082464123177575742160690315666730642727773288362853901330620841098230284739614618790097180848133698381487679399364400048499041582830157094876815030301231505774900176910650887780842536610942820066913075027528705150102760422836458745949063992228680293226303245265232017738712226154128654682937687199768621565945171
d = gmpy2.next_prime(int(pow(n, 0.2919)))
m = pow(c,d,n)
flag = long_to_bytes(m)
print(flag)
flag:
CCTF{RSA_N3w_rEc0rd5_4Nd_nEw_!nSi9h75!}
Derik
题目:
#!/usr/bin/env python3
from Crypto.Util.number import *
from secret import C, e, d, p, q, r, flag
O = [1391526622949983, 2848691279889518, 89200900157319, 31337]
assert isPrime(e) and isPrime(d) and isPrime(p) and isPrime(q) and isPrime(r)
assert C[0] * p - C[1] * q >= 0
assert C[2] * q - C[3] * r >= 0
assert C[4] * r - C[5] * p >= 0
assert (C[0] * p - C[1] * q) ** e + (C[2] * q - C[3] * r) ** e + (C[4] * r - C[5] * p) ** e == d * (C[0] * p - C[1] * q) * (C[2] * q - C[3] * r) * (C[4] * r - C[5] * p)
assert C[6] * e - C[7] * d == O[3]
n = e * d * p * q * r
m = bytes_to_long(flag)
c = pow(m, 65537, n)
print(f'C = {C}')
print(f'c = {c}')
C = [5960650533801939766973431801711817334521794480800845853788489396583576739362531091881299990317357532712965991685855356736023156123272639095501827949743772, 6521307334196962312588683933194431457121496634106944587943458360009084052009954473233805656430247044180398241991916007097053259167347016989949709567530079, 1974144590530162761749719653512492399674271448426179161347522113979158665904709425021321314572814344781742306475435350045259668002944094011342611452228289, 2613994669316609213059728351496129310385706729636898358367479603483933513667486946164472738443484347294444234222189837370548518512002145671578950835894451, 8127380985210701021743355783483366664759506587061015828343032669060653534242331741280215982865084745259496501567264419306697788067646135512747952351628613, 5610271406291656026350079703507496574797593266125358942992954619413518379131260031910808827754539354830563482514244310277292686031300804846114623378588204, 10543, 4]
c = 80607532565510116966388633842290576008441185412513199071132245517888982730482694498575603226192340250444218146275844981580541820190393565327655055810841864715587561905777565790204415381897361016717820490400344469662479972681922265843907711283466105388820804099348169127917445858990935539611525002789966360469324052731259957798534960845391898385316664884009395500706952606508518095360995300436595374193777531503846662413864377535617876584843281151030183895735511854
C[6] * e - C[7] * d == O[3],即10543 * e - 4 * d = 31337,该方程为一个丢番图方程,我们可以先求e和d的通解,然后去爆破符合条件的e和d。求出的通解为e = -31337 - 4 * k,d = -82604332 - 10543 * k。
求出e和d之后,根据前三组条件,三个未知数,用z3约束器求解一下即可。
解题代码:
from Crypto.Util.number import *
import gmpy2
from z3 import *
O = [1391526622949983, 2848691279889518, 89200900157319, 31337]
C = [5960650533801939766973431801711817334521794480800845853788489396583576739362531091881299990317357532712965991685855356736023156123272639095501827949743772, 6521307334196962312588683933194431457121496634106944587943458360009084052009954473233805656430247044180398241991916007097053259167347016989949709567530079, 1974144590530162761749719653512492399674271448426179161347522113979158665904709425021321314572814344781742306475435350045259668002944094011342611452228289, 2613994669316609213059728351496129310385706729636898358367479603483933513667486946164472738443484347294444234222189837370548518512002145671578950835894451, 8127380985210701021743355783483366664759506587061015828343032669060653534242331741280215982865084745259496501567264419306697788067646135512747952351628613, 5610271406291656026350079703507496574797593266125358942992954619413518379131260031910808827754539354830563482514244310277292686031300804846114623378588204, 10543, 4]
c = 80607532565510116966388633842290576008441185412513199071132245517888982730482694498575603226192340250444218146275844981580541820190393565327655055810841864715587561905777565790204415381897361016717820490400344469662479972681922265843907711283466105388820804099348169127917445858990935539611525002789966360469324052731259957798534960845391898385316664884009395500706952606508518095360995300436595374193777531503846662413864377535617876584843281151030183895735511854
#10543 * e - 4 * d = 31337
# for k in range(-10000,1000):
# e = -31337 - 4 * k
# d = -82604332 - 10543 * k
# if C[6] * e - C[7] * d == O[3] and isPrime(e) and isPrime(d):
# print(e,d)
e = 3
d = 73
p, q, r = Ints('p q r')
s = Solver()
s.add(C[0] * p - C[1] * q == 1391526622949983)
s.add(C[2] * q - C[3] * r == 2848691279889518)
s.add(C[4] * r - C[5] * p == 89200900157319)
if s.check()==sat:
result = s.model()
p = result.eval(p).as_long()
q = result.eval(q).as_long()
r = result.eval(r).as_long()
n = p*q*r
phi = (p-1)*(q-1)*(r-1)
d1 = gmpy2.invert(65537,phi)
m = pow(c,d1,n)
flag = long_to_bytes(m)
print(flag)
flag:
CCTF{____Sylvester____tHE0r3m_Of_D3r!va7i0n!}
Risk
题目代码:
#!/usr/bin/env python3
from Crypto.Util.number import *
from secret import m, flag
def genPrime(m, nbit):
assert m >= 2
while True:
a = getRandomNBitInteger(nbit // m)
r = getRandomNBitInteger(m ** 2 - m + 2)
p = a ** m + r
if isPrime(p):
return (p, r)
def genkey(m, nbit):
p, r = genPrime(m, nbit // 2)
q, s = genPrime(m, nbit // 2)
n = p * q
e = r * s
return (e, n)
def encrypt(msg, pkey):
e, n = pkey
m = bytes_to_long(msg)
c = pow(m, e, n)
return c
pkey = genkey(m, 2048)
enc = encrypt(flag, pkey)
print(f'pkey = {pkey}')
print(f'enc = {enc}')
output.txt:
pkey = (150953688, 373824666550208932851344358703053061405262438259996622188837935528607451817812480600479188884096072016823491996056842120586016323642383543231913508464973502962030059403443181467594283936168384790367731793997013711256520780338341018619858240958105689126133812557401122953030695509876185592917323138313818881164334490044163316692588337720342646339764174333821950301279825316497898035760524780198230860089280791887363472060435443944632303774987556026740232641561706904946900169858650106994947597642013168757868017723456208796677559254390940651802333382820063200360490892131573853635471525711894510477078934343423255983)
enc = 275574424285842306309073814038154403551700455145115884031072340378743712325975683329051874910297915882286569143815715537085387363420246497061870251520240399514896001311724695996978111559476733709139080970977190150345474341853495386364275702356438666152069791355990718058189043717952080875207858163490627801836274404446661613239167700736337269924479349700031535265765885064606399858172168036794462235707003475360358004643720927563261787867952228496769300443415094124132722170498229611285689671203272698693505808912907778910378274197503048226322090611405601517624884408718689404556983397217070272851442351897456769883
e = r*s,且e的bit长度为28,那么r以及s的bit长度则为14,由此可知m ** 2 - m + 2=14,可计算出m = 4。之后利用sage中的divisors函数分解e计算出r和s。因为p = a ** m + r,其中r对于a**m来说非常小,所以 n 4 ≈ a ∗ b \sqrt[4]{n} \approx a*b 4n≈a∗b;再联立 n = ( a 4 + r ) ∗ ( b 4 + s ) n = (a^4+r)*(b^4+s) n=(a4+r)∗(b4+s)构造方程组,进而解出a和b,此时p和q也计算出来了
# m ** 2 - m + 2 = 14, m = 4
div = divisors(e)
rs = []
for i in div:
if int(i).bit_length()==14:
rs.append(int(i))
s,r = rs[0],rs[1]
a_b = gmpy2.iroot(n,4)[0]
a,b = symbols('a b')
eq = [a*b-a_b,a**4*b**4+a**4*s+b**4*r+r*s-n]
result = list(nonlinsolve(eq, [a, b]))[0]
a = abs(result[0])
b = abs(result[1])
p = gmpy2.mpz(a**4+r)
q = gmpy2.mpz(b**4+s)
经计算,gcd(e,p-1)和gcd(e,q-1)都不为1,p的bit长度为1021远远大于flag的长度且gcd(e,p-1)较小,于是我们将其转换在模p下的多项式环下有限域开根,再遍历flag
from Crypto.Util.number import *
import gmpy2
n = 373824666550208932851344358703053061405262438259996622188837935528607451817812480600479188884096072016823491996056842120586016323642383543231913508464973502962030059403443181467594283936168384790367731793997013711256520780338341018619858240958105689126133812557401122953030695509876185592917323138313818881164334490044163316692588337720342646339764174333821950301279825316497898035760524780198230860089280791887363472060435443944632303774987556026740232641561706904946900169858650106994947597642013168757868017723456208796677559254390940651802333382820063200360490892131573853635471525711894510477078934343423255983
e = 150953688
c = 275574424285842306309073814038154403551700455145115884031072340378743712325975683329051874910297915882286569143815715537085387363420246497061870251520240399514896001311724695996978111559476733709139080970977190150345474341853495386364275702356438666152069791355990718058189043717952080875207858163490627801836274404446661613239167700736337269924479349700031535265765885064606399858172168036794462235707003475360358004643720927563261787867952228496769300443415094124132722170498229611285689671203272698693505808912907778910378274197503048226322090611405601517624884408718689404556983397217070272851442351897456769883
p = 15040222622096320078383580808680733765955114958694997949647342925417877088612792495485641348591026281373930569798925789027166056695954731923306109646611840570310396750856642056018981080439916663195842593441587057719678555907050674529272376248049062724657792390788687452049496308886252188791975094655675938807
q = 24854995563762799317055160315647073592768859410925406616067526817964296709994775588158311030813096922905657553370793515214591086698010302872311633588541111630338981703494212247996116660819640489213219705595382514374022123356637290058228183400682431815794876393612877273757515867990847040787313812864434536969
phi = gmpy2.mpz(p-1)
d = gmpy2.invert(gmpy2.mpz(e//72),phi)
m = pow(c,d,p)
P.<x>=PolynomialRing(Zmod(p),implementation='NTL')
f = x**72-m
res = f.monic().roots()
for i in res:
flag = long_to_bytes(int(i[0]))
if b"CCTF{" in flag:
print(flag)
break
flag:
CCTF{S!mP1E_A7t4cK_0n_SpEc1aL-5trucTur3D_RSA_pR1me5!}
【可能真正喜欢一个人,眼里没有ta的不好吧。】