
Фаззер для драйверов ядра Linux
Этот репозиторий содержит все исходные файлы (включая скрипты настройки), необходимые для запуска difuze.
Ubuntu >= 14.04.5 LTS
См. README
Как описано в нашей статье, difuze состоит из двух основных компонентов: Восстановление интерфейса и Движок фаззинга
Механизм восстановления интерфейса основан на анализах проходов LLVM. Каждый шаг восстановления интерфейса реализован в виде отдельного прохода. Следуйте инструкциям ниже, чтобы запустить Восстановление интерфейса.
Этот шаг устанавливает LLVM и c2xml:
Сначала убедитесь, что у вас установлен libxml (требуется для c2xml):
sudo apt-get install libxml2-dev
sudo pip install lxml
Далее мы подготовили единый скрипт, который загружает и собирает все необходимые инструменты.
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.
Пример:
python setup_difuze.py -o difuze_deps
Для завершения настройки также потребуется изменить локальную переменную окружения PATH. Скрипт настройки сообщит вам точные изменения, которые необходимо внести.
Этот шаг зависит от успешного выполнения Настройки. У нас есть единый скрипт, который собирает всё, пожалуйста.
cd InterfaceHandlers
./build.sh
Этот шаг зависит от успешного выполнения Сборки. Для запуска компонентов восстановления интерфейса на драйверах ядра необходимо сначала преобразовать драйверы в LLVM-биткод.
Во-первых, нам нужно собрать ядро. То есть вы должны уметь компилировать ядро с помощью обычной настройки сборки, т.е. make.
Сначала мы захватываем вывод команды make, а из этого вывода извлекаем точную команду компиляции.
makebear make <все опции make>
Пример: bear make -j8Это создаст файл compile_commands.json в текущем каталоге.
Просто передайте V=1 и перенаправьте вывод в файл.
Пример:
make V=1 O=out ARCH=arm64 > makeout.txt 2>&1
ПРИМЕЧАНИЕ: НЕ ИСПОЛЬЗУЙТЕ НЕСКОЛЬКО ПРОЦЕССОВ, т.е. -j. Работа в многопроцессорном режиме испортит выходной файл, так как несколько процессов попытаются записать в него одновременно.
Вот и всё. Затем на следующем шаге наш скрипт берёт сгенерированный файл makeout.txt и запускает восстановление интерфейса на всех распознанных драйверах.
Все различные шаги восстановления интерфейса объединены в единый скрипт helper_scripts/run_all.py
Как запустить:
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:
Все сгенерированные файлы биткода будут помещены в папку, указанную в аргументе -l.
Этот шаг занимает много времени, в зависимости от количества ядер.
Если вы уже выполнили этот шаг, его можно пропустить, передав -skb.
Этот этап выполняет связывание: он просматривает все файлы биткода, определяет связанные файлы биткода, которые нужно связать, и связывает их (с помощью llvm-link) в единый файл биткода (который будет сохранён рядом с соответствующим файлом биткода).
Как и на предыдущем шаге, его можно пропустить, передав -skl.
Этот шаг ищет объявления точек входа в файлах заголовков и сохраняет их конфигурацию в файле: hdr_file_config.txt в каталоге сборки LLVM.
Чтобы пропустить: -skp
Этот шаг определяет все точки входа во всех объединённых файлах биткода драйверов.
Результат будет сохранён в файле: entry_point_out.txt в каталоге сборки LLVM.
Пример содержимого файла entry_point_out.txt:
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