Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
VulnFanatic-NG — Plugin do BianryNinja para identificar vulnerabilidades em binários descompilados com varreduras programáticas e suporte a LLM. | Kitploit
Ferramentas/GitHubGitHub/martyx00/vulnfanatic-ng
Análise Estática de Código (SAST)Análise de VulnerabilidadesAnálise de CódigoExploraçãoEngenharia ReversaFuzzingTestes de PenetraçãoSegurança de HardwareAnálise de BináriosSegurança da Cadeia de SuprimentosAprendizado e EducaçãoEngenharia Reversa Assistida por IA
1415há 2 mesesAinda não revisado

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar
GitHubmartyx00/vulnfanatic-ng

VulnFanatic-NG

Plugin do BianryNinja para identificar vulnerabilidades em binários descompilados com varreduras programáticas e suporte a LLM.

Ver Repositório

VulnFanatic-NG

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.


Como funciona

Uma varredura é executada em até três fases (Fase 3 é opcional e somente online):

Fase 1 — chamadas de funções perigosas

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):

  • a expressão de chamada e seus argumentos,
  • o protótipo declarado da função chamada (das informações de tipo do Binary Ninja, caso contrário de uma tabela interna) para que o modelo mapeie argumentos para parâmetros corretamente — variantes fortificadas __*_chk e *_s com verificação de limites recebem argumentos iniciais extras, deslocando a posição do formato/tamanho/destino,
  • o tipo e tamanho em bytes de cada argumento da chamada (capacidades do buffer), derivados do tipo da expressão HLIL do argumento, de modo que um campo de struct como 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,
  • o valor concreto / intervalo de cada argumento resolvido pela propagação de constantes e análise de conjunto de valores do Binary Ninja (por exemplo, um comprimento provado constante 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,
  • o layout do quadro de pilha da função chamadora (offsets de variáveis e tamanhos em bytes) quando ela contém um buffer de tamanho fixo, para que um estouro de pilha possa ser julgado em relação às variáveis adjacentes e ao endereço de retorno salvo (vulnfanatic.includeStackLayout),
  • as restrições de caminho (as condições 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.

Raciocínio, rascunho e confiança

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.

Ajustando precisão vs. recall

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.
    • Modelo validador separado (recomendado quando usar a passagem de validação). Defina 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):

  • Proveniência do argumento — o contexto informa ao modelo, por argumento, se ele é uma constante de tempo de compilação, um parâmetro de função, ou derivado de uma fonte contaminada, que o modelo usa para definir a confiança.
  • Consciência de variantes com verificação de limites — os prompts tratam variantes _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.
  • Tamanhos explícitos de buffer — capacidades de byte de argumento e campo de struct são fornecidas para que o modelo compare capacidade com bytes escritos em vez de adivinhar.

Varredura Offline (sem LLM)

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:

  • Eliminado (não relatado): um 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.
  • Alta confiança: sinalizado sem nenhuma verificação mitigadora encontrada em qualquer lugar no fluxo de execução.
  • Rebaixado (→ médio): o argumento de tamanho/comprimento foi resolvido para um intervalo constante/limitado pela análise de conjunto de valores do Binary Ninja, ou uma verificação real de limites/validação comparando o argumento relevante (por exemplo, uma comparação 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.

Fase 2 — código sensível à segurança (com portão de símbolo)

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.

Fase 3 — auditoria de endurecimento contra ataques de hardware (online, opt-in)

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.

Fluxo de trabalho de triagem

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).

Várias varreduras (abas)

O painel é com abas. A primeira aba é sempre New Scan, onde você define:

  • um nome de varredura opcional (em branco → <timestamp> <mode>, por exemplo 2026-06-15 14:03:50 offline),
  • um caminho de regras personalizadas para Fase 1 / Fase 2 / Fase 3 opcional (em branco → os padrões incluídos), para que você possa executar um conjunto de regras alternativo,
  • uma caixa de seleção Phase 3 (desligada por padrão) para executar adicionalmente a auditoria de endurecimento contra ataques de hardware somente online,

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.


Instalação

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).

  1. (Opcional) Instale a contagem precisa de tokens no Python do Binary Ninja: ``` pip install tiktoken

    root@kitploit:~
  2. Crie um link simbólico ou copie a pasta vulnfanatic_ng para o diretório de plugins do usuário do Binary Ninja:

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

    Por exemplo, no macOS: ``` ln -s "$(pwd)/vulnfanatic_ng" "$HOME/Library/Application Support/Binary Ninja/plugins/vulnfanatic_ng"

    root@kitploit:~
  3. Reinicie o Binary Ninja (ou execute Recarregar Plugins). Um ícone VF aparece na barra lateral direita.


Configuração

Abra Configurações (a engrenagem / Editar ▸ Preferências ▸ Configurações) e pesquise por vulnfanatic. Defina no mínimo:

Backends LLM

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 openai via 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.

Modo de teste (execução a seco, sem LLM)

Defina vulnfanatic.apiBaseUrl para o valor literal TEST para executar sem qualquer LLM:

  • O modelo nunca é chamado (sem rede, sem necessidade de chave da API/modelo).
  • Cada candidato (cada local de chamada perigosa na Fase 1, cada função sensível à segurança na Fase 2) é sinalizado.
  • O prompt completo — prompt do sistema e o contexto gerado completo — para cada candidato é escrito em seu próprio arquivo em /tmp/vulnfanatic_ng/<binary>-<timestamp>/.
  • A tabela de descobertas mostra uma coluna Arquivo de Prompt (passe o mouse para o caminho completo), e o painel de detalhes e as exportações incluem o caminho.

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.

Registro de depuração

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):

  • REJECTED — o LLM retornou um veredito de não é um problema.
  • SKIPPED — eliminado antes do LLM por uma regra comprovadamente segura (uma string de formato constante, ou argumentos todos constantes); a linha explica qual.
  • ERROR — o candidato não pôde ser analisado (falha na construção do contexto, ou a resposta do LLM não pôde ser analisada / a conexão falhou); a linha carrega o erro.

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.


Uso

  1. Abra um binário e deixe a análise terminar.
  2. Clique no ícone da barra lateral VF para abrir o VulnFanatic-NG.
  3. Pressione Iniciar Varredura (varredura LLM completa) ou Varredura Offline (rápida, Fase 1 programática sem LLM — veja acima). O progresso é mostrado no painel e na barra de status do Binary Ninja; as descobertas aparecem ao vivo e podem ser canceladas.
  4. Clique em uma descoberta para ler a explicação; clique duas vezes para ir para o código.
  5. Clique com o botão direito em uma descoberta para Marcar como falso positivo — ela se move para o final da tabela, acinzentada e tachada, e a entrada do menu muda para Marcar como problema real para desfazer. (O menu de clique direito também tem Ir para o código.)
  6. Exporte para Markdown ou JSON, ou Limpe para descartar descobertas salvas.

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.


Personalizando regras

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}.


Ajuste fino do modelo (MLX, Apple Silicon)

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

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:~
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.

Teste manual dentro do Binary Ninja

  1. Construa um pequeno programa C vulnerável (ex.: um que use 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.
  2. Inicie seu servidor compatível com OpenAI local e defina vulnfanatic.apiBaseUrl, vulnfanatic.apiKey e vulnfanatic.model.
  3. Abra o binário, execute Iniciar Verificação e confirme que as chamadas perigosas são relatadas e que um duplo clique navega para os locais das chamadas.

Solução de Problemas

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:

  • Instale certifi no Python que o Binary Ninja usa: pip install certifi. O VulnFanatic-NG o detecta automaticamente.
  • Aponte para um pacote de CA: defina 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.
  • Último recurso: desative 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:

  • O rascunho excedeu o orçamento de resposta → aumente vulnfanatic.maxResponseTokens.
  • Mais comum: o prompt preenche a janela de contexto do modelo, não deixando espaço para gerar, então a resposta para após alguns tokens não importa o quão alto 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.

Limitações

  • A Fase 2 depende de símbolos. Em um binário stripado, correspondências baseadas em nome são confiáveis, então por padrão apenas as regras de evidência de string são executadas (funções que referenciam constantes de string reveladoras ainda são auditáveis). Defina vulnfanatic.phase2ForceEnable para também auditar correspondências baseadas em nome, ou vulnfanatic.phase2RequireSymbols=off. A verificação de símbolos é uma heurística.
  • O mapeamento HLIL ↔ local da chamada pode falhar; o VulnFanatic-NG cai para MLIL/assembly e anota a representação usada por cada achado.
  • Os vereditos são tão bons quanto o modelo. Trate os achados como pistas para revisão manual, não como verdade absoluta.
  • Alguns servidores locais ignoram ou rejeitam 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.

Licença

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

Baixar ferramenta
switch
  • um sumário de fluxo de dados dos argumentos — onde cada argumento da chamada é definido e usado dentro da função,
  • resolução de parâmetros entre chamadores — quando um argumento perigoso é um parâmetro da função chamadora, o contexto informa o que cada chamador realmente passa para ele (por exemplo, "todos os chamadores passam uma string literal"), para que um parâmetro de formato/tamanho que é sempre constante não seja confundido como controlado pelo atacante,
  • o corpo descompilado completo da função chamadora,
  • definições de tipos de dados (struct/union/enum) para os tipos referenciados ao longo da cadeia de chamadas e das variáveis de argumento, para que o modelo conheça os tamanhos reais de buffer/campo e larguras de inteiro,
  • os corpos descompilados das funções que produzem ou consomem as variáveis de argumento da chamada (rastreadas via def/uso HLIL), que é o que torna possível o raciocínio de use-after-free / double-free e tamanho contaminado,
  • caminhos de chamada desde pontos de entrada / funções exportadas até a chamada,
  • o corpo descompilado de cada função ao longo desses caminhos de chamada (primeiro a chamada perigosa), cada um anotado com o local da chamada e as condições que protegem o próximo salto,
  • os corpos de outras funções que essas funções de caminho chamam (por exemplo, para MAIN→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), e
  • dicas de fonte contaminada (funções de entrada como recv/read/getenv chamadas na mesma função).
  • medium
    high
  • vulnfanatic.skipConstantArgCalls (padrão desligado) — ignore locais de chamada de classe de estouro cujos argumentos são todos constantes em tempo de compilação.
  • ParâmetroSignificado
    vulnfanatic.apiProviderQual 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.apiBaseUrlBase 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.apiKeyChave 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.modelObrigatório (exceto no modo de teste). O identificador do modelo (para azure, o nome da implantação).
    vulnfanatic.apiModeApenas openai: chat (padrão, /chat/completions) vs completions (prompt único achatado — para modelos base/instruct servidos sem um template de chat).
    vulnfanatic.azureApiVersionApenas azure: o parâmetro de consulta api-version (padrão 2024-10-21).
    ProvedorapiBaseUrlAutenticaçãoNotas
    openaiseu servidor, ex. http://localhost:8080/v1Authorization: BearerChat/Completions compatível com OpenAI: llama.cpp local / ollama / vLLM, OpenAI e endpoint compatível com OpenAI da AWS Bedrock.
    anthropicem branco → https://api.anthropic.comx-api-key + anthropic-versionMessages API do Claude (POST <base>/v1/messages). temperature não é enviado (os modelos atuais do Claude o rejeitam).
    googleem branco → https://generativelanguage.googleapis.comChave da API na URLgenerateContent do Gemini (<base>/v1beta/models/<model>:generateContent).
    azurehttps://<resource>.openai.azure.comCabeçalho api-keyAzure OpenAI; defina model como o nome da implantação e azureApiVersion como sua versão da 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
    Registro de depuração
    vulnfanatic.sendJsonResponseFormat
    vulnfanatic.tlsVerify
    vulnfanatic.caBundlePath
    CERTIFICATE_VERIFY_FAILED
    vulnfanatic.rulesPhase1Path
    vulnfanatic.rulesPhase2Path
    vulnfanatic.rulesPhase3Path