
Fuzzer para Drivers do Kernel Linux
Este repositório contém todas as fontes (incluindo scripts de configuração) que você precisa para colocar o difuze em funcionamento.
Ubuntu >= 14.04.5 LTS
Consulte o readme
Conforme explicado em nosso artigo, existem dois componentes principais do difuze: Interface Recovery e Fuzzing Engine
O mecanismo de recuperação de interface é baseado em passes de análise do LLVM. Cada etapa da recuperação de interface é escrita como passes individuais. Siga as instruções abaixo para colocar a Interface Recovery em funcionamento.
Esta etapa cuida da instalação do LLVM e do c2xml:
Primeiro, certifique-se de que você tenha o libxml (necessário para o c2xml):
sudo apt-get install libxml2-dev
sudo pip install lxml
Em seguida, criamos um único script que baixa e compila todas as ferramentas necessárias.
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.
Exemplo:
python setup_difuze.py -o difuze_deps
Para completar a configuração, você também precisa de modificações na variável de ambiente PATH local. O script de configuração lhe dará as alterações exatas que você precisa fazer.
Isso depende da conclusão bem-sucedida da Configuração. Temos um único script que compila tudo, de nada.
cd InterfaceHandlers
./build.sh
Isso depende da conclusão bem-sucedida da Compilação. Para executar os componentes da Interface Recovery nos drivers do kernel, primeiro precisamos converter os drivers em bitcode LLVM.
Primeiro, precisamos ter um kernel compilável. Isso significa que você deve ser capaz de compilar o kernel usando a configuração de compilação normal, ou seja, make.
Primeiro capturamos a saída do comando make; a partir dessa saída, extraímos o comando de compilação exato.
makebear make <all the options to make>
Exemplo: bear make -j8Isso gerará um arquivo compile_commands.json no diretório atual.
Basta passar V=1 e redirecionar a saída para o arquivo.
Exemplo:
make V=1 O=out ARCH=arm64 > makeout.txt 2>&1
NOTA: NÃO USE MÚLTIPLOS PROCESSOS, ou seja, -j. Executar no modo multiprocessamento irá bagunçar o arquivo de saída, pois múltiplos processos tentam escrever no arquivo de saída.
É isso. Em seguida, na etapa seguinte, nosso script pega o makeout.txt gerado e executa a Interface Recovery em todos os drivers reconhecidos.
Todas as várias etapas da Interface Recovery estão encapsuladas em um único script helper_scripts/run_all.py
Como executar:
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.
O script compila, vincula e executa a Interface Recovery em todos os drivers reconhecidos, portanto pode levar um tempo considerável (45 min - 90 min).
O script acima realiza as seguintes tarefas em modo multiprocessador para usar todos os núcleos da CPU:
Todos os arquivos de bitcode gerados serão colocados na pasta fornecida ao argumento -l.
Esta etapa leva um tempo considerável, dependendo do número de núcleos que você possui.
Portanto, se você já tiver realizado esta etapa, pode pulá-la passando -skb.
Isso realiza a vinculação: percorre todos os arquivos de bitcode, identifica os arquivos de bitcode relacionados que precisam ser vinculados e os vincula (usando llvm-link) em um arquivo de bitcode consolidado (que será armazenado junto ao arquivo de bitcode correspondente).
Semelhante à etapa anterior, você pode pular esta etapa passando -skl.
Esta etapa procura as declarações de ponto de entrada nos arquivos de cabeçalho e armazena sua configuração no arquivo: hdr_file_config.txt no diretório de compilação do LLVM.
Para pular: -skp
Esta etapa identifica todos os pontos de entrada em todos os arquivos de bitcode consolidados dos drivers.
A saída será armazenada no arquivo: entry_point_out.txt no diretório de compilação do LLVM.