I. 서론
소프트웨어 취약점 탐지는 전체 시스템의 안정성을 확보하기 위한 핵심 과제이다. 그러나 대부분의 소프트웨어는 소스 코드 접근이 불가능하거나 제한적이어서 실행 파일 자체를 대상으로 한 바이너리 분석이 필수적이다. 따라서 소프트웨어의 취약점을 바이너리 수준에서 탐지할 필요성이 커지고 있다.
특히 한정된 자원을 사용하는 임베디드 및 IoT기기의 소프트웨어는 대부분 스트립(stripped) 바이너리 형태로 배포된다. 스트립 바이너리는 함수 및 변수명 등 코드 분석에 유용한 디버깅 정보가 의도적으로 제거되어 있어 내부 구조나 제어 흐름을 파악할 수 있는 핵심 단서가 부족하다. 따라서 기존의 소스 코드 기반 분석 기술을 적용하기 어렵다.
Microsoft는 2006–2018년 취약점의 약 70%가 메모리 안전성 문제라고 보고했다[1]. Chrome 역시 심각한 보안 버그의 약 70%가 메모리 안전성 문제임을 밝혔으며, Use-After-Free의 경우 36.1%에 달한다고 밝혔다[2]. 특히, Double Free[3]와 Use-After-Free[4] 같은 버그 클래스는 시스템의 안정성과 보안에 직접적인 영향을 미치는 대표적인 사례로 Double Free, Use-After-Free에 대해 패턴을 정의하는 연구가 필요하다.
한편, 최근 대규모 언어 모델(Large Language Model, LLM)이 코드의 의미론적 구조를 이해하고 분석하는 데 뛰어난 성능을 보이면서, 이를 보안 취약점 탐지에 활용하려는 연구가 급증하고 있다. 하지만 대부분의 연구가 소스 코드 기반 연구에 집중되어 있고 정보 손실이 많은 스트립 바이너리 분석 연구는 상대적으로 연구가 부족하다. LATTE[5]나 Vul-BinLLM[6]과 같은 연구들이 LLM을 바이너리 분석에 적용하기 시작했지만, 여전히 특정 보안 약점 유형에 국한되어 있다는 문제가 있다.
본 논문에서는 위의 문제를 해결하기 위해 LLM을 활용한 바이너리 동적 메모리 할당과 해제에 대한 보안 약점 탐지 프레임워크를 제안한다. 제안하는 프레임워크는 Ghidra를 이용해 스트립 바이너리를 디컴파일 의사코드로 디컴파일하고, 이후 메모리 해제 함수를 식별하여 이를 기준으로 역방향 슬라이싱을 통해 메모리 할당 함수까지의 데이터 흐름 경로를 추출한다. 추출된 코드에서 메모리 할당 및 해제 지점에 어텐션 마커를 삽입하여 LLM이 분석의 핵심 위치에 집중하도록 유도한다.
기존 LLM 기반 바이너리 분석 연구들은 일반적인 보안 약점 탐지(예: Command Injection, Integer Overflow 등) 및 데이터 흐름 분석에 집중한 것과 달리 본 논문에서는 스트립 바이너리 환경에서 메모리 관리 보안 약점(예: Double Free, Use-After-Free)을 탐지하는 새로운 접근 방법을 제시한다. 본 논문의 기여도를 정리하면 다음과 같다.
⦁ 학습 데이터셋 구축 및 파인튜닝 없이 프롬프트 엔지니어링을 통해 메모리 보안 약점을 탐지할 수 있는 프레임워크. Use-After-Free 취약점 유형에 대해 88.2%의 정확도를 달성하여 실제 메모리 보안 약점을 탐지할 가능성을 입증함.
⦁ 전체 분석 파이프라인 자동화. Python 스크립트를 구현하여 전체 1,996개 샘플을 순차적으로 처리함.
⦁ 새로운 취약점 유형 및 다양한 바이너리 형식으로 확장할 수 있는 프레임워크. 프롬프트 엔지니어링 및 코드 전처리만 필요하므로 새로운 취약점 유형이나 다른 CWE 카테고리로 확장 시 새로운 프롬프트를 재설계할 수 있음. 예를 들어, CWE-476(NULL Pointer Dereference)의 경우 포인터 역참조 지점을 기준점으로, CWE-787(Out-of-bounds Write)의 경우 배열 접근 지점을 기준점으로 설정하는 방식으로 슬라이싱 기준점과 어텐션 마커를 재정의하여 적용할 수 있음.
II. 배경지식 및 관련 연구
2.1 동적 메모리 할당과 관련된 버그 클래스 유행
2.1.1 Double Free(CWE-415)
Double Free는 Dangling Pointer에 대해 한번 더 해제를 시도할 때 발생하는 보안 취약점이다. 이 Double Free의 발생 메커니즘은 아래 Fig. 1.과 같다.

Fig. 1. Double Free vulnerability example
Double Free가 발생하면 힙 메타데이터가 손상되어 다음과 같은 보안 위협이 발생할 수 있다.
⦁ 프로그램 충돌: 손상된 힙 구조로 인한 세그멘테이션 폴트
⦁ 임의 쓰기: 힙 메타데이터 조작을 통한 임의 메모리 쓰기
⦁ 코드 실행: 함수 포인터 덮어쓰기를 통한 제어 흐름 탈취
2.1.2 Use-After-Free(CWE-416)
Use-After-Free는 해제된 메모리 영역을 다시 참조할 때 발생하는 보안 취약점이다. 포인터가 가리키는 메모리가 해제된 후에도 포인터 값은 그대로 유지되어, 이후 해당 포인터를 통한 접근 시 문제가 발생한다(Fig. 2. 참조). Use-After-Free의 위험성은 다음과 같다.

Fig. 2. Use-After-Free vulnerability example
⦁ 정보 유출: 재할당된 메모리의 민감한 데이터 노출
⦁ 코드 실행: 가상 함수 테이블(vtable) 조작을 통한 임의 포인터 참조
2.1.3 실제 공격 사례 분석
앞서 설명한 두 가지 메모리 해제와 관련된 보안 취약점들이 실제 환경에서 어떻게 악용되는지 이해하기 위해, 두 가지 대표적인 사례를 분석한다.
⦁ CVE-2019-11932
CVE-2019-11932는 WhatsApp이 사용하는 android-gif-drawable 라이브러리 v1.2.18 이전 버전에서 발견된 Double Free 취약점으로, 특수 제작된 GIF 파일을 통해 원격 코드 실행(RCE)이 가능했다. 이 취약점은 CVSS 3.1 기준 9.8점(Critical)으로 평가되었으며, 네트워크를 통한 원격 공격이 가능하고 사용자 상호작용만 요구되는 높은 위험도를 가졌다[7].
해당 취약점은 GIF 디코딩 루틴의 DDGifSlurp 함수에서 발생했다. 정상적으로는 모든 프레임이 동일한 크기이므로 할당된 버퍼(rasterBits)를 재사용하지만, 프레임 크기가 다를 경우 reallocarray()를 호출하여 버퍼를 재할당한다. 공격자가 첫 번째 프레임을 정상 크기(예: 40×10)로, 두 번째 프레임을 0×20으로 조작하면, reallocarray(rasterBits, 0)이 호출되어 첫 번째 free()가 발생한다. 세 번째 프레임도 유사하게 조작하면 동일한 포인터가 다시 해제되어 Double Free가 발생한다. 이를 통해 공격자는 힙의 free list를 조작하여 동일한 메모리 영역에 대한 두 개의 포인터를 확보하고, 이를 악용하여 임의 코드 실행에 성공할 수 있었다[8][9].
이 취약점은 WhatsApp for Android 2.19.244 이전 버전에 영향을 미쳤으며, 악의적인 GIF를 메시지로 전송하여 피해자가 WhatsApp 이미지 수신할 때 트리거 되는 방식으로 악용되어, 사용자 상호 작용이 없는 제로 클릭 (0-click)공격에 활용될 수 있다. 이 취약점은 Facebook은 2019년 10월 공식 보안 권고를 통해 이를 공개하고 패치를 배포하였다.
⦁ CVE-2024-1086
CVE-2024-1086은 Linux 커널의 netfilter: nf_tables 컴포넌트에서 발견된 Use-After-Free 취약점으로, CVSS 3.1 기준 7.8점(High)으로 평가되었다[10].
취약점의 핵심 메커니즘은 nft_verdict_init() 함수에서 drop 오류 값으로 양수 값을 허용하는 결함에서 시작된다. NF_DROP이 NF_ACCEPT와 유사한 drop 오류 값을 발생시킬 때, nf_hook_slow() 함수는 Double Free 상황을 일으킨다. 먼저 공격자는 unprivileged user namespace 기능을 통해 nf_tables에 접근하여 이 취약점을 트리거한다. Double Free가 발생하면 공격자는 물리 메모리를 스캔하여 커널 베이스 주소를 찾아 KASLR (Kernel Address Space Layout Randomization)을 우회한다. 이후 modprobe_path 커널 변수에 대한 읽기/쓰기 권한을 획득하여 이를 덮어쓴 후, root 쉘을 획득한다.
이 취약점은 Linux 커널 버전 3.15부터 6.8-rc1까지 광범위하게 영향을 미쳤으며, Debian, Ubuntu, Fedora, Red Hat 등 주요 배포판에 존재했다. 2024년 3월 보안 연구자 Notselwyn이 상세한 분석과 PoC(Proof-of-Concept) 익스플로잇을 공개한 후, 공격자들은 이를 권한 상승 도구로 활용하기 시작했다. 미국 CISA는 랜섬웨어 캠페인에서의 실제 악용 사례를 확인하고, 이 취약점을 Known Exploited Vulnerabilities (KEV) 카탈로그에 추가하였다[11][12].
앞서 분석한 두 사례는 메모리 보안 약점이 실제 환경에서 심각한 위협으로 발전할 수 있음을 보여준다. CVE-2019-11932는 서드파티 라이브러리의 메모리 관리 오류가 모바일 애플리케이션 보안을 위협한 사례이며, CVE-2024-1086은 운영체제 커널의 메모리 취약점이 랜섬웨어 공격에 활용된 사례이다. 특히 후자의 경우, Use-After-Free와 Double Free가 복합적으로 작용하여 KASLR 우회와 권한 상승을 달성하는 정교한 공격 체인을 구성하였다. 이는 메모리 보안 약점의 조기 탐지가 소프트웨어 보안에서 중요함을 시사하며, 본 연구의 필요성을 뒷받침한다.
2.2 바이너리 분석 기술
2.2.1 정적 바이너리 분석의 필요성
소스 코드가 없는 상황에서 보안 약점을 탐지하기 위해서는 바이너리 수준의 분석이 필수적이다. 특히 서드파티 라이브러리, IoT, 임베디드 시스템 및 펌웨어 등은 소스 코드 접근이 불가능한 경우가 많다. 바이너리 분석을 위해서는 기계어를 사람이나 분석 도구가 이해할 수 있는 고수준 표현으로 변환하는 디컴파일 과정이 필요하며, 현재 디컴파일 하기 위해 IDA Pro[13], Ghidra[14], Binary Ninja[15] 등 다양한 도구들이 사용되고 있다. 본 연구에서는 Headless 모드를 통해 대규모 자동화 분석이 가능한 Ghidra를 사용한다.
2.2.2 스트립 바이너리 분석을 위한 Ghidra
Ghidra는 2019년 공개된 오픈소스 리버스 엔지니어링 프레임워크이다. 스트립 바이너리 환경에서 Ghidra로 디컴파일 코드는 다음과 같은 특성을 갖는다. 변수명과 함수명이 주소 기반으로 자동 생성되며(예: FUN_00101234, local_10), 이러한 일관된 패턴은 본 연구에서 free(), malloc() 같은 메모리 관리 함수를 정규표현식으로 탐지하는 데 활용된다.
또한 Ghidra의 DecompInterface API는 각 함수의 디컴파일 의사코드와 함께 호출 관계(caller-callee) 정보를 제공한다. 이를 이용하여 호출 체인 역추적 시 메모리 해제 지점에서 할당 지점까지의 함수 간 데이터 흐름을 추적하는 핵심 기반이 된다. 또한 Headless analyzer를 이용하여 Python 스크립트로 전체 분석 파이프라인을 자동화해서 1,996개 샘플을 순차적으로 처리할 수 있었다.
2.3 LLM 기반 바이너리 보안 관련 연구
최근 대규모 언어 모델(LLM)은 코드의 의미론적 구조를 이해하고 분석하는 데 뛰어난 성능을 보이면서, 이를 보안 약점 탐지에 활용하려는 연구가 급증하고 있다. LLM의 핵심 메커니즘인 self-attention은 입력 시퀀스의 모든 위치 간 관계를 동시에 고려하여 긴 거리의 의존성을 효과적으로 포착할 수 있게 하며[16], 실제로 8k 토큰 이상의 컨텍스트에서 함수 간 의존성을 추적할 수 있음이 실증되었다[17]. 또한 LLM은 추가 학습 없이도 프롬프트를 통해 새로운 작업을 수행하는 In-Context Learning 능력을 보인다[18]. 본 절에서는 LLM을 바이너리 분석에 적용한 대표적인 연구를 검토하고, 본 연구와의 차별점을 명확히 한다.
2.3.1 LATTE: LLM 기반 정적 바이너리 오염 분석
LATTE[5]는 Liu 등이 제안한 최초의 LLM 기반 정적 바이너리 오염 분석(taint analysis) 기법이다. 전통적인 오염 분석은 외부 입력(source)으로 부터 취약점 발생 지점(sink)까지 오염된 데이터의 흐름을 추적하여 취약점을 탐지한다. 하지만, 오염 전파 규칙과 취약점 검사 규칙을 수동으로 정의해야 하는 한계가 있었다. LATTE는 LLM을 활용하여 이러한 규칙 정의를 자동화한다.
LATTE의 핵심은 Dangerous Flow(DF) 기반 분석이다. Ghidra로 디컴파일 바이너리에서 (1) LLM으로 source와 sink를 자동 식별하고, (2) 역방향 데이터 의존성 분석으로 source에서 sink까지의 함수 호출 체인(DF)을 추출한 후, (3) 함수 단위로 분할된 Prompt Sequence를 GPT-4.0에 입력하여 오염 데이터의 흐름을 단계적으로 추적한다. Juliet Test Suite 평가에서 CWE-78(OS Command Injection)에서 96.46%, CWE-134(Controlled Format String)에서 93.88%의 정확도를 달성하였으며, 실제 펌웨어에서 37개의 신규 취약점을 발견하였다.
그러나 LATTE는 taint analysis 특성상 외부 입력으로 인한 취약점(CWE-78, 134, 190 등)에만 적용할 수 있으며, source-sink 데이터 흐름 추적을 핵심 메커니즘으로 사용한다. 반면, 본 논문은 메모리 관리 취약점에 특화된 접근으로, 포인터 상태의 흐름을 추적하여 분석한다는 차이가 있다.
2.3.2 VulBinLLM: 스트립 바이너리 취약점 탐지
VulBinLLM[6]은 Hussain 등이 제안한 스트립 바이너리 환경에 특화된 LLM 기반 취약점 탐지 프레임워크이다. VulBinLLM은 아래 전략을 통해 취약점 탐지를 진행한다. 첫째, 취약점 최적화 디컴파일을 수행한다. RetDec으로 디컴파일 코드에 GPT-4o를 활용하여 (1) 잠재적 취약점에 대한 주석 추가, (2) 코드 구조 단순화, (3) 의미 있는 변수명 복원을 수행하여 LLM이 취약점을 더 명확하게 인식하도록 한다. 둘째, 확장 컨텍스트 윈도우와 메모리 관리 에이전트를 도입한다. 함수 분석 큐(VulBinQ)를 통해 순차적으로 함수를 처리하고, SQL 데이터베이스에 분석 결과를 저장하여 LLM의 컨텍스트 윈도우 제약을 우회한다.
Juliet Test Suite 평가에서 VulBinLLM은 CWE-78에서 96.55%, CWE-134에서 99.74%, CWE-190에서 99.34%의 정확도를 달성하였다. 그러나 합성 데이터셋에서만 평가되었으며, 또한 메모리 안전성 취약점은 탐지 범위에 포함되지 않았다.
III. 방법론
본 논문에서 제안하는 프레임워크는 Fig. 3.과 같이 세 가지 주요 모듈로 구성되며, 역할 분담을 통해 스트립 바이너리에서 메모리 보안 약점을 효율적으로 탐지한다.

Fig. 3. An overview of proposed framework
첫째, 디컴파일 모듈(Decompilation Module)은 스트립 바이너리를 입력받아 Ghidra를 통해 디컴파일 의사코드로 변환하고, 메모리 관리 함수를 탐지한다. 둘째, 보안 약점 후보 추출 모듈(Vulnerability Candidate Extraction Module)은 역방향 슬라이싱을 통해 메모리 할당-해제 경로를 추출하고 어텐션 마커를 삽입한다. 셋째, LLM 기반 검증 모듈(LLM-based Verification Module)은 추출된 코드에 대해 의미론적 추론을 수행하여 최종 보안 약점 여부를 판단한다.
3.1 디컴파일 모듈
디컴파일 모듈은 스트립 바이너리를 분석할 수 있는 형태로 변환하는 전처리 과정을 담당한다. 이 모듈의 출력은 구조화된 함수 정보와 호출 관계 그래프이며, 다음 모듈의 입력으로 사용된다.
3.1.1 Ghidra 기반 디컴파일
바이너리 분석의 첫 단계는 기계어를 분석할 수 있는 고수준 표현으로 변환하는 것이다. 본 연구에서는 NSA에서 개발한 오픈소스 리버스 엔지니어링 프레임워크인 Ghidra를 활용한다. Ghidra는 다양한 프로세서 아키텍처를 지원하며, 특히 headless 모드를 통한 대규모 자동화 분석이 가능하다는 장점이 있다.
디컴파일 과정은 다음과 같이 수행된다. 먼저 컴파일된 ELF 바이너리를 Ghidra 프로젝트에 임포트한 후, analyzeHeadless 명령을 통해 자동 분석을 시작한다. 이때 -import 플래그로 바이너리를 로드하고, -postScript 옵션으로 Python 스크립트(decompile_extract.py)를 실행하여 디컴파일을 자동화한다.
해당 스크립트는 Ghidra의 DecompInterface API를 호출하여 각 함수를 디컴파일 의사코드로 변환하고, 호출 그래프를 추출하여 저장한다. 아래 Fig. 4.를 활용하여 배치 처리를 위해 Headless 모드에서 수행하였다.

Fig. 4. Ghidra Headless Mode Command
디컴파일 스크립트는 DecompInterface API를 활용하여 각 함수를 디컴파일 의사코드로 변환한다. 이 과정에서 다음 정보를 추출한다.
⦁ 함수 엔트리 포인트 (예: 0x00101234)
⦁ 자동 생성된 함수명 (예: FUN_00101234)
⦁ 디컴파일 C 스타일 의사코드
⦁ 지역 변수명 (예: local_10, local_20)
3.1.2 함수 정보 추출
디컴파일 코드에서 의미 있는 함수만을 추출하기 위해 다단계 필터링을 수행한다. 먼저 함수 블록을 "FUNCTION: [함수명] @ [주소]" 패턴으로 분리하고, 각 함수의 코드 영역을 추출한다.
Fig. 5.와 같은 구조화된 출력에서 함수 블록을 정규표현식으로 분리하여 추출한다. 각 함수에 대해서는 다음과 같은 필터링 기준을 적용한다.

Fig. 5. Function block struct
⦁ 코드 길이가 10자 미만인 함수 제외 (의미 없는 stub 함수 제거)
⦁ 시스템 초기화 함수 제외 (_DT_INIT, _DT_FINI, _FINI_0, entry, processEntry 등)
⦁ 자기 자신에 대한 재귀 호출
⦁ C 언어 키워드(if, for, while 등)
최종적으로 각 함수에 대해 함수명, 디컴파일 코드, 호출하는 리스트를 포함하는 FuntionInfo를 생성한다.
3.1.3 메모리 해제 함수 탐지
메모리 보안 약점 탐지를 위한 첫 단계는 보안 약점이 실제로 발생하는 메모리 해제 지점을 찾는 것이다. Double Free와 Use-After-Free는 모두 메모리 해제 이후에 문제가 발생하는 취약점 유형이므로, 다음과 같은 함수 호출을 탐지한다.
⦁ C 언어: free()
⦁ C++ 언어: delete, operator_delete (단일 객체), operator_delete__ (배열)
본 연구에서는 정규표현식 기반 패턴 매칭을 통해 디컴파일 코드에서 이러한 함수 호출을 탐지하고 해당 위치와 라인 번호를 기록한다. 구체적으로 각 함수의 코드를 줄 단위로 스캔하며 free, delete , operator_delete 등의 패턴이 포함된 줄을 식별한다.
탐지된 메모리 해제 지점은 이후 역방향 호출 체인의 시작점으로 사용된다.
3.2 보안 약점 후보 추출 모듈
보안 약점 후보 추출 모듈은 디컴파일 코드에서 메모리 할당-해제와 관련된 경로만을 선택적으로 추출하여, LLM이 분석해야 할 코드의 양을 줄이고 핵심 지점에 집중하도록 한다.
3.2.1 호출 체인 역추적
역방향 슬라이싱은 프로그램 슬라이싱[19]에서 설명하는 방법의 하나로 기준점에서 시작하여 해당 변수에 영향을 미친 모든 이전 문장을 역추적하는 기법이다. 본 연구에서는 프로그램 슬라이싱의 모든 데이터와 제어 의존성을 분석하지 않고, 이를 간소화하여 함수 호출 관계만 역방향으로 추적한다.
1. 기준점 설정: 메모리 해제 함수(free/delete)를 포함하는 함수를 시작점으로 설정
2. 호출자 탐색: 해당 함수를 호출하는 모든 상위 함수를 찾음 (caller 탐색)
3. 재귀적 역추적: 각 호출자에 대해 재귀적으로 상위 호출자를 탐색
4. 깊이 제한: 최대 깊이 30으로 제한하여 무한 재귀 방지
5. 순환 참조 방지: 방문한 함수를 추적하여 순환 참조 차단
이러한 역방향 슬라이싱을 통해 아래의 결과를 도출한다.
⦁ 메모리 해제 지점(deallocation point)에서 시작
⦁ 메모리 할당 지점(allocation point)까지 역추적
⦁ 보안 약점 발생에 관련된 호출 체인만을 추출
3.2.2 메모리 할당 지점 식별
추출된 호출 체인 내에서, 메모리 할당이 발생하는 지점을 식별한다. 이는 역추적의 종료점이 되며, 추적하려는 포인터가 최초로 생성되는 지점이다. 다음과 같은 함수들을 할당 지점으로 탐지한다.
⦁ C 언어: malloc(), calloc(), realloc()
⦁ C++ 언어: new, operator_new (단일 객체), operator_new__ (배열)
메모리 할당-해제 지점을 식별함으로써 해당 메모리의 전체 흐름을 파악할 수 있다. 따라서 Double Free 또는 Use-After-Free 패턴을 탐지하는 기반을 마련한다.
3.2.3 어텐션 마커 삽입
메모리 흐름을 파악하여 핵심 지점을 명확히 할 수 있도록 어텐션 마커를 삽입한다. 호출 체인 역추적으로 식별된 할당-해제 지점에 Fig. 6. 형태의 주석을 추가한다. 이러한 형태는 LLM이 긴 코드에서 핵심 위치를 식별하도록 도움을 주게 된다.

Fig. 6. Annotation markers are inserted to enable the LLM to recognize key points in the memory flow. Within the call chain extracted via the reverse slicing method, allocation point marking inserts annotations at memory allocation points, while criterion point marking inserts annotations at memory deallocation points.
3.3 LLM 기반 보안 약점 탐지
본 프레임워크에서 LLM은 최종 검증 단계에서 사용된다. LLM의 역할은 단순 패턴 매칭이 아닌 정적 분석이 제공한 코드 조각과 컨텍스트 정보를 바탕으로 다음과 같은 추론을 수행한다.
1. 코드 흐름 이해: 함수 간 호출 관계를 추적하고, 메모리 할당부터 해제까지의 흐름을 분석
2. 포인터 동일성 판단: 어텐션 마커로 표시된 여러 free() 호출이 동일한 포인터를 대상으로 하는지 판단. 디컴파일 코드에서 자동 생성된 변수명 간의 관계를 분석하여 실제 메모리 주소 동일성을 추론
3. 보안 약점 메커니즘 추론: 프롬프트에 제시된 분석 단계(예: "free() 호출 횟수 계산 → 포인터 추적 → 판단 규칙 적용")를 따라 코드가 왜 취약한지/안전한지 논리적으로 설명 생성
4. 최종 이진 분류 및 근거 제시: VULNERABLE 또는 SAFE로 분류하고, 구체적인 판단 근거(REASONING)를 자연어로 생성
본 연구에서는 DeepSeek-R1-Distill-Qwen 32B[20] 모델을 활용하여 보안 약점을 탐지한다. 효과적인 분석을 위해 CWE 유형별로 특화된 프롬프트를 설계하였다.
3.3.1 CWE-415 전용 프롬프트
CWE-415는 동일한 포인터를 여러 번 해제하는 취약점 유형이다. 이를 탐지하기 위해 다음과 같은 3단계 분석 프롬프트를 설계하였다.
1. free() 호출 횟수 계산: 전체 함수에서 free() 함수가 호출되는 횟수를 확인하고 각 위치를 표시
2. 포인터 동일성 추적: 동일한 포인터 변수가 여러번 해제되는지 검사. 예: 'free(ptr); ... free(ptr);'
3. 판단 규칙 적용
⦁ 동일 포인터가 2회 이상 해제→VULNERABLE
⦁ 각 포인터가 최대 1회 해제 → SAFE
이후 취약한 case와 안전한 case의 예시 코드를 포함하여 모델이 패턴을 명확히 인식할 수 있도록 유도하였다.
3.3.2 CWE-416 전용 프롬프트
CWE-416은 메모리 해제 후 해당 포인터를 사용하는 취약점 유형이다. 탐지를 위해 다음 4단계 프롬프트를 설계하였다.
1. free() 호출 지점 확인: 메모리가 해제되는 위치를 식별
2. 해제 이후 코드 검사: free() 호출 이후의 코드에서 해당 포인터 사용 여부 확인
3. 포인터 사용 패턴 분석: 다음과 같은 사용 형태를 검사
⦁ 역참조: *ptr, ptr->field
⦁ 함수 인자 전달: function(ptr)
⦁ 배열 접근: ptr[index]
4. 판단 규칙 적용
⦁ 해제 후 포인터 사용 → VULNERABLE
⦁ 해제 후 포인터 미사용 또는 NULL 체크 → SAFE
이후 CWE-415와 같은 방식을 위해 취약한 case와 안전한 case의 예시 코드를 포함하여 프롬프트를 구성하였다.
3.3.3 응답 처리
LLM의 응답을 일관되게 처리하기 위해 다음과 같은 구조화된 출력 형식을 요구한다.
⦁ PREDICTION: [VULNERABLE 또는 SAFE]
⦁ CONFIDENCE: [0.0-1.0 범위의 신뢰도]
⦁ REASONING: [구체적인 분석 근거]
위 형식을 통해 이진 분류 결과를 명확히 도축하고, 모델의 판단 확신도를 정량화할 수 있으며, 판단 근거를 통해 오탐/미탐 원인 분석을 가능하게 하였다.
응답 파싱은 문자열 라인별 매칭을 사용하여 각 필드를 추출한다. 구체적으로 각 라인을 순회하며 'PREDICTION:', 'CONFIDENCE:', 'REASONING:' 접두사로 시작하는 라인을 찾아 해당 값을 추출한다.
IV. 실험 및 평가
4.1 실험 환경
4.1.1 하드웨어 및 소프트웨어
본 실험은 다음과 같은 환경에서 수행되었다.
⦁ GPU: NVIDIA H100 PCIe (80GB VRAM)
⦁ CPU: Intel Xeon Silver 4514Y
⦁ RAM: 512GB DDR5
⦁ CUDA: 12.2
LLM 모델은 Hugging Face Transformers [21] 라이브러리를 통해 DeepSeek-R1-Distill-Qwen-32B를 로드 하였으며, BFloat16 양자화와 SDPA 어텐션 최적화를 적용하여 메모리 효율성을 높였다.
4.1.2 데이터셋
실험에는 NIST Juliet Test Suite v1.3[22]의 CWE-415(Double Free)와 CWE-416(Use-After-Free) 테스트 케이스를 사용하였다. Juliet Test Suite는 NIST에서 제공하는 표준 취약점 유형 벤치마크로, 각 CWE별로 다양한 패턴의 취약 코드(bad)와 정상 코드(good)를 포함한다. 이를 통해 탐지 성능을 정량적으로 측정할 수 있다.
실제 스트립 바이너리 환경을 재현하기 위해, Juliet의 C/C++ 소스 코드를 다음 과정을 거쳐 실험용 바이너리로 변환하였다:
1. 컴파일: gcc 11.4.0으로 컴파일 (최적화 옵션: -O0, 디버깅 심볼 포함)
2. 스트립: strip 명령어로 디버깅 심볼, 함수명, 변수명 제거
3. 디컴파일: Ghidra Headless Analyzer로 ELF 바이너리를 디컴파일 의사코드로 변환
4. 전처리: 역방향 슬라이싱을 통한 할당-해제 지점 식별 및 어텐션 마커 삽입
5. 프롬프트 생성: CWE 유형별 분석 지시문과 함께 LLM 입력용 프롬프트 구성
최종 데이터셋 통계는 다음과 같다. 전체 2,280개 샘플 중 1,996개(87.5%)가 유효한 ground truth를 보유하고 있으며, 나머지 284개(12.5%)는 원본 소스 파일 매칭 실패, 디컴파일 과정 중에 함수 패턴 매칭 실패, 최적화로 인한 함수 호출 변형, Ghidra 디컴파일 실패로 인해 제거되었다.
본 연구에서 사용한 바이너리는 Juliet Test Suite의 소스코드를 컴파일한 후 “strip” 명령어로 심볼을 제거한 형태며, 실제 상용 소프트웨어나 임베디드 펌웨어와 차이가 있을 수 있다.
4.1.3 평가 지표
본 연구에서는 이진 분류 성능을 평가하기 위해 다음 메트릭을 사용한다.
⦁ Accuracy: (TP+TN) / (TP+TN+FP+FN)
⦁ Precision: TP / (TP + FP)
⦁ Recall: TP / (TP + FN)
⦁ F1 Score: 2 × (Precision × Recall ) / (Precision + Recall)
각 CWE 유형별로 confusion matrix를 생성하여 True Positive(TP), False Positive(FP), True Negative(TN), False Negative(FN)을 분석하고, 이를 통해 오탐과 미탐의 원인을 파악한다.
4.2 실험 결과
제안된 방법은 유효한 1,996개 샘플에 대해 평가되어 전체 83.6%의 정확도를 달성했다(Table 1). CWE-416이 CWE-415보다 우수한 성능을 보였으며, 특히 재현율에서 14.9%p 높은 84.8%를 기록했다.
Table 1. Performance Metrics by CWE Type

4.2.1 CWE-415 평가
CWE-415는 높은 정밀도(92.6%)를 보였으나 상대적으로 낮은 재현율(69.9%)을 기록했다.
재현율 69.9%는 221개의 FN이 발생했음을 의미한다. 분류 결과의 reasoning 필드를 분석한 결과, FN의 주요 원인은 다음과 같이 분류되었다.
⦁ 함수 간 분리된 Double Free case
가장 큰 비중을 차지하는 오류 패턴으로, 서로 다른 함수에서 발생하는 free() 호출을 연결하지 못한 경우이다. 역방향 슬라이싱을 통해 관련 함수들의 호출 그래프가 프롬프트에 포함되었음에도 LLM은 함수 경계를 넘어서는 데이터 흐름 추적에 한계를 보였다. 예를 들어, 한 함수에서 'free(__ptr)'을 호출한 후 다른 함수 'FUN_00101394(__ptr)'에 포인터를 전달하고, 해당 함수 내부에서 다시 free가 발생하는 패턴에서, LLM은 "There is 1 free() call in the code"라고 판단하며 dataflow를 완전히 추적하지 못했다.

Fig. 7. CWE-415 Confusion Matrix
⦁ Free 호출 횟수 오판
LLM이 명시적으로 "There is 1 free() call"이라고 판단하여 실제로 존재하는 두 번째 free()를 놓친 경우이다. 주요 원인으로는 조건문 내부에 숨겨진 free(), 매크로로 감싸진 free 호출, 그리고 디컴파일 과정에서 최적화로 인해 일부 free()가 변형된 경우 등이 있었다. 이는 프롬프트에서 "Count all free() calls"를 강조했음에도, 복잡한 제어 흐름에서는 완전한 카운팅이 어려움을 보여준다.
⦁ 복잡한 포인터 패턴
루프 내부의 복잡한 free() 패턴, 동일한 메모리를 가리키는 서로 다른 변수명, 전역 변수를 통한 간접 free 등 구조적으로 복잡한 패턴에서 오류가 발생했다. 특히 'ptr1 = malloc(100); ptr2 = ptr1; free(ptr1); free(ptr2);'와 같이 변수명이 다른 경우, LLM은 서로 다른 메모리로 간주하는 경향을 보였다.
4.2.2 CWE-416 평가
CWE-416은 88.2%의 정확도와 87.5%의 F1 점수로 CWE-415보다 우수한 성능을 보였다. 특히 재현율이 84.8%로 CWE-415의 69.9%보다 14.9%p 높아, 실제 보안 약점의 대부분을 탐지할 수 있었다.
41개(15.2%)의 FN은 CWE-415의 30.1%보다 절반 수준이다. 주요 원인을 분석한 결과, LLM이 free() 이후 포인터 사용이 없다고 잘못 판단한 경우였다. 특히 루프 제어 흐름에서, 첫 번째 반복에서 포인터를 해제하고 두 번째 반복에서 사용하는 패턴을 추적하지 못했다. LLM의 reasoning을 보면 "After the free() call, the pointer is not used again"이라고 판단했으나, 실제로는 루프가 계속되어 freed가 된 포인터가 사용되었다. 또한 Callee 함수에서 포인터를 해제하고 반환한 후, 호출자에서 해당 포인터를 계속 사용하는 패턴을 놓쳤다. caller context를 충분히 고려하지 못한 결과라고 판단된다.

Fig. 8. CWE-416 Confusion Matrix
전반적으로 LLM이 명확한 시퀀스 패턴 인식에서 강점을 보였지만, 전역 상태 추적과 함수 간의 데이터 흐름 분석에서 한계를 보여, 향후 연구에서 호출 그래프 정보를 더 활용하거나, 프로시저 간 최적화(interprocedural optimization) 정보를 모델에게 포함하는 방향으로 개선할 필요가 있어 보인다.
V. 결론
본 논문은 스트립 바이너리 환경에서 메모리 보안 약점을 탐지하는 프레임워크를 제안하였다. 제안한 프레임워크는 Ghidra 도구를 이용하여 디컴파일을 수행하고, 메모리 해제 지점을 기준으로 역방향 호출 체인을 적용하여 메모리 할당부터 해제까지의 전체 흐름을 효과적으로 파악할 수 있도록 하였다. 마지막으로 어텐션 마커를 활용한 프롬프트 엔지니어링을 통해 파인튜닝 없이 LLM의 few-shot 추론 능력만으로 83.6%의 정확도를 달성하였다. 특히 CWE-416인 Use-After-Free에서 88.2%의 높은 정확도를 보여, 제안한 프레임워크를 이용한 메모리 보안 약점 탐지가 가능하다는 것을 입증하였다.
그러나 다음과 같은 한계점도 존재했다. 첫째, 함수 간 분리된 메모리 연산 추적의 한계와 LLM이 함수 간 데이터 흐름(interprocedural dataflow)을 완전히 파악하지 못하는 경우가 있었다. 둘째, 본 연구에서 사용된 데이터셋은 Juliet Test Suite를 컴파일 후 인위적으로 스트립 바이너리로, 실제 상용 소프트웨어나 임베디드 펌웨어와는 구조적 차이가 존재할 수 있다. 실제 제품의 경우 컴파일러 최적화 수준, 난독화 기법, 링킹 방식 등이 다를 수 있으며, 이러한 요인들이 디컴파일 품질과 보안 약점 탐지 성능에 영향을 미칠 수 있다.
향후 연구에서는 호출 그래프와 데이터 의존성 정보를 더 체계적으로 프롬프트에 통합하여 함수 간 분석 정확도를 향상할 것이다. 또한 실제 CVE 데이터베이스의 취약점과 IoT, 임베디드 기기의 바이너리를 대상으로 검증을 확대하여 실용성을 입증할 것이다. 마지막으로 두 종류의 취약점 유형이 아닌 다양한 취약점 유형으로 탐지 범위를 확장할 예정이다.
참고문헌
- Microsoft Security Response Center, "A proactive approach to more secure code," https://www.microsoft.com/en-us/msrc/blog/2019/07/a-proactive-approach-to-more-secure-code/, Access date: Oct. 10, 2025.
- Google Security Blog, "An update on memory safety in Chrome," https://security.googleblog.com/2021/09/an-update-on-memory-safety-in-chrome.html, Access date: Oct. 10, 2025.
- MITRE Common Weakness Enumeration, "CWE-415: Double Free," https://cwe.mitre.org/data/definitions/415.html, Access date: Oct. 10, 2025.
- MITRE Common Weakness Enumeration, "CWE-416: Use-After-Free," https://cwe.mitre.org/data/definitions/416.html, Access date: Oct. 10, 2025.
- P. Liu, X. Wang, Y. Zhang, and Z. Su, "LLM-powered static binary taint analysis," ACM Transactions on Software Engineering and Methodology, vol. 34, no. 3, pp. 1–36, Feb. 2025. https://doi.org/10.1145/3711816
- N. Hussain, M. Ahmed, A. Rahman, and S. Chen, "VulBinLLM: LLM-powered vulnerability detection for stripped binaries," arXiv preprint, arXiv:2505.22010, May 2025.
- National Vulnerability Database (NVD), "CVE-2019-11932 Detail," https://nvd.nist.gov/vuln/detail/CVE-2019-11932, Access date: Nov. 13, 2025.
- Awakened1712 Blog, "How a double-free bug in WhatsApp turns to RCE," https://awakened1712.github.io/hacking/hacking-whatsapp-gif-rce/, Access date: Nov. 13, 2025.
- IBM X-Force Blog, "Reproducing a million-dollar bug: WhatsApp CVE-2019-11932 (with AFL & Frida)," https://www.ibm.com/think/x-force/reproducing-million-dollar-bug-whatsapp-cve-2019-11932-afl-frida, Access date: Nov. 13, 2025.
- National Vulnerability Database (NVD), "CVE-2024-1086 Detail," https://nvd.nist.gov/vuln/detail/CVE-2024-1086, Access date: Nov. 13, 2025.
- pwning.tech, "Flipping Pages: An analysis of a new Linux vulnerability in nf_tables and hardened exploitation techniques," https://pwning.tech/nftables/, Access date: Nov. 18, 2025.
- Cybersecurity and Infrastructure Security Agency (CISA), "Known Exploited Vulnerabilities Catalog: CVE-2024-1086," https://www.cisa.gov/known-exploited-vulnerabilities-catalog/, Access date: Nov. 18, 2025.
- Hex-Rays, "IDA Pro," https://hex-rays.com/ida-pro, Access date: Oct. 10, 2025.
- National Security Agency GitHub, "Ghidra," https://github.com/NationalSecurityAgency/ghidra, Access date: Oct. 10, 2025.
- Binary Ninja, "Binary Ninja," https://binary.ninja/, Access date: Oct. 10, 2025.
- A. Vaswani et al., "Attention is all you need," Advances in Neural Information Processing Systems, vol. 30, pp. 5998–6008, Dec. 2017.
- Y. Assogba and D. Ren, "Evaluating long range dependency handling in code generation models using multi-step key retrieval," arXiv preprint, arXiv:2407.21049, Jul. 2024.
- Q. Dong et al., "A survey on in-context learning," Proceedings of the 2024 Conference on Empirical Methods in Natural Language Processing (EMNLP), pp. 1–23, Nov. 2024.
- M. Weiser, "Program slicing," IEEE Transactions on Software Engineering, vol. SE-10, no. 4, pp. 352–357, Jul. 1984. https://doi.org/10.1109/TSE.1984.5010248
- D. Guo et al., "DeepSeek-R1: Incentivizing reasoning capability in LLMs via reinforcement learning," arXiv preprint, arXiv:2501.12948, Jan. 2025.
- Hugging Face Documentation, "Transformers," https://huggingface.co/docs/transformers/main/index, Access date: Oct. 10, 2025.
- arichardson/juliet-test-suite-c, "Juliet Test Suite for C/C++ (version 1.3)," https://github.com/arichardson/juliettest-suite-c, Access date: May 1, 2023.