DragonKnight CTF2024-Crypto方向wp

DragonKnight CTF

前言

打了一会就去鸣潮战斗爽了,所以没写几题,趁着有时间复现一下。

注:附件在我的github


题目

Crypto_签到

task

from Crypto.Util.number import *

m = b'flag{********}'

a = getPrime(247)
b = getPrime(247)
n = getPrime(247)

seed = bytes_to_long(m)

class LCG:
   def __init__(self, seed, a, b, m):
      self.seed = seed 
      self.a = a 
      self.b = b 
      self.m = m 
   def generate(self):
      self.seed = (self.a * self.seed + self.b) % self.m
      self.seed = (self.a * self.seed + self.b) % self.m
      return self.seed

seed = bytes_to_long(m)
output = LCG(seed,a,b,n)

for i in range(getPrime(16)):
   output.generate()

print(output.generate())
print(output.generate())
print(output.generate())
print(output.generate())
print(output.generate())

'''
5944442525761903973219225838876172353829065175803203250803344015146870499
141002272698398325287408425994092371191022957387708398440724215884974524650
42216026849704835847606250691811468183437263898865832489347515649912153042
67696624031762373831757634064133996220332196053248058707361437259689848885
19724224939085795542564952999993739673429585489399516522926780014664745253
'''

思路:额,就是lcg进行了两次,是一个比较基础的题,网上有很多脚本,我前面的一个博客里面也有,直接套就好了。

 

exp

c = []

import gmpy2
from Crypto.Util.number import GCD, isPrime, long_to_bytes

t=[]
for i in range(1,len(c)):
   t.append(c[i]-c[i-1])
m = 0

for i in range(1,len(t)-1):
   m = GCD(t[i+1]*t[i-1]-t[i]**2, m)

a = (c[3]-c[2])*gmpy2.invert(c[2]-c[1],m) % m
b = (c[2]-a*c[1]) % m 
a_1=gmpy2.invert(a,m)

for i in range(2**16):
   c[1] = (c[1]-b) * a_1 % m
   flag = long_to_bytes(c[1])
      if b'flag{' in flag:
         print(flag)
         break

#flag{Hello_CTF}

 

 

EzDES

task

from Crypto.Cipher import DES
from Crypto.Util.Padding import pad
from secret import flag,key

key = bytes.fromhex(key)
des = DES.new(key, DES.MODE_ECB)
enc = des.encrypt(pad(flag,64))
print(enc)

"""
b't\xe4f\x19\xc6\xef\xaaL\xc3R}\x08;K\xc9\x88\xa6|\nF\xc3\x12h\xcd\xd3x\xc3(\x91\x08\x841\xca\x8b\xc1\x94\xb5\x9f[\xcd\xc6\x9f\xf9\xf6\xca\xf5\x1a\xda\x16\xcf\x89\x154\xa1\xfe\xc5\x16\xcf\x89\x154\xa1\xfe\xc5'
"""

思路:当时比赛时题目框里面的hint是想想des中key的特点,说实话,当时我真的不知道,后面在群里交流的时候才知道是弱密钥。

分别是这八个

 

0x0101010101010101
0xFEFEFEFEFEFEFEFE
0xE0E0E0E0F1F1F1F1
0x1F1F1F1F0E0E0E0E
0x0000000000000000
0xFFFFFFFFFFFFFFFF
0xE1E1E1E1F0F0F0F0
0x1E1E1E1E0F0F0F0F

随便拿一个当key就出来了。

exp

c=

from Crypto.Cipher import DES

key='0000000000000000'
key = bytes.fromhex(key)
des = DES.new(key, DES.MODE_ECB)
flag=des.decrypt(c)
print(flag)

#DRKCTF{We4k_K3y_1s_V3ry_D4nger0us_In_DES}

 

 

MatrixRSA_Revenge

task

from Crypto.Util.number import *
import os

flag = b"DRKCTF{??????????????}" + os.urandom(212)

p = getPrime(120)
q = getPrime(120)
print(f"p = {p}")

print(f"q = {q}")
part = [bytes_to_long(flag[16*i:16*(i+1)]) for i in range(16)]

M = Matrix(Zmod(n),[
[part[4*i+j] for j in range(4)] for i in range(4)
])

e = 65537
C = M ** e
print(f"C = {list(C)}")

"""
p = 724011645798721468405549293573288113 
q = 712853480230590736297703668944546433
C = [(354904294318305224658454053059339790915904962123902870614765704810196137, 307912599668649689143528844269686459695648563337814923172488152872006235, 143644686443811064172873392982322248654471792394264352463341325181752577, 22995887787365556743279529792687264972121816670422146768160153217903088), (111349308911096779758451570594323566987628804920420784718347230085486245, 370237591900013263581099395076767089468466012835217658851568690263421449, 305451886364184428434479088589515273362629589399867618474106045683764897, 454103583344277343974714791669312753685583930212748198341578178464249150), (168497521640129742759262423369385500102664740971338844248603058993335309, 228941893018899960301839898935872289351667488000643221589230804176281482, 340080333594340128998141220817079770261711483018587969623825086357581002, 122922413789905368029659916865893297311475500951645918611759627764993518), (10332477229415731242316540110058798318207430965033579181240340751539101, 238172263316130590821973648893483382211906906298557131324791759298887701, 487586702165464601760230182019344052665496627253691596871783460314632260, 12238020921585443139790088280608644406695242899000592355653073240122626)]
"""

思路:这个题目主要考察了一般线性群的阶,这个题就是四阶模p矩阵的阶,然后就是rsa了。

 

exp

p= 
q=
C=[]

from Crypto.Util.number import *

phi1=(p-1)*(p+1)*(p^2+p+1)*p*(p^2+1)
phi2=(q-1)*(q+1)*(q^2+q+1)*q*(q^2+1)

d=inverse(65537,phi1*phi2)
C=Matrix(Zmod(p*q),C)

M=C**d

flag=b""
for i in range(4):
   for j in range(4):
      flag+=long_to_bytes(int(M[i,j]))
print(flag)

#DRKCTF{a58986e7-33e5-4f65-8c22-b8a5e620752d}

 

 

MidRSA

task

from Crypto.Util.number import *
from secret import flag
import random
import gmpy2

def generate_Key1(ebits):
   e = [getPrime(ebits) for _ in range(4)]
   return e

def encrypt1(message,e):
   n = gmpy2.next_prime(bytes_to_long(message) << 300)
   m = getPrime(256)
   c = [int(pow(m,e[i],n)) for i in range(len(e))]
   return c

def generate_Key2(nbits):
   p = getPrime(nbits // 2)
   q = getPrime(nbits // 2)
   n = p*q
   e = [random.getrandbits(nbits // 4) for _ in range(3)]
   return n,e

def encrypt2(message,e,n):
   m = bytes_to_long(message)
   c = [int(pow(m,e[i],n)) for i in range(len(e))]
   return c

assert flag.startswith(b"DRKCTF{")

flag1 = flag[:len(flag)//2]
flag2 = flag[len(flag)//2:]

ebits = 7
e1 = generate_Key1(ebits)
cipher1 = encrypt1(flag1,e1)
print("e1 =",e1)
print("cipher1 =",cipher1)

nbits = 1024
n,e2 = generate_Key2(nbits)
cipher2 = encrypt2(flag2,e2,n)
print("e2 =",e2)
print("cipher2 =",cipher2)
print("n =",n)

"""
e1 = [109, 71, 109, 73]
cipher1 = [36272047346364825234770733058042613197790911431212158822254782055957208837848605160852567043492625692783344073921185227328379941291979083011033, 13421582077901767047291741873622169312010984740586925881415103229648835151589774736786336965745532072099996467445790339749720696886313635920080, 36272047346364825234770733058042613197790911431212158822254782055957208837848605160852567043492625692783344073921185227328379941291979083011033, 41425183140413487232780768389488969603566343428250573532166425276868000949579663990819005141199597640625439816343697426958648927294289659127871]
e2 = [79572758141493570128961125255246129069540961757778793209698370333142346488381, 80555585862127636800866563977080055603517001358195529410497461746213789997225, 44651921320695090688745333790065512192118202496468714141526113242887125432380]
cipher2 = [58600444300331800249882073146233995912287198739549440714207984476331259754331716531491187240053630185776787152600165426285021284302994699108557023545574315706006132536588848833818758624067461985444940651823107522770906474037882323326792755635934081822967331031854184791299228513024491344725765476710816941057, 16511944800191885973496391252612222059697387587833308714567450121364756390806094606646424594583975159634952911600665271092389815248477961923357683297311169260578508157717777465241680062644118354471550223231057620392252324514411927096940875466794869671163453991620492008856178108060167556176019729800517994337, 80885008609388989196377721090246742575908473911131498982960117640742106565184297197238656375198284856442596226398287448931285735903463892735111244609358611618958293002176923706195402338331128766464276441210238388187625107435781170368017908610916585774514676482124401329575553658828115269495158818527164441546]
n = 93468142044831350317940409833603031534515663349871776634867176846669780024082517910566484997161088199091160371537367121403194814422867749777235397168852158723228851090445429617275680206703935781244466363279841409768649097588586494453125840436600639420286950914680651600232197982546122764845043227394567787283
"""

第一部分

在官方wp中是类似爆破的方法去写的,在这里用格的方法去写,看鸡块师傅的博客可能会更加清楚一点

exp

e= [109, 71, 73]
c= [36272047346364825234770733058042613197790911431212158822254782055957208837848605160852567043492625692783344073921185227328379941291979083011033, 13421582077901767047291741873622169312010984740586925881415103229648835151589774736786336965745532072099996467445790339749720696886313635920080, 41425183140413487232780768389488969603566343428250573532166425276868000949579663990819005141199597640625439816343697426958648927294289659127871]

L = Matrix(ZZ, 3, 4)
for i in range(3):
   L[i,0] = e[i]*1000
   L[i,i+1] = 1
L = L.LLL()

alist1 = L[0][1:]
k1nl = 1
k1nr = 1
for i in range(3):
   if(alist1[i]<0):
      k1nr *= c[i]**(-alist1[i])
   else:
      k1nl *= c[i]**alist1[i]
k1n = k1nl-k1nr

alist2 = L[1][1:]
k2nl = 1
k2nr = 1
for i in range(3):
   if(alist2[i]<0):
      k2nr *= c[i]**(-alist2[i])
   else:
      k2nl *= c[i]**alist2[i]
k2n = k2nl-k2nr

n = gcd(k1n,k2n)

for i in range(2,10000):
   while(n % i == 0):
      n //= i

print(long_to_bytes(n>>300))

#DRKCTF{5d0b96e8-e069-4

第二部分

 

就是简单的共模了

e = [79572758141493570128961125255246129069540961757778793209698370333142346488381, 80555585862127636800866563977080055603517001358195529410497461746213789997225, 44651921320695090688745333790065512192118202496468714141526113242887125432380]
c = [58600444300331800249882073146233995912287198739549440714207984476331259754331716531491187240053630185776787152600165426285021284302994699108557023545574315706006132536588848833818758624067461985444940651823107522770906474037882323326792755635934081822967331031854184791299228513024491344725765476710816941057, 16511944800191885973496391252612222059697387587833308714567450121364756390806094606646424594583975159634952911600665271092389815248477961923357683297311169260578508157717777465241680062644118354471550223231057620392252324514411927096940875466794869671163453991620492008856178108060167556176019729800517994337, 80885008609388989196377721090246742575908473911131498982960117640742106565184297197238656375198284856442596226398287448931285735903463892735111244609358611618958293002176923706195402338331128766464276441210238388187625107435781170368017908610916585774514676482124401329575553658828115269495158818527164441546]
n = 93468142044831350317940409833603031534515663349871776634867176846669780024082517910566484997161088199091160371537367121403194814422867749777235397168852158723228851090445429617275680206703935781244466363279841409768649097588586494453125840436600639420286950914680651600232197982546122764845043227394567787283

from Crypto.Util.number import long_to_bytes
from gmpy2 import gmpy2

r,s1,s2 = gmpy2.gcdext(e[0], e[1])
m = (pow(c[0],s1,n)*pow(c[1],s2,n)) % n
print(long_to_bytes(m))

#378-82e7-120e4b761a0b}

 

 

MyEncrypto

task

from Crypto.Util.number import *
from secret import flag 
import random

def getMyPrime(): 
   while True: 
   r = random.getrandbits(64) 
   _p = r**6 -3*r**5 - r**4 + r**2 - r - 6
   _q = r**7 + 2*r**6 + r**5 + 4*r**4 + 7*r**2 + r + 4653
   if isPrime(_p) and isPrime(_q): 
      return _p, _q

def enc(m, n): 
   return pow(m, 65537, n) 

def LCG(s,a,b,n):
   return (a*s + b) % n

seed = bytes_to_long(flag)
P = getPrime(512)
a = random.randrange(0,P)
b = random.randrange(0,P)

def Roll():
   global seed
   seed = LCG(seed,a,b,P)
   return seed % 2**16

p, q = getMyPrime()
n = p * q 
enc_P = enc(P, n)
print(f"n = {n}") 
print(f"enc_P = {enc_P}")

out = []
for _ in range(40):
   out.append(Roll())

print(f"a = {a}")
print(f"b = {b}")
print(f"out = {out}")

"""
n = 17959692613208124553115435318871530105762927141420294800783695207170608966804977782615874404539156257549097962410144332053383210075663138848832474791712256427111304125146378883542387121684653496644116081809328796925343393644118376497507
enc_P = 17215745298239635988196009014709535403293865406390546681749129213899045156482782458937447412919331336842808052179915132663427715069134196783415529688715962754860563850858056507148936427379551986735103284388996678146580229028006898491552
a = 2759277675743644814124420138047586760905070650864591936190199977578763421196999718749092450720072564786874114432179104175692800471519816376692104515142375
b = 8111240578821759579875175166986910195923820191652867334412871591814076020421468033017946066268237980082938735686222173713853299600396887041341974719819186
out = [39566, 15295, 19818, 55685, 49100, 6517, 2675, 9567, 37243, 40312, 42906, 35874, 44178, 1256, 40298, 29149, 35721, 19886, 63020, 50116, 6844, 39897, 16134, 50218, 44609, 46188, 52712, 49903, 20933, 5441, 19411, 8330, 6904, 39350, 60853, 43446, 35910, 43728, 61533, 13757]
"""

第一部分

按着题目的节奏走,先求出r,然后就知道了_p和_q,也就找到了P

代码

n = 17959692613208124553115435318871530105762927141420294800783695207170608966804977782615874404539156257549097962410144332053383210075663138848832474791712256427111304125146378883542387121684653496644116081809328796925343393644118376497507

from Crypto.Util.number import *
from sympy import *

r=Symbol('r')
_p = r**6 -3*r**5 - r**4 + r**2 - r - 6
_q = r**7 + 2*r**6 + r**5 + 4*r**4 + 7*r**2 + r + 4653
z=solve([_p*_q-n],[r])
print(z)

#z=1248775963213848425

enc_P = 17215745298239635988196009014709535403293865406390546681749129213899045156482782458937447412919331336842808052179915132663427715069134196783415529688715962754860563850858056507148936427379551986735103284388996678146580229028006898491552
z=1248775963213848425
_p = z**6 -3*z**5 - z**4 + z**2 - z - 6
_q = z**7 + 2*z**6 + z**5 + 4*z**4 + 7*z**2 + z + 4653
d=inverse(65537,(_p-1)*(_q-1))
P=pow(enc_P,d,_p*_q)
print('P=', P)

#P=10679387699123200522776360035184725927822172255453595568464894884736102462568579313264894449779104030120028056158023524486966766295648236135714849745610937

第二部分

一种是论文做法,参考RECONTRUNC.pdf (cmu.edu),大概意思是根据lcg去写出方程,再利用cvp去恢复lcg

代码,参考了Kicky_Mu师傅的代码

def gen_matrix(a:int, modulus:int, size:int) -> list:
   matrix = [[0]*size for _ in range(size)]
   for i in range(size):
      matrix[0][i] = pow(a, i, modulus)
   for i,j in zip(range(1,size), range(1,size)):
      if i==j:
         matrix[i][j] = modulus
   return matrix

def attack(a:int, modulus:int, output_length:int, Ys:list):
   I = inverse_mod(2**output_length, modulus)
   y = [(el*I) % modulus for el in Ys]
   L = IntegerMatrix.from_matrix(gen_matrix(a, modulus, len(Ys)))
   reduced = LLL.reduction(L)
   Xi_I = CVP.closest_vector(reduced, y, method="fast")
   Xi = [xi_i*2**output_length % modulus for xi_i in Xi_I]
   return Xi

diffs = []
for i in range(len(out) - 1):
   diffs += [out[i + 1] - out[i]]
Xi = attack(a, P, 16, diffs)
seed = ((((Xi[0] - b) * inverse_mod(a - 1, P)) % P) - b) * inverse_mod(a, P) % P
flag = long_to_bytes(seed)
print(flag)

第二种就是直接去手算这个表达式

然后就出来了

代码

P=10679387699123200522776360035184725927822172255453595568464894884736102462568579313264894449779104030120028056158023524486966766295648236135714849745610937
a = 2759277675743644814124420138047586760905070650864591936190199977578763421196999718749092450720072564786874114432179104175692800471519816376692104515142375
b = 8111240578821759579875175166986910195923820191652867334412871591814076020421468033017946066268237980082938735686222173713853299600396887041341974719819186
out = [39566, 15295, 19818, 55685, 49100, 6517, 2675, 9567, 37243, 40312, 42906, 35874, 44178, 1256, 40298, 29149, 35721, 19886, 63020, 50116, 6844, 39897, 16134, 50218, 44609, 46188, 52712, 49903, 20933, 5441, 19411, 8330, 6904, 39350, 60853, 43446, 35910, 43728, 61533, 13757]from Crypto.Util.number import *
import gmpy2
from Crypto.Util.number import *

L = [0] + out
n = len(out)
A = [1]
B = [0]
for i in range(1,n):
   A.append(a*A[i-1] % P)
   B.append((a*B[i-1] + (a*L[i]+b-L[i+1])*gmpy2.invert(2^16,P))%P)

A = A[1:]
B = B[1:]
Ge = Matrix(ZZ,n+1,n+1)
for i in range(len(A)):
   Ge[i,i] = P
   Ge[-2,i] = A[i]
   Ge[-1,i] = B[i]

Ge[-2,-2] = 1
Ge[-1,-1] = P // 2^16

M = Ge.LLL()[0]
H1 = M[-2]
L1 = out[0]
seed1 = H1 * 2^16 + L1
seed = ((seed1 - b)*gmpy2.invert(a,P))%P

print(long_to_bytes(int(seed)))

#DRKCTF{a57b63a6-ecf5-46d3-a501-2d359a4fd168}

 

 

 

 

心如草木,向阳而生
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇