
DR.CHECKER : 리눅스 커널 드라이버를 위한 건실한 취약점 탐지 도구

이 저장소는 설정 스크립트를 포함한 모든 소스를 포함합니다. 이제 경고와 해당 소스 파일을 함께 볼 수 있는 멋진 UI를 제공합니다.
Ubuntu >= 14.04.5 LTS
2018년 2월 16일:
미리 빌드된 도커 컨테이너에서 DR.CHECKER를 사용하는 방법에 대한 자세한 내용은 Docker 사용법 문서를 참조하세요.
구현은 LLVM, 특히 LLVM 3.8을 기반으로 합니다. 또한 헤더를 파싱하기 위해 c2xml과 같은 도구가 필요합니다.
먼저, cmake(설치/빌드 스크립트에서 사용)와 libxml(c2xml에 필요)이 설치되어 있는지 확인하세요:
sudo apt-get install cmake libxml2-dev
다음으로, 필요한 모든 도구를 다운로드하고 빌드하는 단일 스크립트를 제공합니다.
cd helper_scripts
python setup_drchecker.py --help
usage: setup_drchecker.py [-h] [-b TARGET_BRANCH] [-o OUTPUT_FOLDER]
optional arguments:
-h, --help 도움말 메시지를 표시하고 종료합니다.
-b TARGET_BRANCH 설정할 LLVM의 브랜치(버전)입니다. 기본값:
release_38 (예: release_38)
-o OUTPUT_FOLDER 모든 항목을 설정할 폴더입니다.
예시:
python setup_drchecker.py -o drchecker_deps
설치를 완료하려면 로컬 PATH 환경 변수를 수정해야 합니다. 설정 스크립트가 필요한 정확한 변경 사항을 알려줄 것입니다.
이 단계는 설정이 성공적으로 완료되어야 합니다. 모든 것을 빌드하는 단일 스크립트가 있습니다.
cd llvm_analysis
./build.sh
이 단계는 빌드가 성공적으로 완료되어야 합니다. 커널 드라이버에서 DR.CHECKER를 실행하려면 먼저 이를 LLVM 비트코드로 변환해야 합니다.
먼저, 빌드 가능한 커널이 필요합니다. 즉, 일반 빌드 설정(make)을 사용하여 커널을 컴파일할 수 있어야 합니다.
먼저 make 명령의 출력을 캡처하고, 이 출력에서 정확한 컴파일 명령을 추출합니다.
make (또는 makeout.txt) 출력 생성V=1을 전달하고 출력을 파일로 리디렉션하면 됩니다.
예시:
make V=1 O=out ARCH=arm64 > makeout.txt 2>&1
참고: 여러 프로세스를 사용하지 마십시오(즉, -j). 멀티프로세싱 모드로 실행하면 여러 프로세스가 출력 파일에 쓰려고 하여 출력 파일이 손상됩니다.
이제 DR.CHECKER가 나머지 작업을 처리합니다.
DR.CHECKER 분석을 실행하려면 여러 단계가 있으며, 이러한 모든 단계는 단일 스크립트 helper_scripts/runner_scripts/run_all.py에 포함되어 있습니다.
실행 방법:
python run_all.py --help
usage: run_all.py [-h] [-l LLVM_BC_OUT] [-a CHIPSET_NUM] [-m MAKEOUT] [-g COMPILER_NAME] [-n ARCH_NUM] [-o OUT] [-k KERNEL_SRC_DIR] [-skb] [-skl] [-skp] [-ske] [-ski] [-f SOUNDY_ANALYSIS_OUT]
optional arguments:
-h, --help 도움말 메시지를 표시하고 종료합니다.
-l LLVM_BC_OUT 생성된 모든 비트코드 파일을 저장할 대상 디렉토리입니다.
-a CHIPSET_NUM 칩셋 번호입니다. 유효한 칩셋 번호는 다음과 같습니다:
1(mediatek)|2(qualcomm)|3(huawei)|4(samsung)
-m MAKEOUT makeout.txt 파일의 경로입니다.
-g COMPILER_NAME makeout.txt에서 사용된 컴파일러 이름입니다.
컴파일 명령을 필터링하는 데 필요합니다. 예: aarch64-linux-android-gcc
-n ARCH_NUM 대상 아키텍처, 32비트(1) 또는 64비트(2)입니다.
-o OUT out 폴더의 경로입니다. 일부 커널을 컴파일할 때 출력 디렉토리로 사용될 수 있는 폴더입니다.
(참고: 모든 커널에 별도의 out 폴더가 필요한 것은 아닙니다)
-k KERNEL_SRC_DIR 커널 소스의 기본 디렉토리입니다.
-skb LLVM 빌드 건너뛰기 (기본값: 건너뛰지 않음).
-skl Dr Linker 건너뛰기 (기본값: 건너뛰지 않음).
-skp 헤더 파싱 건너뛰기 (기본값: 건너뛰지 않음).
-ske 진입점 식별 건너뛰기 (기본값: 건너뛰지 않음).
-ski Soundy 분석 건너뛰기 (기본값: 건너뛰지 않음).
-f SOUNDY_ANALYSIS_OUT soundy 분석 출력을 저장할 출력 폴더의 경로입니다.
이 스크립트는 모든 드라이버에 대해 빌드, 링크 및 DR.CHECKER를 실행하므로 **상당한 시간(45분~90분)**이 소요될 수 있습니다. 개별 드라이버에서 DR.CHECKER를 수동으로 실행하려면 standalone을 참조하세요.
위 스크립트는 모든 CPU 코어를 사용하기 위해 멀티프로세서 모드로 다음 작업을 수행합니다:
생성된 모든 비트코드 파일은 -l 인수로 제공된 폴더에 배치됩니다.
이 단계는 보유한 코어 수에 따라 상당한 시간이 소요됩니다.
따라서 이 단계를 이미 수행한 경우 -skb를 전달하여 건너뛸 수 있습니다.
이 단계는 링크를 수행하며, 모든 비트코드 파일을 검토하여 링크해야 할 관련 비트코드 파일을 식별하고 llvm-link를 사용하여 통합 비트코드 파일(해당 비트코드 파일과 함께 저장됨)로 링크합니다.
위 단계와 마찬가지로 -skl을 전달하여 건너뛸 수 있습니다.
이 단계는 헤더 파일에서 진입점 선언을 찾고 해당 구성을 LLVM 빌드 디렉토리 아래의 hdr_file_config.txt 파일에 저장합니다.
건너뛰려면: -skp
이 단계는 모든 드라이버 통합 비트코드 파일에서 모든 진입점을 식별합니다.
출력은 LLVM 빌드 디렉토리 아래의 entry_point_out.txt 파일에 저장됩니다.
entry_point_out.txt 파일 내용 예시:
FileRead:hidraw_read:/home/drchecker/33.2.A.3.123/llvm_bc_out/drivers/hid/llvm_link_final/final_to_check.bc
FileWrite:hidraw_write:/home/drchecker/33.2.A.3.123/llvm_bc_out/drivers/hid/llvm_link_final/final_to_check.bc
IOCTL:hidraw_ioctl:/home/drchecker/33.2.A.3.123/llvm_bc_out/drivers/hid/llvm_link_final/final_to_check.bc
건너뛰려면: -ske
이 단계는 entry_point_out.txt 파일의 모든 진입점에 대해 DR.CHECKER를 실행합니다. 각 진입점의 출력은 -f 옵션으로 제공된 폴더에 저장됩니다.
건너뛰려면: -ski
이제 커널 소스가 있는 상태에서 취약점 경고가 나타날 때까지의 예시를 보여드리겠습니다.
미디어텍 커널 33.2.A.3.123.tar.bz2를 업로드했습니다. 먼저 위 파일을 다운로드하고 압축을 풉니다.
압축을 푼 폴더가 ~/mediatek_kernel이라고 가정합니다.
cd ~/mediatek_kernel
source ./env.sh
cd kernel-3.18
# 다음 단계는 커널에 따라 필요하지 않을 수 있습니다.
mkdir out
make O=out ARCH=arm64 tubads_defconfig
# 다음 명령은 모든 컴파일 명령을 makeout.txt에 복사합니다.
make V=1 -j8 O=out ARCH=arm64 > makeout.txt 2>&1
cd <repo_path>/helper_scripts/runner_scripts
python run_all.py -l ~/mediatek_kernel/llvm_bitcode_out -a 1 -m ~/mediatek_kernel/kernel-3.18/makeout.txt -g aarch64-linux-android-gcc -n 2 -o ~/mediatek_kernel/kernel-3.18/out -k ~/mediatek_kernel/kernel-3.18 -f ~/mediatek_kernel/dr_checker_out
위 명령은 **상당한 시간(30분~1시간)**이 소요됩니다.
첫째, 모든 분석 결과는 ~/mediatek_kernel/dr_checker_out(-f 옵션에 제공된 인수) 폴더에 있으며, 각 진입점에 대해 모든 경고를 JSON 형식으로 포함하는 .json 파일이 생성됩니다. 이 json 파일은 컨텍스트별로 정리된 경고를 포함합니다.
둘째, ~/mediatek_kernel/dr_checker_out/instr_warnings(-f 옵션에 제공된 인수 기준) 폴더에는 명령어 위치별로 정리된 경고가 포함됩니다.
이러한 경고는 Visualizer를 사용하여 분석할 수 있습니다.
마지막으로, 각 진입점에 대한 모든 경고의 요약이 유형별로 정리되어 출력 CSV 파일 **~/mediatek_kernel/dr_checker_out/warnings_stats.csv(-f 옵션에 제공된 인수 기준)**에 기록됩니다.
-g 옵션 값-g 옵션 값을 제공하려면 커널을 컴파일하는 데 사용된 *-gcc 바이너리의 이름을 알아야 합니다.
쉽게 알아내는 방법은 makeout.txt에서 gcc를 grep하는 것이며, 컴파일러 명령에서 *-gcc 바이너리 이름을 확인할 수 있습니다.
위 예시의 경우, 예시 빌드에서 grep gcc makeout.txt를 실행하면 다음과 같은 줄을 많이 볼 수 있습니다:
aarch64-linux-android-gcc -Wp,-MD,fs/jbd2/.transaction.o.d -nostdinc -isystem ...
따라서 -g의 값은 aarch64-linux-android-gcc여야 합니다.
빌드할 커널이 32비트인 경우 바이너리는 대부분 arm-eabi-gcc일 것입니다.
-a 옵션 값칩셋 유형에 따라 해당 번호를 제공해야 합니다.
-o 옵션 값이 값은 커널 빌드 중 make 명령에 O= 옵션으로 제공된 폴더의 경로입니다.
모든 커널이 별도의 out 경로를 필요로 하지는 않습니다. O 옵션을 제공하지 않고 커널을 빌드할 수 있으며, 이 경우 run_all.py를 실행할 때 해당 옵션에 값을 제공하지 말아야 합니다.
모든 경고를 볼 수 있는 웹 기반 UI를 제공합니다. 시각화를 참조하세요.
BugDetectorDriver.cpp에서 해당 #define DISABLE_* 줄의 주석을 해제하여 하나 이상의 취약점 검사기를 비활성화할 수 있습니다.
원하는 경우 결과를 후처리하는 스크립트도 제공합니다. 확인해 보세요.
즐거운 시간 되세요!!