import time import sys import re import tkinter as tk from tkinter import scrolledtext import threading # --- ВАШИ ИСХОДНЫЕ ДАННЫЕ --- class Colors: RESET = "\033[0m" RED = "\033[91m" GREEN = "\033[92m" YELLOW = "\033[93m" CYAN = "\033[96m" BOLD = "\033[1m" def print_slow(text, delay=0.03): """Функция для эффекта печатной машинки""" for char in text: sys.stdout.write(char) sys.stdout.flush() time.sleep(delay) print() def print_scene_header(scene_num, title): print(f"\n{Colors.YELLOW}{'='*50}") print(f"{Colors.BOLD}СЦЕНА {scene_num}: {title.upper()}{Colors.RESET}") print(f"{Colors.YELLOW}{'='*50}{Colors.RESET}\n") quiz_data = [ { "scene": 1, "title": "Брифинг в рубке", "text": "Главный инженер: «Новичок, наша сеть сейчас под атакой. Чтобы снять первую блокировку с консоли, напомни мне главный постулат современной архитектуры безопасности, на которую мы перешли».", "question": "Что означает концепция Zero Trust (Нулевое доверие)?", "options": ["Доверять всем устройствам внутри корпоративной сети по умолчанию", "Никогда не доверять, всегда проверять любой запрос на доступ", "Полностью заблокировать доступ в интернет всем сотрудникам", "Доверять только администраторам, а остальным запрещать всё"], "correct": 1 }, { "scene": 2, "title": "Периметр под огнем", "text": "Система разблокирована. Вы видите попытку входа под учеткой директора. Система запросила подтверждающий код из приложения. Нужно классифицировать эти два шага для журнала аудита.", "question": "Ввод логина 'Director' — это идентификация или аутентификация? А ввод кода из приложения?", "options": ["Оба действия — это аутентификация", "Логин — идентификация, код из приложения — аутентификация", "Логин — аутентификация, код из приложения — идентификация", "Оба действия — это идентификация"], "correct": 1 }, { "scene": 3, "title": "Троянский конь изнутри", "text": f"{Colors.RED}ВНИМАНИЕ: Обнаружена аномалия!{Colors.RESET} Сотрудник бухгалтерии в 03:00 ночи пытается скачать базу клиентов. Это не внешний хакер, угроза исходит изнутри периметра.", "question": "К какому вектору угроз относится эта ситуация и какая система помогла ее обнаружить?", "options": ["Внешний вектор, обнаружен с помощью антивируса", "Физический вектор, обнаружен камерами видеонаблюдения", "Внутренний вектор (инсайдер), обнаружен SIEM-системой", "Программный вектор, обнаружен файрволом"], "correct": 2 }, { "scene": 4, "title": "Физическая брешь", "text": "Охрана сообщает: «С рабочего стола украден ноутбук аналитика!» На нем хранились отчеты. Вору не осталось ничего, кроме самого железа и жесткого диска.", "question": "Какие средства защиты гарантируют, что данные на украденном диске останутся нечитаемым набором символов?", "options": ["Сложный пароль на Windows и скрытые папки", "Шифрование жесткого диска (FDE) и модуль доверенной загрузки (TPM)", "Установленный браузер Tor и отключенный Wi-Fi", "Регулярная дефрагментация диска и очистка корзины"], "correct": 1 }, { "scene": 5, "title": "Восстановление системы", "text": "Благодаря вашим верным решениям, скомпрометированный аккаунт заблокирован, а данные в безопасности. Штатные вирусы изолированы. Настало время закрыть инцидент.", "question": "Согласно модели NIST, как называется финальный этап жизненного цикла реагирования на инцидент, на котором данные восстанавливаются из бэкапов?", "options": ["Защита (Protect)", "Обнаружение (Detect)", "Реагирование (Respond)", "Восстановление (Recover)"], "correct": 3 } ] # --- КЛАСС ГРАФИЧЕСКОГО ИНТЕРФЕЙСА --- class HackerApp: def __init__(self, root): self.root = root self.root.title("ОПЕРАЦИЯ: НУЛЕВОЕ ДОВЕРИЕ") self.root.geometry("800x600") self.root.configure(bg="black") # Настройка шрифта (Consolas или монопшринный по умолчанию) self.font = ("Consolas", 11) # Поле вывода текста (Терминал) self.text_area = scrolledtext.ScrolledText( root, bg="#050505", fg="#00FF41", font=self.font, insertbackground="white", wrap=tk.WORD, state=tk.DISABLED, # Запрещаем ручной ввод в главное окно borderwidth=0, highlightthickness=0 ) self.text_area.pack(padx=10, pady=(10, 0), fill=tk.BOTH, expand=True) # Строка ввода ответов self.input_frame = tk.Frame(root, bg="black") self.input_frame.pack(padx=10, pady=10, fill=tk.X) self.input_var = tk.StringVar() self.input_entry = tk.Entry( self.input_frame, textvariable=self.input_var, bg="#0A0A0A", fg="#00FFFF", font=self.font, insertbackground="#00FFFF", borderwidth=1, relief="solid" ) self.input_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, ipady=5) self.input_entry.bind("", self.on_enter) # Механизм замены стандартного ввода/вывода self.input_ready = threading.Event() self.user_input = "" # Перенаправляем стандартный вывод (print) в наше окно sys.stdout = self # Функция для записи в текстовое поле (с поддержкой потоков) def write(self, text): # Очищаем ANSI-коды, так как Tkinter их не понимает, # но заменяем их на теги цветов Tkinter clean_text = re.sub(r'\x1B\[[0-?]*[ -/]*[@-~]', '', text) def _write(): self.text_area.config(state=tk.NORMAL) # Простая эмуляция цветов (зеленный по умолчанию) if Colors.RED in text: self.text_area.insert(tk.END, clean_text, "red") elif Colors.YELLOW in text: self.text_area.insert(tk.END, clean_text, "yellow") elif Colors.CYAN in text: self.text_area.insert(tk.END, clean_text, "cyan") elif Colors.BOLD in text: self.text_area.insert(tk.END, clean_text, "bold") else: self.text_area.insert(tk.END, clean_text) self.text_area.see(tk.END) self.text_area.config(state=tk.DISABLED) # Используем root.after для безопасности потоков в Tkinter self.root.after(0, _write) def flush(self): pass # Заглушка для sys.stdout # Обработка нажатия Enter в строке ввода def on_enter(self, event): self.user_input = self.input_var.get() self.input_entry.delete(0, tk.END) self.input_entry.config(state=tk.DISABLED) # Блокируем ввод пока идет процесс self.input_ready.set() # Сигнализируем основному потоку, что ответ получен # Замена стандартной функции input() def gui_input(self, prompt): self.write(prompt) self.input_ready.clear() # Разблокируем поле ввода в главном потоке интерфейса def unlock(): self.input_entry.config(state=tk.NORMAL) self.input_entry.focus_set() self.root.after(0, unlock) # Ждем, пока пользователь не нажмет Enter self.input_ready.wait() # Выводим то, что ввел пользователь (эффект эха) self.write(self.user_input + "\n") return self.user_input # --- ИЗМЕНЕННАЯ ФУНКЦИЯ MAIN --- def main(app): print(f"{Colors.CYAN}{Colors.BOLD}") print("╔══════════════════════════════════════════════╗") print("║ ОПЕРАЦИЯ: НУЛЕВОЕ ДОВЕРИЕ ║") print("║ СИМУЛЯЦИЯ ИБ-АНАЛИТИКА ║") print("╚══════════════════════════════════════════════╝{Colors.RESET}\n") print_slow("Инициализация терминала безопасности...") time.sleep(1) print_slow("Загрузка базы данных лекций по НСД...") time.sleep(1) print_slow(f"{Colors.YELLOW}Статус: ТРЕВОГА. Требуется подтверждение допуска.{Colors.RESET}") time.sleep(1) score = 0 for level in quiz_data: print_scene_header(level["scene"], level["title"]) print_slow(level["text"]) time.sleep(0.5) print(f"\n{Colors.BOLD}>> ВАШ ОТВЕТ:{Colors.RESET}") for i, option in enumerate(level["options"]): print(f" [{i + 1}] {option}") # Заменяем стандартный input() на наш графический while True: try: # ВАЖНО: тут используем app.gui_input вместо обычного input user_answer = int(app.gui_input(f"\n{Colors.CYAN}Введите номер варианта (1-{len(level['options'])}: ")) - 1 if 0 <= user_answer < len(level["options"]): break else: print(f"{Colors.RED}Ошибка: Выбран несуществующий вариант. Попробуйте снова.{Colors.RESET}") except ValueError: print(f"{Colors.RED}Ошибка: Введите пожалуйста цифру.{Colors.RESET}") print("\n" + "-"*40) if user_answer == level["correct"]: print(f"{Colors.GREEN}[ УСПЕХ ] Верный ответ! Угроза нейтрализована.{Colors.RESET}") score += 1 else: print(f"{Colors.RED}[ ПРОВАЛ ] Неверный ответ! Системе нанесен ущерб.{Colors.RESET}") correct_text = level["options"][level["correct"]] print(f"{Colors.YELLOW}Подсказка системы: Правильный ответ -> {correct_text}{Colors.RESET}") print("-"*40 + "\n") time.sleep(1.5) # Финал игры print(f"{Colors.YELLOW}{'='*50}{Colors.RESET}") print(f"{Colors.BOLD}СИМУЛЯЦИЯ ЗАВЕРШЕНА{Colors.RESET}") print(f"{Colors.YELLOW}{'='*50}{Colors.RESET}\n") print_slow(f"Итоговый результат: {score} из {len(quiz_data)} верных решений.") if score == len(quiz_data): print_slow(f"\n{Colors.GREEN}{Colors.BOLD}РАНГ: ЭКСПЕРТ. Вы полностью остановили утечку данных и доказали, что уместно применять меры защиты заблаговременно. Добро пожаловать в отдел ИБ!{Colors.RESET}") elif score >= 3: print_slow(f"\n{Colors.YELLOW}{Colors.BOLD}РАНГ: УЧЕНИК. Атака частично отражена, но компания понесла некоторые потери. Вам стоит перечитать лекцию про внутренние угрозы и криптографию.{Colors.RESET}") else: print_slow(f"\n{Colors.RED}{Colors.BOLD}РАНГ: ПРОВАЛ. Сервера скомпрометированы, данные утекли в сеть. Уступить инициативу — значит допустить потерю данных. Симуляция провалена.{Colors.RESET}") if __name__ == "__main__": # Создаем графическое окно root = tk.Tk() app = HackerApp(root) # Настраиваем цветовые теги для текста в Tkinter app.text_area.tag_config("red", foreground="#FF4444") app.text_area.tag_config("yellow", foreground="#FFFF00") app.text_area.tag_config("cyan", foreground="#00FFFF") app.text_area.tag_config("bold", font=("Consolas", 11, "bold"), foreground="#FFFFFF") # Запускаем логику игры в отдельном потоке, чтобы не зависало окно game_thread = threading.Thread(target=main, args=(app,), daemon=True) game_thread.start() # Запускаем графический цикл root.mainloop()