소프트웨어 개발
Symbolic Execution심볼릭 실행
심볼릭 실행(Symbolic Execution)은 구체적인 입력값 대신 기호(symbol)를 사용하여 프로그램의 모든 실행 경로를 수학적으로 탐색하는 프로그램 분석 기법이다. 1976년 James King이 최초로 제안했으며, 버그 탐지, 테스트 케이스 자동 생성, 보안 취약점 발견에 사용된다.
핵심 아이디어
구체적 값(예: x=5) 대신 기호(예: x=α)를 입력으로 주고 프로그램을 실행한다. 각 분기마다 조건을 기호식으로 기록하고, SMT 솔버가 수집된 조건을 만족하는 구체적 입력값을 계산한다.
구체적 vs 기호적 실행
| 항목 | 구체적 실행 | 기호적 실행 |
|---|---|---|
| 입력 | 특정 값 (x=5) | 기호 (x=α) |
| 탐색 경로 | 단일 경로 | 모든 경로 (이론상) |
| 버그 발견 | 입력 의존적 | 체계적 |
| 확장성 | 높음 | 경로 폭발 문제 |
| 제약 조건 | 없음 | SMT 솔버 필요 |
상태와 경로 조건 (형식적 정의)
심볼릭 실행은 두 가지 상태를 유지한다.
| 기호 | 이름 | 설명 |
|---|---|---|
| σ (Symbolic State) | 기호 상태 | 변수와 기호 표현식 간의 매핑 |
| π (Path Constraint) | 경로 제약 | 해당 경로에 도달하기 위한 조건들의 논리곱 |
코드 예시 — 실행 트리
위 코드의 심볼릭 실행 트리:
KLEE 실습 예제
경로 폭발 문제 (Path Explosion)
분기와 루프가 많을수록 탐색 경로가 기하급수적으로 늘어난다.
완화 전략
| 전략 | 설명 |
|---|---|
| 루프 경계 설정 | 최대 반복 횟수 제한 |
| 경로 병합 | 유사한 경로의 상태를 통합 |
| 휴리스틱 탐색 | 코드 커버리지 최대화 방향으로 우선순위 |
| Concolic Testing | 구체적 실행 + 기호적 실행 혼합 |
| 분산 실행 | 여러 머신에서 병렬 경로 탐색 |
고전적 심볼릭 실행의 한계
1. 비선형 제약 조건
2. 환경 상호작용
파일 시스템, 네트워크, OS 콜 등 외부 환경과의 상호작용은 완전 기호화 어려움.
Concolic Testing (동적 심볼릭 실행)
고전적 심볼릭 실행의 한계를 극복한 현대적 접근법. Concrete + Symbolic의 합성어.
제약 조건 최적화
불필요한 제약 제거 (Slicing)
점진적 풀이 (Incremental Solving)
주요 도구
| 도구 | 연도 | 언어/플랫폼 | 특징 |
|---|---|---|---|
| DART | 2005 | C | 최초의 Concolic Testing, Bell Labs |
| CUTE/jCUTE | 2005 | C/Java | 포인터·동적 자료구조 지원 |
| EXE | 2006 | C | 비트 수준 메모리 모델링, STP 솔버 |
| KLEE | 2008 | C/C++ (LLVM) | EXE 기반, 오픈소스, 높은 커버리지 |
| SAGE | 2008 | x86 바이너리 | Microsoft, Whitebox Fuzzing |
| PEX | 2008 | .NET | Microsoft, 자동 단위 테스트 |
| angr | 2016 | 바이너리 | Python, CTF·리버싱 |
| Manticore | 2017 | EVM/x86 | 스마트 컨트랙트 취약점 |
| Z3 | — | 범용 | Microsoft, SMT 솔버 백엔드 |
메모리 모델링 정확도
| 도구 | 정수 | 포인터 | 배열 | 비고 |
|---|---|---|---|---|
| DART | ✓ | 구체적 값만 | ✗ | 단순 |
| CUTE | ✓ | 등식/부등식 | ✗ | 중간 |
| EXE/KLEE | ✓ | ✓ | ✓ | 최고 정확도 |
Python으로 간단 구현 (Z3 솔버)
역사적 발전
| 연도 | 사건 |
|---|---|
| 1976 | James King — 심볼릭 실행 최초 제안 |
| 2005 | DART, CUTE 등장 — 현대적 Concolic Testing 시작 |
| 2006 | EXE — 비트 수준 메모리 모델 |
| 2008 | KLEE, SAGE, PEX 등장 — 산업 적용 확대 |
| 2009 | KLEE 오픈소스화 |
| 2013 | 30주년 회고 논문 |
| 2016~ | angr, Manticore — 바이너리·블록체인 확장 |
활용 사례
| 분야 | 활용 | 대표 도구 |
|---|---|---|
| 소프트웨어 테스팅 | 자동 테스트 케이스 생성, 코드 커버리지 극대화 | KLEE, PEX |
| 취약점 탐지 | 버퍼 오버플로우, SQL 인젝션, 메모리 손상 | SAGE, EXE |
| 스마트 컨트랙트 | 재진입 공격, 정수 오버플로우 감지 | Manticore, Mythril |
| 리버스 엔지니어링 | 바이너리 분석, CTF 문제 풀이 | angr |
| OS/커널 테스팅 | 시스템 콜 경로 분석, 드라이버 버그 탐지 | S2E |
장단점 요약
장점
- •높은 코드 커버리지 자동 달성
- •깊이 숨겨진 버그 체계적 발견
- •정확한 버그 재현 입력값 생성 (false positive 없음)
- •복잡한 조건 분기 자동 탐색
단점
- •경로 폭발: 분기·루프 증가 시 지수적 복잡도
- •제약 풀이 병목: SMT 솔버 성능이 전체 성능 결정
- •환경 모델링 어려움: 파일 시스템, 네트워크 등 외부 환경
- •부동소수점 정확도: 실수 연산 제약 조건의 불완전 처리
- •동시성 처리: 멀티스레드 비결정성 처리 어려움
관련 개념
- •퍼징 (Fuzzing) — 심볼릭 실행과 결합하는 하이브리드 테스팅
- •정형 검증 (Formal Verification) — 수학적 프로그램 검증
- •SMT 솔버 — 심볼릭 실행의 핵심 백엔드 (Z3, STP)
- •소프트웨어 테스팅 — 심볼릭 실행의 적용 분야
- •스마트 컨트랙트 — Manticore 등으로 취약점 분석
- •동적 프로그래밍 — 경로 탐색 최적화 관련
참고문헌
- •King, J.C. (1976). Symbolic Execution and Program Testing
- •Godefroid, P. et al. (2005). DART: Directed Automated Random Testing
- •Cadar, C. et al. (2008). KLEE: Unassisted and Automatic Generation of High-Coverage Tests
- •Postype @cpuu. 심볼릭 실행이란?
- •Velog @dddd. Symbolic Execution이란
- •Baldoni, R. et al. (2018). A Survey of Symbolic Execution Techniques
