
TriforceAFL을 사용하는 linux 시스템 콜 퍼저
신규: TriforceAFL 및 TLSF를 사용해보고 싶은 분들을 위해 Richard Johnson이 두 가지를 모두 설치하는 Dockerfile을 만들었습니다(심지어 Linux 커널도 빌드해 줍니다). 여기에서 사용할 수 있습니다: https://hub.docker.com/r/moflow/afl-triforce/tags/.
이것은 AFL과 QEMU를 사용하여 Linux x86_64 커널의 시스템 콜
퍼징을 수행하는 데 사용되는 파일 모음입니다. 사용하려면
https://github.com/nccgroup/TriforceAFL 의 TriforceAFL과
퍼징할 커널 이미지가 필요합니다. 스크립트는 TriforceAFL이
$TAFL 또는 ../TriforceAFL/에 있다고 가정합니다 (참고: testAfl 빌드에는
../TriforceAFL/config.h가 존재해야 합니다).
빌드하려면:
make
실행하려면 먼저 커널을 ./kern/bzImage에 설치하고
/proc/kallsyms를 ./kern/kallsyms로 추출하세요. K=kern 환경 변수를
커널을 가리키도록 설정하세요. 그런 다음 실행합니다:
make inputs
./runFuzz -M M0
runFuzz 스크립트는 항상 마스터/슬레이브 모드로 실행되므로
마스터 또는 슬레이브 이름을 기대합니다. 자세한 사용법은 runFuzz 스크립트를
참조하세요.
또한 이것은 소량의 예제 입력만 생성합니다. 많은 수의 중요한 시스템 콜을
테스트하려면 각 시스템 콜에 대해 하나의 예제를 생성하거나, 적어도
시스템 콜의 각 "형태"마다 하나의 예제를 생성하는 것이 좋습니다.
이러한 예제는 inputs/에 배치해야 합니다.
예제는 gen2.py를 참조하세요.
테스트 케이스(예: 크래시)를 재현하려면 다음을 실행합니다:
./runTest inputs/ex1
./runTest outputs/crashes/id*
또한 에뮬레이션 환경 밖에서 -t 옵션으로 드라이버를 실행할 수 있으며,
-vv로 상세 로깅을, -x로 실제 시스템 콜 수행 없이 실행할 수 있습니다:
./driver -tvvx < inputs/ex1
strace ./driver -t < inputs/ex1
커널을 부팅하고 대화식으로 테스트를 실행하는 것이 유용할 때가 있습니다. 그렇게 하려면 rootTemplate 파일을 원하는 대로 편집한 다음(예: 루트 파일시스템에 더 많은 테스트 도구를 추가), 다음을 실행합니다:
./runCmd
쉘 외의 다른 명령은 runCmd의 명령줄 인수로 지정하여 호출할 수 있습니다.
참고: 쉘 사용이 끝나면 ^A-c를 사용하여 QEMU 프롬프트를
열고 quit을 입력하세요.
디버깅은 디버깅 기호가 활성화된 커널을 빌드하면 가장 쉽습니다.
runTest를 사용하여 커널을 시작하고 드라이버를 통해 테스트를 실행하거나,
runCmd를 사용하여 쉘에서 수동으로 테스트 케이스를 실행하세요.
실행 스크립트를 편집하여 afl-qemu-system-trace를 시작할 때 -s 옵션을
포함하세요. 그러면 TCP 포트 1234에서 gdb 지원이 활성화됩니다.
getvmlinux를 사용하여 bzImage 커널에서 vmlinux 커널 이미지를 추출하고
시스템 부팅 후 gdb를 실행하세요:
cp kern/bzImage .
./getvmlinux
gdb ./vmlinux
target remote :1234
break somefunction
continue
runTest가 크래시를 일으킨 후 디버거를 연결하거나
runCmd에서 버그를 수동으로 트리거하기 전에 디버거를 연결할 수 있습니다.
Linux 소스는 기본적으로 최적화가 켜진 상태로 컴파일됩니다.
이로 인해 디버깅이 혼란스럽고 어려워질 수 있습니다.
파일별로 최적화를 비활성화하려면 해당 파일이 있는 하위 디렉터리의
Linux make 파일을 편집하고 Makefile에 CFLAGS_name.o = -O0을 추가하면 됩니다.
예를 들어 kernel/Makefile을 편집하고 CFLAGS_sys_ni.o = -O0을 추가하면
kernel/sys_ni.o를 빌드할 때 최적화가 비활성화됩니다.
getSyms 셸 스크립트는 runCmd를 사용하여 cat /proc/kallsyms를 실행하고
kallsyms라는 로컬 파일로 추출합니다. 이는 일반적으로
퍼징을 위해 커널을 준비하는 데 사용됩니다:
K=yourKernDir ./getSyms를 실행하여 kallsyms를 가져옵니다mv kallsyms yourKernDir을 실행하여 설치합니다참고: Linux 2.* 커널을 퍼징할 때는 CPU 타이머를 활성화해야 합니다.
타이머가 활성화되지 않으면 패닉 및 로깅 감지가 제대로 작동하지 않는 것으로
보이며 패닉이 발생하면 멈춤(hang)이 발생합니다. 타이머를 활성화하려면
driver.c에서 startForkserver(0) 대신 startForkserver(1)을 호출하세요.
이 문제는 Linux 3.* 및 Linux 4.* 커널에서는 발생하지 않는 것으로 보입니다.