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
P4wnP1_aloa — P4wnP1 A.L.O.A. de MaMe82 es un framework que convierte una Raspberry Pi Zero W en una plataforma flexible y de bajo costo para pruebas de penetración, operaciones de equipo rojo y compromisos físicos ... o en "Un Pequeño Aparato Ofensivo". | Kitploit
Herramientas/GitHubGitHub/rogandawes/p4wnp1_aloa
Auditoría Wi-FiSeguridad BluetoothFrameworks de ExploitsMapeo de RedesHacking de HardwarePruebas de PenetraciónRed TeamingDesarrollo de Payloads
GitHubrogandawes/p4wnp1_aloa

P4wnP1_aloa

P4wnP1 A.L.O.A. de MaMe82 es un framework que convierte una Raspberry Pi Zero W en una plataforma flexible y de bajo costo para pruebas de penetración, operaciones de equipo rojo y compromisos físicos ... o en "Un Pequeño Aparato Ofensivo".

4.4k58012hace 2 añosRevisado 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

P4wnP1 A.L.O.A.

P4wnP1 A.L.O.A. por MaMe82 es un framework que convierte una Raspberry Pi Zero W en una plataforma flexible y de bajo costo para pentesting, red teaming y compromisos físicos ... o en "A Little Offensive Appliance".

0. Cómo instalar

La imagen más reciente se puede encontrar en la pestaña de versiones (release).

La forma más fácil de acceder a una instalación nueva de P4wnP1 A.L.O.A. es usar el cliente web a través del WiFi generado (la PSK es MaMe82-P4wnP1, la URL http://172.24.0.1:8000) o SSH (contraseña por defecto toor).

1. Características

Emulación de dispositivo USB Plug&Play

  • Funciones USB:
    • USB Ethernet (RNDIS y CDC ECM)
    • USB Serial
    • USB Mass Storage (Flashdrive o CD-Rom)
    • HID Keyboard
    • HID Mouse
  • Reconfiguración en tiempo de ejecución de la pila USB (sin reinicio)
  • La detección de conexión/desconexión permite mantener P4wnP1 A.L.O.A. encendido (alimentación externa) y disparar una acción si el dispositivo USB emulado se conecta a un nuevo host
  • No es necesario lidiar con diferentes interfaces Ethernet internas, ya que CDC ECM y RNDIS están conectados a un puente virtual
  • Almacenamiento y carga persistente de plantillas de configuración para los ajustes USB

HIDScript

  • Reemplazo del limitado DuckyScript
  • Lenguaje de scripting sofisticado para automatizar teclado y ratón
  • Hasta 8 trabajos HIDScript pueden ejecutarse en paralelo (mantener un trabajo para mover el ratón, mientras otros se inician bajo demanda para realizar inyección arbitraria de ratón y teclado sin problemas)
  • HIDScript está basado en JavaScript, con librerías comunes disponibles, lo que permite scripts más complejos (llamadas a funciones, uso de Math para cálculos del ratón, etc.)
  • Teclado
    • Basado en UTF-8, por lo que no hay limitación a caracteres ASCII
    • Puede reaccionar a la retroalimentación del teclado real del huésped leyendo los cambios de estado de los LEDs de NUMLOCK, CAPSLOCK y SCROLLLOCK (si el sistema operativo objetivo comparte el estado de LED entre todos los teclados conectados, lo cual no es el caso para OSX)
    • Tomar decisiones de ramificación en HIDScript, basadas en la retroalimentación de LED
  • Ratón
    • Movimiento relativo (rápido, pero no preciso)
    • Movimiento relativo escalonado (más lento, pero preciso ... mueve el ratón en pasos de 1 DPI)
    • Posicionamiento absoluto en Windows (pixel perfect si se conocen las dimensiones de la pantalla del objetivo)
  • El teclado y el ratón no solo están controlados por el mismo lenguaje de scripting, ambos pueden usarse en el mismo script. Esto permite combinarlos para lograr objetivos que no podrían alcanzarse usando solo teclado o ratón.
  • Diseños de idioma actuales: br, de, es, fr, gb, it, ru y us

Bluetooth

  • Interfaz completa con la pila Bluez (actualmente sin soporte para descubrimiento/conexión remota de dispositivos)
  • Permite ejecutar un Punto de Acceso de Red Bluetooth (NAP)
  • Emparejamiento personalizable (modo heredado basado en PIN o SSP)
  • Soporte de Alta Velocidad (usa tramas 802.11 para lograr tasas de transferencia similares a WiFi)
  • Reconfiguración en tiempo de ejecución de la pila Bluetooth
  • Nota: PANU también es posible, pero actualmente no está soportado (sin conexión remota de dispositivos)
  • Almacenamiento y carga persistente de plantillas de configuración para los ajustes Bluetooth

WiFi

  • Firmware modificado (construido con el framework Nexmon)
    • Permite KARMA (suplantar respuestas válidas para Puntos de Acceso probados por dispositivos remotos y permitir la asociación)
    • Difundir balizas adicionales (Beacons) para emular múltiples SSID
    • Canal encubierto WiFi
    • Nota: El modo monitor heredado de Nexmon está incluido, pero no es soportado por P4wnP1. El modo monitor sigue siendo inestable y probablemente provocará un fallo del firmware si la configuración cambia.
  • Configuración fácil del Punto de Acceso
  • Configuración fácil del modo Estación (conectarse a un AP existente)
  • Modo de conmutación por error (si no es posible conectarse al Punto de Acceso objetivo, levantar un Punto de Acceso propio)
  • Reconfiguración en tiempo de ejecución de la pila WiFi
  • Almacenamiento y carga persistente de plantillas de configuración para los ajustes WiFi

Redes

  • Configuración sencilla de la interfaz Ethernet para
    • interfaz Bluetooth NAP
    • interfaz USB (si RNDIS/CDC ECM está habilitado)
    • interfaz WiFi
  • Soporta servidor DHCP dedicado por interfaz
  • Soporte para modo cliente DHCP
  • Configuración manual
  • Almacenamiento y carga persistente de plantillas de configuración para cada interfaz

Herramientas (Tooling)

No hay mucho que decir aquí, P4wnP1 A.L.O.A. está respaldado por KALI Linux, por lo que todo debería estar a tu alcance (o se puede instalar usando apt)

Configuración y Control vía CLI, de forma remota si es necesario

  • Todas las funciones mencionadas hasta ahora se pueden configurar usando un cliente CLI
  • El servicio central de P4wnP1 es un único binario, que se ejecuta como una unidad systemd que preserva el estado en tiempo de ejecución
  • El cliente CLI se comunica con este servicio mediante RPC (gRPC para ser específicos) para cambiar el estado del núcleo
  • Como el CLI utiliza un enfoque RPC, también puede usarse para configuración remota
  • Si se accede a P4wnP1 vía SSH, el cliente CLI está allí, esperando tus comandos (o tu kung fu de autocompletado por tabulación)
  • El CLI está escrito en Go (como la mayor parte del código) y por lo tanto compila para la mayoría de las plataformas y arquitecturas principales

Así que si quieres usar un archivo por lotes ejecutándose en un host Windows remoto para configurar P4wnP1 ... no hay problema:

  1. Compila el cliente para Windows
  2. Asegúrate de poder conectarte a P4wnP1 de alguna manera (Bluetooth, WiFi, USB)
  3. Añade el parámetro host a tus comandos del cliente
  4. ... y usa el CLI como lo harías con acceso local.

Configuración y Control vía cliente web

Aunque no estaba planeado inicialmente, P4wnP1 A.L.O.A. se puede configurar usando un webclient. Aunque el cliente no estaba planeado, evolucionó hasta convertirse en una pieza de software agradable. De hecho, terminó siendo la principal herramienta de configuración para P4wnP1 A.L.O.A. El webclient tiene capacidades que no se pueden acceder desde el CLI (almacenamiento de plantillas, creación de "TriggerActions").

Las características principales:

  • Debería funcionar en la mayoría de los navegadores móviles y de escritorio, con una apariencia y sensación consistentes (Quasar Framework)
  • Usa gRPC a través de websockets (sin API RESTful, sin XHR, casi el mismo enfoque que CLI)
  • Gracias a esta interfaz, el webclient no solo depende de un esquema de solicitud y respuesta, sino que recibe "eventos push" del núcleo de P4wnP1. Esto significa:
    • Si tú (o un script) cambias el estado de P4wnP1 A.L.O.A., estos cambios se reflejarán inmediatamente en el webclient
    • Si tienes varios webclients ejecutándose, los cambios del estado del núcleo se reflejarán de un cliente a todos los demás clientes
  • Incluye un editor de HIDScript, con
    • resaltado de sintaxis
    • autocompletado (CTRL+SPACE)
    • almacenamiento y carga persistente de HIDScripts
    • ejecución bajo demanda de HIDScript directamente desde el navegador
    • un administrador de trabajos HIDScript (cancelar trabajos en ejecución, inspeccionar estado y resultados del trabajo)
  • Incluye una visión general y editor para TriggerActions
  • Soporte completo de plantillas para todas las funciones descritas hasta ahora
  • El WebClient es una Aplicación de Página Única, una vez cargado todo se ejecuta del lado del cliente, solo se intercambian solicitudes gRPC

Automatización

El enfoque de automatización de la versión anterior de P4wnP1 (scripts bash estáticos) ya no se podía utilizar.

El enfoque de automatización de P4wnP1 A.L.O.A. tenía que cumplir estos requisitos:

  • Fácil de usar y entender
  • Utilizable desde un webclient
  • Ser genérico y flexible, al mismo tiempo
  • Todo lo que se podía hacer con el antiguo enfoque de "script bash", todavía debería ser posible
  • Poder acceder a todos los subsistemas (USB, WiFi, Bluetooth, Interfaces Ethernet, HIDScript ... )
  • Modular, con partes reutilizables
  • Capacidad para soportar tareas lógicas (simples) sin escribir código adicional
  • Permitir computación física, utilizando los puertos GPIO

Con la introducción de las llamadas "TriggerActions" y combinándolas con el sistema de plantillas (almacenamiento persistente de ajustes para todos los subsistemas) se pudieron satisfacer todos los requisitos. Los detalles sobre TriggerActions se pueden encontrar en la sección WorkFlow.

Tutorial de uso

2. Flujo de trabajo parte 1 - HIDScript

P4wnP1 A.L.O.A. no utiliza conceptos como configuración estática o payloads. De hecho, no tiene ningún flujo de trabajo estático.

P4wnP1 A.L.O.A. está diseñado para ser lo más flexible posible, para permitir su uso en todos los escenarios posibles (incluyendo aquellos que no pude imaginar mientras creaba P4wnP1 A.L.O.A.).

Pero hay algunos conceptos básicos que me gustaría repasar en esta sección. Como es difícil explicarlo todo sin crear una documentación (en video) adecuada, visitaré algunos casos de uso comunes y ejemplos para explicar lo que necesita ser explicado.

Sin embargo, es poco probable que tenga tiempo para proporcionar una documentación completa. Así que animo a todos a apoyarme con tutoriales e ideas, que podrían enlazarse de vuelta a este README

Ahora comencemos con una de las tareas más básicas:

2.1 Ejecutar una inyección de pulsaciones de teclas contra un host que tenga P4wnP1 conectado vía USB

El requisito de configuración mínimo para lograr este objetivo es:

  • El subsistema USB está configurado para emular al menos un teclado
  • Existe una forma de acceder a P4wnP1 (de forma remota), para iniciar la inyección de pulsaciones de teclas

La configuración predeterminada de P4wnP1 (imagen sin modificar) ya cumple estos requisitos:

  • Los ajustes USB están inicializados para proporcionar teclado, ratón y ethernet sobre USB (ambos, RNDIS y CDC ECM)
  • P4wnP1 ya se puede acceder de forma remota, utilizando uno de los siguientes métodos:
    • WiFi
      • El nombre del Punto de Acceso debería ser obvio
      • la contraseña es MaMe82-P4wnP1
      • la IP de P4wnP1 es 172.24.0.1
    • USB Ethernet
      • la IP de P4wnP1 es 172.16.0.1
    • Bluetooth
      • nombre del dispositivo P4wnP1
      • PIN 1337
      • la IP es 172.26.0.1
      • Nota: Secure Simple Pairing está DESACTIVADO para forzar el emparejamiento por PIN. Esto significa nuevamente que el modo de alta velocidad está desactivado también. Por lo tanto, la conexión Bluetooth es muy lenta, lo cual es menos problemático para el acceso SSH, pero solicitar el webclient podría tomar hasta 10 minutos (en contraste con algunos segundos con alta velocidad habilitada).
  • Un servidor SSH es accesible desde todas las IPs mencionadas
  • El usuario SSH para KALI Linux es root, la contraseña por defecto es toor
  • El webclient se puede alcanzar a través de las tres conexiones en el puerto 8000 vía HTTP

Nota: Implementar una conexión HTTPS actualmente no está dentro del alcance del proyecto. Así que ten esto en cuenta si manejas datos sensibles, como credenciales WiFi, en el webclient. Todo el proyecto no está construido con seguridad en mente (y es poco probable que esto se convierta en un requisito). Por lo tanto, despliega medidas apropiadas (por ejemplo, restringir el acceso al webclient con iptables, si el Punto de Acceso está configurado con Autenticación Abierta; no mantengas la Discoverabilidad y Conectividad Bluetooth habilitadas sin protección PIN, etc. etc.)

En este punto asumo:

  1. Has conectado P4wnP1 a algún host objetivo vía USB (el puerto micro USB más interno de la Raspberry es el que se debe usar)
  2. El host USB ejecuta una aplicación que puede recibir las pulsaciones de teclas y tiene el foco de entrada del teclado actual (por ejemplo, un editor de texto)
  3. Estás conectado remotamente a P4wnP1 vía SSH (la mejor manera es WiFi), preferiblemente la conexión SSH se ejecuta desde un host diferente al que tiene P4wnP1 A.L.O.A. conectado vía USB

Para ejecutar el cliente CLI desde la sesión SSH, emite el siguiente comando:``` root@kali:~# P4wnP1_cli The CLI client tool could be used to configure P4wnP1 A.L.O.A. from the command line. The tool relies on RPC so it could be used remotely.

Version: v0.1.0-alpha1

Usage: P4wnP1_cli [command]

Available Commands: db Database backup and restore evt Receive P4wnP1 service events help Help about any command hid Use keyboard or mouse functionality led Set or Get LED state of P4wnP1 net Configure Network settings of ethernet interfaces (including USB ethernet if enabled) system system commands template Deploy and list templates trigger Fire a group send action or wait for a group receive trigger usb USB gadget settings wifi Configure WiFi (spawn Access Point or join WiFi networks)

Flags: -h, --help help for P4wnP1_cli --host string The host with the listening P4wnP1 RPC server (default "localhost") --port string The port on which the P4wnP1 RPC server is listening (default "50051")

Use "P4wnP1_cli [command] --help" for more information about a command.

root@kitploit:~
La pantalla de ayuda ya muestra que el cliente CLI utiliza diferentes comandos para interactuar con los diversos subsistemas de 
P4wnP1 A.L.O.A. La mayoría de estos comandos tienen sus propios subcomandos, nuevamente. La ayuda para cada comando o subcomando se puede 
acceder agregando `-h` al comando CLI:```
root@kali:~# P4wnP1_cli hid run -h
Run script provided from standard input, commandline parameter or by path to script file on P4wnP1

Usage:
  P4wnP1_cli hid run [flags]

Flags:
  -c, --commands string      HIDScript commands to run, given as string
  -h, --help                 help for run
  -r, --server-path string   Load HIDScript from given path on P4wnP1 server
  -t, --timeout uint32       Interrupt HIDScript after this timeout (seconds)

Global Flags:
      --host string   The host with the listening P4wnP1 RPC server (default "localhost")
      --port string   The port on which the P4wnP1 RPC server is listening (default "50051")

Ahora, para escribir "Hello world" al host USB, se podría usar el siguiente comando CLI:

P4wnP1_cli hid run -c 'type("Hello world")'

La salida resultante en la sesión SSH debería verse similar a esto:``` TempFile created: /tmp/HIDscript295065725 Start appending to 'HIDscript295065725' in folder 'TMP' Result: null

root@kitploit:~
En el host USB, se debería haber escrito "Hello World" en la aplicación con el foco del teclado.

*Si tu cliente SSH se ejecuta en el propio host USB, el "Hello world" escrito termina en algún lugar entre la salida resultante 
del comando CLI (no pertenece a la salida, sino que se ha escrito entre medio).*

**Objetivo logrado. Inyectamos pulsaciones de teclas en el objetivo.**
 
Mucha lectura para una tarea simple como la inyección de pulsaciones de teclas, pero de nuevo, esta sección tiene la intención de explicar conceptos básicos.

### 2.2 Pasando a características de lenguaje más sofisticadas de HIDScript

Si lograste ejecutar la inyección de pulsaciones de teclas "Hello world", este es un buen punto para explorar algunas características adicionales de HIDScript.

Ya conocemos el comando `type`, pero intentemos discutir algunos comandos HIDScript más sofisticados:

#### Pulsando teclas especiales y combinaciones

El comando `type` soporta presionar retorno, codificando un carácter de "nueva línea" en la cadena de entrada, así:```
P4wnP1_cli hid run -c 'type("line 1\nline 2\nline 3 followed by pressing RETURN three times\n\n\n")'

Pero, ¿qué pasa con las teclas especiales o combinaciones de teclas?

¡El comando press viene al rescate!

Usemos press para enviar CTRL+ALT+DELETE al host USB:``` P4wnP1_cli hid run -c 'press("CTRL ALT DELETE")'

root@kitploit:~
*Nota: Dos de las teclas han sido modificadores (CTRL y ALT) y solo una ha sido una tecla real (DELETE)*

Pulsemos la tecla 'A' sin ninguna tecla modificadora:```
P4wnP1_cli hid run -c 'press("A")'

El resultado debería ser una 'a' minúscula, porque press("A") interpreta 'A' como tecla. El comando type("A"), por otro lado, intenta presionar una combinación de teclas que debería dar como resultado un carácter de salida 'A' mayúscula.

Combinemos un modificador y una tecla no modificadora para producir un carácter de salida 'A' mayúscula (imitando el comportamiento de type("A"):``` P4wnP1_cli hid run -c 'press("SHIFT A")'

root@kitploit:~
Esto debería haber producido una salida de A mayúscula.

Es importante entender que `press` interpreta sus argumentos de tecla como teclas, mientras que `type` intenta encontrar las
combinaciones de teclas apropiadas para producir los caracteres de salida deseados.   

En un último ejemplo, combinemos `press` y `type`.```
P4wnP1_cli hid run -c 'type("before caps\n"); press("CAPS"); type("after caps\n"); press("CAPS");'

El último comando escribió una cadena, activó BLOQ MAYÚS, escribió otra cadena y desactivó BLOQ MAYÚS nuevamente. Como resultado, BLOQ MAYÚS debería estar en su estado inicial (alternado dos veces), pero una de las cadenas se escribe en mayúsculas y la otra en minúsculas, aunque ambas cadenas se han dado en minúsculas.

Notas adicionales sobre las pulsaciones de teclas con press:

No quiero profundizar en el funcionamiento interno de los informes de teclado USB, pero vale la pena mencionar algunas cosas para delimitar los límites y posibilidades del comando press (que en sí mismo funciona basándose en informes de teclado sin procesar):

  • un informe de teclado puede contener hasta 8 teclas modificadoras a la vez
  • las teclas modificadoras son
    • LEFT_CTRL
    • RIGHT_CTRL
    • LEFT_ALT
    • RIGHT_ALT
    • LEFT_SHIFT
    • RIGHT_SHIFT
    • LEFT_GUI
    • RIGHT_GUI
  • P4wnP1 permite usar alias para los modificadores comunes
    • CTRL == CONTROL == LEFT_CTRL
    • ALT == LEFT_ALT
    • SHIFT == LEFT_SHIFT
    • WIN == GUI == LEFT_GUI
  • además de los modificadores, press consume hasta seis teclas normales o especiales
    • las teclas normales representan caracteres y teclas especiales
    • ejemplos de teclas especiales: BACKSPACE, ENTER (== RETURN), F1 .. F12)
    • las teclas son independientes de la distribución del idioma (press("Z") da como resultado USB_KEY_Z para la distribución de teclado EN_US, pero produce USB_KEY_Y para una distribución alemana. Esto corresponde a presionar la tecla física 'Z' en un teclado alemán, que también produciría USB_KEY_Y).
    • /usr/local/P4wnP1/keymaps/common.json contiene un mapa de teclas JSON formateado con todas las teclas posibles (ten cuidado de no modificar el archivo)
  • agregar varias teclas a un solo comando press no produce una secuencia de teclas. Todas las teclas dadas se presionan al mismo tiempo y se liberan al mismo tiempo.
  • press libera las teclas automáticamente, lo que significa que una secuencia como "mantener presionado ALT, presionar TAB, presionar TAB, soltar ALT" actualmente no es posible

Distribución del teclado

El comando HIDScript para cambiar la distribución del teclado es layout(<nombre del mapa de idioma>).

El siguiente ejemplo cambia la distribución del teclado a 'US', escribe algo y cambia la distribución a 'German' antes de continuar escribiendo:``` P4wnP1_cli hid run -c 'layout("us"); type("Typing with EN_US layout\n");layout("de"); type("Typing with German layout supporting special chars üäö\n");'

root@kitploit:~
El resultado de salida del comando anterior depende de la distribución del teclado objetivo utilizada por el host USB. En un host con distribución de teclado alemán, el resultado se ve así:```
Tzping with EN?US lazout
Typing with German layout supporting special chars üäö

En un host con distribución de teclado US se ve así:``` Typing with EN_US layout Tzping with German lazout supporting special chars [';

root@kitploit:~
Tenga en cuenta que el resultado previsto solo se logra si la distribución del teclado de P4wnP1 coincide con la distribución del teclado realmente utilizada por el host USB. El comando `layout` permite alinear la distribución interna de P4wnP1 con la del host USB objetivo. Poder cambiar la distribución en medio de un HIDScript en ejecución podría resultar útil: ¿Quién sabe? Tal vez desee forzar por fuerza bruta la distribución del teclado del host objetivo emitiendo comandos con distribuciones cambiantes hasta que uno de los comandos escritos logre el efecto deseado. **Importante:** La distribución tiene un efecto global. Esto significa que si se ejecutan varios HIDScripts de forma concurrente y uno de ellos establece una nueva distribución, todos los demás scripts se ven afectados de inmediato también.

#### Velocidad de escritura

Por defecto, P4wnP1 inyecta pulsaciones de teclas lo más rápido posible. Dependiendo de su objetivo, esto podría ser demasiado (piense en contramedidas que evitan la inyección de pulsaciones basándose en el análisis del comportamiento de la velocidad de escritura). HIDScript admite un comando para cambiar este comportamiento.

`typingSpeed(delayMillis, jitterMillis)`

El primer argumento del comando `typingSpeed` representa un retardo constante en milisegundos, que se aplica entre dos pulsaciones de teclas. El segundo argumento es una fluctuación adicional en milisegundos. Agrega un retardo aleatorio adicional, que varía entre 0 y la fluctuación dada en milisegundos, al retardo estático proporcionado con el primer argumento.

Intentemos usar `typingSpeed` para ralentizar la escritura:```
P4wnP1_cli hid run -c 'typingSpeed(100,0); type("Hello world")'

A continuación, en lugar de un retardo constante, probamos un jitter aleatorio:``` P4wnP1_cli hid run -c 'typingSpeed(0,500); type("Writing with random jitter up to 500 milliseconds")'

root@kitploit:~
Finalmente, combinando y ajustando ambos valores, podríamos simular una velocidad de escritura natural:```
P4wnP1_cli hid run -c 'typingSpeed(100,150); type("Writing with more natural speed")'

Importante: La velocidad de escritura tiene un efecto global. Esto significa que si hay múltiples HIDScripts ejecutándose concurrentemente y uno de los scripts establece una nueva velocidad de escritura, todos los demás scripts se ven afectados inmediatamente también.

Esperar el informe de LED

Esperar el informe de LED, o para ser precisos los cambios de estado de LED, es una de las características de teclado más sofisticadas de HIDScript. Podría ser muy potente pero necesita un poco de explicación.

Puede que hayas notado que (dependiendo del SO del host USB) los modificadores de estado del teclado (NUM LOCK, SCROLL LOCK, CAPS LOCK) se comparten entre varios teclados conectados. Por ejemplo, si conectas dos teclados a un host Windows y alternas CAPS LOCK en uno de ellos, el LED de CAPS LOCK cambia en ambos teclados.

Exactamente esta prueba podría usarse para determinar si los modificadores de estado del teclado se comparten entre todos los teclados para un SO determinado.

En caso de que un host USB soporte este tipo de compartición de estado (por ejemplo Windows lo hace), el lenguaje HIDScript de P4wnP1 podría hacer uso de ello.

Imagina el siguiente escenario:

P4wnP1 está conectado a un host USB y quieres aplicar inyección de pulsaciones, pero no quieres que el HIDScript ejecute las pulsaciones inmediatamente. En lugar de eso, el HIDScript debería esperar hasta que pulses NUMLOCK, CAPSLOCK o SCROLLLOCK en el teclado real del host. ¿Por qué? Quizás estás en un compromiso, alguien entró y no quieres que ese "alguien" vea cómo mágicamente se teclean una gran cantidad de caracteres en una ventana de consola que apareció de repente. Así que esperas hasta que "alguien" salga, pulsas NUM LOCK y finalmente aparece una ventana de consola y una gran cantidad de caracteres se teclean mágicamente... Creo que lo has entendido.

El comportamiento descrito podría lograrse así:``` P4wnP1_cli hid run -c 'waitLED(NUM); type("A huge amount of characters\n")'

root@kitploit:~
Si probaste el comando anterior, la escritura solo debería comenzar si la tecla BLOQ NUM está presionada en el teclado físico del host USB, pero es posible que encuentres casos donde las pulsaciones de teclas se emitan de inmediato, incluso si BLOQ NUM no fue presionado (y el LED del teclado no ha cambiado).

Este comportamiento es intencional y la razón es otro caso de uso para el comando `waitLED`:

Quizás hayas usado otros lenguajes de scripting de teclado y otros dispositivos USB capaces de inyectar pulsaciones de teclas anteriormente. La mayoría de estos dispositivos comparten un problema común: ¡No sabes cuándo empezar a escribir!

Si comienzas a escribir inmediatamente después de que el dispositivo USB se enciende, es probable que el host USB no haya terminado la enumeración del dispositivo y, por lo tanto, no haya logrado activar los controladores del teclado. En última instancia, tus pulsaciones de teclas se pierden.

Para superar esto, podrías agregar un retraso antes de que comience la inyección de pulsaciones. ¿Pero cuánto tiempo debería ser ese retraso? ¿Cinco segundos, 10 segundos, 30 segundos?

La respuesta es: ¡depende! Depende de qué tan rápido el host pueda enumerar el dispositivo y activar el controlador del teclado. De hecho, no podrías saber cuánto tiempo toma esto sin probar contra el objetivo real.

Pero como ya hemos aprendido, los sistemas operativos como Windows comparten el estado de los LED entre varios teclados. Esto significa que si el LED de BLOQ NUM del teclado del host está configurado como ENCENDIDO antes de conectar un segundo teclado, el LED de BLOQ NUM en este nuevo teclado también debe configurarse como ENCENDIDO una vez conectado. Si el LED de BLOQ NUM se hubiera configurado en APAGADO, de todos modos, el teclado recién conectado recibe el estado del LED (todos los LED apagados en este caso). Lo interesante de esto es que esta "actualización del LED" solo podría enviarse desde el host USB al teclado conectado si el controlador del teclado ha terminado de cargarse (de lo contrario, no sería posible enviar el estado del LED).

¿No es hermoso? El host USB nos dice: "Estoy listo para recibir pulsaciones de teclas". No hay necesidad de jugar con retrasos iniciales.

Pero aquí hay otro problema: Supongamos que conectamos P4wnP1 a un host USB. Ejecutamos un HIDScript que comienza con `waitLED` en lugar de un retraso hecho a mano. La escritura comienza después del `waitLED`, ¡pero no pasa nada! De todos modos, nuestras pulsaciones de teclas se pierden. ¿Por qué? Porque es probable que hayamos perdido la actualización del estado del LED, ya que llegó antes de que siquiera iniciáramos nuestro HIDScript.

Exactamente esta "condición de carrera" es la razón por la cual P4wnP1 conserva todos los cambios de estado del LED reconocidos, a menos que al menos un HIDScript los consuma llamando a `waitLED` (o `waitLEDRepeat`). Esto podría resultar en el comportamiento descrito anteriormente, donde un `waitLED` regresa de inmediato, aunque no haya ocurrido ningún cambio de LED. Ahora sabemos: El cambio de LED efectivamente ocurrió, pero podría haber sucedido mucho antes (antes de que siquiera iniciáramos el HIDScript), porque el cambio de estado se conservó. También sabemos que este comportamiento es necesario para evitar perder cambios de estado del LED, en caso de que se use `waitLED` para probar la "disponibilidad del controlador del teclado del host USB".

*Nota: Vale la pena mencionar que `waitLED` regresa SOLO si el estado del LED recibido difiere del estado interno de P4wnP1. Esto significa que, incluso si escuchamos un cambio en cualquier LED con `waitLED(ANY)`, aún podría suceder que recibamos un estado inicial del LED de un host USB que no difiera del estado interno de P4wnP1. En este caso, `waitLED(ANY)` se bloquearía para siempre (o hasta que ocurra un cambio real de LED). Este caso especial podría manejarse llamando a `waitLED(ANY_OR_NONE)`, que regresa tan pronto como llega un nuevo estado del LED, incluso si no resulta en un cambio.*

**Suficiente explicación, pasemos a la práctica... antes de hacerlo, tenemos que cambiar un poco la configuración del hardware:**

Conecta una fuente de alimentación externa al segundo puerto USB de la Raspberry Pi Zero (el exterior). Esto asegura que P4wnP1 no pierda energía cuando se desconecte del host USB, ya que ya no depende de la energía del bus. El puerto USB que debe usarse para conectar P4wnP1 al host USB objetivo es el más interno de los dos puertos.

Ahora, inicia el siguiente HIDScript``` 
P4wnP1_cli hid run -c 'while (true) {waitLED(ANY);type("Attached\n");}'

Desconecte P4wnP1 del host USB (¡y asegúrese de que permanezca encendido)! Vuelva a conectarlo al host USB... Cada vez que vuelva a conectar P4wnP1 al host, debería escribirse "Adjuntado" en el host.

Esto nos enseñó 3 hechos:

  1. waitLED podría usarse como comando inicial en scripts, para comenzar a escribir tan pronto como el controlador de teclado esté listo.
  2. waitLED no es la elección perfecta para pausar scripts HID hasta que se presione una tecla que cambie el LED en el host USB, ya que los cambios de estado preservados podrían desbloquear el comando de forma no deseada.
  3. Proporcionar HIDScript más complejo como parámetro a la CLI no es muy conveniente.

Como aún no hemos terminado con el comando waitLED, ahora nos ocupamos del tercer hecho. Salgamos de la CLI.

  • termine la CLI de P4wnP1 con CTRL+C (en caso de que el script HID en bucle aún se esté ejecutando)
  • abra un navegador en el host que ha estado usando para la conexión SSH a P4wnP1 (no el host USB)
  • se puede acceder al cliente web a través de la misma IP que el servidor SSH, el puerto es 8000 (para WiFi http://172.24.0.1:8000)
  • navegue a la pestaña "HIDScript" en el cliente web ahora abierto
  • desde allí puede cargar y almacenar scripts HID (no lo hacemos ahora, aunque ms_snake.js es un muy buen ejemplo del poder de los disparadores basados en LED)

Reemplace el script en la ventana del editor con el siguiente:``` return waitLED(ANY);

root@kitploit:~
Después de presionar un botón de ejecución, el lado derecho de la ventana debería mostrar un nuevo trabajo HID en ejecución. Si presiona el pequeño 
botón "info" a la derecha del trabajo HIDScript, podría ver detalles, como su estado (debería estar ejecutándose), el ID del trabajo
y el ID de la VM (este es el número de la máquina virtual JavaScript que ejecuta este trabajo. Hay 8 de estas VM, por lo que 8 HIDScripts podrían
ejecutarse en paralelo).

Ahora, si se emite algún cambio de LED desde el host USB (alternando NUM, CAPS o SCROLL), el trabajo HIDScript debería finalizar. 
Aún se puede encontrar en los trabajos "Succeeded".

Si presiona nuevamente el pequeño botón "info", debería haber información sobre el valor del resultado (codificado como JSON),
que se ve algo así:```
{"ERROR":false,"ERRORTEXT":"","TIMEOUT":false,"NUM":true,"CAPS":false,"SCROLL":false,"COMPOSE":false,"KANA":false}

Entonces el comando waitLED devuelve un objeto JavaScript que se ve así:``` { ERROR: false, // gets true if an error occurred (f.e. HIDScript was aborted, before waitLED could return)
ERRORTEXT: "", // corresponding error string TIMEOUT: false, // gets true if waitLED timed out (more on this in a minute) NUM: true, // gets true if NUM LED had changed before waitLED returned CAPS: false, // gets true if CAPS LED had changed before waitLED returned SCROLL: false, // gets true if SCROLL LED had changed before waitLED returned COMPOSE: false, // gets true if COMPOSE LED had changed before waitLED returned (uncommon) KANA: false // gets true if KANA LED had changed before waitLED returned (uncommon) }

root@kitploit:~
En mi caso, `NUM` se volvió verdadero. En tu caso quizás fue `CAPS`. No importa cuál LED fue. "Lo que importa es 
el hecho de que el valor de retorno da la oportunidad de examinar el cambio de LED que hace que el comando retorne y así
podría usarse para tomar decisiones de bifurcación en tu HIDScript (basadas en cambios de estado de LED emitidos por el teclado real del host USB).

Probemos un ejemplo:```
while (true) {
 result = waitLED(ANY);
 if (result.NUM) {
   type("NUM has been toggled\n");
 }
 if (result.SCROLL) {
   type("SCROLL has been toggled\n");
 }
 if (result.CAPS) {
   break; //exit loop
 }
}

Suponiendo que el script dado ya está ejecutándose, presionar NUM en el host USB debería resultar en escribir "NUM ha sido alternado", mientras que presionar SCROLL LOCK resulta en el texto escrito "SCROLL ha sido alternado". Este comportamiento se repite, hasta que se presiona CAPS LOCK y el cambio de LED resultante aborta el bucle y finaliza el HIDScript.

Puf... un montón de texto sobre este comando para un solo comando HIDScript, pero aún quedan algunas cosas.

Proporcionamos argumentos como NUM, ANY o ANY_OR_NONE al comando waitLED, sin más explicación.

El comando waitLED acepta hasta dos argumentos:

El primer argumento, como habrás adivinado, es un filtro de lista blanca para los LEDs a observar. Los argumentos válidos son:

  • ANY (reaccionar a un cambio en cualquiera de los LEDs)
  • ANY_OR_NONE (reaccionar a cada nuevo estado del LED, incluso si no hay cambio)
  • NUM (ignorar todos los cambios de LED, excepto en el LED NUM)
  • CAPS (ignorar todos los cambios de LED, excepto en el NUM CAPS)
  • SCROLL (ignorar todos los cambios de LED, excepto en el NUM SCROLL)
  • varios filtros se pueden combinar así CAPS | NUM, NUM | SCROLL

El segundo argumento, que no hemos usado hasta ahora, es una duración de tiempo de espera en milisegundos. Si no ocurre ningún cambio de LED durante esta duración de tiempo de espera, waitLED regresa y tiene TIMEOUT: true establecido en el objeto resultante (además, ERROR se establece en true y ERRORTEXT indica un tiempo de espera agotado).

El siguiente comando esperaría un cambio en el LED NUM, pero aborta la espera después de 5 segundos:``` waitLED(NUM,5000)

root@kitploit:~
Aunque `waitLED` es un comando muy potente si se usa correctamente, no ha ayudado a abordar nuestra sencilla tarea de pausar robustamente un HIDScript hasta que se presione una tecla modificadora de estado en el host USB objetivo (recuerde: queríamos pausar la ejecución para asegurarnos de que el "alguien" no deseado se hubiera ido antes de que comience la escritura, pero `waitLED` ocasionalmente retornaba antes de tiempo, debido a cambios de estado de LED preservados).

Aquí es donde `waitLEDRepeat` entra en juego y viene al rescate.

Pegue el siguiente script en el editor y trate de hacer que el comando retorne. Inspeccione los resultados del HIDScript después.```
return waitLEDRepeat(ANY)

Deberías notar rápidamente que el mismo LED debe cambiarse varias veces con frecuencia para que el comando waitLEDRepeat retorne. El comando waitLEDRepeat no retornaría si LED diferentes cambian de estado o si el cambio en un solo LED ocurre demasiado lento.

El argumento proporcionado a waitLEDRepeat (que es ANY en el ejemplo) cumple exactamente el mismo propósito que en waitLED. Es un filtro de lista blanca. Por ejemplo, waitLEDRepeat(NUM) solo retornaría para cambios del LED de BLOQ NUM - sin importar qué tan rápido y seguido presiones la tecla BLOQ MAYÚS, no retornaría a menos que BLOQ NUM se presione frecuentemente.

Por defecto, uno de los LEDs de la lista blanca debe cambiar 3 veces y el retardo entre dos cambios sucesivos no debe ser mayor a 800 milisegundos para que waitLEDRepeat retorne. Este comportamiento se puede ajustar proporcionando argumentos adicionales como se muestra en este ejemplo:``` filter = ANY; // same filters as for waitLED num_changes = 5; // how often the SAME LED has to change, in order to return from waitLEDRepeat max_delay = 800; // the maximum duration between two LED changes, which should be taken into acccount (milliseconds) timeout = 10000; // timeout in milliseconds

waitLEDRepeat(filter, num_changes, max_delay); //wait till a LED frequently changed 5 times, no timeout waitLEDRepeat(filter, num_changes, max_delay, timeout); //wait till a LED frequently changed 5 times, abort after 10 seconds

root@kitploit:~
Así es como se interactúa con los informes LED de un host USB en HIDScript.

*Nota: `waitLEDRepeat` no difiere de `waitLED` en cuanto al consumo de cambios de estado LED preservados.
De todas formas, es mucho más difícil activarlo sin intención.*

Por lo tanto, `waitLEDRepeat` es la elección correcta si la tarea es pausar HIDScripts hasta que ocurra la interacción humana. Por supuesto,
también podría usarse para bifurcaciones, ya que proporciona el mismo objeto de retorno que `waitLED`.

Hasta este punto hemos adquirido bastante conocimiento sobre HIDScript (por supuesto, no sobre todo, ni siquiera hemos
explorado las capacidades de control del ratón de este lenguaje de script). De todas formas, este tutorial trata sobre el flujo de trabajo de P4wnP1 A.L.O.A.
y conceptos básicos. Así que no examinaremos otras características de HIDScript por ahora y continuaremos.

Resumamos lo que hemos aprendido sobre el flujo de trabajo y conceptos de P4wnP1 hasta ahora:
- Podemos iniciar acciones como la inyección de teclas desde el cliente CLI, bajo demanda
- Podemos usar el cliente web para lograr lo mismo, teniendo control adicional sobre los trabajos de HIDScript
- Si conectamos una fuente de alimentación externa a P4wnP1 A.L.O.A., nos conectamos/desconectamos a/de diferentes hosts USB y los
HIDScripts ya iniciados continúan funcionando sin problemas
- Podemos configurar la pila USB exactamente según nuestras necesidades (y cambiar su configuración en tiempo de ejecución, sin reiniciar
P4wnP1)
- Podemos escribir HIDScripts multipropósito, con lógica compleja basada en JavaScript (con soporte para funciones, bucles,
bifurcaciones, etc., etc.)

### 3. Workflow parte 2 - Plantillas y TriggerActions

Antes de continuar con los otros conceptos principales de P4wnP1 A.L.O.A., refinemos nuestro primer objetivo, que era "ejecutar una inyección
de teclas contra un host USB":

- El nuevo objetivo es escribir "Hello world" en el editor de un host USB Windows (notepad.exe).
- El editor debería ser abierto por P4wnP1 (no manualmente por el usuario).
- El editor debería cerrarse automáticamente cuando se altere alguno de los LED del teclado del host USB.
- Cada vez que P4wnP1 se conecte al host USB, este comportamiento debería repetirse (con fuente de alimentación externa, sin reinicio de
P4wnP1)
- El proceso *solo debería ejecutarse una vez*, a menos que P4wnP1 se reconecte al host USB, incluso si ocurren cambios sucesivos en los LED del
teclado después de que el HIDScript se haya iniciado.
- Incluso si se reinicia P4wnP1, el mismo comportamiento debería poder recuperarse sin necesidad de recrear los detalles de la configuración
desde cero nuevamente.

Iniciar notepad, escribir "Hello world" y cerrar notepad después de un cambio de LED podría hacerse con las cosas que hemos aprendido
hasta ahora. Un HIDScript correspondiente podría verse algo así:

// Starting notepad press("WIN R"); // Windows key + R, to open run dialog delay(500); // wait 500ms for the dialog to open type("notepad.exe\n"); // type 'notepad.exe' to the run dialog, append a RETURN press delay(2000); // wait 2 seconds for notepad to come up

// Type the message type("Hello world") // Type "Hello world" to notepad

// close notepad after LED change waitLED(ANY); // wait for a single LED change press("ALT F4"); // ALT+F4 shortcut to close notepad

//as we changed content, there will be a confirmation dialog before notepad exits delay(500); // wait for the confirmation dialog press("RIGHT"); // move focus to next button (don't save) with RIGHT ARROW press("SPACEBAR"); // confirm dialog with space

root@kitploit:~
Lo único nuevo en este script es el comando `delay`, que no necesita mucha explicación. Retrasa la ejecución por la cantidad de milisegundos indicada.

El script se puede pegar en el editor HIDScript del cliente web e iniciar con "run" para probarlo.

Debería funcionar como se espera, así que ya casi terminamos. Para poder reutilizar el script, incluso después de un reinicio, lo almacenamos de forma persistente. Esto se puede lograr presionando el botón "store" en la pestaña HIDScript del webclient. Después de ingresar un nombre (usamos `tutorial1` por ahora) y confirmar el diálogo, el HIDScript debería haberse almacenado. Podemos verificarlo presionando el botón "Load & Replace" en el webclient. El script almacenado debería aparecer en la lista de scripts almacenados con el nombre `tutorial1.js` (la extensión `.js` se agrega automáticamente, si no se ha proporcionado ya en el diálogo "store").

**Advertencia: Si se usa un nombre de un archivo ya existente en el diálogo de almacenamiento, el archivo correspondiente se sobrescribe sin solicitar confirmación adicional.**

Intentemos iniciar el script almacenado usando el cliente CLI desde una sesión SSH, de la siguiente manera:```
P4wnP1_cli hid run tutorial1.js

Esto debería haber funcionado. Esto significa que es posible iniciar HIDScripts almacenados desde todas las aplicaciones que admiten comandos de shell o desde un simple script de bash, utilizando el cliente CLI de P4wnP1 A.L.O.A.

Incluso sería posible iniciar el script de forma remota desde un cliente CLI compilado para Windows. Suponiendo que el host Windows pueda alcanzar P4wnP1 A.L.O.A. a través de WiFi y la IP de P4wnP1 esté configurada como 172.24.0.1, el comando adecuado sería el siguiente:``` P4wnP1_cli.exe --host 172.24.0.1 hid run tutorial1.js

root@kitploit:~
*Nota: Al momento de escribir esto, aún no he decidido si P4wnP1 A.L.O.A. incluye un binario CLI para cada 
plataforma y arquitectura posible. Pero es probable que se proporcionen versiones precompiladas para las principales plataformas. Si
no es así, no es un gran problema, ya que la compilación cruzada del código Go del cliente CLI tarda menos de un minuto.*

El siguiente paso es permitir que el script se ejecute nuevamente cada vez que P4wnP1 se vuelva a conectar a un host USB. Un enfoque que ya 
utilizamos para lograr tal comportamiento fue envolver todo en un bucle y anteponer un `waitLED(ANY_OR_NONE)`. El
`waitLED(ANY_OR_NONE)` aseguró que el bucle solo continúe si el host USB objetivo señala que el controlador de teclado está 
listo para recibir entrada mediante el envío de una actualización del estado global de los LED del teclado. Un script modificado en consecuencia podría verse 
así:```
while (true) {
  waitLED(ANY_OR_NONE);     // wait till keyboard driver sends the initial LED state
  
  // Starting notepad
  press("WIN R");           // Windows key + R, to open run dialog
  delay(500);               // wait 500ms for the dialog to open
  type("notepad.exe\n");    // type 'notepad.exe' to the run dialog, append a RETURN press
  delay(2000);              // wait 2 seconds for notepad to come up

  // Type the message
  type("Hello world")       // Type "Hello world" to notepad

  // close notepad after LED change
  waitLED(ANY);       // wait for a single LED change
  press("ALT F4");          // ALT+F4 shortcut to close notepad

  //as we changed content, there will be a confirmation dialog before notepad exits
  delay(500);               // wait for the confirmation dialog
  press("RIGHT");           // move focus to next button (don't save) with RIGHT ARROW
  press("SPACEBAR");        // confirm dialog with space 
}

El script dado anteriormente, en efecto, se ejecutaría cada vez que P4wnP1 se adjunta a un host USB. Pero el script no es muy robusto, porque hay un segundo waitLED involucrado, que espera hasta que notepad.exe esté cerrado nuevamente.

Hacerlo de esta manera implica varios problemas. Por ejemplo, si P4wnP1 se desconecta antes de que se escriba "Hello world", el waitLED bloqueante sería el que está antes de press("ALT F4") y la ejecución continuaría exactamente en ese punto del HIDScript una vez que P4wnP1 se adjunte a un host USB (quizás diferente) nuevamente.

Un criterio de eliminación definitivo para el enfoque elegido es el siguiente problema: No se podría cumplir el requisito de que el script se ejecute solo una vez después de adjuntar P4wnP1 a un host USB, ya que presionar NUM LOCK varias veces reiniciaría el script una y otra vez.

Entonces, ¿cómo solucionamos esto ?

Presentemos TriggerActions

La solución al problema son las llamadas "TriggerActions". Como su nombre lo indica, este concepto de flujo de trabajo de P4wnP1 A.L.O.A. ejecuta acciones basadas en desencadenantes predefinidos.

Para hacerse una idea de lo que estoy hablando, diríjase a la pestaña "TRIGGER ACTIONS" en el cliente web. Dependiendo de la configuración actual, puede que ya existan TriggerActions. No nos importan las TriggerActions existentes por ahora.

Haga clic en el botón "ADD ONE" y se debería agregar una nueva TriggerActions y abrirse instantáneamente en modo de edición. La nueva TriggerAction está deshabilitada por defecto y debe habilitarse para que sea editable. Por lo tanto, alternamos el interruptor de habilitación.

Ahora, desde el menú desplegable llamado "Trigger", se debe seleccionar la opción "USB gadget connected to host". La acción debería tener un valor preestablecido de "write log entry" seleccionado. Lo dejamos así y presionamos el botón "Update".

La TriggerAction recién agregada debería ser visible ahora en la vista general de TriggerActions (la que tiene el ID más alto) y mostrar un resumen del Trigger y la Acción seleccionados en forma legible.

Para probar si la TriggerAction recién definida funciona, navegue hasta la pestaña "Event Log" del cliente web. Asegúrese de tener el cliente web abierto a través de WiFi (no Ethernet USB). Aplique alimentación externa a P4wnP1, desconéctelo del host USB y conéctelo nuevamente. Cada vez que P4wnP1 se adjunte a un host USB, se debería enviar un mensaje de registro al cliente, de inmediato.

Si repitió esto varias veces, quizás notó que el disparador "USB gadget connected to host" se activa muy rápido (o en una etapa temprana de la fase de enumeración USB). Para ser más precisos: cuando este disparador se activa, se sabe que P4wnP1 se conectó a un host USB, pero no hay garantía de que el host USB haya logrado cargar todos los controladores de dispositivo USB necesarios. De hecho, es muy poco probable que el controlador del teclado USB esté cargado cuando se activa el disparador. Debemos tener esto en cuenta.

Antes de continuar con nuestra tarea, hacemos una prueba adicional. Volvemos a la pestaña "TriggerAction" y presionamos el pequeño botón azul con forma de lápiz para nuestra TriggerAction recién creada. Terminamos nuevamente en modo de edición.

Esta vez, habilitamos la opción One shot. Luego, volvemos a "Event Log" y nuevamente desconectamos y reconectamos P4wnP1 del host USB. Esta vez, la TriggerAction debería activarse solo una vez. No importa cuántas veces se reconecte P4wnP1 al host USB después, no se debería crear ningún nuevo mensaje de registro que indique una conexión USB.

Cabe mencionar que una TriggerAction "One shot" no se elimina después de que se ha activado el disparador. En cambio, la TriggerAction se deshabilita nuevamente. Volver a habilitarla permite reutilizar una TriggerAction sin redefinirla. No se pierde nada hasta que se presione el botón rojo de "basura" en una TriggerAction, lo que eliminará la TriggerAction respectiva.

Advertencia: Si se hace clic en el botón de eliminar de una TriggerAction, la TriggerAction se elimina permanentemente sin más confirmación.

En este punto, hagamos lo obvio. Editamos la TriggerAction creada y seleccionamos "start a HIDScript" en lugar de "write log entry" para la acción a ejecutar. Además, deshabilitamos "one-shot" nuevamente. Aparece un nuevo campo de entrada llamado "script name". Al hacer clic en este campo de entrada, aparece un cuadro de diálogo de selección para todos los HIDScripts almacenados, incluido nuestro HIDScript tutorial1.js creado anteriormente.

Antes de que probemos si esto funciona, permítanme hacer una nota rápida sobre la acción "write log entry": P4wnP1 A.L.O.A. no realiza un seguimiento de los disparadores que ya se han activado. Esto significa que las entradas de registro creadas por una acción "write log entry" se entregan a todos los clientes que escuchan, pero no son almacenadas por el servicio P4wnP1 (por varias razones). El cliente web, por otro lado, almacena la entrada de registro hasta que el propio cliente web se recarga. Lo mismo se aplica a los eventos, que están relacionados con los trabajos HIDScript. Si un HIDScript finaliza (con éxito o error), se envía un evento a todos los clientes web actualmente abiertos. En resumen, cada cliente web tiene un estado de ejecución que contiene más información que el propio servicio central. Si el estado de ejecución del cliente web crece demasiado (uso excesivo de memoria), solo se necesita recargar el cliente para borrar la información de estado "histórica". Si el servicio central se comportara de la misma manera y almacenara toda la información histórica, se quedaría sin recursos muy pronto. Por lo tanto, este concepto se aplica a la mayoría de los subsistemas de P4wnP1 A.L.O.A.

Ahora volvamos a nuestra tarea. Tenemos una TriggerAction lista, que debería ejecutar nuestro HIDScript cada vez que P4wnP1 se adjunte a un host USB.

Dependiendo del host USB objetivo, esto funciona de manera más o menos confiable. En mi configuración de prueba no funcionó en absoluto y hay una razón:

Revisemos las primeras líneas de nuestro HIDScript:``` // Starting notepad press("WIN R"); // Windows key + R, to open run dialog delay(500); // wait 500ms for the dialog to open type("notepad.exe\n"); // type 'notepad.exe' to the run dialog, append a RETURN press ... snip ...

root@kitploit:~
Recordando que el disparador "USB gadget connected" se activa en la fase temprana de enumeración USB y que el controlador de teclado del host USB no se ha cargado necesariamente, el problema se vuelve evidente. Debemos anteponer algún tipo de retardo al script para asegurarnos de que el controlador de teclado esté activo (de lo contrario, nuestras pulsaciones de teclas no llegarían a ninguna parte).

Como ya sabemos que no es posible predecir el retardo óptimo, optamos por el enfoque `waitLED(ANY_OR_NONE)` explicado anteriormente. El nuevo script se ve así:```
waitLED(ANY_OR_NONE);   //assure keyboard driver is ready

// Starting notepad
press("WIN R");	        // Windows key + R, to open run dialog
delay(500);             // wait 500ms for the dialog to open
type("notepad.exe\n"); 	// type 'notepad.exe' to the run dialog, append a RETURN press
delay(2000);            // wait 2 seconds for notepad to come up

// Type the message
type("Hello world")     // Type "Hello world" to notepad

// close notepad after LED change
waitLEDRepeat(ANY);     // wait for a single LED change
press("ALT F4");        // ALT+F4 shortcut to close notepad

//as we changed content, there will be a confirmation dialog before notepad exits
delay(500);             // wait for the confirmation dialog
press("RIGHT");         // move focus to next button (don't save) with RIGHT ARROW
press("SPACEBAR");      // confirm dialog with space

Guardar el script modificado con el mismo nombre (tutorial1) sobrescribe el anterior HIDScript sin más confirmación, como ya se indicó. Por lo tanto, no es necesario ajustar nuestro TriggerAction, ya que el nombre del HIDScript al que hace referencia el TriggerAction no ha cambiado.

Con este pequeño cambio, todo debería funcionar según lo previsto y el script debería ejecutarse cada vez que nos conectemos a un host USB, pero solo una vez.

Ahora, si P4wnP1 se reinicia o pierde energía, nuestro HIDScript sobreviviría porque lo hemos almacenado de forma persistente, pero el TriggerAction desaparecería. No hace falta decir que los TriggerActions también podrían almacenarse de forma persistente.

El botón "store" en la pestaña "TriggerAction" funciona exactamente igual que el del editor de HIDScript. Hay que tener en cuenta que todos los TriggerActions actualmente activos se almacenarán si se confirma el diálogo "store" (incluidos los deshabilitados). La mejor práctica es eliminar todos los TriggerActions que no pertenezcan a la tarea del ámbito actual antes de almacenar (deberían haberse almacenado antes, si era necesario) y almacenar solo el pequeño conjunto de TriggerActions relevantes para la tarea actual, usando un nombre adecuado. Hay dos opciones para cargar los TriggerActions almacenados a los activos:

  • "load & replace" limpia todos los trigger actions activos y carga solo los almacenados.
  • "load & add" mantiene los TriggerActions ya activos y añade los almacenados. Por lo tanto, "load & add" podría usarse para construir un conjunto complejo de TriggerActions a partir de conjuntos más pequeños. El conjunto resultante podría, a su vez, almacenarse.

Por ahora, solo debemos almacenar nuestro único TriggerAction, que inicia nuestro HIDScript. El nombre que usamos para almacenar es nuevamente tutorial1 y no entrará en conflicto con el HIDScript llamado tutorial1.

Confirme el almacenamiento exitoso presionando el botón "load&replace" en la pestaña "TriggerAction". El conjunto de TriggerActions almacenado debería estar en la lista y llamarse tutorial1.

Advertencia: Los diálogos de "load" de TriggerActions permiten eliminar TriggerActions almacenados presionando el botón rojo de "papelera" junto a cada acción. Al presionar el botón se elimina permanentemente el conjunto de TriggerActions respectivo, sin más confirmación.

En este punto, podríamos eliminar con seguridad nuestro TriggerAction de la pestaña "TriggerActions" (¡no con el botón de papelera de uno de los diálogos de carga!).

Con el TriggerAction eliminado de los activos, no sucede nada si desconectamos y volvemos a conectar P4wnP1 del host USB.

En cualquier caso, el conjunto de TriggerActions almacenado tutorial1 persistirá a los reinicios y se podrá recargar en cualquier momento.

En lugar de recargar el conjunto de TriggerActions desde el webclient, intentaremos hacerlo usando el cliente CLI.

Echemos un vistazo rápido a la pantalla de ayuda del subcomando template deploy:``` root@kali:~# P4wnP1_cli template deploy -h Deploy given gadget settings

Usage: P4wnP1_cli template deploy [flags]

Flags: -b, --bluetooth string Deploy Bluetooth template -f, --full string Deploy full settings template -h, --help help for deploy -n, --network string Deploy network settings template -t, --trigger-actions string Deploy trigger action template -u, --usb string Deploy USB settings template -w, --wifi string Deploy WiFi settings templates

Global Flags: --host string The host with the listening P4wnP1 RPC server (default "localhost") --port string The port on which the P4wnP1 RPC server is listening (default "50051")

root@kitploit:~
La pantalla de uso muestra que las plantillas de TriggerAction se pueden implementar con el indicador `-t`. Ejecutamos el siguiente comando para restaurar el conjunto de TriggerAction almacenado:``` 
P4wnP1_cli template deploy -t tutorial1

La TriggerAction que lanza HIDScript en conexiones de host USB ahora está cargada de nuevo y debería mostrarse en la pestaña TriggerActions del webclient. Si P4wnP1 A.L.O.A. está conectado a un host USB, el script debería ejecutarse de nuevo.

El almacenamiento, carga e implementación de plantillas es uno de los dos conceptos principales detrás del flujo de trabajo de automatización de P4wnP1; el otro son las ya conocidas TriggerActions. Vale la pena mencionar que no solo los conjuntos de TriggerAction pueden almacenarse y cargarse como plantillas en sí mismos, sino que las TriggerActions podrían usarse para implementar plantillas ya almacenadas, si eso tiene sentido.

Revisando nuestras tareas, parece que todos los requisitos definidos se cumplen ahora:

  • escribimos "Hello world" en el editor de un host Windows USB
  • el editor es abierto por P4wnP1, no manualmente por el usuario
  • el editor se cierra automáticamente, cuando uno de los LEDs del teclado cambia una vez
  • cada vez que P4wnP1 se conecta a un host USB, este comportamiento se repite
  • el HIDScript se ejecuta solo una vez, a menos que P4wnP1 se vuelva a conectar al host USB, incluso si ocurren cambios sucesivos en los LEDs del teclado
  • si P4wnP1 se reinicia, el mismo comportamiento podría recuperarse cargando el conjunto de TriggerAction almacenado (que nuevamente hace referencia al HIDScript almacenado). Esto podría lograrse con un solo comando CLI o con un simple "load&add" o "load&replace" desde la pestaña de acciones de disparo del webclient.

Una vez más, agreguemos objetivos adicionales:

  • debe asegurarse que la configuración USB tenga habilitada la funcionalidad del teclado (la configuración actual no hace esto y la TriggerAction no podría iniciar el HIDScript en caso de que el teclado USB esté deshabilitado)
  • la configuración creada debe aplicarse al arranque de P4wnP1 A.L.O.A., sin necesidad de cargar manualmente el conjunto de TriggerAction. La configuración debe sobrevivir a un reinicio de P4wnP1.

Para lograr los dos objetivos adicionales, tenemos que sumergirnos en un nuevo tema y ...

Introducir Plantillas Maestras y Plantilla Maestra de Inicio

Antes de analizar las Plantillas Maestras, hacemos algo que aún no hemos hecho, porque todo funcionó como se esperaba hasta ahora: Definimos una configuración USB válida que coincida con nuestra tarea.

  • número de serie del dispositivo: 123456789
  • nombre del producto del dispositivo: Auto Writer
  • fabricante del dispositivo: The Creator
  • ID del producto: 0x9876
  • ID del proveedor: 0x1D6B
  • funciones USB habilitadas
    • teclado HID
    • ratón HID

Primero, echemos un vistazo a la pantalla de uso del comando CLI, que podría usarse para implementar estos ajustes:``` root@kali:~# P4wnP1_cli usb set -h set USB Gadget settings

Usage: P4wnP1_cli usb set [flags]

Flags: -e, --cdc-ecm Use the CDC ECM gadget function -n, --disable If this flag is set, the gadget stays inactive after deployment (not bound to UDC) -h, --help help for set -k, --hid-keyboard Use the HID KEYBOARD gadget function -m, --hid-mouse Use the HID MOUSE gadget function -g, --hid-raw Use the HID RAW gadget function -f, --manufacturer string Manufacturer string (default "MaMe82") -p, --pid string Product ID (format '0x1347') (default "0x1347") -o, --product string Product name string (default "P4wnP1 by MaMe82") -r, --rndis Use the RNDIS gadget function -s, --serial Use the SERIAL gadget function -x, --sn string Serial number (alpha numeric) (default "deadbeef1337") -u, --ums Use the USB Mass Storage gadget function --ums-cdrom If this flag is set, UMS emulates a CD-Rom instead of a flashdrive (ignored, if UMS disabled) --ums-file string Path to the image or block device backing UMS (ignored, if UMS disabled) -v, --vid string Vendor ID (format '0x1d6b') (default "0x1d6b")

Global Flags: --host string The host with the listening P4wnP1 RPC server (default "localhost") --json Output results as JSON if applicable --port string The port on which the P4wnP1 RPC server is listening (default "50051")

root@kitploit:~
El comando tiene un montón de banderas, pero también hay un montón de configuraciones USB modificables. 
Desplegar nuestra configuración USB definida podría hacerse así, usando la CLI:```
root@kali:~# P4wnP1_cli usb set \
> --sn 123456789 \
> --product "Auto Writer" \
> --manufacturer "The Creator" \
> --pid "0x9876" \
> --vid "0x1d6b" \
> --hid-keyboard \
> --hid-mouse
Successfully deployed USB gadget settings
Enabled:      true
Product:      Auto Writer
Manufacturer: The Creator
Serialnumber: 123456789
PID:          0x9876
VID:          0x1d6b

Functions:
    RNDIS:        false
    CDC ECM:      false
    Serial:       false
    HID Mouse:    true
    HID Keyboard: true
    HID Generic:  false
    Mass Storage: false

El resultado de (el largo) comando muestra la configuración USB resultante. Comprobemos la pestaña "USB settings" del cliente web para confirmar que se han aplicado. Todos los cambios deberían reflejarse, si nada salió mal.

Aunque es perfectamente posible implementar una configuración USB usando la CLI, existen varios beneficios al usar el cliente web en lugar de la CLI. En este caso:

  • cambiar la configuración desde el cliente web es más fácil y conveniente
  • el cliente web mantiene un estado de configuración interno, lo que permite definir configuración USB sin implementarla realmente (la CLI, por otro lado, solo podía manipular la configuración implementándola. Esto, nuevamente, reinicia toda la pila USB de P4wnP1 y toda funcionalidad dependiente. Por ejemplo, los scripts HIDScript ya en ejecución se interrumpirían o las interfaces de red USB se reimplementan)
  • la configuración actual del cliente web podría almacenarse en una plantilla persistente, sin implementarla previamente
  • el cliente CLI (actualmente) no puede almacenar configuración USB

En nuestro caso actual, es obviamente una mejor opción usar el cliente web para los cambios necesarios en la configuración USB. Lo bueno del enfoque CLI (que ya usamos aquí) es que, como la CLI nos obligó a implementar la configuración USB, pudimos confirmar que funcionan antes de almacenarlas en una plantilla persistente.

Continuemos almacenando la configuración USB:

Nuevamente presionamos el botón "store", esta vez en la pestaña "USB settings". De nuevo llamamos a la plantilla tutorial1 (no hay conflicto con la plantilla de TriggerAction almacenada con el mismo nombre, porque se usa un espacio de nombres diferente para la configuración USB).

Ahora tenemos dos nuevas plantillas almacenadas de forma persistente:

  1. una plantilla para el conjunto de TriggerAction, llamada tutorial1
  2. una plantilla para la configuración USB, también llamada tutorial1

Suponiendo que el estado (de la configuración USB actual, TriggerActions o ambos) haya cambiado de alguna manera, podríamos recargar ambas configuraciones almacenadas a la vez, emitiendo el siguiente comando CLI:``` P4wnP1_cli template deploy --usb tutorial1 --trigger-actions tutorial1

root@kitploit:~
El comando `P4wnP1 template deploy` podría cargar una plantilla para cada uno de los subsistemas de P4wnP1 A.L.O.A. en una sola
ejecución (para el subsistema de red se podrían cargar múltiples plantillas, una por cada adaptador). Desplegar plantillas para
varios subsistemas se considera una tarea común al trabajar con P4wnP1 A.L.O.A., porque en la mayoría de los casos debería ser
necesario reconfigurar varios subsistemas para alcanzar un solo objetivo. Para tener esto en cuenta, se han introducido las llamadas *Plantillas Maestras*.

Una Plantilla Maestra podría consistir en:
- una plantilla de conjunto TriggerAction ya almacenada
- una plantilla de configuración USB ya almacenada
- una plantilla de configuración WiFi ya almacenada
- una plantilla de configuración Bluetooth ya almacenada
- múltiples plantillas de configuración de red almacenadas (una por cada adaptador)

Una Plantilla Maestra podría definirse, almacenarse o cargarse, utilizando el "Editor de Plantillas Maestras" de la pestaña
"Configuración Genérica" del cliente web. Usar el cliente web es una manera conveniente de definir Plantillas Maestras, ya que te ayuda permitiendo
solo seleccionar plantillas que ya han sido almacenadas para los respectivos subsistemas (y actualmente el
cliente web es la única forma de definir Plantillas Maestras).

Así que definamos una Plantilla Maestra para nuestra tarea actual:
1) Navegue a la pestaña "Configuración Genérica" del cliente web
2) En el "Editor de Plantillas Maestras" haga clic en el botón pequeño a la derecha del campo "Plantilla de TriggerActions"
3) En el diálogo, elija la plantilla `tutorial1` y confirme con el botón "Aceptar"
4) Si seleccionó la plantilla incorrecta, vuelva a abrir el diálogo y seleccione una diferente o use el icono "x" a la derecha
de "Plantilla de TriggerAction" para eliminar la selección actual
5) Repita los pasos para la selección de "Plantilla USB", nuevamente elija `tutorial1` (que es una plantilla diferente para
el subsistema USB, aunque comparte el nombre con la de las TriggerActions)
6) Verifique que se hayan seleccionado las plantillas correctas para ambos, USB y TriggerActions, y que todas las demás Plantillas queden
vacías
7) Almacene la nueva Plantilla Maestra presionando el botón "Almacenar" y proporcionando el nombre `tutorial1`

Para confirmar que la plantilla se ha almacenado, puede usar el botón "Cargar Almacenada" – la plantilla debería aparecer
en la selección. Cancele el diálogo "Cargar Almacenada" nuevamente.

Ahora presione el botón "Desplegar Almacenada", seleccione la plantilla llamada `startup` y confirme con "Aceptar".

En contraste con la función "Cargar Almacenada", que carga una plantilla almacenada en el Editor de Plantillas Maestras, la
función "Desplegar Almacenada" aplica todas las configuraciones de una Plantilla Maestra a los subsistemas correspondientes de P4wnP1,
inmediatamente (sin siquiera cargarlas en el Editor de Plantillas Maestras).

Como la Plantilla Maestra `startup` sobrescribe la configuración WiFi actual, podría ocurrir que haya perdido la conexión
al cliente web y necesite reconectarse a la red WiFi de P4wnP1.

Una vez que se haya reconectado exitosamente e inspeccione la configuración USB actual y las TriggerActions actuales, las configuraciones que
almacenamos anteriormente han sido sobrescritas por las subconfiguraciones de la Plantilla Maestra `startup`.

Hay dos formas de desplegar nuevamente la Plantilla Maestra `tutorial1`:
1) Desplegarla usando el diálogo "Desplegar Almacenada" del "Editor de Plantillas Maestras" (como se hizo con la Plantilla Maestra `startup`
hace un minuto)
2) Desplegarla usando el cliente CLI con `P4wnP1_cli template deploy --full tutorial1` (la bandera `--full` es un alias
para Plantilla Maestra)

Al poder desplegar la Plantilla Maestra `tutorial1`, ya hemos alcanzado uno de nuestros nuevos objetivos:

Se asegura que la configuración USB tenga la funcionalidad de teclado habilitada cuando cargamos nuestra configuración de inyección de teclas.

Un breve resumen de cómo funciona esto:
- la Plantilla Maestra `tutorial1` carga la configuración USB, llamada `tutorial1`, que tiene
  - teclado USB y ratón USB habilitados
- la Plantilla Maestra `tutorial1` carga un conjunto TriggerAction con una sola TriggerAction
  - la TriggerAction inicia el script HID `tutorial1.js` cada vez que P4wnP1 se conecta a un host USB
    - el script HID comienza a escribir, una vez que se activa el disparador `waitLED` (controlador de teclado listo) y termina después de un cambio
    sucesivo de LED

El único objetivo restante es el siguiente: La configuración creada debe aplicarse al arranque de P4wnP1 A.L.O.A., sin necesidad
de cargar manualmente el conjunto TriggerAction. La configuración debe sobrevivir a un reinicio de P4wnP1.

Este objetivo podría lograrse ahora bastante fácil. La pestaña "Configuración Genérica" del cliente web presenta una tarjeta llamada
*Plantilla Maestra de Inicio*. Cambiar la Plantilla Maestra de Inicio a `tutorial1` en este punto tendría efecto inmediato
y probablemente *destruiría la configuración de arranque funcional de P4wnP1 A.L.O.A.".

**Importante: Si una Plantilla Maestra deja subplantillas vacías (p. ej., si no hay plantilla Bluetooth seleccionada), el
subsistema respectivo no se reconfigura cuando se carga la Plantilla Maestra. Si bien esto es útil para la reconfiguración en tiempo de ejecución
sin restablecer subsistemas ya en funcionamiento como la pila USB o WiFi si no es necesario, las Plantillas Maestras
usadas como Plantilla Maestra de Inicio dejan subsistemas sin plantillas definidas en un ESTADO INDEFINIDO. Si, por
ejemplo, no se proporciona una plantilla WiFi válida, es poco probable que P4wnP1 A.L.O.A. sea accesible vía WiFi después
del reinicio**

Por lo tanto, antes de desplegar nuestra nueva Plantilla Maestra `tutorial1` como Plantilla Maestra de Inicio, aseguramos que se carguen las configuraciones apropiadas
para los otros subsistemas. Hacemos esto de la siguiente manera:

1) Desde el "Editor de Plantillas Maestras" presione el botón "Cargar Almacenada" y recargue la plantilla `tutorial1` en el editor.
2) La plantilla debe tener `tutorial1` configurado para "Plantilla TriggerActions" y para "Plantilla USB"
3) Para "Plantilla WiFi" seleccione la plantilla llamada `startup`
4) Para "Plantilla Bluetooth" seleccione la plantilla llamada `startup`
5) Para "Plantillas de Red" seleccione las plantillas llamadas:
    1) `bteth_startup`
    2) `usbeth_startup`
    3) `wlan0_startup_dhcp_server`
6) Sobrescriba la Plantilla Maestra `tutorial1` con la nueva configuración (presione "Almacenar", ingrese `tutorial1` y confirme con
"Aceptar")
7) Verifique dos veces que los cambios se hayan aplicado, presionando "Cargar Almacenada" nuevamente, y seleccionando `tutorial1`. Todas
las subsecciones de la Plantilla Maestra cargada deberían verse como se describe aquí.

Ahora estamos listos para desplegar nuestra nueva Plantilla Maestra como Plantilla Maestra de Inicio. Después de hacerlo, presionamos el botón "reiniciar".

Una vez reiniciado, P4wnP1 A.L.O.A. debería activar automáticamente el HIDScript (y aún debería ser accesible vía WiFi,
para permitir la reconfiguración)

**Felicidades, todos los objetivos alcanzados**

Ha aprendido sobre los conceptos de flujo de trabajo muy básicos de P4wnP1 A.L.O.A.

## 3. Hacia dónde ir desde aquí

Actualmente no es posible proporcionar una documentación completa. Así que aquí hay algunos comentarios sobre temas que no han sido
tocados aún, pero que vale la pena investigar.

### BashScripts

P4wnP1 permite ejecutar BashScripts desde TriggerActions. Los scripts que se pueden usar desde TriggerActions se encuentran en
`/usr/local/P4wnP1/scripts`. Si se llama a un script desde una TriggerAction, varios argumentos (como el disparador real) se
pasan a través de variables bash. El archivo `/usr/local/P4wnP1/scripts/trigger-aware.sh` proporciona un buen ejemplo de un script bash
que actúa de manera diferente según el disparador que lo llama. Vale la pena echar un vistazo a este script, ya que utiliza
todas las "variables TriggerAction" disponibles actualmente.

### GPIO

La comunidad de la versión anterior de P4wnP1 ocasionalmente presentó modificaciones de hardware o extensiones de la Raspberry PI y
la pregunta de cómo integrarlas. No es posible para mí proporcionar una solución genérica a este problema. Tampoco
es una buena idea proporcionar soporte para una extensión de hardware muy específica, que solo es utilizada por unas pocas personas. Con
la introducción de TriggerAction surgió la idea de admitir GPIO tanto como disparadores a través de entrada GPIO como Acciones que emiten
salida GPIO. Aunque no estaba planeado para el primer lanzamiento, esta característica ya se ha implementado. Aún no he
tenido tiempo de documentarla y podría suceder fácilmente que algunas cosas cambien. La funcionalidad utiliza la biblioteca "periph.io"
con algunas extensiones menores (detección de bordes personalizada con anti-rebote personalizado para GPIO, gracias a @marcaruel por el
intercambio sobre esto)

### nexmon KARMA

El firmware WiFi incluido con P4wnP1 A.L.O.A. ha sido modificado (utilizando el marco nexmon) para admitir KARMA.
Esta característica no ha llegado al núcleo hasta ahora (necesita alguna reelaboración a nivel de firmware) y, por lo tanto, no está disponible desde el
cliente web o CLI. Si desea experimentar con las funciones karma, hay una CLI de Python heredada que permite configurar
las opciones KARMA sobre la marcha. El script de Python se puede encontrar aquí:
`/usr/local/P4wnP1/legacy/karmatool.py`

Consejo: Para aprovechar al máximo la funcionalidad KARMA, debe configurar P4wnP1 A.L.O.A. para que proporcione un Punto de Acceso WiFi sin
autenticación, de lo contrario no tendría mucho sentido. Para la inundación de balizas pobre esto no es necesario, pero los SSID personalizados
(estáticos) para balizas son limitados en número (ahorrando recursos en el chip WiFi)

Pantalla de ayuda de karmatool.py:```
root@kali:/usr/local/P4wnP1/legacy# ./karmatool.py 
Firmware in use seems to be KARMA capable
Firmware configuration tool for KARMA modified nexmon WiFi firmware on Pi0W/Pi3 by MaMe82
=========================================================================================

RePo:       https://github.com/mame82/P4wnP1_nexmon_additions
Creds to:   seemoo-lab for "NEXMON" project

A hostapd based Access Point should be up and running, when using this tool
(see the README for details).
            
Usage:      python karmatool.py [Arguments]

Arguments:
   -h                   Print this help screen
   -i                   Interactive mode
   -d                   Load default configuration (KARMA on, KARMA beaconing off, 
                        beaconing for 13 common SSIDs on, custom SSIDs never expire)
   -c                   Print current KARMA firmware configuration
   -p 0/1               Disable/Enable KARMA probe responses
   -a 0/1               Disable/Enable KARMA association responses
   -k 0/1               Disable/Enable KARMA association responses and probe responses
                        (overrides -p and -a)
   -b 0/1               Disable/Enable KARMA beaconing (broadcasts up to 20 SSIDs
                        spotted in probe requests as beacon)
   -s 0/1               Disable/Enable custom SSID beaconing (broadcasts up to 20 SSIDs
                        which have been added by the user with '--addssid=' when enabled)
   --addssid="test"     Add SSID "test" to custom SSID list (max 20 SSIDs)
   --remssid="test"     Remove SSID "test" from custom SSID list
   --clearssids         Clear list of custom SSIDs
   --clearkarma         Clear list of karma SSIDs (only influences beaconing, not probes)
   --autoremkarma=600   Auto remove KARMA SSIDs from beaconing list after sending 600 beacons
                        without receiving an association (about 60 seconds, 0 = beacon forever)
   --autoremcustom=3000    Auto remove custom SSIDs from beaconing list after sending 3000
                        beacons without receiving an association (about 5 minutes, 0 = beacon
                        forever)
   
Example:
   python karmatool.py -k 1 -b 0    Enables KARMA (probe and association responses)
                                    But sends no beacons for SSIDs from received probes
   python karmatool.py -k 1 -b 0    Enables KARMA (probe and association responses)
                                    and sends beacons for SSIDs from received probes
                                    (max 20 SSIDs, if autoremove isn't enabled)
   
   python karmatool.py --addssid="test 1" --addssid="test 2" -s 1
                                    Add SSID "test 1" and "test 2" and enable beaconing for
                                    custom SSIDs

Canal encubierto WiFi

El canal encubierto WiFi no se ha portado a Go y no forma parte del núcleo de P4wnP1. De todas formas, se proporciona la funcionalidad heredada. Para que el canal encubierto funcione, deben cumplirse varias condiciones:

  • se debe aplicar una inyección de tecleo al cliente objetivo para inyectar stage1
  • stage1 carga stage2 a través de una versión simplificada del canal encubierto HID, por lo tanto se debe proporcionar un dispositivo USB HID especial y se debe iniciar un servidor especial de canal encubierto HID en P4wnP1 para proporcionar stage2
  • se debe iniciar un segundo servidor que interactúe con el firmware WiFi modificado, para gestionar los clientes que se conectan a través del canal encubierto WiFi y proporcionar acceso interactivo a shell a esos clientes (el servidor es una aplicación de consola diseñada para ejecutarse en un multiplexor de terminal, como screen)

Todas las condiciones mencionadas podrían cumplirse usando el conjunto de características de P4wnP1 A.L.O.A., si los componentes necesarios (stager HID, servidor de canal encubierto WiFi, agente cliente a entregar) se proporcionan.

Realizar dicha tarea con P4wnP1 A.L.O.A. es un gran ejemplo de sus capacidades. Además, ayuda a distinguir qué se supone que es P4wnP1 A.L.O.A. y qué no se supone que sea.

P4wnP1 A.L.O.A. no está destinado a:

  • ser una herramienta "armamentizada"
  • proporcionar payloads RTR que cualquiera pueda ejecutar sin entender lo que sucede o los riesgos involucrados

P4wnP1 A.L.O.A. está destinado a:

  • ser una plataforma flexible, de bajo costo y tamaño de bolsillo
  • servir como habilitador para tareas como la descrita aquí
  • apoyar la creación de prototipos, pruebas y ejecución de todo tipo de tareas relacionadas con USB, comúnmente utilizadas durante compromisos de pentest o redteam, sin proporcionar una solución estática finalizada

En cierto sentido, la carpeta /usr/local/P4wnP1/legacy alberga las herramientas externas necesarias para ejecutar el canal encubierto WiFi (a saber, el servidor WiFi, el servidor stager del canal encubierto HID y el agente cliente del canal encubierto WiFi). Estos componentes podrían considerarse como partes externas (no pertenecen al núcleo de P4wnP1 A.L.O.A.).

Adicionalmente, P4wnP1 A.L.O.A. proporciona una configuración que utiliza los componentes dados para hacer lo siguiente:

  • drive-by contra hosts Windows para entregar código cliente en memoria que descarga stage2 a través del canal encubierto HID, basado en inyección de tecleo (HIDScript)
  • iniciar la inyección de tecleo tan pronto como P4wnP1 se conecte a un host USB (TriggerAction que ejecuta HIDScript)
  • poner en marcha el stager, que entrega el agente cliente del canal encubierto WiFi a través del canal encubierto HID, tan pronto como comience la inyección de tecleo (TriggerAction que ejecuta un script bash, que a su vez inicia el servidor externo)
  • poner en marcha el servidor del canal encubierto WiFi, cuando sea necesario (misma TriggerAction y BashScript)
  • desplegar una configuración USB que proporcione un teclado USB (para permitir la inyección de tecleo) y un dispositivo HID raw adicional (sirve como canal encubierto para la entrega de stage2) - la configuración USB se almacena en una plantilla de ajustes
  • desplegar una configuración WiFi que permita el acceso remoto a P4wnP1, para permitir la interacción con la interfaz CLI del servidor del canal encubierto WiFi - la configuración WiFi se almacena en una plantilla de ajustes
  • proporcionar un único punto de entrada para desplegar todas las configuraciones necesarias a la vez (realizado por una Plantilla Maestra, que consiste en la configuración WiFi adecuada, la configuración USB adecuada y las TriggerActions necesarias para iniciar el HIDScript)

La Plantilla Maestra se llama "wifi covert channel". Al desplegarla desde la pestaña "generic settings" del cliente web ("DEPLOY STORED" desde el Editor de Plantillas Maestras), P4wnP1 A.L.O.A. queda configurado para ejecutar todos los pasos descritos.

Tan pronto como se reconecte a un host USB, debería comenzar a escribir stage1 y los servidores correspondientes se iniciarán internamente. Desde una sesión SSH (por ejemplo, a través de WiFi), se puede acceder al servidor del canal encubierto WiFi usando screen -d -r wifi_c2 para interactuar con los clientes que se hayan conectado de vuelta a través del canal encubierto WiFi.

Como la inyección de tecleo depende de la distribución de idioma del host USB, el HIDScript correspondiente llamado wifi_covert_channel.js tiene una variable language que se puede usar para ajustar la distribución del teclado en uso. Además, hay una variable llamada hide (falso por defecto). Si hide se establece a verdadero, la ventana de consola en el cliente se oculta mientras se escribe stage1. Esto, nuevamente, señala cómo tareas complejas pueden reducirse a una simple variable booleana, gracias a HIDScript y al motor JavaScript subyacente.

La demostración "wifi covert channel" proporcionada con las Plantillas Maestras de P4wnP1 también se puede usar como Plantilla Maestra de inicio, ya que el acceso WiFi sigue siendo posible y, por lo tanto, la configuración se puede cambiar nuevamente de forma remota en cualquier momento.

El BashScript involucrado, que se llama desde una TriggerAction, es un buen ejemplo de lo flexible que puede llegar a ser el cliente CLI. Dado que el stager HID necesita saber en qué archivo de dispositivo escuchar (el que representa el dispositivo HID genérico), pero esta información solo está disponible en tiempo de ejecución (depende de las funciones de gadget USB habilitadas), el script solicita al CLI que reporte el dispositivo HID correcto ejecutando hidraw=$(P4wnP1_cli usb get device raw).

El BashScript completo se aloja en la carpeta /usr/local/P4wnP1/scripts, como todos los scripts bash que deberían ser accesibles desde TriggerActions.

Bluetooth NAP

P4wnP1 proporciona funcionalidad de red basada en Bluetooth a través del Protocolo de Encapsulación de Red Bluetooth (BNEP). La característica actualmente más interesante es el Punto de Acceso a Red Bluetooth (NAP), que permite el acceso remoto IP basado en Bluetooth a P4wnP1, por ejemplo desde dispositivos móviles.

Para usar esta característica, se deben tener en cuenta algunas cosas:

  • La interfaz de red Bluetooth, llamada bteth, se puede configurar y plantillar como las otras interfaces de red (cliente web o CLI)
  • Para permitir el acceso NAP desde un móvil Android (iPhone no probado), el móvil no solo necesita conectarse, sino que además P4wnP1 debe asignar una IP adecuada para la puerta de enlace predeterminada en la interfaz bteth a través de DHCP. Esto se debe a que el móvil quiere usar el NAP como puerta de enlace hacia Internet (que sería el uso previsto). Si el NAP en sí mismo no proporcionara una puerta de enlace, el móvil Android no realizaría más solicitudes después del D.O.R.A. de DHCP. La forma más sencilla de superar esto es instruir al servidor DHCP para que proporcione la IP de la propia interfaz bteth como puerta de enlace predeterminada (opción 3 de DHCP). Incluso si no hay una conexión ascendente real, esto funcionó durante mis pruebas, ya que el móvil debe acceder a la puerta de enlace con comunicación de capa 3 para "avisar a casa". Incluso si las pruebas de conectividad sucesivas fallan, la conexión de capa 3 funcional persiste. Esto permite, por ejemplo, acceso SSH a través de Bluetooth. Con "High Speed" habilitado, el cliente web también funciona bastante bien.
  • Para permitir el emparejamiento basado en PIN, se debe deshabilitar el Emparejamiento Simple Seguro (SSP). Si SSP está habilitado, el agente de emparejamiento en ejecución confirma cada clave de paso (lo que significa incluso menos seguridad que con el emparejamiento PIN heredado, ya que cualquier dispositivo puede conectarse). Quizás se implemente un diálogo de confirmación para el emparejamiento de clave de paso basado en SSP en el CLI/cliente web en el futuro, pero actualmente está fuera del alcance. Recomiendo encarecidamente deshabilitar "discoverable" y "bondable" si se usa SSP, tan pronto como el dispositivo previsto se haya emparejado.
  • Otra limitación de tener SSP deshabilitado es que "High Speed" no sería utilizable para conexiones Bluetooth (o para habilitar High Speed, el emparejamiento debe realizarse con SSP). Sin "High Speed" habilitado (usa tramas 802.11 para la comunicación), tomaría unos 10 minutos solicitar el cliente web; con High Speed habilitado toma unos segundos. Sin embargo, usar SSH y el cliente CLI a través de un NAP sin "High Speed" debería estar bien.
  • La configuración predeterminada de la interfaz de red Bluetooth (bteth_startup) y la configuración predeterminada de Bluetooth () deberían permitir acceso "Low Speed" a través de SSH con emparejamiento PIN heredado. El PIN es y se puede cambiar desde el cliente web.

Grupos de TriggerActions

Las TriggerActions vienen con una capacidad de enrutamiento interesante llamada "Grupos". No logré presentar una demostración de la característica a tiempo, pero planeo incluir un ejemplo de un contador binario de 4 bits basado en LEDs (usando GPIOs, un interruptor de palanca y 4 LEDs).

La idea de los grupos es la siguiente:

Considere que desea tener 4 TriggerActions (TAs) que se activen exactamente con el mismo disparador (por ejemplo, "al conectarse a un host USB"). Podría lograr esto creando 4 TAs, cada una con el disparador "al conectarse a un host USB".

Alternativamente, podría crear una TriggerAction que envíe el valor 1 a un grupo llamado "connected" cuando ocurra "al conectarse a un host USB". Ahora defina sus otras 4 TriggerActions para que se activen cuando se reciba el valor 1 en un grupo llamado "connected". El resultado sería el mismo y no tendría mucho sentido por ahora (de hecho, necesita una TriggerAction más). El único efecto positivo, por ahora, es que las TriggerActions son ligeramente más legibles, gracias al nombre del grupo, que se puede elegir libremente.

Ahora, lo primero avanzado que podría hacer es ejecutar el siguiente comando CLI:

`P4wnP1_cli trigger add group connected 1```` P4wnP1_cli trigger send --group-name=connected --group-value=1

root@kitploit:~
Este comando tendría exactamente el mismo efecto que la TriggerAction "al conectarse al host USB" y las otras 4
TA, que están esperando que el valor `1` llegue al grupo `connected` se dispararían. Como quizás recuerdes, el
cliente CLI podría ejecutarse de forma remota (desde diferentes plataformas), por lo que podría usarse para disparar un comando de forma remota.

El Trigger que reacciona a "canales de grupo" se llama "valor en canal de grupo". El trigger más interesante se llama
"múltiples valores en canal de grupo". Este trigger de "múltiples valores" permite escuchar secuencias ordenadas de valores, o 
uno de múltiples valores o todos los valores en una secuencia desordenada, antes de dispararse.

Digamos que quieres ejecutar un BashScript cuando se cumplan estas condiciones:
- El AP WiFi está activo
- P4wnP1 ha sido conectado a un host USB

Podrías crear TA para ambos eventos de esta manera:
1) En "AP WiFi activo" --> enviar valor 1 al grupo "conditions"
2) En "conectado al host USB" --> enviar valor 2 al grupo "conditions"

Ahora podrías implementar una tercera TriggerAction así:
- En "múltiples valores en canal de grupo"; valores (1,2); tipo "All (logical AND)" --> iniciar script bash

En esta configuración, el script bash solo se iniciaría si ambos Trigger "condition" se han disparado.

Si se hubiera usado "secuencia ordenada exacta" en lugar de "All (logical AND)" como tipo, el script bash solo
se iniciaría si el AP WiFi se levanta antes que el Trigger de conexión USB (no al revés). En combinación con disparadores GPIO,
esto podría usarse, por ejemplo, para disparar acciones basadas en la entrada de un simple teclado PIN.

Estoy seguro de que tienes algunas buenas ideas de uso para los canales de "grupo".

Vale la pena mencionar:

El cliente CLI puede realizar una espera bloqueante hasta que llegue un valor específico a un "canal de grupo", usando un comando como
este:```
P4wnP1_cli trigger wait --group-name=waitgroup --group-value=1

Esto podría usarse para ejecutar scripts desde TriggerActions, utilizando la CLI (con todo su poder como GPIO).

Trabajo en progreso, secciones faltantes:

  • Variables de activación de HIDScript (variables pasadas a HIDScripts lanzados desde TriggerActions)
  • Helpers de HIDScript (funciones de PowerShell)
  • Demo de serpiente HIDScript (ratón)
  • Almacenamiento masivo USB (helper genimg)

4. Rescate: Ayuda, no puedo acceder a P4wnP1 A.L.O.A. porque he estropeado la configuración

P4wnP1 A.L.O.A. no te protege de una mala configuración, lo que lo hace inutilizable (al igual que una consola de root no te protegería de ejecutar rm -rf /).

En caso de que hayas estropeado todo, aquí tienes algunas ideas para solucionarlo:

Copia de seguridad de la base de datos

Antes de realizar cambios críticos en una configuración de P4wnP1 que aún funcione, crea una copia de seguridad de la base de datos. Esto se puede hacer desde la pestaña "Generic Settings" del webclient o desde la CLI, con el comando P4wnP1_cli db backup. La copia de seguridad se almacenará en la carpeta /usr/local/P4wnP1/db con el nombre elegido. La función "restore" o el comando P4wnP1_cli db restore se pueden usar para restaurar una copia de seguridad dada. Una copia de seguridad contiene todas las plantillas almacenadas (USB, WiFi, Network, Bluetooth, TriggerActions, MasterTemplates) y la Startup Master Template que se haya establecido. La copia de seguridad no incluye HIDScripts ni BashScripts, ya que ambos se almacenan como archivos para permitir una edición sencilla.

No tengo copia de seguridad y todo está estropeado

Cuando P4wnP1 A.L.O.A. se inicia, comprueba si existe una base de datos. Si la base de datos no existe, crea una nueva base de datos basada en una copia de seguridad inicial que viene con P4wnP1 A.L.O.A.

La copia de seguridad inicial se almacena en /usr/local/P4wnP1/db/init.db y nunca debe ser eliminada o sobrescrita.

Para forzar a P4wnP1 a recrear la base de datos, la actual debe ser eliminada. Esto se puede lograr montando la tarjeta SD de P4wnP1 A.L.O.A. en un sistema que sea capaz de escribir particiones EXT.

Una vez hecho esto, elimina la carpeta /usr/local/P4wnP1/store de la partición raíz de la tarjeta SD. Esto elimina la base de datos y, por lo tanto, fuerza la recreación cuando P4wnP1 se inicia de nuevo.

Tengo una copia de seguridad, pero no puedo acceder a P4wnP1 para restaurarla

Si no puedes restaurar una base de datos existente porque no tienes acceso, aún puedes seguir los pasos de "No tengo copia de seguridad y todo está estropeado". Además de eliminar la carpeta /usr/local/P4wnP1/store, reemplaza el archivo /usr/local/P4wnP1/db/init.db con el de tu copia de seguridad (asegúrate de tener una copia de respaldo de init.db).

Esto debería recrear tu base de datos personalizada una vez que se reinicie P4wnP1.

He estropeado la Startup Master Template de mi copia de seguridad

Si tienes una copia de seguridad para la cual la Startup Master Template no funciona, tienes que realizar algunos pasos adicionales, ya que no es posible cambiar la Startup Template directamente en una copia de seguridad.

Primero sigue los pasos de "No tengo copia de seguridad y todo está estropeado" que recrean la base de datos inicial de P4wnP1. Después de un reinicio de P4wnP1, deberías poder acceder al webclient de P4wnP1 de forma remota nuevamente.

Ve a "Generic Settings" y restaura tu propia copia de seguridad (la que tiene la Startup Master Template incorrecta). La "Startup Master Template" debería mostrar tu Master Template "rota" como seleccionada. Si no es así, recarga la pestaña del navegador que aloja la aplicación webclient.

Nuevamente, navega a la pestaña "Generic Settings" y selecciona una Startup Master Template que se sepa que funciona. En este punto, deberías estar listo para reiniciar.

Ninguno de los anteriores ayudó

Lo siento, parece que tienes que recrear tu tarjeta SD de P4wnP1 A.L.O.A. desde una imagen limpia.

5. Créditos

En construcción, orden aleatorio

  • @JohanBrandhorst (intercambio cercano sobre gRPC-web a través de gopherjs, implementación ridículamente rápida de "websocket for server streaming", solicitud de característica)
  • @steevdave, @_binkybear (scripts de compilación de Kali, discusión e intercambio en curso)
  • @Re4sonKernel (Apoyo en mover cambios del kernel de P4wnP1 a un repositorio bien mantenido y popular, colaboración en correcciones de Bluez)
  • @SymbianSyMoh (Inspiración para el re-disparo de ataque HID sin reinicio)
  • @quasarframework (podría listar esto en librerías de terceros, pero el trabajo realizado aquí es una locura; la apariencia del webclient de P4wnP1 está más o menos basada en componentes predeterminados de esta hermosa librería)
  • @CyberArms (uno de los primeros seguidores de P4wnP1, escritor del mejor tutorial e incluso libros sobre estos temas)
  • @LucaBongiorni (no solo uno de los primeros seguidores, hace en hardware lo que yo solo hago en software; da charlas sobre el tema USB y honra las soluciones de código abierto, en general un gran tipo e inspiración)
  • @evilsocket (su bloque me empujó hacia Go, un gran desarrollador de código abierto, lee su código y sabes a lo que me refiero)
  • @RoganDawes y @Singe de @SensePost (tipos inspiradores)
  • @Swiftb0y (Seguidor temprano, creador de la "vieja" Wiki de P4wnP1, probador temprano de ideas para P4wnP1 A.L.O.A.)
  • @marcaruel (discusión sobre detección de flancos GPIO usando periph.io)

6. Tareas pendientes y soporte

Esta no es una lista de tareas completa, pero quedan algunos hitos y me encantaría recibir algo de apoyo de la comunidad en esto.

  • Portar la funcionalidad completa del canal encubierto HID al núcleo de Go (estoy solo con eso)
  • añadir comando de configuración de Bluetooth para la CLI
  • Crear diseños de teclado adicionales (actualmente se admiten br, de, es, fr, gb, it, ru y us)
  • Extender la funcionalidad Bluetooth para permitir la conexión a otros dispositivos detectables (autenticación y confianza)
  • Mover la funcionalidad WiFi KARMA desde una herramienta Python dedicada al núcleo de P4wnP1 (con soporte de webclient))
  • Crear documentación completa para HIDScript (básicamente solo falta la parte del ratón)
  • Crear documentación completa para P4wnP1 (esperando a la comunidad)
  • Eliminar una dependencia restante en el netlink de docker (ver README de la carpeta netlink)

Nota sobre Bluetooth:

P4wnP1 funciona con enlaces personalizados a la API de Bluez. Aunque la API de Bluez admite Low Energy (GATT, emular periféricos, etc.), no está planeado integrar esta funcionalidad en P4wnP1 A.L.O.A.

Nota sobre Nexmon:

P4wnP1 utiliza nexmon. La mayoría de la gente conoce nexmon como una modificación de firmware que permite habilitar el modo monitor e inyección de paquetes para chips WiFi Broadcom (incluido el BCM43430a1, que es utilizado por la Raspberry Pi Zero W). Pero nexmon es más, es un marco de trabajo que permite modificar blobs de firmware ARM (después de un poco de reversión), con parches escritos en código C de alto nivel. P4wnP1 utiliza este marco de trabajo para aplicar parches personalizados al firmware WiFi, que habilitan el soporte KARMA basado en hardware y el soporte de firmware (así como del controlador) para el canal encubierto WiFi. No es el objetivo de estas modificaciones proporcionar un modo monitor adecuado o soporte de inyección para la interfaz WiFi integrada. Aunque la funcionalidad de modo monitor heredada de nexmon está incluida en el firmware WiFi actual, se considera "errónea", ya que interfiere con la funcionalidad WiFi estándar utilizada por P4wnP1 (se bloquea si la interfaz se usa en modo estación, etc.).

7. Copyright

root@kitploit:~
P4wnP1 A.L.O.A.
Copyright (C) 2018 Marcus Mengs

Este programa es software libre: puedes redistribuirlo y/o modificar
bajo los términos de la Licencia Pública General de GNU publicada por
la Free Software Foundation, ya sea la versión 3 de la Licencia, o
(a tu elección) cualquier versión posterior.

Este programa se distribuye con la esperanza de que sea útil,
pero SIN NINGUNA GARANTÍA; sin siquiera la garantía implícita de
COMERCIABILIDAD o IDONEIDAD PARA UN PROPÓSITO PARTICULAR.  Ver la
Licencia Pública General de GNU para más detalles.

Deberías haber recibido una copia de la Licencia Pública General de GNU
junto con este programa.  Si no es así, consulta <http://www.gnu.org/licenses/>.
Descargar herramienta
startup
1337