Home LLM4Decompile: Decompiling Binary Code with Large Language Models
Post
Cancel

LLM4Decompile: Decompiling Binary Code with Large Language Models

바이너리를 C 소스 코드로 복원하는 디컴파일(decompile) 문제에 LLM을 적용.
End2end-Decompile(바이너리→어셈→C 직접 복원)과 Refined-Decompile(Ghidra 결과를 LLM으로 정제) 두 축.
Decompile-Eval: 토큰 유사도 대신 재컴파일 가능성(syntax) + 재실행 가능성(semantics)으로 평가.
대규모 데이터(최적화 단계 O0~O3 포함)·중복 제거(LSH)·2단계 학습으로 성능 향상.
일부 벤치마크에서 기존 도구나 GPT-4o 대비 재실행률 2배+ 개선.


1) 배경과 문제 정의

전통 도구(예: Ghidra/IDA Pro)는 CFG 패턴과 규칙 기반 복원을 수행하지만, 최적화된 바이너리에서는

  • 변수명/고수준 구조(루프/조건) 소실,
  • 포인터 연산·goto 등 저수준 표현으로 치환,
  • 결과 코드 가독성/재실행성 미흡
    이라는 한계를 자주 보입니다.

Pipeline

LLM4Decompile은 LLM을 디컴파일 전용으로 파인튜닝하여, 사람 친화적인 소스 형태로의 복원을 목표로 합니다.


2) 접근 개요: Refined vs End2end

  • Refined-Decompile: Ghidra가 생성한 의사코드를 LLM이 정제(가독성↑, syntax 오류 수정)
  • End2end-Decompile: objdump로 얻은 어셈블리에서 곧장 C 코드를 생성

본 연구는 두 경로 모두를 강화:

  • LLM4Decompile-End: 대규모/다양한 학습데이터, 데이터 클린징, 2-Stage 학습
  • LLM4Decompile-Ref: Ghidra의 비실행/실행 바이너리 중 비실행 오브젝트를 활용해 대량 정제 데이터를 효율 수집, 최종 정제 성능↑

llm_end llm_ref


3) 학습 데이터 & 전처리

3.1 asm—source 페어 구축

  • 대규모 공개 C 함수 집합에서 소스→(GCC O0/O1/O2/O3)→오브젝트/실행파일→objdump→ASM 생성
  • ASM–소스 페어를 만들고, 프롬프트에 최적화 단계 힌트를 삽입:
1
2
3
This is the assembly code with [O{0|1|2|3}] optimization:
[ASM]
What is the source code?

3.2 데이터 품질 향상

  • MinHash + LSH를 이용한 중복 제거
  • 극단적으로 짧은 샘플 제외(예: < 10 토큰)

3.3 2-Stage 학습

  • Stage 1 (Compilable/비실행): 링크 전 오브젝트(외부 심볼 바인딩 없음)로 대량 학습 → 바이너리 패턴 폭넓게 습득
  • Stage 2 (Executable/실행): 실제 링크된 실행 파일 기반으로 세부 실용성 보정

4) 학습 목적 함수

본 문제를 기계 번역 시나리오로 보고, 입력(ASM)출력(C 코드)의 조건부 생성으로 최적화합니다.

4.1 Next-Token Prediction (NTP)

표준 언어모델 목적(자연어/코드 공통)으로, 전체 시퀀스의 다음 토큰 확률을 최대화:

\[\mathcal{L}_{\text{NTP}} = - \sum_{t=1}^{T} \log p_\theta\big(x_t \mid x_{<t}\big)\]
  • 입력(ASM)과 출력(C) 전체 토큰에 대해 손실을 계산
  • 단, 디컴파일에서는 출력 시퀀스(소스) 복원이 핵심이므로, 아래의 S2S 목적이 더 직접적

4.2 Sequence-to-Sequence (S2S)

입력 시퀀스(ASM)가 주어졌을 때 출력(C 코드) 부분 토큰만에 대해 음의 로그우도를 최소화:

\[\mathcal{L}_{\text{S2S}} = -\sum_{i}\log P_\theta\big(x_i,\dots,x_j \,\big|\, x_1,\dots,x_{i-1}\big)\]
  • 출력 토큰 범위 $x_i\ldots x_j$에 대해서만 손실 집계
  • 실험적으로 S2S $\ge$ NTP 또는 S2S $+$ NTP 조합이 유리한 경향

5) Refined-Decompile 세부

  • Ghidra 결과는 논리 구조 보존 측면에서 유용하나, 가독성/구문 오류가 잦음
  • 효율적 데이터 수집: 실행 파일은 디컴파일에 고비용비실행 오브젝트로 대체 시 속도 ~10×
  • 필터링: 지나치게 긴 의사코드는 모델 한계를 초과 → 길이 컷 적용
  • 결과: End2end 대비 정제 단계에서 상한 성능이 더 높게 관측(추가 향상)

6) 평가: Decompile-Eval

6.1 왜 BLEU/Edit-Sim이 부족한가?

  • 변수/함수명 변경은 의미 보존이나 토큰 유사도는 크게 변동
  • 반대로 한 줄 논리 오류는 의미 붕괴지만 n-gram 점수는 높게 나올 수 있음

6.2 프로토콜(파이프라인)

1) C 소스 → 2) GCC 컴파일 → 3) objdump로 ASM →
4) (LLM) 디컴파일로 C 복원 → 5) 재컴파일(Re-compilability) → 6) 테스트(Re-executability)

  • Re-compilability: 복원 코드가 컴파일 성공(syntax 정합성)
  • Re-executability: 준비된 assertion 테스트 통과(semantic 보존)

7) 주요 결과

7.1 End2end

모델 HumanEval(Avg) ExeBench(Avg)
DeepSeek-Coder (base, 6.7B/33B) ~0 ~0
GPT-4o ~16 ~3.8
LLM4Decompile-End-1.3B ~27.3 ~14.5
LLM4Decompile-End-6.7B ~45.4 ~18.0
LLM4Decompile-End-33B ~31.5 ~15.4

최적화 단계가 O0 → O3로 갈수록 난이도가 높아지므로, 모든 모델에서 성능 하락.
6.7B가 33B보다 좋은 구간도 존재(학습 토큰/스케줄 차이).

7.2 유사도 지표

모델 BLEU(Avg) EditSim(Avg)
DeepSeek-Coder-33B 0.034 0.116
LLM4Decompile-1B 0.493 0.595
LLM4Decompile-6B 0.819 0.850
LLM4Decompile-33B 0.755 0.807

주의: BLEU/ES는 의미를 온전히 반영하지 못하므로 참고 지표로만 사용.


8) 난점: 코드 난독화(Obfuscation)

일반적인 상용 난독화(예: O-LLVM 변형 등)에서는 Ghidra/LLM4Decompile 모두 취약.
무단 역공학 위험 우려 대비 측면에서 악용 리스크는 제한적으로 관찰.

obfuscation


발표 자료

  • 자세한 내용은 논문이나 아래 발표 자료로 확인 가능합니다.

Presentation Slides

This post is licensed under CC BY 4.0 by the author.