Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
VulnFanatic-NG — Plugin de BianryNinja para identificar vulnerabilidades en binarios descompilados con escaneos programáticos y soporte de LLM. | Kitploit
Herramientas/GitHubGitHub/martyx00/vulnfanatic-ng
Análisis Estático de Código (SAST)Análisis de VulnerabilidadesAnálisis de CódigoExplotaciónIngeniería InversaFuzzingPruebas de PenetraciónSeguridad de HardwareAnálisis de BinariosSeguridad de Cadena de SuministroAprendizaje y EducaciónReversing Asistido por IA
1415hace 2 mesesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
GitHubmartyx00/vulnfanatic-ng

VulnFanatic-NG

Plugin de BianryNinja para identificar vulnerabilidades en binarios descompilados con escaneos programáticos y soporte de LLM.

Ver Repositorio

VulnFanatic-NG

Investigación de vulnerabilidades asistida por LLM para Binary Ninja.

VulnFanatic-NG añade un panel lateral que escanea el binario actual y pregunta a un LLM — un modelo alojado localmente compatible con OpenAI por defecto, o Anthropic Claude, Google Gemini, o Azure OpenAI (ver Backends de LLM) — para juzgar si el código sospechoso es realmente vulnerable. Funciona principalmente a partir de la salida del descompilador (HLIL) de Binary Ninja, recurriendo al ensamblador cuando es necesario, e informa solo problemas confirmados con referencias en las que se puede hacer clic hacia el código.


Cómo funciona

Un análisis se ejecuta en hasta tres fases (La Fase 3 es opcional y solo en línea):

Fase 1 — llamadas a funciones peligrosas

Encuentra sitios de llamada de funciones peligrosas definidas en rules/phase1_rules.json — strcpy, memcpy, sprintf/cadenas de formato, system, alloca, scanf, APIs de comando/ejecución, RNG débil, la familia free/delete (uso después de liberación / doble liberación), lecturas de entrada no confiable en buffers fijos (recv/read/fread/ReadFile), inyección SQL (sqlite3_exec/mysql_query/PQexec), verificación de certificado TLS deshabilitada (SSL_CTX_set_verify/curl), SSRF, y gestión de privilegios inadecuada (setuid/setresgid), la familia memset/bzero, y comparaciones con una longitud controlada por el atacante (memcmp/strncmp → bypass de autenticación), en C/C++, Win32, y (con el mejor esfuerzo) Rust FFI. Cobertura incluye variantes fortificadas _chk (FORTIFY) y con verificación de límites _s (Anexo-K). Las funciones de salida con formato acotado (snprintf y variantes) tienen su propia regla segura por defecto, por lo que un argumento de tamaño correcto no se reporta como desbordamiento. Los sitios de llamada se encuentran de tres maneras: llamadas directas a los símbolos nombrados; llamadas enrutadas a través de stubs de reenvío / PLT (se recuperan los llamadores reales, de modo que no se pierde una importación alcanzada solo a través de un stub); y — a menos que vulnfanatic.scanIndirectCalls esté desactivado — llamadas indirectas despachadas a través de un puntero a función o vtable que Binary Ninja resolvió a una función peligrosa. Para cada sitio de llamada, construye un contexto interprocedimental centrado en el descompilador, limitado a un presupuesto de tokens (por defecto 100k):

  • la expresión de la llamada y sus argumentos,
  • el prototipo declarado de la función llamada (de la información de tipos de Binary Ninja, o de una tabla incorporada) para que el modelo asigne argumentos a parámetros correctamente — las variantes fortificadas __*_chk y con verificación de límites *_s toman argumentos iniciales adicionales, desplazando la posición del formato/tamaño/destino,
  • el tipo y tamaño en bytes de cada argumento de llamada (capacidades de los buffers), derivado del tipo de la expresión HLIL del argumento, de modo que un campo de estructura como s->buf se resuelva al tamaño real del array del campo en lugar del tamaño del puntero de s; las definiciones de estructuras en la sección de tipos también llevan tamaños en bytes por campo,
  • el valor concreto / rango de cada argumento resuelto por el análisis de propagación de constantes y de conjuntos de valores de Binary Ninja (por ejemplo, una longitud probada constante 0x40 o acotada a [0, 0xff]), que el modelo usa como verdad fundamental al comparar un tamaño con la capacidad de un buffer en lugar de adivinar,
  • el diseño del marco de pila de la función llamadora (desplazamientos de variables y tamaños en bytes) cuando contiene un buffer de tamaño fijo, de modo que un desbordamiento de pila pueda juzgarse frente a las variables adyacentes y la dirección de retorno guardada (vulnfanatic.includeStackLayout),
  • las restricciones de ruta (las condiciones if/bucle/ que protegen la llamada),

Ese contexto, junto con un prompt específico de la regla, se envía al modelo, que devuelve un veredicto estructurado. Los no-problemas se descartan. Los prompts están ajustados para un modelo de código local potente (por ejemplo, Qwen2.5-Coder) y le indican que analice todo el flujo y emita solo JSON.

Razonamiento, borrador y confianza

Se le indica al modelo que favorezca el recuerdo — reporte problemas plausibles y relevantes para la seguridad y exprese incertidumbre a través de una Confianza en lugar de descartar cualquier cosa que no pueda probar completamente. Muestra su trabajo en un borrador que cita los fragmentos de código literales en los que se basó (la fuente de entrada, cada protección, el tamaño/longitud, el tipo relevante, y el sumidero), que se almacena en el hallazgo para que puedas auditar el razonamiento.

Cada hallazgo lleva una Confianza (alta/media/baja): alta = toda la cadena se muestra en el contexto; media = probable, con uno o dos enlaces inferidos; baja = una pista que merece revisión manual. Esta es la métrica principal (la estimación de severidad del modelo es un campo secundario). Establece vulnfanatic.minConfidence para descartar cualquier cosa por debajo de un umbral.

Ajustando precisión vs. recuerdo

Por defecto VulnFanatic-NG favorece el recuerdo (detectar problemas reales). Si obtienes demasiados falsos positivos, ajústalo con cualquiera de:

  • vulnfanatic.validationPass (por defecto desactivado) — ejecuta una segunda pasada del LLM que verifica cada problema marcado contra el mismo contexto (verificando los fragmentos del borrador y re-rastreando el flujo) y puede corregir el veredicto o la confianza. Duplica las llamadas al LLM para los candidatos marcados.
    • Modelo validador separado (recomendado cuando se usa la pasada de validación). Establece vulnfanatic.validatorModel (más validatorProvider / validatorBaseUrl / validatorApiKey) para ejecutar la segunda pasada en un modelo diferente. Una segunda opinión es mucho más útil de un modelo independiente — comparte menos puntos ciegos y es mucho menos probable que refrende automáticamente el primer veredicto (los modelos tienden a preferir sus propias respuestas). Un buen patrón es una cascada: un modelo rápido como analista (recuerdo amplio) y tu modelo más fuerte como validador, que solo se ejecuta sobre los candidatos marcados. Deja el modelo validador en blanco para validar con el modelo analista. El validador debe ser al menos tan capaz como el analista — uno más débil añade principalmente falsos rechazos. Todo excepto proveedor/URL base/clave/modelo se hereda de la configuración de conexión del analista; una clave de validador en blanco reutiliza la clave del analista; y si el endpoint del validador es inalcanzable, se conserva el primer veredicto (el hallazgo nunca se pierde por una caída del validador).
  • vulnfanatic.minConfidence (por defecto low) — ajústalo a / para reportar solo hallazgos más sólidos.

Velocidad. La mayor parte de la latencia por llamada es el razonamiento escrito, por lo que vulnfanatic.verdictReasoning controla cuánto escribe el modelo:

  • concise (por defecto) — una breve justificación de 1 a 3 frases, sin código literal. Mucho más rápido que full con poca pérdida de precisión; también puedes reducir vulnfanatic.maxResponseTokens.
  • full — el borrador detallado con fragmentos citados (más auditable, más lento).
  • none — solo veredicto. Lo más rápido; combínalo con un backend con capacidad de razonamiento (vulnfanatic.reasoningEffort) para que el pensamiento interno del modelo haga el trabajo. En un modelo local simple, none pierde precisión (sin cadena de pensamiento en absoluto).

Funciones de precisión complementarias que siempre están activas (informan al modelo sin suprimir hallazgos):

  • Procedencia de argumentos — el contexto le dice al modelo, por argumento, si es una constante en tiempo de compilación, un parámetro de función, o derivado de una fuente contaminada, que el modelo usa para establecer la confianza.
  • Conciencia de variantes con verificación de límites — los prompts tratan las variantes _s (Anexo K) y _chk (FORTIFY) y las API con longitud acotada como seguras a menos que el propio argumento de tamaño sea incorrecto.
  • Tamaños de buffer explícitos — se proporcionan las capacidades en bytes de los argumentos y los campos de estructura para que el modelo compare la capacidad contra los bytes escritos en lugar de adivinar.

Análisis sin conexión (sin LLM)

El botón Análisis sin conexión ejecuta la Fase 1 sin modelo — heurísticas puramente programáticas declaradas en el bloque offline de cada regla en phase1_rules.json. Marca los sitios de llamada peligrosos y elimina los obviamente seguros, asignando una Confianza heurística:

  • Eliminado (no se informa): un memcpy/memmove con una longitud constante, un strcpy desde una cadena constante, un printf con un formato constante, un system con un comando constante, etc. — llamadas cuyo argumento rector es una constante en tiempo de compilación y por lo tanto no puede ser controlado por el atacante. "Constante" incluye valores que el análisis de conjuntos de valores de Binary Ninja fijó a un número fijo aguas arriba, no solo argumentos literales.
  • Alta confianza: marcado sin ninguna comprobación mitigante encontrada en ningún lugar del flujo de ejecución.
  • Degradado (→ media): el argumento de tamaño/longitud se resolvió a un rango constante/acotado por el análisis de conjuntos de valores de Binary Ninja, o se encontró una comprobación de límites/validación real comparando el argumento relevante (por ejemplo, una comparación strlen/tamaño, if (len < …)) en algún lugar del flujo — incluyendo en las funciones llamadas a lo largo de la ruta — por lo que puede que ya esté manejado. (Una rama que simplemente menciona la variable sin compararla ya no cuenta, eliminando una fuente de degradaciones espurias.)

Las heurísticas usan un pequeño vocabulario declarativo en las reglas (constant_safe_args, eliminate_if_all_args_constant, format_arg_lookup, length_guard_vars, base_confidence, skip) evaluadas por predicados de Python — sin código incrustado para exec. La mayoría de las reglas tienen una definición sin conexión (desbordamiento, cadena de formato, ejecución de comandos, scanf, manejo de rutas, RNG débil, análisis numérico débil, cambios de privilegios, tamaño de asignación, …). Solo las dos categorías que realmente necesitan análisis semántico se saltan sin conexión y se dejan para el LLM: la familia free/delete (uso después de liberación / doble liberación, que necesita seguimiento de la vida útil del puntero) y la verificación TLS (el error es un valor constante específico como SSL_VERIFY_NONE). El resumen sin conexión informa cuántos sitios fueron marcados / eliminados / saltados (necesitan el LLM) / fallidos, para que los recuentos sumen. Esto es un triaje rápido; para un juicio real — y para las categorías saltadas — ejecuta el análisis completo con LLM.

Los hallazgos sin conexión aún construyen el mismo contexto interprocedimental completo que un análisis en línea enviaría (solo para los sitios marcados) y lo almacenan, de modo que una vez que los triajes, se pueden exportar como datos de ajuste fino al igual que los hallazgos en línea. Desactívalo con vulnfanatic.offlineBuildContext si deseas la máxima velocidad sin conexión.

Fase 2 — código sensible a la seguridad (protegido por símbolos)

Solo se ejecuta cuando el binario parece tener símbolos reales / nombres de variables. Localiza funciones sensibles a la seguridad definidas en rules/phase2_rules.json — autenticación, criptografía (incl. algoritmos débiles), verificación de firmas/certificados, manejo de sesiones/tokens, control de acceso, manejo de secretos/claves, validación de entrada, comparación de secretos no constante en tiempo, y deserialización insegura — emparejadas por nombre de función y cadenas referenciadas, luego auditadas por el modelo.

Fase 3 — auditoría de endurecimiento contra ataques hardware (en línea, opcional)

Una auditoría de endurecimiento de firmware contra ataques de inyección de fallos (glitching de voltaje/reloj/EM) y de canal lateral (tiempo/potencia), basada en guías de mitigación de ataques hardware. A diferencia de las Fases 1–2 (que encuentran errores), la Fase 3 informa un control de endurecimiento faltante o violado en una función crítica para la seguridad — por ejemplo: ramas de fallo por defecto, decisiones de seguridad doblemente verificadas, validación de contador después de bucles, constantes de estado con alta distancia de Hamming (frente a 0/1 simple), comparación de secretos de longitud completa en tiempo constante, acceso/borrado de secretos con desplazamiento aleatorio, cifrar-luego-verificar (anti-DFA), contadores de integridad de flujo de control, evitar criptografía en espacio de usuario, y no manejar material de clave sin procesar directamente (rules/phase3_rules.json).

Debido a que las optimizaciones del compilador pueden eliminar protecciones a nivel de fuente, estos controles se verifican mejor en el binario compilado — exactamente lo que esto comprueba. La Fase 3 es solo con LLM (en línea), protegida por símbolos, y desactivada por defecto; actívala por análisis con la casilla Fase 3 en la pestaña de Nuevo Análisis (nunca se ejecuta en modo sin conexión).

Los hallazgos se muestran en una tabla (estado, confianza, fase, CWE, función, dirección, título) con un panel de detalles que muestra la explicación, el borrador del análisis y las notas de validación. Haz doble clic en una fila para navegar la vista del binario hasta el código.

Flujo de trabajo de triaje

Cada hallazgo comienza Sin triangular. Haz clic derecho en una fila para establecer su estado — Marcar como Problema Real, Marcar como Falso Positivo, o Marcar como Sin triangular. Cada cambio de estado muestra un cuadro de texto "Proporciona razón:" (la razón se almacena con el hallazgo). La tabla hace evidente el estado: los Problemas Reales son verde/negrita y se ordenan al principio, los Falsos Positivos son gris/tachados y se ordenan al final, los Sin triangular se sitúan en medio con su color de confianza. Una línea de resumen muestra los recuentos.

Cada pestaña de resultados tiene un botón Exportar triados (ajuste fino)… que exporta solo los hallazgos triados (Problema Real + Falso Positivo) como JSONL en formato de chat de OpenAI para ajuste fino: cada ejemplo empareja el prompt original de sistema+usuario con el veredicto corregido por humano como destino del asistente (un Falso Positivo enseña is_vulnerable=false con tu razón; un Problema Real refuerza is_vulnerable=true), para que puedas mejorar iterativamente la precisión del modelo en tus binarios.

El contexto por hallazgo mostrado en el panel de detalles (y usado para reconstruir los prompts de ajuste fino) se mantiene, por defecto, completo — controlado por vulnfanatic.storedContextChars (0 = ilimitado; establece un límite positivo, p. ej. 4000, para limitar el crecimiento del BNDB a costa de la fidelidad del contexto).

Múltiples análisis (pestañas)

El panel tiene pestañas. La primera pestaña es siempre Nuevo Análisis, donde estableces:

  • un Nombre de análisis opcional (en blanco → <marca de tiempo> <modo>, p. ej. 2026-06-15 14:03:50 sin conexión),
  • una ruta de reglas personalizadas para Fase 1 / Fase 2 / Fase 3 opcional (en blanco → los valores predeterminados incluidos), para que puedas ejecutar un conjunto de reglas alternativo,
  • una casilla Fase 3 (desactivada por defecto) para ejecutar adicionalmente la auditoría de endurecimiento contra ataques hardware solo en línea,

luego presiona Iniciar Análisis o Análisis sin Conexión. Cada ejecución abre su propia pestaña de resultados y los hallazgos se transmiten en vivo. Todos los análisis se almacenan en el BNDB, por lo que puedes, p. ej., conservar un análisis sin conexión y luego agregar un análisis en línea, o comparar ejecuciones con diferentes conjuntos de reglas, lado a lado — reaparecen como pestañas cuando vuelves a abrir la base de datos. Cerrar una pestaña elimina permanentemente ese análisis del BNDB — para evitar accidentes, muestra una confirmación que requiere marcar "Confirmo que perderé los resultados de para siempre" antes de que se active el botón Eliminar resultados para siempre. Exportar análisis actual… escribe la pestaña seleccionada a Markdown/JSON.

Cada binario abierto tiene su propio estado de panel independiente — sus propias pestañas de análisis y análisis en ejecución. Iniciar un análisis en un binario y cambiar a otro muestra los resultados del segundo binario (y te permite analizarlo por separado); el análisis del primer binario sigue ejecutándose en segundo plano y está intacto cuando vuelves.


Instalación

La carpeta del paquete de este plugin se llama vulnfanatic_ng (un identificador válido de Python — Binary Ninja importa el nombre de la carpeta del plugin como un módulo, por lo que un nombre con guión como VulnFanatic-NG no se cargaría).

  1. (Opcional) Instala el conteo preciso de tokens en el Python de Binary Ninja: ``` pip install tiktoken

    root@kitploit:~
  2. Cree un enlace simbólico o copie la carpeta vulnfanatic_ng en el directorio de plugins de usuario de Binary Ninja:

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

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

    root@kitploit:~
  3. Reinicie Binary Ninja (o ejecute Reload Plugins). Aparece un icono VF en la barra lateral derecha.


Configuración

Abra Ajustes (el engranaje / Edit ▸ Preferences ▸ Settings) y busque vulnfanatic. Configure como mínimo:

Backends LLM

vulnfanatic.apiProvider selecciona cómo se forman y autentican las solicitudes. El contrato de veredicto (y todas las indicaciones de reglas) son idénticos entre proveedores.

AWS Bedrock se puede usar a través del proveedor openai mediante su endpoint compatible con OpenAI, por lo que no necesita un backend dedicado.

Otros ajustes útiles: vulnfanatic.maxContextTokens (predeterminado 100000), vulnfanatic.maxResponseTokens, vulnfanatic.temperature, vulnfanatic.reasoningEffort (off/low/medium/high; predeterminado high — pide al modelo que piense antes de responder donde sea compatible, mapeado por proveedor: openai/azure reasoning_effort, anthropic pensamiento adaptativo + output_config.effort, google thinkingConfig dinámico; se elimina automáticamente y se reintenta si un modelo lo rechaza), vulnfanatic.requestTimeoutSec, vulnfanatic.callPathMaxDepth / , (incluye los cuerpos descompilados de las funciones a lo largo de la ruta de llamada; predeterminado activado) / (límite, predeterminado 12), (incluye también otras funciones llamadas a lo largo de la ruta, que pueden contener las comprobaciones de límites/validación; predeterminado activado) / (límite, predeterminado 12), (incluye definiciones de struct/union/enum; predeterminado activado) / (límite, predeterminado 24), (rastrea los argumentos de llamada hacia atrás a través de sus productores /consumidores e incluye esos cuerpos; predeterminado activado) / (límite, predeterminado 8), (incluye el diseño de variables de pila de la función llamante cuando tiene un búfer de tamaño fijo; predeterminado activado), (también coincide con llamadas peligrosas despachadas a través de un puntero a función/vtabla resuelto; predeterminado activado — desactive para un escaneo más rápido en binarios muy grandes), (ejecuta la segunda pasada de doble comprobación; predeterminado desactivado) / / / / (ejecuta la pasada de validación en un modelo independiente y separado — en blanco = mismo modelo que el analista) / (//; descarta hallazgos por debajo de esto; predeterminado ), (informa los sitios que el modelo no pudo puntuar como pistas "Unscored" con confianza en lugar de descartarlos; predeterminado activado), (omite sitios de llamada de desbordamiento con todos los argumentos constantes; predeterminado desactivado), (//; cuánto razonamiento escribe el modelo por veredicto — la principal palanca de velocidad; predeterminado ), / / (habilita cada fase; La fase 3 es solo en línea y generalmente se activa por escaneo mediante la casilla Nueva exploración en lugar de aquí), / , (codificación tiktoken para estimaciones de tokens; retrocede a una heurística de caracteres si tiktoken no está instalado), (construye contexto completo para hallazgos fuera de línea para que puedan exportarse para ajuste fino; predeterminado activado), (traza detallada del pipeline en la consola; predeterminado desactivado) / (redacta todos los detalles que identifican el binario para que el registro pueda compartirse — consulte más abajo), , (verifica certificados HTTPS; predeterminado activado) / (paquete CA para HTTPS — consulte Solución de problemas si encuentra ), y / / (apunte estos a sus propios archivos de reglas para personalizar detecciones y prompts).

Nota de seguridad: la clave API se almacena en los ajustes de Binary Ninja en texto plano. Prefiera la anulación mediante variable de entorno para claves sensibles.

Modo de prueba (ejecución en seco, sin LLM)

Establezca vulnfanatic.apiBaseUrl al valor literal TEST para ejecutar sin ningún LLM:

  • El modelo nunca se llama (sin red, sin necesidad de clave API/modelo).
  • Cada candidato (cada sitio de llamada peligrosa en la Fase 1, cada función sensible a la seguridad en la Fase 2) se marca.
  • El prompt completo — prompt del sistema y el contexto generado completo — para cada candidato se escribe en su propio archivo bajo /tmp/vulnfanatic_ng/<binary>-<timestamp>/.
  • La tabla de hallazgos muestra una columna Archivo de prompt (pase el ratón para ver la ruta completa), y el panel de detalles y las exportaciones incluyen la ruta.

Úselo para inspeccionar y validar exactamente lo que VulnFanatic-NG enviaría al modelo, e iterar sobre los prompts/contexto de las reglas sin gastar tiempo de modelo.

Registro de depuración

Active vulnfanatic.debugLogging para imprimir una traza detallada, paso a paso, del pipeline de escaneo (tanto en línea como fuera de línea) en el registro/consola de Binary Ninja: cada sitio de llamada, cada decisión de omisión/eliminación, construcción de contexto (solo tamaño), cada solicitud LLM (proveedor/modelo/endpoint, reintentos, fallbacks), cada veredicto y cada hallazgo reportado. Las claves API nunca se registran.

Mientras el registro de depuración está activado, un escaneo en línea mantiene cada candidato en la tabla de resultados en lugar de descartar los que no se convierten en problemas confirmados, cada uno etiquetado con un estado solo de depuración (atenuado, ordenado al final):

  • REJECTED — el LLM devolvió un veredicto de no es un problema.
  • SKIPPED — eliminado antes del LLM por una regla demostrablemente segura (una cadena de formato constante, o argumentos todos constantes); la fila explica cuál.
  • ERROR — el candidato no pudo ser analizado (falló la construcción de contexto, o la respuesta del LLM fue no analizable / la conexión falló); la fila lleva el error.

Por lo tanto, un escaneo de depuración muestra una fila por candidato en el total /N, y el resumen informa problemas frente a recuentos de rechazados/omitidos/error por separado. Puede hacer clic derecho en cualquiera de estas filas para reclasificarlo como Problema real o Falso positivo (lo que lo hace elegible para exportación de ajuste fino). (Los escaneos fuera de línea no se ven afectados — nunca llaman al LLM.)

Independientemente del modo de depuración, cuando un modelo devuelve una respuesta no analizable — un token errático como <unused…> de Gemma, prosa en lugar de JSON, o un mensaje vacío (solo un role, sin content) — el cliente realiza un reintento correctivo, pidiendo de nuevo JSON solo con el formato de salida estructurada desactivado; si eso tiene éxito, mantiene el formato desactivado para el resto del escaneo. El cliente también lee el canal de razonamiento (reasoning_content / reasoning) cuando content está vacío, por lo que los modelos de razonamiento que colocan su respuesta allí siguen funcionando.

El caso de mensaje vacío es común con modelos de razonamiento como GPT-OSS / o1 servidos a través de una API compatible con OpenAI (ej. mlx-community/gpt-oss-20b): con response_format=json_object establecido, el canal de respuesta "final" de armonía a menudo se suprime y el servidor devuelve {"role": "assistant"} sin contenido. Estos modelos también pueden quemar todo su presupuesto de salida en el canal de razonamiento y ser truncados a mitad de pensamiento, devolviendo prosa sin ningún JSON. El reintentado automático recupera los casos relacionados con el formato; si persiste, desactive vulnfanatic.sendJsonResponseFormat, reduzca vulnfanatic.reasoningEffort (así que menos presupuesto va al pensamiento), y/o aumente vulnfanatic.maxResponseTokens. Una respuesta persistente de <unused…>/basura en su lugar generalmente significa que el prompt supera la ventana de contexto del modelo (establezca vulnfanatic.modelContextWindow y/o aumente la longitud de contexto del servidor), o que el modelo es una mala opción para salida JSON estricta (un modelo de código como Qwen2.5-Coder se comporta mucho mejor que Gemma aquí).

Retroceso conservador de recuerdo. Cuando un candidato aún no puede puntuarse después del reintento, vulnfanatic.flagUnparseableResponses (predeterminado activado) lo reporta de todos modos como un hallazgo "Unscored" con confianza UNKNOWN — un valor distinto de low (el modelo nunca produjo un veredicto, por lo que no es un juicio de baja confianza) que se ordena al final — manteniendo la salida parcial del modelo como explicación, para que no pierda el sitio, simplemente lo revisa manualmente. Desactívelo para descartar dichos sitios (entonces aparecen solo como errores de análisis, o filas ERROR de depuración).

También active vulnfanatic.debugAnonymous para hacer que el registro sea seguro de compartir: redacta todo lo que pueda identificar el archivo analizado — los nombres de símbolos/variables y direcciones se convierten en hashes salados por ejecución (aún consistentes dentro de una ejecución para que el flujo sea seguible), el nombre del archivo se oculta, el texto del hallazgo se reemplaza con <redacted>, el host del endpoint LLM se hashea, y el código descompilado / prompts / contexto se registran solo como tamaños (nunca el contenido). Así puede enviar un registro de depuración para informar un problema sin revelar nada sobre su binario.


Uso

  1. Abra un binario y deje que el análisis finalice.
  2. Haga clic en el icono de la barra lateral VF para abrir VulnFanatic-NG.
  3. Presione Iniciar escaneo (escaneo LLM completo) o Escaneo sin conexión (rápido, Fase 1 programática sin LLM — véase más arriba). El progreso se muestra en el panel y en la barra de estado de Binary Ninja; los hallazgos aparecen en vivo y pueden cancelarse.
  4. Haga clic en un hallazgo para leer la explicación; haga doble clic para ir al código.
  5. Haga clic derecho en un hallazgo para Marcar como falso positivo — se mueve al final de la tabla, atenuado y tachado, y la entrada del menú cambia a Marcar como problema real para deshacerlo. (El menú contextual también tiene Ir al código).
  6. Exporte a Markdown o JSON, o Limpiar para descartar hallazgos guardados.

Los hallazgos — incluido su estado de falso positivo — se almacenan en la base de datos de Binary Ninja. Se escriben en el .bndb cuando guarda la base de datos (y se vacían inmediatamente si ya existe un .bndb), por lo que sobreviven al reabrir.

El escaneo analiza cada sitio de llamada coincidente (sin límite), lo que es apropiado para modelos locales. Para un endpoint alojado/de pago, tenga en cuenta el volumen en binarios grandes.


Personalización de reglas

Ambos archivos de reglas comparten un envoltorio con un system_prompt compartido y output_schema, más una lista de rules. Copie un archivo empaquetado, edite las funciones/palabras clave/prompts, y apunte vulnfanatic.rulesPhase1Path / vulnfanatic.rulesPhase2Path a su copia. Las reglas de la Fase 1 coinciden por functions (exacto) y name_regex; las reglas de la Fase 2 coinciden por name_keywords, name_regex, y string_keywords. El prompt de cada regla puede usar el marcador de posición {function}.


Ajuste fino del modelo (MLX, Apple Silicon)

Las exportaciones triadas están diseñadas para alimentarse directamente de vuelta al modelo. Después de triar hallazgos en varios binarios y hacer clic en Exportar triados (ajuste fino)… en cada uno (recolectando los archivos .jsonl en una carpeta), scripts/finetune_mlx.py ejecuta un ajuste fino LoRA de MLX sobre ellos.```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:~
El script toma la **carpeta de datos de entrenamiento** como su argumento posicional y el
**`--model`** base (ruta local o ID de repositorio MLX/HF); otros parámetros son opcionales:
`--adapter-path`, `--valid-split` (0.1), `--iters`, `--batch-size` (ajustado automáticamente para
ajustarse a una división pequeña), `--num-layers`, `--learning-rate`, `--max-seq-length`
(`0` = **autoajuste** al ejemplo más largo, limitado a 16384; establezca un valor positivo para
forzarlo), `--fine-tune-type` (`lora`/`dora`/`full`), `--seed`, `--fuse`/`--fused-path`,
y `--dry-run` (preparar datos + imprimir el comando sin entrenar). Todo después de un
literal `--` se reenvía textualmente a `mlx_lm lora`. Fusiona recursivamente cada
`*.jsonl` en la carpeta, valida y **desduplica** los ejemplos de chat, crea la
división `train.jsonl`/`valid.jsonl` que MLX espera, luego lanza `python -m mlx_lm lora`
(y `mlx_lm fuse` con `--fuse`).

Sirva el resultado con un servidor compatible con OpenAI (`mlx_lm.server --model <ruta>`)
y apunte `vulnfanatic.apiBaseUrl` de vuelta a él para escanear con su modelo ajustado.

> Los contextos de VulnFanatic-NG son grandes, por lo que, de forma predeterminada, el script **autoajusta**
> `--max-seq-length` a su ejemplo más largo (redondeado hacia arriba, limitado a **16384 tokens**).
> Las secuencias largas dominan la memoria de entrenamiento, por lo que un modelo grande cerca de este límite puede
> dejar sin memoria a una Mac más pequeña. Si sus ejemplos exceden el límite, se truncan — pase un
> `--max-seq-length` más alto (más memoria) o reduzca `vulnfanatic.storedContextChars`
> antes de exportar. Si el entrenamiento es interrumpido por una señal (ej. `exit -10` / SIGBUS), eso es
> un fallo por falta de memoria: reduzca `--max-seq-length`, agregue `-- --grad-checkpoint`, o use un
> modelo más pequeño.

---

## Desarrollo y pruebas

El plugin tiene cero dependencias de terceros requeridas. Los módulos puros
(`rules`, `tokens`, `llm`, `findings`, `settings`, `prototypes`) están cubiertos por una
suite de pruebas fuera de línea que no necesita ni Binary Ninja ni una red. La suite `tests/`
reside en el repositorio fuente del proyecto (no se envía dentro del
plugin publicado); ejecútela desde allí. Desde el directorio del paquete aún puede
verificar la sintaxis de cada módulo:```
python3 -m py_compile *.py ui/*.py
python3 -m unittest discover -s tests   # from the source repository

Los módulos que interactúan con Binary Ninja (context_builder, phase1, phase2) se importan limpiamente sin Binary Ninja (su acceso a la API está protegido) pero requieren un Binary Ninja en ejecución para ejercitarse.

Prueba manual dentro de Binary Ninja

  1. Construya un pequeño programa C vulnerable (por ejemplo, uno que haga strcpy de argv[1] en un búfer fijo en la pila y llame a system() con la entrada). Compile con símbolos para ejercitar también la Fase 2.
  2. Inicie su servidor local compatible con OpenAI y configure vulnfanatic.apiBaseUrl, vulnfanatic.apiKey y vulnfanatic.model.
  3. Abra el binario, ejecute Iniciar escaneo y confirme que las llamadas peligrosas son reportadas y que al hacer doble clic se navega a los sitios de las llamadas.

Solución de problemas

SSL: CERTIFICATE_VERIFY_FAILED ... unable to get local issuer certificate — el certificado del endpoint HTTPS es correcto, pero el Python incluido con Binary Ninja no tiene un paquete de CA para verificarlo (común en macOS y en Pythons integrados; verá esto con endpoints alojados como AWS Bedrock, Anthropic, Google, Azure). Solución con una de las siguientes, en orden de preferencia:

  • Instale certifi en el Python que Binary Ninja usa: pip install certifi. VulnFanatic-NG lo detecta automáticamente.
  • Apunte a un paquete de CA: establezca vulnfanatic.caBundlePath en un archivo de paquete (o directorio) — por ejemplo, la ruta impresa por python3 -m certifi, o /etc/ssl/cert.pem.
  • Último recurso: desactive vulnfanatic.tlsVerify (solo para un endpoint de confianza/interno o un servidor local autofirmado — esto deshabilita la verificación del certificado).

HTTP 400 ... tokenizer.chat_template is not set — el modelo que está sirviendo no tiene una plantilla de chat, por lo que el endpoint /chat/completions no puede formatear los mensajes. VulnFanatic-NG vuelve automáticamente al endpoint /completions para el resto del escaneo cuando ve este error, por lo que el escaneo continúa. Para evitar la primera solicitud fallida por completo, establezca vulnfanatic.apiMode en completions. Alternativamente, arréglelo del lado del servidor sirviendo un modelo que incluya una plantilla de chat, o pase una a su servidor — por ejemplo, para vLLM: --chat-template <template.jinja> (o use una variante de modelo -Instruct/-Chat). La plantilla de chat dedicada generalmente da mejores resultados que el prompt plano de completions.

No JSON object found ... response looks truncated — la respuesta del modelo se cortó antes de que el JSON terminara. Dos causas:

  • El bloc de notas excedió el presupuesto de respuesta → aumente vulnfanatic.maxResponseTokens.
  • Más comúnmente: el prompt llena la ventana de contexto del modelo, sin dejar espacio para generar, por lo que la respuesta se detiene después de unos pocos tokens sin importar cuán alto sea maxResponseTokens. Los servidores locales a menudo tienen una ventana pequeña (ollama predeterminado num_ctx=2048). Solución: establezca vulnfanatic.modelContextWindow al valor de la ventana de su servidor (por ejemplo, ollama num_ctx, llama.cpp -c, vLLM --max-model-len) — VulnFanatic-NG entonces limita automáticamente el contexto que envía para que el prompt + la respuesta quepan. También mantenga vulnfanatic.maxResponseTokens razonable (≈8192, no 65535) y/o aumente la ventana del servidor. Las ventanas pequeñas (≤8k) no pueden contener el contexto interprocedimental completo; use un modelo/servidor configurado para 32k+.

IncompleteRead / Could not complete request ... after N attempt(s) — el servidor aceptó la solicitud pero cerró la conexión antes de enviar la respuesta completa. Esto casi siempre significa que el servidor del modelo se cayó o se estancó durante la generación: falta de memoria (contexto grande + salida larga), un tiempo de espera interno/del trabajador, o un proxy reiniciando la conexión. VulnFanatic-NG reintenta una vez automáticamente y luego omite ese sitio. Revise los registros del servidor del modelo para la causa real; reducir vulnfanatic.maxContextTokens y/o vulnfanatic.maxResponseTokens, o darle al servidor más memoria / una ventana de contexto más grande, generalmente lo resuelve.

Limitaciones

  • La Fase 2 depende de los símbolos. En un binario sin símbolos, las coincidencias basadas en nombres son poco fiables, por lo que por defecto solo se ejecutan las reglas de evidencia de cadenas (las funciones que hacen referencia a constantes de cadena reveladoras aún se pueden auditar). Establezca vulnfanatic.phase2ForceEnable para también auditar coincidencias basadas en nombres, o vulnfanatic.phase2RequireSymbols=off. La compuerta de símbolos es una heurística.
  • La asignación HLIL ↔ sitio de llamada puede fallar; VulnFanatic-NG recurre a MLIL/ensamblador y anota la representación utilizada por cada hallazgo.
  • Los veredictos son solo tan buenos como el modelo. Trate los hallazgos como pistas para una revisión manual, no como verdad absoluta.
  • Algunos servidores locales ignoran o rechazan response_format=json_object; el cliente lo tolera y aún así extrae JSON. Desactive vulnfanatic.sendJsonResponseFormat si su servidor rechaza el parámetro por completo.

Licencia

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

Descargar herramienta
switch
  • un resumen del flujo de datos de los argumentos — dónde se define y utiliza cada argumento de la llamada dentro de la función,
  • resolución de parámetros a través de los llamadores — cuando un argumento peligroso es un parámetro de la función llamadora, el contexto informa lo que cada llamador realmente pasa por él (por ejemplo, "todos los llamadores pasan un literal de cadena"), de modo que un parámetro de formato/tamaño que siempre es constante no se confunda con controlado por el atacante,
  • el cuerpo descompilado completo de la función llamadora,
  • definiciones de tipos de datos (struct/union/enum) para los tipos referenciados a lo largo de la cadena de llamadas y las variables de los argumentos, para que el modelo conozca los tamaños reales de los buffers/campos y las anchuras enteras,
  • los cuerpos descompilados de las funciones que producen o consumen las variables de los argumentos de la llamada (rastreadas mediante uso/definición HLIL), que es lo que hace posible el razonamiento sobre uso después de liberación / doble liberación y tamaño contaminado,
  • rutas de llamada desde los puntos de entrada / funciones exportadas hasta la llamada,
  • el cuerpo descompilado de cada función a lo largo de esas rutas de llamada (la más cercana a la llamada peligrosa primero), cada una anotada con el sitio de llamada y las condiciones que protegen el siguiente salto,
  • los cuerpos de otras funciones que esas funciones de la ruta llaman (por ejemplo, para MAIN→ABCD→strcpy, también las funciones que MAIN y ABCD llaman en otros lugares), ya que pueden contener las comprobaciones de límites/validación que protegen el valor peligroso (vulnfanatic.includeCallPathSiblings, completado mientras el presupuesto lo permita), y
  • pistas de fuentes contaminadas (funciones de entrada como recv/read/getenv llamadas en la misma función).
  • medium
    high
  • vulnfanatic.skipConstantArgCalls (por defecto desactivado) — salta sitios de llamada de clase de desbordamiento cuyos argumentos son todos constantes en tiempo de compilación.
  • SettingSignificado
    vulnfanatic.apiProviderQué backend LLM llamar: openai (predeterminado), anthropic, google, o azure. Consulte Backends LLM más abajo. Todos los proveedores se alcanzan mediante la biblioteca estándar de Python — no necesita pip install.
    vulnfanatic.apiBaseUrlBase del endpoint para el proveedor seleccionado (consulte la tabla más abajo). Predeterminado http://localhost:8080/v1. Establézcalo al literal TEST para habilitar el modo de prueba (véase más abajo).
    vulnfanatic.apiKeyClave API / token de portador. Puede estar en blanco para servidores locales. Anulado por las variables de entorno VULNFANATIC_API_KEY o OPENAI_API_KEY.
    vulnfanatic.modelRequerido (excepto en modo de prueba). El identificador del modelo (para azure, el nombre de despliegue).
    vulnfanatic.apiModeSolo openai: chat (predeterminado, /chat/completions) vs completions (prompt único aplanado — para modelos base/instruct servidos sin plantilla de chat).
    vulnfanatic.azureApiVersionSolo azure: el parámetro de consulta api-version (predeterminado 2024-10-21).
    ProveedorapiBaseUrlAutenticaciónNotas
    openaisu servidor, ej. http://localhost:8080/v1Authorization: BearerChat/Completions compatible con OpenAI: llama.cpp / ollama / vLLM local, OpenAI, y el endpoint compatible con OpenAI de AWS Bedrock.
    anthropicen blanco → https://api.anthropic.comx-api-key + anthropic-versionMessages API de Claude (POST <base>/v1/messages). No se envía temperature (los modelos Claude actuales lo rechazan).
    googleen blanco → https://generativelanguage.googleapis.comClave API en la URLgenerateContent de Gemini (<base>/v1beta/models/<model>:generateContent).
    azurehttps://<resource>.openai.azure.comCabecera api-keyAzure OpenAI; establezca model en el nombre de despliegue y azureApiVersion en su versión de 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 depuración
    vulnfanatic.sendJsonResponseFormat
    vulnfanatic.tlsVerify
    vulnfanatic.caBundlePath
    CERTIFICATE_VERIFY_FAILED
    vulnfanatic.rulesPhase1Path
    vulnfanatic.rulesPhase2Path
    vulnfanatic.rulesPhase3Path