gnosis@kim:~#

gnosis@kim:~ # cat blog/firmagent-ndss-2026-paper-review.md

# [Paper review] FirmAgent — Fuzzing + LLM for automated IoT firmware vulnerability discovery (NDSS 2026)

[Tech note]21 min read[ko]

#Embedded#AI_for_Security#Fuzzing

NDSS 2026 | 칭화대 Network Security Lab
"Leveraging Fuzzing to Assist LLM Agents with IoT Firmware Vulnerability Discovery"


인트로: 왜 이 논문을 골랐나

IoT 기기 수가 2025년 기준 약 180억 대를 넘어서면서, 공격 표면이 폭발적으로 커지고 있다. 문제는 IoT 펌웨어의 특성상 소스코드 없이 바이너리만 존재하는 경우가 대부분이라, 취약점을 찾기가 일반 소프트웨어보다 훨씬 까다롭다는 것이다.

이 분야에는 크게 두 가지 접근이 있다:

  • 정적 분석: 바이너리를 실행하지 않고 코드 패턴으로 취약점을 찾는다. 빠르고 전체 코드를 볼 수 있지만, False Positive가 많고 PoC 생성이 불가능하다.
  • 동적 분석 (Fuzzing): 프로그램을 실제로 실행하면서 크래시를 유발한다. 실제 취약점을 확인할 수 있지만, 복잡한 조건 분기를 통과하기 어려워 False Negative가 많다.

기존 도구 단독으로는 정확도(Precision)와 커버리지(Coverage)를 동시에 달성하기 어렵다는 것이 이 분야의 오래된 딜레마다. FirmAgent는 여기에 LLM을 결합해 이 딜레마를 해결한다.

핵심 아이디어는 의외로 심플하다:

Fuzzing이 런타임 정보를 수집하고, LLM Agent가 그 정보를 기반으로 취약점 경로를 추론한 뒤 PoC를 자동 생성한다.

기존에도 LLM을 보안 분석에 쓰려는 시도가 있었지만, 대부분 LLM을 fuzzing 도중에 호출하는 방식이라 오버헤드가 크고 hallucination도 심했다. FirmAgent는 fuzzing이 끝난 후 LLM이 독립적으로 분석하게 만들어서 두 문제를 동시에 해결한다. 이게 이 논문의 핵심 contribution이다.


논문 기본 정보

항목내용
논문명FirmAgent: Leveraging Fuzzing to Assist LLM Agents with IoT Firmware Vulnerability Discovery
저자칭화대학교 Network Security Lab
학회NDSS 2026 (보안 분야 4대 탑티어 학회, CORE Ranking A*)
출판 시기2025년 2월 아카이브 프리프린트
GitHubhttps://github.com/vul337/FirmAgent
데이터셋14개 실제 IoT 펌웨어 (공개 DB 없음)
비교 대상EmTaint, HermeScan, Greenhouse, Hy-FirmFuzz

NDSS는 IEEE S&P, ACM CCS, USENIX Security와 함께 보안 분야 Big 4 학회다. 여기에 accept된 것 자체가 상당한 수준의 검증을 받았다는 의미.


배경 지식

IoT Firmware 취약점 탐지의 현실

IoT 펌웨어 분석이 일반 소프트웨어 분석보다 어려운 이유가 몇 가지 있다:

  1. Binary-only: 소스코드가 없다. 디컴파일러(Ghidra, IDA) 출력에 의존해야 하는데, 결과가 완벽하지 않다.
  2. 다양한 아키텍처: ARM, MIPS, MIPSEL 등 다양한 CPU 아키텍처를 지원해야 한다.
  3. 하드웨어 의존성: NVRAM, GPIO, 특수 칩셋 등 하드웨어에 의존하는 코드가 많아 에뮬레이션이 어렵다.
  4. 웹 서비스 중심: IoT 기기의 취약점 대부분이 웹 관리 인터페이스(httpd, CGI)에서 발생한다.

알려진 주요 취약점 유형:

  • Command Injection: system(), popen() 등에 사용자 입력이 그대로 전달
  • Buffer Overflow: strcpy(), strcat() 등에서 경계 검사 없이 데이터 복사
  • Format String: printf() 계열 함수에 사용자 입력이 포맷 스트링으로 사용

정적 분석 vs 동적 분석 — 더 자세히

구분정적 분석동적 분석 (Fuzzing)
실행 여부실행 안 함실제 실행
입력바이너리/소스코드무작위/변형된 입력
장점빠름, 전체 코드 커버리지실제 취약점 확인 가능 (Low FP)
단점FP 다수, 코드 의미 이해 불가, PoC 불가FN 많음, 조건 분기 돌파 어려움
대표 도구CodeQL, EmTaint, IDAAFL++, Greenhouse, Hy-FirmFuzz
IoT 특유 문제aliasing, indirect call resolution하드웨어 의존 분기, Emulation 실패

정적 분석의 FP 문제가 심각한 이유: 예를 들어 recv() 와 system() 을 둘 다 import하는 바이너리가 있다고 하자. 정적 분석기는 "입력 함수와 위험 함수가 같은 바이너리에 있다"는 이유만으로 alert를 발생시킨다. 하지만 실제로 recv() 의 데이터가 system()까지 도달하는지는 확인하지 못한다. 이게 심볼 동시 출현(symbol co-occurrence) 기반 탐지의 근본적 한계다.

동적 분석의 FN 문제가 심각한 이유: Fuzzing은 입력을 무작위로 변형해서 넣지만, if (strcmp(input, "SPECIFIC_KEY") == 0) 같은 조건을 무작위로 맞출 확률이 극히 낮다. IoT 펌웨어는 이런 하드웨어 상태/설정값 의존 조건 분기가 많아서 fuzzer가 코드의 깊은 부분까지 도달하지 못하는 경우가 흔하다.

Taint Analysis (오염 분석)

Taint analysis는 신뢰할 수 없는 입력 데이터(taint source)가 위험한 함수(sink)까지 도달하는지 추적하는 기법이다.

[Source]         [Propagation]        [Sink]
recv(buf)  →  sprintf(cmd, buf)  →  system(cmd)
  ↑ 입력             ↑ 전파              ↑ 위험!
  • Source: recv(), getenv(), nvram_get(), fgets() 같은 외부 입력 함수
  • Sink: system(), popen(), execve(), strcpy() 같은 위험 함수
  • Propagation: source의 데이터가 변수 할당, 함수 호출 등을 통해 sink까지 전달되는 경로

전통적 taint analysis의 한계:

  • Aliasing 문제: 포인터가 같은 메모리를 가리키는 경우 추적이 어려움
  • Indirect Call: 함수 포인터를 통한 호출은 정적으로 해석 불가
  • 코드 의미 이해 불가: atoi(input)으로 정수 변환한 뒤 system()에 넣으면 위험한가? 정적 분석기는 이 의미를 모른다

FirmAgent는 이 taint analysis를 LLM이 코드 의미와 함께 수행하게 만든다. LLM은 디컴파일된 코드를 읽고 "이 입력이 정수로 변환되니까 command injection은 불가능하다"는 판단을 내릴 수 있다.

LLM in Security — 기대와 현실

LLM을 보안 분석에 활용하는 연구가 최근 급증하고 있다:

  • 코드 취약점 탐지
  • 악성코드 분석
  • 패킹 보완
  • PoC/Exploit 생성

장점: 코드의 의미를 이해하고, 자연어 수준의 취약점 설명이 가능하다.

치명적 한계 — Hallucination: LLM이 존재하지 않는 취약점을 "확신을 가지고" 보고하는 현상. 선행 연구에서 LLM 단독 사용 시 Precision이 낮다는 결과가 반복적으로 나왔다.

FirmAgent의 핵심 인사이트: Fuzzing이 수집한 실제 실행 정보를 LLM에게 넘겨줘서 hallucination을 억제한다. LLM에게 "이 코드가 취약한지 판단해봐"가 아니라 "fuzzing 결과 이 경로로 입력이 실제로 흘러갔는데, 이 경로가 취약한지 판단해봐"라고 묻는 것이다.


❓ 문제 정의: 기존 접근의 한계와 Research Questions

정적 분석의 한계

  • Taint source를 정적으로 식별 → aliasing + 코드 의미 이해 불가
  • IoT 펌웨어의 다양한 입력 경로 중 실제 도달 가능한 것 특정 불가
  • 결과: False Positive 폭증

동적 분석의 한계

  • 복잡한 조건 분기 통과 어려움 → firmware 코드의 상당 부분 미탐색
  • IoT 특유의 하드웨어 상태/설정값 의존 분기 → Fuzzing 돌파 어려움
  • 결과: False Negative 폭증

이 딜레마를 해결하기 위한 3개의 Research Question:

RQ1: Fuzzing이 수집한 런타임 정보로 LLM의 False Positive를 줄일 수 있는가?

RQ2: LLM이 Fuzzing이 놓친 취약점 경로를 보완할 수 있는가?

RQ3: 두 기술의 결합이 SOTA 단독 도구보다 더 많은 취약점을 더 높은 정밀도로 찾는가?

세 질문 모두 실험으로 검증된다. 특히 RQ1은 ablation study의 Firm-Cut 변형으로 명확하게 답한다.


⚙️ 제안 방법: FirmAgent 파이프라인

FirmAgent의 전체 파이프라인은 크게 두 단계로 나뉜다.

Stage 1: Fuzzing-Driven Information Collection

펌웨어를 QEMU full-system emulation 위에서 실제 실행하면서 정보를 수집하는 단계다.

1-1. Pre-fuzzing Analysis

Fuzzing을 시작하기 전에 타겟을 분석하는 사전 작업:

Service Handler Detection:

  • 펌웨어의 웹 서비스 핸들러 (CGI, SOAP 등)를 자동 식별
  • HTTP 요청을 받아 처리하는 함수들을 fuzzing 대상으로 설정
  • 예: httpd의 /cgi-bin/ 핸들러, mini_httpd의 URL 라우팅 함수

Keyword Dictionary Analysis:

  • HTTP 파라미터명, URL 패턴, 설정 키값 등에서 의미 있는 키워드 수집
  • 이 키워드들을 fuzzing 입력 생성에 활용 (dictionary-based mutation)
  • 예: "password", "cmd", "action=reboot" 같은 문자열

Sink Scope and Distance:

  • 위험 함수(sink)까지의 call graph 거리를 측정
  • 거리가 가까운 경로에 fuzzing 리소스를 집중
  • coverage-guided fuzzing의 방향을 sink 도달로 유도

1-2. Runtime Monitoring

실제 fuzzing 실행 중 세 가지 정보를 동시에 수집:

Dictionary-Based and Distance-Guided Mutation:

  • 수집한 키워드와 sink 거리 정보를 기반으로 입력을 변형
  • 일반적인 coverage-guided mutation보다 목적 지향적
  • 코드 커버리지를 최대화하면서 동시에 sink 도달을 유도

Memory Taint Detection:

  • 실행 중 메모리에서 taint된 데이터의 흐름을 추적
  • Csource (실제로 입력이 흘러들어가는 코드 지점)를 동적으로 식별
  • 정적 분석과 달리 "실제로 이 경로로 데이터가 흘러갔다"는 증거를 수집

Indirect Call Resolution:

  • 함수 포인터, vtable 등을 통한 간접 호출을 동적으로 해석
  • 정적 분석에서는 불가능한 call graph 완성
  • 이 정보가 LLM의 taint path reconstruction에 핵심적

이 과정의 최종 출력물은 두 가지:

  1. Csource: 입력이 실제로 흘러들어가는 코드 지점
  2. Potential Paths: Csource에서 sink까지의 후보 경로

Stage 2: Taint-to-PoC Agent (LLM)

Fuzzing이 수집한 정보를 LLM Agent 2개가 순차적으로 분석하는 단계다.

2-1. Taint Propagation Agent

역할: Taint Source에서 Sink까지 경로를 분석하고 취약점 여부를 판정한다.

입력:

  • Fuzzing이 식별한 Csource (실제 입력이 흘러간 지점)
  • 재구성된 Potential vulnerability path
  • 디컴파일된 바이너리 코드

LLM이 하는 것:

  • 바이너리를 리버싱하여 data flow를 의미론적으로 추적
  • 조건 분기, 함수 호출, 포인터 역참조 등 코드 의미를 고려
  • Source → Sink 도달 가능 여부 판정
  • 취약점 유형 분류 (command injection, buffer overflow 등)

왜 LLM이 기존 taint analysis보다 나은가?

  • 기존: recv() → ??? → system() — 중간 경로를 aliasing 때문에 추적 못함
  • FirmAgent: LLM이 디컴파일 코드를 읽고 "이 변수가 저 함수의 인자로 전달되고, 그 함수가 system()을 호출한다"는 의미적 추론 가능
  • 게다가 Fuzzing이 "실제로 이 경로로 데이터가 흘러갔다"는 증거까지 제공하니 hallucination이 줄어듦

2-2. PoC Generation Agent

역할: 취약점 확인 + PoC Testcase 생성

입력:

  • Taint Propagation Agent의 alert (취약점 후보)
  • Fuzzing이 생성한 testcase (크래시 입력 등)

동작:

  • LLM이 fuzzing testcase를 정제하여 취약점 재현 가능한 PoC 생성
  • 불필요한 노이즈를 제거하고, 핵심 트리거 조건만 남김
  • 생성된 PoC를 에뮬레이션 환경에서 실행해 검증

PoC 성공 = Verified vulnerability. 이게 FirmAgent의 최종 출력이다.

논문 결과: 182개 취약점 중 167개에서 PoC 자동 생성 성공 (91.8%).

이 구조의 핵심: Fuzzing이 LLM의 Hallucination을 억제한다

기존 LLM 단독 분석:

"이 코드를 보니 system() 호출이 있고 recv()도 있으니까 취약할 것이다" → 추측 기반, FP 높음

FirmAgent:

"Fuzzing 결과 이 경로(recv → process_input → handler_cmd → system)로 실제로 데이터가 흘러갔다. 이 경로가 취약한지 판단해봐" → 증거 기반, FP 낮음

이 차이가 precision 91%와 37%(EmTaint)의 차이를 만든다.


실험 결과

데이터셋

  • 14개 실제 IoT 펌웨어
  • 벤더: NETGEAR, D-Link, Tenda, ASUS, TP-Link, TRENDnet, TOTOLINK, Linksys
  • 선정 기준: Full-system Emulation이 가능한 펌웨어
  • 평가 지표: Precision, Recall, CVE 할당 수, Unique Vulnerabilities

기존 도구 비교 (TABLE IV)

도구AlertTP (Vuln)Precision
EmTaint271037.0%
HermeScan2157133.0%
Greenhouse20840.0%
Hy-FirmFuzz1313100%
FirmAgent20018291.0%

수치가 말해준다:

  • FirmAgent: 200개 alert 중 182개가 실제 취약점. precision 91%.
  • EmTaint: 27개 alert 중 10개만 실제 취약점. precision 37%. 정적 분석의 FP 문제가 그대로 드러남.
  • HermeScan: alert는 215개로 가장 많지만 71개만 TP. precision 33%. alert만 많으면 의미 없다.
  • Hy-FirmFuzz: precision 100%이지만 13개밖에 못 찾음. 높은 precision이지만 recall이 처참.
  • Greenhouse: 20개 중 8개. IoT에서 fuzzing 단독의 한계.

FirmAgent만 precision과 recall을 동시에 높은 수준으로 달성했다.

Ablation Study — 각 컴포넌트의 기여

변형AlertTPPrecisionFPR
FirmAgent (full)20018291.0%9.0%
Firm-Directed19417690.7%9.3%
Firm-Indirect (간접 호출 제거)18716990.4%9.6%
Firm-Cut (Fuzzing 정보 제거)23217274.1%25.9%
Firm-Emt (EmTaint 대체)341544.1%55.9%
Firm-Her (HermeScan 대체)1207159.2%40.8%

가장 주목할 결과: Firm-Cut

  • Fuzzing 정보 없이 LLM만으로 분석한 변형
  • Precision이 91% → 74.1%로 급락, FPR은 9% → 25.9%로 폭증
  • "Fuzzing 정보가 LLM의 hallucination을 억제한다"는 핵심 주장의 직접적 증거

Firm-Emt (EmTaint로 source 정보 대체)는 precision 44.1%. 정적 분석이 제공하는 taint source 정보의 품질이 fuzzing 기반보다 크게 떨어진다는 것을 보여준다.

PoC 생성 결과

182개 confirmed 취약점에 대한 PoC 생성 시도:

유형개수비율
E-PoC (완전 자동 성공)16791.8%
H-PoC (수정 필요)158.2%
F-PoC (실패)18-

PoC 자동 생성 성공률 91.8%. 보안 연구자 입장에서 이 수치는 상당히 실용적이다. 취약점을 찾는 것도 중요하지만, 재현 가능한 PoC가 있어야 vendor에 보고하거나 CVE를 받을 수 있다.

Unique Vulnerabilities — FirmAgent만 찾은 것

Venn diagram에서 확인되는 것:

  • FirmAgent가 찾은 182개 중 140개는 다른 도구가 놓친 unique 취약점
  • 이 중 17개가 CVE 할당
  • 나머지 42개는 다른 도구와 겹침

140개를 독점적으로 찾았다는 건, 기존 도구들의 커버리지 한계를 FirmAgent가 실질적으로 메웠다는 뜻이다.


한계 & 의의

논문이 인정한 한계

  1. Full-system Emulation 의존: 에뮬레이션이 안 되는 펌웨어는 분석 불가. 14개라는 데이터셋 규모 자체가 이 제약의 직접적 결과다. 실제 IoT 펌웨어의 상당수는 NVRAM, 특수 하드웨어 의존으로 에뮬레이션이 안 된다.
  2. 평가 규모 14개: 14개 펌웨어에서 91%가 1,000개 규모에서도 유지될지는 미지수다. 통계적 신뢰도를 위해서는 더 큰 데이터셋이 필요하다.
  3. Binary-only 환경: 소스코드 없이 바이너리만 분석하므로 정보 손실이 불가피하다. 디컴파일러 품질에 따라 결과가 달라질 수 있다.
  4. LLM Hallucination 완전 해결은 아님: 91% precision은 인상적이지만, 여전히 9%의 FP가 존재한다. LLM의 본질적 한계.
  5. 분석 시간 오버헤드: Fuzzing + LLM 두 단계 모두 시간이 소요된다. 실시간 탐지에는 부적합.

의의

  1. Fuzzing × LLM 결합의 구체적 방법론 제시: "둘을 합치면 좋겠다"는 아이디어는 많았지만, 어떻게 합칠지의 구체적 아키텍처를 제시하고 검증한 것이 contribution.
  2. Ablation으로 각 컴포넌트 기여도 입증: 특히 Firm-Cut 실험이 "왜 fuzzing 정보가 필요한가"를 깔끔하게 답한다.
  3. End-to-end PoC 자동화: 취약점 탐지에서 끝나지 않고 PoC 생성까지 연결한 것은 실무적 가치가 크다.
  4. 17개 CVE 할당: 실제 영향력 있는 취약점을 찾았다는 실증.

SCOUT 프로젝트와의 비교

내가 개발하고 있는 SCOUT 프로젝트와 비교해보면 접근 방식이 꽤 다르다.

항목FirmAgentSCOUT
핵심 접근Dynamic-first (Fuzzing → LLM)Static-first (Evidence chain → Dynamic promotion)
Precision91% (14개 대상, confirmed)측정 중 (1,123개 대상)
규모14개 펌웨어1,123개 펌웨어
파이프라인2-stage (Fuzzing → LLM Agent)42-stage sequential pipeline
LLM 역할Taint reasoning + PoC 생성의 핵심FP 검증 + 분류의 보조
에뮬레이션필수 전제선택적 (정적 분석이 기본)
CVE 탐지PoC 기반 confirmedNVD 매칭 + 시그니처 기반
산출물Alert + PoCSARIF, CycloneDX VEX, Evidence chain
전제 조건Full-system Emulation 가능한 펌웨어Firmware blob만 있으면 됨

접근 방식의 근본적 차이

FirmAgent: "적은 수를 깊게" — 에뮬레이션 가능한 펌웨어만 대상으로 하지만, fuzzing + LLM으로 높은 precision과 PoC까지 도달한다.

SCOUT: "많은 수를 넓게" — 에뮬레이션 없이도 분석 가능하므로 1,100개+ 펌웨어를 대상으로 하지만, precision은 아직 FirmAgent 수준에 못 미친다.

상호 보완 가능성

두 접근은 사실 경쟁이 아니라 상호 보완적이다.

  1. SCOUT의 정적 파이프라인으로 대규모 스크리닝 → 유의미한 후보만 추출
  2. FirmAgent 방식의 fuzzing + LLM taint reasoning으로 후보를 깊게 검증
  3. PoC 자동 생성으로 confirmed vulnerability로 승격

이렇게 하면 SCOUT의 넓은 커버리지 + FirmAgent의 깊은 검증을 모두 가져갈 수 있다. 실제로 SCOUT v2.2.0에서 Ghidra 디컴파일 결과를 taint analysis에 연결하는 작업을 진행 중인데, FirmAgent의 Taint Propagation Agent 구조가 좋은 참고가 된다.

SCOUT가 FirmAgent에서 배울 점

  1. Fuzzing 정보를 LLM 컨텍스트로 활용: SCOUT의 fp_verification이 "코드 없이" LLM에게 판정을 시키는 문제를 FirmAgent 방식으로 해결할 수 있다.
  2. PoC 자동 생성 파이프라인: SCOUT에도 poc_refinement 스테이지가 있지만, FirmAgent처럼 fuzzing testcase를 seed로 활용하는 구조가 더 효과적일 수 있다.
  3. Ablation study 설계: 논문급 검증을 위해 각 컴포넌트의 기여를 분리해서 측정하는 방법론.

✅ 정리

FirmAgent는 "Fuzzing이 LLM의 hallucination을 억제한다"는 단순하지만 강력한 아이디어를 체계적으로 구현하고 검증한 논문이다.

핵심 수치
Precision91.0%
TP (Confirmed Vuln)182 / 200
PoC 자동 성공률91.8%
CVE 할당17개
Unique (다른 도구 미탐지)140개
FPR9.0%

가장 인상 깊은 것: Firm-Cut ablation에서 fuzzing 정보를 제거하면 precision이 91% → 74%로 떨어진다는 결과. LLM을 잘 쓰려면 "좋은 컨텍스트를 주는 것"이 핵심이라는 교훈을 정량적으로 보여준다.

아쉬운 것: 14개 펌웨어라는 규모. 이 규모에서 91%가 수백 개 규모에서도 유지될지는 후속 연구가 필요하다. 에뮬레이션 전제도 현실적 제약.

내가 SCOUT를 발전시키면서 가장 많이 참고할 포인트는 "LLM에게 어떤 컨텍스트를 줘야 hallucination이 줄어드는가"에 대한 이 논문의 답 — fuzzing이 수집한 실제 런타임 정보 — 이다.


참고 자료


이 글은 세종대학교 CYAI Lab 세미나에서 발표한 내용을 블로그용으로 재구성한 것입니다.