| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- 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("<Return>", 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()
|