2023羊城杯

2023羊城杯——Crypto题解

比赛成绩并不算好,不过挺开心的

前一天玩游戏玩晚了,导致今天状态挺不好的。很多题能更早做出来,却卡了很久。

经过这次比赛又学到了好多

Danger_RSA

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from Crypto.Util.number import *

m = bytes_to_long(flag)


def get_key(a, nbit):
assert a >= 2
while True:
X = getRandomInteger(nbit // a)
s = getRandomRange(pow(2, a ** 2 - a + 4), pow(2, a ** 2 - a + 5))
p = X ** a + s
if isPrime(p):
return (p, s)


p, s = get_key(a, 1024)
q, t = get_key(a, 1024)

N = p * q
e = s * t
c = pow(m, e, N)
print("N =", N)
print("e =", e)
print("c =", c)
# N =
# e = 11079917583
# c =

根据$p,q$的生成方式可知$p = x^a+s,q = y^a+t$

根据$e$的比特大小判断出$a=4,s = 17bit,t = 17bit$

把$e$分解后得到$e = 3\times7^2 \times 19 \times 691 \times 5741$

选出合适的乘积作为$s,t$

$\therefore p =x^4 + s,q = y^4 + t$,$p \approx x^4,q \approx y^4$

则$n \approx(xy)^4 \longrightarrow xy = n^{\frac{1}{4}}$

得到$xy$之后

联立$n = (x^4+s)(y^4+t)$与$x\times y = xy$

解出$x,y$,这里要注意的是,s,t要选合适,才有整数解,多试试

然后就能出p,q了,发现$e$和$\phi(n)$不互素

处理一下即可

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from Crypto.Util.number import *
import gmpy2

n = 20289788565671012003324307131062103060859990244423187333725116068731043744218295859587498278382150779775620675092152011336913225797849717782573829179765649320271927359983554162082141908877255319715400550981462988869084618816967398571437725114356308935833701495015311197958172878812521403732038749414005661189594761246154666465178024563227666440066723650451362032162000998737626370987794816660694178305939474922064726534186386488052827919792122844587807300048430756990391177266977583227470089929347969731703368720788359127837289988944365786283419724178187242169399457608505627145016468888402441344333481249304670223
e = 11079917583
c = 13354219204055754230025847310134936965811370208880054443449019813095522768684299807719787421318648141224402269593016895821181312342830493800652737679627324687428327297369122017160142465940412477792023917546122283870042482432790385644640286392037986185997262289003477817675380787176650410819568815448960281666117602590863047680652856789877783422272330706693947399620261349458556870056095723068536573904350085124198592111773470010262148170379730937529246069218004969402885134027857991552224816835834207152308645148250837667184968030600819179396545349582556181916861808402629154688779221034610013350165801919342549766

s = 120561
t = 91903


ab = int(gmpy2.iroot(n,4)[0])

# var('a b')
# f1 = a*b-ab
# f2 = ab^4 + a^4*t + b^4*s + s*t - n
# ans = solve([f1,f2],[a,b])
# print(ans)

a = 47783641287938625512681830427927501009821495321018170621907812035456872958654
b = 44416071018427916652440592614276227563515579156219730344722242565477265479486

p = a^4 + s
q = b^4 + t
assert p*q == n

phi = (p-1)*(q-1)

# print(gcd(e,phi))
# 21

d = gmpy2.invert(e // 21,p - 1)
m_21 = pow(c,d,p)
#求出m的21次方
e = 21

R.<x>=PolynomialRing(Zmod(p))
f = x^e - m_21
f = f.monic()
mps = f.roots()
for i in mps:
flag=long_to_bytes(int(i[0]))
if b'DASCTF' in flag:
print(flag)

一般flag没有填充的情况下,会小于p,所以用$p,q$单独作公钥求解

求解出$m^{21} \equiv c^{d} \mod p$

再用多项式环求根

参考:2023 CryptoCTF wp by lingfeng (medium分类——1)_c_ling_feng的博客-CSDN博客

Easy_3L

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
from gmpy2 import *
from Crypto.Util.number import *
from secret import flag

m = bytes_to_long(flag)


def get_key():
p = getPrime(1400)
f = getRandomNBitInteger(1024)
while True:
q = getPrime(512)
if gcd(f, q) != 1:
continue
else:
break
h = (invert(f, p) * q) % p
return p, h


def encrypt1(m):
a = getPrime(250)
b = getRandomNBitInteger(240)
n = getPrime(512)
seed = m
s = [0] * 6
s[0] = seed
for i in range(1, 6):
s[i] = (s[i - 1] * a + b) % n
return s


def encrypt2(msg, p, h):
s = getRandomNBitInteger(512)
c = (s * h + msg) % p
return c


s = encrypt1(m)
print("S1 =", s[1])
print("S2 =", s[2])
print("S4 =", s[4])
print("S5 =", s[5])

p, h = get_key()
c = encrypt2(s[3], p, h)
print("p =", p)
print("h =", h)
print("c =", c)

# S1 =
# S2 =
# S4 =
# S5 =
# p =
# h =
# c =

没给出S3,要先把S3求出来,然后就是LCG求解

已知$c \equiv sh+msg \mod p \longrightarrow c = sh + msg +kp$

$\therefore msg = c - sh -kp$

构造这样的格

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#sage
from Crypto.Util.number import *
import gmpy2

p = 25886434964719448194352673440525701654705794467884891063997131230558866479588298264578120588832128279435501897537203249743883076992668855905005985050222145380285378634993563571078034923112985724204131887907198503097115380966366598622251191576354831935118147880783949022370177789175320661630501595157946150891275992785113199863734714343650596491139321990230671901990010723398037081693145723605154355325074739107535905777351
h = 2332673914418001018316159191702497430320194762477685969994411366563846498561222483921873160125818295447435796015251682805613716554577537183122368080760105458908517619529332931042168173262127728892648742025494771751133664547888267249802368767396121189473647263861691578834674578112521646941677994097088669110583465311980605508259404858000937372665500663077299603396786862387710064061811000146453852819607311367850587534711
c = 20329058681057003355767546524327270876901063126285410163862577312957425318547938475645814390088863577141554443432653658287774537679738768993301095388221262144278253212238975358868925761055407920504398004143126310247822585095611305912801250788531962681592054588938446210412897150782558115114462054815460318533279921722893020563472010279486838372516063331845966834180751724227249589463408168677246991839581459878242111459287

Ge = Matrix(ZZ,[
[-p,0,0],
[-h,1,0],
[c,0,2^512]
])

for i in Ge.LLL():
if abs(i[-1]) == 2^512:
S3 = i[0]

S1 = 28572152986082018877402362001567466234043851789360735202177142484311397443337910028526704343260845684960897697228636991096551426116049875141
S2 = 1267231041216362976881495706209012999926322160351147349200659893781191687605978675590209327810284956626443266982499935032073788984220619657447889609681888
S4 = 9739918644806242673966205531575183334306589742344399829232076845951304871478438938119813187502023845332528267974698273405630514228632721928260463654612997
S5 = 9755668823764800147393276745829186812540710004256163127825800861195296361046987938775181398489372822667854079119037446327498475937494635853074634666112736

output = [S1,S2,S3,S4,S5]
t = []
for i in range(1,len(output)):
t.append(output[i]-output[i-1])

T = []
for i in range(1,len(t)-1):
T.append(t[i+1]*t[i-1] - t[i]**2)

m = []
for i in range(len(T)-1):
mm = gmpy2.gcd(T[i],T[i+1])
m.append(int(mm))
# print(m)
for i in m:
if isPrime(i):
a = gmpy2.invert(t[0],i) * t[1] % i
b = output[1] - a*output[0] % i
a_ = gmpy2.invert(a,i)

seed = a_ * (output[0]-b) % i
print(long_to_bytes(seed))

signinCrypto

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
from random import *
from Crypto.Util.number import *
from Crypto.Cipher import DES3
from flag import flag
from key import key
from iv import iv
import os
import hashlib
import secrets

K1= key
hint1 = os.urandom(2) * 8
xor =bytes_to_long(hint1)^bytes_to_long(K1)
print(xor)

def Rand():
rseed = secrets.randbits(1024)
List1 = []
List2 = []
seed(rseed)
for i in range(624):
rand16 = getrandbits(16)
List1.append(rand16)
seed(rseed)
for i in range(312):
rand64 = getrandbits(64)
List2.append(rand64)
with open("task.txt", "w") as file:
for rand16 in List1:
file.write(hex(rand16)+ "\n")
for rand64 in List2:
file.write(hex((rand64 & 0xffff) | ((rand64 >> 32) & 0xffff) << 16) + "\n")
Rand()

K2 = long_to_bytes(getrandbits(64))
K3 = flag[:8]

KEY = K1 + K2 + K3

IV=iv

IV1=IV[:len(IV)//2]
IV2=IV[len(IV)//2:]

digest1 = hashlib.sha512(IV1).digest().hex()
digest2 = hashlib.sha512(IV2).digest().hex()

digest=digest1+digest2
hint2=(bytes_to_long(IV)<<32)^bytes_to_long(os.urandom(8))
print(hex(bytes_to_long((digest.encode()))))
print(hint2)


mode = DES3.MODE_CBC
des3 = DES3.new(KEY, mode, IV)

pad_len = 8 - len(flag) % 8
padding = bytes([pad_len]) * pad_len
flag += padding

cipher = des3.encrypt(flag)

ciphertext=cipher.hex()
print(ciphertext)

# 334648638865560142973669981316964458403
# 0x62343937373634656339396239663236643437363738396663393438316230353665353733303939613830616662663633326463626431643139323130616333363363326631363235313661656632636265396134336361623833636165373964343533666537663934646239396462323666316236396232303539336438336234393737363465633939623966323664343736373839666339343831623035366535373330393961383061666266363332646362643164313932313061633336336332663136323531366165663263626539613433636162383363616537396434353366653766393464623939646232366631623639623230353933643833
# 22078953819177294945130027344
# a6546bd93bced0a8533a5039545a54d1fee647007df106612ba643ffae850e201e711f6e193f15d2124ab23b250bd6e1

重点是求KEYIV

观察代码,能猜测出,K1IV,长度为8,

说明xor =bytes_to_long(hint1)^bytes_to_long(K1),hint1的高位没有受影响

输出long_to_bytes(xor),能够得到hint1 = b'\xfb\xc2' * 8

随即能出K1 = b"dasctfda"

K2通过随机数求得

给出的是rand64[16:32]+rand64[48:64]

随机数的生成机制: 通过生成32bit的数进行拼接或者移位(大佬教的)

如果要生成16bit的数,是先生成32bit再取这个数的高16位

如果要生成64bit的数,先生成两个32bit的数x1,x2,再进行拼接x2||x1

本题中,因为两次seed是一样的,所以rand16就是x1的前16位,后面输出的rand16x2的前16位

rand64 = x2[:16] || rand64[16:32] || x1[:16] || rand64[48:64]

这样就有了全部rand64,一共312个rand64

K3前七位是DASCTF{,最后一位不太确定

又因为hint2=(bytes_to_long(IV)<<32)^bytes_to_long(os.urandom(8)),说明IV的前面32bit不受影响

直接打印出,得到b'GWHT',注意到给出的那一段数据是两端重复数据拼接在一起的。

说明IV1 = IV2 = b'GWHT',$\therefore$IV = b'GWHTGWHT'

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
from Crypto.Util.number import *
from Crypto.Cipher import DES3
from extend_mt19937_predictor import ExtendMT19937Predictor

predictor = ExtendMT19937Predictor()

xor = 334648638865560142973669981316964458403
# print(long_to_bytes(xor))

hint1 = b'\xfb\xc2' * 8

K1 = long_to_bytes(bytes_to_long(hint1) ^ xor)
# print(K1)
# K1 = b'dasctfda'
hint2 = 22078953819177294945130027344
# print(long_to_bytes(hint2))

K1 = b"dasctfda"
IV = b"GWHTGWHT"

f = open("task.txt",'r')

data = []
for i in f.readlines():
data.append(eval(i))

data1 = data[:624]
data2 = data[624:]

data3 = []

for i in data2:
b = (i >> 16) & 0xffff
d = i & 0xffff
data3.append(d)
data3.append(b)
for i,j in zip(data1,data3):
t = (i << 16) + j
predictor.setrandbits(t,32)

K2 = long_to_bytes(predictor.predict_getrandbits(64))
# print(K2)
K3 = b"DASCTF{"

c = "a6546bd93bced0a8533a5039545a54d1fee647007df106612ba643ffae850e201e711f6e193f15d2124ab23b250bd6e1"
c = bytes.fromhex(c)
for i in range(2**8):
KEY = K1 + K2 + K3 + long_to_bytes(i)
try:
mode = DES3.MODE_CBC
des3 = DES3.new(KEY, mode, IV)
flag = des3.decrypt(c)
if b'DASCTF{' in flag:
print(flag)
except:
continue

esyRSA——复现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from gmpy2 import invert
from md5 import md5
from secret import p, q

e = ?????
n = p*q
phi = (p-1)*(q-1)
d = invert(e, phi)
ans = gcd(e,phi)

print n, e, d
print "Flag: DASCTF{%s}" %md5(str(p + q)).hexdigest()

"""
n =
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913
"""

发现这个n是有重复部分的,把重复部分删去后是正确的n

n=80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373

$\because ed \equiv 1 \mod \phi(n)$

$\longrightarrow ed = k\phi(n) + 1$

同除$e \times \phi(n)$

$\longrightarrow \frac{d}{\phi(n)} = \frac{k}{e} + \frac{1}{e\times \phi(n)}$

$\because \phi(n) \approx n$

$\therefore 上式 \longrightarrow \frac{d}{n} \approx \frac{k}{e}$

对$\frac{d}{n}$进行连分数展开,得到的一串分数的分母很可能就是e

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#sage
import hashlib

n = 80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913

c = continued_fraction(Integer(d) / Integer(n))

i = 1
while 1:
k = int(c.numerator(i)) #取连分数的分子
e = int(c.denominator(i)) #取连分数的分母
#计算kphi
if (e * d - 1) % k == 0 and len(str(e)) == 5:
phi = (e * d - 1) // k
p_q = n - phi + 1
print("p+q=",p_q)
print("e=",e)
# e = 13521
print("k=",k)
# k = 2384
var('p q')
f1 = p * q - n
f2 = p + q - p_q
sol = solve([f1,f2],[p,q])
print(sol)
break
else:
i += 1

p = 7920625690369490250766357750388349704260128405941822835255851274284409978206593795103040446837018619894098452542488850045009467407103749792461438242280929
q = 10181341212828413853336916619161138854377885230386496425058202154486415709366161346816273366144505351043947477469664133317598479763451392984403646602585037

flag = "DASCTF{" + hashlib.md5(str(p+q).encode()).hexdigest() + '}'
print(flag)

另外一种用格的思路解决

$\because ed \equiv 1 \mod phi$

$\therefore ed = kphi + 1 \longrightarrow ed = k(n - p - q + 1) + 1$

$ed = kn - k(p+q-1)+1$

$k(p+q-1)-1 = kn -ed$

构造格

规约后能得到e,再求k(p+q-1)ed - 1的公因数得到k

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import hashlib

n = 80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913

Ge = Matrix(ZZ,[
[2^512 , d],
[0 , n]]
)

L = Ge.LLL()[0]
e = abs(L[0]) // 2^512

k = gcd(e*d - 1,L[1]+1)

p_q = (L[1]+1) // k + 1
flag = "DASCTF{" + hashlib.md5(str(p_q).encode()).hexdigest() + '}'
print(flag)

MCeorpkpleer

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
from Crypto.Util.number import *
from secret import flag


def pubkey(list, m, w):
pubkey_list = []
for i in range(len(e_bin)):
pubkey_list.append(w * list[i] % m)
return pubkey_list


def e_cry(e, pubkey):
pubkey_list = pubkey
encode = 0
for i in range(len(e)):
encode += pubkey_list[i] * int(e[i]) % m
return encode


p = getPrime(1024)
q = getPrime(1024)
n = p * q
e = getPrime(64)
m = bytes_to_long(flag)
c = pow(m, e, n)

e_bin = (bin(e))[2:]
list = [pow(3, i) for i in range(len(e_bin))]
m = getPrime(len(bin(sum(list))) - 1)
w = getPrime(64)
pubkey = pubkey(list, m, w)
en_e = e_cry(e_bin, pubkey)

print('p = {}\n'
'n = {}\n'
'c = {}\n'
'pubkey = {}\n'
'en_e = {}'.format((p >> 435) << 435, n, c, pubkey, en_e))

'''
p =
n =
c =
pubkey =
en_e = 31087054322877663244023458448558
'''

给出p的高位,coppersmith梭出p

需要求一下e

观察加密发现,list是固定的,因为len(e_bin)==64

而且pubkey的第一位就是w

又$\because pubkey_i \equiv list_i × w \mod m$

$\therefore km = list_i \times w-pubkey_i$

通过这个,求出几个km,再求公因数,经过验证即可求得m = 4522492601441914729446821257037

然后感觉是解背包加密$c = (pubkey_1×e_1 \mod m) + \dots + (pubkey_{64}×e_{64}\mod m) $

构造格

正确结果卡在中间,一开始没发现,以为是自己思路错了。草!!!!!!

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
from Crypto.Util.number import *
import gmpy2

phigh =
N =
enc =


R.<x> = PolynomialRing(Zmod(n))

f = phigh + x
root = f.small_roots(X = 2^435,beta = 0.4)
if root:
p = phigh + int(root[0])
# print(p)
q = N // p

mod =
pubkey =
c =

n = len(pubkey)

Ge = Matrix(ZZ,n+2,n+2)
for i in range(n):
Ge[i,i] = 1
Ge[i,-1] = pubkey[i]

Ge[-2,-2] = 1
Ge[-2,-1] = c
Ge[-1,-1] = mod


for i in Ge.LLL():
if i[-1] == 0:
tmp = i[:-2]
ans = ''
for j in tmp:
if abs(j) == 0:
ans += '0'
if abs(j) == 1:
ans += '1'
e = int(ans,2)
if isPrime(e) and e.bit_length() == 64:
print(e)
d = gmpy2.invert(e,(p-1)*(q-1))
m = pow(enc,d,N)
print(long_to_bytes(int(m)))

下次一定看清楚www

另外一种解法是利用上超递增序列list

$\because c = (pubkey_1×e_1 \mod m) + \dots + (pubkey_{64}×e_{64}\mod m)$

把$pubkey \equiv w \times list$代入

$\therefore c = (w \times list_1 \times e_1 \mod m) + \dots + (w \times list_{64} \times e_{64} \mod m)$

$\therefore c \equiv w(list_1 \times e_1 + \dots +list_{64}\times e_{64} ) \mod m$

$c \times w^{-1} \equiv list_1 \times e_1 + \dots +list_{64}\times e_{64} \mod m$

list是个超递增序列

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from Crypto.Util.number import *

c = 31087054322877663244023458448558
mod = 4522492601441914729446821257037
w = 18143710780782459577

c = c * inverse(w,mod) % mod

list1 = [pow(3, i) for i in range(64)]

m = ''
for i in list1[::-1]:
if c >= i:
m += '1'
c -= i
else:
m += '0'

e = int(m[::-1],2)
print(e)
# e =15960663600754919507

XOR贯穿始终

先核心价值观解码得到压缩包的密钥:C0ngr4tulati0n5_y0u_fou^d_m3

拿到题目,以及私钥文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from gmpy2 import gcd
from Crypto.Util.number import getPrime
from secret import enflag

p = getPrime(512)
q = getPrime(512)
n = q * p
phi = (p - 1) * (q - 1)
e = getPrime(17)
assert gcd(e, phi) == 1
# 以上信息生成了私钥文件,但文件被损坏了你能提取有用信息吗

c = pow(enflag, e, n)
print('c = ' + str(c))

'''
c = 91817924748361493215143897386603397612753451291462468066632608541316135642691873237492166541761504834463859351830616117238028454453831120079998631107520871612398404926417683282285787231775479511469825932022611941912754602165499500350038397852503264709127650106856760043956604644700201911063515109074933378818
'''
1
2
3
4
5
6
7
8
9
10
11
12
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALmtMy+2uH1ZtbIL
SuiAukFthyQRH5mp7UmLyzZQkdg9zEP9/5tgffikQ7ytx5kHySHnazgAO1sOzmYE
N4Axlev6uafiP8B1Eij97v5VkYJ1I9e3mtBNheTbXKoT8op+ASQ1fQaF4A8UzLuW
eZeZI8JTH/SH+bolAK3kiZXDFdkTAgMBAAECgYEAl067LaC7Cvs2A5cMPhfYsESv
IgcKN1CwW4Sd3u8dSphhgu7TgyzIuvwxbuo2g1BC6WwKhaI6vGN+csfw6nh98GEn
/p3D0huNroAYvf/DRRB9UnHdttX7wB+Mv3P0RBDWHgBiCDVvHFuFUV78cIs0tnbn
jxjU07aPV2XRC3AfA2ECQQDqWUNPVg3i6vTyHCL7EGkbeUheYpAAfcKCQrxjc5+5
X6A+XtgHAA1JHwykPlCpHUOmlA85DJF1ejuoImzlgRLJAkEAytTCnQF+MN2r1gaA
UETZyj5qMYT7Th8zKEVVVJjDawLnuX4usJ2FyRnjCkk86U75QSJhw5mMc0QnG25u
Gz3++w==
-----END PRIVATE KEY-----

私钥文件base64解密再转16进制

根据(PKCS1) RSA 公私钥 pem 文件解析 - 知乎 (zhihu.com)

提取到n,p,q。然后解密。中间那段绿色的不太明白代表什么意思,求师傅教教。后面了解到那个是d

解出来的结果和压缩包密钥异或一下才是真的flag。当时想到异或,但是把字符拿来异或了,卡了几分钟才做出来的导致痛失三血www

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from Crypto.Util.number import *
import gmpy2

n = 0xb9ad332fb6b87d59b5b20b4ae880ba416d8724111f99a9ed498bcb365091d83dcc43fdff9b607df8a443bcadc79907c921e76b38003b5b0ece660437803195ebfab9a7e23fc0751228fdeefe5591827523d7b79ad04d85e4db5caa13f28a7e0124357d0685e00f14ccbb9679979923c2531ff487f9ba2500ade48995c315d913
e = 0x10001
p = 0xcad4c29d017e30ddabd606805044d9ca3e6a3184fb4e1f332845555498c36b02e7b97e2eb09d85c919e30a493ce94ef9412261c3998c7344271b6e6e1b3dfefb
q = 0xea59434f560de2eaf4f21c22fb10691b79485e6290007dc28242bc63739fb95fa03e5ed807000d491f0ca43e50a91d43a6940f390c91757a3ba8226ce58112c9

c = 91817924748361493215143897386603397612753451291462468066632608541316135642691873237492166541761504834463859351830616117238028454453831120079998631107520871612398404926417683282285787231775479511469825932022611941912754602165499500350038397852503264709127650106856760043956604644700201911063515109074933378818

d = gmpy2.invert(e,(p-1)*(q-1))
m = pow(c,d,n)
print(long_to_bytes(int(m)))

a = b'C0ngr4tulati0n5_y0u_fou^d_m3'
flag = long_to_bytes(bytes_to_long(a) ^ int(m))
print(flag)

日落越来越早了,不到6.30天就几乎全黑了,感叹时间过的好快啊,转眼就大二了。

近来几天状态不太好,而且这两天天公不作美,很多计划都被打乱了,怪难受的,明天就得开始上课了,算是给暑期的学习过程画一个句号了。

写在最后

星盟安全团队纳新!

欢迎师傅们加群(346014666)学习、讨论!

-------------已经到底啦!-------------