Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
VulnFanatic-NG — Плагин BianryNinja для выявления уязвимостей в декомпилированных бинарных файлах, сочетающий программные проверки и поддержку LLM. | Kitploit
Инструменты/GitHubGitHub/martyx00/vulnfanatic-ng
Статический анализ кода (SAST)Анализ уязвимостейАнализ КодаЭксплуатацияОбратная инженерияФаззингТестирование на ПроникновениеАппаратная БезопасностьАнализ Бинарных ФайловБезопасность Цепочки ПоставокОбучение и ОбразованиеОбратная Разработка с Помощью ИИ
14152 месяцев назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
GitHubmartyx00/vulnfanatic-ng

VulnFanatic-NG

Плагин BianryNinja для выявления уязвимостей в декомпилированных бинарных файлах, сочетающий программные проверки и поддержку LLM.

Репозиторий

VulnFanatic-NG

LLM-assisted vulnerability research for Binary Ninja.

VulnFanatic-NG добавляет боковую панель, которая сканирует текущий бинарный файл и спрашивает LLM — по умолчанию локально размещённую модель, совместимую с OpenAI, или Anthropic Claude, Google Gemini, либо Azure OpenAI (см. Бэкенды LLM) — является ли подозрительный код действительно уязвимым. Она работает в основном с выходом декомпилятора (HLIL) Binary Ninja, переходя к ассемблеру при необходимости, и сообщает только о подтверждённых проблемах с кликабельными ссылками на код.


Как это работает

Сканирование выполняется максимум в три фазы (фаза 3 — опциональная и только онлайн):

Фаза 1 — вызовы опасных функций

Находит места вызовов опасных функций, определённых в rules/phase1_rules.json: strcpy, memcpy, sprintf/строки формата, system, alloca, scanf, API команд/exec, слабый ГПСЧ, семейство free/delete (use-after-free / double-free), чтение недоверенных входных данных в буферы фиксированного размера (recv/read/fread/ReadFile), SQL-инъекции (sqlite3_exec/mysql_query/PQexec), отключённую проверку сертификатов TLS (SSL_CTX_set_verify/curl), SSRF и некорректное управление привилегиями (setuid/setresgid), семейство memset/bzero и сравнения с длиной, контролируемой атакующим (memcmp/strncmp → обход аутентификации) для C/C++, Win32 и (в лучшем случае) Rust FFI. Покрытие включает укреплённые варианты _chk (FORTIFY) and Annex-K _s variants. Ограниченные функции форматированного вывода (snprintf и варианты) имеют собственное правило безопасности по умолчанию, так что корректный аргумент размера не сообщается как переполнение. Места вызовов находятся тремя способами: прямые вызовы именованных символов; вызовы через пересылающие заглушки / PLT-стабы (реальные вызывающие восстанавливаются, поэтому импорт, доступный только через стаб, не пропускается); и — если vulnfanatic.scanIndirectCalls не выключен — косвенные вызовы через указатель на функцию или vtable, которые Binary Ninja сопоставил с опасной функцией. Для каждого места вызова он строит межпроцедурный, ориентированный на декомпилятор контекст, в пределах лимита токенов (по умолчанию 100k):

  • выражение вызова и его аргументы,
  • объявленный прототип вызываемой функции (из информации о типах Binary Ninja, иначе из встроенной таблицы), чтобы модель правильно сопоставляла аргументы с параметрами — укреплённые варианты __*_chk и проверяющие границы *_s принимают дополнительные ведущие аргументы, сдвигая позицию формата/размера/назначения,
  • тип и размер в байтах каждого аргумента вызова (ёмкости буферов), выводимые из типа выражения HLIL аргумента, так что поле структуры, например s->buf, разрешается в реальный размер массива поля, а не в размер указателя s; определения структур в разделе типов также содержат размеры полей в байтах,
  • конкретное значение / диапазон каждого аргумента, определённые с помощью константного распространения и анализа множества значений Binary Ninja (например, длина, доказанно постоянная 0x40 или ограниченная [0, 0xff]), которые модель использует как эталон при сравнении размера с ёмкостью буфера вместо догадок,
  • раскладка стекового кадра вызывающей функции (смещения переменных и их размеры в байтах), когда она содержит буфер фиксированного размера, чтобы переполнение стека можно было оценивать относительно соседних переменных и сохранённого обратного адреса (vulnfanatic.includeStackLayout),
  • ограничения пути (условия if/циклов/switch, защищающие вызов),

Этот контекст вместе со специальным для правила запросом отправляется модели, которая возвращает структурированный вердикт. Не-проблемы отбрасываются. Запросы настроены на сильную локальную модель кода (например, Qwen2.5-Coder) и предписывают ей проанализировать весь поток и выдать только JSON.

Рассуждения, черновик и уверенность

Модели предписано отдавать предпочтение полноте (recall) — сообщать о правдоподобных, значимых для безопасности проблемах и выражать неуверенность через Confidence, а не отбрасывать то, что она не может полностью доказать. Она показывает свою работу в черновике (scratchpad), который цитирует дословные фрагменты кода, на которые она опиралась (исходный источник, каждую защиту, размер/длину, соответствующий тип и приёмник), и который сохраняется в находке, чтобы вы могли проверить рассуждения.

Каждая находка несёт Confidence (high/medium/low): high = вся цепочка показана в контексте; medium = вероятно, с одной-двумя предполагаемыми связями; low = зацепка, заслуживающая ручной проверки. Это главный показатель (оценка серьёзности модели — вторичное поле). Установите vulnfanatic.minConfidence, чтобы отбрасывать всё ниже порога.

Настройка точности и полноты

По умолчанию VulnFanatic-NG отдаёт предпочтение полноте (выявлению реальных проблем). Если ложных срабатываний слишком много, ужесточите настройки любым из способов:

  • vulnfanatic.validationPass (по умолчанию выкл) — запускает второй проход LLM, который перепроверяет каждую помеченную проблему на том же контексте (сверяя фрагменты из черновика и повторно прослеживая поток) и может исправить вердикт или уверенность. Удваивает вызовы LLM для помеченных кандидатов.
    • Отдельная модель валидатора (рекомендуется при использовании прохода валидации). Укажите vulnfanatic.validatorModel (и validatorProvider / validatorBaseUrl / validatorApiKey), чтобы запустить второй проход на другой модели. Второе мнение гораздо полезнее от независимой модели — у неё меньше общих слепых зон и гораздо меньше вероятность бездумно одобрить первый вердикт (модели склонны предпочитать собственные ответы). Хороший паттерн — каскад: быстрая модель в роли аналитика (широкая полнота) и ваша самая сильная модель в роли валидатора, который запускается только на помеченных кандидатах. Оставьте модель валидатора пустой, чтобы проверять моделью аналитика. Валидатор должен быть по крайней мере не слабее аналитика — более слабый в основном добавляет ложные отклонения. Всё, кроме провайдера/базового URL/ключа/ модели, наследуется из настроек подключения аналитика; пустой ключ валидатора повторно использует ключ аналитика; а если конечная точка валидатора недоступна, сохраняется первый вердикт (находка никогда не теряется из-за сбоя валидатора).
  • vulnfanatic.minConfidence (по умолчанию low) — поднимите до medium/, чтобы сообщать только о более сильных находках.

Скорость. Основная задержка на вызов приходится на записываемые рассуждения, поэтому vulnfanatic.verdictReasoning управляет тем, сколько модель пишет:

  • concise (по умолчанию) — краткое обоснование на 1–3 предложения, без дословного кода. Намного быстрее full с небольшой потерей точности; можно также снизить vulnfanatic.maxResponseTokens.
  • full — подробный черновик с цитируемыми фрагментами (наиболее проверяемый, самый медленный).
  • none — только вердикт. Самый быстрый; сочетайте его с бэкендом, поддерживающим рассуждения (vulnfanatic.reasoningEffort), чтобы внутреннее мышление модели делало работу. На простой локальной модели none теряет точность (вообще без цепочки рассуждений).

Вспомогательные функции точности, которые всегда включены (они информируют модель, не подавляя находки):

  • Происхождение аргументов — контекст сообщает модели для каждого аргумента, является ли он константой времени компиляции, параметром функции или производным от заражённого источника, и модель использует это для установки уверенности.
  • Учёт вариантов с проверкой границ — запросы рассматривают варианты _s (Annex K) и _chk (FORTIFY), а также API с ограничением длины как безопасные, если только сам аргумент размера не неверен.
  • Явные размеры буферов — предоставляются ёмкости аргументов и полей структур в байтах, чтобы модель сравнивала ёмкость с записанными байтами, а не гадала.

Офлайн-сканирование (без LLM)

Кнопка Scan Offline запускает фазу 1 без модели — чисто программные эвристики, объявленные в блоке offline каждого правила в phase1_rules.json. Она помечает опасные места вызовов и исключает заведомо безопасные, присваивая эвристический Confidence:

  • Исключена (не сообщается): memcpy/memmove с константной длиной, strcpy из константной строки, printf с константным форматом, system с константной командой и т. д. — вызовы, чей управляющий аргумент является константой времени компиляции и поэтому не может контролироваться атакующим. «Константа» включает значения, которые анализ множества значений Binary Ninja зафиксировал выше по потоку, а не только буквальные аргументы.
  • High уверенность: помечено без каких-либо смягчающих проверок, найденных где-либо в потоке выполнения.
  • Понижена (→ medium): аргумент размера/длины либо был сведён анализом множества значений Binary Ninja к константному/ограниченному диапазону, либо где-то в потоке найдена реальная проверка границ/валидации, сравнивающая соответствующий аргумент (например, сравнение strlen/размера, if (len < …)) — в том числе в функциях, вызываемых по пути, — так что он, возможно, уже обработан. (Ветвь, которая лишь упоминает переменную без сравнения, больше не учитывается, что устраняет источник ложных понижений.)

Эвристики используют небольшой декларативный словарь в правилах (constant_safe_args, eliminate_if_all_args_constant, format_arg_lookup, length_guard_vars, base_confidence, skip), вычисляемый предикатами Python — без встроенного кода для exec. У большинства правил есть офлайн-определение (переполнение, форматная строка, выполнение команд, scanf, обработка путей, слабый ГПСЧ, слабый числовой разбор, изменение привилегий, размер выделения, …). Только две категории, которым действительно нужен семантический анализ, пропускаются в офлайне и оставляются LLM: семейство free/delete (use-after-free / double-free, требующее отслеживания времени жизни указателей) и проверка TLS (ошибка заключается в конкретном константном значении, например SSL_VERIFY_NONE). Офлайн-сводка сообщает, сколько мест было помечено / исключено / пропущено (нужна LLM) / не удалось, так что суммы сходятся. Это быстрая сортировка; для настоящего суждения — и для пропущенных категорий — запустите полное сканирование LLM.

Офлайн-находки по-прежнему строят тот же полный межпроцедурный контекст, который отправило бы онлайн-сканирование (только для помеченных мест), и сохраняют его, так что после сортировки их можно экспортировать как данные для тонкой настройки, как и онлайн-находки. Отключите через vulnfanatic.offlineBuildContext, если нужна максимальная офлайн-скорость.

Фаза 2 — код, чувствительный к безопасности (только при наличии символов)

Запускается только тогда, когда в бинарном файле, судя по всему, есть реальные символы / имена переменных. Находит чувствительные к безопасности функции, определённые в rules/phase2_rules.json, — аутентификация, криптография (вкл. слабые алгоритмы), проверка подписей/сертификатов, обработка сессий/токенов, контроль доступа, обработка секретов/ключей, валидация ввода, непостоянное по времени сравнение секретов и небезопасная десериализация, — сопоставляя по имени функции и строкам, на которые есть ссылки, а затем анализирует модель.

Фаза 3 — аудит защиты от аппаратных атак (онлайн, по запросу)

Аудит укрепления прошивки против атак с внесением сбоев (glitching по напряжению/тактовой частоте/ЭМИ) и побочных каналов (время/потребление), основанный на рекомендациях по смягчению аппаратных атак. В отличие от фаз 1–2 (которые находят ошибки), фаза 3 сообщает об отсутствующем или нарушенном контроле укрепления в функции, критичной для безопасности, — например: ветви с отказом по умолчанию, дважды проверенные решения безопасности, проверка счётчика после цикла, константы состояния с большим расстоянием Хэмминга (вместо простых 0/1), постоянное по времени сравнение секрета полной длины, доступ/очистка секрета со случайным смещением, шифрование-затем-проверка (анти-DFA), счётчики целостности потока управления, отказ от криптографии в пользовательском пространстве и отсутствие прямой работы с сырым ключевым материалом (rules/phase3_rules.json).

Поскольку оптимизации компилятора могут удалять защиту на уровне исходного кода, эти контроли лучше всего проверять на скомпилированном бинарном файле — именно это и делается. Фаза 3 — только LLM (онлайн), зависит от символов и отключена по умолчанию; включайте её для каждого сканирования флажком Phase 3 на вкладке New Scan (в офлайн-режиме она не запускается).

Находки перечислены в таблице (status, confidence, phase, CWE, function, address, title) с панелью деталей, показывающей объяснение, черновик анализа и заметки валидации. Двойной щелчок по строке перемещает представление бинарного файла к коду.

Рабочий процесс сортировки

Каждая находка начинается со статуса Untriaged. Щёлкните правой кнопкой по строке, чтобы задать статус — Mark as Real Issue, Mark as False Positive или Mark as Untriaged. При каждом изменении статуса появляется текстовое поле "Provide reason:" (причина сохраняется вместе с находкой). Таблица делает статус наглядным: Real Issues — зелёные/жирные и сортируются вверх, False Positives — серые/зачёркнутые и сортируются вниз, Untriaged находятся между ними со своим цветом уверенности. Сводная строка показывает количество.

На каждой вкладке результатов есть кнопка Export triaged (fine-tuning)…, которая экспортирует только отсортированные находки (Real Issue + False Positive) как JSONL в формате чата OpenAI для тонкой настройки: каждый пример объединяет исходный системный+пользовательский запрос с исправленным человеком вердиктом в качестве целевого ответа ассистента (False Positive учит is_vulnerable=false с вашей причиной; Real Issue закрепляет is_vulnerable=true), так что вы можете итеративно повышать точность модели на ваших бинарных файлах.

Контекст по каждой находке, показываемый на панели деталей (и используемый для восстановления запросов тонкой настройки), по умолчанию сохраняется полностью — этим управляет vulnfanatic.storedContextChars (0 = без ограничений; установите положительный предел, например 4000, чтобы ограничить рост BNDB ценой точности контекста).

Несколько сканирований (вкладки)

Панель работает с вкладками. Первая вкладка — всегда New Scan, где вы задаёте:

  • необязательное имя сканирования (пусто → <timestamp> <mode>, например 2026-06-15 14:03:50 offline),
  • необязательный путь к пользовательским правилам для фаз 1 / 2 / 3 (пусто → встроенные по умолчанию), чтобы можно было запустить альтернативный набор правил,
  • флажок Phase 3 (по умолчанию выключен) для дополнительного запуска онлайн-аудита защиты от аппаратных атак,

затем нажмите Start Scan или Scan Offline. Каждый запуск открывает собственную вкладку результатов, и находки поступают в неё в реальном времени. Все сканирования хранятся в BNDB, так что вы можете, например, сохранить офлайн-сканирование, а позже добавить онлайн-сканирование или сравнить запуски с разными наборами правил бок о бок — они снова появляются как вкладки при повторном открытии базы данных. Закрытие вкладки навсегда удаляет это сканирование из BNDB — во избежание случайностей появляется подтверждение, требующее отметить "I confirm that I will lose the results from forever." перед активацией кнопки Delete results forever. Export current scan… записывает выбранную вкладку в Markdown/JSON.

У каждого открытого бинарного файла своё независимое состояние панели — свои вкладки сканирований и выполняющееся сканирование. Запуск сканирования в одном бинарном файле и переключение на другой показывает результаты второго (и позволяет сканировать его отдельно); сканирование первого продолжает работать в фоне и остаётся нетронутым при переключении обратно.


Установка

Папка пакета этого плагина называется vulnfanatic_ng (допустимый идентификатор Python — Binary Ninja импортирует имя папки плагина как модуль, поэтому имя с дефисом, например VulnFanatic-NG, не загрузилось бы).

  1. (Необязательно) Установите точный подсчёт токенов в Python Binary Ninja: ``` pip install tiktoken

    root@kitploit:~
  2. Создайте символическую ссылку или скопируйте папку vulnfanatic_ng в каталог пользовательских плагинов Binary Ninja:

    • macOS: ~/Library/Application Support/Binary Ninja/plugins/
    • Linux: ~/.binaryninja/plugins/
    • Windows: %APPDATA%\Binary Ninja\plugins\

    Например, на macOS: ``` ln -s "$(pwd)/vulnfanatic_ng" "$HOME/Library/Application Support/Binary Ninja/plugins/vulnfanatic_ng"

    root@kitploit:~
  3. Перезапустите Binary Ninja (или выполните Reload Plugins). В правой боковой панели появится значок VF.


Конфигурация

Откройте Настройки (шестерёнка / Edit ▸ Preferences ▸ Settings) и найдите vulnfanatic. Установите как минимум:

LLM-бэкенды

vulnfanatic.apiProvider определяет, как формируются и аутентифицируются запросы. Контракт вердикта (и все промпты правил) одинаков для всех провайдеров.

AWS Bedrock можно использовать через провайдера openai с его OpenAI-совместимой конечной точкой, поэтому отдельный бэкенд не нужен.

Другие полезные настройки: vulnfanatic.maxContextTokens (по умолчанию 100000), vulnfanatic.maxResponseTokens, vulnfanatic.temperature, vulnfanatic.reasoningEffort (off/low/medium/high; по умолчанию high — просит модель подумать перед ответом, где это поддерживается, с сопоставлением по провайдерам: openai/azure reasoning_effort, anthropic адаптивное мышление + output_config.effort, google динамический thinkingConfig; автоматически удаляется и повторяется, если модель его отвергает), vulnfanatic.requestTimeoutSec, vulnfanatic.callPathMaxDepth / , (включать декомпилированные тела функций вдоль пути вызовов; по умолчанию вкл.) / (предел, по умолчанию 12), (также включать другие функции, вызываемые вдоль пути, которые могут содержать проверки границ/валидации; по умолчанию вкл.) / (предел, по умолчанию 12), (включать определения struct/union/enum; по умолчанию вкл.) / (предел, по умолчанию 24), (прослеживать аргументы вызовов до их производителей /потребителей и включать их тела; по умолчанию вкл.) / (предел, по умолчанию 8), (включать раскладку стековых переменных вызывающей функции, если в ней есть буфер фиксированного размера; по умолчанию вкл.), (также сопоставлять опасные вызовы, отправляемые через разрешённый указатель на функцию/vtable; по умолчанию вкл. — отключите для более быстрого сканирования очень больших бинарных файлов), (выполнять второй проверочный проход; по умолчанию выкл.) / / / / (выполнять проверочный проход на отдельной независимой модели — пусто = та же модель, что у аналитика) / (//; отбрасывать находки ниже этого уровня; по умолчанию ), (сообщать о местах, которые модель не смогла оценить, как лиды с уверенностью ("Unscored") вместо их отбрасывания; по умолчанию вкл.), (пропускать места вызовов переполнения с полностью константными аргументами; по умолчанию выкл.), (//; объём рассуждений, которые модель пишет для каждого вердикта, — главный рычаг скорости; по умолчанию ), / / (включать каждый этап; этап 3 — только для онлайн-сканирования и обычно переключается при каждом сканировании через флажок New Scan, а не здесь), / , (кодировка tiktoken для оценки токенов; при отсутствии tiktoken используется эвристика по символам, если tiktoken не установлен), (строить полный контекст для офлайн-находок, чтобы их можно было экспортировать для дообучения; по умолчанию вкл.), (подробный трассировочный вывод конвейера в консоль; по умолчанию выкл.) / (редактировать все детали, идентифицирующие бинарный файл, чтобы лог можно было передавать другим — см. ниже), , (проверять HTTPS сертификаты; по умолчанию вкл.) / (набор CA для HTTPS — см. раздел Troubleshooting, если вы столкнулись с ), и / / (укажите эти параметры на свои файлы правил, чтобы настроить обнаружения и промпты).

Замечание по безопасности: API-ключ хранится в настройках Binary Ninja в открытом виде. Для чувствительных ключей предпочтительнее переопределение через переменную окружения.

Тестовый режим (пробный запуск без LLM)

Установите vulnfanatic.apiBaseUrl в буквальное значение TEST, чтобы запустить без LLM:

  • Модель никогда не вызывается (не нужны ни сеть, ни API-ключ/модель).
  • Помечается каждый кандидат (каждое опасное место вызова на этапе 1, каждая чувствительная к безопасности функция на этапе 2).
  • Полный промпт — системный промпт и полный сгенерированный контекст — для каждого кандидата записывается в отдельный файл в каталоге /tmp/vulnfanatic_ng/<binary>-<timestamp>/.
  • В таблице находок появляется столбец Prompt File (при наведении виден полный путь), а панель сведений и экспорт включают этот путь.

Используйте это, чтобы проверить и убедиться, что именно VulnFanatic-NG отправил бы модели, и чтобы итерировать промпты/контекст правил, не тратя время модели.

Отладочное журналирование

Включите vulnfanatic.debugLogging, чтобы выводить подробную пошаговую трассировку конвейера сканирования (и онлайн, и офлайн) в журнал/консоль Binary Ninja: каждое место вызова, каждое решение о пропуске/исключении, сбор контекста (только размер), каждый LLM-запрос (провайдер/модель/конечная точка, повторы, fallback'и), каждый вердикт и каждую найденную находку. API-ключи никогда не записываются в журнал.

Пока включено отладочное журналирование, онлайн-сканирование сохраняет каждого кандидата в таблице результатов, вместо того чтобы отбрасывать тех, кто не стал подтверждённой проблемой; каждый помечен статусом, доступным только в режиме отладки (затемнён, отсортирован вниз):

  • REJECTED — LLM вернул вердикт не проблема.
  • SKIPPED — исключён до LLM по доказуемо безопасному правилу (константная форматная строка или полностью константные аргументы); строка объясняет, какое именно.
  • ERROR — кандидата не удалось проанализировать (не удалось собрать контекст, либо ответ LLM не удалось разобрать / соединение не удалось); строка содержит ошибку.

Таким образом, отладочное сканирование показывает по одной строке на каждого кандидата в общем количестве /N, а сводка отдельно сообщает количество проблем и отклонённых/пропущенных/ошибочных. Вы можете щёлкнуть правой кнопкой мыши по любой из этих строк, чтобы переклассифицировать её как Real Issue или False Positive (что делает её пригодной для экспорта на дообучение). (Офлайн-сканирования не затрагиваются — они никогда не вызывают LLM.)

Независимо от режима отладки, когда модель возвращает неразбираемый ответ — случайный токен вроде <unused…> у Gemma, прозу вместо JSON или пустое сообщение (только role, без content) — клиент делает одну корректирующую повторную попытку, снова запрашивая JSON только с отключённым форматом структурированного вывода; если это удаётся, он оставляет формат выключенным до конца сканирования. Клиент также читает канал рассуждений (reasoning_content / reasoning), когда content пуст, поэтому reasoning-модели, помещающие ответ туда, тоже работают.

Случай пустого сообщения часто встречается у reasoning-моделей, таких как GPT-OSS / o1, обслуживаемых через OpenAI-совместимый API (например, mlx-community/gpt-oss-20b): при установленном response_format=json_object канал "final"-ответа harmony часто подавляется, и сервер возвращает {"role": "assistant"} без содержимого. Эти модели также могут израсходовать весь свой бюджет вывода на канал рассуждений и быть обрезанными на середине мысли, возвращая прозу вообще без JSON. Автоповтор исправляет случаи, связанные с форматом; если это продолжается, отключите vulnfanatic.sendJsonResponseFormat, уменьшите vulnfanatic.reasoningEffort (чтобы на размышления уходило меньше бюджета) и/или увеличьте vulnfanatic.maxResponseTokens. Устойчивый ответ <unused…>/мусор обычно означает, что промпт превышает окно контекста модели (задайте vulnfanatic.modelContextWindow и/или увеличьте длину контекста на сервере), или что модель плохо подходит для строгого JSON-вывода (кодовая модель вроде Qwen2.5-Coder ведёт себя здесь гораздо лучше, чем Gemma).

Фолбэк, сохраняющий полноту. Когда кандидата по-прежнему не удаётся оценить после повторной попытки, vulnfanatic.flagUnparseableResponses (по умолчанию вкл.) всё равно сообщает о нём как о находке "Unscored" с уверенностью UNKNOWN — значением, отличным от low (модель никогда не выносила вердикт, так что это не низкоуверенное суждение), которое сортируется вниз, — сохраняя частичный вывод модели в качестве объяснения; таким образом, вы не теряете место, а просто просматриваете его вручную. Отключите эту опцию, чтобы вместо этого отбрасывать такие места (тогда они появляются только как ошибки анализа или строки ERROR в отладочном режиме).

Также включите vulnfanatic.debugAnonymous, чтобы сделать лог безопасным для передачи: он редактирует всё, что может идентифицировать анализируемый файл — имена символов/переменных и адреса становятся хешами с солью для каждого запуска (при этом консистентны в рамках запуска, чтобы поток был прослеживаем), имя файла скрывается, текст находок заменяется на <redacted>, хост LLM-эндпоинта хешируется, а декомпилированный код / промпты / контекст логируются только как размеры (не содержимое). Поэтому вы можете отправить отладочный лог для сообщения о проблеме, не раскрывая ничего о вашем бинарном файле.


Использование

  1. Откройте бинарный файл и дождитесь завершения анализа.
  2. Нажмите значок VF на боковой панели, чтобы открыть VulnFanatic-NG.
  3. Нажмите Start Scan (полное LLM-сканирование) или Scan Offline (быстрый программный этап 1 без LLM — см. выше). Ход выполнения отображается на панели и в строке состояния Binary Ninja; находки появляются в реальном времени, сканирование можно отменить.
  4. Нажмите на находку, чтобы прочитать объяснение; двойной щелчок переходит к коду.
  5. Щёлкните правой кнопкой по находке, чтобы выбрать Mark as false positive — она переместится вниз таблицы, станет серой и зачёркнутой, а пункт меню изменится на Mark as real issue для отмены. (В контекстном меню также есть Go to code.)
  6. Export в Markdown или JSON или Clear, чтобы удалить сохранённые находки.

Находки — включая их статус ложного срабатывания — хранятся в базе данных Binary Ninja. Они записываются в .bndb при сохранении базы данных (и немедленно сбрасываются, если .bndb уже существует), поэтому они переживают повторное открытие.

Сканирование анализирует каждое подходящее место вызова (без ограничения), что уместно для локальных моделей. Для размещённого/платного эндпоинта учитывайте объём на больших бинарных файлах.


Настройка правил

Оба файла правил используют общую обёртку с общим system_prompt и output_schema, а также список rules. Скопируйте входящий в комплект файл, отредактируйте функции/ключевые слова/промпты и укажите vulnfanatic.rulesPhase1Path / vulnfanatic.rulesPhase2Path на свою копию. Правила этапа 1 сопоставляются по functions (точно) и name_regex; правила этапа 2 — по name_keywords, name_regex и string_keywords. В prompt каждого правила можно использовать плейсхолдер {function}.


Дообучение модели (MLX, Apple Silicon)

Экспорт после триажа предназначен для прямой подачи обратно в модель. После триажа находок по нескольким бинарным файлам и нажатия Export triaged (fine-tuning)… на каждом (сбор файлов .jsonl в одну папку), scripts/finetune_mlx.py выполняет на них MLX LoRA-дообучение.```bash pip install mlx-lm # Apple Silicon / macOS

Fine-tune a local 4-bit model on every *.jsonl under ./exports

python scripts/finetune_mlx.py ./exports
--model mlx-community/Qwen2.5-Coder-7B-Instruct-4bit
--adapter-path ./vf-adapters --iters 800

...then fuse the adapters into a standalone model

python scripts/finetune_mlx.py ./exports --model
--fuse --fused-path ./vf-qwen-coder-vuln

root@kitploit:~
Скрипт принимает **папку training-data** в качестве позиционного аргумента и
базовую **`--model`** (локальный путь или идентификатор репозитория MLX/HF); остальные параметры необязательны:
`--adapter-path`, `--valid-split` (0.1), `--iters`, `--batch-size` (автоматически ограничивается до
соответствия небольшому разбиению), `--num-layers`, `--learning-rate`, `--max-seq-length`
(`0` = **автоподбор** по самому длинному примеру, с ограничением до 16384; укажите положительное значение, чтобы
принудительно задать его), `--fine-tune-type` (`lora`/`dora`/`full`), `--seed`, `--fuse`/`--fused-path`,
и `--dry-run` (подготовить данные + вывести команду без обучения). Всё, что указано после
литерального `--`, передаётся дословно в `mlx_lm lora`. Он рекурсивно объединяет все
файлы `*.jsonl` в папке, проверяет и **дедуплицирует** чат-примеры, создаёт
разбиение `train.jsonl`/`valid.jsonl`, которое ожидает MLX, затем запускает `python -m mlx_lm lora`
(и `mlx_lm fuse` с параметром `--fuse`).

Опубликуйте результат с помощью OpenAI-совместимого сервера (`mlx_lm.server --model <path>`)
и укажите `vulnfanatic.apiBaseUrl` на него, чтобы сканировать с вашей дообученной моделью.

> Контексты VulnFanatic-NG велики, поэтому по умолчанию скрипт **автоподбирает**
> `--max-seq-length` под ваш самый длинный пример (с округлением вверх, с ограничением в **16384 токена**).
> Длинные последовательности занимают основную часть памяти при обучении, поэтому большая модель вблизи этого предела может вызвать
> нехватку памяти на Mac поменьше. Если ваши примеры превышают предел, они усекаются — передайте
> большее `--max-seq-length` (больше памяти) или уменьшите `vulnfanatic.storedContextChars`
> перед экспортом. Если обучение прерывается сигналом (например, `exit -10` / SIGBUS), это
> сбой из-за нехватки памяти: уменьшите `--max-seq-length`, добавьте `-- --grad-checkpoint` или используйте
> модель поменьше.

---

## Разработка и тестирование

У плагина нет обязательных сторонних зависимостей. Чистые модули
(`rules`, `tokens`, `llm`, `findings`, `settings`, `prototypes`) покрыты
автономным набором тестов, которому не нужны ни Binary Ninja, ни сеть. Набор `tests/`
находится в исходном репозитории проекта (он не поставляется внутри
публикуемого плагина); запускайте его оттуда. Из каталога пакета вы по-прежнему можете
проверить синтаксис каждого модуля:```
python3 -m py_compile *.py ui/*.py
python3 -m unittest discover -s tests   # from the source repository

Модули, ориентированные на Binary Ninja (context_builder, phase1, phase2), импортируются без Binary Ninja без проблем (их доступ к API защищён), но для работы требуют запущенного Binary Ninja.

Ручной тест внутри Binary Ninja

  1. Соберите небольшую уязвимую программу на C (например, такую, которая strcpy из argv[1] в фиксированный стековый буфер и вызывает system() для входных данных). Скомпилируйте с символами, чтобы также задействовать фазу 2.
  2. Запустите локальный сервер, совместимый с OpenAI, и задайте vulnfanatic.apiBaseUrl, vulnfanatic.apiKey и vulnfanatic.model.
  3. Откройте бинарный файл, запустите Start Scan, и убедитесь, что опасные вызовы сообщаются, а двойной щелчок переходит к местам вызовов.

Устранение неполадок

SSL: CERTIFICATE_VERIFY_FAILED ... unable to get local issuer certificate — сертификат HTTPS-эндпоинта в порядке, но в комплектном Python из Binary Ninja нет набора корневых сертификатов (CA bundle) для его проверки (часто встречается на macOS и во встроенных Python; вы увидите это у хостинг-эндпоинтов вроде AWS Bedrock, Anthropic, Google, Azure). Исправляется одним из следующих способов, в порядке предпочтения:

  • Установите certifi в Python, который использует Binary Ninja: pip install certifi. VulnFanatic-NG подхватит его автоматически.
  • Укажите на CA bundle: задайте vulnfanatic.caBundlePath как путь к файлу пакета (или каталогу) — например, путь, выводимый python3 -m certifi, или /etc/ssl/cert.pem.
  • Крайний случай: отключите vulnfanatic.tlsVerify (только для доверенного/внутреннего эндпоинта или локального сервера с самоподписанным сертификатом — это отключает проверку сертификатов).

HTTP 400 ... tokenizer.chat_template is not set — у обслуживаемой вами модели нет chat-шаблона, поэтому эндпоинт /chat/completions не может форматировать сообщения. VulnFanatic-NG автоматически переключается на эндпоинт /completions для остальной части сканирования, когда видит эту ошибку, поэтому сканирование продолжается. Чтобы полностью избежать первого неудачного запроса, установите vulnfanatic.apiMode в completions. Альтернативно, исправьте это на стороне сервера, обслуживая модель с chat-шаблоном, или передайте его вашему серверу — например, для vLLM: --chat-template <template.jinja> (или используйте вариант модели -Instruct/-Chat). Специализированный chat-шаблон обычно даёт лучшие результаты, чем плоский промпт completions.

No JSON object found ... response looks truncated — ответ модели был обрезан до завершения JSON. Две причины:

  • Черновик (scratchpad) превысил бюджет ответа → увеличьте vulnfanatic.maxResponseTokens.
  • Чаще всего: промпт заполняет контекстное окно модели, не оставляя места для генерации, поэтому ответ обрывается после нескольких токенов независимо от того, насколько велико maxResponseTokens. Локальные серверы часто имеют небольшое окно (ollama по умолчанию использует num_ctx=2048!). Исправьте это, установив vulnfanatic.modelContextWindow в значение окна вашего сервера (например, ollama num_ctx, llama.cpp -c, vLLM --max-model-len) — VulnFanatic-NG затем автоматически ограничивает отправляемый контекст, чтобы промпт + ответ помещались. Также держите vulnfanatic.maxResponseTokens разумным (≈8192, а не 65535) и/или увеличьте окно сервера. Крошечные окна (≤8k) не могут вместить полный межпроцедурный контекст; используйте модель/сервер, настроенные на 32k+.

IncompleteRead / Could not complete request ... after N attempt(s) — сервер принял запрос, но закрыл соединение до отправки полного ответа. Это почти всегда означает, что сервер модели завершился или завис в процессе генерации: нехватка памяти (большой контекст + длинный вывод), внутренний/рабочий тайм-аут или прокси, сбрасывающий соединение. VulnFanatic-NG автоматически повторяет попытку один раз, а затем пропускает этот сайт. Проверьте собственные журналы сервера модели, чтобы найти настоящую причину; уменьшение vulnfanatic.maxContextTokens и/или vulnfanatic.maxResponseTokens или выделение серверу больше памяти / большего контекстного окна обычно решает проблему.

Ограничения

  • Фаза 2 зависит от символов. В stripped binary сопоставления по именам ненадёжны, поэтому по умолчанию выполняются только правила строковых улик (функции, ссылающиеся на характерные строковые константы, по-прежнему можно проверять). Установите vulnfanatic.phase2ForceEnable, чтобы также проверять сопоставления по именам, или vulnfanatic.phase2RequireSymbols=off. Символьный фильтр — эвристика.
  • Сопоставление HLIL ↔ места вызовов может давать сбои; VulnFanatic-NG переключается на MLIL/ассемблер и отмечает, какое представление использовано для каждой находки.
  • Вердикты настолько хороши, насколько хороша модель. Относитесь к находкам как к зацепкам для ручной проверки, а не как к истине в последней инстанции.
  • Некоторые локальные серверы игнорируют или отклоняют response_format=json_object; клиент терпимо относится к этому и всё равно извлекает JSON. Отключите vulnfanatic.sendJsonResponseFormat, если ваш сервер полностью отклоняет этот параметр.

Лицензия

Apache-2.0 (© Martin Petran) — см. plugin.json.

Скачать инструмент
  • сводка потока данных аргументов — где каждый аргумент вызова определяется и используется внутри функции,
  • разрешение параметров по вызывающим — когда опасный аргумент является параметром вызывающей функции, контекст сообщает, что фактически передаёт каждый вызывающий (например, «все вызывающие передают строковый литерал»), чтобы параметр формата/ размера, который всегда постоянен, не был принят за контролируемый атакующим,
  • полное декомпилированное тело вызывающей функции,
  • определения типов данных (struct/union/enum) для типов, на которые ссылаются цепочка вызовов и переменные аргументов, чтобы модель знала реальные размеры буферов/полей и ширину целых чисел,
  • декомпилированные тела функций, которые производят или используют переменные аргументов вызова (отслеживаемые через определение/использование HLIL), что и делает возможным анализ use-after-free / double-free и заражённых размеров,
  • пути вызовов от точек входа / экспортируемых функций до вызова,
  • декомпилированное тело каждой функции на этих путях вызовов (сначала ближайшей к опасному вызову), каждая с аннотацией места вызова и условий, защищающих следующий переход,
  • тела других функций, которые вызывают функции пути (например, для MAIN→ABCD→strcpy также функции, которые MAIN и ABCD вызывают в других местах), поскольку в них могут находиться проверки границ/валидации, управляющие опасным значением (vulnfanatic.includeCallPathSiblings, заполняется, пока позволяет бюджет), и
  • подсказки о заражённых источниках (входные функции, такие как recv/read/getenv, вызываемые в той же функции).
  • high
  • vulnfanatic.skipConstantArgCalls (по умолчанию выкл) — пропускать места вызовов класса переполнения, все аргументы которых являются константами времени компиляции.
  • SettingMeaning
    vulnfanatic.apiProviderКакой LLM-бэкенд вызывать: openai (по умолчанию), anthropic, google или azure. См. LLM backends ниже. Все провайдеры доступны через стандартную библиотеку Python — ничего pip install не требуется.
    vulnfanatic.apiBaseUrlБазовый URL конечной точки для выбранного провайдера (см. таблицу ниже). По умолчанию http://localhost:8080/v1. Установите буквальное значение TEST, чтобы включить тестовый режим (см. ниже).
    vulnfanatic.apiKeyAPI-ключ / bearer-токен. Может быть пустым для локальных серверов. Переопределяется переменными окружения VULNFANATIC_API_KEY или OPENAI_API_KEY.
    vulnfanatic.modelОбязательно (кроме тестового режима). Идентификатор модели (для azure — имя развёртывания).
    vulnfanatic.apiModeТолько для openai: chat (по умолчанию, /chat/completions) или completions (один плоский промпт — для базовых/instruct-моделей, обслуживаемых без чат-шаблона).
    vulnfanatic.azureApiVersionТолько для azure: параметр запроса api-version (по умолчанию 2024-10-21).
    ProviderapiBaseUrlАутентификацияПримечания
    openaiваш сервер, напр. http://localhost:8080/v1Authorization: BearerOpenAI-совместимые Chat/Completions: локальные llama.cpp / ollama / vLLM, OpenAI и OpenAI-совместимая конечная точка AWS Bedrock.
    anthropicпусто → https://api.anthropic.comx-api-key + anthropic-versionClaude Messages API (POST <base>/v1/messages). temperature не отправляется (текущие модели Claude отвергают его).
    googleпусто → https://generativelanguage.googleapis.comAPI-ключ в URLGemini generateContent (<base>/v1beta/models/<model>:generateContent).
    azurehttps://<resource>.openai.azure.comзаголовок api-keyAzure OpenAI; задайте model как имя развёртывания, а azureApiVersion — как вашу версию API.
    vulnfanatic.callPathMaxPaths
    vulnfanatic.callPathIncludeBodies
    vulnfanatic.callPathMaxBodies
    vulnfanatic.includeCallPathSiblings
    vulnfanatic.callPathSiblingMaxBodies
    vulnfanatic.includeDataTypes
    vulnfanatic.maxTypeDefs
    vulnfanatic.includeVariableDataflow
    vulnfanatic.dataflowMaxFunctions
    vulnfanatic.includeStackLayout
    vulnfanatic.scanIndirectCalls
    vulnfanatic.validationPass
    vulnfanatic.validatorModel
    vulnfanatic.validatorProvider
    vulnfanatic.validatorBaseUrl
    vulnfanatic.validatorApiKey
    vulnfanatic.minConfidence
    low
    medium
    high
    low
    vulnfanatic.flagUnparseableResponses
    UNKNOWN
    vulnfanatic.skipConstantArgCalls
    vulnfanatic.verdictReasoning
    concise
    full
    none
    concise
    vulnfanatic.runPhase1
    vulnfanatic.runPhase2
    vulnfanatic.runPhase3
    vulnfanatic.phase2RequireSymbols
    vulnfanatic.phase2ForceEnable
    vulnfanatic.tokenizerEncoding
    vulnfanatic.offlineBuildContext
    vulnfanatic.debugLogging
    vulnfanatic.debugAnonymous
    Debug logging
    vulnfanatic.sendJsonResponseFormat
    vulnfanatic.tlsVerify
    vulnfanatic.caBundlePath
    CERTIFICATE_VERIFY_FAILED
    vulnfanatic.rulesPhase1Path
    vulnfanatic.rulesPhase2Path
    vulnfanatic.rulesPhase3Path