この大会は2022/12/3 2:00(JST)~2022/12/5 2:00(JST)に開催されました。
今回もチームで参戦。結果は4915点で475チーム中24位でした。
自分で解けた問題をWriteupとして書いておきます。
Join Discord! (Informational)
Discordに入り、#announcementsチャネルのメッセージを見ると、フラグが書いてあった。
TUCTF{7h4nk5_f0r_j01n1n6_u5}
Leisurely Math (Programming)
$ nc chals.tuctf.com 30202 8903 + 1765 - 8007 Answer:
繰り返し、四則演算の答えをevalで答えていけばよいが、途中でスクリプトを変更するコードが出てくるので、その場合はevalを使わないようにする。
#!/usr/bin/env python3 import socket import string def recvuntil(s, tail): data = b'' while True: if tail in data: return data.decode() data += s.recv(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('chals.tuctf.com', 30202)) i = 1 while True: print('Round: %d' % i) data = recvuntil(s, b'\n').rstrip() print(data) if data.startswith('exec'): data = recvuntil(s, b'\n').rstrip() print(data) ans = eval(data) elif data[0] in string.digits: ans = eval(data) else: break data = recvuntil(s, b': ') print(data + str(ans)) s.sendall(str(ans).encode() + b'\n') data = recvuntil(s, b'\n').rstrip() print(data) i += 1
実行結果は以下の通り。
Round: 1 5996 - 2119 * 1307 Answer: -2763537 Correct! Round: 2 8663 - 8754 - 9806 * 1984 + 382 * 7771 - 7217 + 4166 Answer: -16489724 Correct! Round: 3 7875 - 4127 + 825 + 2391 * 5861 * 8656 - 9523 * 4459 * 3567 * 2936 Answer: -444582064432955 Correct! : : Round: 217 384 * 2989 + 3824 + 6135 - 1115 - 6785 - 8299 - 95 + 4441 + 414 Answer: 1146296 Correct! Round: 218 exec('\nimport os\nscript_path = os.path.realpath( __file__ )\nnew_program = ""\nwith open( script_path, "r" ) as f:\n lines = f.readlines()\n for line in lines:\n for char in line:\n if char.isalpha():\n new_program += chr( ord( char ) + 1 )\n else:\n new_program += char\nwith open( script_path, "w" ) as f:\n f.write( new_program )\nos.system( "cls" )\nos.system( "clear" )\n') 5722 - 2913 - 2852 + 4059 + 1274 - 2961 + 979 + 1529 - 9484 + 4831 - 330 Answer: -146 Correct! Round: 219 3886 * 6860 * 7266 - 4660 * 2981 + 6424 * 7058 - 7752 - 7666 Answer: 193728171074 Correct! : : Round: 227 7644 * 165 - 591 - 3277 - 5040 - 2399 + 6162 + 6874 Answer: 1262989 Correct! Round: 228 3299 + 2869 - 698 - 1912 - 1759 * 7580 * 4449 Answer: -59319492222 Correct! Round: 229 Here is your flag: TUCTF{7h4nk5_f0r_74k1n6_7h1n65_4_l177l3_5l0w_4268285}
TUCTF{7h4nk5_f0r_74k1n6_7h1n65_4_l177l3_5l0w_4268285}
That One RSA Challenge (Cryptography)
$ nc chals.tuctf.com 30003 That one RSA Challenge: Options: 1) Generate RSA Message 2) Exit 1 Generating RSA... n:10683056179532275497494322908531698584344422075416105799583765788674095581794757581679062276473318546247611230358286388481761328254612195488217194458976062128428044702531786323379051979941573794294687702619017493990782102020021363739169973928110789262754216832205575535500949117118001027399864796224562441446926260573132225906490350769309555711559208398934760123161 e:5 c:8176566829021528930311087337684299656651175996237050248928778822664811561182426484128445467162985030874776007692440517236408539231151511454489256999578335906317713460573759316655060037794428043630027064839498917698728550477723280424358111591441943069024931967203574624902159252837306386334274180905622013082718527756027784085834099753091678523356301420646238112875 Options: 1) Generate RSA Message 2) Exit 1 Generating RSA... n:6887879171986104574373642945440619457908229375975304899880685868832943411735297206066352105744348146004806196756354114218116486611361043423428861682525854438882874870097416661654165321891064197049309913602081537960658790294231234627260856114161173287601067783735612151828577847781069158844998327582452213264058182688584580147443133837362042883406337342404940544361 e:5 c:4148676611576085237922195161446112435729578569070212737206322240063752390283190299422079072117944195256177533534862402415121898193828489180436429880219270889850632294941938463149292958581407387522369990049543234115761666709491486093520537162964731927621789946026980192125724639638737591303289779711057319610427896767911106583023234089933701878246800161241364129816 Options: 1) Generate RSA Message 2) Exit
eが5固定のようなので、n, cのペアを5つ集め、Hastad's Broadcast Attackで復号する。
#!/usr/bin/env python3 import socket from Crypto.Util.number import * from sympy.ntheory.modular import crt from gmpy2 import iroot def recvuntil(s, tail): data = b'' while True: if tail in data: return data.decode() data += s.recv(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('chals.tuctf.com', 30003)) ns = [] cs = [] for _ in range(5): data = recvuntil(s, b'Exit\n').rstrip() print(data) print('1') s.sendall(b'1\n') for i in range(9): data = recvuntil(s, b'\n').rstrip() print(data) if i == 3: n = int(data.split(':')[1]) ns.append(n) elif i == 7: c = int(data.split(':')[1]) cs.append(c) e = 5 me, _ = crt(ns, cs) m, success = iroot(me, e) assert success flag = long_to_bytes(m).decode() print(flag)
実行結果は以下の通り。
That one RSA Challenge: Options: 1) Generate RSA Message 2) Exit 1 Generating RSA... n:7889013948113429798278972302671539175301293488242917671552573119651777676116328810587304690958329450540775764834953963992797755174487687308119082196203088232372806787156332980818261513321073406761936392321253331199806081477118647282987638479107559162387137969310056422048619776021999170787496257959124072694480190136804267975007469172872410603181761147868732789957 e:5 c:5953486994469679770285994503441003952127560441626983862332695554856261594053423814133078554689506112962517950876539765501175542911909148343795214564714450128641479662515240905344017332659420683722785908359509378975375439950023220409444882621736638309408922366910705785098535747643112190526349426892500281359982963293081336555101529088051713582355893908594036408832 Options: 1) Generate RSA Message 2) Exit 1 Generating RSA... n:9781918828032202227301020862283271351666744219317849324603218722306039646724834308470648898200070746966872879113627123749676229395958888244888615900825777825042111873088592488800534542293607979803443131376966471789783530459733678199040741773600277818533651486052333491184170574402584256105767797180796009373317056502606910428112243052274480898092946461179057423431 e:5 c:8170113435944326464524075068289575750545358845793484288314334989819473883035099498726712329886195759849345290631801824127952665088605205896233921421311476593732620276426091140506800339155164805502668141006548253302511728247173162090233490098087729307680305536262452712013765780411609184894552826841667345058878520300233381003870355220059980005522578719569450573198 Options: 1) Generate RSA Message 2) Exit 1 Generating RSA... n:5769662059493037326838681424376503062239328448812114038636566871193778089935047505302884031942579397301957967677706758993329924467218343606856460050058650455316604846034176713296394496664662112653080400130696448468600679383659096811757444833061954008631101371962483132539367134706598643240571487668085947066434513349610075539154795764258384681522588385706325517619 e:5 c:3629592579037272026198717660412535408515221248858233088365765439386846963506043926673998695613192810556232586776023771897215004262441678528361237841398460322211633765670094194192859707971613533189413078948800691532583096972856427504235972329249902748645859657904398970632271043856293772688493268839788433269868362990626308290043238343210552466272424707569581194799 Options: 1) Generate RSA Message 2) Exit 1 Generating RSA... n:12672626983347050769700482064853150433107232512886489783526954121293704531127239705724436679877991425030448723475239879264611762869474150595506312823796777459367225473044132028457313494861340105891319860223889804606254706484908231895459388131011195397315857928409212368475959655401650638538494730190683372092522700229306705885837860397101516387633166140379688965427 e:5 c:7055583151890955925810944571879137791643669877164314487042597917025698562615723363540387754263336918660996676704894308928828731364030459670994591146698604908799175872744040737989020760386902071371620252469362467186297027528215014806530069665443574691178609031670559029122986166342612056477057241036987428886031827132962830849264673260937763122026859588753663803894 Options: 1) Generate RSA Message 2) Exit 1 Generating RSA... n:6208342415876278607018244913736867659243485506847518281452593363925200041710188544123513552854427547365398266478461164952411281118259679890135871403169129139461884659610613791173072313015077905720089254421440256014907704206795531671204245879459492289676230342806734749392407834860522922765749970031180284138983779570050788310689670216150054750074864358949046129999 e:5 c:1222563905891228016808738307424690658174508026564281099701998913991287576407461876171772734361400755177373008474472491999997009555847720114492657732087810911681880774108712182858615389688812655640172979228877810604313802042778266303319003129620789641852808910781536731922579153047856223486067540989712829237856211153768250987156120927668931277322063251279404888769 TUCTF{0bl1g4t0ry_RSA_chall_l0l}
TUCTF{0bl1g4t0ry_RSA_chall_l0l}
A Sheep Jumps Over Fence (Cryptography)
まずhexデコードする。すると、base64文字列になるので、デコードする。
111111111122222222223333333333444444444455555555556666 0123456789012345678901234567890123456789012345678901234567890123 TFiacmaraeinyghaU{swoegotctdprysCtiemsemauyctacsThslesfdsraropl}
転置暗号になっていて、16バイトごとに文字を結合していけば、フラグになる。
#!/usr/bin/env python3 from base64 import * with open('sheep.enc', 'r') as f: enc = eval(f.read()) length = (enc.bit_length() + 7) // 8 b64 = enc.to_bytes(length, 'big') print('[+] Decode 1:', b64.decode()) dec = b64decode(b64) print('[+] Decode 2:', dec.decode()) flag = '' for i in range(16): for j in range(len(dec) // 16): flag += chr(dec[i + j * 16]) print('[*] flag:', flag)
実行結果は以下の通り。
[+] Decode 1: VEZpYWNtYXJhZWlueWdoYVV7c3dvZWdvdGN0ZHByeXNDdGllbXNlbWF1eWN0YWNzVGhzbGVzZmRzcmFyb3BsfQ== [+] Decode 2: TFiacmaraeinyghaU{swoegotctdprysCtiemsemauyctacsThslesfdsraropl} [*] flag: TUCTF{thisisawelcomemessagefromdatasecurityandcryptographyclass}
TUCTF{thisisawelcomemessagefromdatasecurityandcryptographyclass}
More Effort (Cryptography)
暗号化処理の概要は以下の通り。
・rsa = RSA() ・rsa.p: 512ビット素数 ・rsa.s = 0 ・i: 1以上18000000未満に対して、以下を実行 ・rsa.s += pow(i, rsa.p-2, rsa.p) ・rsa.s = rsa.s % rsa.p ・rsa.q: rsa.sの次の素数 ・rsa.n = rsa.p * rsa.q ・rsa.phi = (rsa.p - 1) * (rsa.q - 1) ・rsa.e = 65537 ・rsa.d = pow(rsa.e, -1, rsa.phi) ・rsa.p、rsa.eを出力 ・c = pow(<フラグの数値>, rsa.e, rsa.n) ・cを出力
以下の式が成り立ち、右辺の方の計算の方が早いので、置き換えて、sを割り出し、qを算出し復号する。
pow(i, rsa.p-2, rsa.p) = pow(i, -1, rsa.p)
#!/usr/bin/env python3 from Crypto.Util.number import * import gmpy2 p = 11545307730112922786664290405312669819594345207377186481347514368962838475959085036399074594822885814719354871659183685801279739518405830244888530641898849 e = 65537 c = 114894293598203268417380013863687165686775727976061560608696207173455730179934925684529986102237419507146768083815607566149240438056135058988227916482404733131796310418493418060300571541865427288945087911872630289527954636816219365941817260989104786329938318143577075200571833575709614521758701838099810751 s = 0 for i in range(1, 18000000): s += pow(i, -1, p) s = s % p q = gmpy2.next_prime(s) n = p * q phi = (p - 1) * (q - 1) e = 65537 d = pow(e, -1, phi) m = pow(c, d, n) flag = long_to_bytes(m).decode() print(flag)
TUCTF{syqow82pam_%shsjQF; ^7dagsWCpsp_#aes}
Two Part Hashing (Cryptography)
XORと推測し、鍵を求め、PDFを復号する。
#!/usr/bin/env python3 with open('crypto.enc.pdf', 'rb') as f: enc = f.read() PDF_HEAD = b'%PDF-1.' key = [] for i in range(len(PDF_HEAD)): key.append(enc[i] ^ PDF_HEAD[i]) assert key[:3] == key[4:7] key = key[:4] dec = b'' for i in range(len(enc)): dec += bytes([enc[i] ^ key[i % len(key)]]) with open('flag.pdf', 'wb') as f: f.write(dec)
復号したPDFには、ハッシュに関する内容が書かれ、どこにもフラグは見当たらない。PDFのプロパティを見ると、作成者に以下が設定されている。
nc chal.tuctf.com 30000
$ nc chal.tuctf.com 30000 fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5 [ + ] Welcome to the hash oracle! [ + ] Enter anything you want to hash, and I'll hash it for you! [ + ] 1. Hash [ + ] 2. Get hidden flag [ + ] 3. Exit [ + ] Enter your option: 1 [ + ] Enter data to hash: 1 [ + ] Hashing... [ + ] Hashed data: ba89 $ nc chal.tuctf.com 30000 fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5 [ + ] Welcome to the hash oracle! [ + ] Enter anything you want to hash, and I'll hash it for you! [ + ] 1. Hash [ + ] 2. Get hidden flag [ + ] 3. Exit [ + ] Enter your option: 2 [ + ] Hidden flag: fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5
このハッシュアルゴリズムからフラグを求める必要があるようだ。
$ nc chal.tuctf.com 30000 fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5 [ + ] Welcome to the hash oracle! [ + ] Enter anything you want to hash, and I'll hash it for you! [ + ] 1. Hash [ + ] 2. Get hidden flag [ + ] 3. Exit [ + ] Enter your option: 1 [ + ] Enter data to hash: 11 [ + ] Hashing... [ + ] Hashed data: 9362 $ nc chal.tuctf.com 30000 fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5 [ + ] Welcome to the hash oracle! [ + ] Enter anything you want to hash, and I'll hash it for you! [ + ] 1. Hash [ + ] 2. Get hidden flag [ + ] 3. Exit [ + ] Enter your option: 1 [ + ] Enter data to hash: 12 [ + ] Hashing... [ + ] Hashed data: 9463 $ nc chal.tuctf.com 30000 fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5 [ + ] Welcome to the hash oracle! [ + ] Enter anything you want to hash, and I'll hash it for you! [ + ] 1. Hash [ + ] 2. Get hidden flag [ + ] 3. Exit [ + ] Enter your option: 1 [ + ] Enter data to hash: 13 [ + ] Hashing... [ + ] Hashed data: 9564 $ nc chal.tuctf.com 30000 fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5 [ + ] Welcome to the hash oracle! [ + ] Enter anything you want to hash, and I'll hash it for you! [ + ] 1. Hash [ + ] 2. Get hidden flag [ + ] 3. Exit [ + ] Enter your option: 1 [ + ] Enter data to hash: 111 [ + ] Hashing... [ + ] Hashed data: 9362ba89 $ nc chal.tuctf.com 30000 fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5 [ + ] Welcome to the hash oracle! [ + ] Enter anything you want to hash, and I'll hash it for you! [ + ] 1. Hash [ + ] 2. Get hidden flag [ + ] 3. Exit [ + ] Enter your option: 1 [ + ] Enter data to hash: 1211 [ + ] Hashing... [ + ] Hashed data: 94639362 $ nc chal.tuctf.com 30000 fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5 [ + ] Welcome to the hash oracle! [ + ] Enter anything you want to hash, and I'll hash it for you! [ + ] 1. Hash [ + ] 2. Get hidden flag [ + ] 3. Exit [ + ] Enter your option: 1 [ + ] Enter data to hash: 21 [ + ] Hashing... [ + ] Hashed data: 9563
2バイトごとに対応するhashが決まるようだ。もう少し規則を見てみる。
$ nc chal.tuctf.com 30000 fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5 [ + ] Welcome to the hash oracle! [ + ] Enter anything you want to hash, and I'll hash it for you! [ + ] 1. Hash [ + ] 2. Get hidden flag [ + ] 3. Exit [ + ] Enter your option: 1 [ + ] Enter data to hash: !! [ + ] Hashing... [ + ] Hashed data: 6342 $ nc chal.tuctf.com 30000 fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5 [ + ] Welcome to the hash oracle! [ + ] Enter anything you want to hash, and I'll hash it for you! [ + ] 1. Hash [ + ] 2. Get hidden flag [ + ] 3. Exit [ + ] Enter your option: 1 [ + ] Enter data to hash: "! [ + ] Hashing... [ + ] Hashed data: 6543 $ nc chal.tuctf.com 30000 fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5 [ + ] Welcome to the hash oracle! [ + ] Enter anything you want to hash, and I'll hash it for you! [ + ] 1. Hash [ + ] 2. Get hidden flag [ + ] 3. Exit [ + ] Enter your option: 1 [ + ] Enter data to hash: #! [ + ] Hashing... [ + ] Hashed data: 6744
1バイト目のASCIIコードを1増やすと、hashの1バイト目は2増え、2バイト目は1増える。
$ nc chal.tuctf.com 30000 fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5 [ + ] Welcome to the hash oracle! [ + ] Enter anything you want to hash, and I'll hash it for you! [ + ] 1. Hash [ + ] 2. Get hidden flag [ + ] 3. Exit [ + ] Enter your option: 1 [ + ] Enter data to hash: !" [ + ] Hashing... [ + ] Hashed data: 6443 $ nc chal.tuctf.com 30000 fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5 [ + ] Welcome to the hash oracle! [ + ] Enter anything you want to hash, and I'll hash it for you! [ + ] 1. Hash [ + ] 2. Get hidden flag [ + ] 3. Exit [ + ] Enter your option: 1 [ + ] Enter data to hash: !# [ + ] Hashing... [ + ] Hashed data: 6544 $ nc chal.tuctf.com 30000 fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5 [ + ] Welcome to the hash oracle! [ + ] Enter anything you want to hash, and I'll hash it for you! [ + ] 1. Hash [ + ] 2. Get hidden flag [ + ] 3. Exit [ + ] Enter your option: 1 [ + ] Enter data to hash: ab [ + ] Hashing... [ + ] Hashed data: 25c3 $ nc chal.tuctf.com 30000 fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5 [ + ] Welcome to the hash oracle! [ + ] Enter anything you want to hash, and I'll hash it for you! [ + ] 1. Hash [ + ] 2. Get hidden flag [ + ] 3. Exit [ + ] Enter your option: 1 [ + ] Enter data to hash: zz [ + ] Hashing... [ + ] Hashed data: 6ff4
2バイト目のASCIIコードを1増やすと、hashの1バイト目は1増え、2バイト目は1増える。
以上から以下のことが言える。
・hashの1バイト目 = 1バイト目のASCIIコード * 2 + 2バイト目のASCIIコード ・hashの2バイト目 = 1バイト目のASCIIコード + 2バイト目のASCIIコード
255を超えた場合は255で割った余りになる。
このことから逆算し、フラグのハッシュからフラグを復号する。
#!/usr/bin/env python3 def rev_hash(s): code1 = int(s[:2], 16) code2 = int(s[2:], 16) char1 = code1 - code2 if char1 < 0: char1 += 255 char2 = code2 - char1 return chr(char1) + chr(char2) flag_hash = 'fda9da9708c1d7a2d4a038cbdfaa3acc059cd29dd09fcb95049d4ed69f6ba36e9c6a53d5' flag = '' for i in range(0, len(flag_hash), 4): flag += rev_hash(flag_hash[i:i+4]) print(flag)
復号結果は以下の通り。
TUCTF{5m4ll_5um_h45h1n6_f7w_475928}X
最後についている"X"を削除すれば、フラグになる。
TUCTF{5m4ll_5um_h45h1n6_f7w_475928}
Unmix The Flag (Cryptography)
問題文に以下の点字が書かれている。
⠱⠁ ⠹⠣ ⠱⠹ ⠱⠁ ⠹⠣ ⠹⠳ ⠱⠁ ⠹⠣ ⠹⠪ ⠱⠁ ⠹⠣ ⠱⠩ ⠹⠣ ⠱⠩ ⠹⠱ ⠻⠁ ⠫⠩ ⠫⠡ ⠻⠻ ⠹⠣ ⠱⠩ ⠹⠱ ⠻⠁ ⠻⠪ ⠻⠁ ⠻⠱ ⠫⠡ ⠻⠻ ⠫⠡ ⠫⠩
GS-8 Brailleとしてhttps://www.dcode.fr/gs8-braille-codeでデコードする。
5a42545a42485a42495a42534253457a6361774253457a797a7561776163
hexデコードする。
$ echo 5a42545a42485a42495a42534253457a6361774253457a797a7561776163 | xxd -r -p ZBTZBHZBIZBSBSEzcawBSEzyzuawac
フラグにはおそらく"_"が含まれているので、numShiftをブルートフォースし、"CTF"が含まれているものを探す。あとは逆順で復号していけば、フラグがわかる。
#!/usr/bin/env python3 import string upperFlag = string.ascii_uppercase[:26] lowerFlag = string.ascii_lowercase[:26] MIN_LETTER = ord("a") MIN_CAPLETTER = ord("A") def unmix(oneLetter, num): if(oneLetter.isupper()): word = ord(oneLetter) - MIN_CAPLETTER shift = ord(num) - MIN_CAPLETTER return upperFlag[(word - shift) % len(upperFlag)] if(oneLetter.islower()): word = ord(oneLetter) - MIN_LETTER shift = ord(num) - MIN_LETTER return lowerFlag[(word - shift) % len(lowerFlag)] def unpuzzled(puzzle): data = '' i = 0 while i < len(puzzle): if puzzle[i].isupper(): if puzzle[i:i+3] == 'CTF': data += '_' else: b1 = '{0:05b}'.format(upperFlag.index(puzzle[i])) b2 = '{0:05b}'.format(upperFlag.index(puzzle[i+1])) b3 = '{0:05b}'.format(upperFlag.index(puzzle[i+2])) data += chr(int(b1 + b2 + b3, 2)) i += 3 if puzzle[i].islower(): b1 = '{0:01x}'.format(lowerFlag.index(puzzle[i])) b2 = '{0:01x}'.format(lowerFlag.index(puzzle[i+1])) data += chr(int(b1 + b2, 16)) i += 2 return data enc = 'ZBTZBHZBIZBSBSEzcawBSEzyzuawac' for numShift in lowerFlag: unmixed = '' for count, alpha in enumerate(enc): unmixed += unmix(alpha, numShift) if 'CTF' in unmixed: break flag = unpuzzled(unmixed) print(flag)
復号結果は以下の通り。
THIS_is_easy
TUCTF{THIS_is_easy}