단순히 잘못되었거나 예상치 못하거나 임의적일 수 있는 데이터를 프로그램에 입력으로 제공하는 퍼징은 대규모 시스템에서 버그를 찾을 수 있는 매우 효과적인 방식이며 소프트웨어 개발 수명 주기의 중요한 부분이기도 합니다.
Android의 빌드 시스템은 LLVM 컴파일러 인프라 프로젝트 프로젝트의 libFuzzer를 포함하는 방식으로 퍼징을 지원합니다. 테스트 LibFuzzer는 테스트 아래의 기능과 연결되어 있으며, 퍼징 세션 도중에 발생하는 모든 입력 선택, 변형 및 충돌 보고를 처리합니다. LLVM의 새니타이저는 메모리 손상 감지 및 코드 범위 측정항목을 돕는 데 사용됩니다.
이 도움말은 Android의 libFuzzer를 소개하고 계측화된 빌드를 수행하는 방법에 대해 설명하며, fuzzer를 쓰고 실행하고 맞춤설정하는 내용까지 담고 있습니다.
설정 및 빌드
기기에서 제대로 작동하는 이미지를 실행하려면 공장 출고 시 이미지를 다운로드하고 기기를 플래시하면 됩니다. 또는 AOSP 소스 코드를 다운로드하고 아래의 설정 및 빌드 예시를 따를 수 있습니다.
도움말: 자세한 설정 정보는 다운로드 및 빌드 섹션을 참조하세요. 안내에 따라 빌드 환경을 설정하고 소스를 다운로드하고 Android를 빌드하세요(명령어 생성까지).
설정 예시
이 예시에서는 타겟 기기가 Pixel (taimen)이고 이미 USB 디버깅 (aosp_taimen-userdebug)에 대한 준비를 마쳤다고 가정합니다. 드라이버 바이너리에서 다른 Pixel 바이너리를 다운로드할 수 있습니다.
Android의 libFuzzer를 사용하여 포괄적인 fuzzer를 작성하는 과정을 보여주려면 다음과 같은 취약한 코드를 테스트 사례로 사용하세요. 이는 fuzzer를 테스트하여 모든 부분이 올바르게 작동하는지 확인하고 충돌 데이터가 어떤 모습인지를 보여줄 수 있도록 도와줍니다.
Fuzz 대상은 빌드 파일 및 fuzz 타겟 소스 코드라는 두 파일로 구성됩니다. 파일을 추가하려는 라이브러리 옆의 위치에 파일을 만듭니다. fuzzer에 퍼징의 역할을 설명하는 이름을 지정하세요.
libFuzzer를 사용하여 퍼즈 타겟을 작성합니다. 퍼즈 타겟은 지정된 크기의 데이터 blob를 취하여 퍼징하려는 함수에 전달하는 함수입니다. 다음은 취약한 테스트 함수를 위한 기본 fuzzer입니다.
#include <stddef.h>
#include <stdint.h>
extern "C" int LLVMFuzzerTestOneInput(const char *data, size_t size) {
// ...
// Use the data to call the library you are fuzzing.
// ...
return FuzzMe(data, size);
}
Android의 빌드 시스템에 fuzzer 바이너리를 생성하도록 지시합니다. fuzzer를 빌드하려면 이 코드를 Android.bp 파일에 추가합니다.
cc_fuzz {
name: "fuzz_me_fuzzer",
srcs: [
"fuzz_me_fuzzer.cpp",
],
// If the fuzzer has a dependent library, uncomment the following section and
// include it.
// static_libs: [
// "libfoo", // Dependent library
// ],
//
// The advanced features below allow you to package your corpus and
// dictionary files during building. You can find more information about
// these features at:
// - Corpus: https://llvm.org/docs/LibFuzzer.html#corpus
// - Dictionaries: https://llvm.org/docs/LibFuzzer.html#dictionaries
// These features are not required for fuzzing, but are highly recommended
// to gain extra coverage.
// To include a corpus folder, uncomment the following line.
// corpus: ["corpus/*"],
// To include a dictionary, uncomment the following line.
// dictionary: "fuzz_me_fuzzer.dict",
}
fuzzer를 타겟에서 실행하기 위해 만들려면 (기기):
SANITIZE_TARGET=hwaddress m fuzz_me_fuzzer
호스트에서 fuzzer를 실행하기 위해 fuzzer를 만들려면 다음 안내를 따르세요.
SANITIZE_HOST=address m fuzz_me_fuzzer
편의를 위해 fuzz 대상의 경로와 바이너리의 이름을 포함하는 일부 셸 변수를 정의합니다 (앞에서 작성한 빌드 파일에서).
export FUZZER_NAME=your_fuzz_target
이러한 단계를 수행하면 fuzzer가 빌드됩니다. fuzzer의 기본 위치(이 예시의 경우 Pixel 빌드)는 입니다.