Rust 퍼징은 LLVM의 libFuzzer 퍼징 엔진에 대한 바인딩을 제공하는 libfuzzer-sys
크레이트를 통해 지원됩니다. 자세한 내용은 libfuzzer-sys 저장소 및 LLVM libFuzzer 프로젝트 페이지 를 참조하십시오.
rust_fuzz
모듈은 실행될 때 퍼지를 시작하는 fuzzer 바이너리를 생성합니다( cc_fuzz
모듈과 유사). fuzzer는 libFuzzer
퍼징 엔진을 활용하므로 퍼징을 제어하기 위해 여러 인수를 사용할 수 있습니다. 이것들은 libFuzzer 문서 에 열거되어 있습니다.
rust_fuzz
모듈은 rust_binary
모듈의 확장이며 동일한 속성과 고려 사항을 공유합니다. 또한 cc_fuzz
모듈과 동일한 속성과 기능을 많이 구현합니다.
기본적인 Rust fuzzer 작성하기
다음 코드를 사용하여 Android.bp
빌드 파일에서 fuzz 모듈을 정의할 수 있습니다.
rust_fuzz {
name: "example_rust_fuzzer",
srcs: ["fuzzer.rs"],
// Config for running the target on fuzzing infrastructure can be set under
// fuzz_config. This shares the same properties as cc_fuzz's fuzz_config.
fuzz_config: {
fuzz_on_haiku_device: true,
fuzz_on_haiku_host: false,
},
// Path to a corpus of sample inputs, optional. See https://llvm.org/docs/LibFuzzer.html#corpus
corpus: ["testdata/*"],
// Path to a dictionary of sample byte sequences, optional. See https://llvm.org/docs/LibFuzzer.html#dictionaries
dictionary: "example_rust_fuzzer.dict",
}
fuzzer.rs
파일에는 간단한 fuzzer가 포함되어 있습니다.
fn heap_oob() {
let xs = vec![0, 1, 2, 3];
let val = unsafe { *xs.as_ptr().offset(4) };
println!("Out-of-bounds heap value: {}", val);
}
fuzz_target!(|data: &[u8]| {
let magic_number = 327;
if data.len() == magic_number {
heap_oob();
}
});
Here fuzz_target!(|data: &[u8]| { /* fuzz using data here */ });
libFuzzer
엔진에 의해 호출되는 fuzz-target 진입점을 정의합니다. data
인수는 libFuzzer
엔진에서 제공하는 바이트 시퀀스로 대상 기능을 퍼지하기 위한 입력으로 조작됩니다.
이 예제 fuzzer에서는 heap_oob
함수를 호출할지 여부를 결정하기 위해 데이터 길이만 확인되며, 호출하면 범위를 벗어난 읽기가 발생합니다. libFuzzer
는 Coverage-guided fuzzer이므로 처음 326B 데이터가 새로운 실행 경로를 생성하지 않는다고 판단하므로 문제가 있는 길이로 빠르게 수렴합니다.
트리 내 tools/security/fuzzing/example_rust_fuzzer/ 에서 이 예제를 찾습니다. 트리 내에서 다른 fuzzer( rustlib
종속성을 퍼지하는)의 약간 더 복잡한 예를 보려면 legacy_blob_fuzzer 를 참조하세요.
구조 인식 Rust fuzzers를 작성하는 방법에 대한 지침은 Rust Fuzz 프로젝트의 공식 문서인 Rust Fuzz 책 을 참조하세요.