Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Pi-Zero-2W-Bad-USB — Configura tu Pi Zero 2W para que sea un BadUSB | Kitploit
Herramientas/GitHubGitHub/psycostea/pi-zero-2w-bad-usb
Seguridad de Sistemas EmbebidosExplotaciónScripting y AutomatizaciónHacking de HardwareCTFPruebas de PenetraciónAprendizaje y EducaciónRed TeamingDesarrollo de Payloads
GitHubpsycostea/pi-zero-2w-bad-usb

Pi-Zero-2W-Bad-USB

Configura tu Pi Zero 2W para que sea un BadUSB

37218hace 3 mesesRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
Ver Repositorio

Raspberry Pi Zero 2 W BadUSB HID Toolkit

Una plataforma de ataque BadUSB / HID programable construida sobre una Raspberry Pi Zero 2 W. La Pi se enumera como un dispositivo compuesto USB (teclado más un volumen de almacenamiento masivo de solo lectura opcional) y ejecuta cargas útiles al estilo Ducky-Script contra el host al que está conectada. Diseñada para pruebas de penetración autorizadas, ejercicios de red-team y CTFs.

⚠️ Aviso legal. Úselo solo en sistemas que posea o para los que tenga permiso explícito por escrito. El acceso no autorizado es ilegal en la mayoría de las jurisdicciones, y fingir que no lo sabía no ayudará.


Tabla de contenido

  1. Características
  2. Cómo funciona
  3. Hardware
  4. Instalación
  5. Operación diaria
  6. Escribir cargas útiles
  7. Referencia de configuración
  8. Notas de arquitectura
  9. Pruebas
  10. Solución de problemas
  11. Estructura del repositorio
  12. Créditos

Características

  • Cargas útiles de pulsaciones de teclas programables en un dialecto compatible con Ducky-Script.
  • Detección confiable de conexión al host a través del estado configured del UDC — sin disparos de carga útil espurios al arrancar.
  • "Reinicio entre ataques" que realmente funciona en hardware Pi Zero 2 W. Desconecte, reconecte, dispare de nuevo — sin ciclo de energía.
  • Salvaguardas configurables contra bucles descontrolados si el dispositivo se deja conectado: intervalo mínimo entre disparos y límite de disparos por minuto, ambos anulables mediante variables de entorno.
  • Dispositivo de almacenamiento masivo compuesto opcional respaldado por un archivo de imagen plana (solo lectura por defecto — exponer la tarjeta SD en vivo era el antiguo problema difícil de depurar de corrupción del sistema de archivos).
  • Distribuciones de teclado US y UK seleccionables por carga útil con LAYOUT.
  • Variables, IF / ELSE, WHILE, HOLD / RELEASE, INJECT_MOD, generadores RANDOM_*, STRING_BLOCK / STRINGLN_BLOCK, DEFINE.
  • Integración con systemd con ExecStop que desmonta el gadget limpiamente. Sin estado residual de configfs, el reinicio funciona sin necesidad de reiniciar el sistema.
  • Permisos gestionados por udev para /dev/hidg0 — sin nodos de dispositivo con escritura mundial.
  • Suite de pruebas pytest de 34 pruebas para el parser Ducky, ejecutable en cualquier host sin Pi conectada.
  • Indicador de estado LED ACT después de cada ejecución de carga útil.

Cómo funciona

root@kitploit:~
+----------------+        Cable USB        +-------------+
|  Raspberry Pi  | ===================>>>  |  PC Host    |
|  Zero 2 W      |   (Pi emula HID +      |  (objetivo) |
|  (este dispositivo)|    unidad opcional)  |             |
+----------------+                         +-------------+
        |
        |  /home/pi/pi-badusb/
        |
        +-- badusb.service ----> monitor_and_run.py
                                   |
                                   |  on `state == configured`:
                                   v
                                 run_payload.py
                                   |
                                   v
                                 /dev/hidg0  (gadget HID USB)
  1. Al arrancar, la unidad systemd badusb.service ejecuta gadget_setup.sh, que utiliza configfs/libcomposite para componer un gadget USB con una función de teclado HID y (opcionalmente) un LUN de almacenamiento masivo respaldado por un archivo de imagen plana en /var/badusb/storage.img.
  2. Luego, la unidad ejecuta monitor_and_run.py. Sondea /sys/class/udc/<udc>/state y espera a configured — el estado de la especificación USB que significa que un host ha enumerado exitosamente el gadget. (NO usamos la existencia de /dev/hidg0 como señal: eso es cierto desde el momento en que el gadget se vincula al UDC en el arranque, independientemente de si hay algo conectado.)
  3. Cuando el host se conecta, el escuchador ejecuta run_payload.py, que analiza payload.txt y escribe informes HID en /dev/hidg0.
  4. Cuando la carga útil finaliza, el escuchador desvincula activamente el gadget del UDC (la Pi Zero 2 W no puede detectar la desconexión física mediante software — consulte ), espera un tiempo de enfriamiento y vuelve a vincular. El dispositivo entonces espera la siguiente transición a .

Hardware

ComponenteNota
Raspberry Pi Zero 2 WProbada en la revisión de hardware de 2026-05. La Pi Zero W más antigua con el controlador dwc_otg BCM2835 también funciona en principio, pero este README asume 2 W con dwc2.
Cable micro-USB a USB-AO un adaptador en formato "stick USB" que permita enchufar la Pi directamente a un puerto host.
Opcional: cargador separadoSi desea alimentar la Pi desde una fuente que no sea el host para que el escuchador pueda arrancar antes de conectarse a un objetivo (de lo contrario, el puerto host suministra la energía).

La Pi Zero 2 W tiene dos puertos micro-USB:

  • PWR IN — solo alimentación, no expone líneas de datos USB al bloque dwc2 OTG.
  • USB — el puerto de datos OTG; aquí es donde se conecta al objetivo.

Software


Instalación

Clone o copie el repositorio en la Pi, luego ejecute el 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

Después del reinicio, habilite e inicie el servicio:

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

install.sh es idempotente — vuelva a ejecutarlo cada vez que cambie archivos del proyecto. Él:

  • Detecta /boot/firmware (Bookworm+) vs /boot (más antiguo).
  • Asegura que dtoverlay=dwc2,dr_mode=otg esté activo bajo un bloque [all] en config.txt. Los valores predeterminados de Raspberry Pi Imager colocan esta línea dentro de un filtro [cm5] que no aplica en Pi Zero 2 W; el instalador agrega una anulación marcada para que las re-ejecuciones no la dupliquen.
  • Asegura que modules-load=dwc2 esté en cmdline.txt.
  • Advierte si g_ether sigue presente en cmdline.txt (roba el UDC de libcomposite y rompe el modo gadget).
  • Instala la unidad systemd en /etc/systemd/system/badusb.service.
  • Instala la regla udev en /etc/udev/rules.d/99-badusb-hidg.rules para que sea escribible por el grupo .

Operación diaria

root@kitploit:~
# Iniciar / detener / reiniciar
sudo systemctl start badusb
sudo systemctl stop badusb
sudo systemctl restart badusb              # seguro hacerlo mientras está conectado

# Ver en vivo
journalctl -u badusb -f

# Deshabilitar inicio automático al arrancar
sudo systemctl disable badusb

# Ajustar tiempos (crea un drop-in de anulación)
sudo systemctl edit badusb
# (pegue un bloque [Service] con Environment="BADUSB_REARM_COOLDOWN_S=8" etc.)
sudo systemctl restart badusb

El servicio depende de sys-kernel-config.mount y la presencia de un UDC, por lo que no puede disparar cargas útiles antes de que el gadget esté realmente listo.

Editar la carga útil no requiere reinicio — payload.txt se lee fresco en cada conexión.


Escribir cargas útiles

payload.txt reside en el directorio de instalación. La referencia completa de comandos está en payload_commands.md.

Ejemplo mínimo

root@kitploit:~
REM Abrir el diálogo Ejecutar y escribir un saludo via Notepad
LAYOUT US
GUI r
DELAY 1500
STRING notepad
ENTER
DELAY 2500
STRINGLN Hola desde la Pi Zero 2 W

Variables, condicionales, bucles

root@kitploit:~
VAR $USER="alice"
VAR $COUNT=0
WHILE $COUNT < 3
  STRINGLN Hola $USER (iteración $COUNT)
  VAR $COUNT = $COUNT + 1
END_WHILE

IF $USER == "alice"
  STRINGLN coincidencia
ELSE
  STRINGLN fallo
END_IF

Las expresiones matemáticas en VAR pasan por un evaluador seguro que recorre ast — sin nombres, sin llamadas, sin acceso a atributos, solo literales numéricos y + - * / // % **.

Mantener modificadores pulsados

root@kitploit:~
HOLD SHIFT
STRINGLN esta línea está en mayúsculas
RELEASE SHIFT

Enviar combinaciones de modificadores arbitrarias

root@kitploit:~
REM Mantener Ctrl+Shift (0x01 + 0x02) y pulsar A
INJECT_MOD 0x03
STRING a
REM Liberar todos los modificadores
INJECT_MOD 0x00

Aleatoriedad

root@kitploit:~
RANDOM_LETTER 12      # 12 letras aleatorias mixtas mayúsculas/minúsculas
RANDOM_NUMBER 6       # 6 dígitos aleatorios
RANDOM_SPECIAL 4      # 4 símbolos ASCII aleatorios

Distribución de teclado

root@kitploit:~
LAYOUT UK             # cambiar a mapeos UK ISO para posteriores STRING/STRINGLN
STRING @ " # ~ £ \ |  # escribe correctamente en un host con configuración regional UK

Coloque otro archivo en keymaps/ (junto a us.py y uk.py) y la directiva LAYOUT <nombre> lo cargará mediante importlib.


Referencia de configuración

Gadget de almacenamiento masivo (al inicio de gadget_setup.sh)

Estas se pueden anular por invocación configurándolas en el entorno al ejecutar gadget_setup.sh manualmente, o globalmente mediante las directivas Environment= de la unidad.

Parámetros ajustables del escuchador (monitor_and_run.py)

Anular con:

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

Notas de arquitectura

Por qué el escuchador usa el estado del UDC, no /dev/hidg0

La implementación anterior probaba la existencia + escritura de /dev/hidg0 como señal de "host conectado". Ese nodo de dispositivo se crea en el momento en que el gadget se vincula al UDC en el arranque — mucho antes de que algún host lo haya enumerado realmente. Así que las cargas útiles se disparaban inmediatamente al encender, independientemente de dónde estuviera conectada la Pi.

La señal confiable es /sys/class/udc/<udc>/state, que informa el estado del dispositivo según la especificación USB. Solo configured significa que el host ha emitido SetConfiguration(1) — el dispositivo ahora es elegible para enviar informes HID.

Por qué forzamos la desvinculación después de cada carga útil

Detectar la desconexión física en la Pi Zero 2 W es imposible desde el software: la placa no conecta VBUS sense al bloque dwc2 OTG del SoC. Después de una desconexión física:

  • /sys/class/udc/<udc>/state permanece en configured.
  • current_speed permanece en high-speed.
  • El registro dwc2 GOTGCTL permanece en 0x000d0000 (bit BSesVld establecido).
  • No se disparan eventos udev.

Entonces, en lugar de esperar una señal que nunca llegará, el escuchador causa activamente la desconexión: después de cada carga útil, escribe "" en el archivo configfs UDC del gadget (que el kernel interpreta como desvinculación), duerme BADUSB_REARM_COOLDOWN_S, luego escribe el nombre del UDC nuevamente para volver a vincular. La siguiente conexión del host produce una transición limpia a configured que el escuchador puede detectar.

Si el operador deja la Pi conectada después de una carga útil, la re-vinculación hace que el host re-enumere el gadget. Para evitar un bucle de disparo descontrolado, entran en juego dos salvaguardas:

  1. BADUSB_MIN_INTER_FIRE_S — si ocurre una transición a configured dentro de esta ventana desde el disparo anterior, suprímelo y vuelve a desvincular. El gadget cicla silenciosamente en segundo plano.
  2. BADUSB_MAX_FIRES_PER_MINUTE — límite duro de ventana deslizante. Por encima del límite, el escuchador pausa durante BADUSB_RATELIMIT_PAUSE_S y registra una advertencia.

Por qué nunca usamos rm -rf en configfs

Los archivos de atributos administrados por el kernel de configfs (bcdUSB, idVendor, webusb/*, os_desc/*, …) no se pueden eliminar con rm(2) — el kernel devuelve EPERM. Se liberan solo cuando su directorio padre es eliminado con rmdir. Tanto gadget_setup.sh como teardown_gadget.sh recorren el árbol configfs en el orden canónico de libcomposite — solo rmdir, nunca rm en archivos de atributos — y el kernel limpia el resto automáticamente.

Por qué los ayudantes Python usan os.write no file.write

Escribir una cadena vacía mediante open(path, "w").write("") no invoca write(2) con cero bytes — el TextIOWrapper de CPython lo omite. Para la desvinculación de configfs (que el kernel interpreta a partir de una escritura de longitud cero después de eliminar el salto de línea), usamos os.write(fd, b"\n") directamente para que la llamada al sistema siempre se emita con al menos un byte.


Pruebas

El parser Ducky tiene una suite de pruebas pytest de 34 pruebas que se ejecuta contra un MockHIDEngine (un reemplazo en memoria para el escritor HID real), por lo que no necesita Pi ni hardware USB.

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

La cobertura incluye:

  • safe_eval_math aceptando aritmética, rechazando nombres / llamadas / acceso a atributos / constantes de cadena.
  • evaluate_condition para comparaciones numéricas y de cadenas sensibles a mayúsculas/minúsculas.
  • VAR con =, +=, -=, *=, /=.
  • IF / ELSE / END_IF tomando la rama correcta.
  • WHILE / END_WHILE contando iteraciones para < y <=.

Solución de problemas

"La carga útil nunca se dispara al conectar"

  1. cat /sys/class/udc/*/state — debe alcanzar configured cuando el host enumera. Si permanece en not attached, el host no está hablando: pruebe con un cable diferente (algunos son solo de carga) o un puerto host diferente.
  2. lsmod | grep dwc2 — debe estar cargado. Si solo está dwc_otg, dtoverlay=dwc2,dr_mode=otg no se está aplicando; vuelva a ejecutar install.sh y reinicie.
  3. journalctl -u badusb -f mientras conecta — debe mostrar Host attached. Running payload. dentro de ~2s de la enumeración del host.

"La carga útil se dispara en bucle con el LED parpadeando, incluso desconectado"

Este fue un error real que ahora está corregido. Si ocurre, ha revertido a una compilación anterior a os.write. Asegúrese de que monitor_and_run.py coincida con la rama main actual (busque os.write(fd, payload)).

"El servicio no se reinicia — Operation not permitted"

Antes de la corrección, gadget_setup.sh usaba rm -rf en configfs. La versión actual usa teardown_gadget() — si ve esos errores, tiene una copia antigua. Vuelva a implementar desde main.

"Permiso denegado en /dev/hidg0"

La regla udev necesita un hot-plug para aplicarse, o sudo udevadm trigger y un nuevo inicio de sesión para que el usuario pi recoja el grupo plugdev.

"Advertencia g_ether durante la instalación"

Elimine g_ether de cmdline.txt; reclama el UDC antes de que libcomposite pueda vincularse.

"El host muestra una unidad USB pero no del tamaño que esperaba"

El tamaño del almacenamiento masivo se establece con BACKING_SIZE_MB y solo tiene efecto en la primera ejecución cuando se crea la imagen de respaldo. 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

"Quiero dejar la Pi conectada sin que spamee al host"

Para eso están BADUSB_MIN_INTER_FIRE_S y BADUSB_MAX_FIRES_PER_MINUTE. Ajústelos más altos mediante systemctl edit badusb. Con los valores predeterminados, una Pi dejada conectada se vuelve a disparar cada ~15s durante el primer minuto, luego pausa 60s, luego reanuda.


Estructura del repositorio

root@kitploit:~
.
├── README.md                   Este archivo
├── LICENSE                     MIT
├── install.sh                  Instalador idempotente (configuración de firmware, systemd, udev, plugdev)
├── gadget_setup.sh             Compone el gadget USB mediante configfs/libcomposite
├── teardown_gadget.sh          Desmontaje canónico de configfs (configurado como ExecStop)
├── reload_gadget.sh            Ayudante manual de desvinculación/re-vinculación del UDC
├── autorun.sh                  Envoltorio de lanzamiento manual heredado (se prefiere systemd)
├── monitor_and_run.py          Escuchador: espera conexión del host, ejecuta carga útil, fuerza rearme
├── run_payload.py              Intérprete de estilo Ducky-Script
├── payload.txt                 Su carga útil — edite libremente; se relee en cada conexión
├── payload_commands.md         Referencia completa de comandos
├── etc/
│   ├── badusb.service          Unidad systemd
│   └── 99-badusb-hidg.rules    Regla udev para la propiedad de /dev/hidg0
├── keymaps/
│   ├── __init__.py             Cargador dinámico de distribuciones
│   ├── us.py                   US ANSI (predeterminado)
│   └── uk.py                   UK ISO
└── tests/
    ├── __init__.py
    ├── conftest.py             Configuración de ruta de pytest
    └── test_parser.py          34 pruebas del parser contra MockHIDEngine

Créditos

  • Scripts e inspiración del proyecto original: Psycostea.
  • Investigación de gadgets USB: USB Rubber Ducky, Hak5, documentación de libcomposite, el controlador del kernel dwc2.
  • Revisión de corrección 2026-05: reescribió la detección de conexión del host, hizo seguro el almacenamiento masivo, corrigió varios errores del parser, agregó una abstracción de mapas de teclado, migró el inicio a systemd, agregó el arnés de pruebas unitarias y solucionó la incapacidad a nivel de hardware de la Pi Zero 2 W para detectar desconexión física.

Licencia

MIT — consulte LICENSE.

Descargar herramienta
Notas de arquitectura
configured
RequisitoPor qué
Raspberry Pi OS (Debian Bookworm o Trixie, 64-bit Lite recomendado)El script de instalación escribe en /boot/firmware/... en Bookworm+ y retrocede a /boot/... en imágenes más antiguas.
Python 3Viene con Pi OS.
mkfs.vfatPara formatear la imagen de respaldo de almacenamiento masivo en la primera ejecución. Deshabilitar si no se usa almacenamiento masivo.
Acceso root para la configuraciónToca systemd, udev y /boot/firmware/config.txt.
/dev/hidg0
plugdev
  • Agrega el usuario pi a plugdev.
  • Crea /var/badusb/ para la imagen de respaldo de almacenamiento masivo.
  • VariableValor por defectoSignificado
    ENABLE_MASS_STORAGE10 para un gadget solo HID.
    BACKING_FILE/var/badusb/storage.imgImagen plana expuesta al host.
    BACKING_SIZE_MB64Creada en la primera ejecución si falta.
    BACKING_LABELBADUSBEtiqueta del volumen FAT.
    MASS_STORAGE_RO1Solo lectura por defecto.
    Variable de entornoValor por defectoSignificado
    BADUSB_POST_PAYLOAD_FLUSH_S0.5Dormir después de la carga útil antes de desvincular para que las escrituras HID drenen.
    BADUSB_REARM_COOLDOWN_S5Cuánto tiempo permanece el gadget oscuro para el host entre desvincular y volver a vincular.
    BADUSB_MIN_INTER_FIRE_S10Segundos mínimos entre dos disparos de carga útil; por debajo, el disparo se suprime y el gadget se desvincula nuevamente.
    BADUSB_MAX_FIRES_PER_MINUTE6Límite duro; por encima, pausa durante BADUSB_RATELIMIT_PAUSE_S.
    BADUSB_RATELIMIT_PAUSE_S60Duración de la pausa después de activar el límite de tasa.
  • RANDOM_* corrección de longitud; RANDOM_<desconocido> sin operación + advertencia.
  • INJECT_MOD persistencia del byte modificador en pulsaciones de tecla posteriores.
  • HOLD SHIFT poniendo en mayúsculas cada carácter en STRINGLN abc.
  • LAYOUT US vs LAYOUT UK produciendo diferentes informes para @ y "; distribución desconocida retrocede a la anterior.
  • STRING_BLOCK uniendo líneas; STRINGLN_BLOCK respetando la sangría mínima.