Загрузка данных


import itertools
import numpy as np

# Данные из output.txt
seed = [
    1,
    0,
    0,
    1,
    1,
    1,
    1,
    1,
    0,
    0,
    1,
    0,
    0,
    0,
    0,
    0,
    1,
    1,
    0,
    1,
    0,
    0,
    1,
    1,
    0,
    1,
    1,
    1,
    0,
    0,
    1,
    0,
]
hex_enc = "0a9e47b25066fedf5d59d26b0701223e3f1010c84ac95f51021bb0242f833480797984c4f5c33d0cc9aa9bc5654be281f9b72595dbacc309e1deea7f174858e849d31df30dea39f1"

# Переводим hex в биты шифротекста
num_of_bits = len(hex_enc) * 4
bin_enc = bin(int(hex_enc, 16))[2:].zfill(num_of_bits)
enc_bits = [int(b) for b in bin_enc]

# Известный префикс флага для получения первых бит гаммы
known_text = "DUCKERZ{"
known_bits = [int(b) for char in known_text for b in format(ord(char), "08b")]
target_keystream = [known_bits[i] ^ enc_bits[i] for i in range(len(known_bits))]


class Cipher:

  def __init__(self, polynom, seed):
    self.state = np.array(seed, dtype=np.uint8)
    self.polynom = np.array(polynom, dtype=np.uint8)

  def step(self):
    feedback = np.bitwise_xor.reduce(self.state[self.polynom])
    output = self.state[-1]
    self.state[1:] = self.state[:-1]
    self.state[0] = feedback
    return output

  def generate_keystream(self, length):
    return [self.step() for _ in range(length)]


print("[*] Поиск полинома обратной связи...")
found_polynom = None

# Перебираем комбинации индексов полинома (обычно в таких тасках длина невелика)
for r in range(1, 6):
  for combo in itertools.combinations(range(len(seed)), r):
    c = Cipher(list(combo), seed)
    ks = c.generate_keystream(len(target_keystream))
    if ks == target_keystream:
      found_polynom = list(combo)
      break
  if found_polynom:
    break

if found_polynom:
  print(f"[+] Полином найден: {found_polynom}")

  # Генерируем полную гамму для всего шифротекста
  c = Cipher(found_polynom, seed)
  full_keystream = c.generate_keystream(len(enc_bits))

  # Расшифровываем биты с помощью XOR
  decrypted_bits = [enc_bits[i] ^ full_keystream[i] for i in range(len(enc_bits))]

  # Превращаем биты обратно в символы текста
  byte_list = []
  for i in range(0, len(decrypted_bits), 8):
    byte_bits = decrypted_bits[i : i + 8]
    if len(byte_bits) < 8:
      break
    byte_val = int("".join(map(str, byte_bits)), 2)
    byte_list.append(byte_val)

  flag = "".join(map(chr, byte_list))
  print(f"\n[+] ФЛАГ УСПЕШНО РАСШИФРОВАН:\n{flag}")
else:
  print("[-] Не удалось найти полином среди комбинаций небольшой длины.")