Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
difuze — 리눅스 커널 드라이버용 퍼저 | Kitploit
도구/GitHubGitHub/ucsb-seclab/difuze
Android SecurityVulnerability AnalysisFuzzingBinary Analysis
GitHubucsb-seclab/difuze

difuze

리눅스 커널 드라이버용 퍼저

저장소 보기
385854년 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

difuze: Linux 커널 드라이버용 퍼저

License

이 저장소에는 difuze를 실행하는 데 필요한 모든 소스(셋업 스크립트 포함)가 포함되어 있습니다.

테스트 환경

Ubuntu >= 14.04.5 LTS

0. Docker에서 difuze 실행하기

readme를 참조하세요.

우리의 논문에서 설명한 대로, difuze에는 인터페이스 복구와 퍼징 엔진의 두 가지 주요 구성 요소가 있습니다.

1. 인터페이스 복구

인터페이스 복구 메커니즘은 LLVM 분석 패스(pass)를 기반으로 합니다. 인터페이스 복구의 각 단계는 개별 패스로 작성되어 있습니다. 인터페이스 복구를 실행하는 방법은 아래 지침을 따르세요.

1.1 설정

이 단계에서는 LLVM과 c2xml을 설치합니다.

root@kitploit:~
sudo apt-get install libxml2-dev
sudo pip install lxml

다음으로, 필요한 모든 도구를 다운로드하고 빌드하는 단일 스크립트를 만들었습니다.

root@kitploit:~
cd helper_scripts
python setup_difuze.py --help
usage: setup_difuze.py [-h] [-b TARGET_BRANCH] [-o OUTPUT_FOLDER]

optional arguments:
  -h, --help        show this help message and exit
  -b TARGET_BRANCH  Branch (i.e. version) of the LLVM to setup. Default:
                    release_38 e.g., release_38
  -o OUTPUT_FOLDER  Folder where everything needs to be setup.

예시:

root@kitploit:~
python setup_difuze.py -o difuze_deps

설정을 완료하려면 로컬 PATH 환경 변수도 수정해야 합니다. 설정 스크립트가 필요한 정확한 변경 사항을 알려줍니다.

1.2 빌드

이 단계는 설정이 성공적으로 완료되어야 합니다. 모든 것을 빌드하는 단일 스크립트가 있습니다. 마음껏 사용하세요.

root@kitploit:~
cd InterfaceHandlers
./build.sh

1.3 실행

이 단계는 빌드가 성공적으로 완료되어야 합니다. 커널 드라이버에서 인터페이스 복구 구성 요소를 실행하려면 먼저 드라이버를 llvm 비트코드로 변환해야 합니다.

1.3.1 커널 빌드

먼저 빌드 가능한 커널이 필요합니다. 즉, 일반적인 빌드 설정을 사용하여 커널을 컴파일할 수 있어야 합니다. 예: make. 먼저 make 명령의 출력을 캡처하고, 이 출력에서 정확한 컴파일 명령을 추출합니다.

1.3.1.1 make 출력 생성
옵션 1: Bear 사용 (권장)
  1. Bear 설치
  2. Bear를 사용하여 make 실행:
    root@kitploit:~
    bear make <all the options to make>
    
    예시: bear make -j8

이렇게 하면 현재 디렉터리에 compile_commands.json 파일이 생성됩니다.

옵션 2

V=1을 전달하고 출력을 파일로 리다이렉트하면 됩니다. 예시:

root@kitploit:~
make V=1 O=out ARCH=arm64 > makeout.txt 2>&1

참고: 다중 프로세스를 사용하지 마세요 즉, -j를 사용하지 마세요. 다중 처리 모드로 실행하면 여러 프로세스가 출력 파일에 쓰려고 시도하므로 출력 파일이 손상됩니다.

이상입니다. 다음 단계에서 우리 스크립트는 생성된 makeout.txt를 가져와 인식된 모든 드라이버에 대해 인터페이스 복구를 실행합니다.

1.3.2 인터페이스 복구 분석 실행

인터페이스 복구의 모든 다양한 단계는 단일 스크립트 helper_scripts/run_all.py로 묶여 있습니다. 실행 방법:

root@kitploit:~
cd helper_scripts
python run_all.py --help

usage: run_all.py [-h] [-l LLVM_BC_OUT] [-a CHIPSET_NUM] [-m MAKEOUT]
                  [-c COMPJSON] [-g COMPILER_NAME] [-n ARCH_NUM] [-o OUT]
                  [-k KERNEL_SRC_DIR] [-isclang] [-clangp CLANG_PATH]
                  [-llvmlinkp LLVMLINK_PATH] [-skb] [-skl] [-skp] [-skP]
                  [-ske] [-skI] [-ski] [-skv] [-skd] [-f IOCTL_FINDER_OUT]

optional arguments:
  -h, --help            show this help message and exit
  -l LLVM_BC_OUT        Destination directory where all the generated bitcode
                        files should be stored.
  -a CHIPSET_NUM        Chipset number. Valid chipset numbers are:
                        1(mediatek)|2(qualcomm)|3(huawei)|4(samsung)
  -m MAKEOUT            Path to the makeout.txt file.
  -c COMPJSON           Path to the compile_commands_json generated by Bear.
  -g COMPILER_NAME      Name of the compiler used in the makeout.txt, This is
                        needed to filter out compilation commands. Ex: aarch64
                        -linux-android-gcc
  -n ARCH_NUM           Destination architecture, 32 bit (1) or 64 bit (2).
  -o OUT                Path to the out folder. This is the folder, which
                        could be used as output directory during compiling
                        some kernels.
  -k KERNEL_SRC_DIR     Base directory of the kernel sources.
  -isclang              flag to indicate that clang was used to built the
                        kernel
  -clangp CLANG_PATH    Absolute path to the clang binary (if not provided,
                        the one available in the path will be used)
  -llvmlinkp LLVMLINK_PATH
                        Absolute path to the llvm-link binary (if not
                        provided, the one available in the path will be used)
  -skb                  Skip LLVM Build (default: not skipped).
  -skl                  Skip Dr Linker (default: not skipped).
  -skp                  Skip Parsing Headers (default: not skipped).
  -skP                  Skip Generating Preprocessed files (default: not
                        skipped).
  -ske                  Skip Entry point identification (default: not
                        skipped).
  -skI                  Skip Generate Includes (default: not skipped).
  -ski                  Skip IoctlCmdParser run (default: not skipped).
  -skv                  Skip V4L2 ioctl processing (default: not skipped).
  -skd                  Skip Device name finder (default: not skipped).
  -f IOCTL_FINDER_OUT   Path to the output folder where the ioctl command
                        finder output should be stored.


이 스크립트는 인식된 모든 드라이버에 대해 인터페이스 복구를 빌드, 링크 및 실행하므로 상당한 시간(45분~90분) 이 걸릴 수 있습니다.

위 스크립트는 모든 CPU 코어를 활용하기 위해 다중 프로세서 모드로 다음 작업을 수행합니다:

1.3.2.1 LLVM 빌드
  • 기본적으로 활성화되어 있습니다.

생성된 모든 비트코드 파일은 -l 인수로 제공된 폴더에 저장됩니다. 이 단계는 사용 가능한 코어 수에 따라 상당한 시간이 걸립니다. 이미 이 단계를 수행했다면 -skb를 전달하여 이 단계를 건너뛸 수 있습니다.

1.3.2.2 모든 드라이버 비트코드 파일을 하나의 통합 비트코드 파일로 링크
  • 기본적으로 활성화되어 있습니다

이 작업은 링크를 수행하며, 모든 비트코드 파일을 검토하여 링크해야 할 관련 비트코드 파일을 식별하고 이를 (llvm-link를 사용하여) 통합 비트코드 파일로 링크합니다(해당 비트코드 파일 옆에 저장됩니다).

위 단계와 유사하게 -skl을 전달하여 이 단계를 건너뛸 수 있습니다.

1.3.2.3 엔트리 함수 필드를 식별하기 위한 헤더 파싱
  • 기본적으로 활성화되어 있습니다.

이 단계는 헤더 파일에서 엔트리 포인트 선언을 찾아 해당 구성을 LLVM 빌드 디렉터리 아래의 hdr_file_config.txt 파일에 저장합니다.

건너뛰려면: -skp

1.3.2.4 모든 통합 비트코드 파일에서 엔트리 포인트 식별
  • 기본적으로 활성화되어 있습니다

이 단계는 모든 드라이버 통합 비트코드 파일에서 모든 엔트리 포인트를 식별합니다. 출력은 LLVM 빌드 디렉터리 아래의 entry_point_out.txt 파일에 저장됩니다.

entry_point_out.txt 파일 내용의 예:

root@kitploit:~
IOCTL:msm_lsm_ioctl:/home/difuze/kernels/pixel/msm/sound/soc/msm/qdsp6v2/msm-lsm-client.c:msm_lsm_ioctl.txt:/home/difuze/pixel/llvm_out/sound/soc/msm/qdsp6v2/llvm_link_final/final_to_check.bc
IOCTL:msm_pcm_ioctl:/home/difuze/kernels/pixel/msm/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c:msm_pcm_ioctl.txt:/home/difuze/pixel/llvm_out/sound/soc/msm/qdsp6v2/llvm_link_final/final_to_check.bc

건너뛰려면: -ske

1.3.2.5 식별된 모든 엔트리 포인트에서 Ioctl Cmd Finder 실행
  • 기본적으로 활성화되어 있습니다.

이 단계는 entry_point_out.txt 파일의 모든 엔트리 포인트에 대해 주요 인터페이스 복구 구성 요소(IoctlCmdParser)를 실행합니다. 각 엔트리 포인트의 출력은 -f 옵션으로 제공된 폴더에 저장됩니다.

건너뛰려면: -ski

1.4 예시:

이제 커널 소스가 있는 시점부터 인터페이스 복구 결과를 얻는 시점까지의 예시를 보여드리겠습니다.

mediatek 커널 33.2.A.3.123.tar.bz2을 업로드했습니다. 먼저 위 파일을 다운로드하고 압축을 풉니다.

위 파일을 ~/mediatek_kernel이라는 폴더에 압축을 풀었다고 가정해 보겠습니다.

1.4.1 빌드

Bear를 설치하고 아래 단계를 따르세요:

root@kitploit:~
cd ~/mediatek_kernel
source ./env.sh
cd kernel-3.18
# the following step may not be needed depending on the kernel
mkdir out
make O=out ARCH=arm64 tubads_defconfig
# generating compile_commands.json
bear make -j8 O=out ARCH=arm64

1.4.2 인터페이스 복구 실행

root@kitploit:~
cd <repo_path>/helper_scripts

python run_all.py -l ~/mediatek_kernel/llvm_bitcode_out -a 1 -c ~/mediatek_kernel/kernel-3.18/compile_commands.json -n 2 -o ~/mediatek_kernel/kernel-3.18/out -k ~/mediatek_kernel/kernel-3.18 -f ~/mediatek_kernel/ioctl_finder_out

위 명령은 시간이 꽤 걸립니다(30분~1시간).

1.4.3 출력 이해하기

먼저 모든 분석 결과는 ~/mediatek_kernel/ioctl_finder_out (-f 옵션에 주어진 인수) 폴더에 저장됩니다. 각 엔트리 포인트에 대해 복구된 인터페이스에 대한 모든 정보를 포함하는 .txt 파일이 생성됩니다.

인터페이스에 대한 정보만 관심 있고 다른 것은 신경 쓰지 않는다면 parse_interface_output.py 스크립트를 사용하는 것이 좋습니다. 이 스크립트는 인터페이스 복구 패스의 복잡한 출력을 깔끔하고 일관된 형식의 멋진 json 파일로 변환합니다.

root@kitploit:~
cd <repo_path>/helper_scripts
python parse_interface_output.py <ioctl_finder_out_dir> <output_directory_for_json_files>

여기서 <ioctl_finder_out_dir>은 -f 옵션에 제공한 폴더와 동일해야 하며, <output_directory_for_json_files>는 json 파일이 생성될 폴더입니다.

해당 ioctl의 인터페이스 복구에 대응하는 json 파일을 사용할 수 있습니다.

1.4.4 참고 사항:

1.4.4.1 -g 옵션의 값 (makeout.txt를 사용하는 경우에만)

-g 옵션의 값을 제공하려면 커널 컴파일에 사용된 *-gcc 바이너리의 이름을 알아야 합니다. 이를 알 수 있는 쉬운 방법은 makeout.txt에서 gcc를 grep하는 것입니다. 그러면 컴파일러 명령에서 *-gcc 바이너리 이름을 알 수 있습니다.

위 예시에서 예제 빌드에 대해 grep gcc makeout.txt를 실행하면 아래와 같은 많은 줄이 표시됩니다:

root@kitploit:~
aarch64-linux-android-gcc -Wp,-MD,fs/jbd2/.transaction.o.d  -nostdinc -isystem ...

따라서 -g의 값은 aarch64-linux-android-gcc여야 합니다.

빌드할 커널이 32비트라면 바이너리는 대개 arm-eabi-gcc입니다.

Qualcomm(또는 msm) 칩셋의 경우 *.gcc 대신 *gcc-wrapper.py가 표시될 수 있습니다. 이 경우 *gcc-wrapper.py를 제공해야 합니다.

1.4.4.2 -a 옵션의 값

칩셋 유형에 따라 해당 번호를 제공해야 합니다.

1.4.4.3 -o 옵션의 값

이것은 커널 빌드 중 make 명령의 O= 옵션에 제공된 폴더의 경로입니다.

모든 커널이 별도의 out 경로를 필요로 하는 것은 아닙니다. O 옵션을 제공하지 않고 커널을 빌드할 수도 있습니다. 이 경우 run_all.py를 실행할 때 해당 옵션에 값을 제공하지 말아야 합니다.

clang으로 빌드된 커널

clang을 사용하여 빌드된 커널의 경우 위 옵션 외에 다음 옵션을 지정하세요(compile_commands.json을 사용했다고 가정):

root@kitploit:~
-isclang -clangp <PATH_TO_THE_CLANG_USED_TO_BUILD_THE_KERNEL> -llvmlinkp <PATH_TO_THE_LLVM_LINK (will be in the same folder as clang)>

1.5 후처리

퍼징을 시작하기 전에 (죄송합니다만) 연구용 품질의 파서로 출력을 약간 처리해야 합니다.

이 파서는 여기에서 찾을 수 있습니다. 실행할 주요 스크립트는 run_all.py입니다:

root@kitploit:~
$ python run_all.py --help
usage: run_all.py [-h] -f F -o O [-n {manual,auto,hybrid}] [-m M]

run_all options

optional arguments:
  -h, --help            show this help message and exit
  -f F                  Filename of the ioctl analysis output OR the entire
                        output directory created by the system
  -o O                  Output directory to store the results. If this
                        directory does not exist it will be created
  -n {manual,auto,hybrid}
                        Specify devname options. You can choose manual
                        (specify every name manually), auto (skip anything that
                        we don't identify a name for), or hybrid (if we
                        detected a name, we use it, else we ask the user)
  -m M                  Enable multi-device output most ioctls only have one
                        applicable device node, but some may have multiple. (0
                        to disable)

-f에는 ioctl 분석 출력 디렉터리(예: ~/mediatek_kernel/ioctl_finder_out)를 전달하면 됩니다.

-o는 후처리 결과를 저장할 위치입니다. 결과는 쉽게 이해할 수 있는 XML 파일(jpits)로 저장됩니다.

-n은 장치 이름 복구에 얼마나 의존할지 시스템에 지정합니다. 작업이나 이름 찾기를 전혀 하고 싶지 않다면 auto를 지정할 수 있습니다. 물론 이 경우 이름을 복구하지 못한 장치는 건너뛰게 됩니다. 복구 결과를 전혀 신뢰하지 않으려면(충분히 합리적입니다) manual 옵션을 사용하여 모든 장치의 이름을 직접 지정할 수 있습니다. hybrid는 이 둘의 조합입니다. 가능하면 장치 이름을 자동으로 지정하고, 실패하면 사용자에게 요청합니다.

-m 때로는 ioctl이 둘 이상의 장치에 대응할 수 있습니다(예: v4l2/subdev ioctl에서 흔함). 이 지원은 기본적으로 활성화되어 있지만 각 장치에 대한 장치 수를 지정하려면 사용자 상호 작용이 필요합니다. 이것이 너무 번거롭다면 -m 0을 전달하여 프롬프트를 비활성화할 수 있습니다(각 ioctl에 대해 단일 장치를 가정합니다).

실행 후 out 폴더에는 각 ioctl에 대한 폴더가 생성됩니다.

2 퍼징

2.1 Mango Fuzz

MangoFuzz는 간단한 프로토타입 퍼저로, Peach(특히 MozPeach)를 기반으로 합니다.

특별히 정교한 퍼저는 아니지만 버그를 찾아냅니다. 또한 쉽게 확장할 수 있도록 설계되었습니다. 이 퍼저에는 퍼즈 엔진(fuzz engine)과 실행기(executor)의 두 가지 구성 요소가 있습니다. 실행기는 여기에서, 퍼즈 엔진은 여기에서 찾을 수 있습니다.

2.1.1 실행기

실행기는 퍼즈 엔진이 보낼 데이터를 수신하면서 휴대폰에서 실행됩니다.

휴대폰 아키텍처에 맞게 컴파일하고, adb push로 휴대폰에 넣은 다음, 수신하려는 포트로 실행하기만 하면 됩니다!

2.1.2 퍼즈 엔진

MangoFuzz와의 인터페이스는 상당히 간단합니다. Engine 객체와 Parser 객체가 필요하며, 엔진을 여기에 연결하면 됩니다. 그런 다음 Parser로 jpits를 파싱하고 Engine을 실행하면 됩니다. 간단합니다! 시작하는 데 도움이 되도록 몇 가지 간단한 실행 스크립트를 제공했습니다.

특정 드라이버를 대상으로 실행하려면 출력 디렉터리(후처리 스크립트로 생성된)의 ioctl 폴더 중 하나에서 runner.py를 사용할 수 있습니다.

예: ./runner.py -f honor8/out/chb -num 1000. 이는 MangoFuzz가 chb ioctl/드라이버와 관련된 모든 ioctl 명령 값 쌍에 대해 1000회 반복 실행하도록 지시합니다.

대신 전체 장치(휴대폰)를 대상으로 실행하려면 dev_runner.py를 사용할 수 있습니다. 예: ./dev_runner.py -f honor8/out -num 100. 이렇게 하면 드라이버 파일을 계속 반복하면서 각각 100회 반복씩 무작위로 전환합니다.

퍼즈 엔진이 휴대폰과 통신하려면 먼저 ADB를 사용하여 포트 포워딩을 설정해야 합니다(예: adb forward tcp:2022 tcp:2022).

도구 다운로드