2023安洵杯

2023第六届安洵杯网络安全挑战赛——Crypto——Wp

有幸和团队师傅参与比赛,并且取得了第六名的好成绩

010101

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
# -*- coding:utf-8 -*-
import os
import random
import string
import hashlib
import socketserver
from Crypto.Util.number import isPrime, long_to_bytes, getStrongPrime, bytes_to_long

flag = b"D0g3{******************************************}"

class MyServer(socketserver.BaseRequestHandler):
def proof(self):
random.seed(os.urandom(8))
random_str = ''.join([random.choice(string.ascii_letters + string.digits) for _ in range(20)])
str_sha256 = hashlib.sha256(random_str.encode()).hexdigest()
self.request.sendall(('SHA256(XXXX + %s):%s\n' % (random_str[4:], str_sha256)).encode())
self.request.sendall('Give Me XXXX:\n'.encode())
XXXX = self.request.recv(2048).strip()

if hashlib.sha256((XXXX + random_str[4:].encode())).hexdigest() != str_sha256:
return False

return True

def getPQN(self):
while True:
p = getStrongPrime(2048)
q = getStrongPrime(2048)
n = p * q
if p.bit_length() == 2048 and q.bit_length() == 2048 and n.bit_length() == 4096:
return p, q, n

def encrypt(self):
p, q, n = self.getPQN()
m = bytes_to_long(flag)
e = 0x10001
c = pow(m, e, n)
p = bin(p)[2:]
p1 = list(p[:1024])
p2 = list(p[1024:])
p1[random.choice([i for i, c in enumerate(p1) if c == '1'])] = '0'
p2[random.choice([i for i, c in enumerate(p1) if c == '0'])] = '1'
return n, ''.join(p1) + ''.join(p2), c

def handle(self):
if not self.proof():
self.request.sendall(b'Error Hash!')
return
n, p, c = self.encrypt()
self.request.sendall('Press 1 to get ciphertext\n'.encode())
number = self.request.recv(512).strip().decode()
if number == '1':
self.request.sendall((str(n) + '\n').encode())
self.request.sendall((str(p) + '\n').encode())
self.request.sendall((str(c) + '\n').encode())
else:
self.request.sendall('Incorrect input!\n'.encode())
return


class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass

if __name__ == '__main__':
sever = socketserver.ThreadingTCPServer(('0.0.0.0', 10001), MyServer)
ThreadedTCPServer.allow_reuse_address = True
ThreadedTCPServer.allow_reuse_port = True
sever.serve_forever()

关键在

1
2
p1[random.choice([i for i, c in enumerate(p1) if c == '1'])] = '0'
p2[random.choice([i for i, c in enumerate(p1) if c == '0'])] = '1'

意思就是$p_1$中有一个1被改为了0

对于$p_2$来说,是有可能不改变的,因为索引值是$p_1$的(不知道这里是笔误还是原本就这样)

直接爆破即可,遍历$p_1$中的0,$p_2$分两种情况,一种是不变的时候,一种是变的情况

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

n = 603929041261800903893255846837373435975689488156082111538579411971234122241475748036901372456410420191268918203740933624479627880138860787078343962957545877493495346831028915623609911739520855865598159115403599691845611787894864022849387193442196306247844978619825889396851220746270712372629345235420222076680115154790661980407543403831934888441296510749707016149742835334975569330963811702631399381154725473397239011407333239568323785920549918563058163802790187563167758518996273164519358725587751057556099683209931508156206102023550113078755175573231054144175740037978473444981801474458374782704295305402882601070280107624282520071733642472567932754610400320318631599250987727798785732693028629127928075161764000633755172649305820758541646921112640799416373141028867694424520169726284794592230472739528017824591893518858631575238481300188255385565135530781399021638113121796002810581237621059229401475373166398218013467690838657741784353265467188916419980824688886467277205321029087429010136873982224751707535560753990915173665180626848355707628545030678081326994468311753531184000767912265077615115921131730201921373353972239662406236256449307913217499123008959838210605102941439012579314919044679872148810171587616630982300997769
P = "11010001001011001110010111110000100100111111011100110000001011110010001010111010001000110011110011100101101111000010000110010011010001100111010001101101010110110000001000111101001111001111100111010001110001110000011101110111100010100110111111010101101000100101011101111100100100011101001001010101010100100100010111001101101001001101010111101001101010111111111010101111000110010011001001010010101110010110111110111001011011000111101110100100001100100111101100010100100000111001111111111000101001101111111001010000111110000110111110110101101001111010010001111111010011101111111011101000011101100010000000101000010010001100101001001100000000110111110101001101001010110111011100101001111111111110010100101101001110000000100011000001011110110101110111010001101000000101111101011010010000000110100011110101000000110011100001001010000111110101111011001110001000101010010110100010010000011010000000010110010110110010100000010111100011000101001110100100001110011010101011010111101000100010001000100100001110001100000011001000000011010110000100011000010010011100101101000001011110011010111111011001001101000101010011001010100000101011011010001101000110100001010111000111011111000111000110010111011111001001000111101101111101101100110000010001010100000000010111001011010110101000110010010100000110010001010001010111110010001110100100001110110100011100110010101101010010000110010000000000001101001001111000001001110111100101011010000101000001101100000011010110110001001100001010110010111110000100010010001111000111110111001110111010000010110111101110010011101010001101000100011111100111101110100100001001010110000110011110011000110010000111111110011100001110011010010010001011000011101000001100100110101001010110101000100010110000111001100011101000110010101101110000001110101010010100011111000011011010110001111000001000111011110111000111111011011101101011011011010101010001001000001001101111101101011010000001111001101010000100100011011010011011011011110011101001110011000101101010001000111100101010111001110100001001011101000111110110111111101001100110111011"
c = 86686439679874830246557653015232666024548117379353423678475364097072178826632356840355752060131181776717167764598857424931346233132869924918276685776350661070390576961130941951957979601769745016239304945501929062576701514720613007436301407348380329606694430576562909174904437860869521166636000289719433717305895080524202468368216882473127238573270504191177749274378107593390170231953722023523109786520395037511557586384515517033167064188185912051635528465308305202059386081496894767608262032863369259646855260874931901314784267182224186084544278686060811418808427473393401031779270067234650782676467179083936163361798893672177127354928129838729299397848748974202105320442165321749085841967661828478087899131573349766763269557239693467725757622240790567302886026262903788677893782986023554124746338684896334712802104286022426080359219997110717128626202867661389035295735029082783484639744693093659639224377233571685420055087016612362091684619532730540899821020173872616220719344374207934384262583860759996308412468708264575433904901696415884548016664119511545715549106666120050640487895135909555493016879887730329494392167451911914419832673885582817232756022767909864103483310200762274943174788555599167912909253375001595679099288103
e = 65537

a1 = [i for i, c in enumerate(list(P[:1024])) if c == '0']
a2 = [i for i, c in enumerate(list(P[1024:])) if c == '1']

# p2不变的情况
for i in tqdm(a1):
pp = list(P[:1024])
pp[int(i)] = "1"
p = int(("".join(pp) + "".join(list(P[1024:]))),2)
if isPrime(p):
print(f"p = {p}")
q = n // p
d = gmpy2.invert(e,(p-1)*(q-1))
m = pow(c,d,n)
flag = long_to_bytes(m)
if b"D0g3{" in flag:
print(flag)
break
# D0g3{sYuWzkFk12A1gcWxG9pymFcjJL7CqN4Cq8PAIACObJ}

这题做了两遍,第一遍估计是代码写的不对,爆了3~4次都没出,索性重新拿数据,然后运气比较好,刚好是$p_2$不变的情况,秒出

POA

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# -*- coding:utf-8 -*-
from Crypto.Util.number import isPrime, long_to_bytes, getStrongPrime, bytes_to_long
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import os
import binascii
import random
import string
import hashlib
import socketserver

FLAG = '**********'
KEY = b'****************'
IV = b'****************'


def cbc_decrypt(c, iv):
aes = AES.new(KEY, AES.MODE_CBC, iv=iv)
return aes.decrypt(c)


def encrypt():
plain_text = ''.join([random.choice(string.ascii_letters) for _ in range(2)]) + FLAG
aes = AES.new(KEY, AES.MODE_CBC, iv=IV)
plain_text = pad(plain_text.encode(), AES.block_size)
cipher = aes.encrypt(plain_text)
return IV.hex() + cipher.hex()


def asserts(pt: bytes):
num = pt[-1]
if len(pt) == 16:
result = pt[::-1]
count = 0
for i in result:
if i == num:
count += 1
else:
break
if count == num:
return True
else:
return False
else:
return False


def decrypt(c):
iv = c[:32]
cipher = c[32:]
plain_text = cbc_decrypt(binascii.unhexlify(cipher), binascii.unhexlify(iv))
if asserts(plain_text):
return True
else:
return False


class MyServer(socketserver.BaseRequestHandler):
def proof(self):
random.seed(os.urandom(8))
random_str = ''.join([random.choice(string.ascii_letters + string.digits) for _ in range(20)])
str_sha256 = hashlib.sha256(random_str.encode()).hexdigest()
self.request.sendall(('SHA256(XXXX + %s):%s\n' % (random_str[4:], str_sha256)).encode())
self.request.sendall('Give Me XXXX:\n'.encode())
XXXX = self.request.recv(2048).strip()

if hashlib.sha256((XXXX + random_str[4:].encode())).hexdigest() != str_sha256:
return False

return True

def handle(self):
if not self.proof():
self.request.sendall(b'Error Hash!')
return
cipher = encrypt()
self.request.sendall('Welcome to AES System, please choose the following options:\n1. encrypt the flag\n2. decrypt the flag\n'.encode())
n = 0
while n < 65536:
options = self.request.recv(512).strip().decode()
if options == '1':
self.request.sendall(('This is your flag: %s\n' % cipher).encode())
elif options == '2':
self.request.sendall('Please enter ciphertext:\n'.encode())
recv_cipher = self.request.recv(512).strip().decode()
if decrypt(recv_cipher):
self.request.sendall('True\n'.encode())
else:
self.request.sendall('False\n'.encode())
else:
self.request.sendall('Input wrong! Please re-enter\n'.encode())
n += 1
return


class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass

if __name__ == '__main__':
sever = socketserver.ThreadingTCPServer(('0.0.0.0', 10010), MyServer)
ThreadedTCPServer.allow_reuse_address = True
ThreadedTCPServer.allow_reuse_port = True
sever.serve_forever()

预言填充攻击,0xGame和NewStar都有出现过

小改一下脚本即可

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
from pwn import *
import string
from itertools import product
import hashlib
from tqdm import *

# context.log_level = 'debug'
table = string.ascii_letters + string.digits

host = '124.71.177.14' #ip地址
port = 10010 #端口

GeShi = b'Give Me XXXX:' # 改格式!
p = remote(host,port) #建立连接

data = p.recvuntil(GeShi).decode()

proof = data.split('SHA256')[1]

Xnum = proof.split('+')[0].upper().count("X") #要爆破的数量
tail = proof.split('+')[1].split(')')[0].strip()
hash = proof.split('+')[1].split('\n')[0].split(":")[1]

print("未知数:",Xnum)
print(tail)
print(hash)
print("开始爆破")
for i in product(table,repeat=Xnum):
head = ''.join(i)
t = hashlib.sha256((head + tail).encode()).hexdigest()
if t == hash:
print('爆破成功!结果是:', end='')
print(head)
p.send(head.encode())
break

print("以下是提交完XXXX之后的流程\n")

p.recvuntil(b"2. decrypt the flag\n")
p.sendline(b"1")
temp = p.recvline().decode().split("flag: ")[1].strip()
print(f"temp = {temp}")
token = binascii.unhexlify(temp)
print(f"token = {token}")

def dec(iv, token):
p.sendline(b"2")
p.sendlineafter(b"Please enter ciphertext:", binascii.hexlify(iv+token))
p.recvline()
return b'True' in p.recvline()

counter = len(token) // 16
true_flag = ''
t = token[::]
for ct in range(1, counter):
oldIv = t[16*ct-16:16*ct]
token = t[16*ct:16*ct+16]
flag = [] # 记录原始解密值
suf = []

for i in tqdm(range(1,17)):
for j in range(256):
payload = b"D0g3{U_Get_Fl4g}"[:16-i] + bytes([j]) + bytes(suf) + token
if dec(payload[:16], payload[16:]):
flag.append(j ^ i)

suf.insert(0, j)
for v in range(len(suf)):
suf[v] = suf[v] ^ i ^ (i+1)
print(flag)
break

ans = ""

flag.reverse()

for i in range(16):
ans += chr(oldIv[i] ^ flag[i])
true_flag += ans
print(true_flag)

print(true_flag)
# D0g3{0P@4Ttk}

得到的是QT{0P@d4Ttk},手动改为D0g3{0P@4Ttk}

Rabin

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# -*- coding:utf-8 -*-
import os
import random
import string
import hashlib
import socketserver
from secret import *
import uuid
import gmpy2
from Crypto.Util.number import isPrime, long_to_bytes, getStrongPrime, bytes_to_long


def get_flag(head):
table = string.printable
name = ''.join([random.choice(table) for i in range(10)])
return head + '{' + str(uuid.uuid5(uuid.NAMESPACE_OID, name)) + '}'


def relation():
a, b = 0, 0
for i in range(x - (2**2 - 1)):
a += pow(e1, i)
for j in range(3):
b += pow(e2, j)
if a == b:
return True
return False


def get_pqr():
while True:
p = getStrongPrime(1024)
q = getStrongPrime(1024)
if p % 4 == 3 and q % 4 == 3:
break
r = 2
while True:
r = r * x
if r.bit_length() > 1024 and isPrime(r - 1):
r = r - 1
break
return p, q, r


def encrypt():
if relation():
print('success')
else:
print('false')

flag = get_flag('D0g3')

m1 = ''.join([random.choice(string.ascii_letters) for _ in range(234)]) + ' ' + flag[:21]
m2 = flag[21:] + ' ' + ''.join([random.choice(string.ascii_letters) for _ in range(234)])

p, q, r = get_pqr()
phi = (p - 1) * (q - 1) * (q - 1)
while True:
try:
d = gmpy2.invert(e2, phi)
break
except Exception as e:
p, q, r = get_pqr()

n = p * q * r
inv_p = gmpy2.invert(p, q)
inv_q = gmpy2.invert(q, p)

c1 = pow(bytes_to_long(m1.encode()), e1, n)
c2 = pow(bytes_to_long(m2.encode()), e2, n)

return n, inv_p, inv_q, c1, c2


class MyServer(socketserver.BaseRequestHandler):
def proof(self):
random.seed(os.urandom(8))
random_str = ''.join([random.choice(string.ascii_letters + string.digits) for _ in range(20)])
str_sha256 = hashlib.sha256(random_str.encode()).hexdigest()
self.request.sendall(('SHA256(XXXX + %s):%s\n' % (random_str[4:], str_sha256)).encode())
self.request.sendall('Give Me XXXX:\n'.encode())
XXXX = self.request.recv(2048).strip()

if hashlib.sha256((XXXX + random_str[4:].encode())).hexdigest() != str_sha256:
return False

return True

def handle(self):
if not self.proof():
self.request.sendall(b'Error Hash!')
return

n, inv_p, inv_q, c1, c2 = encrypt()
self.request.sendall('Press 1 to get ciphertext\n'.encode())
number = self.request.recv(512).strip().decode()
if number == '1':
self.request.sendall(("n = %d\n" % n).encode())
self.request.sendall(("inv_p = %d\n" % inv_p).encode())
self.request.sendall(("inv_q = %d\n" % inv_q).encode())
self.request.sendall(("c1 = %d\n" % c1).encode())
self.request.sendall(("c2 = %d\n" % c2).encode())
else:
self.request.sendall('Incorrect input!\n'.encode())
return


class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass

if __name__ == '__main__':
sever = socketserver.ThreadingTCPServer(('0.0.0.0', 10100), MyServer)
ThreadedTCPServer.allow_reuse_address = True
ThreadedTCPServer.allow_reuse_port = True
sever.serve_forever()

题目是Rabin,估计和2有关,大胆猜测了一下$e_1 = 2$

然后简单爆破了一下知道$x = 8,e_2 = 7$

r已知,接下来分解$p \times q$
$$
\because \quad pp^{-1} \equiv 1 \mod q\quad \quad qq^{-1} \equiv 1 \mod p
$$

$$
\therefore \quad pp^{-1} = k_1q + 1 \quad \quad qq^{-1} = k_2p + 1
$$

两式相乘得
$$
pp^{-1}qq^{-1} = (k_1q + 1)(k_2q_2 + 1) = k_1k_2pq + k_2p + k_1q + 1
$$
移项得
$$
pp^{-1}qq^{-1} - k_2p -k_1q - 1 = k_1k_2pq
$$
经测试,$k_1,k_2 \approx 1023bit$

可以认为$k_2p + k_1q \approx p\times q$

把上式同除$p\times q$,即可得到$k_1\times k_2$

然后即可求得$k_2p + k_1q$

因为$k_1q,k_2p$是$(x - k_1q)(x-k_2p) = 0$,即这个方程$x^2 - (k_1q + k_2p)x + k_1k_2pq = 0$的两根

利用求根公式$x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$

这里$a = 1,b = k_1q + k_2p,c = k_1k_2pq$

求解后得到$x_1 = k_1q,x_2 = k_2p$

再分别和$p \times q$求公因数,得到$p,q$

得到$p,q$后,前半部分是解Rabin,后半部分求逆元或者有限域开根都可以

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
from Crypto.Util.number import *
import gmpy2

e1 = 2
e2 = 5
x = 8
a = b = 0
for i in range(x - (2**2 -1 )):
a += pow(e1,i)
for j in range(3):
b += pow(e2, j)

# print(a == b)
n = 305742085102073958685058774990374612856503657611159209468741748564654591176180299818778135460948807176614281796016904753313757927457094861196369069821421681665875176139845644195736238144691839008758614457979812997005126606399842320648487994406393728514493129219688752202978501994811535834779889459729683428077498441713132964635907469366512175886337946124631196824508247375645971308484279007920881639616776491331812849657775358960227848680733861313065565269244274482334952541032707333167429562469558762781469669359057084779217532331399410333624558772093729396962312936037020992117478202860898927073068360026814644581294222733341428537874383052653054496502673372786144676806905626251642090622209277799682962538245425774337944285158783294880516595307576719556933669812074808919685419881388267486868941401975800053647291641426673593791774634377598637815942343627245274057532320854646240153245893536480745586533270387549779636700040935751519181245119278044454115223974366280075995685049945977835434961621019
inv_p = 80275679918090105134294823865673211657060049627413874971428297415355157707252877991145232186659935067961745973100698632943949790304190096567884607037119257848837354982500048978070619820510408650386626542338056277335180497955588848138448991963800265073331348097617541306117998857780109771194563339021595188562
inv_q = 91430270065720942392278749444269989843094838912787188266496611817766528132774187319335115624057615900976202412507879118712912101862728738204907877396022887953429108729897171677408597080700062032905675017013140349657979587207083820584906055634857776106802178757131724480934751871117394549988315719808677297400
c1 = 27982926262483311148784661440434049509041271145373939684263123722309350890886129800416935949757799004078048732281935770255739076672223113235604245680214981770721357810264502828783436566049916012826991722307971435988653591370445652627932863934280322586450541943726361669705223005256707033393323681199742226865639061796493744221386650671921408599281675072195109604944995246990117259752921959078570716019348911611821807743542202606017861680093899453962535751057029803212313708486252499961531916769339026243456254415795474566725045397580987945276292940425615563426872706612654673760957132954706561315315926583847756728581334589763622690426645925379033552965887091774261328484101677385760510308565939450969280431514193153901465147874994288888863961626533437546523090704677258271361008899424058968841403657808839941136606557821902221756903088734659178298942185013814206583151273573533540756898457572685280130826705824899847574123392575025182545331871707478881582060832153045557952057641871852784168481101647
c2 = 161619014853290061321220693856242384241899565606310997462914314289208211523608827698222734190386889612098570760765052452215805711014546122099647560430788381292730765852839847593053599250289125651012417026034998933486356540308165710913202176920168248765753912975464775516099366852853130484143941438754410599163284892652060800647319146257668079858962426955881454668916171211181142453679621166656675384626603665740562005722087726838877971126595828345860415781411146330129891129797182526922825440860137352029911523070206447988669663751215339049795213569586767141039747546364893768334626213397240105328357731197925663794385770706516043309955122745946633182399168534133436912290389494270925639788309351783493083085094045092781888997140679841389857851588928742292158429434570541383701331355804702559218884246423448924119442796513423570240629502315241227996438176424546368309332048747610392861954126660466095971227213870875955019656804172566974654412258429352773642042554134725696296293760333163865827998422748
# print(inv_p.bit_length())
# print(inv_q.bit_length())

def getr():
r = 2
while True:
r = r * x
if r.bit_length() > 1024 and isPrime(r - 1):
r = r - 1
break
return r
r = getr()
# print(r)

pq = n // r

temp = inv_p*inv_q * pq
k1k2 = (temp- pq) // pq
print(k1k2) #检验过这个式子没问题


k1q_k2p = temp - k1k2 * pq - 1

delta = k1q_k2p**2 - 4 * k1k2*pq

k1q = (k1q_k2p + gmpy2.iroot(delta,2)[0]) // 2
k2p = (k1q_k2p - gmpy2.iroot(delta,2)[0]) // 2
q = gmpy2.gcd(k1q,pq)
p = gmpy2.gcd(k2p,pq)
print(f"q = {q}")
print(f"p = {p}")

def decrypt1(c,p,q,inv_p,inv_q,n):
mp = pow(c, (p + 1) // 4, p)
mq = pow(c, (q + 1) // 4, q)
inv_p = gmpy2.invert(p, q)
inv_q = gmpy2.invert(q, p)

a = (inv_p * p * mq + inv_q * q * mp) % n
b = n - int(a)
c = (inv_p * p * mq - inv_q * q * mp) % n
d = n - int(c)
aa = [a, b, c, d]
for i in aa:
flag = long_to_bytes(int(i))
if b"D0g3" in flag:
print(flag)
break

decrypt1(c1,p,q,inv_p,inv_q,pq)
# D0g3{82309bce-9db6-53
phi = (p-1)*(q-1)*(r-1)
d = gmpy2.invert(e2,phi)
m = pow(c2,d,n)
print(long_to_bytes(m))
# 40-a9e4-a67a9ba15345}
# D0g3{82309bce-9db6-5340-a9e4-a67a9ba15345}

赛后发现这道题有原题,我测!!!!!!

crypto杂记(1) - hash_hash - 博客园 (cnblogs.com)————————————Grabs

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