Snapchange - KVM으로 스냅샷 기반 퍼징 치트시트
Snapchange (AWS)는 스냅샷 기반 퍼징을 위한 Rust 프레임워크입니다. 기존 퍼저는 각 입력에 대해 대상을 재시작하는데, 흥미로운 코드가 비용이 큰 설정 뒤의 깊은 곳에 있을 때 매우 느립니다 — 네트워크 핸드셰이크, 로그인, 파싱된 설정, 로드된 데이터베이스. Snapchange는 대신 메모리 스냅샷을 취합니다 — 정확히 관심 있는 순간의 대상 — 그리고 KVM을 사용하여 그 상태에서 복원하고 변경하여 매우 높은 반복 속도를 달성하며 기존 퍼징이 도달할 수 없는 코드에 대해 완전히 달성합니다.
스냅샷 퍼징은 KVM과 root가 필요합니다. 격리된 환경에서 실행합니다.
요구사항
| 요구사항 | 참고 |
|---|
| KVM 포함 Linux | /dev/kvm 접근 가능 |
| Rust 도구 체인 | Snapchange는 Rust 라이브러리 |
| QEMU | 스냅샷을 취하는 데 사용 |
| Root | KVM 및 메모리 접근용 |
모델
| 단계 | 발생 |
|---|
| 1. 스냅샷 | 관심 순간까지 QEMU에서 대상 실행, 메모리 + 레지스터 덤프 |
| 2. 하네스 | 입력이 가는 곳과 언제 중지할지 설명하는 Rust 퍼저 작성 |
| 3. 퍼징 | Snapchange는 반복당 스냅샷을 복원하고 입력을 변경 |
| 4. 심사 | 충돌은 정확한 레지스터/메모리 상태로 기록됨 |
중요한 통찰: 모든 설정 비용이 한 번 지급됩니다, 스냅샷에서. 이후의 모든 반복은 마이크로초 내에 그 상태에서 시작합니다.
스냅샷 가져오기
# 개념적: QEMU 아래에서 대상을 실행하고, 관심 함수에 중단,
# 그 후 물리적 메모리 및 레지스터 상태 덤프
./snapchange/qemu_snapshot/take_snapshot.sh --target ./my-server
| 아티팩트 | 포함 |
|---|
fuzzvm.physmem | 전체 게스트 물리적 메모리 |
fuzzvm.qemuregs | CPU 레지스터 상태 |
*.symbols | 커버리지/중단점을 위한 심볼 테이블 |
vmlinux / 바이너리 | 기호화용 |
퍼저 작성
// 개념적 모양 — Snapchange 예제에서 완전한 코드 참조
impl Fuzzer for MyFuzzer {
type Input = Vec<u8>;
const START_ADDRESS: u64 = 0x555555555000;
const MAX_INPUT_LENGTH: usize = 1024;
fn set_input(&mut self, input: &Self::Input, fuzzvm: &mut FuzzVm<Self>) -> Result<()> {
// 대상이 읽는 게스트 메모리의 변경된 입력 작성
fuzzvm.write_bytes_dirty(VirtAddr(BUFFER_ADDR), CR3, input)?;
Ok(())
}
fn reset_breakpoints(&self) -> Option<&[AddressLookup]> { /* 정지 조건 */ }
fn crash_breakpoints(&self) -> Option<&[AddressLookup]> { /* 충돌 사이트 */ }
}
| 요소 | 목적 |
|---|
START_ADDRESS | 각 반복이 실행을 재개할 위치 |
set_input | 퍼즈 입력을 게스트 메모리에 주입 |
reset_breakpoints | 반복이 정상적으로 끝나는 위치 |
crash_breakpoints | 충돌을 나타내는 주소 (예. panic, abort) |
실행
| 명령어 | 설명 |
|---|
cargo run -r -- fuzz -c 8 | 8개 코어로 퍼징 |
cargo run -r -- project translate | 기호화/스냅샷 검사 |
cargo run -r -- coverage | 코퍼스에서 커버리지 생성 |
cargo run -r -- trace <input> | 단일 단계 입력 추적 |
cargo run -r -- minimize <input> | 충돌 입력 축소 |
스냅샷 퍼징이 여기서 승리하는 이유
| 대상 특성 | 기존 퍼징 | Snapchange |
|---|
| 비용이 큰 시작 | 모든 반복 지급 | 한 번 지급 |
| 인증/핸드셰이크 필요 | 도달하기 어려움 | 스냅샷 지나침 |
| 상태 저장 프로토콜 | 어려움 | 세션 중간 스냅샷 |
| 커널/하이퍼바이저 코드 | 매우 어려움 | 자연스러운 적합 |
커버리지 및 심사
| 기능 | 참고 |
|---|
| 중단점 커버리지 | 기본 블록의 중단점을 통한 커버리지 |
| 충돌 중복 제거 | 결함 주소/상태로 그룹화 |
| 단일 단계 추적 | 주어진 입력에 대한 전체 명령 추적 |
| 메모리 검사 | 충돌 시 게스트 메모리 읽기 |
Snapchange vs 다른 퍼저
| 측면 | Snapchange | AFL++ | LibAFL (Nyx) | syzkaller |
|---|
| 실행 | KVM 스냅샷 복원 | 프로세스 포크 | 스냅샷 (Nyx) | VM + 시스콜 |
| 설정 비용 | 한 번 지급 | 매 반복 | 한 번 | VM당 |
| 대상 | VM 스냅샷의 모든 것 | 사용자 공간 바이너리 | 설정 가능 | OS 커널 |
| 노력 | 높음 (Rust 퍼저 작성) | 낮음 | 높음 | 중간 |
LibAFL (스냅샷 백엔드도 제공) 및 커널 시스콜 퍼징을 위한 syzkaller와 비교합니다.
리소스