
BianryNinja 플러그인: 디컴파일된 바이너리에서 취약점을 식별하며 프로그래매틱 스캔과 LLM 지원을 모두 제공합니다.
LLM 기반 취약점 연구 도구 for Binary Ninja.
VulnFanatic-NG는 사이드바 패널을 추가하여 현재 바이너리를 스캔하고 LLM(기본값은 로컬 호스팅 OpenAI 호환 모델, 또는 Anthropic Claude, Google Gemini, Azure OpenAI — LLM 백엔드 참조)에게 의심스러운 코드가 실제로 취약한지 판단하도록 요청합니다. 주로 Binary Ninja의 디컴파일러 출력(HLIL) 을 사용하며, 필요시 어셈블리로 폴백하고, 확인된 문제만 코드로의 클릭 가능한 참조와 함께 보고합니다.
스캔은 최대 3단계로 진행됩니다(3단계는 옵트인이며 온라인 전용).
rules/phase1_rules.json에 정의된 위험한 함수의 호출 지점을 찾습니다 — strcpy, memcpy, sprintf/포맷 문자열, system, alloca, scanf, 명령어/실행 API, 취약한 RNG, free/delete 계열(use-after-free / double-free), 신뢰할 수 없는 입력을 고정 버퍼로 읽기(recv/read/fread/ReadFile), SQL 인젝션(sqlite3_exec/mysql_query/PQexec), 비활성화된 TLS 인증서 검증(SSL_CTX_set_verify/curl), SSRF, 부적절한 권한 관리(setuid/setresgid), memset/bzero 계열, 공격자 제어 길이와의 비교(memcmp/strncmp → 인증 우회) 등 C/C++, Win32, (최선의) Rust FFI를 대상으로 합니다. 강화된 _chk(FORTIFY) 및 Annex-K _s 변형도 포함됩니다. 제한된 포맷 출력 함수(snprintf 및 변형)는 자체 기본 안전 규칙을 가지므로 올바른 크기 인수가 오버플로로 보고되지 않습니다. 호출 지점은 세 가지 방식으로 찾습니다: 명명된 심볼에 대한 직접 호출; 포워딩 thunk / PLT 스텁을 통한 호출(실제 호출자가 복구되므로 스텁을 통해서만 도달하는 임포트도 놓치지 않음); 그리고 vulnfanatic.scanIndirectCalls가 꺼져 있지 않은 한 — Binary Ninja가 위험한 함수로 해석한 함수 포인터 또는 vtable을 통해 디스패치되는 간접 호출. 각 호출 지점에 대해 프로시저 간, 디컴파일러 중심의 컨텍스트를 구축하며, 토큰 제한(기본값 100k) 이내로 예산이 할당됩니다:
__*_chk 및 경계 검사 *_s 변형은 추가 선행 인수를 취하여 포맷/크기/대상 위치를 변경함,s->buf와 같은 구조체 필드는 s의 포인터 크기가 아닌 필드의 실제 배열 크기로 해석됨; 타입 섹션의 구조체 정의도 필드별 바이트 크기를 전달함,0x40으로 증명되거나 [0, 0xff]로 제한됨), 모델이 크기를 버퍼 용량과 비교할 때 추측 대신 실제 기준으로 사용함,vulnfanatic.includeStackLayout),if/루프/switch 조건),MAIN→ABCD→strcpy의 경우 MAIN 및 ABCD가 다른 곳에서 호출하는 함수도 포함) — 위험한 값을 제어하는 경계/검증 검사를 포함할 수 있으므로(vulnfanatic.includeCallPathSiblings, 예산이 허용하는 동안 채움), 및recv/read/getenv와 같은 입력 함수).해당 컨텍스트와 규칙별 프롬프트가 모델로 전송되며, 모델은 구조화된 판정을 반환합니다. 문제가 아닌 것은 제외됩니다. 프롬프트는 강력한 로컬 코드 모델(예: Qwen2.5-Coder)에 맞게 조정되었으며, 전체 흐름을 분석하고 JSON만 출력하도록 지시합니다.
모델은 재현율을 선호하도록 지시됩니다 — 그럴듯하고 보안 관련 문제를 보고하고, 완전히 증명할 수 없는 것은 버리지 않고 신뢰도(Confidence) 를 통해 불확실성을 표현합니다. 모델은 스크래치패드에 작업 과정을 보여주며, 이는 의존한 코드 조각(입력 소스, 각 가드, 크기/길이, 관련 타입, 싱크)을 그대로 인용하며, 이는 발견 항목에 저장되어 추론을 감사할 수 있습니다.
각 발견 항목은 신뢰도(높음/중간/낮음)를 전달합니다: 높음 = 전체 체인이 컨텍스트에 표시됨; 중간 = 가능성 있음, 하나 또는 두 개의 링크가 추론됨; 낮음 = 수동 검토가 필요한 단서. 이것이 주요 지표입니다(모델의 심각도 추정은 보조 필드). vulnfanatic.minConfidence를 설정하여 임계값 미만의 항목을 제외할 수 있습니다.
기본적으로 VulnFanatic-NG는 재현율(실제 문제 발견)을 선호합니다. 너무 많은 오탐이 발생하면 다음 중 하나로 조정할 수 있습니다:
vulnfanatic.validationPass (기본값 꺼짐) — 두 번째 LLM 패스를 실행하여 각 플래그된 문제를 동일한 컨텍스트에 대해 이중 검증(스크래치패드 조각 확인 및 흐름 재추적)하며, 판정이나 신뢰도를 수정할 수 있습니다. 플래그된 후보에 대해 LLM 호출이 두 배가 됩니다.
vulnfanatic.validatorModel(및 validatorProvider / validatorBaseUrl / validatorApiKey)을 설정하여 두 번째 패스를 다른 모델에서 실행합니다. 독립적인 모델의 두 번째 의견이 훨씬 더 유용합니다 — 블라인드 스팟을 덜 공유하고 첫 번째 판정을 쉽게 도장 찍지 않을 가능성이 높습니다(모델은 자신의 답변을 선호하는 경향이 있음). 좋은 패턴은 캐스케이드: 빠른 모델을 분석자(넓은 재현율)로, 가장 강력한 모델을 검증자로 사용하며, 검증자는 플래그된 후보에 대해서만 실행됩니다. 검증자 모델을 비워두면 분석자 모델로 검증합니다. 검증자는 분석자보다 최소한 동등한 능력을 가져야 합니다 — 더 약한 모델은 주로 오탐만 추가합니다. 공급자/기본 URL/키/모델을 제외한 모든 것은 분석자 연결 설정에서 상속됩니다; 빈 검증자 키는 분석자 키를 재사용합니다; 검증자 엔드포인트에 연결할 수 없으면 첫 번째 판정이 유지됩니다(검증자 중단으로 발견 항목이 손실되지 않음).vulnfanatic.minConfidence (기본값 low) — medium/high로 높이면 더 강력한 발견 항목만 보고합니다.vulnfanatic.skipConstantArgCalls (기본값 꺼짐) — 인수가 모두 컴파일 타임 상수인 오버플로 클래스 호출 지점을 건너뜁니다.속도. 대부분의 호출당 지연 시간은 작성된 추론에 있으므로, vulnfanatic.verdictReasoning 은 모델이 작성하는 양을 제어합니다:
concise (기본값) — 간결한 1~3문장 근거, 코드 인용 없음. full보다 훨씬 빠르며 정확도 손실이 거의 없음; vulnfanatic.maxResponseTokens를 낮출 수도 있음.full — 인용된 조각이 포함된 상세 스크래치패드(가장 감사 가능, 가장 느림).none — 판정만. 가장 빠름; 추론 가능한 백엔드(vulnfanatic.reasoningEffort)와 함께 사용하여 모델의 내부 사고가 작업을 수행하도록 함. 일반 로컬 모델에서 none은 정확도를 잃음(체인 오브 thought 전혀 없음).항상 켜져 있는 정밀도 지원 기능(모델에 정보를 제공하지만 발견 항목을 억제하지 않음):
_s(Annex K) 및 _chk(FORTIFY) 변형과 길이 제한 API를 크기 인수 자체가 잘못되지 않는 한 안전한 것으로 처리합니다.Scan Offline 버튼은 모델 없이 1단계를 실행합니다 — phase1_rules.json의 각 규칙에 있는 offline 블록에 선언된 순수 프로그램적 휴리스틱입니다. 위험한 호출 지점을 플래그하고 명백히 안전한 것은 제거하며, 휴리스틱 신뢰도를 할당합니다:
memcpy/memmove, 상수 문자열의 strcpy, 상수 포맷의 printf, 상수 명령어의 system 등 — 제어 인수가 컴파일 타임 상수이므로 공격자가 제어할 수 없는 호출. "상수"에는 Binary Ninja의 값 집합 분석이 상위에서 고정된 숫자로 고정한 값도 포함되며, 리터럴 인수뿐만이 아닙니다.strlen/크기 비교, if (len < …))가 흐름 어딘가에서 발견됨 — 경로를 따라 호출된 함수를 포함 — 따라서 이미 처리되었을 수 있음. (변수를 비교 없이 언급하기만 하는 분기는 더 이상 카운트되지 않으며, 이로 인해 잘못된 다운그레이드의 원인이 제거됨.)휴리스틱은 규칙에서 작은 선언적 어휘(constant_safe_args, eliminate_if_all_args_constant, format_arg_lookup, length_guard_vars, base_confidence, skip)를 사용하며, Python 조건자에 의해 평가됩니다 — exec할 내장 코드 없음. 대부분의 규칙에는 오프라인 정의(오버플로, 포맷 문자열, 명령어 실행, scanf, 경로 처리, 취약한 RNG, 취약한 숫자 파싱, 권한 변경, 할당 크기 등)가 있습니다. 진정으로 의미 분석이 필요한 두 가지 범주만 오프라인에서 건너뛰고 LLM에 맡깁니다: free/delete 계열(use-after-free / double-free, 포인터 수명 추적 필요) 및 TLS 검증(버그는 SSL_VERIFY_NONE과 같은 특정 상수 값). 오프라인 요약은 플래그/제거/건너뜀(LLM 필요)/실패된 사이트 수를 보고하여 합계가 맞춰집니다. 이는 빠른 트라이지입니다; 실제 판단 — 및 건너뛴 범주에 대해서는 — 전체 LLM 스캔을 실행하십시오.
오프라인 발견 항목은 온라인 스캔이 보낼 동일한 전체 프로시저 간 컨텍스트(플래그된 사이트에 대해서만)를 구축하고 저장하므로, 트라이지 후 온라인 발견 항목과 마찬가지로 파인튜닝 데이터로 내보낼 수 있습니다. 최대 오프라인 속도를 원하면 vulnfanatic.offlineBuildContext로 비활성화하십시오.
바이너리에 실제 심볼/변수 이름이 있는 것으로 보일 때만 실행됩니다. rules/phase2_rules.json에 정의된 보안에 민감한 함수를 찾습니다 — 인증, 암호화(약한 알고리즘 포함), 서명/인증서 검증, 세션/토큰 처리, 접근 제어, 비밀/키 처리, 입력 검증, 비상수 시간 비밀 비교, 안전하지 않은 역직렬화 — 함수 이름 및 참조된 문자열로 일치시킨 후 모델이 감사합니다.
펌웨어 강화 감사: 오류 주입(전압/클록/EM 글리칭) 및 부채널(타이밍/전력) 공격에 대한 것으로, 하드웨어 공격 완화 지침에 기반합니다. 1~2단계(버그를 찾음)와 달리, 3단계는 보안에 중요한 함수에서 누락되거나 위반된 강화 제어를 보고합니다. 예: 기본 실패 분기, 이중 확인된 보안 결정, 루프 후 카운터 검증, 높은 해밍 거리 상태 상수(단순 0/1 대신), 상수 시간 전체 길이 비밀 비교, 무작위 오프셋 비밀 접근/지우기, 암호화 후 검증(anti-DFA), 제어 흐름 무결성 카운터, 사용자 영역 암호화 회피, 원시 키 자료 직접 처리 회피 (rules/phase3_rules.json).
컴파일러 최적화는 소스 수준 보호를 제거할 수 있으므로, 이러한 제어는 컴파일된 바이너리에서 가장 잘 확인됩니다 — 정확히 이것이 확인하는 것입니다. 3단계는 LLM 전용(온라인), 심볼 게이트, 기본적으로 비활성화됨; 새 스캔 탭의 Phase 3 체크박스로 스캔당 활성화할 수 있습니다(오프라인 모드에서는 절대 실행되지 않음).
발견 항목은 표(상태, 신뢰도, 단계, CWE, 함수, 주소, 제목)에 나열되며, 설명, 분석 스크래치패드, 검증 노트를 보여주는 세부 정보 창이 있습니다. 행을 더블 클릭하면 바이너리 뷰가 해당 코드로 이동합니다.