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
Pi-Zero-2W-Bad-USB — Configure your Pi Zero 2W to be a BadUSB | Kitploit
Ferramentas/GitHubGitHub/psycostea/pi-zero-2w-bad-usb
Embedded Systems SecurityExploitationScripting & AutomationHardware HackingCTFPenetration TestingLearning & EducationRed TeamingPayload Development
GitHubpsycostea/pi-zero-2w-bad-usb

Pi-Zero-2W-Bad-USB

Configure your Pi Zero 2W to be a BadUSB

372há 2 mesesRevisado 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
Ver Repositório

Raspberry Pi Zero 2 W BadUSB HID Toolkit

Uma plataforma de ataque BadUSB / HID programável construída em um Raspberry Pi Zero 2 W. O Pi se enumera como um dispositivo USB composto (teclado mais um volume de armazenamento em massa opcional somente leitura) e executa payloads no estilo Ducky-Script contra o host no qual está conectado. Projetado para engajamentos autorizados de red team, testes de penetração e CTFs.

⚠️ Aviso legal. Use apenas em sistemas que você possui ou para os quais possui permissão explícita por escrito para testar. Acesso não autorizado é ilegal na maioria das jurisdições, e fingir que não sabia não vai ajudar.


Índice

  1. Funcionalidades
  2. Como funciona
  3. Hardware
  4. Instalação
  5. Operação diária
  6. Escrevendo payloads
  7. Referência de configuração
  8. Notas de arquitetura
  9. Testes
  10. Solução de problemas
  11. Estrutura do repositório
  12. Créditos

Funcionalidades

  • Payloads de teclas programáveis em um dialeto compatível com Ducky-Script.
  • Detecção confiável de conexão do host através do estado configured do UDC — sem disparos espúrios de payload na inicialização.
  • "Reinicialização entre ataques" que realmente funciona no hardware Pi Zero 2 W. Desconecte, reconecte, dispare novamente — sem necessidade de ciclo de energia.
  • Salvaguardas configuráveis contra loops descontrolados se o dispositivo permanecer conectado: intervalo mínimo entre disparos e limite de taxa de disparos por minuto, ambos sobreponíveis por variáveis de ambiente.
  • Dispositivo de armazenamento em massa composto opcional apoiado por um arquivo de imagem plana (somente leitura por padrão — expor seu cartão SD ao vivo era a velha fonte de corrupção de sistema de arquivos difícil de depurar).
  • Layouts de teclado EUA e Reino Unido selecionáveis por payload com LAYOUT.
  • Variáveis, IF / ELSE, WHILE, HOLD / RELEASE, INJECT_MOD, geradores RANDOM_*, STRING_BLOCK / STRINGLN_BLOCK, DEFINE.
  • Integração com systemd com ExecStop que desmonta o gadget de forma limpa. Sem estado residual do configfs, a reinicialização funciona sem reiniciar.
  • Permissões gerenciadas por udev para /dev/hidg0 — sem nós de dispositivo com permissão de escrita mundial.
  • Conjunto de testes pytest com 34 testes para o parser Ducky, executável em qualquer host sem um Pi conectado.
  • Indicador de status com LED ACT após cada execução de payload.

Como funciona

root@kitploit:~
+----------------+        Cabo USB        +-------------+
|  Raspberry Pi  | ===================>>>  |  PC Host    |
|  Zero 2 W      |   (Pi emula HID +      |  (alvo)     |
|  (este dispositivo)|    unidade opcional)|             |
+----------------+                         +-------------+
        |
        |  /home/pi/pi-badusb/
        |
        +-- badusb.service ----> monitor_and_run.py
                                   |
                                   |  em `state == configured`:
                                   v
                                 run_payload.py
                                   |
                                   v
                                 /dev/hidg0  (gadget HID USB)
  1. Na inicialização, a unidade systemd badusb.service executa gadget_setup.sh, que usa configfs/libcomposite para compor um gadget USB com uma função de teclado HID e (opcionalmente) um LUN de armazenamento em massa apoiado por um arquivo de imagem plana em /var/badusb/storage.img.
  2. Em seguida, a unidade executa monitor_and_run.py. Ele verifica /sys/class/udc/<udc>/state e aguarda o estado configured — o estado USB-spec que significa que um host enumerou o gadget com sucesso. (Nós não usamos a existência de /dev/hidg0 como sinal: isso é verdade no momento em que o gadget se liga ao UDC na inicialização, independentemente de algo estar conectado.)
  3. Quando o host se conecta, o listener executa run_payload.py, que analisa payload.txt e escreve relatórios HID em /dev/hidg0.
  4. Quando o payload termina, o listener desliga ativamente o gadget do UDC (o Pi Zero 2 W não pode detectar desconexão física via software — veja ), dorme um tempo de espera e religa. O dispositivo então aguarda a próxima transição .

Hardware

ComponenteNota
Raspberry Pi Zero 2 WTestado na revisão de hardware de 2026-05. Pi Zero W mais antigo com o driver dwc_otg BCM2835 também funciona em princípio, mas este README assume o 2 W com dwc2.
Cabo micro-USB para USB-AOu um adaptador com formato de "pen drive" que permite ao Pi se conectar diretamente a uma porta do host.
Opcional: carregador separadoSe você quiser alimentar o Pi a partir de uma fonte não host para que o listener possa inicializar antes de ser conectado a um alvo (caso contrário, a porta do host fornece a energia).

O Pi Zero 2 W tem duas portas micro-USB:

  • PWR IN — apenas energia, não expõe linhas de dados USB ao bloco OTG dwc2.
  • USB — a porta de dados OTG; é aqui que você conecta ao alvo.

Software


Instalação

Clone ou copie o repositório para o Pi, então execute o instalador:

root@kitploit:~
git clone http://your-gitea/admin/Pi-Zero-2W-Bad-USB.git /home/pi/pi-badusb
cd /home/pi/pi-badusb
sudo ./install.sh
sudo reboot

Após a reinicialização, habilite e inicie o serviço:

root@kitploit:~
sudo systemctl enable --now badusb.service
journalctl -u badusb -f

install.sh é idempotente — execute-o novamente sempre que alterar os arquivos do projeto. Ele:

  • Detecta /boot/firmware (Bookworm+) vs /boot (mais antigo).
  • Garante que dtoverlay=dwc2,dr_mode=otg esteja ativo sob um bloco [all] em config.txt. Os padrões do Raspberry Pi Imager colocam esta linha dentro de um filtro [cm5] que não se aplica ao Pi Zero 2 W; o instalador anexa uma substituição marcada com sentinela para que execuções repetidas não a dupliquem.
  • Garante que modules-load=dwc2 esteja em cmdline.txt.
  • Avisa se g_ether ainda estiver presente em cmdline.txt (ele rouba o UDC do libcomposite e quebra o modo gadget).
  • Instala a unidade systemd em /etc/systemd/system/badusb.service.
  • Instala a regra udev em /etc/udev/rules.d/99-badusb-hidg.rules para que seja gravável pelo grupo .

Operação diária

root@kitploit:~
# Iniciar / parar / reiniciar
sudo systemctl start badusb
sudo systemctl stop badusb
sudo systemctl restart badusb              # seguro fazer enquanto conectado

# Acompanhar ao vivo
journalctl -u badusb -f

# Desabilitar início automático na inicialização
sudo systemctl disable badusb

# Ajustar temporizações (cria um drop-in de substituição)
sudo systemctl edit badusb
# (cole um bloco [Service] com Environment="BADUSB_REARM_COOLDOWN_S=8" etc.)
sudo systemctl restart badusb

O serviço depende de sys-kernel-config.mount e da presença de um UDC, portanto não pode disparar payloads antes do gadget estar realmente pronto.

Editar o payload não requer reinicialização — payload.txt é lido novamente a cada conexão.


Escrevendo payloads

payload.txt fica no diretório de instalação. A referência completa de comandos está em payload_commands.md.

Exemplo mínimo

root@kitploit:~
REM Abrir diálogo Executar e digitar uma saudação via Bloco de Notas
LAYOUT US
GUI r
DELAY 1500
STRING notepad
ENTER
DELAY 2500
STRINGLN Olá do Pi Zero 2 W

Variáveis, condicionais, loops

root@kitploit:~
VAR $USER="alice"
VAR $COUNT=0
WHILE $COUNT < 3
  STRINGLN Olá $USER (iteração $COUNT)
  VAR $COUNT = $COUNT + 1
END_WHILE

IF $USER == "alice"
  STRINGLN correspondido
ELSE
  STRINGLN não correspondido
END_IF

Expressões matemáticas em VAR passam por um avaliador seguro que percorre a ast — sem nomes, sem chamadas, sem acesso a atributos, apenas literais numéricos e + - * / // % **.

Segurando modificadores

root@kitploit:~
HOLD SHIFT
STRINGLN esta linha está em maiúsculas
RELEASE SHIFT

Enviando combinações arbitrárias de modificadores

root@kitploit:~
REM Segurar Ctrl+Shift (0x01 + 0x02) e pressionar A
INJECT_MOD 0x03
STRING a
REM Liberar todos os modificadores
INJECT_MOD 0x00

Aleatoriedade

root@kitploit:~
RANDOM_LETTER 12      # 12 letras aleatórias maiúsculas/minúsculas
RANDOM_NUMBER 6       # 6 dígitos aleatórios
RANDOM_SPECIAL 4      # 4 símbolos ASCII aleatórios

Layout do teclado

root@kitploit:~
LAYOUT UK             # alternar para mapeamentos ISO do Reino Unido para STRING/STRINGLN subsequentes
STRING @ " # ~ £ \ |  # digita corretamente em um host com locale UK

Coloque outro arquivo em keymaps/ (ao lado de us.py e uk.py) e a diretiva LAYOUT <nome> o capturará via importlib.


Referência de configuração

Gadget de armazenamento em massa (topo de gadget_setup.sh)

Estes podem ser substituídos por invocação, definindo-os no ambiente ao executar gadget_setup.sh manualmente, ou globalmente através das diretivas Environment= da unidade.

Ajustes do Listener (monitor_and_run.py)

Substitua com:

root@kitploit:~
sudo systemctl edit badusb
# No editor:
# [Service]
# Environment="BADUSB_REARM_COOLDOWN_S=8"
# Environment="BADUSB_MIN_INTER_FIRE_S=20"
sudo systemctl restart badusb

Notas de arquitetura

Por que o listener usa o estado do UDC, não /dev/hidg0

A implementação anterior testava a existência + capacidade de escrita de /dev/hidg0 como sinal de "host conectado". Esse nó de dispositivo é criado no momento em que o gadget se liga ao UDC na inicialização — muito antes de qualquer host realmente o ter enumerado. Assim, os payloads eram disparados imediatamente após a energização, independentemente de onde o Pi estava conectado.

O sinal confiável é /sys/class/udc/<udc>/state, que reporta o estado do dispositivo conforme a especificação USB. Apenas configured significa que o host emitiu SetConfiguration(1) — o dispositivo agora está apto a enviar relatórios HID.

Por que forçamos o desligamento após cada payload

Detectar desconexão física no Pi Zero 2 W é impossível via software: a placa não conecta o sense VBUS ao bloco OTG dwc2 do SoC. Após uma desconexão física:

  • /sys/class/udc/<udc>/state permanece em configured.
  • current_speed permanece em high-speed.
  • O registrador dwc2 GOTGCTL permanece em 0x000d0000 (bit BSesVld definido).
  • Nenhum evento udev é disparado.

Então, em vez de esperar por um sinal que nunca virá, o listener ativamente causa a desconexão: após cada payload, ele escreve "" no arquivo UDC do configfs (que o kernel interpreta como desligamento), dorme BADUSB_REARM_COOLDOWN_S, então escreve o nome do UDC de volta para religar. A próxima conexão do host produz uma transição configured limpa que o listener pode detectar.

Se o operador deixar o Pi conectado após um payload, o religamento faz com que o host reenumerie o gadget. Para evitar um loop de disparo descontrolado, duas salvaguardas entram em ação:

  1. BADUSB_MIN_INTER_FIRE_S — se uma transição configured ocorrer dentro desta janela do disparo anterior, suprima-o e desligue novamente. O gadget cicla silenciosamente em segundo plano.
  2. BADUSB_MAX_FIRES_PER_MINUTE — limite máximo com janela deslizante. Acima do limite, o listener pausa por BADUSB_RATELIMIT_PAUSE_S e registra um aviso.

Por que nunca usamos rm -rf no configfs

Os arquivos de atributo gerenciados pelo kernel do configfs (bcdUSB, idVendor, webusb/*, os_desc/*, …) não podem ser removidos por rm(2) — o kernel retorna EPERM. Eles são liberados apenas quando seu diretório pai é removido com rmdir. Tanto gadget_setup.sh quanto teardown_gadget.sh percorrem a árvore configfs na ordem canônica do libcomposite — apenas rmdir, nunca rm em arquivos de atributo — e o kernel limpa o resto automaticamente.

Por que os helpers Python usam os.write e não file.write

Escrever uma string vazia via open(path, "w").write("") não invoca write(2) com zero bytes — o TextIOWrapper do CPython o elimina. Para o desligamento via configfs (que o kernel interpreta a partir de uma escrita de comprimento zero após remover a nova linha), usamos os.write(fd, b"\n") diretamente para que a chamada de sistema seja sempre emitida com pelo menos um byte.


Testes

O parser Ducky possui um conjunto de testes pytest com 34 testes que são executados contra um MockHIDEngine (um substituto em memória para o escritor HID real), portanto não precisa de Pi nem de hardware USB.

root@kitploit:~
cd /home/pi/pi-badusb
python3 -m pytest tests/

A cobertura inclui:

  • safe_eval_math aceitando aritmética, rejeitando nomes / chamadas / acesso a atributos / constantes de string.
  • evaluate_condition para comparações numéricas e de strings com distinção entre maiúsculas/minúsculas.
  • VAR com =, +=, -=, *=, /=.
  • IF / ELSE / END_IF tomando o ramo correto.
  • WHILE / END_WHILE contagens de iteração para < e <=.

Solução de problemas

"O payload nunca dispara quando conectado"

  1. cat /sys/class/udc/*/state — deve atingir configured quando o host enumerar. Se permanecer em not attached, o host não está se comunicando: tente um cabo diferente (alguns são apenas para carga) ou uma porta de host diferente.
  2. lsmod | grep dwc2 — deve estar carregado. Se apenas dwc_otg estiver lá, dtoverlay=dwc2,dr_mode=otg não está sendo aplicado; execute install.sh novamente e reinicie.
  3. journalctl -u badusb -f enquanto conecta — deve mostrar Host attached. Running payload. dentro de ~2s da enumeração do host.

"O payload dispara em loop com o LED piscando, mesmo desconectado"

Este era um bug real que agora foi corrigido. Se acontecer, você reverteu para uma versão anterior ao os.write. Certifique-se de que monitor_and_run.py corresponde ao branch main atual (procure por os.write(fd, payload)).

"O serviço não reinicia — Operation not permitted"

A versão anterior do gadget_setup.sh usava rm -rf no configfs. A versão atual usa teardown_gadget() — se você vir esses erros, tem uma cópia antiga. Reimplante a partir do main.

"Permissão negada em /dev/hidg0"

A regra udev precisa de uma conexão a quente para ser aplicada, ou sudo udevadm trigger e um novo login para que o usuário pi pegue o grupo plugdev.

"Aviso g_ether durante a instalação"

Remova g_ether de cmdline.txt; ele reivindica o UDC antes que libcomposite possa se ligar.

"O host mostra uma unidade USB, mas não do tamanho que eu esperava"

O tamanho do armazenamento em massa é definido por BACKING_SIZE_MB e só entra em vigor na primeira execução quando a imagem de apoio é criada. Para redimensionar:

root@kitploit:~
sudo systemctl stop badusb
sudo rm /var/badusb/storage.img
sudo BACKING_SIZE_MB=256 /home/pi/pi-badusb/gadget_setup.sh
sudo systemctl start badusb

"Quero deixar o Pi conectado sem que ele fique enviando dados para o host"

É para isso que servem BADUSB_MIN_INTER_FIRE_S e BADUSB_MAX_FIRES_PER_MINUTE. Defina-os mais altos via systemctl edit badusb. Com os padrões, um Pi deixado conectado dispara novamente a cada ~15s no primeiro minuto, então pausa por 60s, depois retoma.


Estrutura do repositório

root@kitploit:~
.
├── README.md                   Este arquivo
├── LICENSE                     MIT
├── install.sh                  Instalador idempotente (config do firmware, systemd, udev, plugdev)
├── gadget_setup.sh             Compõe o gadget USB via configfs/libcomposite
├── teardown_gadget.sh          Desmontagem canônica do configfs (configurado como ExecStop)
├── reload_gadget.sh            Helper manual de desligar/religar UDC
├── autorun.sh                  Wrapper de execução manual legado (systemd é preferido)
├── monitor_and_run.py          Listener: aguarda conexão do host, executa payload, força religamento
├── run_payload.py              Interpretador estilo Ducky-Script
├── payload.txt                 Seu payload — edite à vontade; relido a cada conexão
├── payload_commands.md         Referência completa de comandos
├── etc/
│   ├── badusb.service          Unidade systemd
│   └── 99-badusb-hidg.rules    Regra udev para propriedade de /dev/hidg0
├── keymaps/
│   ├── __init__.py             Carregador dinâmico de layout
│   ├── us.py                   US ANSI (padrão)
│   └── uk.py                   UK ISO
└── tests/
    ├── __init__.py
    ├── conftest.py             Configuração de caminho do pytest
    └── test_parser.py          34 testes do parser contra um MockHIDEngine

Créditos

  • Scripts originais do projeto e inspiração: Psycostea.
  • Pesquisa sobre gadget USB: USB Rubber Ducky, Hak5, documentação do libcomposite, o driver do kernel dwc2.
  • Passagem de correção de 2026-05: reescreveu a detecção de conexão do host, tornou o armazenamento em massa seguro, corrigiu vários bugs do parser, adicionou uma abstração de mapa de teclas, migrou a inicialização para systemd, adicionou o harness de testes unitários e contornou a incapacidade em nível de hardware do Pi Zero 2 W de detectar desconexão física.

Licença

MIT — veja LICENSE.

Baixar ferramenta
Notas de arquitetura
configured
RequisitoPor quê
Raspberry Pi OS (Debian Bookworm ou Trixie, 64-bit Lite recomendado)O script de instalação escreve em /boot/firmware/... no Bookworm+ e volta para /boot/... em imagens mais antigas.
Python 3Vem com Pi OS.
mkfs.vfatPara formatar a imagem de apoio do armazenamento em massa na primeira execução. Desative se desabilitar o armazenamento em massa.
Acesso root para configuraçãoMexe com systemd, udev e /boot/firmware/config.txt.
/dev/hidg0
plugdev
  • Adiciona o usuário pi ao grupo plugdev.
  • Cria /var/badusb/ para a imagem de apoio do armazenamento em massa.
  • VariávelPadrãoSignificado
    ENABLE_MASS_STORAGE10 para um gadget apenas HID.
    BACKING_FILE/var/badusb/storage.imgImagem plana exposta ao host.
    BACKING_SIZE_MB64Criada na primeira execução se ausente.
    BACKING_LABELBADUSBRótulo do volume FAT.
    MASS_STORAGE_RO1Somente leitura por padrão.
    Variável de ambientePadrãoSignificado
    BADUSB_POST_PAYLOAD_FLUSH_S0.5Dormir após o payload antes de desvincular para que as escritas HID sejam drenadas.
    BADUSB_REARM_COOLDOWN_S5Quanto tempo o gadget fica invisível para o host entre desvincular e religar.
    BADUSB_MIN_INTER_FIRE_S10Segundos mínimos entre dois disparos de payload; abaixo disso, o disparo é suprimido e o gadget se desvincula novamente.
    BADUSB_MAX_FIRES_PER_MINUTE6Limite máximo; acima disso, pausa por BADUSB_RATELIMIT_PAUSE_S.
    BADUSB_RATELIMIT_PAUSE_S60Duração da pausa após acionamento do limite de taxa.
  • RANDOM_* correção de comprimento; RANDOM_<desconhecido> sem operação + aviso.
  • INJECT_MOD persistência do byte modificador através de teclas subsequentes.
  • HOLD SHIFT capitalizando cada caractere em STRINGLN abc.
  • LAYOUT US vs LAYOUT UK produzindo relatórios diferentes para @ e "; layout desconhecido volta para o anterior.
  • STRING_BLOCK unindo linhas; STRINGLN_BLOCK respeitando recuo mínimo.