week1

xor

题目

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import xor
from Crypto.Util.number import bytes_to_long

key = b'New_Star_CTF'
flag='flag{*******************}'

m1 = bytes_to_long(bytes(flag[:13], encoding='utf-8'))
m2 = flag[13:]

c1 = m1 ^ bytes_to_long(key)
c2 = xor(key, m2)
print('c1=',c1)
print('c2=',c2)

考点:异或,pwn库里的xor()函数

只要了解一下异或运算就可以解决,运算法则为:0 ⊕ 0 = 0,1 ⊕ 0 = 1,0 ⊕ 1 = 1,1 ⊕ 1 = 0(同为 0,异为 1)

一个特点是p、q异或的结果与其中一个再进行一次异或就可以得到另一个

pwntools 中的 xor(),它可以将不同类型和长度的数据进行异或

题目将明文分成两部分m1和m2,分别和key进行了异或运算,只要再把c1、c2和key异或一次,结果合起来,就是flag,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import xor
#The Python pwntools library has a convenient xor() function that can XOR together data of different types and lengths
from Crypto.Util.number import bytes_to_long,long_to_bytes

key = b'New_Star_CTF'

c1= 8091799978721254458294926060841
c2= b';:\x1c1<\x03>*\x10\x11u;'

m1 = c1 ^ bytes_to_long(key) # 自带的异或符号^只能用于整数类型操作
m2 = xor(key, c2)
m1 = long_to_bytes(m1)

print(m1+m2)
# flag{0ops!_you_know_XOR!}

Base

题目

4C4A575851324332474E324547554B494A5A4446513653434E564D444154545A4B354D45454D434E4959345536544B474D5134513D3D3D3D

考点:base系列编码

之前用的在线网站进行解码,但说实话,挺复杂,因为这个进行了好几个base系列的编码,看了官方wp后知道了CyberChef,用这个就可以一把梭哈

看了官方wp后才想起来我对base编码其实了解到不太熟,看了之后才了解了编码原理

一眼秒了

题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from Crypto.Util.number import *
from gmpy2 import *
from serct import flag
p = getPrime(512)
q = getPrime(512)
n = p*q
m = bytes_to_long(flag)
e = 65537
c = powmod(m, e, n)
print(n)
print(c)

# 52147017298260357180329101776864095134806848020663558064141648200366079331962132411967917697877875277103045755972006084078559453777291403087575061382674872573336431876500128247133861957730154418461680506403680189755399752882558438393107151815794295272358955300914752523377417192504702798450787430403387076153
# 48757373363225981717076130816529380470563968650367175499612268073517990636849798038662283440350470812898424299904371831068541394247432423751879457624606194334196130444478878533092854342610288522236409554286954091860638388043037601371807379269588474814290382239910358697485110591812060488786552463208464541069

考点:rsa,分解n

p和q都不算太大,直接用在线网站分解一下n,得到p、q后按RSA解密就行(求phi,然后求d)

但是补充一下yafu的用法,打开cmd,输入yafu-x64.exe,之后输入factor(需要分解的素数),如果数比较大,就要放到txt里,记得回车,然后再从cmd里输入yafu-x64.exe “factor(@)” -batchfile D:\data.txt,每次用完会自动删除这个txt文件

有了p和q之后就没有难度了,rsa解密就行,代码如下

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

n= 52147017298260357180329101776864095134806848020663558064141648200366079331962132411967917697877875277103045755972006084078559453777291403087575061382674872573336431876500128247133861957730154418461680506403680189755399752882558438393107151815794295272358955300914752523377417192504702798450787430403387076153
c=48757373363225981717076130816529380470563968650367175499612268073517990636849798038662283440350470812898424299904371831068541394247432423751879457624606194334196130444478878533092854342610288522236409554286954091860638388043037601371807379269588474814290382239910358697485110591812060488786552463208464541069
p=7221289171488727827673517139597844534869368289455419695964957239047692699919030405800116133805855968123601433247022090070114331842771417566928809956044421
q=7221289171488727827673517139597844534869368289455419695964957239047692699919030405800116133805855968123601433247022090070114331842771417566928809956045093

phi = (p-1)*(q-1)
e = 65537
d = inverse(e,phi)
m = pow(c,d,n)
print(long_to_bytes(m))
# flag{9cd4b35a-affc-422a-9862-58e1cc3ff8d2}

Strange King

题目

某喜欢抽锐刻 5 的皇帝想每天进步一些,直到他娶了个模,回到原点,全部白给😅 这是他最后留下的讯息:ksjr{EcxvpdErSvcDgdgEzxqjql},flag 包裹的是可读的明文

考点:变异凯撒

是凯撒密码的变形,把密文前四个字符和flag对比就会发现他们的ascii码值分别差了5、7、9、11(其实题目也提醒了锐刻5和每天进步一点,说明一开始偏移5,逐渐加2),然后取模,是为了防止超出范围(一开始我模没取对,想着是取ascii表的模,然后写不对,其实应该大写字母和小写字母分别取26,使其在各自的范围里)代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
txt = 'ksjr{EcxvpdErSvcDgdgEzxqjql}'
plain = ''
i = 5
for j in txt:
if j.islower():
plain = plain + chr(97 + (ord(j) - i - 97)%26)
elif j.isupper():
plain = plain + chr(65 + (ord(j) - i - 65)%26)
else:
plain = plain + j
i += 2
print(plain)
# flag{PleaseDoNotStopLearing}

week2

这是几次方? 疑惑

题目

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


flag = b'flag{*****}'
p = getPrime(512)
q = getPrime(512)
n = p*q
e = 65537

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

hint = p^e + 10086

print("c =", c)
print("[n, e] =", [n, e])
print("hint =", hint)
'''
c = 36513006092776816463005807690891878445084897511693065366878424579653926750135820835708001956534802873403195178517427725389634058598049226914694122804888321427912070308432512908833529417531492965615348806470164107231108504308584954154513331333004804817854315094324454847081460199485733298227480134551273155762
[n, e] = [124455847177872829086850368685666872009698526875425204001499218854100257535484730033567552600005229013042351828575037023159889870271253559515001300645102569745482135768148755333759957370341658601268473878114399708702841974488367343570414404038862892863275173656133199924484523427712604601606674219929087411261, 65537]
hint = 12578819356802034679792891975754306960297043516674290901441811200649679289740456805726985390445432800908006773857670255951581884098015799603908242531673390
'''

考点:异或符号的运算优先级

这道题需要清楚异或操作的优先级是低于乘除加减的,所有hint是p和e+10086的异或结果,这样就可以得到p,再用n整除得到q,然后就是RSA解密了,代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
from Crypto.Utill.number import *
import gmpy2
c = 36513006092776816463005807690891878445084897511693065366878424579653926750135820835708001956534802873403195178517427725389634058598049226914694122804888321427912070308432512908833529417531492965615348806470164107231108504308584954154513331333004804817854315094324454847081460199485733298227480134551273155762
n = 124455847177872829086850368685666872009698526875425204001499218854100257535484730033567552600005229013042351828575037023159889870271253559515001300645102569745482135768148755333759957370341658601268473878114399708702841974488367343570414404038862892863275173656133199924484523427712604601606674219929087411261
hint = 12578819356802034679792891975754306960297043516674290901441811200649679289740456805726985390445432800908006773857670255951581884098015799603908242531673390
e = 65537
p = hint ^ 10086 + e
q= n//p
phi = (q-1)*(p-1)
d = gmpy2.invert(e,phi)
m = pow(c,d,n)
print(long_to_bytes(m))
# flag{yihuo_yuan_lai_xian_ji_suan_liang_bian_de2333}

Since you konw something

题目

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import xor
# The Python pwntools library has a convenient xor() function that can XOR together data of different types and lengths
from Crypto.Util.number import bytes_to_long

key = ?? # extremely short
FLAG = 'flag{????????}'
c = bytes_to_long(xor(FLAG,key))

print("c={}".format(c))

'''
c=218950457292639210021937048771508243745941011391746420225459726647571
'''

考点:异或

这道题要再了解一下pwntools库里的xor函数,举个例子,我们进行xor(data, key),那么data中的第一个字节(对应的ascii值,后面同理)会和key里的第一个字节进行异或,依此类推,当data的字节数超过key的长度时,key会从头开始重复使用,直到data中的数据全部处理完毕

从题目可以知道key很短,恰巧我们知道FLAG的前几个字节(falg),所以异或一下就可以知道key是’ns’,之后c和key再异或一次就可以知道flag了(对称性),代码如下

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import xor
# The Python pwntools library has a convenient xor() function that can XOR together data of different types and lengths
from Crypto.Util.number import bytes_to_long,long_to_bytes

c=218950457292639210021937048771508243745941011391746420225459726647571
FLAG = b'flag{????????}'
print(long_to_bytes(c))
c = long_to_bytes(c)
print(xor(c,FLAG))
key = 'ns'
print(xor(c,key))
# flag{Y0u_kn0w_th3_X0r_b3tt3r}

茶里茶气

题目

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
from Crypto.Util.number import *

flag = "flag{*****}"
assert len( flag ) == 25

a = ""
for i in flag:
a += hex(ord(i))[2:]
l = int(a,16).bit_length()
print("l =" , l )

v0 = int(a,16)>>(l//2)
v1 = int(a,16)-(v0<<(l//2))
p = getPrime(l//2+10)

v2 = 0
derta = 462861781278454071588539315363
v3 = 489552116384728571199414424951
v4 = 469728069391226765421086670817
v5 = 564098252372959621721124077407
v6 = 335640247620454039831329381071
assert v1 < p and v0 < p and derta < p and v3 < p and v4 < p and v5 < p and v6 < p

for i in range(32):
v1 += (v0+v2) ^ ( 8*v0 + v3 ) ^ ( (v0>>7) + v4 ) ; v1 %= p
v0 += (v1+v2) ^ ( 8*v1 + v5 ) ^ ( (v1>>7) + v6 ) ; v0 %= p
v2 += derta ; v2 %= p

print( "p =" , p )
print( "v0 =" , v0 )
print( "v1 =" , v1 )

"""
l = 199
p = 446302455051275584229157195942211
v0 = 190997821330413928409069858571234
v1 = 137340509740671759939138452113480
"""

考点TEA(Tiny Encryption Algorithm)加密算法

不知道是TEA加密算法也没有关系,因为逆推其实也很简单,如下,自己写一下就很清晰

把最终的V2求出来后把顺序反过来退回去就行,就改成减号,把起始的V0和V1求出来后,就可以求出来a,把a转十六进制,两位一个转字符就可以求出flag,代码如下
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
v2 = 0
delta = 462861781278454071588539315363
v3 = 489552116384728571199414424951
v4 = 469728069391226765421086670817
v5 = 564098252372959621721124077407
v6 = 335640247620454039831329381071
l = 199
p = 446302455051275584229157195942211
v0 = 190997821330413928409069858571234
v1 = 137340509740671759939138452113480

for i in range( 32 ):
v2 += delta ; v2 %= p

for i in range(32):
v2 -= delta ; v2 %= p
v0 -= (v1+v2) ^ ( 8*v1 + v5 ) ^ ( (v1>>7) + v6 ) ; v0 %= p
v1 -= (v0+v2) ^ ( 8*v0 + v3 ) ^ ( (v0>>7) + v4 ) ; v1 %= p

a = hex((v0<<((l//2))) + v1)[2:]
print(a)
flag = ""
for i in range(0,len(a),2):
flag += chr(int(a[i:i+2],16))
print(flag)
# flag{f14gg9_te2_1i_7ea_7}

Just one and more than two

题目

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

flag = b'flag{?????}'
m1 = bytes_to_long(flag[:len(flag)//2])
m2 = bytes_to_long(flag[len(flag)//2:])
e = 65537
p, q, r= (getPrime(512) for _ in range(3))
N=p*q*r
c1 = pow(m1, e, p)
c2 = pow(m2, e, N)

print(f'p={p}\nq={q}\nr={r}\nc1={c1}\nc2={c2}')

'''
p=11867061353246233251584761575576071264056514705066766922825303434965272105673287382545586304271607224747442087588050625742380204503331976589883604074235133
q=11873178589368883675890917699819207736397010385081364225879431054112944129299850257938753554259645705535337054802699202512825107090843889676443867510412393
r=12897499208983423232868869100223973634537663127759671894357936868650239679942565058234189535395732577137079689110541612150759420022709417457551292448732371
c1=8705739659634329013157482960027934795454950884941966136315983526808527784650002967954059125075894300750418062742140200130188545338806355927273170470295451
c2=1004454248332792626131205259568148422136121342421144637194771487691844257449866491626726822289975189661332527496380578001514976911349965774838476334431923162269315555654716024616432373992288127966016197043606785386738961886826177232627159894038652924267065612922880048963182518107479487219900530746076603182269336917003411508524223257315597473638623530380492690984112891827897831400759409394315311767776323920195436460284244090970865474530727893555217020636612445
'''

考点:欧拉函数

一道RSA题,flag被分成两部分分别进行加密,c1是m1通过e和p加密得到,c2是m2通过e和N加密得到,要求m1和m2就得求对应的d1和d2,只要了解一下欧拉函数就可以了,我们已知p、q、r,且他们都是素数,那么

$ phi(p) = p - 1 $

$ phi(N) = (p -1)(q - 1)(r - 1) $

再分别求一下e关于他们两个的逆元就可以得到d1和d2,后面就是RSA解密了,代码如下

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

p=11867061353246233251584761575576071264056514705066766922825303434965272105673287382545586304271607224747442087588050625742380204503331976589883604074235133
q=11873178589368883675890917699819207736397010385081364225879431054112944129299850257938753554259645705535337054802699202512825107090843889676443867510412393
r=12897499208983423232868869100223973634537663127759671894357936868650239679942565058234189535395732577137079689110541612150759420022709417457551292448732371
c1=8705739659634329013157482960027934795454950884941966136315983526808527784650002967954059125075894300750418062742140200130188545338806355927273170470295451
c2=1004454248332792626131205259568148422136121342421144637194771487691844257449866491626726822289975189661332527496380578001514976911349965774838476334431923162269315555654716024616432373992288127966016197043606785386738961886826177232627159894038652924267065612922880048963182518107479487219900530746076603182269336917003411508524223257315597473638623530380492690984112891827897831400759409394315311767776323920195436460284244090970865474530727893555217020636612445
e = 65537
N = p*q*r
d1 = gmpy2.invert(e,p-1)
d2 = gmpy2.invert(e,(p-1)*(q-1)*(r-1))
m1 = pow(c1, d1, p)
m2 = pow(c2, d2, N)

print(long_to_bytes(m1)+long_to_bytes(m2))
# flag{Y0u_re4lly_kn0w_Euler_4nd_N3xt_Eu1er_is_Y0u!}

week3

没e这能玩

题目

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
from Crypto.Util.number import *
import random
import sympy
import gmpy2

m = bytes_to_long(b'flag{*****}')

p = getPrime(512)
q = getPrime(512)
r = getPrime(512)
h1 = 1*p + 1*q + 1*r
h2 = 2*p + 3*q + 3*r
h3 = 9*p + 9*q + 6*r
print( "hint_of_pqr=" , h1 , h2 , h3 )

e = getPrime(64)
a_big_prime = getPrime( 512 )
hint = pow(a_big_prime,e,2**512)
print( "big_prime is: " , a_big_prime )
print( "hint is: " , hint )

n = p*q*r
c = pow( m , e , n )
print( "c=" , c )

"""
hint_of_pqr= 31142735238530997044538008977536563192992446755282526163704097825748037157617958329370018716097695151853567914689441893020256819531959835133410539308633497 83244528500940968089139246591338465098116598400576450028712055615289379610182828415628469144649133540240957232351546273836449824638227295064400834828714760 248913032538718194100308575844236838621741774207751338576000867909773931464854644505429950530402814602955352740032796855486666128271187734043696395254816172
big_prime is: 10340528340717085562564282159472606844701680435801531596688324657589080212070472855731542530063656135954245247693866580524183340161718349111409099098622379
hint is: 1117823254118009923270987314972815939020676918543320218102525712576467969401820234222225849595448982263008967497960941694470967789623418862506421153355571
c= 999238457633695875390868312148578206874085180328729864031502769160746939370358067645058746087858200698064715590068454781908941878234704745231616472500544299489072907525181954130042610756999951629214871917553371147513692253221476798612645630242018686268404850587754814930425513225710788525640827779311258012457828152843350882248473911459816471101547263923065978812349463656784597759143314955463199850172786928389414560476327593199154879575312027425152329247656310
"""

考点:离散对数

是一道RSA题目,n是p、q、r的乘积,而题目告诉我们pqr之间的线性关系(三个未知数,三个方程,可以解出p、q、r)

那接下来就是要求d,但是题目没有给我们e,给的是a_big_prime^e(mod 2^512)

参考了一些博客,知道是离散对数问题,但是我不太了解离散对数(之后会多看看的),然后直接在一个博客里就找到了一个库里的一个函数,可以直接求出e

python的 sympy库discrete_log函数是专门求指数的,discrete_log(x,y,z),x为模数,y为余数,z为底数

用这个函数求出来e后就是RSA解密的经典过程了

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

h1 = 31142735238530997044538008977536563192992446755282526163704097825748037157617958329370018716097695151853567914689441893020256819531959835133410539308633497
h2 = 83244528500940968089139246591338465098116598400576450028712055615289379610182828415628469144649133540240957232351546273836449824638227295064400834828714760
h3 = 248913032538718194100308575844236838621741774207751338576000867909773931464854644505429950530402814602955352740032796855486666128271187734043696395254816172
big_prime= 10340528340717085562564282159472606844701680435801531596688324657589080212070472855731542530063656135954245247693866580524183340161718349111409099098622379
hint= 1117823254118009923270987314972815939020676918543320218102525712576467969401820234222225849595448982263008967497960941694470967789623418862506421153355571
c= 999238457633695875390868312148578206874085180328729864031502769160746939370358067645058746087858200698064715590068454781908941878234704745231616472500544299489072907525181954130042610756999951629214871917553371147513692253221476798612645630242018686268404850587754814930425513225710788525640827779311258012457828152843350882248473911459816471101547263923065978812349463656784597759143314955463199850172786928389414560476327593199154879575312027425152329247656310

p = 3 * h1 - h2
r = (9 * h1 - h3)//3
q = h1 - p - r

n = p*q*r
phi = (p-1)*(q-1)*(r-1)
e = sympy.discrete_log(2**512,hint,big_prime)
d = gmpy2.invert(e,phi)
m = pow(c,d,n)
print(long_to_bytes(m))
# flag{th1s_2s_A_rea119_f34ggg}

故事新编

题目

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
from hashlib import md5
zen1 = '''

'''
key1 =
def enc1(plaintext, key):
def shift_char(c, k):
return chr(((ord(c) - ord('A') + (ord(k) - ord('A'))) % 26) + ord('A'))

plaintext = plaintext.upper()
key = key.upper()
ciphertext = []
key_index = 0

for char in plaintext:
if char.isalpha():
ciphertext.append(shift_char(char, key[key_index % len(key)]))
key_index += 1
else:
ciphertext.append(char)

return ''.join(ciphertext)
print('enc = \'\'\'' + enc1(zen1, key1)+'\'\'\'')
flag = b'flag{'+md5(zen1.encode()).hexdigest().encode()+b'}'
print(flag)
#----------------------------------------------
enc = '''
TYBNBBZNT WF TYUMMK NAIB HYFZ.
XFIFBKWG AM CXBMYK BVNF CNITBWBB.
GVEJMX QL VXBHRJ NITV VIFXZRP.
WPFXEYQ QG OWNUXZ MBTV QBEJMBKTNXL.
TYSN JL JXNMMF GZUO GMLNXL.
GCSLTX QL VXBHRJ NITV WYGAS.
SDUHT QL PXOSAWLF
KMTXTJWYANZ VWNHMA.
GCWWJTT VULMG NJYO'M AIYVQOY WHPNOA NH JFRSE UAM KOEMG.
NDNIHCZB IZOPLCDTTBNR JSNLM QNZBNR.
MFEGLT LPHOEL BRNYS IILM LQZRFNMR.
CGFXAG RPJMBKBNEG GVDYOVMW.
'''

考点:维吉尼亚爆破

题目是定义了一个enc函数,它接收明文和密钥,然后将它们全部大写,然后明文里的每个字符依次移动密文对应字符的ASCII值(减去’A’后的值)看到这里,如果古典密码记得熟的话应该就能反应过来这是一个维吉尼亚密码(我吗?我记不住,我问AI的,它告诉我的)

那知道是维吉尼亚加密了,找到密钥不就解出来了,嗯?没给我密钥?那就跟你爆了! 是的,没有密钥的情况下运用在线网站爆破一下就可以得到明文了,我就是用的链接网址的在线工具

之后MD5加密后的十六进制转字节,打印出来就是了

至于故事新编2,是自动密钥密码,与故事新编 1 相类似。是维吉尼亚的变异,在上面那个网站也能爆破,都可以求出flag

不用谢喵

题目

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
from Crypto.Cipher import AES
from Crypto.Util.number import *
import os

KEY = b"fake_key_fake_ke"
FLAG = "flag{fake_flag_fake_flag}"

def decrypt(c):
AES_ECB = AES.new(KEY, AES.MODE_ECB)
decrypted = AES_ECB.decrypt(long_to_bytes(c))

return decrypted.hex()

def encrypt():
iv = os.urandom(16)
AES_CBC = AES.new(KEY, AES.MODE_CBC, iv)
encrypted = AES_CBC.encrypt(FLAG.encode())
print('iv:',iv.hex())

return iv.hex() + encrypted.hex()

c=encrypt()
print('encrypt:',c)
print('decrypt:',decrypt(int(c,16)))

#encrypt: f2040fe3063a5b6c65f66e1d2bf47b4cddb206e4ddcf7524932d25e92d57d3468398730b59df851cbac6d65073f9e138
#什么是AES啊😭,求求你帮我解密吧,我什么都会做的!!!!!😭

'''
什么都会做?那就去学习一下AES的工作模式吧……
我这次就先给你解一下好了,不用谢喵
decrypt: f9899749fec184d81afecd35da430bc394686e847d72141b3a955a4f6e920e7d91cb599d92ba2a6ba51860bb5b32f23b
这对吗?哦不对不对,哦对的对的。
'''

考点:AES的不同分组模式

这道题定义了两个函数,一个CBC分组模式的AES加密函数;一个是ECB分组模式的AES解密函数。

CBC模式是对每个块都使用同一个key进行块加密,但块加密之前,先将明文块与前一个密文块进行异或计算,然后再对异或计算结果进行块加密。对于首个明文块,因为不存在前一个密文块,所以需要额外的一个字节数组来充当”前一个密文块”,这个字节数组被称为初始化向量,IV。解密时要把和key进行块解密操作后的块和前一个密文块(第一个密文块和iv)异或后才能得到明文块。

ECB是最简单的一个分组模式(应该是),对每一个块的加密都是使用同样的key,同样的明文块一定会被加密成同样的密文块。解密过程就是把每一个块和key进行块解密操作就可以了。

那么已知明文是被encrypt()函数加密的,是一个CBC模式,所以我们只要知道iv和key就可以解密了,iv其实很好知道,因为我们知道encrypt,它是iv和密文的十六进制,因为我们知道iv是16个字节,那么encrypt的前32个字符就是iv(每个字节对应两个十六进制字符数)

但是我们不知道key呀,怎么办呢,让我们看看喵帮我们干了什么,嗯,它用ECB模式解密了我们的明文,这不对吧?但是只要我们观察一下,就会发现用ECB模式解密和CBC模式就差一步异或,这样我们就不用知道key了,只要异或就行了

官方wp很巧妙,把所有转成字节型再疑惑,后面查了一下发现十进制和十六进制long_to_bytes的结果是一样的,也是长见识了

1
2
3
4
5
6
7
8
9
10
from Crypto.Util.number import long_to_bytes as l2b , bytes_to_long as b2l

c = 0xf2040fe3063a5b6c65f66e1d2bf47b4cddb206e4ddcf7524932d25e92d57d3468398730b59df851cbac6d65073f9e138
d = 0xf9899749fec184d81afecd35da430bc394686e847d72141b3a955a4f6e920e7d91cb599d92ba2a6ba51860bb5b32f23b

part1=l2b( b2l(l2b(c)[0:16]) ^ b2l(l2b(d)[16:32]))
part2=l2b( b2l(l2b(c)[16:32]) ^ b2l(l2b(d)[32:48]))

print(part1+part2)
# flag{HOw_c4REfu1Ly_yOu_O65ERve!}

两个黄鹂鸣翠柳

题目

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
import random
from Crypto.Util.number import *
while 1:
delta = getPrime(1024)
p = getPrime(512)
q = getPrime(512)
N = p * q
if delta<N:
break
flag = b'flag{xxxxxxxxxxxxx}'
e = getPrime(10)
m = bytes_to_long(flag)
t1 = random.randint(0,255)
t2 = random.randint(0,255)
assert (t1 != t2)
m1 = m + t1 * delta
m2 = m + t2 * delta
c1 = pow(m1, e, N)
c2 = pow(m2, e, N)
print("e = ", e)
print("c1 = ", c1)
print("c2 = ", c2)
print("N = ", N)
print("delta = ", delta)

'''
e = 683
c1 = 56853945083742777151835031127085909289912817644412648006229138906930565421892378967519263900695394136817683446007470305162870097813202468748688129362479266925957012681301414819970269973650684451738803658589294058625694805490606063729675884839653992735321514315629212636876171499519363523608999887425726764249
c2 = 89525609620932397106566856236086132400485172135214174799072934348236088959961943962724231813882442035846313820099772671290019212756417758068415966039157070499263567121772463544541730483766001321510822285099385342314147217002453558227066228845624286511538065701168003387942898754314450759220468473833228762416
N = 147146340154745985154200417058618375509429599847435251644724920667387711123859666574574555771448231548273485628643446732044692508506300681049465249342648733075298434604272203349484744618070620447136333438842371753842299030085718481197229655334445095544366125552367692411589662686093931538970765914004878579967
delta = 93400488537789082145777768934799642730988732687780405889371778084733689728835104694467426911976028935748405411688535952655119354582508139665395171450775071909328192306339433470956958987928467659858731316115874663323404280639312245482055741486933758398266423824044429533774224701791874211606968507262504865993
'''

考点:关联信息攻击,多项式gcd

总的来说就是找到两个多项式的公因子,而这个值大概率就是m1,之后就可以求解出明文。但具体原理有点复杂,用到了Half-GCD 算法,之后细扣

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
from Crypto.Util.number import *

def HGCD(a, b):
if 2 * b.degree() <= a.degree() or a.degree() == 1:
return 1, 0, 0, 1
m = a.degree() // 2
a_top, a_bot = a.quo_rem(x ^ m)
b_top, b_bot = b.quo_rem(x ^ m)
R00, R01, R10, R11 = HGCD(a_top, b_top)
c = R00 * a + R01 * b
d = R10 * a + R11 * b
q, e = c.quo_rem(d)
d_top, d_bot = d.quo_rem(x ^ (m // 2))
e_top, e_bot = e.quo_rem(x ^ (m // 2))
S00, S01, S10, S11 = HGCD(d_top, e_top)
RET00 = S01 * R00 + (S00 - q * S01) * R10
RET01 = S01 * R01 + (S00 - q * S01) * R11
RET10 = S11 * R00 + (S10 - q * S11) * R10
RET11 = S11 * R01 + (S10 - q * S11) * R11
return RET00, RET01, RET10, RET11

def related_message_attack(a, b):
q, r = a.quo_rem(b)
if r == 0:
return b
R00, R01, R10, R11 = HGCD(a, b)
c = R00 * a + R01 * b
d = R10 * a + R11 * b
if d == 0:
return c.monic()
q, r = c.quo_rem(d)
if r == 0:
return d
return related_message_attack(d, r)

e = 683
c1 = 56853945083742777151835031127085909289912817644412648006229138906930565421892378967519263900695394136817683446007470305162870097813202468748688129362479266925957012681301414819970269973650684451738803658589294058625694805490606063729675884839653992735321514315629212636876171499519363523608999887425726764249
c2 = 89525609620932397106566856236086132400485172135214174799072934348236088959961943962724231813882442035846313820099772671290019212756417758068415966039157070499263567121772463544541730483766001321510822285099385342314147217002453558227066228845624286511538065701168003387942898754314450759220468473833228762416
N = 147146340154745985154200417058618375509429599847435251644724920667387711123859666574574555771448231548273485628643446732044692508506300681049465249342648733075298434604272203349484744618070620447136333438842371753842299030085718481197229655334445095544366125552367692411589662686093931538970765914004878579967
delta = 93400488537789082145777768934799642730988732687780405889371778084733689728835104694467426911976028935748405411688535952655119354582508139665395171450775071909328192306339433470956958987928467659858731316115874663323404280639312245482055741486933758398266423824044429533774224701791874211606968507262504865993

is_flag = False

for delt in range(-255, 255, 8):

PR.<x> = PolynomialRing(Zmod(N))
f = x ^ e - c1
g1 = ((x + (delt + 0) * delta) ^ e - c2) * ((x + (delt + 1) * delta) ^ e - c2)
g2 = ((x + (delt + 2) * delta) ^ e - c2) * ((x + (delt + 3) * delta) ^ e - c2)
g3 = ((x + (delt + 4) * delta) ^ e - c2) * ((x + (delt + 5) * delta) ^ e - c2)
g4 = ((x + (delt + 6) * delta) ^ e - c2) * ((x + (delt + 7) * delta) ^ e - c2)
if delt == -7:
g4 = ((x + (delt + 6) * delta) ^ e - c2)
g = g1 * g2 * g3 * g4
res = related_message_attack(f, g)
m1 = int(-res.monic().coefficients()[0])
for t1 in range(256):
m = (m1 % N - t1 * delta) % N
if m > 0:
flag = long_to_bytes(m)
if flag[:4] ==b'flag':
print(flag)
is_flag = True
break

if is_flag:
break
# flag{V_me_the_flag}

week4

圣石匕首

题目

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
import gmpy2
beta=0.37
delta=0.01
n=round((1-2*beta-2*delta)/((1-beta)^2-2*delta-beta),6)
e= 3668637434348843171145584606519031375027610199908169273169275927238735031431533260375377791001464799116453803408104076615710166171199990283470548282669948353598733020244755959461974603778630346457439345913209321194112256348302765254052193562603687450740346132207444615610078198488883539133291840346099727880587092122957231085658576850601488737629051252914095889313671875244094452330062619943781809984690384476868543570724769198985172300665613239047649089399919032152539462701309393130614829962670866062380816370571057536421400102100259975636785825540933280194583888638501981649650640939392658268133881679239293596283
N= 9748523098652101859947730585916490335896800943242955095820326993765071194474558998322598145898741779502734772138283011560029368500998354183150180904846368209977332058847768859238711047784703104535311583123388923571789764758869419482184613566672922481672444028753365755071127320541645016370072493604532087980626825687519083734367691341907014061379844209864141989961751681235215504772582878202048494707090104738899927036896915997556102574747166491969027546256022019959716418675672979328622656831990050058120299353807110233202113906317969377201045402271911946244076903611612303290556012512559696538977841061277173754331
c= 5374936627659221745209010619827617207565185520404653329184605916859755641352457088986635357806048863755173540232471505333583684733535121482637476692432365062808450583470788320547816186936317927449796090525477205337038591439577855884910604383190932340306435201976465543731935147881754136301375206828970248293731391543905441514528959500307972606931927112031018356411970001312995489429650903529877904694901310020882390008248466887950986326522740278880600110217817950511478637493101027659292006016454642135508207492151610829525082829566392116546434101694921106423469015683277992978077101831969525458693031031468092418427
n=int(n+1)
#print(n)
m=int(n*(1-beta))
X=int(pow(N,delta))
Y=int(pow(N,delta+beta))
Z.<x,y>=ZZ[]
L=Matrix(ZZ,n,n)
f=e*x-y
for i in range(n):
g=list(N^max(0,m-i)*x^(n-1-i)*f^i)
for j in range(len(g)):
L[i,j]=g[j][0]*X^(n-1-j)*Y^j
L=L.LLL()[0]
coeff=[]
for i in range(n):
coeff.append((L[i]//(X^(n-1-i)*Y^i),'x'+'**'+str(n-1-i)+'*y'+'**'+str(i)))
s=''
for i in range(len(coeff)):
s+=str(coeff[i][0])+'*'+coeff[i][1]+'+'
f=eval(s[:-1])
factored_f = f.factor()
first_polynomial = factored_f[0][0]
first_coefficient = first_polynomial.coefficients()[0]
k = first_coefficient + 1
dp = first_polynomial.coefficients()[1]
p=(e*dp-1)//k+1
q=N//p
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
m=pow(c,d,N)
print(bytes.fromhex(hex(m)[2:]))

就是一个sage文件,在sagemath里面运行就行了,就是运行比较久(我就复制到Jupyter上运行一下就行了)

flag{small_dp_is_not_secure_adhfaiuhaph}

欧拉欧拉!!

题目

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
from Crypto.Util.number import *

flag = b'flag{*********}'
m = bytes_to_long(flag)


def get_prime(bits):
while True:
p = getPrime(bits)
x = (1 << bits) - 1 ^ p
for i in range(-10, 11):
if isPrime(x + i):
return p, x + i, i


p, q, i = get_prime(512)
n = p * q
e = 65537
c = pow(m, e, n)

print("c =", c)
print("n =", n)
print("i =", i)
'''
c = 14859652090105683079145454585893160422247900801288656111826569181159038438427898859238993694117308678150258749913747829849091269373672489350727536945889312021893859587868138786640133976196803958879602927438349289325983895357127086714561807181967380062187404628829595784290171905916316214021661729616120643997
n = 18104347461003907895610914021247683508445228187648940019610703551961828343286923443588324205257353157349226965840638901792059481287140055747874675375786201782262247550663098932351593199099796736521757473187142907551498526346132033381442243277945568526912391580431142769526917165011590824127172120180838162091
i = -3
'''

考点:二进制加法,间接求欧拉函数

我们有以下式子

$ x = (1 << bits) - 1 \text{^} p $

那么就要了解一下二进制加法

1
2
3
a = 0b1001
b = a ^ 0b1111 = 0b0110
a + b = 1111

所有我们有$ x + p= (1 << bits) - 1 $

然后1<<512是$ 2^{512} $

所以$ x + p= 2^{512} - 1 $

所以$ p+q = p+x+i=2^{512}-1+i $

$ phi(n)=(p-1)(q-1)=pq-(p+q)+1=n-2^{512}+2-i $

后面就没有难度了,求出d正常求解就行

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

e = 65537
c = 14859652090105683079145454585893160422247900801288656111826569181159038438427898859238993694117308678150258749913747829849091269373672489350727536945889312021893859587868138786640133976196803958879602927438349289325983895357127086714561807181967380062187404628829595784290171905916316214021661729616120643997
n = 18104347461003907895610914021247683508445228187648940019610703551961828343286923443588324205257353157349226965840638901792059481287140055747874675375786201782262247550663098932351593199099796736521757473187142907551498526346132033381442243277945568526912391580431142769526917165011590824127172120180838162091
i = -3
phi = n - 2**512 + 2 - i
d = gmpy2.invert(e,phi)
m = pow(c,d,n)
print(long_to_bytes(m))
# flag{y0u_really_kn0w_the_phi}

俱以我之名

题目

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
from Crypto.Util.number import *
from gmpy2 import *
import random

def pad(msg, nbits):
pad_length = nbits - len(msg) * 8 - 8
assert pad_length >= 0
pad = random.getrandbits(pad_length).to_bytes((pad_length + 7) // 8, "big")
padded_msg = pad[:len(pad)//2] + b"\x00" + msg + pad[len(pad)//2:]

return padded_msg

def All_in_my_name(p, q):
#开启三技能<俱以我之名>后,维娜立即在周围八格可部署地面召唤“黄金盟誓(Golden_Oath)”;对RSA造成真实伤害。
Golden_Oath = (p-114)*(p-514)*(p+114)*(p+514)*(q-1919)*(q-810)*(q+1919)*(q+810)
x = bytes_to_long(pad(gift, random.randint(bytes_to_long(gift).bit_length(), 512)))
y = inverse(x, Golden_Oath)
return y

flag = b'flag{?????}'
gift = b'?????'
assert gift[:3] == b'end'

p = getPrime(512)
q = getPrime(512)
n = p*q
e = 65537
c = pow(bytes_to_long(flag), e,n)

print(f'n = {n}')
print(f'c = {c}')
print(f'All_in_my_name = {All_in_my_name(p, q)}')

'''
n = 141425071303405369267688583480971314815032581405819618511016190023245950842423565456025578726768996255928405749476366742320062773129810617755239412667111588691998380868379955660483185372558973059599254495581547016729479937763213364591413126146102483671385285672028642742654014426993054793378204517214486744679
c = 104575090683421063990494118954150936075812576661759942057772865980855195301985579098801745928083817885393369435101522784385677092942324668770336932487623099755265641877712097977929937088259347596039326198580193524065645826424819334664869152049049342316256537440449958526473368110002271943046726966122355888321
All_in_my_name = 217574365691698773158073738993996550494156171844278669077189161825491226238745356969468902038533922854535578070710976002278064001201980326028443347187697136216041235312192490502479015081704814370278142850634739391445817028960623318683701439854891399013393469200033510113406165952272497324443526299141544564964545937461632903355647411273477731555390580525472533399606416576667193890128726061970653201509841276177937053500663438053151477018183074107182442711656306515049473061426018576304621373895497210927151796054531814746265988174146635716820986208719319296233956243559891444122410388128465897348458862921336261068868678669349968117097659195490792407141240846445006330031546721426459458395606505793093432806236790060342049066284307119546018491926250151057087562126580602631912562103705681810139118673506298916800665912859765635644796622382867334481599049728329203920912683317422430015635091565073203588723830512169316991557606976424732212785533550238950903858852917097354055547392337744369560947616517041907362337902584102983344969307971888314998036201926257375424706901999793914432814775462333942995267009264203787170147555384279151485485660683109778282239772043598128219664150933315760352868905799949049880756509591090387073778041
'''

考点:维娜攻击

当e过大或过小的时候我们都可以考虑维纳攻击,当然还要满足$ d<\frac{1}{3}n^{\frac{1}{4}} $,且$ q<p<2q $

我们简单推一下,我们知道$ n=p*q $

$ phi(n)=(p-1)(q-1)=pq -(p+q)+1 $

因为p和q都是非常大的数,我们近似处理后n和phi(n)就差不多大。

我们知道$ ed=1 \mod phi(n) $

所以$ ed = k\times phi(n)+1 $,两边同时除以$ d*phi(n) $

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

同样的$ d*phi(n) $是很大的数,$ \frac{1}{d\times phi(n)} $可以忽略,phi(n)用n来代替,就可以得到$ \frac{e}{n}=\frac{k}{d} $

e和n都是已知的,我们就可以用连分数展开,得到k和d的可能值(原理还没搞懂,目前只能直接用)

这里的”俱以我之名”就是一个维纳攻击(是的,我玩舟),那么我们就要找能连分数展开的式子

$ xy=1\mod Golden_Oath $

所以$ \frac{y}{Golden_Oath}=\frac{k}{x} $

其中$ Golden_Oath = (p-114)(p-514)(p+114)(p+514)(q-1919)(q-810)(q+1919)(q+810)
$我们可以看成$ n^4 $

那我们对这个式子进行连分数展开,就能找到一系列近似值,再判断一下’end’在不在求出来的x里就可以找到x了,代码如下

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
from Crypto.Util.number import *
from gmpy2 import *
import random

n = 141425071303405369267688583480971314815032581405819618511016190023245950842423565456025578726768996255928405749476366742320062773129810617755239412667111588691998380868379955660483185372558973059599254495581547016729479937763213364591413126146102483671385285672028642742654014426993054793378204517214486744679
c = 104575090683421063990494118954150936075812576661759942057772865980855195301985579098801745928083817885393369435101522784385677092942324668770336932487623099755265641877712097977929937088259347596039326198580193524065645826424819334664869152049049342316256537440449958526473368110002271943046726966122355888321
y = 217574365691698773158073738993996550494156171844278669077189161825491226238745356969468902038533922854535578070710976002278064001201980326028443347187697136216041235312192490502479015081704814370278142850634739391445817028960623318683701439854891399013393469200033510113406165952272497324443526299141544564964545937461632903355647411273477731555390580525472533399606416576667193890128726061970653201509841276177937053500663438053151477018183074107182442711656306515049473061426018576304621373895497210927151796054531814746265988174146635716820986208719319296233956243559891444122410388128465897348458862921336261068868678669349968117097659195490792407141240846445006330031546721426459458395606505793093432806236790060342049066284307119546018491926250151057087562126580602631912562103705681810139118673506298916800665912859765635644796622382867334481599049728329203920912683317422430015635091565073203588723830512169316991557606976424732212785533550238950903858852917097354055547392337744369560947616517041907362337902584102983344969307971888314998036201926257375424706901999793914432814775462333942995267009264203787170147555384279151485485660683109778282239772043598128219664150933315760352868905799949049880756509591090387073778041
e = 65537

class ContinuedFraction():
def __init__(self, numerator, denumerator):
self.numberlist = []
self.fractionlist = []
self.GenerateNumberList(numerator, denumerator)
self.GenerateFractionList()

def GenerateNumberList(self, numerator, denumerator):
while numerator != 1:
quotient = numerator // denumerator
remainder = numerator % denumerator
self.numberlist.append(quotient)
numerator = denumerator
denumerator = remainder

def GenerateFractionList(self):
self.fractionlist.append([self.numberlist[0], 1])
for i in range(1, len(self.numberlist)):
numerator = self.numberlist[i]
denumerator = 1
for j in range(i):
temp = numerator
numerator = denumerator + numerator * self.numberlist[i - j - 1]
denumerator = temp
self.fractionlist.append([numerator, denumerator])

n = pow(n,4)
a = ContinuedFraction(y, n)
for k, x in a.fractionlist:
# 判断哪一个是我们所需的 x
if b'end' in long_to_bytes(x):
print(x)
print(k)
break

print(long_to_bytes(x))
Golden_Oath = (x*y-1)//k
print(Golden_Oath)

'''
103697213497220650500739251621743955651854455782387759691953279488676501281257640431561
56398712132783063027132828918468670442692437484816382768162819797891220782528221182512
b'5`\xf4\xf6t\xa3\x00end1n9_A_G2@nd_Ov3RTu2e\x1c\x13"H\x0f\xc9'
#400042032831098007958224589201074030167511216235146696966889080122265111949126155016295896501799032251334875101500882585261911204171467951139573150807043239564581043145433814155757093989016940205116328236031283789686099217459678429270939065783626769903068201144816933538226628329294355184200590029028565011348654002192085571172863125467318356642528249715812871925525776008917314884490518613080652875623759460663908309369135829140204137773254011408135516737187092812588388209697036416805176286184831779945910125467423823737934475944632379524991238593952097013985394648562259886597816452815669024660257170465154297959999722533255899489096196292778430386116108069053440749172609798098777046509743030019115282253351905670418760503352277616008654327326851761671410084489662135479597061419403235762755010286075975241013273964842915146756571330207605591193457296347769260777032489271278979332616929093357929916558230665466587125254822846466292980360420737307459205352964255972268278992730637939153686420457279334894980200862788513296786385507282999530973028293157179873999483225505784146175328159014143540959190522315340971608002638786511995717564457749873410017343184395040614025573440462522210939180555090227730875845671821586191943346000
'''

有了Golden_Oath,也知道n=p*q,解个方程就可以求出来p和q了

1
2
3
4
5
6
7
8
9
10
11
12
Golden_Oath = 400042032831098007958224589201074030167511216235146696966889080122265111949126155016295896501799032251334875101500882585261911204171467951139573150807043239564581043145433814155757093989016940205116328236031283789686099217459678429270939065783626769903068201144816933538226628329294355184200590029028565011348654002192085571172863125467318356642528249715812871925525776008917314884490518613080652875623759460663908309369135829140204137773254011408135516737187092812588388209697036416805176286184831779945910125467423823737934475944632379524991238593952097013985394648562259886597816452815669024660257170465154297959999722533255899489096196292778430386116108069053440749172609798098777046509743030019115282253351905670418760503352277616008654327326851761671410084489662135479597061419403235762755010286075975241013273964842915146756571330207605591193457296347769260777032489271278979332616929093357929916558230665466587125254822846466292980360420737307459205352964255972268278992730637939153686420457279334894980200862788513296786385507282999530973028293157179873999483225505784146175328159014143540959190522315340971608002638786511995717564457749873410017343184395040614025573440462522210939180555090227730875845671821586191943346000
from sympy import symbols, Eq, solve

p, q = symbols('p q')
equation1 = Eq(p * q, n)
equation2 = Eq((p-114)*(p-514)*(p+114)*(p+514)*(q-1919)*(q-810)*(q+1919)*(q+810), Golden_Oath)
solutions = solve((equation1, equation2), (p, q))
print(f"p 和 q 的解: {solutions}")

'''
p 和 q 的解: [(-11256874906034337229658272553494271626180719204801621165552253304119314454014247481847595578004383239651599038196432752043642616511808644606155091511313329, -12563439896413287507369191021540890661182794010085857062984791988214078294298809633469029528754549607502031091193150571585844351836163514784874848514208151), (11256874906034337229658272553494271626180719204801621165552253304119314454014247481847595578004383239651599038196432752043642616511808644606155091511313329, 12563439896413287507369191021540890661182794010085857062984791988214078294298809633469029528754549607502031091193150571585844351836163514784874848514208151)]
'''

有了p,q后就标准RSA解密过程抬走

1
2
3
4
5
6
p = 11256874906034337229658272553494271626180719204801621165552253304119314454014247481847595578004383239651599038196432752043642616511808644606155091511313329
q = 12563439896413287507369191021540890661182794010085857062984791988214078294298809633469029528754549607502031091193150571585844351836163514784874848514208151
d = inverse(e, (p-1)*(q-1))
m = pow(c, d, n)
print(long_to_bytes(m))
# b'flag{rE@L_d@m@9e_15_7h3_mo5t_au7hEn7ic_dam49E}'

week5

RSA?cmd5!

题目

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 gmpy2 import *
import hashlib

# 什么?你说你用 MD5 给 RSA 签名了?!

m = '*******'
assert len(m) == 7
flag = 'flag{th1s_1s_my_k3y:' + m + '0x' + hashlib.sha256(m.encode()).hexdigest() + '}'

p = getStrongPrime(512)
q = getStrongPrime(512)
n = p * q
e = 65537
phi = (p - 1) * (q - 1)
d = inverse(e, phi)


def get_MD5(m0):
import hashlib
md5_object = hashlib.md5(m0.encode())
md5_result = md5_object.hexdigest()
return md5_result


def get_s(m0, d0, n0):
hm0 = get_MD5(m0)
hm1 = bytes_to_long(hm0.encode())
s0 = pow(hm1, d0, n0)
return s0


def rsa_encode(m0, e0, n0):
m1 = bytes_to_long(m0.encode())
c0 = pow(m1, e0, n0)
return c0


def get_flag(m0): # 请用这个函数来转m得到flag
import hashlib
flag = 'flag{th1s_1s_my_k3y:' + m0 + '0x' + hashlib.sha256(m0.encode()).hexdigest() + '}'
print(flag)


s = get_s(m, d, n)
c = rsa_encode(flag, e, n)

print("密文c =", c)
print("签名s =", s)
print("公钥[n,e] =", [n, e])

'''
密文c = 119084320846787611587774426118526847905825678869032529318497425064970463356147909835330423466179802531093233559613714033492951177656433798856482195873924140269461792479008703758436687940228268475598134411304167494814557384094637387369282900460926092035234233538644197114822992825439656673482850515654334379332
签名s = 5461514893126669960233658468203682813465911805334274462134892270260355037191167357098405392972668890146716863374229152116784218921275571185229135409696720018765930919309887205786492284716906060670649040459662723215737124829497658722113929054827469554157634284671989682162929417551313954916635460603628116503
公钥[n,e] = [139458221347981983099030378716991183653410063401398496859351212711302933950230621243347114295539950275542983665063430931475751013491128583801570410029527087462464558398730501041018349125941967135719526654701663270142483830687281477000567117071676521061576952568958398421029292366101543468414270793284704549051, 65537]
'''

考点:RSA数字签名

一眼看下来是很正常的一个RSA加密,多就多在这个s,所以我们仔细研究一下s的函数,它传入m0,求了m0的md5值,之后进行以下步骤

$ s=(hm_1)^d\mod n $

我们知道e,所以很容易解这个式子

$ hm_1=s^e=(hm_1)^{ed}=(hm_1)^{k*phi+1}=hm_1\mod n $

知道hm1后,我们要在线网站解一下md5,就可以知道m0了,然后用来获取flag的函数一用就可以解出flag了,解出的m0如下,在线网站是md5在线解密破解

代码如下

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 *
from gmpy2 import *

s = 7270513885194445005322518350289419893608325839878215682947885852347014936106128407554345668066935779849573932055239642406851308417046145495939362638652861562381316163080735160853285303356461796079298817982074998651099375222398758502559657988024308504098238446594559605603104540325738607539729848183025647146
e = 65537
n = 118167767283404647838357773955032661171703847685597271116789633496884884504237966404005641401909577369476550625894333528860763752286157264860218284704704444830864099870199623580368198306940575628872723737071517733553706154898255520538220530675603850372384339470410704813339357637359108745206967929184573003377


def get_flag(m0): # 请用这个函数来转m得到flag
import hashlib
flag = 'flag{th1s_1s_my_k3y:' + m0 + '0x' + hashlib.sha256(m0.encode()).hexdigest() + '}'
print(flag)


hm_int = pow(s, e, n)
hm_str = long_to_bytes(hm_int).decode()
print(hm_str) # 86133884de98baada58a8c4de66e15b8

m = 'adm0n12' # 通过 cmd5.com 查询到的结果
get_flag(m)
# flag{th1s_1s_my_k3y:adm0n120xbfab06114aa460b85135659e359fe443f9d91950ca95cbb2cbd6f88453e2b08b}

easyECC

题目

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
from Crypto.Util.number import * # type: ignore
from secret import flag

p = 64408890408990977312449920805352688472706861581336743385477748208693864804529
a = 111430905433526442875199303277188510507615671079377406541731212384727808735043
b = 89198454229925288228295769729512965517404638795380570071386449796440992672131
E = EllipticCurve(GF(p),[a,b])
m = E.random_point()
G = E.random_point()
k = 86388708736702446338970388622357740462258632504448854088010402300997950626097
K = k * G
r = getPrime(256)
c1 = m + r * K
c2 = r * G
c_left =bytes_to_long(flag[:len(flag)//2]) * m[0]
c_right = bytes_to_long(flag[len(flag)//2:]) * m[1]


print(f"c1 = {c1}")
print(f"c2 = {c2}")
print(f"cipher_left = {c_left}")
print(f"cipher_right = {c_right}")


'''
c1 = (10968743933204598092696133780775439201414778610710138014434989682840359444219 : 50103014985350991132553587845849427708725164924911977563743169106436852927878 : 1)
c2 = (16867464324078683910705186791465451317548022113044260821414766837123655851895 : 35017929439600128416871870160299373917483006878637442291141472473285240957511 : 1)
c_left = 15994601655318787407246474983001154806876869424718464381078733967623659362582
c_right = 3289163848384516328785319206783144958342012136997423465408554351179699716569
'''

考点:ECC

很简单的一道ecc了,所以的值都给了,我们可以发现flag被分成两部分分别乘了m[0]和m[1],所以我们只需要分别解出m[0]和m[1]就行,那么只要求出密文m就可以了,而k已经给了,该有的值也都有了,所以只要套解密代码求一下就出来了(代码也是看到一篇博客知道的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 运行环境sagemath
from Crypto.Util.number import *
p = 64408890408990977312449920805352688472706861581336743385477748208693864804529
a = 111430905433526442875199303277188510507615671079377406541731212384727808735043
b = 89198454229925288228295769729512965517404638795380570071386449796440992672131
k = 86388708736702446338970388622357740462258632504448854088010402300997950626097

E = EllipticCurve(GF(p),[a,b])

c1 = E([10968743933204598092696133780775439201414778610710138014434989682840359444219,50103014985350991132553587845849427708725164924911977563743169106436852927878])
c2 = E([16867464324078683910705186791465451317548022113044260821414766837123655851895,35017929439600128416871870160299373917483006878637442291141472473285240957511])
cipher_left = 15994601655318787407246474983001154806876869424718464381078733967623659362582
cipher_right = 3289163848384516328785319206783144958342012136997423465408554351179699716569

m = c1 - k * c2
left = cipher_left//m[0]
right = cipher_right//m[1] # 不能转int或Integer型,不然结果为0,不知道为什么,很奇怪
print(long_to_bytes(int(left))+long_to_bytes(int(right)))

得出flag为:flag{This_is_the_last_crypto_}

没e也能玩?

题目

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

p = getPrime(1024)
q = getPrime(1024)
d = inverse(65537,(p-1)*(q-1))
dp = d %(p-1)
dq = d%(q-1)
print(f'c={pow(bytes_to_long(flag),e,p*q)}')
print(f'p={p}')
print(f'q={q}')
print(f'dp={dp}')
print(f'dq={dq}')

''''
c=312026920216195772014255984174463085443866592575942633449581804171108045852080517840578408476885673600123673447592477875543106559822653280458539889975125069364584140981069913341705738633426978886491359036285144974311751490792757751756044409664421663980721578870582548395096887840688928684149014816557276765747135567714257184475027270111822159712532338590457693333403200971556224662094381891648467959054115723744963414673861964744567056823925630723343002325605154661959863849738333074326769879861280895388423162444746726568892877802824353858845944856881876742211956986853244518521508714633279380808950337611574412909
p=108043725609186781791705090463399988837848128384507136697546885182257613493145758848215714322999196482303958182639388180063206708575175264502030010971971799850889123915580518613554382722069874295016841596099030496486069157061211091761273568631799006187376088457421848367280401857536410610375012371577177832001
q=121590551121540247114817509966135120751936084528211093275386628666641298457070126234836053337681325952068673362753408092990553364818851439157868686131416391201519794244659155411228907897025948436021990520853498462677797392855335364006924106615008646396883330251028071418465977013680888333091554558623089051503
dp=11282958604593959665264348980446305500804623200078838572989469798546944577064705030092746827389207634235443944672230537015008113180165395276742807804632116181385860873677969229460704569172318227491268503039531329141563655811632035522134920788501646372986281785901019732756566066694831838769040155501078857473
dq=46575357360806054039250786123714177813397065260787208532360436486982363496441528434309234218672688812437737096579970959403617066243685956461527617935564293219447837324227893212131933165188205281564552085623483305721400518031651417947568896538797580895484369480168587284879837144688420597737619751280559493857
'''

考点:dp,dq泄露

把最后一个式子变化一下可以得到

$ m = c^d + k \times n = c^d + k\times p\times q $

两边同时分别模p和q,可以得到两个式子

$ m_p = m\mod p = c^d \mod p $

$ m_q = m \mod q = c^d \mod q $

由已知的第一二个式子我们可以知道

$ d = k\times(p - 1)+ dp $

再带入$ m_p = c^d \mod p $可以得到

$ m_p = c^{dp} \mod p $

即可以求出mp,mq

再分析一下这两个式子$ m_p = c^d \mod p $;$ m_q = c^d \mod q $我们可以得到

$ c^d = K\times p +m_p $

$ c^d = k\times q + m_q $

下式带入上式得到

$ K\times p = k\times q + m_q - m_p $

两边模q得到

$ K\times p = (m_q - m_p)\mod q $

两边乘一个p对q的逆元,得到

$ K = p’\times (m_q - m_p) \mod q $

求出K后再带入$ c^d = K\times p +m_p $就可以得到c^d,从而解出明文

下面是代码实现(代码就是短短几行)

1
2
3
4
5
6
7
8
9
10
c=312026920216195772014255984174463085443866592575942633449581804171108045852080517840578408476885673600123673447592477875543106559822653280458539889975125069364584140981069913341705738633426978886491359036285144974311751490792757751756044409664421663980721578870582548395096887840688928684149014816557276765747135567714257184475027270111822159712532338590457693333403200971556224662094381891648467959054115723744963414673861964744567056823925630723343002325605154661959863849738333074326769879861280895388423162444746726568892877802824353858845944856881876742211956986853244518521508714633279380808950337611574412909
p=108043725609186781791705090463399988837848128384507136697546885182257613493145758848215714322999196482303958182639388180063206708575175264502030010971971799850889123915580518613554382722069874295016841596099030496486069157061211091761273568631799006187376088457421848367280401857536410610375012371577177832001
q=121590551121540247114817509966135120751936084528211093275386628666641298457070126234836053337681325952068673362753408092990553364818851439157868686131416391201519794244659155411228907897025948436021990520853498462677797392855335364006924106615008646396883330251028071418465977013680888333091554558623089051503
dp=11282958604593959665264348980446305500804623200078838572989469798546944577064705030092746827389207634235443944672230537015008113180165395276742807804632116181385860873677969229460704569172318227491268503039531329141563655811632035522134920788501646372986281785901019732756566066694831838769040155501078857473
dq=46575357360806054039250786123714177813397065260787208532360436486982363496441528434309234218672688812437737096579970959403617066243685956461527617935564293219447837324227893212131933165188205281564552085623483305721400518031651417947568896538797580895484369480168587284879837144688420597737619751280559493857
I = gmpy2.invert(q,p)
m1 = pow(c,dp,p)
m2 = pow(c,dq,q)
m = (((m1-m2)*I)%p)*q+m2
print(long_to_bytes(m))

得出flag为:flag{No_course_e_can_play}

格格你好棒

题目

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
from Crypto.Util.number import *
import random

flag = b'******'
m = bytes_to_long(flag)

a = getPrime(1024)
b = getPrime(1536)

p = getPrime(512)
q = getPrime(512)
r = random.randint(2**8, 2**9)
assert ((p+2*r) * 3*a + q) % b < 70

c = pow(m, 0x10001, p*q)

print(f'c =', c)
print(f'a =', a)
print(f'b =', b)

'''
c = 75671328500214475056134178451562126288749723392201857886683373274067151096013132141603734799638338446362190819013087028001291030248155587072037662295281180020447012070607162188511029753418358484745755426924178896079516327814868477319474776976247356213687362358286132623490797882893844885783660230132191533753
a = 99829685822966835958276444400403912618712610766908190376329921929407293564120124118477505585269077089315008380226830398574538050051718929826764449053677947419802792746249036134153510802052121734874555372027104653797402194532536147269634489642315951326590902954822775489385580372064589623985262480894316345817
b = 2384473327543107262477269141248562917518395867365960655318142892515553817531439357316940290934095375085624218120779709239118821966188906173260307431682367028597612973683887401344727494920856592020970209197406324257478251502340099862501536622889923455273016634520507179507645734423860654584092233709560055803703801064153206431244982586989154685048854436858839309457140702847482240801158808592615931654823643778920270174913454238149949865979522520566288822366419746
'''

考点:格攻击

关注断言((p+2*r) * 3*a + q) % b < 70

结果是一个小于70的数,相当于已知(爆破很快的),那么可以设成x,就可以写出下面这个样子

$ 3a(p+2r)+q=k\times b+x $

移项后就可以构造出下面这个格

$ \begin{align}(k,p+2r)\begin{pmatrix} b&0 \\ 3a&1 \end{pmatrix} =(x-q,p+2r)\end{align} $

复现时把3a放在上面发现不行,后面想了一下确实是,因为那样向量的大小就未知了,所以还是得像上面这样构造,构造好了sage跑出来后,我们得爆破一下x和r,这样就可以把p和q求出来,然后就标准rsa就行

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

c = 63970090307730335877809721304200883550049640814796584855311919788444862517887223732986595675409088426370045912297203884697715744287109423956446588104144896948474600924252971426757693149049788176140093762669257572818136268391076675502412382985137721246839664247241033867414491199483652292036165169353341736721
a = 169095591032842107903100075180638676605851796444162152675549552436872904263319011471312171874748357621716550291723406808357475877569622382251716493461335948233920131882151228308789748286370580144669281233868187101339909767205887609164975015547772498904502805235278789412044800177551190013789791754504529931231
b = 6064645365981235887306179215270851271718801644429108711725310294864007556801445216060166346337708059041073442260127725535139356989204300545757168654885686344461282796094266688090445897296901297377920786192865778222921548386038058555872765953356732109313734205459623312689902913019046944089470201948948652890006944620407534229412159275346491001935499731177063675134035072472112134333424000794637616785944210359606751334132126595044554089452160862222153579096125950

mat = [[b,0],[3*a,1]]
M = Matrix(ZZ,mat)
qq,pp= M.LLL()[0] # pp=p+2r,qq=x-q

print(pp)
print(qq)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import gmpy2
import libnum

pp = 11955063068051544630946316468962078511069091314797871913634545080191072376861594574934166492638293328464581874921393333283491910392413726570145081889323365

qq = 8045923199163511894962326127962855996723489290534633417316373444301965842496393267385921312122459846420286036232396674929308891656715922685980889381589005

c = 63970090307730335877809721304200883550049640814796584855311919788444862517887223732986595675409088426370045912297203884697715744287109423956446588104144896948474600924252971426757693149049788176140093762669257572818136268391076675502412382985137721246839664247241033867414491199483652292036165169353341736721

for i in range(2 ** 8, 2 ** 9):
for j in range(70):
p = pp - 2 * i
q = qq + j
phi = (p - 1) * (q - 1)
if gmpy2.gcd(phi, 65537) != 1:
continue
d = gmpy2.invert(65537, phi)
n = p * q
m = pow(c, d, n)
flag = libnum.n2s(int(m))
if b'flag' in flag:
print(flag)
break

得出flag为:flag{u_are_@_master_of_latt1ce_Crypt0gr@phy}

学以致用

题目

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
import random
from Crypto.Util.number import *

def pad(msg, nbits):
# pad了一下,仔细看看,别好不容易解出来了却没看到flag👼
pad_length = nbits - len(msg) * 8 - 16
assert pad_length >= 0
pad = random.getrandbits(pad_length).to_bytes((pad_length + 7) // 8, "big")
return pad[:len(pad)//2] + b"*" + msg + b"*" + pad[len(pad)//2:]

if __name__ == '__main__':
p = getPrime(1024)
q = getPrime(1024)
n = p*q
e = 3
Nbits = 2048
flag = b'flag{?????}'
gift = b'GoOd_byE_nEw_5t@r'

flag1 = bytes_to_long(pad(flag[:len(flag)//2], Nbits-1))
flag2 = bytes_to_long(pad(flag[len(flag)//2:], Nbits-1))

print('n =',n)
print('c1 =', pow(flag1, e, n))
print('c2 =', pow(flag2, e, n))
print('c3 =', pow(flag1 + flag2 + bytes_to_long(gift), e, n))

'''
n = 17072342544150714171879132077494975311237876365187751353863158074020024719122755004761547735987417065592254800869192615807192722193500063611855839293567948232939959753821265552288663615847715716482887552271575844394350597695771100384136647573934496089812758071894172682439278191678102960768874456521879228612030147515967603129172838399997929502420254427798644285909855414606857035622716853274887875327854429218889083561315575947852542496274004905526475639809955792541187225767181054156589100604740904889686749740630242668885218256352895323426975708439512538106136364251265896292820030381364013059573189847777297569447
c1 = 8101607280875746172766350224846108949565038929638360896232937975003150339090901182469578468557951846695946788093600030667125114278821199071782965501023811374181199570231982146140558093531414276709503788909827053368206185816004954186722115752214445121933300663507795347827581212475501366473409732970429363451582182754416452300394502623461416323078625518733218381660019606631159370121924340238446442870526675388637840247597153414432589505667533462640554984002009801576552636432097311654946821118444391557368410974979376926427631136361612166670672126393485023374083079458502529640435635667010258110833498681992307452573
c2 = 14065316670254822235992102489645154264346717769174145550276846121970418622727279704820311564029018067692096462028836081822787148419633716320984336571241963063899868344606864544582504200779938815500203097282542495029462627888080005688408399148971228321637101593575245562307799087481654331283466914448740771421597528473762480363235531826325289856465115044393153437766069365345615753845871983173987642746989559569021189014927911398163825342784515926151087560415374622389991673648463353143338452444851518310480115818005343166067775633021475978188567581820594153290828348099804042221601767330439504722881619147742710013878
c3 = 8094336015065392504689373372598739049074197380146388624166244791783464194652108498071001125262374720857829973449322589841225625661419126346483855290185428811872962549590383450801103516360026351074061702370835578483728260907424050069246549733800397741622131857548326468990903316013060783020272342924805005685309618377803255796096301560780471163963183261626005358125719453918037250566140850975432188309997670739064455030447411193814358481031511873409200036846039285091561677264719855466015739963580639810265153141785946270781617266125399412714450669028767459800001425248072586059267446605354915948603996477113109045600
'''

考点:groebner_basis()

虽说原理还不理解,但是解题代码看的七七八八了,就是用groebner_basis()这个函数可以求出多项式的解来,格式是x减去所求值的一个多项式,所以取负,再取系数,就可以得到所求值

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
# sage
from Crypto.Util.number import long_to_bytes, bytes_to_long

n = 17072342544150714171879132077494975311237876365187751353863158074020024719122755004761547735987417065592254800869192615807192722193500063611855839293567948232939959753821265552288663615847715716482887552271575844394350597695771100384136647573934496089812758071894172682439278191678102960768874456521879228612030147515967603129172838399997929502420254427798644285909855414606857035622716853274887875327854429218889083561315575947852542496274004905526475639809955792541187225767181054156589100604740904889686749740630242668885218256352895323426975708439512538106136364251265896292820030381364013059573189847777297569447
c1 = 8101607280875746172766350224846108949565038929638360896232937975003150339090901182469578468557951846695946788093600030667125114278821199071782965501023811374181199570231982146140558093531414276709503788909827053368206185816004954186722115752214445121933300663507795347827581212475501366473409732970429363451582182754416452300394502623461416323078625518733218381660019606631159370121924340238446442870526675388637840247597153414432589505667533462640554984002009801576552636432097311654946821118444391557368410974979376926427631136361612166670672126393485023374083079458502529640435635667010258110833498681992307452573
c2 = 14065316670254822235992102489645154264346717769174145550276846121970418622727279704820311564029018067692096462028836081822787148419633716320984336571241963063899868344606864544582504200779938815500203097282542495029462627888080005688408399148971228321637101593575245562307799087481654331283466914448740771421597528473762480363235531826325289856465115044393153437766069365345615753845871983173987642746989559569021189014927911398163825342784515926151087560415374622389991673648463353143338452444851518310480115818005343166067775633021475978188567581820594153290828348099804042221601767330439504722881619147742710013878
c3 = 8094336015065392504689373372598739049074197380146388624166244791783464194652108498071001125262374720857829973449322589841225625661419126346483855290185428811872962549590383450801103516360026351074061702370835578483728260907424050069246549733800397741622131857548326468990903316013060783020272342924805005685309618377803255796096301560780471163963183261626005358125719453918037250566140850975432188309997670739064455030447411193814358481031511873409200036846039285091561677264719855466015739963580639810265153141785946270781617266125399412714450669028767459800001425248072586059267446605354915948603996477113109045600
gift = b'GoOd_byE_nEw_5t@r'

x, y = PolynomialRing(Zmod(n), 'x, y').gens()
f1 = x**3 - c1
f2 = y**3 - c2
f3 = (x + y + bytes_to_long(gift))**3 - c3

gb = Ideal(f1, f2, f3).groebner_basis()
f1, f2 = gb # 返回一个多项式

flag1 = int(-f1.coefficients()[1]) # 取负是为了求出m,因为上面多项式是x减去我们所求

flag2 = int(-f2.coefficients()[1])
print(flag1)
# 出题的时候加了给pad,大家得注意一下,flag在一堆trash中间,别做出了却没看见flag
print((long_to_bytes(flag1)).split(b'*')[2]+(long_to_bytes(flag2).split(b'*')[1]))

# b'flag{W1Sh_you_Bec0me_an_excelL3nt_crypt0G2@pher}'