Crypto_Checkin

使用 Cyberchef 分析得知这是 Base 套娃编码后的 Flag,解码后得到 Flag:flag{Th1s_1s_B4s3_3nc0d3}

Screenshot-202310081456.webp

凯撒大帝

直接遍历凯撒所有情况能够发现 Flag:flag{chutihaonan}
写 Writeup 也好难的。

立正

观察得密文中间 4gNUx4NgQgEUb4NC64NHxZLg636V6CDBiDNUHw8HkapH 这一串应该是 Base64 编码后的字符串,但是直接解码没有意义,应该需要预处理。注意到 hgrfhg 可能是单词 decode,尝试凯撒无果,但是发现 Reverse 后可以通过凯撒得到单词 decode:

Screenshot-202310081614.webp

注意到开头应该是 Look at you,对大写字母部分也进行凯撒。最后只保留密文中间的部分进行处理,逐个尝试数字部分的凯撒 Amount,直到能够正确解密出 Flag:

Screenshot-202310081617.webp

所以 Flag:flag{Y0U_MU57_5t4nd_uP_r1gHt_n0W}

残缺的 MD5

直接按照题目要求编写代码遍历情况:

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

def md5(input_string: str) -> str:
md5_hash = hashlib.md5()
md5_hash.update(input_string.encode('utf-8'))
md5_hex = md5_hash.hexdigest()
return md5_hex

alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
for comb in itertools.product(*(alphabet for _ in range(3))):
string = f"KCLWG{comb[0]}K8M9O3{comb[1]}DE{comb[2]}84S9"
string_md5 = md5(string).upper()
if re.match(r"F0AF....B1F463....F7AE...B2AC4E6", string_md5):
print(string, string_md5)

运行代码后可以得到 Flag:flag{F0AF1443B1F463EAFFF7AEBB8B2AC4E6}

进制

能用 Cyberchef Magic 完成的题目为什么还要写题解…

Screenshot-202310081605.webp

所以 Flag:flag{ahfkjlhkah}

okk

通过搜索引擎搜索和后发现了 Ook Encoding,直接使用工具解码得到 Flag:flag{123456789}

熊斐特

熊斐特是吧,直接 Atbash Cipher 得到 Flag:flag{atbash cipher}

埃特巴什码是由熊斐特博士发现的。熊斐特博士为库姆兰《死海古卷》的最初研究者之一,他在《圣经》历史研究方面最有名气的著作是《逾越节的阴谋》。他运用这种密码来研究别人利用其他方法不能破解的那些经文。这种密码被运用在公元1世纪的艾赛尼/萨多吉/拿撒勒教派的经文中,用以隐藏姓名。

黑暗之歌

先是盲文加密,使用在线工具解密后得到 ♬♩¶♯♬♭♬♫♫♪♬♯‖♯♬§♬§♯¶‖¶‖‖‖¶‖♭♯¶‖♬♬♭‖♯‖¶♫♫♯=。这是是音乐符号加密,使用在线工具解密得到 Flag:flag{b2cc-9091-8a29}

写 Writeup 的时候发现,做题时用的盲文加密解密工具网站裂了,不过其他工具其实也能解,多一个 Base64 解码的步骤。

迷雾重重

使用 .- 替换 01,然后 Morse 解码,得到flagmorse_is_very_fun,所以 Flag:flag{morse_is_very_fun}

难言的遗憾

关键词「清政府」「编码」「中文」,猜测为汉字的电报码,使用在线工具转码后能得到 Flag:flag{一天不学高数我就魂身难受}

小兔子可爱捏

众所周知,宇宙的终极答案是 42,以其作为密钥使用在线工具解密 Rabbit 可以得到 Flag:flag{i_love_technology}

电信诈骗

从题面中我们可以得到下面的流程:先 v 个 50 作为启动资金,然后利用地宫第四行第七列的东西卷土重来,所以我们可以得到下面的解密流程:XOR 50 → ROT 47。使用 Cyberchef 进行处理:

Screenshot-202310081546.webp

得到 Flag:flag{Cr42y_7hursd4y_v1v0_5o!!!}

what is m

这题直接是将 Flag 通过 bytes_to_long 转成了一个长整型,那么我们只需要用 long_to_bytes 将其转换回来即可,写点代码:

1
2
3
4
5
from Crypto.Util.number import long_to_bytes

m = 7130439814057451283123261212311792965221465187093665325418151083084336062884806048278336517910440471098303223600583095785498954652150321894178963775030272294956440353105533996517701166778749

print(long_to_bytes(m).decode('utf-8'))

运行后得到 Flag:flag{TherE_4r3_s3vER4L_al7erN4T1V35_7O_tHe_L0N6_t0_bYTes_1unctI0n_Bg926gaBbZCI}

really_ez_rsa

这题直接给出了 p 和 q 的值,不说了,直接计算私钥然后解码即可,上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
from Crypto.Util.number import long_to_bytes, inverse

p = 217873395548207236847876059475581824463
q = 185617189161086060278518214521453878483
c = 6170206647205994850964798055359827998224330552323068751708721001188295410644
e = 65537
n = p * q

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)

print(long_to_bytes(m).decode('utf-8'))

运行程序解码后得到 Flag:flag{Y0ung_meiyou_xiaojj}

……?

XOR

题目给了 RSA 加密中 p 与 q 的 xor 值,当然,其实还有 p 与 q 的乘法值 n,所以可以通过一些手段计算出 p 和 q:

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
import itertools
from tqdm import tqdm

def explode(n,x,r):
n1 = n
x1 = x
cur_mod = 1
a_list, b_list = [0], [0]
for _ in tqdm(range(r)):
cur_mod *= 2
next_a = []
next_b = []
for al, bl in zip(a_list, b_list):
for ah, bh in itertools.product([0, 1], repeat=2):
aa, bb = ah*(cur_mod // 2) + al, bh*(cur_mod // 2) + bl
if ((aa * bb % cur_mod == n1 % cur_mod) and ((aa ^ bb) == x1 % cur_mod)):
next_a.append(aa)
next_b.append(bb)
a_list, b_list = next_a, next_b
for a in a_list:
for b in b_list:
if a*b == n1 and a ^ b == x1:
return a, b

n = 20810298530643139779725379335557687960281905096107101411585220918672653323875234344540342801651123667553812866458790076971583539529404583369246005781146655852295475940942005806084842620601383912513102861245275690036363402134681262533947475193408594967684453091957401932685922178406769578067946779033282889429596341714417295489842047781388337010440309434639274398589029236213499110100040841426995862849012466514170374143655264739023758914247116354182164550612494432327931655944868705959874670536031052370968354394583880324756639698871918124498442308334232127034553164826483441746719644515097123067550594588348951855987
x = 66138689143868607947630785415331461127626263390302506173955100963855136134289233949354345883327245336547595357625259526618623795152771487180400409991587378085305813144661971099363267511657121911410275002816755637490837422852032755234403225128695875574749525003296342076268760708900752562579555935703659615570
r = 1024

print(explode(n,x,r))

运行后就能得到 p 和 q 的值,直接计算 d 然后进行解密:

1
2
3
4
5
6
7
8
9
10
11
12
13
from Crypto.Util.number import long_to_bytes, inverse

p = 121707024037268877853347577606022680727723421754483145354598542291389059730952536897407296725631390435306824149329251450428520017032068370905491236371588783551854860933656246846861645834009102275363106544337746297119821339365287420703692873394398852690091625453178968493127766149991473384937200789954598163517
q = 170986832479534233007906048950464510414382588164533889416767650420928742690929190093999799507883047422413122991286355305384227808800633111611572663168246588357071419165779511128259447564377245832827901688451015954867004306626552500789867499455455629032408110167560346510245108938981288797349665759162752876911
c = 15294238831055894095745317706739204020319929545635634316996804750424242996533741450795483290384329104330090410419090776738963732127756947425265305276394058773237118310164375814515488333015347737716139073947021972607133348357843542310589577847859875065651579863803460777883480006078771792286205582765870786584904810922437581419555823588531402681156158991972023042592179567351862630979979989132957073962160946903567157184627177910380657091234027709595863061642453096671316307805667922247180282486325569430449985678954185611299166777141304330040782500340791721548519463552822293017606441987565074653579432972931432057376
e = 65537
n = p * q

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)

print(long_to_bytes(m).decode('utf-8'))

运行后得到 Flag:flag{7428fbd7-639b-11ee-b51b-64d69af3cb76}

easymath

很显然这题是一个伪随机数生成器(PseudoRandom Number Generator),题目给了 PRNG 的代码以及其 7 个连续状态。其中最重要的是 PRNG 的计算公式:当前状态结合 a、b 和 n 一起计算出下一个状态

1
S_{n+1} = (a \times S_{n} + b) \ mod \ n

而题目既没有提供 a 和 b,甚至没有告知 n,但是显然有数学方法可以解决这个问题。参照这篇文章的内容,使用下面的代码可以进行攻击得到 n 的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from Crypto.Util.number import *
from functools import reduce
from sympy import factorint as factor

data = [...]

delta = [d1 - d0 for (d0, d1) in zip(data, data[1:])]
m_mul = [d0 * d2 - d1 * d1 for (d0, d1, d2)
in zip(delta, delta[1:], delta[2:])]
m = reduce(GCD, m_mul)
factors = factor(m)
if len(factors) > 1:
for (prime, degree) in factors:
if size(prime) == 256:
m = prime
break
m //= (prime**degree)
print(m)

运行程序后得到 n 的值,参考这篇文章的数学运算,可以得到下面的代码计算出 a 和 b 的值:

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

s = [...]

n = 312769358113056565136009929613710078319
a = (s[1]-s[2])*inverse(s[0]-s[1], n)
b = (s[1]-(a*s[0])) % n

for i in range(2, 6):
c = (s[i]*a+b) % n
assert c == s[i+1]

print(f"n = {n}", f"a = {a}", f"b = {b}", sep="\n")

现在已经得到了所有值,接下来直接计算下一个状态:

1
2
3
4
5
6
7
n = 312769358113056565136009929613710078319
a = 502544169271820386689252632658814094367301437045954876397315583623220656128
b = 11856650155037935400579201826386146297
s = 201319433320428898153580935653793106657

c = (s * a + b) % n
print("flag{"+str(c)+"}")

运行后得到 Flag:flag{302184756857257140159769321021979097116}

ez_rsa

不难发现 Flag 被拆成了两部分分别加密,先看第一部分:第一部分的 n 由 32 个较小的质数得到,所以直接进行分解得到

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
P20 = 10203735303764112277
P20 = 11718181938374860349
P20 = 16340211116882594287
P20 = 10621161426185076191
P20 = 15622487550947237203
P20 = 16651625235320957803
P20 = 12712357180113548549
P20 = 11777892065426651999
P20 = 11964584391817142269
P20 = 15616762946597906161
P19 = 9281508366366115669
P20 = 17075632607344331131
P20 = 10100522426677320149
P20 = 13498192768855092449
P19 = 9356350172425710359
P20 = 10436802938040427139
P20 = 10126802520926958821
P20 = 14198042938738648387
P20 = 17088379813205887661
P20 = 14147604789494386003
P20 = 10635881647150245973
P20 = 11502613740816749197
P20 = 10270880245559150279
P19 = 9723861249937499279
P20 = 15774106340553595249
P20 = 13618885037077024279
P20 = 10040612110882504553
P20 = 13428970346605599557
P20 = 10986943768724409089
P19 = 9261040693807289549
P20 = 16946507762934111301
P20 = 16880270107514803247

直接解密就可以了:

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

f = open("ez_rsa.1.txt", "r").read()
f = f.split("\n")
f = [int(_.split(" = ")[1]) for _ in f]

a = 1
for i in f:
assert isPrime(i)
a *= (i-1)

n = 114107341297408283801468814470303963122122556489590451040619457052827864984505912502462030175984161431709841571908269123131659496812467145870607611968843929870716066046232009282431653653484798819370087696248364531531706249180822839879862098012984590503284615395588919199545142177727328844260380842155437987767067800740569616584597507776426572206990858918111272636507821551592564540694671795374831548677720629329358177802890287837056940407030212276399942462042866947423728888561392653713356355778914658317507319575084393752755452971007289968044006561357799908892371839922838486713582082980752194204224263283004373
c = 28535916699190273475273097091422420145718978597126134891571109006456944397344856577421369324831702083810238921719657496747722337086131545474384253288151783029981352196506749672783866527948391034258269669654392993063423671431837882584570973320095601407578443348352802850496429240170710269529489900871208384711844617081275862971410246759090936379744946527813691945129059991795202769186014306943707223831130752782380563227353615164053563120572722464543812139164048342504963081408349934180883607554389607335607410546630525512019818062185681153477671373000186961748278118124044645584490544698827467815360888525822167

d = inverse(65537, a)
print(long_to_bytes(pow(c, d, n)).decode('ascii'))

运行后得到 Flag 的前半部分:flag{05929ec9778ed7 。至于第二部分,则可以采用共模攻击:

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
import gmpy2
import libnum

e1 = 13
e2 = 15
c1 = 5640630966585093229374938575158853304507369792931959909038819773057666482368490365383634362421839045569190487785222799103423460816096797210546343809620912249021763787314569982909943181390882015170344954037813745251119237402775124991005154299085147091159741067430623420349690886728161235034687649593258746455165172528681627568611599473627285223154284756417744280966157271904828156564067870877521824545300153084830020169048653830385763172792698591998191641849931039720453035065355411394516308865955772746815765864888631258825704788352584540380169938419618543124830541663995097651872542381
c2 = 5481001445755770090420425478456880914921441486935672376394423326451811448703288166341447356603281843336826624725965666634194700496514262129376916108926167953996689011980280761368893884042609095616407660087448963015169181749124738976578495911295096014725354350167650232970262765851074146687931181216305972147994236689422572940877763047930111954798962097847426932730342258169023809341164876019161104439561164839132092594444017039073155506935768658830659965630065643619399324102814118128802834719820426253836317043818687888302054465994498115387703382090351794495827905499417861507007863378916334790750453883661675063377

n = 21235204662158833223664424963408105101885570855652885953922511758363954474947609854216589644512813634294435585894296340005122907229365513346971631594453999584706013889403572150499529308966742992668850443386284277210686717652643585324255759216699733045642544284406720854291604837774882256435503827543483289606177965628162259184958789025311291796067574924595051311298594432767265114154138693108465671184854794167878031822162731921299518989845784744659944947091213703810190708463199067553747177712259911724424547999547534441790125049383068377243727588278432796727885216967953646999183906479537750330738956233695342750567

def rsa_def(e1, e2, c1, c2, n):
e1, e2, c1, c2, n = int(e1), int(e2), int(c1), int(c2), int(n)
print("e1,e2:", e1, e2)
print(gmpy2.gcd(e1, e2))
s = gmpy2.gcdext(e1, e2)
print(s)
s1 = s[1]
s2 = s[2]
if s1 < 0:
s1 = - s1
c1 = gmpy2.invert(c1, n)
elif s2 < 0:
s2 = - s2
c2 = gmpy2.invert(c2, n)
m = (pow(c1, s1, n) * pow(c2, s2, n)) % n
return int(m)

m = rsa_def(e1, e2, c1, c2, n)
print(m)
print(libnum.n2s(int(m)).decode())

运行后得到 Flag 后半部分:39d94ee1a77b742714} 。所以 Flag:flag{05929ec9778ed739d94ee1a77b742714}

e?

事实上这个 e 就是加密时候所用的 e,此题并不是爆破 e。因为 e 并不是质数,所以不能用正常的 RSA 解密方法进行解密。查的相关情况的解密代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from gmpy2 import gcd, invert, iroot
from Crypto.Util.number import long_to_bytes

def decrypt(p, q, e, c):
n = p * q
phi = (p - 1) * (q - 1)
t = gcd(e, phi)
d = invert(e // t, phi)
m = pow(c, d, n)
msg = iroot(m, t)
if msg[1]:
print(long_to_bytes(msg[0]))

p = 70724362259337647663584082414795381346569735601816096923682814277857463878289
q = 114427188167532721707398034034072867253267857672869034942206947096293901917007
e = 1314
c = 4308122681135507736058122041934864039713319497673888928736468819190185301630702240416683093700232966794026900978699666246019059398861283337865339404916304

decrypt(p, q, e, c)

运行后得到 Flag:flag{This_e_is_real_or_not}

factorizing_n

题目说分解 n,去 FactorDB 查了一下,n 是一个质数的五次方。直接上代码吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from Crypto.Util.number import long_to_bytes, inverse
import sympy

c = 52409805591744226507807531465616894934028463651864630447934395956954575834603756391651746535033902964658694070544877880970130028487381287088425209448038533705903737694267359561133766799228825599943891152463160326583722749586721691729062524310148743637505134465210906856660867852927837112666513674858029892207902196213784902541173835447263733760225682942461048573387925463479672527491229113710629340960375692432470493054415657845868577650170648157402682163577152288432313996310562452677399267755695644659367792066311336521698894993982901657735586844358679888210537898629281625526455444811591386493005341435516094660429968084363084301878446471676122069724608083578102382181382107225473535696274374370868301830807644939881080301668756603163431000745972823980427048672732291
n = 226515252384227990547287743140613580056836242860947832749754689048997071950972581790210817523352001702907675581567498443649554801433663166425134375454937126656357069687274036935331269594383360450823787099121079436459236734336130768046337169817940540921822023269188752420603975467384377614321048859304185067329741055517464271746238143742661897809442359331215501438861121047081117632626097939097519866099140569819965948998542652908170134545593659233229897003698175558888336706474178958535138595687148003367152624421106553412886263257022809480187410133186189435436294593588009551451899398811758511878324326255293307347560753524372663257044426744744426759970254203341706284024734042826158828749144322843934985927079504722440497388146240627249465363931951790326885478025237643
a = 11776588228599764849559519654482976956833367474471407292255776713760090338489966385328569279135095351660161277221351884258247731394014018172166064062551483
e = 65537

a_minus_1 = a - 1
a_power_4 = a**4

phi_n = a_minus_1 * a_power_4
d = inverse(e, phi_n)

print(long_to_bytes(pow(c, d, n)).decode('ascii'))

运行后得到 Flag:flag{1f95f530f85b940db810fc917607ee22}

哈希猫

阅读代码我们可以得知,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
import hashlib
from itertools import product

def bump_hash(hash_function, target_length: int, target_hash: str):
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'"
for candidate in product(charset, repeat=target_length):
candidate_str = ''.join(candidate)
if hash_function(candidate_str.encode()).hexdigest() == target_hash:
return candidate_str
return "."*target_length

print("flag{", end="")
print(bump_hash(hashlib.sha224, 2, "52cef2ca1e9afa0f8324650342107494cbc67a02c281aaaf7fa39a68"), end="")
print(bump_hash(hashlib.md5, 3, "488c48a970381b744a00a1361a9d73cc"), end="")
print(bump_hash(hashlib.sha224, 2, "08c01a630693b07c4c9cc117ec4c736b13bbbf9a250dea4bb6fc921f"), end="")
print(bump_hash(hashlib.sha384, 2, "f922469e4aaeeaefa4e504c952fd42917fc9178be1f9d850354c7c9972bde07a0c0c6d73426030f3f9ff2c9bbd17a814"), end="")
print(bump_hash(hashlib.sha512, 2, "4dd6cf34aec0721cf1289fee6219fb385ba2d94a812ea7af7f6707856c2cd4353376ba28975cdede220132a02093c1be025cc7f2f96cab3738230c870bed10c8"), end="")
print(bump_hash(hashlib.sha224, 2, "24296a0d1555ad424b04dd5f6268c5613dae32cde8a469ca8c9065b9"), end="")
print(bump_hash(hashlib.sha224, 2, "15d46f8eae648f5945c4605b15e0507836ee1251b74de2e95bf9394d"), end="")
print(bump_hash(hashlib.sha512, 2, "06d7f10221568b60a8e807ba4076c8de0a21964672cccfe6502bc9bc7fce0cb2a9a783c0126139654a9e378179bc4ca6c27cf2a373c176e168d681d3c7d445d0"), end="")
print(bump_hash(hashlib.sha256, 2, "e2eca64bd73ce8672efc022c65d7a599f8bbfc1e216a6fe9d08f82e20061d618"), end="")
print(bump_hash(hashlib.sha512, 2, "95a643e631efd3bb1ca6447862751ce2d28d6eaf06c93eda1467de18d8421f1d140b49d989790c04ac2a9d54557ad4d5505de1104288cf9f2c91954e2edf92a5"), end="")
print(bump_hash(hashlib.sha224, 2, "67701fc8d94bc2a16190c7772e995ec8bf4de7d994f98dad3b4a7e7f"), end="")
print(bump_hash(hashlib.sha224, 2, "2c078bb825b7497237cc1eab056e7cef59ea09cedb35842e51969d79"), end="")
print(bump_hash(hashlib.md5, 3, "b887783bc1e6d92745a0fd158a64b68b"), end="")
print(bump_hash(hashlib.sha224, 2, "c931c2baed5528cf3fa607b964dc07b27ab874e0fa881acbf77ffd0d"), end="")
print(bump_hash(hashlib.sha256, 2, "38d25a3673675f496c0d4161146426fb6019a35b59bc843e0425e2a49d5d84f9"), end="")
print(bump_hash(hashlib.sha224, 2, "08b21d02a9127423cbcde6ef1c68ec4bf53c240544ff23b444a1ff56"), end="")
print(bump_hash(hashlib.sha384, 2, "27ecdc4955f474abe88ccc75d1de00a4002d977e186e9abcc605e5e7725695635a756e1c42d677fcd5e74c910ee474ef"), end="")
print(bump_hash(hashlib.sha1, 3, "98ff09ef130e5508ca8616f7f851c367c916a3f4"), end="")
print(bump_hash(hashlib.sha224, 2, "d1bec2939974bb5c790423049f7c4fa4eec976618c801003e657071c"), end="")
print(bump_hash(hashlib.md5, 2, "9d607a663f3e9b0a90c3c8d4426640dc"), end="")
print("}", end="")

运行后得到 Flag:flag{y0u've_c0Me_To_UNDeRsTanD_HASh_oTbCo4bFgDa3}

好好好!

已知 dp,直接开干:

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

for i in range(1, e):
if (dp*e-1) % i == 0:
if n % (((dp*e-1)//i)+1) == 0:
p = ((dp*e-1)//i)+1
q = n//(((dp*e-1)//i)+1)
phi = (q-1)*(p-1)
d = gp.invert(e, phi)
m = pow(c, d, n)

print(long_to_bytes(m))

运行后得到:

1
7U25DUJJ7USYATEN5SREOFFG5NY57FPS77U5DFPY54JEG3NYKWSYA3YD5CXYTTNW53QS====

这是 Base32,但却是自定义字母表的 Base32。题目中已经给出了部分字母表,剩下的直接爆破:

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

src = "7U25DUJJ7USYATEN5SREOFFG5NY57FPS77U5DFPY54JEG3NYKWSYA3YD5CXYTTNW53QS===="

STANDARD_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
REMAIN_ALPHABET = 'DFJNOU257'

for p in itertools.permutations(REMAIN_ALPHABET):
CUSTOM_ALPHABET = f"{p[0]}{p[1]}{p[2]}EGK{p[3]}MAPZ{p[4]}{p[5]}3TISLXYHW{p[6]}B4{p[7]}R{p[8]}6CQV"
DECODE_TRANS = str.maketrans(CUSTOM_ALPHABET, STANDARD_ALPHABET)
dec = base64.b32decode(src.translate(DECODE_TRANS))
try:
assert dec[0:4] == b'flag'
print(dec.decode('ascii'))
except:
pass

得到 Flag:flag{fa48a440-d0ff-0c2a-366243-a46b7e7853}