
Консоль DFIR-триажа для Windows-хостов, которая объединяет сбор артефактов, таймлайны с корреляцией по Sigma, сканирование YARA, проверку сокетов и учётных записей, обогащение индикаторов и калиброванную оценку риска.
Наведите Kage на подозрительный Windows-хост — и он выполнит всю триаж-обработку одной цепочкой: CyLR собирает артефакты, Hayabusa сопоставляет журналы событий с правилами Sigma, THOR Lite ищет совпадения по YARA, VirusTotal и AbuseIPDB квалифицируют индикаторы, а выбранный вами AI-провайдер составляет черновик отчёта. Каждый этап транслируется в реальном времени, запечатывает свои результаты и может быть воспроизведён отдельно.```bash pip install -r requirements.txt python -m dfirconsole # → http://127.0.0.1:8787
<p align="center">
<img src="https://assets.kitploit.com/production/public/readmes/55114/7d59d87cd6f41f9d8dc66e4da743e6c6728a7156a06f9de9bdc18cdfd1fbb5cd/de22d9f23b6327fc806bbd1febb370cdca42f33eff3718eca9a0864eeb7d87e2-display-v1.webp" alt="Kage overview" width="100%">
<br><sub>Обзор: одиннадцать закрытых шагов слева, поток журнала
выполнения и оценка, разбитая на четыре компонента.</sub>
</p>
---
## 📑 Содержание
- [Установка](#-installation)
- [Запуск первого сканирования](#-running-your-first-scan)
- [Добавление THOR Lite вручную](#-adding-thor-lite-manually)
- [Цепочка](#-the-chain)
- [Оценка риска](#-risk-score)
- [Оповещения](#-alerts)
- [Системный контекст](#-system-context)
- [Журналирование и аудит](#-logging--audit)
- [YARA](#-yara)
- [Печати](#-seals)
- [Представления](#-views)
- [Конфигурация](#-configuration)
- [Справочник CLI](#-cli-reference)
- [Устранение неполадок](#-troubleshooting)
- [Версия для Linux](#-linux-version--in-progress)
- [Благодарности](#-credits)
---
## 📦 Установка
### Требования
| | |
|---|---|
| ОС | Windows 10 / 11 или Windows Server |
| Python | 3.10+ с [python.org](https://www.python.org/downloads/), **установленный для всех пользователей** |
| Права | **Администратор** |
| Диск | несколько ГБ свободного места для коллекции |
### Установка```powershell
# 1. Extract Kage anywhere — Desktop, C:\Kage, a USB stick, it does not matter
cd C:\Kage
# 2. Install the dependencies
pip install -r requirements.txt
# 3. Check the environment before touching a host
python preflight.py
preflight.py сообщает, что готово, а что отсутствует.```
Workspace : C:\Kage
System : Windows 11
Python : 3.12.3
Dependencies [ok] module fastapi [ok] module uvicorn [ok] module httpx
Rights and disk space [ok] console running as administrator [ok] free space: 84.2 GB
Tooling [!] CyLR in C:\Kage\tools\cylr → the "Locate the tooling" step downloads it [!] THOR Lite → optional step — it will simply be skipped
### Запуск — от имени администратора```powershell
python -m dfirconsole
Или щёлкните правой кнопкой мыши по launch.bat → Запуск от имени администратора, что автоматически настроит
virtualenv, выполнит установку и откроет браузер за вас.```
Kage DFIR Toolkit 1.5.0
code C:\Kage\dfirconsole
workspace C:\Kage
open http://127.0.0.1:8787
> **Рабочая область — это то место, откуда вы запустили программу.** Настраивать ничего не нужно. Инструменты,
> доказательства и результаты — всё оказывается рядом с консолью.
### Попробуйте сначала без риска```powershell
python -m dfirconsole --demo
Демонстрационный режим создаёт синтетическое вторжение — вредоносное вложение, закодированный PowerShell, отключённый Defender, кража учётных данных, закрепление, C2, удалённые теневые копии — и прогоняет всю цепочку на нём. Ничто на вашей машине не затрагивается. Лучший способ изучить интерфейс перед реальным инцидентом.
Запустите от имени администратора, откройте http://127.0.0.1:8787 и проверьте, что в строке состояния
отображается live run · Windows, а не demonstration mode.
Нажмите Settings:
| Поле | Пример | Почему это важно |
|---|---|---|
| Case reference | INC-2026-0042 | задаёт имя отчёта, журнала и архива |
| Analyst | N. Delaunay | отображается в шапке отчёта |
Оставьте Workspace folder пустым — он сам отслеживает папку запуска. Нажмите Save.
Левый столбец — это цепочка сохранности. У каждого шага есть флажок; все отмечены по умолчанию, кроме сканирования YARA.
Для первого запуска снимите отметки со всего, кроме:``` ☑ Prepare the workspace ☑ Exclude the folder from Defender ☑ Locate the tooling ☑ Update the Sigma rules
Нажмите **Run 4 steps**. Примерно минута. Это загружает CyLR и Hayabusa и
подтверждает, что ваше повышение прав действительно работает *до* начала чего-либо длительного.
### Шаг 4 — Сбор и анализ
Как только эти четыре будут запечатаны, отметьте остальные:```
☑ Collect the artefacts CyLR — a few minutes, several GB
☑ Capture the system context accounts, sockets, disk root, log coverage
☑ Build the timeline Hayabusa correlates against Sigma
☑ Analyse the timeline score, alert families, indicators
Нажмите Run и наблюдайте за потоком журнала выполнения. Каждый завершённый шаг получает seal — SHA-256, который вы сможете проверить позже.
| Где | Что вы получаете |
|---|---|
| Overview | оценка риска с её четырьмя компонентами, оповещения по семействам |
| Alerts | каждое оповещение с фильтрацией по серьёзности и семейству |
| System | учётные записи, сокеты, привязанные к процессам, подозрительные папки, покрытие журналов |
| Indicators | хеши, IP-адреса и домены, извлечённые из таймлайна |
Нажмите на любую строку таблицы, чтобы открыть панель чтения: каждое поле, полная командная
строка, все необработанные данные. ← → для перемещения между элементами, Esc для закрытия.
С настроенными API-ключами:``` ☑ Enrich the indicators VirusTotal + AbuseIPDB reputation ☑ Write the summary the AI drafts the report
Без ключей оба помечаются как *пропущенные*, и вместо этого создаётся **локальный отчёт** — та же структура, без сетевого вызова.
### Шаг 7 — Экспорт
В правом верхнем углу панели управления:
- **Report** — HTML для печати, тринадцать нумерованных разделов, готов к экспорту в PDF
- **JSON** — полное состояние, включая печати
- **Log** — всё, что вывела консоль
> 💡 **Повторный запуск отдельного шага:** дважды щёлкните по его тегу в левой колонке. Полезно,
> когда Hayabusa завершается с ошибкой, но сбор данных прошёл успешно — не нужно собирать дважды.
---
## 🔦 Добавление THOR Lite вручную
Сканирование YARA — единственный шаг, который Kage **не может** настроить за вас. Nextron требует
регистрации, поэтому бинарный файл нельзя загрузить скриптом. CyLR и Hayabusa загружаются сами;
THOR — нет.
### 1. Получите архив
Зарегистрируйтесь и скачайте по адресу
[nextron-systems.com/thor-lite](https://www.nextron-systems.com/thor-lite/).
Вы получите сканер **и файл лицензии** (`.lic`) — обычно по электронной почте.
### 2. Поместите его в `tools\thor\`
Kage уже создал эту папку при первом запуске. Скопируйте в неё содержимое архива,
**сохраняя всё вместе**:```
C:\Kage\
└── tools\
└── thor\ ← everything goes here
├── thor64-lite.exe the scanner
├── yourname.lic the licence — THOR will not start without it
├── config\ from the archive
├── signatures\ from the archive — the YARA rules themselves
└── custom-signatures\ from the archive
Почему их нужно держать вместе? THOR запускается из каталога, содержащего его исполняемый файл, и разрешает свои сигнатуры относительно этого каталога. Копирование одного лишь бинарного файла даёт вам сканер, которому нечего искать.
Два других инструмента находятся рядом с ним, каждый в своей собственной папке:```
tools
├── cylr\ CyLR.exe ← downloaded automatically
├── hayabusa\ hayabusa-.exe ← downloaded automatically
└── thor\ thor64-lite.exe + .lic ← you place this one
### 3. Проверка```powershell
python preflight.py
def __init__(self, target, port, timeout=10, concurrency=100):
self.target = target
self.port = port
self.timeout = timeout
self.concurrency = concurrency
self.results = []
self.lock = threading.Lock()
self.stop_event = threading.Event()
self.attempts = 0
self.successes = 0
self.start_time = None
self.end_time = None
self.credentials = []
self.valid_credentials = []
self.errors = []
self.stats = {}
self.config = {}
self.logger = None
self.verbose = False
self.debug = False
self.quiet = False
self.output_file = None
self.input_file = None
self.username = None
self.password = None
self.username_file = None
self.password_file = None
self.combo_file = None
self.protocol = None
self.service = None
self.threads = []
self.queue = queue.Queue()
self.session = None
self.proxy = None
self.user_agent = None
self.headers = {}
self.cookies = {}
self.retries = 3
self.delay = 0
self.jitter = 0
self.follow_redirects = True
self.verify_ssl = False
self.max_redirects = 5
self.rate_limit = None
self.rate_limit_window = 60
self.rate_limit_count = 0
self.rate_limit_start = None
self.rate_limit_lock = threading.Lock()
self.rate_limit_event = threading.Event()
self.rate_limit_thread = None
self.rate_limit_running = False
self.rate_limit_stop = threading.Event()
self.rate_limit_queue = queue.Queue()
self.rate_limit_results = []
self.rate_limit_errors = []
self.rate_limit_stats = {}
self.rate_limit_config = {}
self.rate_limit_logger = None
self.rate_limit_verbose = False
self.rate_limit_debug = False
self.rate_limit_quiet = False
self.rate_limit_output_file = None
self.rate_limit_input_file = None
self.rate_limit_username = None
self.rate_limit_password = None
self.rate_limit_username_file = None
self.rate_limit_password_file = None
self.rate_limit_combo_file = None
self.rate_limit_protocol = None
self.rate_limit_service = None
self.rate_limit_threads = []
self.rate_limit_queue = queue.Queue()
self.rate_limit_session = None
self.rate_limit_proxy = None
self.rate_limit_user_agent = None
self.rate_limit_headers = {}
self.rate_limit_cookies = {}
self.rate_limit_retries = 3
self.rate_limit_delay = 0
self.rate_limit_jitter = 0
self.rate_limit_follow_redirects = True
self.rate_limit_verify_ssl = False
self.rate_limit_max_redirects = 5
self.rate_limit_rate_limit = None
self.rate_limit_rate_limit_window = 60
self.rate_limit_rate_limit_count = 0
self.rate_limit_rate_limit_start = None
self.rate_limit_rate_limit_lock = threading.Lock()
self.rate_limit_rate_limit_event = threading.Event()
self.rate_limit_rate_limit_thread = None
self.rate_limit_rate_limit_running = False
self.rate_limit_rate_limit_stop = threading.Event()
self.rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_results = []
self.rate_limit_rate_limit_errors = []
self.rate_limit_rate_limit_stats = {}
self.rate_limit_rate_limit_config = {}
self.rate_limit_rate_limit_logger = None
self.rate_limit_rate_limit_verbose = False
self.rate_limit_rate_limit_debug = False
self.rate_limit_rate_limit_quiet = False
self.rate_limit_rate_limit_output_file = None
self.rate_limit_rate_limit_input_file = None
self.rate_limit_rate_limit_username = None
self.rate_limit_rate_limit_password = None
self.rate_limit_rate_limit_username_file = None
self.rate_limit_rate_limit_password_file = None
self.rate_limit_rate_limit_combo_file = None
self.rate_limit_rate_limit_protocol = None
self.rate_limit_rate_limit_service = None
self.rate_limit_rate_limit_threads = []
self.rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_session = None
self.rate_limit_rate_limit_proxy = None
self.rate_limit_rate_limit_user_agent = None
self.rate_limit_rate_limit_headers = {}
self.rate_limit_rate_limit_cookies = {}
self.rate_limit_rate_limit_retries = 3
self.rate_limit_rate_limit_delay = 0
self.rate_limit_rate_limit_jitter = 0
self.rate_limit_rate_limit_follow_redirects = True
self.rate_limit_rate_limit_verify_ssl = False
self.rate_limit_rate_limit_max_redirects = 5
self.rate_limit_rate_limit_rate_limit = None
self.rate_limit_rate_limit_rate_limit_window = 60
self.rate_limit_rate_limit_rate_limit_count = 0
self.rate_limit_rate_limit_rate_limit_start = None
self.rate_limit_rate_limit_rate_limit_lock = threading.Lock()
self.rate_limit_rate_limit_rate_limit_event = threading.Event()
self.rate_limit_rate_limit_rate_limit_thread = None
self.rate_limit_rate_limit_rate_limit_running = False
self.rate_limit_rate_limit_rate_limit_stop = threading.Event()
self.rate_limit_rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_rate_limit_results = []
self.rate_limit_rate_limit_rate_limit_errors = []
self.rate_limit_rate_limit_rate_limit_stats = {}
self.rate_limit_rate_limit_rate_limit_config = {}
self.rate_limit_rate_limit_rate_limit_logger = None
self.rate_limit_rate_limit_rate_limit_verbose = False
self.rate_limit_rate_limit_rate_limit_debug = False
self.rate_limit_rate_limit_rate_limit_quiet = False
self.rate_limit_rate_limit_rate_limit_output_file = None
self.rate_limit_rate_limit_rate_limit_input_file = None
self.rate_limit_rate_limit_rate_limit_username = None
self.rate_limit_rate_limit_rate_limit_password = None
self.rate_limit_rate_limit_rate_limit_username_file = None
self.rate_limit_rate_limit_rate_limit_password_file = None
self.rate_limit_rate_limit_rate_limit_combo_file = None
self.rate_limit_rate_limit_rate_limit_protocol = None
self.rate_limit_rate_limit_rate_limit_service = None
self.rate_limit_rate_limit_rate_limit_threads = []
self.rate_limit_rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_rate_limit_session = None
self.rate_limit_rate_limit_rate_limit_proxy = None
self.rate_limit_rate_limit_rate_limit_user_agent = None
self.rate_limit_rate_limit_rate_limit_headers = {}
self.rate_limit_rate_limit_rate_limit_cookies = {}
self.rate_limit_rate_limit_rate_limit_retries = 3
self.rate_limit_rate_limit_rate_limit_delay = 0
self.rate_limit_rate_limit_rate_limit_jitter = 0
self.rate_limit_rate_limit_rate_limit_follow_redirects = True
self.rate_limit_rate_limit_rate_limit_verify_ssl = False
self.rate_limit_rate_limit_rate_limit_max_redirects = 5
self.rate_limit_rate_limit_rate_limit_rate_limit = None
self.rate_limit_rate_limit_rate_limit_rate_limit_window = 60
self.rate_limit_rate_limit_rate_limit_rate_limit_count = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_start = None
self.rate_limit_rate_limit_rate_limit_rate_limit_lock = threading.Lock()
self.rate_limit_rate_limit_rate_limit_rate_limit_event = threading.Event()
self.rate_limit_rate_limit_rate_limit_rate_limit_thread = None
self.rate_limit_rate_limit_rate_limit_rate_limit_running = False
self.rate_limit_rate_limit_rate_limit_rate_limit_stop = threading.Event()
self.rate_limit_rate_limit_rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_rate_limit_rate_limit_results = []
self.rate_limit_rate_limit_rate_limit_rate_limit_errors = []
self.rate_limit_rate_limit_rate_limit_rate_limit_stats = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_config = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_logger = None
self.rate_limit_rate_limit_rate_limit_rate_limit_verbose = False
self.rate_limit_rate_limit_rate_limit_rate_limit_debug = False
self.rate_limit_rate_limit_rate_limit_rate_limit_quiet = False
self.rate_limit_rate_limit_rate_limit_rate_limit_output_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_input_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_username = None
self.rate_limit_rate_limit_rate_limit_rate_limit_password = None
self.rate_limit_rate_limit_rate_limit_rate_limit_username_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_password_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_combo_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_protocol = None
self.rate_limit_rate_limit_rate_limit_rate_limit_service = None
self.rate_limit_rate_limit_rate_limit_rate_limit_threads = []
self.rate_limit_rate_limit_rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_rate_limit_rate_limit_session = None
self.rate_limit_rate_limit_rate_limit_rate_limit_proxy = None
self.rate_limit_rate_limit_rate_limit_rate_limit_user_agent = None
self.rate_limit_rate_limit_rate_limit_rate_limit_headers = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_cookies = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_retries = 3
self.rate_limit_rate_limit_rate_limit_rate_limit_delay = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_jitter = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_follow_redirects = True
self.rate_limit_rate_limit_rate_limit_rate_limit_verify_ssl = False
self.rate_limit_rate_limit_rate_limit_rate_limit_max_redirects = 5
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_window = 60
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_count = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_start = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_lock = threading.Lock()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_event = threading.Event()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_thread = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_running = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_stop = threading.Event()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_results = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_errors = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_stats = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_config = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_logger = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_verbose = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_debug = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_quiet = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_output_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_input_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_username = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_password = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_username_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_password_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_combo_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_protocol = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_service = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_threads = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_session = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_proxy = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_user_agent = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_headers = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_cookies = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_retries = 3
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_delay = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_jitter = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_follow_redirects = True
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_verify_ssl = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_max_redirects = 5
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_window = 60
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_count = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_start = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_lock = threading.Lock()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_event = threading.Event()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_thread = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_running = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_stop = threading.Event()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_results = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_errors = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_stats = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_config = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_logger = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_verbose = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_debug = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_quiet = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_output_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_input_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_username = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_password = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_username_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_password_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_combo_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_protocol = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_service = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_threads = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_session = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_proxy = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_user_agent = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_headers = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_cookies = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_retries = 3
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_delay = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_jitter = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_follow_redirects = True
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_verify_ssl = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_max_redirects = 5
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_window = 60
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_count = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_start = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_lock = threading.Lock()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_event = threading.Event()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_thread = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_running = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_stop = threading.Event()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_results = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_errors = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_stats = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_config = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_logger = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_verbose = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_debug = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_quiet = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_output_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_input_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_username = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_password = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_username_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_password_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_combo_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_protocol = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_service = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_threads = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_session = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_proxy = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_user_agent = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_headers = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_cookies = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_retries = 3
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_delay = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_jitter = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_follow_redirects = True
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_verify_ssl = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_max_redirects = 5
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_window = 60
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_count = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_start = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_lock = threading.Lock()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_event = threading.Event()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_thread = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_running = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_stop = threading.Event()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_results = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_errors = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_stats = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_config = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_logger = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_verbose = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_debug = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_quiet = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_output_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_input_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_username = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_password = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_username_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_password_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_combo_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_protocol = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_service = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_threads = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_session = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_proxy = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_user_agent = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_headers = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_cookies = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_retries = 3
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_delay = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_jitter = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_follow_redirects = True
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_verify_ssl = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_max_redirects = 5
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_window = 60
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_count = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_start = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_lock = threading.Lock()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_event = threading.Event()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_thread = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_running = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_stop = threading.Event()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_results = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_errors = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_stats = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_config = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_logger = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_verbose = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_debug = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_quiet = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_output_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_input_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_username = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_password = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_username_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_password_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_combo_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_protocol = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_service = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_threads = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_session = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_proxy = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_user_agent = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_headers = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_cookies = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_retries = 3
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_delay = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_jitter = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_follow_redirects = True
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_verify_ssl = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_max_redirects = 5
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_window = 60
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_count = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_start = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_lock = threading.Lock()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_event = threading.Event()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_thread = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_running = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_stop = threading.Event()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_results = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_errors = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_stats = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_config = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_logger = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_verbose = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_debug = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_quiet = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_output_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_input_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_username = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_password = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_username_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_password_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_combo_file = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_protocol = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_service = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_threads = []
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_queue = queue.Queue()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_session = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_proxy = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_user_agent = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_headers = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_cookies = {}
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_retries = 3
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_delay = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_jitter = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_follow_redirects = True
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_verify_ssl = False
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_max_redirects = 5
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_window = 60
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_count = 0
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_start = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_lock = threading.Lock()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_event = threading.Event()
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_thread = None
self.rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_rate_limit_running = False
self.```
Tooling
[ok] CyLR in C:\Kage\tools\cylr
[ok] Hayabusa in C:\Kage\tools\hayabusa
[ok] THOR Lite: C:\Kage\tools\thor\thor64-lite.exe
[ok] THOR licence file (*.lic)
Если в строке лицензии отображается [!], THOR запустится и сразу остановится.
Settings → YARA scan folder:
| Значение | Что сканируется | Время |
|---|---|---|
| (пусто) | артефакты, только что собранные CyLR | минуты |
C:\Users\target | один профиль пользователя | минуты |
C:\ | весь системный том | часы |
Отметьте YARA scan в цепочке и запустите её. Вердикты появляются в реальном времени по мере проверки файлов — оповещения, предупреждения, уведомления и чистые файлы, каждый со своим хешем.
По умолчанию ограничения по времени нет. Трёхчасовая проверка — это решение, а не аномалия. Задайте ограничение в минутах, если хотите потолок.
Без THOR этот шаг помечается как пропущенный, и цепочка продолжается. Вы теряете ось YARA в оценке — и ничего больше.
Одиннадцать шагов. Отметьте нужные, дважды щёлкните по тегу, чтобы воспроизвести только его.
| # | Шаг | Что фактически выполняется |
|---|---|---|
| 01 | Подготовка рабочей области | дерево папок, проверка прав и свободного места |
| 02 | Исключение из Defender | Add-MpPreference -ExclusionPath <workspace> |
| 03 | Поиск инструментов | находит и загружает CyLR + Hayabusa из релизов GitHub |
| 04 | Сбор артефактов | CyLR.exe -od evidence\ -of <case>.zip -v |
| 05 | Захват контекста системы | systeminfo · Get-LocalUser · netstat -ano · tasklist · auditpol |
| 06 | Обновление правил Sigma | hayabusa update-rules |
| 07 | Построение таймлайна | hayabusa <csv|dfir>-timeline -d <Logs> -o hayabusa-output.csv -r <rules> |
| 08 | Анализ таймлайна | оценка, семейства оповещений, извлечение индикаторов |
| 09 | Сканирование YARA (опционально) | thor64-lite.exe --nocsv -p <chosen folder> |
| 10 | Обогащение индикаторов | VirusTotal v3 · AbuseIPDB v2 |
| 11 | Написание сводки | ваш AI-провайдер или локальный отчёт |
Подкоманда Hayabusa считывается из его собственного вывода справки, поэтому работают и v3 (csv-timeline), и v4 (dfir-timeline), а неподдерживаемые флаги отбрасываются, а не приводят к сбою команды.
Приоритет триажа, а не доказательство — и никогда не публикуется без своей разбивки.``` 80 / 100 Compromise confirmed by multiple sources CONFIDENCE HIGH · 441 events analysed
SEVERITY 45 / 45 8 critical, 10 high, 3 medium KILL CHAIN 25 / 25 10 ATT&CK tactics, 7 decisive REPUTATION 0 / 20 no indicator confirmed externally CORROBORATION 10 / 10 3 YARA detections · 3 active connections to public hosts
Четыре независимые оси, **каждая с ограничением**. Именно это не даёт одному шумному правилу, сработавшему триста раз, привести к тому же вердикту, что и настоящая многоэтапная атака.
**Уверенность отделена от серьёзности.** Она подсчитывает, сколько независимых источников согласны и было ли достаточно покрытие логированием — поэтому высокий балл, построенный только на Sigma, читается как сильная зацепка, но никогда как подтверждение:
| Балл | Высокая уверенность | Низкая уверенность |
|---|---|---|
| ≥ 70 | Компрометация подтверждена несколькими источниками | Компрометация весьма вероятна — подтверждение всё ещё ограничено |
| ≥ 45 | Вероятная компрометация — рекомендуется локализация | Сильные признаки из одного источника |
| ≥ 25 | Подозрительная активность, требующая уточнения | |
| ≥ 10 | Слабые сигналы, компрометация не установлена | |
| < 10 | Ничего убедительного | |
Пересчитывается каждый раз, когда поступает новый источник — после таймлайна, после YARA, после обогащения.
---
## 🚨 Оповещения

Серьёзность говорит, насколько срочно. Семейства говорят, какого рода.```
FAMILIES AUTHENTICATION 4 INFECTION 1 EXECUTION 6
NETWORK 5 EVASION 5 OTHER 0
TIMESTAMP LEVEL FAMILY RULE ID
09/09 10:26 CRITICAL EVASION Windows Defender Disabled 5001
09/09 11:09 CRITICAL EVASION Volume Shadow Copies Deleted 4688
09/09 11:15 CRITICAL EVASION Security Event Log Cleared 1102
09/09 10:32 CRITICAL AUTH LSASS Memory Access 10
Классифицируется сначала по event ID, затем по формулировке. Когда они расходятся, побеждает текст: 4688 — это создание процесса, но vssadmin delete shadows относится к Evasion, потому что именно там аналитик будет его искать.
Счётчики семейств всегда совпадают с таблицей. Вычисляются по алертам, которые действительно попадают в список — бейдж, обещающий строки, которых вы не можете найти, это баг, а не деталь.
Гистограмма следует за выбором. При активном одном семействе наблюдаемое окно перерисовывается в цвете этого семейства, и отметка указывает его самый загруженный момент.
Триаж не помечает сам себя. THOR пишет в журнал событий Windows во время работы, а сканирование папки с наступательными бинарниками заставляет Hayabusa помечать наш собственный сканер. Эти события исключаются, подсчитываются отдельно, и итог сообщается.

То, что не расскажет ни один журнал событий, зафиксировано в режиме только для чтения:``` NETWORK — 7 listening, 4 established, 8 flagged
RISK PROTO LOCAL REMOTE PROCESS HIGH TCP 10.20.4.11:52233 45.155.205.233:8443 powershell.exe → active connection to the Internet · powershell.exe should not open a socket · remote port 8443 associated with offensive tooling HIGH TCP 0.0.0.0:3389 — TermService.exe → exposed listener on RDP
ROOT C:\ — 3 flagged entries
HIGH C:\Tools folder created 0 day(s) ago → non-standard entry at the disk root · name suggests tooling HIGH C:\Temp folder → frequently abused location
Каждый сокет сопоставляется с владеющим им процессом по **PID** — именно эта перекрёстная ссылка делает `powershell.exe`, удерживающий соединение с публичным хостом, читаемым с первого взгляда.
Локальные учётные записи проверяются на членство в Administrators, состояние «неактивна, но включена» и последний вход. Публичные адреса из **установленных** соединений автоматически попадают в список индикаторов: адрес, с которым идёт обмен во время триажа, стоит как минимум столько же, сколько запись из трёхдневного журнала.
---
## 📋 Логирование и аудит
Триаж стоит ровно столько, сколько машина согласилась записать.```
LOGGING & AUDIT — coverage 51/100 · partial coverage
Blind spots: Sysmon · PowerShell (script blocks) · Process creation
· Credential validation
STATE CHANNEL IMPORTANCE EVENTS
ACTIVE Security critical 84 213
MISSING Sysmon critical —
EMPTY PowerShell (script blocks) critical —
ACTIVE System important 12 045
DISABLED WinRM important —
Шестнадцать каналов классифицированы как active / empty / disabled / missing —
это различие важно: пустой канал находится в одной команде от исправления, а
отсутствующий требует развёртывания. Рядом прочитаны тринадцать подкатегорий auditpol.
Оценка покрытия стоит рядом с оценкой риска. Risk 80, coverage 51 означает, что вердикт опирается на половину доступной информации — и отчёт об этом сообщает.
```
8 verdicts
VERDICT DETECTION FILE HASH SCORE ALERT YARA rule HKTL_Rubeus C:\AD\Tools\Rubeus.exe 9c4133ee… 100 ALERT YARA rule HKTL_AmsiTrigger C:\AD\Tools\AmsiTrigger.exe af7af55c… 95 ALERT YARA rule PS_Reverse_Shell C:\AD\Tools\PowerShellTcp… ab1e98e8… 80 WARNING Suspicious filename C:\AD\Tools\svchost32.exe 6b6f1901… — NOTICE File checked - signed C:\AD\Tools\chrome.exe c5a10bff… — CLEAN Clean C:\AD\Tools\notepad.exe 20eded6a… —
Страница наполняется **во время** сканирования, а не только когда что-то найдено. Именно это отличает *ничего не найдено* от *ничего не просмотрено*.
**Сканирование начинается с первой реальной находки.** THOR открывает каждый запуск дюжиной строк-баннеров — версия, сборка, имя хоста, рабочий каталог, список аргументов, время работы — и завершает сводкой. Ничто из этого не описывает проверяемый хост, поэтому ничто из этого не попадает в представление. Хеши из оповещений помещаются в список индикаторов, готовые для VirusTotal.
---
## 🔐 Печати
Каждый завершённый шаг запечатывается SHA-256, и печать **указывает, что она покрывает**:```
✔ Analyse the timeline SEALED 0.1s
seal 31d1991a65598de8 — content of hayabusa-output.csv
✔ Exclude the folder from Defender SEALED 6.2s
seal 8f2c04b71ae93d55 — execution record (no file produced)
Когда шаг создавал файлы, печать — это хеш их содержимого — запустите его позже, и у вас будет доказательство, что артефакт не был изменён. Когда он не создавал ни одного, печать покрывает только запись о выполнении и говорит об этом, а не подразумевает большее.
У каждого представления свой URL, оно ничего не перезагружает и ничего не теряет — анализ живёт на стороне сервера, и полное обновление восстанавливает его.
| Адрес | Содержимое |
|---|---|
/ | конвейер, журнал выполнения, разбивка по семействам |
/alerts | оповещения по критичности и семейству |
/indicators | индикаторы с репутацией VirusTotal / AbuseIPDB |
/system | машина, учётные записи, сеть, корень диска, покрытие |
/yara | вердикты THOR, в реальном времени во время сканирования |
/attack | выведенные тактики ATT&CK |
/summary | письменный отчёт |
/log | полный журнал, доступный для скачивания |

Каждая команда транслируется по мере выполнения. Шаги запечатываются один за другим; часы останавливаются, когда останавливается цепочка.

Хеши, IP-адреса и домены, извлечённые из временной шкалы, из активных сокетов и из срабатываний YARA — каждый с его репутацией после запуска обогащения.


Любая строка, где угодно, открывается полностью: каждое поле, полная командная строка, необработанные данные THOR. ← → для перемещения между элементами, Esc для закрытия, Copy для JSON.

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


/api/report.html — самодостаточный, тёмный, тринадцать нумерованных разделов, готов к печати в PDF. Никаких внешних ресурсов: он остаётся читаемым через десять лет на офлайн-машине.

Оценка никогда не появляется без своих четырёх компонентов, чтобы читатель мог оспорить одну ось, а не непрозрачное число.


Каждый шаг с его печатью и что эта печать покрывает — содержимое указанного файла или только запись о выполнении.
При печати в PDF отметьте Background graphics в настройках браузера, иначе тёмный фон будет отброшен.
Каждый инструмент владеет папкой, и каждый поставляется с README, объясняющим, что в неё помещается.``` / ├── tools/ │ ├── cylr/ CyLR.exe ← downloaded automatically │ ├── hayabusa/ hayabusa-.exe ← downloaded automatically │ └── thor/ thor64-lite.exe + .lic ← manual, registration required ├── evidence/ collection archive, unpacked └── output/ timeline, logs, enrichment cache
**CyLR и Hayabusa устанавливают себя сами.** Шаг *Locate the tooling* запрашивает
API релизов GitHub, выбирает текущий Windows x64 asset и распаковывает его в
нужную папку. Фиксация версии означает, что загрузка сломается в тот день, когда
upstream двинется дальше; разрешение версии означает, что консоль продолжает
работать без присмотра. Закреплённый URL берёт верх, если API недоступен.
### API-ключи — все опциональны
Всё работает без единого ключа. Несконфигурированные шаги помечаются как *skipped*,
никогда как *failed*.
**Куда помещаются учётные данные.** Репозиторий поставляет `apikeys.env.example`, шаблон
с пустыми значениями. Скопируйте его, храните копию локально:```powershell
copy apikeys.env.example apikeys.env
notepad apikeys.env
Этот проект лицензирован под лицензией MIT — подробности см. в файле LICENSE.
Примечание: Этот инструмент предназначен только для законного тестирования на проникновение и исследовательских целей. Всегда получайте надлежащее разрешение перед тестированием любой системы.```ini
VT_API_KEY=your_virustotal_key ABUSEIPDB_API_KEY=your_abuseipdb_key
AI_PROVIDER=groq AI_API_KEY=your_provider_key AI_MODEL=
**Где их получить**
| Ключ | Бесплатный тариф | Регистрация |
|---|---|---|
| `VT_API_KEY` | 4 запроса/минуту, 500/день | [virustotal.com](https://www.virustotal.com/gui/join-us) |
| `ABUSEIPDB_API_KEY` | 1 000 проверок/день | [abuseipdb.com](https://www.abuseipdb.com/register) |
| `AI_API_KEY` | varies — Groq and Ollama are free | см. таблицу провайдеров ниже |
Вы также можете задать их как переменные окружения вместо файла, что
обычно и нужно в контейнере или на общей рабочей станции реагирования:```powershell
$env:VT_API_KEY = "..."
python -m dfirconsole
У каждого свой эндпоинт, подключённый явно, поэтому выбор Groq никогда не отправит ваш ключ в OpenAI.
| Провайдер | Эндпоинт | Модель по умолчанию |
|---|---|---|
| Anthropic | api.anthropic.com | claude-sonnet-4-6 |
| OpenAI | api.openai.com/v1 | gpt-4o |
| Groq | api.groq.com/openai/v1 | llama-3.3-70b-versatile |
| Mistral | api.mistral.ai/v1 | mistral-large-latest |
| OpenRouter | openrouter.ai/api/v1 | anthropic/claude-sonnet-4 |
| Ollama | localhost:11434/v1 | llama3.1 — без ключа |
| None | — | локальный отчёт |
Небольшие бесплатные тарифы учтены: Groq допускает 12 000 токенов в минуту, поэтому полезная нагрузка измеряется относительно этого потолка и при отклонении по размеру пересылается с меньшим числом алертов и более краткими деталями. Вердикт сохраняется; просто сужается объём подтверждающих данных.
К модели предъявляется стандарт — наблюдаемое отделено от оценённого, калиброванные формулировки, количественные утверждения, явные пробелы в доказательствах и рассмотрение безобидного объяснения.
python -m dfirconsole console on 127.0.0.1:8787 python -m dfirconsole --port 9000 custom port python -m dfirconsole --demo synthetic data, no collection python preflight.py environment check python preflight.py D:\CASE42 check another workspace
python -m pytest tests/ -q 115 tests python tests/ui_check.py browser: full chain, reading pane python tests/ui_nav.py browser: navigation, counts, histogram python tests/ui_flood.py browser: 6000 log lines at once
Для работы браузера требуются `pip install playwright && playwright install chromium`.
---
## 🔧 Устранение неполадок
**"Требуются права администратора" / Defender отказывает в исключении**
Kage не запущен с повышенными правами. Закройте его, щёлкните правой кнопкой по `launch.bat` → *Запуск от имени администратора*, или сначала откройте PowerShell от имени администратора.
**`did not find executable … python.exe`**
Ваш Python установлен из Microsoft Store, который устанавливает его для каждого пользователя отдельно, и он исчезает в сеансе администратора. Переустановите с python.org, *для всех пользователей*.
**CyLR не создал архив / коллекция пуста**
Добавьте `--force-native` в **Settings → CyLR arguments**. Это отключает прямое чтение NTFS в пользу Windows API, что работает, когда определение разделов на диске даёт сбой.
**THOR запускается, а затем замолкает**
Его лицензия отсутствует или истекла, либо `signatures\` не был скопирован рядом с бинарным файлом. Запустите `preflight.py`, чтобы убедиться.
---
## 🐧 Версия для Linux — в разработке
Цепочка триажа для Linux строится на той же консоли, с теми же представлениями и той же моделью оценки. Парсеры уже платформо-независимы; меняется слой доказательств:
| Windows | Linux (в разработке) |
|---|---|
| Сбор через CyLR | Сбор через UAC / CyLR Linux |
| EVTX + Hayabusa Sigma | `journald` / `auth.log` / `syslog` + Sigma |
| `Get-LocalUser` · `auditpol` | `/etc/passwd` · `/etc/shadow` · правила `auditd` |
| `netstat -ano` + `tasklist` | `ss -tunap` |
| Аномалии в корне диска | `/tmp` · `/dev/shm` · `/var/tmp` · cron · юниты systemd |
| THOR Lite | THOR Lite для Linux |
Поставьте звезду или подпишитесь на репозиторий, чтобы не пропустить релиз.
---
## 🙏 Благодарности
Kage — это консоль, а не сборщик или сканер. Основная работа принадлежит этим проектам, и они заслуживают звезды гораздо больше, чем этот репозиторий:
| Инструмент | Репозиторий | Роль в цепочке |
|---|---|---|
| **CyLR** | [orlikoski/CyLR](https://github.com/orlikoski/CyLR) | сбор артефактов в реальном времени через прямое чтение NTFS |
| **Hayabusa** | [Yamato-Security/hayabusa](https://github.com/Yamato-Security/hayabusa) | корреляция Sigma, построение таймлайна |
| **Sigma** | [SigmaHQ/sigma](https://github.com/SigmaHQ/sigma) | правила обнаружения, лежащие в основе каждого оповещения |
| **THOR Lite** | [NextronSystems/thor-lite](https://github.com/NextronSystems/thor-lite) | сканирование YARA и IOC |
| **VirusTotal** | [virustotal.com](https://www.virustotal.com) | репутация хешей, IP и доменов |
| **AbuseIPDB** | [abuseipdb.com](https://www.abuseipdb.com) | оценка злоупотреблений по IP |
| **MITRE ATT&CK** | [attack.mitre.org](https://attack.mitre.org) | фреймворк тактик, лежащий в основе оси kill-chain |
Уважайте лицензии и условия использования каждого проекта — THOR Lite в особенности требует регистрации у Nextron и не подлежит распространению.
---
## 🌐 Экосистема
| | Инструмент | Домен |
|---|---|---|
| ☁️ | [**Kumo** 蜘蛛](https://github.com/karim852/KUMO-Domain-Recon-Tool) | OSINT и разведка доменов |
| 🌑 | **Kage** 影 | триаж хостов в DFIR |
---
> ⚠️ **Только для авторизованного реагирования на инциденты.**
> Запускайте Kage только на хостах, которыми вы владеете или на явный письменный осмотр которых у вас есть разрешение.
<p align="center"><sub>Создано для тех, кто приходит после. 影</sub></p>