Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
VulnFanatic-NG — Plugin per BianryNinja che identifica vulnerabilità nei binari decompilati, con scansioni programmatiche e supporto LLM. | Kitploit
Strumenti/GitHubGitHub/martyx00/vulnfanatic-ng
Analisi Statica del Codice (SAST)Analisi delle VulnerabilitàAnalisi del CodiceExploitReverse EngineeringFuzzingPenetration TestingSicurezza HardwareAnalisi di BinariSicurezza della Supply ChainApprendimento e FormazioneReverse Engineering Assistito dall'IA
14152 mesi faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
GitHubmartyx00/vulnfanatic-ng

VulnFanatic-NG

Plugin per BianryNinja che identifica vulnerabilità nei binari decompilati, con scansioni programmatiche e supporto LLM.

Vedi Repository

VulnFanatic-NG

Ricerca di vulnerabilità assistita da LLM per Binary Ninja.

VulnFanatic-NG aggiunge un pannello laterale che analizza il binario corrente e chiede a un LLM — un modello compatibile con OpenAI ospitato localmente per impostazione predefinita, oppure Anthropic Claude, Google Gemini o Azure OpenAI (vedi Backend LLM) — di stabilire se il codice sospetto è davvero vulnerabile. Funziona principalmente dall'output del decompilatore (HLIL) di Binary Ninja, ripiegando sull'assembly quando necessario, e segnala solo problemi confermati con riferimenti cliccabili al codice.


Come funziona

Una scansione viene eseguita in un massimo di tre fasi (la Fase 3 è opzionale e solo online):

Fase 1 — chiamate a funzioni pericolose

Trova i punti di chiamata delle funzioni pericolose definite in rules/phase1_rules.json — strcpy, memcpy, sprintf/stringhe di formato, system, alloca, scanf, API di comandi/exec, RNG debole, la famiglia free/delete (use-after-free / double-free), letture di input non attendibile in buffer a dimensione fissa (recv/read/fread/ReadFile), iniezione SQL (sqlite3_exec/mysql_query/PQexec), verifica dei certificati TLS disabilitata (SSL_CTX_set_verify/curl), SSRF e gestione impropria dei privilegi (setuid/setresgid), la famiglia memset/bzero e confronti con una lunghezza controllata dall'attaccante (memcmp/strncmp → bypass dell'autenticazione), in C/C++, Win32 e (per quanto possibile) Rust FFI. La copertura include le varianti fortificate _chk (FORTIFY) e quelle _s dell'Annex K. Le funzioni di output formattato limitato (snprintf e varianti) hanno una propria regola sicura di default, così un argomento di dimensione corretto non viene segnalato come overflow. I punti di chiamata vengono trovati in tre modi: chiamate dirette ai simboli nominati; chiamate instradate attraverso thunk di forwarding / stub PLT (i chiamanti reali vengono recuperati, quindi un import raggiunto solo tramite stub non viene perso); e — a meno che vulnfanatic.scanIndirectCalls sia disattivata — chiamate indirette inviate attraverso un puntatore a funzione o vtable che Binary Ninja ha risolto a una funzione pericolosa. Per ogni punto di chiamata costruisce un contesto interprocedurale, incentrato sul decompilatore, limitato a un budget di token (default 100k):

  • l'espressione di chiamata e i suoi argomenti,
  • il prototipo dichiarato della funzione chiamata (dalle informazioni sui tipi di Binary Ninja, altrimenti da una tabella integrata) così il modello mappa correttamente gli argomenti ai parametri — le varianti fortificate __*_chk e quelle con controllo dei limiti *_s hanno argomenti iniziali aggiuntivi, spostando la posizione di formato/dimensione/destinazione,
  • il tipo e la dimensione in byte di ogni argomento di chiamata (capacità dei buffer), derivati dal tipo dell'espressione HLIL dell'argomento, così un campo di struct come s->buf si risolve nella dimensione reale dell'array del campo piuttosto che nella dimensione del puntatore di s; anche le definizioni di struct nella sezione dei tipi riportano le dimensioni in byte per campo,
  • il valore concreto / intervallo di ogni argomento risolto dall'analisi di propagazione delle costanti e value-set di Binary Ninja (ad es. una lunghezza dimostrata costante 0x40 o limitata a [0, 0xff]), che il modello usa come riferimento reale quando confronta una dimensione con la capacità di un buffer invece di fare supposizioni,
  • il layout dello stack frame della funzione chiamante (offset delle variabili e dimensioni in byte) quando contiene un buffer a dimensione fissa, così un overflow dello stack può essere valutato rispetto alle variabili adiacenti e all'indirizzo di ritorno salvato (vulnfanatic.includeStackLayout),
  • i vincoli di percorso (le condizioni if/loop/ che proteggono la chiamata),

Questo contesto, insieme a un prompt specifico per la regola, viene inviato al modello, che restituisce un verdetto strutturato. I non-problemi vengono scartati. I prompt sono ottimizzati per un modello di codice locale potente (ad es. Qwen2.5-Coder) e gli chiedono di analizzare l'intero flusso e di emettere solo JSON.

Ragionamento, scratchpad e confidenza

Al modello viene chiesto di privilegiare il recall — segnalare problemi plausibili e rilevanti per la sicurezza ed esprimere l'incertezza attraverso una Confidence piuttosto che scartare ciò che non può dimostrare completamente. Mostra il suo lavoro in uno scratchpad che cita i frammenti di codice verbatim su cui si è basato (la sorgente di input, ogni guardia, la dimensione/lunghezza, il tipo rilevante e il sink), che viene salvato sulla segnalazione così puoi verificare il ragionamento.

Ogni segnalazione ha una Confidence (alta/media/bassa): alta = l'intera catena è mostrata nel contesto; media = probabile, con uno o due collegamenti dedotti; bassa = una pista che merita una revisione manuale. Questa è la metrica principale (la stima della severità del modello è un campo secondario). Imposta vulnfanatic.minConfidence per scartare tutto ciò che è sotto una soglia.

Ottimizzare precisione vs. recall

Per impostazione predefinita VulnFanatic-NG privilegia il recall (trovare i problemi reali). Se ricevi troppi falsi positivi, puoi stringere con una delle seguenti opzioni:

  • vulnfanatic.validationPass (default disattivata) — esegue un secondo passaggio LLM che ricontrolla ogni problema segnalato contro lo stesso contesto (verificando i frammenti dello scratchpad e ripercorrendo il flusso) e può correggere il verdetto o la confidenza. Raddoppia le chiamate LLM per i candidati segnalati.
    • Modello validatore separato (consigliato quando si usa il passaggio di validazione). Imposta vulnfanatic.validatorModel (più validatorProvider / validatorBaseUrl / validatorApiKey) per eseguire il secondo passaggio su un modello diverso. Una seconda opinione è molto più utile da un modello indipendente — condivide meno punti ciechi ed è molto meno propensa ad approvare acriticamente il primo verdetto (i modelli tendono a preferire le proprie risposte). Un buon pattern è una cascata: un modello veloce come analista (recall ampio) e il tuo modello più forte come validatore, che gira solo sui candidati segnalati. Lascia vuoto il modello validatore per validare con il modello analista. Il validatore dovrebbe essere almeno capace quanto l'analista — uno più debole aggiunge per lo più falsi rifiuti. Tutto tranne provider/URL base/chiave/ modello viene ereditato dalle impostazioni di connessione dell'analista; una chiave del validatore vuota riusa la chiave dell'analista; e se l'endpoint del validatore non è raggiungibile, il primo verdetto viene mantenuto (la segnalazione non viene mai persa a causa di un'interruzione del validatore).
  • vulnfanatic.minConfidence (default low) — alza a / per segnalare solo segnalazioni più solide.

Velocità. La maggior parte della latenza per chiamata è data dal ragionamento scritto, quindi vulnfanatic.verdictReasoning controlla quanto scrive il modello:

  • concise (default) — una breve motivazione di 1–3 frasi, senza codice verbatim. Molto più veloce di full con poca perdita di accuratezza; puoi anche abbassare vulnfanatic.maxResponseTokens.
  • full — lo scratchpad dettagliato con frammenti citati (il più verificabile, il più lento).
  • none — solo il verdetto. Il più veloce; abbinalo a un backend in grado di ragionare (vulnfanatic.reasoningEffort) così il pensiero interno del modello fa il lavoro. Su un modello locale semplice none perde accuratezza (nessuna chain-of-thought).

Funzionalità di precisione di supporto sempre attive (informano il modello senza sopprimere le segnalazioni):

  • Provenienza degli argomenti — il contesto dice al modello, per ogni argomento, se si tratta di una costante a tempo di compilazione, di un parametro di funzione o derivato da una sorgente contaminata, cosa che il modello usa per impostare la confidenza.
  • Consapevolezza delle varianti con controllo dei limiti — i prompt trattano le varianti _s (Annex K) e _chk (FORTIFY) e le API con lunghezza limitata come sicure, a meno che l'argomento della dimensione stesso sia sbagliato.
  • Dimensioni esplicite dei buffer — vengono fornite le capacità in byte di argomenti e campi di struct, così il modello confronta la capacità con i byte scritti invece di fare supposizioni.

Scansione offline (senza LLM)

Il pulsante Scan Offline esegue la Fase 1 senza modello — euristiche puramente programmatiche dichiarate nel blocco offline di ogni regola in phase1_rules.json. Segnala i punti di chiamata pericolosi ed elimina quelli evidentemente sicuri, assegnando una Confidence euristica:

  • Eliminati (non segnalati): un memcpy/memmove con lunghezza costante, uno strcpy da una stringa costante, un printf con formato costante, un system con un comando costante, ecc. — chiamate il cui argomento determinante è una costante a tempo di compilazione e quindi non può essere controllato dall'attaccante. "Costante" include valori che l'analisi value-set di Binary Ninja ha fissato a un numero a monte, non solo argomenti letterali.
  • Confidence alta: segnalati senza alcun controllo mitigante trovato nel flusso di esecuzione.
  • Declassati (→ medio): l'argomento dimensione/lunghezza è stato risolto in un intervallo costante/delimitato dall'analisi value-set di Binary Ninja, oppure è stato trovato un vero controllo di limiti/validazione che confronta l'argomento rilevante (ad es. un confronto strlen/dimensione, if (len < …)) da qualche parte nel flusso — incluse le funzioni chiamate lungo il percorso — quindi potrebbe essere già gestito. (Un ramo che menziona semplicemente la variabile senza confrontarla non conta più, eliminando una fonte di declassamenti spuri.)

Le euristiche usano un piccolo vocabolario dichiarativo nelle regole (constant_safe_args, eliminate_if_all_args_constant, format_arg_lookup, length_guard_vars, base_confidence, skip) valutato da predicati Python — nessun codice incorporato da passare a exec. La maggior parte delle regole ha una definizione offline (overflow, format-string, command-exec, scanf, gestione dei percorsi, RNG debole, parsing numerico debole, modifiche dei privilegi, dimensione delle allocazioni, …). Solo le due categorie che richiedono davvero analisi semantica vengono saltate offline e lasciate all'LLM: la famiglia free/delete (use-after-free / double-free, che richiede il tracciamento del ciclo di vita dei puntatori) e la verifica TLS (il bug è un valore costante specifico come SSL_VERIFY_NONE). Il riepilogo offline riporta quanti siti sono stati segnalati / eliminati / saltati (richiedono l'LLM) / non riusciti, così i conteggi tornano. Questo è un triage rapido; per un giudizio reale — e per le categorie saltate — esegui la scansione LLM completa.

Le segnalazioni offline costruiscono comunque lo stesso contesto interprocedurale completo che una scansione online invierebbe (solo per i siti segnalati) e lo memorizzano, così una volta che le hai triagate possono essere esportate come dati di fine-tuning proprio come le segnalazioni online. Disattiva con vulnfanatic.offlineBuildContext se vuoi la massima velocità offline.

Fase 2 — codice sensibile alla sicurezza (gated dai simboli)

Viene eseguita solo quando il binario sembra avere simboli / nomi di variabile reali. Individua le funzioni sensibili alla sicurezza definite in rules/phase2_rules.json — autenticazione, crittografia (incl. algoritmi deboli), verifica di firme/certificati, gestione di sessioni/token, controllo degli accessi, gestione di segreti/chiavi, validazione dell'input, confronto di segreti non a tempo costante e deserializzazione non sicura — abbinate per nome di funzione e stringhe referenziate, poi controllate dal modello.

Fase 3 — audit di hardening contro attacchi hardware (online, opzionale)

Un audit di hardening del firmware contro attacchi a iniezione di guasti (glitch di tensione/clock/EM) e side-channel (timing/power), basato sulle linee guida per la mitigazione degli attacchi hardware. A differenza delle Fasi 1–2 (che trovano bug), la Fase 3 segnala un controllo di hardening mancante o violato su una funzione critica per la sicurezza — ad esempio: rami default-fail, decisioni di sicurezza a doppio controllo, validazione del contatore post-loop, costanti di stato ad alta distanza di Hamming (invece di semplici 0/1), confronto di segreti a tempo costante su tutta la lunghezza, accesso/cancellazione dei segreti con offset randomizzato, encrypt-then-verify (anti-DFA), contatori di integrità del flusso di controllo, evitare la crittografia in spazio utente e non gestire direttamente materiale chiave grezzo (rules/phase3_rules.json).

Poiché le ottimizzazioni del compilatore possono rimuovere le protezioni a livello di sorgente, questi controlli vanno verificati al meglio sul binario compilato — esattamente ciò che questo controllo fa. La Fase 3 è solo LLM (online), gated dai simboli e disattivata per impostazione predefinita; abilitala per scansione con la casella Phase 3 nella scheda New Scan (non viene mai eseguita in modalità offline).

Le segnalazioni sono elencate in una tabella (stato, confidenza, fase, CWE, funzione, indirizzo, titolo) con un pannello dei dettagli che mostra la spiegazione, lo scratchpad di analisi e le note di validazione. Fai doppio clic su una riga per navigare nella vista binario fino al codice.

Flusso di lavoro di triage

Ogni segnalazione inizia come Untriaged. Fai clic con il tasto destro su una riga per impostarne lo stato — Mark as Real Issue, Mark as False Positive o Mark as Untriaged. Ogni cambio di stato apre una finestra di testo "Provide reason:" (la motivazione viene salvata con la segnalazione). La tabella rende lo stato evidente: i Real Issues sono verdi/grassetto e ordinati in cima, i False Positives sono grigi/barrati e ordinati in fondo, gli Untriaged stanno in mezzo con il colore della loro confidenza. Una riga di riepilogo mostra i conteggi.

Ogni scheda dei risultati ha un pulsante Export triaged (fine-tuning)… che esporta solo le segnalazioni triagate (Real Issue + False Positive) come JSONL in formato chat OpenAI per il fine-tuning: ogni esempio abbina il prompt originale system+user con il verdetto corretto dall'umano come target dell'assistente (un False Positive insegna is_vulnerable=false con la tua motivazione; un Real Issue rinforza is_vulnerable=true), così puoi migliorare iterativamente l'accuratezza del modello sui tuoi binari.

Il contesto per singola segnalazione mostrato nel pannello dei dettagli (e usato per ricostruire i prompt di fine-tuning) viene, per impostazione predefinita, mantenuto per intero — controllato da vulnfanatic.storedContextChars (0 = illimitato; imposta un tetto positivo, es. 4000, per limitare la crescita del BNDB a scapito della fedeltà del contesto).

Scansioni multiple (schede)

Il pannello è a schede. La prima scheda è sempre New Scan, dove imposti:

  • un nome scansione opzionale (vuoto → <timestamp> <mode>, es. 2026-06-15 14:03:50 offline),
  • un percorso personalizzato delle regole per Fase 1 / Fase 2 / Fase 3 opzionale (vuoto → i default inclusi), così puoi eseguire un set di regole alternativo,
  • una casella Phase 3 (disattivata per impostazione predefinita) per eseguire anche l'audit di hardening contro attacchi hardware, solo online,

quindi premi Start Scan o Scan Offline. Ogni esecuzione apre la propria scheda dei risultati e le segnalazioni vi confluiscono in tempo reale. Tutte le scansioni sono salvate nel BNDB, quindi puoi ad esempio tenere una scansione offline e aggiungerne poi una online, o confrontare esecuzioni con set di regole diversi, fianco a fianco — riappaiono come schede quando riapri il database. Chiudere una scheda elimina definitivamente quella scansione dal BNDB — per evitare incidenti viene mostrata una conferma che richiede di spuntare "I confirm that I will lose the results from forever." prima che il pulsante Delete results forever si attivi. Export current scan… scrive la scheda selezionata in Markdown/JSON.

Ogni binario aperto ha il proprio stato del pannello indipendente — le proprie schede di scansione e la scansione in corso. Avviare una scansione in un binario e passare a un altro mostra i risultati del secondo binario (e permette di analizzarlo separatamente); la scansione del primo binario continua in background ed è intatta quando torni indietro.


Installazione

La cartella del pacchetto di questo plugin si chiama vulnfanatic_ng (un identificatore Python valido — Binary Ninja importa il nome della cartella del plugin come modulo, quindi un nome con trattino come VulnFanatic-NG non verrebbe caricato).

  1. (Opzionale) Installa il conteggio token accurato nel Python di Binary Ninja: ``` pip install tiktoken

    root@kitploit:~
  2. Symlink o copia la cartella vulnfanatic_ng nella directory dei plugin utente di Binary Ninja:

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

    Ad esempio, su macOS: ``` ln -s "$(pwd)/vulnfanatic_ng" "$HOME/Library/Application Support/Binary Ninja/plugins/vulnfanatic_ng"

    root@kitploit:~
  3. Riavvia Binary Ninja (o esegui Ricarica plugin). Un'icona VF appare nella barra laterale destra.


Configurazione

Apri Impostazioni (l'ingranaggio / Edit ▸ Preferences ▸ Settings) e cerca vulnfanatic. Imposta almeno:

Backend LLM

vulnfanatic.apiProvider seleziona come vengono formate e autenticate le richieste. Il contratto dei verdetti (e tutti i prompt delle regole) è identico tra i vari provider.

AWS Bedrock può essere usato tramite il provider openai attraverso il suo endpoint compatibile OpenAI, quindi non necessita di un backend dedicato.

Altre impostazioni utili: vulnfanatic.maxContextTokens (predefinito 100000), vulnfanatic.maxResponseTokens, vulnfanatic.temperature, vulnfanatic.reasoningEffort (off/low/medium/high; predefinito high — chiede al modello di pensare prima di rispondere dove supportato, mappato per provider: openai/azure reasoning_effort, anthropic pensiero adattivo + output_config.effort, google thinkingConfig dinamico; rimosso automaticamente e ritentato se un modello lo rifiuta), vulnfanatic.requestTimeoutSec, vulnfanatic.callPathMaxDepth / , (include i corpi decompilati delle funzioni lungo il percorso di chiamata; predefinito on) / (limite, predefinito 12), (include anche le altre funzioni chiamate lungo il percorso, che possono contenere i controlli di limiti/validazione; predefinito on) / (limite, predefinito 12), (include le definizioni di struct/union/enum; predefinito on) / (limite, predefinito 24), (traccia gli argomenti delle chiamate a ritroso attraverso i loro produttori /consumatori e include quei corpi; predefinito on) / (limite, predefinito 8), (include il layout delle variabili di stack della funzione chiamante quando contiene un buffer di dimensione fissa; predefinito on), (abbina anche le chiamate pericolose inviate tramite un puntatore a funzione/vtable risolto; predefinito on — disattiva per una scansione più veloce su binari molto grandi), (esegue la seconda passata di doppio controllo; predefinito off) / / / / (esegue la passata di validazione su un modello separato e indipendente — vuoto = stesso modello dell'analista) / (//; scarta i risultati al di sotto di questa soglia; predefinito ), (segnala i siti che il modello non ha potuto valutare come lead "Unscored" con confidenza invece di scartarli; predefinito on), (salta i siti di overflow con argomenti tutti costanti; predefinito off), (//; quanto ragionamento il modello scrive per ogni verdetto — la principale leva sulla velocità; predefinito ), / / (abilita ogni fase; la Fase 3 è solo online e di solito viene attivata per scansione tramite la casella New Scan piuttosto che qui), / , (codifica tiktoken per le stime dei token; ricade su un'euristica basata sui caratteri se tiktoken non è installato), (costruisce il contesto completo per i risultati offline così possono essere esportati per il fine-tuning; predefinito on), (traccia dettagliata della pipeline sulla console; predefinito off) / (oscura tutti i dettagli identificativi del binario così il log può essere condiviso — vedi sotto), , (verifica i certificati HTTPS; predefinito on) / (bundle CA per HTTPS — vedi Troubleshooting se incontri ), e / / (punta questi ai tuoi file di regole per personalizzare rilevamenti e prompt).

Nota di sicurezza: la chiave API è memorizzata nelle impostazioni di Binary Ninja in chiaro. Preferisci l'override tramite variabile d'ambiente per le chiavi sensibili.

Modalità test (dry run, senza LLM)

Imposta vulnfanatic.apiBaseUrl al valore letterale TEST per eseguire senza alcun LLM:

  • Il modello non viene mai chiamato (nessuna rete, nessuna chiave API/modello necessaria).
  • Ogni candidato (ogni sito di chiamata pericoloso nella Fase 1, ogni funzione sensibile alla sicurezza nella Fase 2) viene segnalato.
  • Il prompt completo — system prompt e il contesto generato completo — per ogni candidato viene scritto in un proprio file in /tmp/vulnfanatic_ng/<binary>-<timestamp>/.
  • La tabella dei risultati mostra una colonna Prompt File (passa il mouse per il percorso completo), e il pannello dei dettagli e le esportazioni includono il percorso.

Usalo per ispezionare e validare esattamente ciò che VulnFanatic-NG invierebbe al modello, e per iterare sui prompt/contesto delle regole senza spendere tempo di modello.

Registrazione di debug

Attiva vulnfanatic.debugLogging per stampare una traccia dettagliata, passo dopo passo, della pipeline di scansione (sia online che offline) sul log/console di Binary Ninja: ogni sito di chiamata, ogni decisione di salto/eliminazione, la costruzione del contesto (solo dimensione), ogni richiesta LLM (provider/modello/endpoint, tentativi, fallback), ogni verdetto e ogni risultato segnalato. Le chiavi API non vengono mai registrate.

Mentre la registrazione di debug è attiva, una scansione online mantiene ogni candidato nella tabella dei risultati invece di scartare quelli che non diventano problemi confermati, ciascuno etichettato con uno stato solo di debug (attenuato, ordinato in fondo):

  • REJECTED — il LLM ha restituito un verdetto di non è un problema.
  • SKIPPED — eliminato prima del LLM da una regola dimostrabilmente sicura (una stringa di formato costante, o argomenti tutti costanti); la riga spiega quale.
  • ERROR — il candidato non ha potuto essere analizzato (costruzione del contesto fallita, o risposta del LLM non analizzabile / connessione fallita); la riga riporta l'errore.

Quindi una scansione di debug mostra una riga per ogni candidato nel totale /N, e il riepilogo riporta separatamente i problemi rispetto ai conteggi di rifiutati/saltati/errori. Puoi fare clic con il tasto destro su una qualsiasi di queste righe per riclassificarla come Real Issue o False Positive (il che la rende idonea per l'esportazione per il fine-tuning). (Le scansioni offline non sono influenzate — non chiamano mai il LLM.)

Indipendentemente dalla modalità di debug, quando un modello restituisce una risposta non analizzabile — un token fuori posto come <unused…> di Gemma, testo invece di JSON, o un messaggio vuoto (solo un role, nessun content) — il client esegue un tentativo correttivo, richiedendo nuovamente JSON solo con il formato di output strutturato disabilitato; se riesce, mantiene il formato disattivato per il resto della scansione. Il client legge anche il canale di ragionamento (reasoning_content / reasoning) quando content è vuoto, così i modelli di ragionamento che mettono la loro risposta lì funzionano comunque.

Il caso del messaggio vuoto è comune con modelli di ragionamento come GPT-OSS / o1 serviti tramite un'API compatibile OpenAI (es. mlx-community/gpt-oss-20b): con response_format=json_object impostato, il canale di risposta "final" harmony viene spesso soppresso e il server restituisce {"role": "assistant"} senza contenuto. Questi modelli possono anche bruciare l'intero budget di output sul canale di ragionamento e venire troncati a metà pensiero, restituendo testo senza alcun JSON. Il tentativo automatico recupera i casi legati al formato; se il problema persiste, disattiva vulnfanatic.sendJsonResponseFormat, abbassa vulnfanatic.reasoningEffort (così meno budget va al pensiero), e/o aumenta vulnfanatic.maxResponseTokens. Una risposta persistente <unused…>/spazzatura invece di solito significa che il prompt supera la finestra di contesto del modello (imposta vulnfanatic.modelContextWindow e/o aumenta la lunghezza del contesto del server), oppure che il modello non è adatto a un output JSON rigoroso (un modello di codice come Qwen2.5-Coder si comporta molto meglio di Gemma qui).

Fallback che preserva il recall. Quando un candidato non può ancora essere valutato dopo il tentativo, vulnfanatic.flagUnparseableResponses (predefinito on) lo segnala comunque come risultato "Unscored" con confidenza UNKNOWN — un valore distinto da low (il modello non ha mai prodotto un verdetto, quindi non è un giudizio a bassa confidenza) che finisce in fondo — mantenendo l'output parziale del modello come spiegazione, così non perdi il sito, semplicemente lo esamini manualmente. Disattivalo per scartare invece tali siti (in tal caso emergono solo come errori di analisi, o righe ERROR in debug).

Abilita anche vulnfanatic.debugAnonymous per rendere il log sicuro da condividere: esso oscura tutto ciò che potrebbe identificare il file analizzato — i nomi di simboli/variabili e gli indirizzi diventano hash con salt per esecuzione (comunque coerenti all'interno di un'esecuzione così il flusso è seguibile), il nome del file è nascosto, il testo dei risultati è sostituito con <redacted>, l'host dell'endpoint LLM è sottoposto a hash, e il codice decompilato / i prompt / il contesto vengono registrati solo come dimensioni (mai il contenuto). Così puoi inviare un log di debug per segnalare un problema senza rivelare nulla sul tuo binario.


Utilizzo

  1. Apri un binario e lascia terminare l'analisi.
  2. Fai clic sull'icona VF nella barra laterale per aprire VulnFanatic-NG.
  3. Premi Start Scan (scansione LLM completa) o Scan Offline (veloce, Fase 1 programmatica senza LLM — vedi sopra). L'avanzamento viene mostrato nel pannello e nella barra di stato di Binary Ninja; i risultati appaiono in tempo reale e possono essere annullati.
  4. Fai clic su un risultato per leggere la spiegazione; doppio clic per saltare al codice.
  5. Fai clic con il tasto destro su un risultato per Mark as false positive — si sposta in fondo alla tabella, in grigio e barrato, e la voce di menu diventa Mark as real issue per annullarlo. (Il menu contestuale ha anche Go to code.)
  6. Export in Markdown o JSON, oppure Clear per scartare i risultati salvati.

I risultati — incluso il loro stato di falso positivo — vengono memorizzati nel database di Binary Ninja. Vengono scritti nel .bndb quando salvi il database (e scaricati immediatamente se un .bndb esiste già), quindi sopravvivono alla riapertura.

La scansione analizza ogni sito di chiamata corrispondente (senza limite), il che è appropriato per modelli locali. Per un endpoint hosted/a pagamento, fai attenzione al volume su binari grandi.


Personalizzazione delle regole

Entrambi i file di regole condividono un involucro con un system_prompt e un output_schema comuni, più una lista di rules. Copia un file incluso, modifica le funzioni/parole chiave/prompt, e punta vulnfanatic.rulesPhase1Path / vulnfanatic.rulesPhase2Path alla tua copia. Le regole della Fase 1 corrispondono per functions (esatte) e name_regex; le regole della Fase 2 corrispondono per name_keywords, name_regex e string_keywords. Il prompt di ogni regola può usare il segnaposto {function}.


Fine-tuning del modello (MLX, Apple Silicon)

Le esportazioni classificate (triaged) sono pensate per essere reintrodotte direttamente nel modello. Dopo aver classificato i risultati su diversi binari e fatto clic su Export triaged (fine-tuning)… su ciascuno (raccogliendo i file .jsonl in un'unica cartella), scripts/finetune_mlx.py esegue un fine-tuning LoRA MLX su di essi.```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:~
Lo script accetta la **cartella training-data** come argomento posizionale e il
modello di base **`--model`** (percorso locale o ID repo MLX/HF); gli altri parametri sono opzionali:
`--adapter-path`, `--valid-split` (0.1), `--iters`, `--batch-size` (limitato automaticamente per
adattarsi a una piccola suddivisione), `--num-layers`, `--learning-rate`, `--max-seq-length`
(`0` = **adattamento automatico** all'esempio più lungo, con limite massimo di 16384; imposta un valore positivo per
forzarlo), `--fine-tune-type` (`lora`/`dora`/`full`), `--seed`, `--fuse`/`--fused-path`
e `--dry-run` (prepara i dati + stampa il comando senza addestramento). Qualunque cosa dopo un
`--` letterale viene inoltrata così com'è a `mlx_lm lora`. Lo script unisce ricorsivamente ogni
`*.jsonl` nella cartella, valida e **deduplica** gli esempi di chat, crea la
suddivisione `train.jsonl`/`valid.jsonl` che MLX si aspetta, quindi lancia `python -m mlx_lm lora`
(e `mlx_lm fuse` con `--fuse`).

Servi il risultato con un server compatibile OpenAI (`mlx_lm.server --model <path>`) e imposta `vulnfanatic.apiBaseUrl` per puntare a esso, così da eseguire la scansione con il modello ottimizzato.

> I contesti di VulnFanatic-NG sono grandi, quindi di default lo script **adatta automaticamente**
> `--max-seq-length` all'esempio più lungo (arrotondato per eccesso, con limite massimo di **16384 token**).
> Le sequenze lunghe dominano la memoria di addestramento, quindi un modello grande vicino a questo limite può
> mandare in esaurimento la memoria di un Mac più piccolo. Se i tuoi esempi superano il limite, vengono troncati — passa un
> `--max-seq-length` più alto (più memoria) o riduci `vulnfanatic.storedContextChars`
> prima dell'esportazione. Se l'addestramento viene interrotto da un segnale (es. `exit -10` / SIGBUS),
> si tratta di un crash per esaurimento della memoria: riduci `--max-seq-length`, aggiungi `-- --grad-checkpoint`, oppure usa un
> modello più piccolo.

---

## Sviluppo e test

Il plugin non ha dipendenze di terze parti richieste. I moduli puri (`rules`, `tokens`, `llm`, `findings`, `settings`, `prototypes`) sono coperti da una suite di test offline che non richiede né Binary Ninja né una connessione di rete. La suite `tests/` risiede nel repository sorgente del progetto (non è inclusa nel plugin pubblicato); eseguila da lì. Dalla directory del pacchetto puoi comunque controllare la sintassi di ogni modulo:```
python3 -m py_compile *.py ui/*.py
python3 -m unittest discover -s tests   # from the source repository

I moduli che si interfacciano con Binary Ninja (context_builder, phase1, phase2) vengono importati senza problemi anche quando Binary Ninja non è presente (il loro accesso alle API è protetto), ma richiedono un'istanza di Binary Ninja in esecuzione per essere esercitati.

Test manuale in Binary Ninja

  1. Creare un piccolo programma C vulnerabile (ad esempio uno che usa strcpy per copiare argv[1] in un buffer di stack fisso e chiama system() sull'input). Compilare con i simboli per esercitare anche la Fase 2.
  2. Avviare il proprio server locale compatibile con OpenAI e impostare vulnfanatic.apiBaseUrl, vulnfanatic.apiKey e vulnfanatic.model.
  3. Aprire il binario, eseguire Start Scan e verificare che le chiamate pericolose vengano segnalate e che il doppio clic porti ai punti di chiamata.

Risoluzione dei problemi

SSL: CERTIFICATE_VERIFY_FAILED ... unable to get local issuer certificate — il certificato dell'endpoint HTTPS è valido, ma il Python incluso in Binary Ninja non ha un bundle di CA con cui verificarlo (comune su macOS e nei Python incorporati; lo si vede con endpoint ospitati come AWS Bedrock, Anthropic, Google, Azure). Risolvere con una delle seguenti opzioni, in ordine di preferenza:

  • Installare certifi nel Python usato da Binary Ninja: pip install certifi. VulnFanatic-NG lo rileva automaticamente.
  • Indicare un bundle di CA: impostare vulnfanatic.caBundlePath su un file bundle (o directory) — ad esempio il percorso stampato da python3 -m certifi, oppure /etc/ssl/cert.pem.
  • Ultima risorsa: disattivare vulnfanatic.tlsVerify (solo per un endpoint fidato/interno o un server locale autofirmato — questo disabilita il controllo dei certificati).

HTTP 400 ... tokenizer.chat_template is not set — il modello che stai servendo non ha un template di chat, quindi l'endpoint /chat/completions non può formattare i messaggi. VulnFanatic-NG torna automaticamente all'endpoint /completions per il resto della scansione quando vede questo errore, quindi la scansione continua. Per evitare del tutto la prima richiesta fallita, impostare vulnfanatic.apiMode su completions. In alternativa, risolverlo lato server servendo un modello che include un template di chat, o passarne uno al proprio server — ad esempio per vLLM: --chat-template <template.jinja> (oppure usare una variante di modello -Instruct/-Chat). Il template di chat dedicato di solito dà risultati migliori del prompt completions appiattito.

No JSON object found ... response looks truncated — la risposta del modello è stata interrotta prima che il JSON fosse completato. Due cause:

  • Lo scratchpad ha superato il budget di risposta → aumentare vulnfanatic.maxResponseTokens.
  • Più comunemente: il prompt riempie la finestra di contesto del modello, non lasciando spazio per generare, quindi la risposta si ferma dopo pochi token non importa quanto alto sia maxResponseTokens. I server locali hanno spesso una finestra piccola (ollama usa di default num_ctx=2048!). Per risolverlo, impostare vulnfanatic.modelContextWindow sulla finestra del proprio server (ad esempio ollama num_ctx, llama.cpp -c, vLLM --max-model-len) — VulnFanatic-NG limita quindi automaticamente il contesto inviato, così prompt + risposta ci stanno. Mantenere anche vulnfanatic.maxResponseTokens su un valore ragionevole (≈8192, non 65535) e/o aumentare la finestra del server. Finestre minuscole (≤8k) non riescono a contenere l'intero contesto interprocedurale; usare un modello/server configurato per 32k+.

IncompleteRead / Could not complete request ... after N attempt(s) — il server ha accettato la richiesta ma ha chiuso la connessione prima di inviare la risposta completa. Questo significa quasi sempre che il server del modello è morto o si è bloccato a metà generazione: esaurimento della memoria (contesto grande + output lungo), un timeout interno/worker, o un proxy che resetta la connessione. VulnFanatic-NG riprova automaticamente una volta e poi salta quel sito. Controllare i log del server del modello per la causa reale; ridurre vulnfanatic.maxContextTokens e/o vulnfanatic.maxResponseTokens, oppure dare al server più memoria / una finestra di contesto più ampia, di solito risolve il problema.

Limitazioni

  • La Fase 2 è sensibile ai simboli. Su un binario stripato, le corrispondenze basate sui nomi sono inaffidabili, quindi di default vengono eseguite solo le regole basate su string-evidence (le funzioni che fanno riferimento a costanti stringa rivelatrici sono comunque controllabili). Impostare vulnfanatic.phase2ForceEnable per controllare anche le corrispondenze basate sui nomi, oppure vulnfanatic.phase2RequireSymbols=off. Il filtro dei simboli è un'euristica.
  • La mappatura HLIL ↔ call-site può fallire; VulnFanatic-NG ripiega su MLIL/assembly e annota la rappresentazione utilizzata per ogni riscontro.
  • I verdetti sono validi quanto il modello. Trattare i riscontri come indizi per una revisione manuale, non come ground truth.
  • Alcuni server locali ignorano o rifiutano response_format=json_object; il client lo tollera ed estrae comunque il JSON. Disabilitare vulnfanatic.sendJsonResponseFormat se il proprio server rifiuta apertamente il parametro.

Licenza

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

Scarica lo strumento
switch
  • un riepilogo del data-flow degli argomenti — dove ogni argomento di chiamata viene definito e usato all'interno della funzione,
  • risoluzione dei parametri attraverso i chiamanti — quando un argomento pericoloso è un parametro della funzione chiamante, il contesto riporta ciò che ogni chiamante passa effettivamente (ad es. "tutti i chiamanti passano una stringa letterale"), così un parametro di formato/dimensione sempre costante non viene scambiato per controllato dall'attaccante,
  • il corpo decompilato completo della funzione chiamante,
  • definizioni dei tipi di dati (struct/union/enum) per i tipi referenziati attraverso la catena di chiamate e le variabili degli argomenti, così il modello conosce le dimensioni reali di buffer/campi e le larghezze degli interi,
  • i corpi decompilati delle funzioni che producono o consumano le variabili degli argomenti della chiamata (tracciati tramite def/use HLIL), ciò che rende possibile il ragionamento su use-after-free / double-free e dimensioni contaminate,
  • percorsi di chiamata dai punti di ingresso / funzioni esportate fino alla chiamata,
  • il corpo decompilato di ogni funzione lungo questi percorsi di chiamata (prima quelle più vicine alla chiamata pericolosa), ciascuna annotata con il punto di chiamata e le condizioni che proteggono il passo successivo,
  • i corpi delle altre funzioni chiamate da quelle sul percorso (ad es. per MAIN→ABCD→strcpy, anche le funzioni che MAIN e ABCD chiamano altrove), poiché potrebbero contenere i controlli di limiti/validazione che condizionano il valore pericoloso (vulnfanatic.includeCallPathSiblings, riempito finché il budget lo consente), e
  • suggerimenti di sorgenti contaminate (funzioni di input come recv/read/getenv chiamate nella stessa funzione).
  • medium
    high
  • vulnfanatic.skipConstantArgCalls (default disattivata) — salta i punti di chiamata della classe overflow i cui argomenti sono tutte costanti a tempo di compilazione.
  • ImpostazioneSignificato
    vulnfanatic.apiProviderQuale backend LLM chiamare: openai (predefinito), anthropic, google o azure. Vedi Backend LLM di seguito. Tutti i provider vengono raggiunti tramite la libreria standard di Python — non c'è nulla da pip install.
    vulnfanatic.apiBaseUrlBase dell'endpoint per il provider selezionato (vedi la tabella sotto). Predefinito http://localhost:8080/v1. Imposta al valore letterale TEST per abilitare la modalità test (vedi sotto).
    vulnfanatic.apiKeyChiave API / bearer token. Può essere vuota per i server locali. Sostituita dalle variabili d'ambiente VULNFANATIC_API_KEY o OPENAI_API_KEY.
    vulnfanatic.modelObbligatorio (tranne in modalità test). L'identificatore del modello (per azure, il nome del deployment).
    vulnfanatic.apiModeSolo openai: chat (predefinito, /chat/completions) vs completions (singolo prompt appiattito — per modelli base/instruct serviti senza un template di chat).
    vulnfanatic.azureApiVersionSolo azure: il parametro di query api-version (predefinito 2024-10-21).
    ProviderapiBaseUrlAutenticazioneNote
    openaiil tuo server, es. http://localhost:8080/v1Authorization: BearerChat/Completions compatibili OpenAI: llama.cpp / ollama / vLLM locali, OpenAI e l'endpoint compatibile OpenAI di AWS Bedrock.
    anthropicvuoto → https://api.anthropic.comx-api-key + anthropic-versionMessages API di Claude (POST <base>/v1/messages). temperature non viene inviata (i modelli Claude attuali la rifiutano).
    googlevuoto → https://generativelanguage.googleapis.comchiave API nell'URLGemini generateContent (<base>/v1beta/models/<model>:generateContent).
    azurehttps://<resource>.openai.azure.comheader api-keyAzure OpenAI; imposta model sul nome del deployment e azureApiVersion sulla tua versione 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
    Registrazione di debug
    vulnfanatic.sendJsonResponseFormat
    vulnfanatic.tlsVerify
    vulnfanatic.caBundlePath
    CERTIFICATE_VERIFY_FAILED
    vulnfanatic.rulesPhase1Path
    vulnfanatic.rulesPhase2Path
    vulnfanatic.rulesPhase3Path