
Plugin do BianryNinja para identificar vulnerabilidades em binários descompilados com varreduras programáticas e suporte a LLM.
Pesquisa de vulnerabilidades assistida por LLM para Binary Ninja.
VulnFanatic-NG adiciona um painel lateral que analisa o binário atual e pergunta a uma LLM — um modelo compatível com OpenAI hospedado localmente por padrão, ou Anthropic Claude, Google Gemini, ou Azure OpenAI (veja Backends LLM) — para julgar se um código suspeito é realmente vulnerável. Funciona principalmente a partir da saída do descompilador (HLIL) do Binary Ninja, recorrendo ao assembly quando necessário, e relata apenas problemas confirmados com referências clicáveis de volta ao código.
Uma varredura é executada em até três fases (Fase 3 é opcional e somente online):
Encontra locais de chamada de funções perigosas definidas em
rules/phase1_rules.json — strcpy,
memcpy, sprintf/strings de formato, system, alloca, scanf, APIs de comando/exec,
RNG fraco, a família free/delete (use-after-free / double-free),
leitura de entrada não confiável para buffers fixos (recv/read/fread/ReadFile),
injeção SQL (sqlite3_exec/mysql_query/PQexec), verificação de certificado TLS
desabilitada (SSL_CTX_set_verify/curl), SSRF, e gerenciamento inadequado
de privilégios (setuid/setresgid), a família memset/bzero, e
comparações com um comprimento controlado pelo atacante (memcmp/strncmp →
bypass de autenticação), em C/C++, Win32, e (melhor esforço) Rust FFI. A cobertura
inclui variantes fortificadas _chk (FORTIFY) e _s (Anexo-K). Funções de saída
formatada com limite (snprintf e variantes) têm sua própria regra segura padrão para que
um argumento de tamanho correto não seja relatado como estouro. Os locais de chamada são
encontrados de três maneiras: chamadas diretas para os símbolos nomeados; chamadas roteadas
através de thunks de encaminhamento / stubs PLT (os chamadores reais são recuperados,
para que uma importação alcançada apenas através de um stub não seja perdida); e — a menos
que vulnfanatic.scanIndirectCalls esteja desligado — chamadas indiretas despachadas através de um
ponteiro de função ou vtable que o Binary Ninja resolveu para uma função perigosa.
Para cada local de chamada, ele constrói um contexto interprocedural, centrado no descompilador,
orçado para um limite de tokens (padrão 100k):
__*_chk e *_s com verificação de limites recebem
argumentos iniciais extras, deslocando a posição do formato/tamanho/destino,s->buf
resolva para o tamanho real do array do campo em vez do tamanho do ponteiro de s;
definições de struct na seção de tipos também carregam tamanhos de campo em bytes,0x40
ou limitado a [0, 0xff]), que o modelo usa como verdade ao comparar um
tamanho com a capacidade do buffer em vez de adivinhar,vulnfanatic.includeStackLayout),if/loop/ que protegem a chamada),Esse contexto mais um prompt específico para a regra é enviado ao modelo, que retorna um veredito estruturado. Não-problemas são descartados. Os prompts são ajustados para um modelo de código local forte (por exemplo, Qwen2.5-Coder) e instruem o modelo a analisar todo o fluxo e emitir apenas JSON.
O modelo é instruído a favorecer recall — relatar problemas plausíveis e relevantes para segurança e expressar incerteza através de uma Confiança em vez de descartar algo que não pode provar completamente. Ele mostra seu trabalho em um rascunho que cita os trechos de código textuais nos quais se baseou (a fonte de entrada, cada guarda, o tamanho/comprimento, o tipo relevante e o sumidouro), que é armazenado no achado para que você possa auditar o raciocínio.
Cada achado carrega uma Confiança (alta/média/baixa): alta = toda a cadeia é mostrada
no contexto; média = provável, com um ou dois elos inferidos; baixa = uma pista que merece
revisão manual. Esta é a métrica principal (a estimativa de severidade do modelo é um
campo secundário). Defina vulnfanatic.minConfidence para descartar qualquer coisa abaixo de um limite.
Por padrão, o VulnFanatic-NG favorece recall (capturar problemas reais). Se obtiver muitos falsos positivos, restrinja com qualquer um destes:
vulnfanatic.validationPass (padrão desligado) — executa uma segunda passagem do LLM que
verifica novamente cada problema sinalizado com o mesmo contexto (verificando os trechos
do rascunho e refazendo o fluxo) e pode corrigir o veredito ou
confiança. Dobra as chamadas LLM para candidatos sinalizados.
vulnfanatic.validatorModel (mais validatorProvider / validatorBaseUrl /
validatorApiKey) para executar a segunda passagem em um modelo diferente. Uma segunda
opinião é muito mais útil vinda de um modelo independente — ele compartilha menos pontos
cegos e é muito menos propenso a carimbar o primeiro veredito (modelos tendem a
preferir suas próprias respostas). Um bom padrão é uma cascata: um modelo rápido como analista
(amplo recall) e seu modelo mais forte como validador, que só é executado
sobre candidatos sinalizados. Deixe o modelo validador em branco para validar com o
modelo analista. O validador deve ser pelo menos tão capaz quanto o analista —
um mais fraco geralmente adiciona falsas rejeições. Tudo, exceto provedor/base URL/chave/
modelo, é herdado das configurações de conexão do analista; uma chave do validador em branco
reutiliza a chave do analista; e se o endpoint do validador estiver inacessível, o primeiro
veredito é mantido (o achado nunca é perdido para uma falha do validador).vulnfanatic.minConfidence (padrão low) — aumente para / para relatar apenas
achados mais fortes.Velocidade. A maior latência por chamada é o raciocínio escrito, então
vulnfanatic.verdictReasoning controla quanto o modelo escreve:
concise (padrão) — uma breve justificativa de 1–3 frases, sem código textual. Muito
mais rápido que full com pouca perda de precisão; você também pode reduzir
vulnfanatic.maxResponseTokens.full — o rascunho detalhado com trechos citados (mais auditável, mais lento).none — apenas veredito. Mais rápido; combine-o com um backend capaz de raciocínio
(vulnfanatic.reasoningEffort) para que o pensamento interno do modelo faça o trabalho.
Em um modelo local simples, none perde precisão (nenhum chain-of-thought).Recursos de precisão que estão sempre ativos (informam o modelo sem suprimir achados):
_s (Anexo K) e
_chk (FORTIFY) e APIs com limite de comprimento como seguras a menos que o argumento
de tamanho em si esteja errado.O botão Scan Offline executa a Fase 1 com nenhum modelo — heurísticas puramente
programáticas declaradas no bloco offline de cada regra em phase1_rules.json. Ele
sinaliza locais de chamada perigosos e elimina os obviamente seguros, atribuindo uma
Confiança heurística:
memcpy/memmove com um comprimento constante, um
strcpy de uma string constante, um printf com um formato constante, um system
com um comando constante, etc. — chamadas cujo argumento governante é uma constante
de tempo de compilação e, portanto, não pode ser controlado pelo atacante. "Constante" inclui valores
que a análise de conjunto de valores do Binary Ninja fixou em um número fixo a montante, não apenas
argumentos literais.strlen/tamanho, if (len < …)) foi encontrada em algum lugar no fluxo —
inclusive nas funções chamadas ao longo do caminho — então pode já estar tratado. (Um ramo que
meramente menciona a variável sem compará-la não conta mais, removendo uma fonte de
rebaixamentos espúrios.)As heurísticas usam um pequeno vocabulário declarativo nas regras
(constant_safe_args, eliminate_if_all_args_constant, format_arg_lookup,
length_guard_vars, base_confidence, skip) avaliadas por predicados Python —
nenhum código embutido para exec. A maioria das regras tem uma definição offline (estouro,
string de formato, execução de comando, scanf, manipulação de caminho, RNG fraco, parsing numérico fraco,
mudanças de privilégio, tamanho de alocação, …). Apenas as duas categorias que genuinamente precisam
de análise semântica são ignoradas offline e deixadas para o LLM: a família free/delete
(use-after-free / double-free, que precisa de rastreamento de tempo de vida de ponteiro) e verificação TLS
(o bug é um valor constante específico como SSL_VERIFY_NONE). O resumo offline relata quantos
locais foram sinalizados / eliminados / ignorados (precisam do LLM) / falharam, para que as contas
se somem. Esta é uma triagem rápida; para julgamento real — e para as categorias ignoradas —
execute a varredura completa do LLM.
Os achados offline ainda constroem o mesmo contexto interprocedural completo que uma varredura
online enviaria (apenas para os locais sinalizados) e o armazenam, para que depois de triá-los
possam ser exportados como dados de fine-tuning assim como achados online. Desative com
vulnfanatic.offlineBuildContext se quiser velocidade máxima offline.
Só executa quando o binário parece ter símbolos reais / nomes de variáveis. Localiza
funções sensíveis à segurança definidas em
rules/phase2_rules.json —
autenticação, criptografia (incl. algoritmos fracos), verificação de assinatura/certificado,
manipulação de sessão/token, controle de acesso, manipulação de segredo/chave,
validação de entrada, comparação de segredo em tempo não constante, e
desserialização insegura — correspondidas por nome de função e strings referenciadas, depois auditadas
pelo modelo.
Uma auditoria de endurecimento de firmware contra ataques de injeção de falha (glitching de
tensão/clock/EM) e canal lateral (tempo/potência), baseada em orientação de mitigação
de ataques de hardware. Diferente das Fases 1–2 (que encontram bugs), a Fase 3 relata um
controle de endurecimento ausente ou violado em uma função crítica de segurança — por
exemplo: ramos com padrão de falha, decisões de segurança duplamente verificadas, validação de contador pós-loop,
constantes de estado com alta distância de Hamming (vs 0/1 simples), comparação de segredo em tempo constante
em comprimento total, acesso/limpeza de segredo com deslocamento aleatório,
criptografar-depois-verificar (anti-DFA), contadores de integridade de fluxo de controle,
evitando criptografia em espaço de usuário, e não manipulando material de chave bruta diretamente
(rules/phase3_rules.json).
Como as otimizações do compilador podem remover proteções no nível do código fonte, esses controles são melhor verificados no binário compilado — exatamente o que isso verifica. A Fase 3 é apenas LLM (online), com portão de símbolo, e desabilitada por padrão; habilite-a por varredura com a caixa de seleção Phase 3 na aba New Scan (nunca executa no modo offline).
Os achados são listados em uma tabela (status, confiança, fase, CWE, função, endereço, título) com um painel de detalhes que mostra a explicação, o rascunho da análise e as notas de validação. Duplo-clique em uma linha para navegar a visualização do binário para o código.
Cada achado começa como Não triado. Clique com o botão direito em uma linha para definir seu status — Mark as Real Issue, Mark as False Positive, ou Mark as Untriaged. Cada mudança de status exibe uma caixa de texto "Provide reason:" (o motivo é armazenado com o achado). A tabela torna o status óbvio: Real Issues são verdes/negrito e classificam para o topo, False Positives são cinza/tachado e classificam para o fundo, Untriaged ficam entre eles com sua cor de confiança. Uma linha de resumo mostra as contagens.
Cada aba de resultado tem um botão Export triaged (fine-tuning)… que exporta apenas
os achados triados (Real Issue + False Positive) como JSONL no formato de chat OpenAI
para fine-tuning: cada exemplo emparelha o prompt original do sistema+usuário com o
veredito corrigido por humano como o alvo do assistente (um False Positive ensina
is_vulnerable=false com seu motivo; um Real Issue reforça is_vulnerable=true),
para que você possa melhorar iterativamente a precisão do modelo em seus binários.
O contexto por achado mostrado no painel de detalhes (e usado para reconstruir os prompts de
fine-tuning) é, por padrão, mantido na íntegra — controlado por
vulnfanatic.storedContextChars (0 = ilimitado; defina um limite positivo, por exemplo 4000,
para limitar o crescimento do BNDB ao custo da fidelidade do contexto).
O painel é com abas. A primeira aba é sempre New Scan, onde você define:
<timestamp> <mode>, por exemplo
2026-06-15 14:03:50 offline),em seguida, pressione Start Scan ou Scan Offline. Cada execução abre sua própria aba de resultado e os achados são transmitidos para ela ao vivo. Todas as varreduras são armazenadas no BNDB, para que você possa, por exemplo, manter uma varredura offline e depois adicionar uma varredura online, ou comparar execuções com conjuntos de regras diferentes, lado a lado — elas reaparecem como abas quando você reabre o banco de dados. Fechar uma aba exclui permanentemente essa varredura do BNDB — para evitar acidentes, exibe uma confirmação que requer marcar "I confirm that I will lose the results from forever." antes que o botão Delete results forever seja ativado. Export current scan… escreve a aba selecionada em Markdown/JSON.
Cada binário aberto tem seu próprio estado de painel independente — suas próprias abas de varredura e varredura em execução. Iniciar uma varredura em um binário e mudar para outro mostra o segundo binário's resultados (e permite que você o analise separadamente); a varredura do primeiro binário continua em execução em segundo plano e permanece intacta quando você voltar.
O nome da pasta do pacote deste plugin é vulnfanatic_ng (um identificador Python válido —
o Binary Ninja importa o nome da pasta do plugin como um módulo, portanto um nome com hífen
como VulnFanatic-NG não carregaria).
(Opcional) Instale a contagem precisa de tokens no Python do Binary Ninja: ``` pip install tiktoken
Crie um link simbólico ou copie a pasta vulnfanatic_ng para o diretório de plugins do usuário do Binary Ninja:
~/Library/Application Support/Binary Ninja/plugins/~/.binaryninja/plugins/%APPDATA%\Binary Ninja\plugins\Por exemplo, no macOS: ``` ln -s "$(pwd)/vulnfanatic_ng" "$HOME/Library/Application Support/Binary Ninja/plugins/vulnfanatic_ng"
Reinicie o Binary Ninja (ou execute Recarregar Plugins). Um ícone VF aparece na barra lateral direita.
Abra Configurações (a engrenagem / Editar ▸ Preferências ▸ Configurações) e pesquise por
vulnfanatic. Defina no mínimo:
vulnfanatic.apiProvider seleciona como as requisições são formadas e autenticadas. O
contrato de veredito (e todos os prompts de regra) são idênticos entre os provedores.
A AWS Bedrock pode ser usada através do provedor
openaivia seu endpoint compatível com OpenAI, portanto não precisa de um backend dedicado.
Outras configurações úteis: vulnfanatic.maxContextTokens (padrão 100000),
vulnfanatic.maxResponseTokens, vulnfanatic.temperature,
vulnfanatic.reasoningEffort (off/low/medium/high; padrão high — pede
ao modelo para pensar antes de responder onde suportado, mapeado por provedor:
openai/azure reasoning_effort, anthropic pensamento adaptativo + output_config.effort,
google thinkingConfig dinâmico; removido automaticamente e repetido se um modelo o rejeitar),
vulnfanatic.requestTimeoutSec,
vulnfanatic.callPathMaxDepth / ,
(incluir os corpos decompilados das funções ao longo
do caminho de chamada; padrão ativado) / (limite, padrão 12),
(incluir também outras funções chamadas ao longo do
caminho, que podem conter as verificações de limites/validação; padrão ativado) /
(limite, padrão 12),
(incluir definições de struct/union/enum; padrão ativado) /
(limite, padrão 24),
(rastrear argumentos de chamada de volta através de seus produtores
/consumidores e incluir esses corpos; padrão ativado) /
(limite, padrão 8),
(incluir o layout de variáveis de pilha da função chamadora
quando ela possui um buffer de tamanho fixo; padrão ativado),
(também corresponder a chamadas perigosas despachadas através de um ponteiro
de função/tabela resolvida; padrão ativado — desative para uma varredura mais rápida em binários muito grandes),
(executar a segunda passagem de verificação dupla; padrão desativado) /
/ /
/ (executar a passagem de validação em um
modelo separado e independente — em branco = mesmo modelo que o analista) /
(//; descartar descobertas abaixo disso; padrão
), (relatar locais que o modelo não conseguiu pontuar como
pistas "Não avaliadas" com confiança em vez de descartá-las; padrão ativado),
(pular locais de chamada de estouro com todos os argumentos constantes;
padrão desativado), (//; quanto
raciocínio o modelo escreve por veredito — a principal alavanca de velocidade; padrão ),
/
/ (ativar cada fase; a Fase 3 é
apenas online e geralmente alternada por varredura através da caixa de seleção Nova Varredura, não aqui),
/ ,
(codificação do tokenizador tiktoken para estimativas de token; recorre a
uma heurística de caracteres se o tiktoken não estiver instalado),
(construir contexto completo para descobertas offline para que possam
ser exportadas para ajuste fino; padrão ativado),
(rastreamento detalhado do pipeline para o console; padrão desativado) /
(ocultar todos os detalhes que identificam o binário para que o log possa ser
compartilhado — veja abaixo),
, (verificar certificados HTTPS;
padrão ativado) / (pacote de CA para HTTPS — veja
Solução de Problemas se você encontrar ), e
/ /
(aponte estes para seus próprios arquivos de regras para personalizar
detecções e prompts).
Nota de segurança: a chave da API é armazenada nas configurações do Binary Ninja em texto simples. Prefira a substituição por variável de ambiente para chaves sensíveis.
Defina vulnfanatic.apiBaseUrl para o valor literal TEST para executar sem qualquer LLM:
/tmp/vulnfanatic_ng/<binary>-<timestamp>/.Use isso para inspecionar e validar exatamente o que o VulnFanatic-NG enviaria ao modelo, e para iterar nos prompts de regra/contexto sem gastar tempo de modelo.
Ative vulnfanatic.debugLogging para imprimir um rastreamento detalhado, passo a passo, do
pipeline de varredura (online e offline) no log/console do Binary Ninja: cada local
de chamada, cada decisão de pular/eliminar, construção de contexto (apenas tamanho), cada requisição
LLM (provedor/modelo/endpoint, tentativas, fallbacks), cada veredito e cada descoberta
relatada. As chaves da API nunca são registradas.
Enquanto o registro de depuração estiver ativado, uma varredura online mantém todos os candidatos na tabela de resultados em vez de descartar aqueles que não se tornam problemas confirmados, cada um marcado com um status específico de depuração (esmaecido, classificado no final):
Assim, uma varredura de depuração mostra uma linha por candidato no total /N, e o resumo relata
problemas vs. contagens de rejeitados/pulados/erro separadamente. Você pode clicar com o botão direito em qualquer
dessas linhas para reclassificá-la como Problema Real ou Falso Positivo (o que a torna elegível para
exportação de ajuste fino). (As varreduras offline não são afetadas — elas nunca chamam o LLM.)
Independentemente do modo de depuração, quando um modelo retorna uma resposta não analisável — um token
solitário como o <unused…> do Gemma, prosa em vez de JSON, ou uma mensagem vazia (apenas um
role, sem content) — o cliente faz uma tentativa corretiva, pedindo novamente apenas JSON
com o formato de saída estruturada desativado; se isso for bem-sucedido, ele mantém o formato desativado
pelo resto da varredura. O cliente também lê o canal de raciocínio
(reasoning_content / reasoning) quando content está vazio, então modelos de raciocínio que colocam
sua resposta lá ainda funcionam.
O caso de mensagem vazia é comum com modelos de raciocínio como GPT-OSS / o1 servidos
através de uma API compatível com OpenAI (ex. mlx-community/gpt-oss-20b): com
response_format=json_object definido, o canal de resposta "final" harmônico é frequentemente suprimido
e o servidor retorna {"role": "assistant"} sem conteúdo. Esses modelos também podem queimar
todo o orçamento de saída no canal de raciocínio e ser truncados no meio do pensamento,
retornando prosa sem JSON algum. A repetição automática recupera os casos relacionados ao formato; se
persistir, desative vulnfanatic.sendJsonResponseFormat, reduza
vulnfanatic.reasoningEffort (para que menos orçamento vá para o pensamento), e/ou aumente
vulnfanatic.maxResponseTokens. Uma resposta persistente <unused…>/lixo, por outro lado, geralmente significa
que o prompt excede a janela de contexto do modelo (defina vulnfanatic.modelContextWindow
e/ou aumente o comprimento de contexto do servidor), ou que o modelo é inadequado para saída JSON
estrita (um modelo de código como Qwen2.5-Coder se comporta muito melhor que o Gemma aqui).
Fallback de preservação de recall. Quando um candidato ainda não pode ser pontuado após a
repetição, vulnfanatic.flagUnparseableResponses (padrão ativado) o relata mesmo assim como
uma descoberta "Não avaliada" com confiança UNKNOWN — um valor distinto de low (o
modelo nunca produziu um veredito, então não é um julgamento de baixa confiança) que classifica no
final — mantendo a saída parcial do modelo como explicação, para que você não perca o
local, apenas revise-o manualmente. Desative-o para descartar tais locais (eles então aparecem
apenas como erros de análise, ou linhas ERROR de depuração).
Além disso, ative vulnfanatic.debugAnonymous para tornar o log seguro para compartilhar:
ele oculta tudo que poderia identificar o arquivo analisado — nomes de símbolos/variáveis e
endereços tornam-se hashes com sal por execução (ainda consistentes dentro de uma execução para que o fluxo seja
rastreável), o nome do arquivo é oculto, o texto da descoberta é substituído por <redacted>, o
host do endpoint LLM é hasheado, e o código decompilado / prompts / contexto são registrados apenas como
tamanhos (nunca o conteúdo). Assim, você pode enviar um log de depuração para relatar um problema sem
revelar nada sobre seu binário.
As descobertas — incluindo seu status de falso positivo — são armazenadas no banco de dados do Binary
Ninja. Elas são gravadas no .bndb quando você salva o banco de dados (e
liberadas imediatamente se um .bndb já existir), portanto sobrevivem à reabertura.
A varredura analisa todos os locais de chamada correspondentes (sem limite), o que é apropriado para modelos locais. Para um endpoint hospedado/pago, esteja atento ao volume em binários grandes.
Ambos os arquivos de regra compartilham um envelope com um system_prompt compartilhado e
output_schema, mais uma lista de rules. Copie um arquivo incluído, edite as
funções/palavras-chave/prompts, e aponte vulnfanatic.rulesPhase1Path /
vulnfanatic.rulesPhase2Path para sua cópia. As regras da Fase 1 correspondem por functions (exatas)
e name_regex; as regras da Fase 2 correspondem por name_keywords, name_regex e
string_keywords. O prompt de cada regra pode usar o espaço reservado {function}.
As exportações triadas são projetadas para serem alimentadas diretamente de volta ao modelo. Após
triar descobertas em vários binários e clicar em Exportar triado
(ajuste fino)… em cada um (coletando os arquivos .jsonl em uma pasta),
scripts/finetune_mlx.py executa um ajuste fino MLX LoRA
neles.```bash
pip install mlx-lm # Apple Silicon / macOS
python scripts/finetune_mlx.py ./exports
--model mlx-community/Qwen2.5-Coder-7B-Instruct-4bit
--adapter-path ./vf-adapters --iters 800
python scripts/finetune_mlx.py ./exports --model
--fuse --fused-path ./vf-qwen-coder-vuln
O script utiliza a **pasta training-data** como seu argumento posicional e o **`--model`** base (caminho local ou ID de repositório MLX/HF); outros parâmetros são opcionais: `--adapter-path`, `--valid-split` (0.1), `--iters`, `--batch-size` (ajustado automaticamente para caber em uma pequena divisão), `--num-layers`, `--learning-rate`, `--max-seq-length` (`0` = **ajuste automático** ao exemplo mais longo, limitado a 16384; defina um valor positivo para forçá-lo), `--fine-tune-type` (`lora`/`dora`/`full`), `--seed`, `--fuse`/`--fused-path` e `--dry-run` (prepara os dados + imprime o comando sem treinar). Qualquer coisa após um `--` literal é encaminhado na íntegra para `mlx_lm lora`. Ele mescla recursivamente todos os `*.jsonl` na pasta, valida e **remove duplicatas** dos exemplos de chat, cria a divisão `train.jsonl`/`valid.jsonl` que o MLX espera e, em seguida, executa `python -m mlx_lm lora` (e `mlx_lm fuse` com `--fuse`).
Sirva o resultado com um servidor compatível com OpenAI (`mlx_lm.server --model <caminho>`) e aponte `vulnfanatic.apiBaseUrl` de volta para ele para escanear com seu modelo ajustado.
> Os contextos do VulnFanatic-NG são grandes, portanto, por padrão, o script **ajusta automaticamente**
> `--max-seq-length` ao seu exemplo mais longo (arredondado para cima, limitado a **16384 tokens**).
> Sequências longas dominam a memória de treinamento, portanto, um modelo grande próximo desse limite pode esgotar
> a memória de um Mac menor. Se seus exemplos excederem o limite, eles são truncados — passe um valor maior de
> `--max-seq-length` (mais memória) ou diminua `vulnfanatic.storedContextChars`
> antes de exportar. Se o treinamento for encerrado por um sinal (por exemplo, `exit -10` / SIGBUS), isso é
> uma falha de falta de memória: reduza `--max-seq-length`, adicione `-- --grad-checkpoint` ou use um
> modelo menor.
---
## Desenvolvimento e testes
O plugin não possui dependências de terceiros obrigatórias. Módulos puros
(`rules`, `tokens`, `llm`, `findings`, `settings`, `prototypes`) são cobertos por uma
suíte de testes offline que não precisa nem do Binary Ninja nem de rede. A suíte `tests/`
reside no repositório de origem do projeto (ela não é enviada dentro do
plugin publicado); execute-a a partir de lá. Do diretório do pacote você ainda pode
verificar a sintaxe de cada módulo:```
python3 -m py_compile *.py ui/*.py
python3 -m unittest discover -s tests # from the source repository
Os módulos voltados para Binary Ninja (context_builder, phase1, phase2) são importados
limposamente sem o Binary Ninja (o acesso às suas APIs é protegido), mas requerem um Binary Ninja em execução
para serem exercitados.
strcpy em argv[1] para um
buffer fixo na pilha e chame system() na entrada). Compile com símbolos
para também exercitar a Fase 2.vulnfanatic.apiBaseUrl,
vulnfanatic.apiKey e vulnfanatic.model.SSL: CERTIFICATE_VERIFY_FAILED ... unable to get local issuer certificate —
o certificado do endpoint HTTPS está correto, mas o Python empacotado do Binary Ninja não possui
um pacote de CA para verificá-lo (comum no macOS e em Pythons embutidos; você verá
isso com endpoints hospedados como AWS Bedrock, Anthropic, Google, Azure). Corrija com uma
das opções abaixo, em ordem de preferência:
pip install certifi.
O VulnFanatic-NG o detecta automaticamente.vulnfanatic.caBundlePath com o caminho de um arquivo
de pacote (ou diretório) — ex.: o caminho impresso por python3 -m certifi, ou /etc/ssl/cert.pem.vulnfanatic.tlsVerify (apenas para um endpoint confiável/interno
ou um servidor local autoassinado — isso desabilita a verificação do certificado).HTTP 400 ... tokenizer.chat_template is not set — o modelo que você está servindo
não possui um modelo de chat, então o endpoint /chat/completions não consegue formatar as
mensagens. O VulnFanatic-NG automaticamente cai para o endpoint /completions para o
resto da verificação ao ver esse erro, então a verificação continua. Para evitar a
primeira requisição com falha completamente, defina vulnfanatic.apiMode como completions. Alternativamente,
corrija do lado do servidor servindo um modelo que inclua um modelo de chat, ou passe um para
o seu servidor — ex.: para vLLM: --chat-template <template.jinja> (ou use uma
variante de modelo -Instruct/-Chat). O modelo de chat dedicado geralmente produz
melhores resultados do que o prompt achatado de completions.
No JSON object found ... response looks truncated — a resposta do modelo foi cortada
antes do JSON terminar. Duas causas:
vulnfanatic.maxResponseTokens.maxResponseTokens esteja. Servidores locais geralmente têm uma janela pequena (ollama
padrão é num_ctx=2048!). Corrija definindo vulnfanatic.modelContextWindow para o tamanho da
janela do seu servidor (ex.: ollama num_ctx, llama.cpp -c, vLLM --max-model-len) —
o VulnFanatic-NG então automaticamente limita o contexto que envia para que prompt + resposta caibam.
Também mantenha vulnfanatic.maxResponseTokens razoável (≈8192, não 65535) e/ou aumente a
janela do servidor. Janelas pequenas (≤8k) não conseguem conter todo o contexto interprocedural;
use um modelo/servidor configurado para 32k+.IncompleteRead / Could not complete request ... after N attempt(s) — o
servidor aceitou a requisição, mas fechou a conexão antes de enviar a resposta
completa. Isso quase sempre significa que o servidor do modelo travou ou parou durante a geração:
falta de memória (contexto grande + saída longa), um timeout interno/de worker, ou um proxy
redefinindo a conexão. O VulnFanatic-NG tenta novamente uma vez automaticamente e depois pula esse
site. Verifique os logs do próprio servidor do modelo para a causa real; reduzir
vulnfanatic.maxContextTokens e/ou vulnfanatic.maxResponseTokens, ou dar ao servidor mais
memória / uma janela de contexto maior, geralmente resolve.
vulnfanatic.phase2ForceEnable para também auditar correspondências baseadas em nome, ou
vulnfanatic.phase2RequireSymbols=off. A verificação de símbolos é uma heurística.response_format=json_object; o cliente
tolera isso e ainda extrai JSON. Desative vulnfanatic.sendJsonResponseFormat
se o seu servidor rejeitar o parâmetro por completo.Apache-2.0 (© Martin Petran) — veja plugin.json.
switchMAIN→ABCD→strcpy, também as funções que MAIN e ABCD chamam em outros lugares), pois
podem conter as verificações de limites/validação que protegem o valor
perigoso (vulnfanatic.includeCallPathSiblings, preenchido enquanto o orçamento permitir), erecv/read/getenv chamadas na
mesma função).mediumhighvulnfanatic.skipConstantArgCalls (padrão desligado) — ignore locais de chamada de classe de estouro
cujos argumentos são todos constantes em tempo de compilação.| Parâmetro | Significado |
|---|
vulnfanatic.apiProvider | Qual backend LLM chamar: openai (padrão), anthropic, google ou azure. Veja Backends LLM abaixo. Todos os provedores são acessados pela biblioteca padrão do Python — nada para pip install. |
vulnfanatic.apiBaseUrl | Base do endpoint para o provedor selecionado (veja a tabela abaixo). Padrão http://localhost:8080/v1. Defina como o literal TEST para ativar o modo de teste (veja abaixo). |
vulnfanatic.apiKey | Chave da API / token bearer. Pode estar em branco para servidores locais. Substituído pelas variáveis de ambiente VULNFANATIC_API_KEY ou OPENAI_API_KEY. |
vulnfanatic.model | Obrigatório (exceto no modo de teste). O identificador do modelo (para azure, o nome da implantação). |
vulnfanatic.apiMode | Apenas openai: chat (padrão, /chat/completions) vs completions (prompt único achatado — para modelos base/instruct servidos sem um template de chat). |
vulnfanatic.azureApiVersion | Apenas azure: o parâmetro de consulta api-version (padrão 2024-10-21). |
| Provedor | apiBaseUrl | Autenticação | Notas |
|---|
openai | seu servidor, ex. http://localhost:8080/v1 | Authorization: Bearer | Chat/Completions compatível com OpenAI: llama.cpp local / ollama / vLLM, OpenAI e endpoint compatível com OpenAI da AWS Bedrock. |
anthropic | em branco → https://api.anthropic.com | x-api-key + anthropic-version | Messages API do Claude (POST <base>/v1/messages). temperature não é enviado (os modelos atuais do Claude o rejeitam). |
google | em branco → https://generativelanguage.googleapis.com | Chave da API na URL | generateContent do Gemini (<base>/v1beta/models/<model>:generateContent). |
azure | https://<resource>.openai.azure.com | Cabeçalho api-key | Azure OpenAI; defina model como o nome da implantação e azureApiVersion como sua versão da API. |
vulnfanatic.callPathMaxPathsvulnfanatic.callPathIncludeBodiesvulnfanatic.callPathMaxBodiesvulnfanatic.includeCallPathSiblingsvulnfanatic.callPathSiblingMaxBodiesvulnfanatic.includeDataTypesvulnfanatic.maxTypeDefsvulnfanatic.includeVariableDataflowvulnfanatic.dataflowMaxFunctionsvulnfanatic.includeStackLayoutvulnfanatic.scanIndirectCallsvulnfanatic.validationPassvulnfanatic.validatorModelvulnfanatic.validatorProvidervulnfanatic.validatorBaseUrlvulnfanatic.validatorApiKeyvulnfanatic.minConfidencelowmediumhighlowvulnfanatic.flagUnparseableResponsesUNKNOWNvulnfanatic.skipConstantArgCallsvulnfanatic.verdictReasoningconcisefullnoneconcisevulnfanatic.runPhase1vulnfanatic.runPhase2vulnfanatic.runPhase3vulnfanatic.phase2RequireSymbolsvulnfanatic.phase2ForceEnablevulnfanatic.tokenizerEncodingvulnfanatic.offlineBuildContextvulnfanatic.debugLoggingvulnfanatic.debugAnonymousvulnfanatic.sendJsonResponseFormatvulnfanatic.tlsVerifyvulnfanatic.caBundlePathCERTIFICATE_VERIFY_FAILEDvulnfanatic.rulesPhase1Pathvulnfanatic.rulesPhase2Pathvulnfanatic.rulesPhase3Path