MoeCTF2022 Crypto
MiniMiniPack
from gmpy2 import *
from Crypto.Util.number import *
import random
from FLAG import flag
def gen_key(size):
s = 1000
key = []
for _ in range(size):
a = random.randint(s + 1, 2 * s)
assert a > sum(key) # 超递增
key.append(a)
s += a
return key
m = bytes_to_long(flag)
L = len(bin(m)[2:])
key = gen_key(L)
c = 0
for i in range(L):
c += key[i]**(m&1)
m >>= 1
print(key)
print(c)
题目很明确的说明超递增序列了 直接判断 解就完了
key = [...]
c = ...
flag = ''
for i in range(len(key)-1,-1,-1):
x = key[i]
if c>=x:
c-=x
flag = '1'+flag
else:
c-=1
flag = '0'+flag
from libnum import *
print(n2s(int(flag,2)))
print(n2s(int(flag[::-1],2)))
# b'moectf{Co#gRa7u1at1o^s_yOu_c6n_d3c0de_1t}'
ez_cbc
from Crypto.Util.number import *
import random
from secret import flag
IV = bytes_to_long(b'cbc!')
K = random.randrange(1,1<<30)
assert flag[:7] == b'moectf{'
assert flag[-1:] == b'}'
block_length = 4
flag = flag + ((block_length - len(flag) % block_length) % block_length) * b'\x00'
plain_block = [flag[block_length * i: block_length * (i + 1)] for i in range(len(flag) // block_length)]
c = []
c0 = (IV ^ bytes_to_long(plain_block[0])) ^ K
c.append(c0)
for i in range(len(plain_block)-1):
c.append(c[i] ^ bytes_to_long(plain_block[i+1]) ^ K)
print(c)
'''
[748044282, 2053864743, 734492413, 675117672, 1691099828, 1729574447, 1691102180, 657669994, 1741780405, 842228028, 1909206003, 1797919307]
'''
注意到block_len=4 而flag前4位已知 所以可以恢复K
接下来就前后xor一下可以还原
from Crypto.Util.number import *
IV = bytes_to_long(b'cbc!')
c = [748044282, 2053864743, 734492413, 675117672, 1691099828, 1729574447, 1691102180, 657669994, 1741780405, 842228028, 1909206003, 1797919307]
flag = b'moectf{'
block_length = 4
flag = flag + ((block_length - len(flag) % block_length) % block_length) * b'\x00'
plain_block = [flag[block_length * i: block_length * (i + 1)] for i in range(len(flag) // block_length)]
K = c[0]^IV^bytes_to_long(plain_block[0])
print(K)
ans = b''
for i in range(len(c)-1):
ans += long_to_bytes(c[i]^c[i+1]^K)
print(ans)
# b'tf{es72b!a5-njad!@-#!@$sad-6bysgwy-1adsw8}\x00\x00'
Signin
from Crypto.Util.number import *
from secret import flag
m=bytes_to_long(flag)
p=getPrime(512)
q=getPrime(512)
print('p=',p)
print('q=',q)
n=p*q
e=65537
c=pow(m,e,n)
print('c=',c)
#p= 12408795636519868275579286477747181009018504169827579387457997229774738126230652970860811085539129972962189443268046963335610845404214331426857155412988073
#q= 12190036856294802286447270376342375357864587534233715766210874702670724440751066267168907565322961270655972226761426182258587581206888580394726683112820379
#c= 68960610962019321576894097705679955071402844421318149418040507036722717269530195000135979777852568744281930839319120003106023209276898286482202725287026853925179071583797231099755287410760748104635674307266042492611618076506037004587354018148812584502385622631122387857218023049204722123597067641896169655595
gcd(e,phi)=65537 这种有两种方法:
- 转到modp,modq (默认flag不太大)
- AMM开根
不知道为什么AMM没开出来 用第一种
from gmpy2 import gcd
from libnum import *
from primefac import *
p= 12408795636519868275579286477747181009018504169827579387457997229774738126230652970860811085539129972962189443268046963335610845404214331426857155412988073
q= 12190036856294802286447270376342375357864587534233715766210874702670724440751066267168907565322961270655972226761426182258587581206888580394726683112820379
c= 68960610962019321576894097705679955071402844421318149418040507036722717269530195000135979777852568744281930839319120003106023209276898286482202725287026853925179071583797231099755287410760748104635674307266042492611618076506037004587354018148812584502385622631122387857218023049204722123597067641896169655595
e = 65537
n = p*q
print(gcd(e,p-1),gcd(e,q-1))
d = modinv(e,p-1)
print(n2s(int(pow(c,d,p))))
# moectf{Oh~Now_Y0u_Kn0W_HoW_RsA_W0rkS!}
knapsack
直接套脚本
只是注意一下这里没有将flag转为二进制0/1 而是直接用ascii乘的 所以硬套有问题 但是输出规约后的格基可以很明显的发现
pubkey = []
nbit = len(pubKey)
# open the encoded message
encoded = '28856686525748125802152914172483571798453880654624111179873716369801238646447969551927508246737816822527579725991046201801262381722186539084044859241033407568422008911415092147086235301286167536726137372507078079415577358704181165698320539751269992479349480281465975374187246799267369957964807679383646749609694064517591097971225234359495013928292239934008888234863117359059334395043146949808360202225171337210959511092044766'
print ("start")
# create a large matrix of 0's (dimensions are public key length +1)
A = Matrix(ZZ, nbit + 1, nbit + 1)
# fill in the identity matrix
for i in range(nbit):
A[i, i] = 1
# replace the bottom row with your public key
for i in range(nbit):
A[i, nbit] = pubKey[i]
# last element is the encoded message
A[nbit, nbit] = -int(encoded)
res = A.LLL()
print(res[0])
for i in range(0, nbit + 1):
# print solution
M = res.row(i).list()
flag = True
for m in M:
if m != 0 and m != 1:
flag = False
break
if flag:
print (i, M)
M = ''.join(str(j) for j in M)
# remove the last bit
M = M[:-1]
M = hex(int(M, 2))[2:-1]
print (M)
flag = [78, 83, 83, 67, 84, 70, 123, 99, 97, 97, 56, 54, 99, 49, 48, 45, 56, 56, 102, 55, 45, 52, 100, 101, 102, 45, 98, 55, 48, 49, 45, 99, 51, 99, 54, 56, 101, 50, 102, 54, 49, 54, 52, 125, 0]
print(''.join(chr(x)for x in flag))
smooth
from Crypto.Util.number import sieve_base,isPrime,getPrime
import random
from secret import flag
def get_vulnerable_prime(): # 光滑数
p=2
while True:
for i in range(136):
smallp=random.choice(sieve_base)
p*=smallp
if isPrime(p+1):
return p+1
P=get_vulnerable_prime()
Q=getPrime(2048)
N=P*Q
e=0x10001
for i in range(1,P-1729):
flag=flag*i%P
c=pow(flag,e,N)
print("c=",hex(c))
print("N=",hex(N))
'''
c= 0x3cc51d09c48948e2485820f6758fb10c7693c236acc527ad563ba8369c50a0bc3f650f39a871ee7ef127950ed916c5f4dc69894e11caf9d178cd7e8f9bf9af77e1c69384cc5444da64022b45636eeb5b7a221792880dd242be2bb99be3ed02c430c2b77d4912bec1619d664e066680910317c2bb0c87fafdf25f0a2400103278f557b8eca51d3b67d61098f1ab68da072bb2810596180afbc81a840cd24efef4d4113235160e725a5af4824dc716d758b3bc792f2458e979398e001b27e44d21682e2ef80ae94e21cd09a12e522ca2e569df72f012fa40341645445c6e68c6233a8a39e5b91eb14b1ccfa61c9bad25e8e3285a22da27cd506ddd63f207517a4e8ede00b104d8806ff4c0e3162c3de69169d7e584952655272b96d39d242bb83019c7eab1ceb0b4b287591e1e0a5b6378e70340a82d3430c5925d215f31fda6d9d0bccea240591b22a3d0f6b5bf4ddf1243d71aca0fd53045c352c8c5497ebcdbd7ac11083d63aba7c053604fda2430c317a4e04702b5ad539e110f101165b21dcd9fdb5ba7324acdba6a506244ce7c911197dfe067441fe7488d164c050f45ef6476aaf399cedde1793cceb8c21d88ec8ecf5e17df27586713d7dd9566ec5023cfef75422b73e2d5a932c661b3cfdf9c4bda12b64380d2be1aa957c3e1416e068937bafe79b8cf303296792388e9c197702e11e7ded6088ae992d352b23a4a27
N= 0xdc77f076092cbe81c44789ccfc1b2ca55eabae65f44cf34382799e8bbb42d4d6c032bd897c21df1da401929d82deb56264823a757f6cacf63e0037146026cbab32ab9e4abc783dcabaac2b7ccc439937be3ab0fbf149524ff29ef0fe6f27e45215d74b40597c70e8207159dc7f542c2a6828500016480053dfc2d8dbf8fcdf6700640184c8f3318f7aab2e17e116edf680592f5eae951159bb8c20cfbd0cbab8b4b95925b5068038d0377a55a4d346ebbf53a1c2943b7c17e1b9d4a1b77916da2e15140b05b96655906942a07d04b7e25fa7521b3b7ae26eda68375a8b8ef2d5b4704a28168b236de97f24a663f0d0a3aeab47767dfe75a21662f5f25ef7f7d4b25c90fd7bcdd7137c23f03b6ea4209f8fb9b4628355e6ad62e6467d26666d3d1b0e6f078c5f3866413a6fcd3c1dc2ff3a5ab286e339d5c72f4d2f0473a4faddcba6b031bb6ec226fd4b319834b5029f09ea0ffeb5b6ed182d5a13675571b6708c38299118043390343e2f79edebd2ae0e0a765a3aebf776f54ca983cdae8547547cfc8430f7222aefa77301d7cc7c03b1451b6603028b21fea869d35138a9c83919985a91b3fdfa934f25a442cc10349b0ed6f2ee3955d40249e8b3fb9f1955534ee06cee41a3ad2d6ff7dbdb0f01e47b9e4d04f65232f5579135ae035e8ba2d1fe6465a730dcc8b9ba3a558ab38f040ea510757d25e92f886c50c24ad967f1
'''
首先利用p-1光滑分解N 然后威尔逊求解原始flag
from libnum import *
from Crypto.Util.number import *
from primefac import *
from gmpy2 import *
c= 247919865318021236816543824112508609330037721750833286282742196998469240722960067279753595030501837090213207723535315566071300075224019751428220840655379721168218967765876422567445308433288640784380506865731600610844664082126014969594703943321684739970369062910447373385433273463771025749544868874364857740886231104642660449357361214123805594448220938783838846810205396685290795472602986247805614885431726718734074115977778392666953702177131899677541805470136367291335492319211844518562048885624275188484150304531414129256199638223451626380382590726717299805272645061058959151344044346830823325114347635303124079585771118897549014215635831461496427865527725984314454215084824799195902666017890251546113340604997387337267033702985082689756489485483884466836894078681988327570736563527551002502155721535243073405426861909050072042543788614648220702009710283495882865771856434684115235716829225548094758262227047147018619782569249121457929508156495153802531122277665993110064189665320728788771547383303757706989175639195759242259782311848793696092654705894717312440565233739658573287960603925813253705712262506080990684572911512172618335848944155481909042800065581602613553170724199031407991191567888665889828134075331392699640862886439
n= 899433060816731427942704257866303221883919943075011482730540487542298141049688747403394155891424984817721637261796322290176226293021163615394020748313287704925351127104543540527171720585852101847552418109218698224283517650904796624423791889310920745115538568493036905521731801701334387698665349013555004156460425949614507368513929122918207275324019164019140872285865669776807164595612153523403959086174282977979597134418614250308867915724091583207037130579480546960070830233323713630083498257555891865243784412939799736393339765165471839069949178185209844627880366832657587045566078602359768140397724951796918685954810361034854946350278789032280015291656197323195678588879611176849643485660527731763117393276077174612788370830514391126349518373263177721819098959415747014310642914994052481426526649746349072693522436372936682595370113958488478854998334540278818899857117443348584084049535307410497695797641157090999920223711713543888446393339441597594366529426635229500879583956083509277478412156698422658437380950061203062993059862799664252602490913513388540711100204971238723316893774082588574855875619371443610116478930704000900105595123789440080606712893908761497290616683388289154125877364596699576556781203346107657789690701809
# 首先利用p-1光滑来分解N 得到p
B = 2
a = 2
while True:
a = pow(a,B,n)
_gcd = gcd(a-1,n)
if 1<_gcd<n:
p = _gcd
q = n//p
print(f'p= {p}\nq= {q}')
break
B = B+1
p= 45130782138821231634664822924606644347274161463663927387578931639175223286413378324882645031302403289842551326638702711998962760517679897418281467484531163375644705075213662848721478455926415639437965574871053673938130437463383431907231224801316309790287364751279984404056565040242248326224648040650860211493169850992812996172453840449200075853777085801648416876006333273306936825124410389797307488083056497244608773881660250930270420195391832629035158125925203262309579280388854014294622011159984832956422300816768157089660974628522818677622546453173413252374696944407138466146678080076210538578674319834619518810099
q= 19929480903966971877741359978214832777067673186776101767607985415984872967131783702304729626331577711025830876686674170433788564223656884574965375895417512648538448454114165043668565344845361735967533803734325629433944151906019295203849389937041766109566748588937702389000280859653264841778232075227804461734481644568063879619171473653153879467534960561551793532641987408308262590477344407917566949561595540828562062207376467975716207562802834742657134267225310067273840884699549038482335638587159643505585791895934244621169372816478043004416985427985158346066496193091020702283948166437350554644511384320505926737291
e=0x10001
d = modinv(e,(p-1)*(q-1))
flag = pow(c,d,n)
# 再利用威尔逊定理
for i in range(1,1730):
flag *= -i
flag %= p
flag = (-flag)%p
print(n2s(int(flag)))
# moectf{Charming_primes!_But_Sm0oth_p-1_1s_vu1nerab1e!}