Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
difuze — Fuzzer para Drivers do Kernel Linux | Kitploit
Ferramentas/GitHubGitHub/ucsb-seclab/difuze
Segurança AndroidAnálise de VulnerabilidadesFuzzingAnálise de Binários
GitHubucsb-seclab/difuze

difuze

Fuzzer para Drivers do Kernel Linux

Ver Repositório
38585há 4 anosRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

difuze: Fuzzer para Drivers do Kernel Linux

License

Este repositório contém todas as fontes (incluindo scripts de configuração) que você precisa para colocar o difuze em funcionamento.

Testado em

Ubuntu >= 14.04.5 LTS

0. Executando difuze a partir do Docker

Consulte o readme

Conforme explicado em nosso artigo, existem dois componentes principais do difuze: Interface Recovery e Fuzzing Engine

1. Interface Recovery

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.

1.1 Configuração

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):

root@kitploit:~
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.

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.

Exemplo:

root@kitploit:~
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.

1.2 Compilando

Isso depende da conclusão bem-sucedida da Configuração. Temos um único script que compila tudo, de nada.

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

1.3 Executando

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.

1.3.1 Compilando o kernel

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.

1.3.1.1 Gerando a saída do make
Opção 1: Usando Bear (RECOMENDADO)
  1. Instale o Bear
  2. Execute make usando Bear:
    root@kitploit:~
    bear make <all the options to make>
    
    Exemplo: bear make -j8

Isso gerará um arquivo compile_commands.json no diretório atual.

Opção 2

Basta passar V=1 e redirecionar a saída para o arquivo. Exemplo:

root@kitploit:~
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.

1.3.2 Executando a análise da Interface Recovery

Todas as várias etapas da Interface Recovery estão encapsuladas em um único script helper_scripts/run_all.py Como executar:

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.


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:

1.3.2.1 LLVM Build
  • Habilitado por padrão.

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.

1.3.2.2 Vinculando todos os arquivos de bitcode dos drivers em um arquivo de bitcode consolidado.
  • Habilitado por padrão.

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.

1.3.2.3 Analisando cabeçalhos para identificar campos da função de entrada.
  • Habilitado por padrão.

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

1.3.2.4 Identificar pontos de entrada em todos os arquivos de bitcode consolidados.
  • Habilitado por padrão.

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.

Exemplo de conteúdo do arquivo 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

Para pular: -ske

1.3.2.5 Executar o Ioctl Cmd Finder em todos os pontos de entrada identificados.
  • Habilitado por padrão.

Esta etapa executará o componente principal da Interface Recovery (IoctlCmdParser) em todos os pontos de entrada no arquivo entry_point_out.txt. A saída para cada ponto de entrada será armazenada na pasta fornecida para a opção -f.

Para pular: -ski

1.4 Exemplo:

Agora, mostraremos um exemplo desde o ponto em que você tem as fontes do kernel até a obtenção dos resultados da Interface Recovery.

Enviamos um kernel mediatek 33.2.A.3.123.tar.bz2. Primeiro, baixe e extraia o arquivo acima.

Digamos que você extraiu o arquivo acima em uma pasta chamada: ~/mediatek_kernel

1.4.1 Compilando

Instale o Bear e siga os passos abaixo:

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 Executando a Interface Recovery

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

O comando acima leva um certo tempo (30 min - 1 hora).

1.4.3 Entendendo a saída

Primeiro, todos os resultados da análise estarão na pasta: ~/mediatek_kernel/ioctl_finder_out (argumento dado à opção -f), para cada ponto de entrada será criado um arquivo .txt, que contém todas as informações sobre a interface recuperada.

Se você está interessado apenas nas informações sobre a interface e não se importa com o resto, recomendamos usar o script parse_interface_output.py. Este script converte a saída louca do passe Interface Recovery em belos arquivos json com um formato limpo e consistente.

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

Aqui <ioctl_finder_out_dir> deve ser o mesmo que a pasta fornecida à opção -f e <output_directory_for_json_files> é a pasta onde os arquivos json devem ser criados.

Você pode usar os arquivos json correspondentes para a recuperação de interface do ioctl correspondente.

1.4.4 Coisas a observar:

1.4.4.1 Valor para a opção -g (apenas se você usar makeout.txt)

Para fornecer o valor da opção -g, você precisa saber o nome do binário *-gcc usado para compilar o kernel. Uma maneira fácil de saber isso é usar grep por gcc no makeout.txt e você verá comandos do compilador a partir dos quais poderá saber o nome do binário *-gcc.

Para o nosso exemplo acima, se você fizer grep gcc makeout.txt para a compilação de exemplo, verá muitas linhas como abaixo:

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

Portanto, o valor para -g deve ser aarch64-linux-android-gcc.

Se o kernel a ser compilado for de 32 bits, então o binário provavelmente será arm-eabi-gcc

Para chipsets Qualcomm (ou msm), você pode ver *gcc-wrapper.py em vez de *.gcc, nesse caso você deve fornecer o *gcc-wrapper.py.

1.4.4.2 Valor para a opção -a

Dependendo do tipo de chipset, você precisa fornecer o número correspondente.

1.4.4.3 Valor para a opção -o

Este é o caminho da pasta fornecida à opção O= para o comando make durante a compilação do kernel.

Nem todos os kernels precisam de um caminho de saída separado. Você pode compilar o kernel sem fornecer a opção O, caso em que você NÃO DEVE fornecer valor para essa opção ao executar run_all.py.

Kernels compilados com clang

Para kernels compilados com clang, além das opções acima, especifique as seguintes opções (assumindo que você usou 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 Pós-processamento

Antes de começarmos o fuzzing, precisamos processar um pouco a saída com nossos analisadores de qualidade de pesquisa (desculpe).

Eles são encontrados aqui. O script principal a ser executado será 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)

Você vai querer passar -f o diretório de saída da análise ioctl, por exemplo, ~/mediatek_kernel/ioctl_finder_out.

-o é onde você vai armazenar os resultados pós-processados. Serão arquivos XML fáceis de digerir (jpits).

-n especifica o sistema até que ponto você deseja confiar em nossa recuperação de nome de dispositivo. Se você não quiser fazer nenhum trabalho/caça a nomes, pode especificar auto. Isso, claro, custa pular qualquer dispositivo para o qual não recuperamos um nome. Se você quiser ser paranóico e não confiar em nenhum de nossos esforços de recuperação (totalmente razoável), pode usar a opção manual para nomear você mesmo cada dispositivo. hybrid então é uma combinação de ambos – nomearemos o dispositivo para você quando pudermos, e recorreremos a você quando falharmos.

-m Às vezes, ioctls podem corresponder a mais de um dispositivo (isso é comum com ioctls v4l2/subdev, por exemplo). O suporte para isso está habilitado por padrão, mas requer interação do usuário para especificar o número de dispositivos para cada dispositivo. Se isso for muito irritante para você, pode desabilitar o prompt passando -m 0 (assumiremos um único dispositivo para cada ioctl).

Após a execução, você deve ter, em sua pasta de saída, uma pasta para cada ioctl.

2 Fuzzing

2.1 Mango Fuzz

MangoFuzz é nosso protótipo simples de fuzzer e é baseado no Peach (especificamente MozPeach).

Não é um fuzzer particularmente sofisticado, mas encontra bugs. Também foi construído para ser facilmente expansível. Há 2 componentes neste fuzzer: o mecanismo de fuzzing e o executor. O executor pode ser encontrado aqui, e o mecanismo de fuzzing pode ser encontrado aqui.

2.1.1 Executor

O executor roda no telefone, ouvindo dados que o mecanismo de fuzzing enviará para ele.

Simplesmente compile para a arquitetura do seu telefone, faça adb push para o telefone e execute com a porta na qual deseja que ele ouça!

2.1.2 Mecanismo de Fuzzing

A interface com o MangoFuzz é bastante simples. Você vai querer um objeto Engine e um objeto Parser, no qual você alimentará seu mecanismo. A partir daqui, você analisa os jpits com seu Parser e então executa o Engine. Fácil! Fornecemos alguns scripts de execução simples para você começar.

Para executar contra drivers específicos, você pode usar runner.py em uma das pastas ioctl no diretório de saída (criado pelos nossos scripts de pós-processamento).

Por exemplo, ./runner.py -f honor8/out/chb -num 1000. Isso diz ao MangoFuzz para executar por 1000 iterações contra todos os pares de valor de comando ioctl pertencentes ao ioctl/driver chb.

Se, em vez disso, quisermos executar contra um dispositivo inteiro (telefone), você pode usar dev_runner.py. Por exemplo, ./dev_runner.py -f honor8/out -num 100. Isso continuará iterando sobre os arquivos de driver, alternando aleatoriamente entre eles por 100 iterações cada.

Note que antes que o mecanismo de fuzzing possa se comunicar com o telefone, você precisará usar ADB para configurar o encaminhamento de porta, por exemplo, adb forward tcp:2022 tcp:2022

Baixar ferramenta