Solution

Бинарь есть, инфы - нет. Плохо. Использую diec:

Info:
    File name: /spbctf_rev/sparta/sparta
    Size: 16384
    File type: ELF64
    String: ELF(AMD64)
    Extension: so
    Operation system: Debian Linux(ABI: 3.2.0)
    Architecture: AMD64
    Mode: 64-bit
    Type: DYN
    Endianness: LE

В строках ничего информативного нет. Поэтому перейду к статическому анализу. Если нет никаких зацепок по строкам, то проще всего начинать с main. Так я и сделаю.

Анализ main

А вот и все строки, что я видел. Ну да ладно. Буду редачить код)

    {
      int32_t argc_1 = argc;
      char** argv_1 = argv;
      puts("With a shield or on a shield? ");
      char buf[0x100];
      fgets(&buf, 0xff, __TMC_END__);
      int32_t rax = strlen(&buf);
      buf[(uint64_t)(rax - 1)] = 0;
      int32_t var_c = 1;
      int32_t var_10 = 0;
      
      for (int32_t i = 0; i <= 6; i += 1)
      {
          for (int32_t j = i; j < rax - 1; j += 7)
          {
              int32_t rax_6 = var_10;
              var_10 = rax_6 + 1;
              
              if (buf[(uint64_t)j] != data_402027[(uint64_t)rax_6])
              {
                  var_c = 0;
                  break;
              }
          }
          
          if (!var_c)
              break;
      }
      
      if (!var_c)
          puts("Oh, on a shield :(");
      else
          puts("Wow, with a shield :)");
      
      return 0;
  }

Значит нам нужно ввести с клавиатуры такую последовательность, которая успешно пройдет цикл:

for (int32_t i = 0; i <= 6; i += 1)
      {
          for (int32_t j = i; j < rax - 1; j += 7)
          {
              int32_t rax_6 = var_10;
              var_10 = rax_6 + 1;
              
              if (buf[(uint64_t)j] != data_402027[(uint64_t)rax_6])
              {
                  var_c = 0;
                  break;
              }
          }
          
          if (!var_c)
              break;
      }
char const data_402027[0x1d] = "st_3phr_b13gcsvut_3yf1rz{55}", 0

Написание декодера

Алгоритм проверки мне известен. Но вместо сравнения я буду сохранять правильный символ. Перепишу алгоритм на Python, сохранив те же имена переменных, чтобы было проще сравнивать:

def decode(buf_len) -> bool:
    key = [ '*' ] * (buf_len - 1)

    pos_1 = 0
    data_402027 = 'st_3phr_b13gcsvut_3yf1rz{55}'

    for i in range(7):
        for j in range(i, buf_len-1, 7):
            pos = pos_1
            pos_1 = pos + 1
            key[j] = data_402027[pos]
            if pos_1 > len(data_402027):
                return False

    print(''.join(key))
    return True

if __name__ == '__main__':
    decode(29)

Сперва я прогнал алгоритм, подбирая длину. Но в целом, этого и не нужно было, ибо длина проверяющей строки должна совпадать с длиной ключа.

root@06f4d898612a:/rev# python3 solve.py
spbctf{th1s_15_r3v3r53_guyz}

Проверю с оригинальным бинарем:

root@06f4d898612a:/rev# ./sparta
With a shield or on a shield?
spbctf{th1s_15_r3v3r53_guyz}
Wow, with a shield :)

IMG