SHELL CTF 2022 writeups

Sanity Check

  • 10 points

  • Problem Description

    • Check the #announcement channel of the discord server.
  • Solution

    • Found the flag in the discord server

How to defeat a dragon

  • 100 points

  • Problem Description

    • Dragonairre,the dragon with the hexadecimal head has attacked the village to take revenge on his last defeat,we need to get the ultimate weapon. Flag Format : SHELLCTF{}.
  • Given File

    • vault
  • Solution

    • Check file

    • Disassemble & Decompile & Reverse

      • main

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        55
        56
        57
        58
        undefined8 main(void)
        {
        long in_FS_OFFSET;
        int local_7c;
        undefined8 local_78;
        undefined8 local_70;
        undefined8 local_68;
        undefined8 local_60;
        undefined8 local_58;
        undefined8 local_50;
        undefined8 local_48;
        undefined8 local_40;
        undefined8 local_38;
        undefined8 local_30;
        undefined8 local_28;
        undefined8 local_20;
        undefined4 local_18;
        long local_10;

        local_10 = *(long *)(in_FS_OFFSET + 0x28);
        local_78 = 0x4654434c4c454853;
        local_70 = 0x343534383433357b;
        local_68 = 0x3434353334633463;
        local_60 = 0x3535333133623736;
        local_58 = 0x3336373333323566;
        local_50 = 0x3631333533323733;
        local_48 = 0x3333336635373665;
        local_40 = 0x3766333937333734;
        local_38 = 0x7d64;
        local_30 = 0;
        local_28 = 0;
        local_20 = 0;
        local_18 = 0;
        printf("Help us defeat the dragon!! Enter the code:");
        __isoc99_scanf(&DAT_00102034,&local_7c);
        if (local_7c == 0x10f2c) {
        printf("Yeahh!!,we did it,We defeated the dragon.Thanks for your help here\'s your reward : %s",
        &local_78);
        }
        else {
        if (local_7c == 0x45) {
        printf("Nice,but this is not the code :(.");
        }
        else {
        if (local_7c == 0x1a4) {
        printf("Bruh!! Seriously?");
        }
        else {
        printf("wron..aaaaaahhhhhhhh");
        }
        }
        }
        if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
        /* WARNING: Subroutine does not return */
        __stack_chk_fail();
        }
        return 0;
        }

    • We need to satisfy (local_7c == 0x10f2c) to get the flag.

    • 0x10f2c = 69420

    • Enter 69420 to get the flag

    • Convert the numbers from hex to string to get the real flag

warmup

  • 100 points

  • Problem Descrition

    • Here's a quick rev challenge to get started. Reverse the binary to obtain the flag.

    • The flag format is shellctf{...}

  • Given File

    • warmup
  • Solution

    • Check file

    • Disassemble & Decompile & Reverse

      • main

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        55
        56
        57
        58
        59
        60
        61
        62
        63
        undefined8 main(void)

        {
        size_t input_str_len;
        long in_FS_OFFSET;
        int i;
        int maybe_real_flag [28];
        char input_flag [40];
        long local_10;
        bool check_valid_flag;

        local_10 = *(long *)(in_FS_OFFSET + 0x28);
        printf("enter the flag: ");
        __isoc99_scanf(&DAT_00102015,input_flag);
        input_str_len = strlen(input_flag);
        if (input_str_len == 0x1b) {
        maybe_real_flag[0] = 0x1cc;
        maybe_real_flag[1] = 0x1a0;
        maybe_real_flag[2] = 0x194;
        maybe_real_flag[3] = 0x1b0;
        maybe_real_flag[4] = 0x1b0;
        maybe_real_flag[5] = 0x18c;
        maybe_real_flag[6] = 0x1d0;
        maybe_real_flag[7] = 0x198;
        maybe_real_flag[8] = 0x1ec;
        maybe_real_flag[9] = 0x188;
        maybe_real_flag[10] = 0xc4;
        maybe_real_flag[11] = 0x1d0;
        maybe_real_flag[12] = 0x15c;
        maybe_real_flag[13] = 0x1a4;
        maybe_real_flag[14] = 0xd4;
        maybe_real_flag[15] = 0x194;
        maybe_real_flag[16] = 0x17c;
        maybe_real_flag[17] = 0xc0;
        maybe_real_flag[18] = 0x1c0;
        maybe_real_flag[19] = 0xcc;
        maybe_real_flag[20] = 0x1c8;
        maybe_real_flag[21] = 0x104;
        maybe_real_flag[22] = 0x1d0;
        maybe_real_flag[23] = 0xc0;
        maybe_real_flag[24] = 0x1c8;
        maybe_real_flag[25] = 0x14c;
        maybe_real_flag[26] = 500;
        check_valid_flag = true;
        for (i = 0; i < 0x1b; i = i + 1) {
        check_valid_flag = (bool)(check_valid_flag & maybe_real_flag[i] >> 2 == (int)input_flag[i]);
        }
        if (check_valid_flag) {
        puts("yes, that\'s it");
        }
        else {
        puts("nah that\'s not it");
        }
        }
        else {
        puts("wrong length");
        }
        if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
        /* WARNING: Subroutine does not return */
        __stack_chk_fail();
        }
        return 0;
        }

    • check_valid_flag must be true if the flag is valid.

    • get_flag.py

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      from pwn import *

      p = process("./warmup")

      input_str = b""
      input_str += bytes(chr(0x1cc >> 2), 'ascii')
      input_str += bytes(chr(0x1a0 >> 2), 'ascii')
      input_str += bytes(chr(0x194 >> 2), 'ascii')
      input_str += bytes(chr(0x1b0 >> 2), 'ascii')
      input_str += bytes(chr(0x1b0 >> 2), 'ascii')
      input_str += bytes(chr(0x18c >> 2), 'ascii')
      input_str += bytes(chr(0x1d0 >> 2), 'ascii')
      input_str += bytes(chr(0x198 >> 2), 'ascii')
      input_str += bytes(chr(0x1ec >> 2), 'ascii')
      input_str += bytes(chr(0x188 >> 2), 'ascii')
      input_str += bytes(chr(0xc4 >> 2), 'ascii')
      input_str += bytes(chr(0x1d0 >> 2), 'ascii')
      input_str += bytes(chr(0x15c >> 2), 'ascii')
      input_str += bytes(chr(0x1a4 >> 2), 'ascii')
      input_str += bytes(chr(0xd4 >> 2), 'ascii')
      input_str += bytes(chr(0x194 >> 2), 'ascii')
      input_str += bytes(chr(0x17c >> 2), 'ascii')
      input_str += bytes(chr(0xc0 >> 2), 'ascii')
      input_str += bytes(chr(0x1c0 >> 2), 'ascii')
      input_str += bytes(chr(0xcc >> 2), 'ascii')
      input_str += bytes(chr(0x1c8 >> 2), 'ascii')
      input_str += bytes(chr(0x104 >> 2), 'ascii')
      input_str += bytes(chr(0x1d0 >> 2), 'ascii')
      input_str += bytes(chr(0xc0 >> 2), 'ascii')
      input_str += bytes(chr(0x1c8 >> 2), 'ascii')
      input_str += bytes(chr(0x14c >> 2), 'ascii')
      input_str += bytes(chr(500 >> 2), 'ascii')

      print(b"input_str: " + input_str)

      p.send(input_str + b"\n")

      print(p.recvline())

      p.interactive()

    • Run get_flag.py and get the flag

tea

  • 268 points

  • Problem Description

    • It's tea time. The flag format is shellctf{...}
  • Given File

    • tea
  • Solution

    • Check file

    • Disassemble & Decompile & Reverse

      • main

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        undefined8 main(void)
        {
        size_t sVar1;

        boilWater();
        sVar1 = strlen(pwd);
        if (sVar1 == 0x20) {
        addSugar();
        addTea();
        addMilk();
        strainAndServe();
        }
        else {
        puts("wrong length");
        }
        return 0;
        }

      • boilWater

        1
        2
        3
        4
        5
        6
        void boilWater(void)
        {
        printf("Enter the flag: ");
        __isoc99_scanf(&DAT_00102019,pwd);
        return;
        }

      • addSugar

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        void addSugar(void)
        {
        size_t pwd_len;
        long in_FS_OFFSET;
        uint i;
        char pwd_part2_sugar;
        undefined8 local_50;
        undefined local_48;
        char pwd_part1;
        undefined8 local_30;
        undefined local_28;
        long local_20;

        local_20 = *(long *)(in_FS_OFFSET + 0x28);
        _pwd_part2_sugar = 0;
        local_50 = 0;
        local_48 = 0;
        _pwd_part1 = 0;
        local_30 = 0;
        local_28 = 0;
        i = 0;
        while( true ) {
        pwd_len = strlen(pwd);
        if (pwd_len <= (ulong)(long)(int)i) break;
        if ((i & 1) == 0) {
        strncat(&pwd_part1,pwd + (int)i,1);
        }
        else {
        strncat(&pwd_part2_sugar,pwd + (int)i,1);
        }
        i = i + 1;
        }
        strncat(&pwd_part2_sugar,&pwd_part1,0x11);
        strcpy(pwd,&pwd_part2_sugar);
        if (local_20 != *(long *)(in_FS_OFFSET + 0x28)) {
        /* WARNING: Subroutine does not return */
        __stack_chk_fail();
        }
        return;
        }

      • addTea

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        void addTea(void)
        {
        size_t pwd_len;
        ulong cur_index;
        long in_FS_OFFSET;
        char cal_val;
        int i;
        int half_pwd_len_16;
        undefined8 pwd_part_tea;
        undefined8 local_40;
        undefined8 local_38;
        undefined8 local_30;
        undefined local_28;
        long local_20;

        local_20 = *(long *)(in_FS_OFFSET + 0x28);
        pwd_part_tea = 0;
        local_40 = 0;
        local_38 = 0;
        local_30 = 0;
        local_28 = 0;
        i = 0;
        while( true ) {
        cur_index = (ulong)i;
        pwd_len = strlen(pwd);
        if (pwd_len >> 1 <= cur_index) break;
        cal_val = (char)(i / 2) * -3 + pwd[i];
        strncat((char *)&pwd_part_tea,&cal_val,1);
        i = i + 1;
        }
        pwd_len = strlen(pwd);
        half_pwd_len_16 = (int)(pwd_len >> 1);
        while( true ) {
        cur_index = (ulong)half_pwd_len_16;
        pwd_len = strlen(pwd);
        if (pwd_len <= cur_index) break;
        cal_val = (char)(half_pwd_len_16 / 6) + pwd[half_pwd_len_16];
        strncat((char *)&pwd_part_tea,&cal_val,1);
        half_pwd_len_16 = half_pwd_len_16 + 1;
        }
        strcpy(pwd,(char *)&pwd_part_tea);
        if (local_20 != *(long *)(in_FS_OFFSET + 0x28)) {
        /* WARNING: Subroutine does not return */
        __stack_chk_fail();
        }
        return;
        }

      • addMilk

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        55
        56
        57
        58
        59
        void addMilk(void)

        {
        size_t pwd_len;
        long in_FS_OFFSET;
        int i;
        char pwd_part1_milk;
        undefined8 local_a0;
        undefined8 local_98;
        undefined8 local_90;
        undefined local_88;
        char pwd_part2_milk;
        undefined8 local_70;
        undefined8 local_68;
        undefined8 local_60;
        undefined local_58;
        char pwd_part_milk;
        undefined8 local_40;
        undefined8 local_38;
        undefined8 local_30;
        undefined local_28;
        long local_20;

        local_20 = *(long *)(in_FS_OFFSET + 0x28);
        _pwd_part1_milk = 0;
        local_a0 = 0;
        local_98 = 0;
        local_90 = 0;
        local_88 = 0;
        _pwd_part2_milk = 0;
        local_70 = 0;
        local_68 = 0;
        local_60 = 0;
        local_58 = 0;
        _pwd_part_milk = 0;
        local_40 = 0;
        local_38 = 0;
        local_30 = 0;
        local_28 = 0;
        for (i = 0; (pwd[i] != '5' && (pwd_len = strlen(pwd), (ulong)(long)i < pwd_len)); i = i + 1) {
        strncat(&pwd_part1_milk,pwd + i,1);
        }
        for (; (pwd[i] != 'R' && (pwd_len = strlen(pwd), (ulong)(long)i < pwd_len)); i = i + 1) {
        strncat(&pwd_part2_milk,pwd + i,1);
        }
        for (; pwd_len = strlen(pwd), (ulong)(long)i < pwd_len; i = i + 1) {
        strncat(&pwd_part_milk,pwd + i,1);
        }
        pwd_len = strlen(&pwd_part1_milk);
        strncat(&pwd_part_milk,&pwd_part1_milk,pwd_len);
        pwd_len = strlen(&pwd_part2_milk);
        strncat(&pwd_part_milk,&pwd_part2_milk,pwd_len);
        strcpy(pwd,&pwd_part_milk);
        if (local_20 == *(long *)(in_FS_OFFSET + 0x28)) {
        return;
        }
        /* WARNING: Subroutine does not return */
        __stack_chk_fail();
        }

      • strainAndServe

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        void strainAndServe(void)
        {
        int iVar1;

        iVar1 = strcmp("R;crc75ihl`cNYe`]m%50gYhugow~34i",pwd);
        if (iVar1 == 0) {
        puts("yep, that\'s right");
        }
        else {
        puts("nope, that\'s not it");
        }
        return;
        }

    • User input will become R;crc75ihl`cNYe`]m%50gYhugow~34i if it is the right flag

      1
      2
      3
      4
      5
      flag ---- [addSugar] ---> flag2
      flag2 --- [addTea] -----> flag3
      flag3 --- [addMilk] ----> flag4

      flag4 is R;crc75ihl`cNYe`]m%50gYhugow~34i

    • We need to reverse the operations in addMilk , addTea , addSugar .

    • There is a problem. There are several answers when reversing the operations in addMilk .

    • In addMilk , the program splits flag3 into 3 part and reassembly the parts to generate flag4

      1
      2
      3
      4
      5
      part1: String with no '5'.
      part2: String starts with '5' and with no 'R'
      part3: String starts with 'R'

      flag4 = ( part3 + part1 + part2 )

      Notice that flag4 is just simply move part3 to the front. The length of part2 is knowned. If we know the length of part3, we can calculate the length of part1 immediately. So we can brute force part3's length.

      Why the length of part2 is knowned? Because (part1 + part2) is not modified. If we found a '5' in (part1 + part2), that '5' must be the start of part2. A the end of part2 is the end of flag4 , obviously.

    • reverse_get_flag.py

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      final_pwd_str = 'R;crc75ihl`cNYe`]m%50gYhugow~34i'
      pwd_len = len(final_pwd_str)
      print("final_pwd_str: " + final_pwd_str)
      print("len(final_pwd_str): " + str(pwd_len))

      for len_guess in range(32):

      pwd_milk_str1 = ""
      pwd_milk_str2 = ""
      pwd_milk_str3 = ""

      pwd_milk_str3_len_guess = len_guess
      i = 0
      if i < pwd_len:
      if final_pwd_str[i] == 'R':
      while i < pwd_milk_str3_len_guess:
      pwd_milk_str3 += final_pwd_str[i]
      i = i + 1
      while i < pwd_len and final_pwd_str[i] != '5':
      pwd_milk_str1 += final_pwd_str[i]
      i = i + 1
      if i < pwd_len:
      if final_pwd_str[i] == '5':
      while i < pwd_len:
      pwd_milk_str2 += final_pwd_str[i]
      i = i + 1

      # print("pwd_milk_str: " + pwd_milk_str1 + " " + pwd_milk_str2 + " " + pwd_milk_str3)
      # print("len: " + str(len(pwd_milk_str1)) + " " + str(len(pwd_milk_str2)) + " " + str(len(pwd_milk_str3)))
      # print("total len: " + str(len(pwd_milk_str1) + len(pwd_milk_str2) + len(pwd_milk_str3)))

      # print("\n---\n")

      milk_pwd_str = pwd_milk_str1 + pwd_milk_str2 + pwd_milk_str3
      pwd_tea_str1 = milk_pwd_str[0:16]
      pwd_tea_str2 = milk_pwd_str[16:32]
      # print(pwd_tea_str1 + pwd_tea_str2)

      i = 0
      while i < 16:
      pwd_tea_str1 = pwd_tea_str1[0:i] + chr(ord(pwd_tea_str1[i]) + (i // 2) * 3) + pwd_tea_str1[i+1:16]
      i = i + 1
      i = 0
      while i < 16:
      pwd_tea_str2 = pwd_tea_str2[0:i] + chr(ord(pwd_tea_str2[i]) - ((16 + i) // 6)) + pwd_tea_str2[i+1:16]
      i = i + 1

      # print(pwd_tea_str1 + " " + pwd_tea_str2)

      # print("\n---\n")

      tea_pwd_str = pwd_tea_str1 + pwd_tea_str2
      flag_list = []
      for i in range(32):
      flag_list.append("?")

      pwd_sugar_odd = tea_pwd_str[0:16]
      pwd_sugar_even = tea_pwd_str[16:32]

      # fill odd
      for i in range(16):
      flag_list[2 * i + 1] = pwd_sugar_odd[i]
      # fill even
      for i in range(16):
      flag_list[2 * i] = pwd_sugar_even[i]

      print(''.join(flag_list))

    • Run reverse_get_flag.py and grep the flag

Alien Communication

  • 100 points

  • Problem Description

    • Aliens are trying to communicate something. They belive in seeing more than what they are hearing. can you help us trying to decode what they are trying to say?
  • Given File

    • Alien_voice.wav
  • Solution

    • Seems like morse code, so throw the file to online morse code decoder: https://morsecode.world/international/decoder/audio-decoder-adaptive.html

    • Then we can get the flag

Tweeeet

  • 100 points

  • Problem Description

    • What are they trying to say?

    • Flag Format: SHELL{SOMETHINGHERE}

  • Given File

    • image.jpeg
  • Solution

    • Open image.jpeg and we can see birds...

    • Go to birds-on-a-wire-cipher online decoder ( https://www.dcode.fr/birds-on-a-wire-cipher ) and get the flag

Tring Tring....

  • 100 points

  • Problem Description

    • Tring Tring my mobile started ringing. "Hey Check your SMS!!"

    • ----. ----. ----. / -.... -.... -.... / ---.. ---.. / ..--- ..--- ..--- / ..--- / -.... -.... / --... --... --... / ...-- ...-- / ..--- / ...-- / -.... / ----. ----. ----. / --... --... --... --... / -.... / --... --... --... --...

    • Flag Format: SHELL{SOMETHINGHERE}

  • Solution

    • Morse code decode ( https://morsecode.world/international/translator.html )

    • Multi-tap Phone (SMS) ( https://www.dcode.fr/multitap-abc-cipher )

OX9OR2

  • 200 points

  • Problem Description

  • Given File

    • encrypted

    • encryption.py

  • Solution

    • encrypted in hex

    • encryption.py code

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      def xor(msg, key):
      o = ''
      for i in range(len(msg)):
      o += chr(ord(msg[i]) ^ ord(key[i % len(key)]))
      return o

      with open('message', 'r') as f:
      msg = ''.join(f.readlines()).rstrip('\n')

      with open('key', 'r') as k:
      key = ''.join(k.readlines()).rstrip('\n')

      assert key.isalnum() and (len(key) == 9)
      assert 'SHELL' in msg

      with open('encrypted', 'w') as fo:
      fo.write(xor(msg, key))

    • SHELL is in msg --> maybe SHELL{ ?

    • We now know 6/9 of the key! And the key is XORISC + (3 char).

    • The key seems like XOR IS C??? .

    • We can use a list of common words which starts with C to brute force the right key and get the flag.

    • getenc.py

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      import re

      enc = [0x0B ,0x07 ,0x17 ,0x05 ,0x1F ,0x38 ,0x17 ,0x7F ,0x1E ,0x07 ,0x7E ,0x01 ,0x16 ,0x01 ,0x70 ,0x19 ,0x2A ,0x1E ,0x6D ,0x7E ,0x10 ,0x05 ,0x60 ,0x3E]
      dec = ['?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?']
      c_dict = ['cabin', 'cabinet', 'cable', 'cake', 'calculate', 'call', 'camera', 'camp', 'campaign', 'campus', 'can', 'Canadian', 'cancer', 'candidate', 'cap', 'capability', 'capable', 'capacity', 'capital', 'captain', 'capture', 'car', 'carbon', 'card', 'care', 'career', 'careful', 'carefully', 'carrier', 'carry', 'case', 'cash', 'cast', 'cat', 'catch', 'category', 'Catholic', 'cause', 'ceiling', 'celebrate', 'celebration', 'celebrity', 'cell', 'center', 'central', 'century', 'CEO', 'ceremony', 'certain', 'certainly', 'chain', 'chair', 'chairman', 'challenge', 'chamber', 'champion', 'championship', 'chance', 'change', 'changing', 'channel', 'chapter', 'character', 'characteristic', 'characterize', 'charge', 'charity', 'chart', 'chase', 'cheap', 'check', 'cheek', 'cheese', 'chef', 'chemical', 'chest', 'chicken', 'chief', 'child', 'childhood', 'Chinese', 'chip', 'chocolate', 'choice', 'cholesterol', 'choose', 'Christian', 'Christmas', 'church', 'cigarette', 'circle', 'circumstance', 'cite', 'citizen', 'city', 'civil', 'civilian', 'claim', 'class', 'classic', 'classroom', 'clean', 'clear', 'clearly', 'client', 'climate', 'climb', 'clinic', 'clinical', 'clock', 'close', 'closely', 'closer', 'clothes', 'clothing', 'cloud', 'club', 'clue', 'cluster', 'coach', 'coal', 'coalition', 'coast', 'coat', 'code', 'coffee', 'cognitive', 'cold', 'collapse', 'colleague', 'collect', 'collection', 'collective', 'college', 'colonial', 'color', 'column', 'combination', 'combine', 'come', 'comedy', 'comfort', 'comfortable', 'command', 'commander', 'comment', 'commercial', 'commission', 'commit', 'commitment', 'committee', 'common', 'communicate', 'communication', 'community', 'company', 'compare', 'comparison', 'compete', 'competition', 'competitive', 'competitor', 'complain', 'complaint', 'complete', 'completely', 'complex', 'complicated', 'component', 'compose', 'composition', 'comprehensive', 'computer', 'concentrate', 'concentration', 'concept', 'concern', 'concerned', 'concert', 'conclude', 'conclusion', 'concrete', 'condition', 'conduct', 'conference', 'confidence', 'confident', 'confirm', 'conflict', 'confront', 'confusion', 'Congress', 'congressional', 'connect', 'connection', 'consciousness', 'consensus', 'consequence', 'conservative', 'consider', 'considerable', 'consideration', 'consist', 'consistent', 'constant', 'constantly', 'constitute', 'constitutional', 'construct', 'construction', 'consultant', 'consume', 'consumer', 'consumption', 'contact', 'contain', 'container', 'contemporary', 'content', 'contest', 'context', 'continue', 'continued', 'contract', 'contrast', 'contribute', 'contribution', 'control', 'controversial', 'controversy', 'convention', 'conventional', 'conversation', 'convert', 'conviction', 'convince', 'cook', 'cookie', 'cooking', 'cool', 'cooperation', 'cop', 'cope', 'copy', 'core', 'corn', 'corner', 'corporate', 'corporation', 'correct', 'correspondent', 'cost', 'cotton', 'couch', 'could', 'council', 'counselor', 'count', 'counter', 'country', 'county', 'couple', 'courage', 'course', 'court', 'cousin', 'cover', 'coverage', 'cow', 'crack', 'craft', 'crash', 'crazy', 'cream', 'create', 'creation', 'creative', 'creature', 'credit', 'crew', 'crime', 'criminal', 'crisis', 'criteria', 'critic', 'critical', 'criticism', 'criticize', 'crop', 'cross', 'crowd', 'crucial', 'cry', 'cultural', 'culture', 'cup', 'curious', 'current', 'currently', 'curriculum', 'custom', 'customer', 'cut', 'cycle']

      key_len = 9
      # flag prefix
      str_known = "SHELL{"
      for i in range(len(str_known)):
      dec[i] = str_known[i]

      keey = ""
      for i in range(len(str_known)):
      keey += chr(enc[i] ^ ord(dec[i]))

      str_unknown_len = key_len - len(str_known)
      for i in range(str_unknown_len):
      keey += "?"
      print(keey)

      for j in range(len(c_dict)):

      if len(c_dict[j]) != (str_unknown_len + 1):
      continue

      keey = keey[:-4] + c_dict[j].upper()

      for i in range(len(dec)):
      dec[i] = chr(enc[i] ^ ord(keey[i % key_len]))

      if re.search("^SHELL{[0-9A-Za-z_]+}$", ''.join(dec)):
      print(''.join(dec) + " , " + keey)

    • Run getenc.py and find the flag