
P4wnP1 A.L.O.A. от MaMe82 — это фреймворк, который превращает Raspberry Pi Zero W в гибкую, недорогую платформу для пентестинга, red teaming и физических воздействий… или в «Немного Агрессивное Устройство».
P4wnP1 A.L.O.A. от MaMe82 — это фреймворк, который превращает Raspberry Pi Zero W в гибкую, недорогую платформу для пентестинга, red teaming и физических взаимодействий... или в "A Little Offensive Appliance" (немного атакующее устройство).
Последний образ можно найти на вкладке релизов.
Самый простой способ получить доступ к свежей установке P4wnP1 A.L.O.A. — использовать веб-клиент через созданную WiFi-сеть (PSK: MaMe82-P4wnP1, URL: http://172.24.0.1:8000) или SSH (пароль по умолчанию: toor).
Math для расчетов мыши и т.д.)Здесь нечего особо сказать: P4wnP1 A.L.O.A. работает на базе KALI Linux, так что всё необходимое будет под рукой (или можно установить через apt)
Так что если вы хотите использовать пакетный файл на удаленном хосте Windows для конфигурации P4wnP1... без проблем:
host в ваши команды клиентаХотя изначально это не планировалось, P4wnP1 A.L.O.A. можно настраивать через веб-клиент. Несмотря на то, что клиент не был запланирован, он стал хорошим программным продуктом. Фактически он стал основным инструментом конфигурации для P4wnP1 A.L.O.A. Веб-клиент имеет возможности, недоступные в CLI (хранение шаблонов, создание "TriggerActions").
Основные возможности:
CTRL+SPACE)Подход к автоматизации старой версии P4wnP1 (статические bash-скрипты) больше не использовался.
Подход к автоматизации P4wnP1 A.L.O.A. должен был удовлетворять следующим требованиям:
Введение так называемых "TriggerActions" и их комбинация с системой шаблонов (постоянное хранение настроек для всех подсистем) позволили удовлетворить все требования. Подробности о TriggerActions можно найти в разделе WorkFlow.
P4wnP1 A.L.O.A. не использует концепции статической конфигурации или пейлоадов. Фактически у него вообще нет статического рабочего процесса.
P4wnP1 A.L.O.A. задуман максимально гибким, чтобы его можно было использовать во всех возможных сценариях (включая те, которые я не мог представить при создании P4wnP1 A.L.O.A.).
Но есть несколько основных концепций, которые я хотел бы рассмотреть в этом разделе. Поскольку сложно всё объяснить без создания надлежащей (видео)документации, я рассмотрю некоторые распространенные случаи использования и примеры, чтобы объяснить, что нужно объяснить.
Тем не менее, вряд ли у меня будет время на создание полноценной документации. Поэтому я призываю всех поддержать меня учебными пособиями и идеями, которые можно будет включить в этот README
Теперь начнём с одной из самых простых задач:
Минимальные требования для достижения этой цели:
Конфигурация по умолчанию P4wnP1 (немодифицированный образ) уже соответствует этим требованиям:
MaMe82-P4wnP1172.24.0.1172.16.0.1P4wnP11337172.26.0.1root, пароль по умолчанию: toorПримечание: Развертывание HTTPS-соединения в настоящее время не входит в сферу проекта. Пожалуйста, учитывайте это при работе с конфиденциальными данными, такими как учетные данные WiFi, в веб-клиенте. Весь проект не создавался с учетом безопасности (и маловероятно, что это когда-либо станет требованием). Поэтому применяйте соответствующие меры (например, ограничьте доступ к веб-клиенту с помощью iptables, если точка доступа настроена с открытой аутентификацией; не держите Bluetooth Discoverability и Connectability включенными без PIN-защиты и т.д.)
На данный момент я предполагаю:
Чтобы запустить CLI-клиент из SSH-сессии, выполните следующую команду:``` 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.
Экран справки уже показывает, что CLI-клиент использует различные команды для взаимодействия с различными подсистемами P4wnP1 A.L.O.A. Большинство этих команд, в свою очередь, имеют собственные подкоманды. Справку для каждой команды или подкоманды можно получить, добавив `-h` к команде 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")
Теперь, чтобы напечатать "Hello world" на USB-хосте, можно использовать следующую команду CLI:
P4wnP1_cli hid run -c 'type("Hello world")'
Вывод результата в SSH-сессии должен выглядеть примерно так:``` TempFile created: /tmp/HIDscript295065725 Start appending to 'HIDscript295065725' in folder 'TMP' Result: null
На USB-хосте в приложение, имеющее фокус ввода, должно было быть введено «Hello World».
*Если ваш SSH-клиент работает на самом USB-хосте, то введённый текст «Hello world» оказывается где-то среди вывода, полученного в результате выполнения команды CLI (он не является частью вывода, а был вставлен между строк).*
**Цель достигнута. Мы внедрили нажатия клавиш на целевое устройство.**
Много чтения для такой простой задачи, как внедрение нажатий клавиш, но, опять же, этот раздел предназначен для объяснения базовых концепций.
### 2.2 Переход к более сложным языковым возможностям HIDScript
Если вам удалось выполнить внедрение нажатий клавиш с «Hello world», то это хороший момент, чтобы изучить некоторые дополнительные возможности HIDScript.
Мы уже знаем команду `type`, но давайте попробуем обсудить более сложные команды HIDScript:
#### Нажатие специальных клавиш и комбинаций
Команда `type` поддерживает нажатие клавиши Return путём кодирования символа «новая строка» во входную строку, например так:```
P4wnP1_cli hid run -c 'type("line 1\nline 2\nline 3 followed by pressing RETURN three times\n\n\n")'
Но как насчёт специальных клавиш или комбинаций клавиш?
Команда press приходит на помощь!
Давайте используем press, чтобы отправить CTRL+ALT+DELETE на USB-хост:```
P4wnP1_cli hid run -c 'press("CTRL ALT DELETE")'
*Примечание: Две из клавиш были модификаторами (CTRL и ALT), и только одна была обычной клавишей (DELETE)*
Нажмем клавишу 'A' без каких-либо клавиш-модификаторов:```
P4wnP1_cli hid run -c 'press("A")'
В результате должен получиться символ 'a' в нижнем регистре, потому что press("A") интерпретирует 'A' как клавишу. Команда type("A"), с другой стороны, пытается нажать комбинацию клавиш, которая должна привести к выводу символа 'A' в верхнем регистре.
Давайте объединим клавишу-модификатор и обычную клавишу, чтобы получить символ 'A' в верхнем регистре (имитируя поведение `type("A"):``` P4wnP1_cli hid run -c 'press("SHIFT A")'
Это должно было привести к выводу заглавной буквы A.
Важно понимать, что `press` интерпретирует переданные ему аргументы как клавиши, в то время как `type` пытается найти подходящие комбинации клавиш для получения нужных выходных символов.
В последнем примере давайте объединим `press` и `type`.```
P4wnP1_cli hid run -c 'type("before caps\n"); press("CAPS"); type("after caps\n"); press("CAPS");'
Последняя команда напечатала строку, переключила CAPSLOCK, напечатала другую строку и снова переключила CAPS LOCK. В результате CAPSLOCK должен вернуться в исходное состояние (переключён дважды), но одна из строк напечатана в верхнем регистре, а другая — в нижнем, хотя обе строки были заданы в нижнем регистре.
Дополнительные примечания к нажатиям клавиш с помощью press:
Я не хочу углубляться в детали внутреннего устройства USB-отчётов клавиатуры, но некоторые вещи стоит упомянуть, чтобы обозначить ограничения и возможности команды press (которая сама по себе работает на основе сырых отчётов клавиатуры):
press использует до шести обычных или специальных клавиш
press("Z") приводит к USB_KEY_Z для раскладки EN_US, но порождает USB_KEY_Y для немецкой раскладки. Это соответствует нажатию аппаратной клавиши 'Z' на немецкой клавиатуре, которая тоже даст USB_KEY_Y.)/usr/local/P4wnP1/keymaps/common.json содержит форматированную JSON-карту клавиш со всеми возможными клавишами (будьте осторожны, не изменяйте файл)press не создаёт последовательность нажатий. Все указанные клавиши нажимаются одновременно и отпускаются одновременно.press автоматически отпускает клавиши, это означает, что последовательность типа «удерживать ALT, нажать TAB, нажать TAB, отпустить ALT» в настоящее время невозможнаКоманда HIDScript для смены раскладки клавиатуры — layout(<имя языковой карты>).
Следующий пример переключает раскладку клавиатуры на 'US', печатает что-то и переключает раскладку на 'German' перед продолжением печати:``` 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");'
Результат вывода команды, приведенной выше, зависит от целевой раскладки, используемой хостом USB.
На хосте с немецкой раскладкой клавиатуры результат выглядит так:```
Tzping with EN?US lazout
Typing with German layout supporting special chars üäö
На хосте с раскладкой клавиатуры US это выглядит так:``` Typing with EN_US layout Tzping with German lazout supporting special chars [';
Обратите внимание, что желаемый результат достигается только в том случае, если раскладка клавиатуры P4wnP1 совпадает с раскладкой клавиатуры, фактически используемой USB-хостом.
Команда `layout` позволяет привести внутреннюю раскладку P4wwP1 в соответствие с раскладкой целевого USB-хоста.
Возможность изменить раскладку во время выполнения HIDScript может оказаться полезной: кто знает, возможно, вы захотите перебрать раскладки клавиатуры целевого хоста, отправляя команды с изменением раскладки, пока одна из набранных команд не даст желаемого эффекта.
**Важно:** Раскладка действует глобально. Это означает, что если одновременно выполняется несколько HIDScript-ов и один из них устанавливает новую раскладку, все остальные скрипты также немедленно изменяют её.
#### Скорость набора
По умолчанию P4wnP1 вводит нажатия клавиш максимально быстро. В зависимости от вашей цели это может быть излишним (вспомните о контрмерах, предотвращающих инъекцию нажатий на основе анализа поведения скорости набора). HIDScript поддерживает команду для изменения этого поведения.
`typingSpeed(delayMillis, jitterMillis)`
Первый аргумент команды `typingSpeed` представляет собой постоянную задержку в миллисекундах, которая применяется между двумя нажатиями клавиш. Второй аргумент — дополнительный джиттер в миллисекундах. Он добавляет случайную задержку в диапазоне от 0 до указанного джиттера (в миллисекундах) к статической задержке, заданной первым аргументом.
Давайте попробуем использовать `typingSpeed` для замедления набора:```
P4wnP1_cli hid run -c 'typingSpeed(100,0); type("Hello world")'
Далее, вместо постоянной задержки, мы пробуем случайный джиттер:``` P4wnP1_cli hid run -c 'typingSpeed(0,500); type("Writing with random jitter up to 500 milliseconds")'
Наконец, комбинируя и настраивая оба значения, мы можем имитировать естественную скорость печати:```
P4wnP1_cli hid run -c 'typingSpeed(100,150); type("Writing with more natural speed")'
Важно: Скорость ввода действует глобально. Это означает, что если одновременно выполняются несколько HIDScript-сценариев, и один из них устанавливает новую скорость ввода, это немедленно влияет на все остальные сценарии.
Ожидание отчета светодиодов, или, точнее, изменений состояния светодиодов, является одной из более сложных клавиатурных функций HIDScript. Это может быть очень мощно, но требует некоторого пояснения.
Вы, возможно, заметили, что (в зависимости от ОС USB-хоста) модификаторы состояния клавиатуры (NUM LOCK, SCROLL LOCK, CAPS LOCK) распространяются на несколько подключенных клавиатур. Например, если подключить две клавиатуры к хосту Windows и переключить CAPS LOCK на одной из них, светодиод CAPS LOCK изменится на обеих клавиатурах.
Именно этот тест можно использовать, чтобы определить, распространяются ли модификаторы состояния клавиатуры на все клавиатуры для данной ОС.
Если хост USB поддерживает такое совместное использование состояния (например, Windows), язык HIDScript от P4wnP1 может этим воспользоваться.
Представьте следующий сценарий:
P4wnP1 подключен к USB-хосту, и вы хотите выполнить инъекцию нажатий клавиш, но не хотите, чтобы HIDScript выполнял нажатия немедленно. Вместо этого HIDScript должен ждать, пока вы не нажмете NUMLOCK, CAPSLOCK или SCROLLLOCK на реальной клавиатуре хоста. Почему? Возможно, вы участвуете в мероприятии, кто-то вошел, и вы не хотите, чтобы именно этот «кто-то» увидел, как магическим образом огромное количество символов вводится в окно консоли, которое внезапно появилось. Поэтому вы ждете, пока «кто-то» выйдет, нажимаете NUM LOCK, и в итоге всплывает окно консоли, и магически вводится огромное количество символов ... думаю, вы поняли.
Описанное поведение можно реализовать следующим образом:``` P4wnP1_cli hid run -c 'waitLED(NUM); type("A huge amount of characters\n")'
Если вы протестировали команду выше, набор текста должен начинаться только при нажатии NUM LOCK на аппаратной клавиатуре USB-хоста, но вы можете столкнуться с ситуациями, когда нажатия клавиш выполняются немедленно, даже если NUM LOCK не была нажата (и светодиод клавиатуры не изменился).
Это ожидаемое поведение, и причина этого — ещё один вариант использования команды `waitLED`:
Возможно, вы ранее использовали другие языки сценариев для клавиатуры и другие USB-устройства, способные вводить нажатия клавиш. У большинства таких устройств есть общая проблема: вы не знаете, когда начинать набор текста!
Если вы начнете набор сразу после включения USB-устройства, вероятно, USB-хост не завершил перечисление устройств и, следовательно, не успел загрузить драйверы клавиатуры. В итоге ваши нажатия будут потеряны.
Чтобы избежать этого, можно добавить задержку перед началом ввода. Но какой должна быть эта задержка? Пять секунд, 10 секунд, 30 секунд?
Ответ: это зависит! Это зависит от того, насколько быстро хост может перечислить устройство и загрузить драйвер клавиатуры. На самом деле, вы не можете знать, сколько времени это займет, без тестирования на реальной цели.
Но, как мы уже узнали, операционные системы, такие как Windows, разделяют состояние светодиодов между несколькими клавиатурами. Это означает, что если светодиод NUM LOCK на клавиатуре хоста включен до подключения второй клавиатуры, то светодиод NUM LOCK на этой новой клавиатуре также должен быть включен после подключения. Если же светодиод NUM LOCK был выключен, то и новая клавиатура получает состояние выключенных светодиодов (все светодиоды выключены). Интересно то, что это «обновление светодиодов» может быть отправлено только от USB-хоста к подключенной клавиатуре, если драйвер клавиатуры уже загружен (иначе отправка состояния светодиодов была бы невозможна).
Разве это не прекрасно? USB-хост сообщает нам: «Я готов принимать нажатия клавиш». Нет необходимости возиться с начальными задержками.
Но есть другая проблема: предположим, мы подключаем P4wnP1 к USB-хосту. Мы запускаем HIDScript, начинающийся с `waitLED` вместо ручной задержки. Набор начинается после `waitLED`, но ничего не происходит — наши нажатия всё равно теряются! Почему? Потому что, скорее всего, мы пропустили обновление состояния светодиодов, так как оно прибыло до того, как мы запустили наш HIDScript.
Именно это «состояние гонки» является причиной, по которой P4wnP1 сохраняет все обнаруженные изменения состояния светодиодов, пока хотя бы один HIDScript не обработает их вызовом `waitLED` (или `waitLEDRepeat`). Это может привести к описанному ранее поведению, когда `waitLED` возвращает управление немедленно, даже если никакого изменения светодиодов не произошло. Теперь мы знаем: изменение светодиодов действительно произошло, но могло произойти гораздо раньше (до того, как мы запустили HIDScript), поскольку изменение состояния было сохранено. Мы также знаем, что такое поведение необходимо, чтобы не пропустить изменения состояния светодиодов в случае использования `waitLED` для проверки «готовности драйвера клавиатуры USB-хоста».
*Примечание: Стоит отметить, что `waitLED` возвращает управление ТОЛЬКО в том случае, если полученное состояние светодиодов отличается от внутреннего состояния P4wnP1. Это означает, что даже если мы ожидаем изменения любого светодиода с помощью `waitLED(ANY)`, всё равно может случиться так, что мы получим начальное состояние светодиодов от USB-хоста, которое не отличается от внутреннего состояния P4wnP1. В этом случае `waitLED(ANY)` будет блокироваться вечно (или до тех пор, пока не произойдет реальное изменение светодиода). Этот частный случай можно обработать, вызвав `waitLED(ANY_OR_NONE)`, который возвращает управление, как только поступает новое состояние светодиодов, даже если оно не приводит к изменению.*
**Достаточно объяснений, давайте перейдём к практике ... прежде чем мы это сделаем, нужно немного изменить аппаратную конфигурацию:**
Подключите внешний источник питания ко второму USB-порту Raspberry Pi Zero (внешнему). Это гарантирует, что P4wnP1 не потеряет питание при отсоединении от USB-хоста, так как он больше не зависит от питания от шины. USB-порт, который следует использовать для подключения P4wnP1 к целевому USB-хосту, — это внутренний из двух портов.
Теперь запустите следующий HIDScript```
P4wnP1_cli hid run -c 'while (true) {waitLED(ANY);type("Attached\n");}'
Отсоедините P4wnP1 от USB-хоста (и убедитесь, что он остаётся включённым)! Снова подключите его к USB-хосту... При каждом повторном подключении P4wnP1 к хосту на хост должно выводиться «Attached».
Это дало нам 3 факта:
waitLED можно использовать в качестве начальной команды в скриптах, чтобы начать печать сразу после готовности драйвера клавиатуры.waitLED не является идеальным выбором для приостановки HID-скриптов до тех пор, пока на USB-хосте не будет нажата клавиша, изменяющая состояние светодиода, поскольку сохранённые изменения состояния могут разблокировать команду непреднамеренным образом.Поскольку мы всё ещё не закончили с командой waitLED, теперь займёмся третьим фактом. Давайте выйдем из CLI.
http://172.24.0.1:8000)ms_snake.js является очень хорошим примером возможностей триггеров на основе LED)Замените скрипт в окне редактора на следующий:``` return waitLED(ANY);
После нажатия кнопки запуска в правой части окна должно появиться новое выполняемое задание HID. Если вы нажмете маленькую кнопку "info" справа от задания HIDScript, вы сможете увидеть детали, такие как его состояние (должно быть 'выполняется'), идентификатор задания и идентификатор VM (это номер виртуальной машины JavaScript, выполняющей это задание. Таких VM 8, поэтому 8 скриптов HIDScript могут выполняться параллельно).
Теперь, если с USB-хоста будет отправлено изменение светодиода (переключением NUM, CAPS или SCROLL), задание HIDScript должно завершиться. Его всё ещё можно найти среди завершённых заданий ("Succeeded").
Если вы снова нажмете маленькую кнопку "info", должна появиться информация о значении результата (закодированном в JSON), которая выглядит примерно так:```
{"ERROR":false,"ERRORTEXT":"","TIMEOUT":false,"NUM":true,"CAPS":false,"SCROLL":false,"COMPOSE":false,"KANA":false}
Итак, команда waitLED возвращает объект JavaScript, выглядящий следующим образом:```
{
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)
}
В моём случае `NUM` стал истинным. В вашем случае, возможно, это был `CAPS`. Неважно, какой именно светодиод. Важно то, что возвращаемое значение даёт возможность проверить изменение светодиода, которое заставляет команду вернуться, и таким образом его можно использовать для принятия решений по ветвлению в вашем HIDScript (на основе изменений состояния светодиода, отправляемых хостом USB с реальной клавиатуры). Давайте попробуем пример:```
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
}
}
В предположении, что данный скрипт уже выполняется, нажатие NUM на USB-хосте должно привести к вводу текста "NUM has been toggled", а нажатие SCROLL LOCK — к тексту "SCROLL has been toggled". Это поведение повторяется до тех пор, пока не будет нажат CAPS LOCK, и вызванное изменение светодиода не прервёт цикл и не завершит HIDScript.
Уф... много текста об этой команде для одной HIDScript-команды, но осталось ещё кое-что.
Мы передавали аргументы вроде NUM, ANY или ANY_OR_NONE команде waitLED без дополнительных пояснений.
waitLED принимает до двух аргументов:
Первый аргумент, как вы, возможно, догадались, — это фильтр белого списка для отслеживаемых светодиодов. Допустимые значения:
ANY (реагировать на изменение любого из светодиодов)ANY_OR_NONE (реагировать на любое новое состояние светодиодов, даже если изменений нет)NUM (игнорировать все изменения светодиодов, кроме NUM)CAPS (игнорировать все изменения светодиодов, кроме CAPS)SCROLL (игнорировать все изменения светодиодов, кроме SCROLL)CAPS | NUM, NUM | SCROLLВторой аргумент, который мы пока не использовали, — это длительность тайм-аута в миллисекундах. Если за это время не произошло ни одного изменения светодиода, waitLED возвращается, и в результирующем объекте устанавливается TIMEOUT: true (кроме того, ERROR устанавливается в true, а ERRORTEXT указывает на тайм-аут).
Следующая команда будет ожидать изменения светодиода NUM, но прервёт ожидание через 5 секунд:``` waitLED(NUM,5000)
Хотя `waitLED` — очень мощная команда при правильном использовании, она не помогла справиться с нашей простой задачей надёжной приостановки HIDScript до нажатия клавиши-модификатора состояния на целевом USB-хосте (помните: мы хотели приостановить выполнение, чтобы убедиться, что нежелательный «кто-то» вышел до начала набора текста, но `waitLED` иногда возвращался раньше времени из-за сохранённых изменений состояния светодиодов).
Здесь на помощь приходит `waitLEDRepeat`.
Вставьте следующий скрипт в редактор и попробуйте заставить команду вернуться. После этого просмотрите результаты HIDScript.```
return waitLEDRepeat(ANY)
Вы быстро заметите, что один и тот же светодиод приходится часто и многократно переключать, чтобы команда
waitLEDRepeat вернула управление. Команда waitLEDRepeat не вернётся, если изменяются разные светодиоды или если
изменения на одном светодиоде происходят слишком медленно.
Аргумент, передаваемый в waitLEDRepeat (в примере это ANY), служит той же цели, что и для waitLED.
Это фильтр по белому списку. Например, waitLEDRepeat(NUM) будет возвращать управление только при изменениях светодиода NUM LOCK — независимо от того,
как быстро и часто вы нажимаете CAPS LOCK, команда не вернётся, пока NUM LOCK не будет нажат с достаточной частотой.
По умолчанию один из светодиодов из белого списка должен измениться 3 раза, а задержка между двумя последовательными изменениями не должна превышать
800 миллисекунд, чтобы waitLEDRepeat вернул управление. Это поведение можно настроить, передав
дополнительные аргументы, как показано в следующем примере:```
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
Итак, вот как взаимодействовать с LED-отчетами от USB-хоста в HIDScript.
*Примечание: `waitLEDRepeat` не отличается от `waitLED`, когда речь идет о потреблении сохраненных изменений состояния LED.
В любом случае, его гораздо сложнее вызвать непреднамеренно.*
Итак, `waitLEDRepeat` — правильный выбор, если задача — приостановить HIDScript до тех пор, пока не произойдет взаимодействие с человеком. Конечно, его также можно использовать для ветвления, поскольку он возвращает тот же объект, что и `waitLED`.
На данный момент мы получили достаточно хорошие знания о HIDScript (конечно, не обо всем, мы даже не рассматривали возможности управления мышью в этом языке сценариев). Тем не менее, этот урок посвящен рабочему процессу и основным концепциям P4wnP1 A.L.O.A. Поэтому мы пока не будем рассматривать другие функции HIDScript и двинемся дальше.
Давайте подведем итог тому, что мы узнали о рабочем процессе и концепциях P4wnP1 на данный момент:
- мы могли запускать такие действия, как инъекция нажатий клавиш, из CLI-клиента по запросу
- мы могли использовать веб-клиент для достижения того же самого, получая при этом дополнительный контроль над задачами HIDScript
- если мы подключаем внешний источник питания к P4wnP1 A.L.O.A., то при подключении/отключении к/от разным USB-хостам уже запущенные HIDScript продолжают бесперебойно работать
- мы могли настроить USB-стек точно под наши нужды (и изменять его конфигурацию во время выполнения без перезагрузки P4wnP1)
- мы могли писать многоцелевые HIDScript со сложной логикой на основе JavaScript (с поддержкой функций, циклов, ветвления и т.д. и т.п.)
### 3. Часть рабочего процесса 2 - Шаблонизация и TriggerActions
Прежде чем продолжить с другими основными концепциями P4wnP1 A.L.O.A., давайте уточним нашу первую цель, которая заключалась в «выполнении инъекции нажатий клавиш против USB-хоста»:
- Новая цель — напечатать «Hello world» в редакторе Windows USB-хоста (notepad.exe).
- Редактор должен быть открыт P4wnP1 (не вручную пользователем).
- Редактор должен автоматически закрываться при переключении любой из клавиатурных LED USB-хоста.
- Каждый раз, когда P4wnP1 подключается к USB-хосту, это поведение должно повторяться (с внешним источником питания, без перезагрузки P4wnP1).
- Процесс *должен выполняться только один раз*, если только P4wnP1 не будет повторно подключен к USB-хосту, даже если после запуска HIDScript произойдут последовательные изменения клавиатурных LED.
- Даже если P4wnP1 перезагружается, то же поведение должно быть восстановимо без повторного создания деталей настройки с нуля.
Запуск notepad, печать «Hello world» и закрытие notepad после изменения LED могут быть выполнены с помощью того, что мы уже узнали. Соответствующий 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
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
Единственное новое в этом скрипте — это команда delay, которая не требует особых объяснений. Она задерживает выполнение на заданное количество миллисекунд.
Скрипт можно вставить в редактор HIDScript веб-клиента и запустить командой "run" для тестирования.
Он должен работать как задумано, так что мы почти закончили. Чтобы иметь возможность повторно использовать скрипт даже после перезагрузки, сохраним его постоянно. Это можно сделать, нажав кнопку "store" на вкладке HIDScript веб-клиента. После ввода имени (пока используем tutorial1) и подтверждения диалога HIDScript должен сохраниться. Мы можем проверить это, нажав кнопку "Load & Replace" в веб-клиенте. Сохранённый скрипт должен появиться в списке сохранённых скриптов под именем tutorial1.js (расширение .js добавляется автоматически, если оно ещё не было указано в диалоге сохранения).
Предупреждение: Если в диалоге сохранения используется имя уже существующего файла, соответствующий файл будет перезаписан без дополнительного подтверждения.
Попробуем запустить сохранённый скрипт с помощью CLI-клиента из SSH-сессии, вот так:``` P4wnP1_cli hid run tutorial1.js
Это должно было сработать. Это означает, что можно запускать сохранённые HIDScripts из всех приложений, поддерживающих команды оболочки
или из простого bash-скрипта с помощью клиента CLI P4wnP1 A.L.O.A.
Было бы даже возможно запустить скрипт удалённо с клиента CLI, скомпилированного для Windows. Предполагая, что хост Windows
может достичь P4wnP1 A.L.O.A. через WiFi, а IP-адрес P4wnP1 установлен на `172.24.0.1`, правильная команда будет выглядеть
так:```
P4wnP1_cli.exe --host 172.24.0.1 hid run tutorial1.js
Примечание: На момент написания этого текста я ещё не решил, будет ли P4wnP1 A.L.O.A. поставлять CLI-бинарник для каждой возможной платформы и архитектуры. Но вполне вероятно, что будут предоставлены предварительно скомпилированные версии для основных платформ. Если нет — это не большая проблема, так как кросс-компиляция Go-кода CLI-клиента занимает меньше минуты.
Следующий шаг — позволить скрипту запускаться снова каждый раз, когда P4wnP1 подключается к USB-хосту. Подход, который мы уже использовали для достижения такого поведения, заключался в том, чтобы обернуть всё в цикл и добавить в начало waitLED(ANY_OR_NONE). waitLED(ANY_OR_NONE) гарантировал, что цикл продолжается только в том случае, если целевой USB-хост сигнализирует, что драйвер клавиатуры готов принимать ввод, отправляя обновление глобального состояния светодиодов клавиатуры. Соответственно модифицированный скрипт может выглядеть так:```
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 }
Приведённый выше скрипт действительно будет запускаться каждый раз, когда P4wnP1 подключается к USB-хосту. Но скрипт не очень надёжен, потому что в нём задействован второй `waitLED`, который ожидает, пока notepad.exe снова закроется.
Такой подход вызывает несколько проблем. Например, если P4wnP1 отключается до того, как будет введён "Hello world", то блокирующий `waitLED` будет тем, что стоит перед `press("ALT F4")`, и выполнение продолжится именно с этой точки HIDScript, как только P4wnP1 снова будет подключён к (возможно, другому) USB-хосту.
Определённым критерием смерти для выбранного подхода является следующая проблема: требование, чтобы скрипт выполнялся только один раз после подключения P4wnP1 к USB-хосту, не выполняется, так как многократное нажатие NUM LOCK будет запускать скрипт снова и снова.
Итак, как это решить?
#### Давайте познакомимся с TriggerActions
Решение проблемы — так называемые "TriggerActions" (действия по триггерам). Как следует из названия, эта концепция рабочего процесса P4wnP1 A.L.O.A. запускает действия на основе предопределённых триггеров.
Чтобы понять, о чём я говорю, перейдите на вкладку "TRIGGER ACTIONS" в веб-клиенте. В зависимости от текущей настройки там уже могут существовать TriggerActions. Сейчас мы не обращаем внимания на существующие TriggerActions.
Нажмите кнопку "ADD ONE" — будет добавлена новая TriggerAction, которая сразу откроется в режиме редактирования. Новая TriggerAction отключена по умолчанию, и её нужно включить, чтобы сделать редактируемой. Поэтому мы переключаем переключатель включения.
Теперь из выпадающего меню "Trigger" следует выбрать опцию "USB gadget connected to host". Для действия должно быть предустановлено значение "write log entry". Оставляем так и нажимаем кнопку "Update".
Теперь новая TriggerAction должна быть видна в обзоре TriggerActions (с наибольшим ID) и показывать сводку выбранного триггера и выбранного действия в читаемой форме.
Чтобы проверить, работает ли новое TriggerAction, перейдите на вкладку "Event Log" веб-клиента. Убедитесь, что вы открыли веб-клиент через Wi-Fi (не через USB Ethernet). Подайте внешнее питание на P4wnP1, отключите его от USB-хоста и снова подключите. Каждый раз при подключении P4wnP1 к USB-хосту немедленно будет отправлено лог-сообщение клиенту.
Если вы повторили это несколько раз, то, возможно, заметили, что триггер "USB gadget connected to host" срабатывает очень быстро (или на ранней стадии фазы перечисления USB). Точнее: когда этот триггер срабатывает, известно, что P4wnP1 был подключён к USB-хосту, но нет гарантии, что USB-хост успел загрузить все необходимые драйверы устройств. **На самом деле крайне маловероятно, что драйвер USB-клавиатуры уже загружен на момент срабатывания триггера. Это нужно иметь в виду.**
Прежде чем продолжить выполнение нашей задачи, проведём дополнительный тест. Возвращаемся на вкладку "TriggerAction" и нажимаем маленькую синюю кнопку в виде ручки для нашей только что созданной TriggerAction. Снова попадаем в режим редактирования.
На этот раз включаем опцию `One shot`. После этого возвращаемся в "Event Log" и снова отключаем и подключаем P4wnP1 к USB-хосту. На этот раз TriggerAction должно сработать только один раз. Сколько бы раз после этого P4wnP1 ни подключался повторно к USB-хосту, новое лог-сообщение, указывающее на USB-подключение, создаваться не должно.
Стоит упомянуть, что TriggerAction в режиме `One shot` не удаляется после срабатывания триггера. Вместо этого TriggerAction снова отключается. Повторное включение позволяет повторно использовать TriggerAction без переопределения. Ничего не теряется до тех пор, пока не будет нажата красная кнопка "trash" на TriggerAction, что приведёт к удалению соответствующей TriggerAction.
**Предупреждение: Если нажать кнопку удаления для TriggerAction, она будет удалена навсегда без дополнительного подтверждения.**
На этом этапе сделаем очевидное. Редактируем созданное TriggerAction и выбираем "start a HIDScript" вместо "write log entry" в качестве выполняемого действия. Кроме того, снова отключаем `one-shot`. Появляется новое поле ввода с названием "script name". Нажатие на это поле ввода открывает диалог выбора всех сохранённых HIDScript, включая наш ранее созданный `tutorial1.js`.
*Прежде чем проверить, работает ли это, позвольте сделать краткое замечание о действии "write log entry": P4wnP1 A.L.O.A. не отслеживает, какие триггеры уже сработали. Это означает, что лог-записи, создаваемые действием "write log entry", доставляются всем слушающим клиентам, но не сохраняются службой P4wnP1 (по ряду причин). С другой стороны, веб-клиент сохраняет лог-запись до тех пор, пока сам веб-клиент не будет перезагружен. То же самое относится к событиям, связанным с заданиями HIDScript. Если HIDScript завершается (успешно или с ошибкой), событие отправляется всем открытым в данный момент веб-клиентам. Таким образом, каждый веб-клиент имеет состояние выполнения, которое содержит больше информации, чем сама основная служба. Если состояние выполнения веб-клиента становится слишком большим (слишком много памяти), нужно просто перезагрузить клиент, чтобы очистить «историческую» информацию. Если бы основная служба вела себя так же и хранила всю историческую информацию, она очень быстро исчерпала бы ресурсы. Таким образом, эта концепция применима к большинству подсистем P4wnP1 A.L.O.A.*
Теперь вернёмся к нашей задаче. У нас есть готовое TriggerAction, которое должно запускать наш HIDScript каждый раз, когда P4wnP1 подключается к USB-хосту.
В зависимости от целевого USB-хоста это работает более или менее надёжно. В моей тестовой конфигурации это вообще не сработало, и на то есть причина:
Давайте рассмотрим первые несколько строк нашего 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 ...
Вспоминая тот факт, что триггер "USB gadget connected" срабатывает на раннем этапе перечисления USB, а драйвер клавиатуры USB-хоста ещё не обязательно загружен, проблема становится очевидной. Нам нужно добавить в скрипт некую задержку, чтобы гарантировать, что драйвер клавиатуры активен (иначе наши нажатия клавиш пропадут в никуда).
Поскольку мы уже знаем, что предсказать оптимальную задержку невозможно, мы используем подход waitLED(ANY_OR_NONE), описанный ранее. Новый скрипт выглядит так:```
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
Сохранение изменённого скрипта под тем же именем (`tutorial1`) перезаписывает предыдущий HIDScript без дополнительного подтверждения, как уже отмечалось. Таким образом, нет необходимости изменять TriggerAction, так как имя HIDScript, на которое ссылается TriggerAction, не изменилось.
С этим небольшим изменением всё должно работать как задумано: скрипт будет запускаться каждый раз при подключении к USB-хосту, но выполнится только один раз.
Теперь, если P4wnP1 будет перезагружен или потеряет питание, наш HIDScript сохранится, потому что мы сохранили его постоянно, но TriggerAction исчезнет. Разумеется, TriggerActions также можно хранить постоянно.
Кнопка «store» на вкладке «TriggerAction» работает точно так же, как в редакторе HIDScript. Следует отметить, что *все текущие активные TriggerActions* будут сохранены при подтверждении диалога «store» (включая отключенные).
Лучшая практика — удалить все TriggerActions, не относящиеся к текущей задаче, перед сохранением (они должны были быть сохранены ранее, если это необходимо) и сохранить только небольшой набор TriggerActions, относящихся к текущей задаче, с подходящим именем. Есть два варианта загрузить сохранённые TriggerActions в активные:
— «load & replace» очищает все активные TriggerActions и загружает только сохранённые.
— «load & add» сохраняет уже активные TriggerActions и добавляет сохранённые. Таким образом, «load & add» можно использовать для построения сложного набора TriggerActions из меньших наборов. Полученный набор затем можно снова сохранить.
Сейчас мы должны сохранить только наш единственный TriggerAction, который запускает HIDScript. Имя для сохранения снова — `tutorial1`, и оно не будет конфликтовать с HIDScript с именем `tutorial1`.
Подтвердите успешное сохранение, нажав кнопку «load&replace» на вкладке «TriggerAction». Сохранённый набор TriggerActions должен появиться в списке и называться `tutorial1`.
**Предупреждение: диалоги загрузки TriggerAction позволяют удалять сохранённые TriggerActions, нажимая красную кнопку «trash» рядом с каждым действием. Нажатие кнопки навсегда удаляет соответствующий набор TriggerActions без дополнительного подтверждения.**
На этом этапе мы можем смело удалить наш TriggerAction с вкладки «TriggerActions» (!!не с помощью кнопки «trash» из одного из диалогов загрузки!!).
После удаления TriggerAction из активных, ничего не произойдёт, если мы отключим и снова подключим P4wnP1 к USB-хосту.
В любом случае, сохранённый набор TriggerActions `tutorial1` переживёт перезагрузки и может быть загружен в любое время.
Вместо перезагрузки набора TriggerActions через веб-клиент, попробуем сделать это с помощью CLI-клиента.
Бегло взглянем на справку подкоманды `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")
Экран использования показывает, что TriggerAction Templates могут быть развернуты с помощью флага -t. Мы выполняем следующую команду, чтобы восстановить сохраненный набор TriggerAction:```
P4wnP1_cli template deploy -t tutorial1
Триггерное действие (TriggerAction), которое запускает HIDScript при подключении к USB-хост-системе, теперь снова загружено и должно отображаться на вкладке TriggerActions веб-клиента. Если P4wnP1 A.L.O.A. подключен к USB-хосту, скрипт должен запуститься снова.
Сохранение, загрузка и развертывание шаблонов — одна из двух основных концепций рабочего процесса автоматизации P4wnP1. Другая — уже известные TriggerActions. Стоит отметить, что не только наборы TriggerActions могут сохраняться и загружаться в качестве шаблонов, но и сами TriggerActions могут использоваться для развертывания уже сохраненных шаблонов, если это имеет смысл.
Возвращаясь к нашим задачам, похоже, что все определенные требования теперь выполнены:
- мы напечатали «Hello world» в редакторе на Windows-хосте с USB-подключением
- редактор открывается P4wnP1, а не вручную пользователем
- редактор автоматически закрывается, когда один из светодиодов клавиатуры переключается один раз
- каждый раз, когда P4wnP1 подключается к USB-хосту, это поведение повторяется
- HIDScript выполняется только один раз, если только P4wnP1 не подключен заново к USB-хосту, даже если происходят последующие переключения светодиодов клавиатуры
- если P4wnP1 перезагружается, то же поведение можно восстановить, загрузив сохраненный набор TriggerActions (который, в свою очередь, ссылается на сохраненный HIDScript). Это можно сделать либо с помощью одной команды CLI, либо простым «load&add» или «load&replace» на вкладке триггерных действий веб-клиента.
Давайте снова добавим дополнительные цели:
- необходимо убедиться, что в конфигурации USB включена функциональность клавиатуры (текущая настройка этого не делает, и TriggerAction не сможет запустить HIDScript, если USB-клавиатура отключена)
- созданная настройка должна применяться при загрузке P4wnP1 A.L.O.A. без необходимости ручной загрузки набора TriggerActions. Настройка должна пережить перезагрузку P4wnP1.
Чтобы достичь двух дополнительных целей, нам нужно углубиться в новую тему и ...
#### Введение в Master Templates и Startup Master Template
Прежде чем мы рассмотрим Master Templates, сделаем то, что мы еще не делали, потому что до сих пор все работало как задумано: определим корректную конфигурацию USB, соответствующую нашей задаче!
- серийный номер устройства: 123456789
- название продукта устройства: Auto Writer
- производитель устройства: The Creator
- Product ID: 0x9876
- Vendor ID: 0x1D6B
- включенные функции USB
- HID keyboard
- HID mouse
Давайте сначала взглянем на экран использования команды CLI, которая может быть применена для развертывания этих настроек:```
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")
Команда имеет много флагов, но также существует много изменяемых настроек USB. Развертывание нашей заданной конфигурации USB можно выполнить следующим образом с помощью 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
Результат выполнения (длинной) команды показывает полученные настройки USB. Давайте проверим вкладку "USB settings" веб-клиента, чтобы убедиться, что они были применены. Все изменения должны быть отражены, если ничего не пошло не так.
Хотя развернуть конфигурацию USB с помощью CLI вполне возможно, есть несколько преимуществ использования веб-клиента по сравнению с CLI. В данном случае:
- изменять настройки через веб-клиент проще и удобнее
- веб-клиент хранит внутреннее состояние настроек, что позволяет определять настройки USB без их фактического развертывания (CLI, с другой стороны, мог изменять настройки только путем их развертывания. Это, в свою очередь, сбрасывает весь стек USB P4wnP1 и все зависимые функции. Например, уже запущенный HIDScript будет прерван или интерфейсы USB-сети будут переразвернуты)
- текущие настройки веб-клиента можно сохранить в постоянный шаблон без предварительного развертывания
- клиент CLI (на данный момент) не умеет сохранять настройки USB
В нашем текущем случае, очевидно, лучше использовать веб-клиент для необходимых изменений настроек USB. Хорошая сторона подхода CLI (который мы уже использовали здесь): поскольку CLI заставил нас развернуть настройки USB, мы смогли убедиться, что они работают, прежде чем сохранять их в постоянный шаблон.
Продолжим с сохранением настроек USB:
Снова нажимаем кнопку "store", на этот раз во вкладке "USB settings". Снова называем шаблон `tutorial1` (конфликта с шаблоном TriggerAction, сохраненным под тем же именем, нет, поскольку для настроек USB используется другое пространство имен).
Теперь у нас есть два новых и постоянно сохраненных шаблона::
1) шаблон для набора TriggerAction, названный `tutorial1`
2) шаблон для настроек USB, также названный `tutorial1`
Предположим, что состояние (текущих настроек USB, TriggerActions или обоих) как-то изменилось. Мы могли бы загрузить оба сохраненных набора настроек одновременно, выполнив следующую команду CLI:
p4wnp1_cli template store tutorial1
P4wnP1_cli template deploy --usb tutorial1 --trigger-actions tutorial1
```
Команда `P4wnP1 template deploy` может загрузить шаблон для каждой из подсистем P4wnP1 A.L.O.A. одним запуском (для сетевой подсистемы можно загрузить несколько шаблонов — по одному на каждый адаптер). Развертывание шаблонов для различных подсистем считается обычной задачей при работе с P4wnP1 A.L.O.A., поскольку в большинстве случаев необходимо перенастроить несколько подсистем для достижения единой цели. Для учета этого были введены так называемые *Главные шаблоны* (Master Templates).
Главный шаблон может состоять из:
- уже сохраненного шаблона набора TriggerAction
- уже сохраненного шаблона настроек USB
- уже сохраненного шаблона настроек Wi-Fi
- уже сохраненного шаблона настроек Bluetooth
- нескольких сохраненных шаблонов сетевых настроек (по одному на каждый адаптер)
Главный шаблон можно определить, сохранить или загрузить с помощью «Редактора главных шаблонов» на вкладке «Общие настройки» веб-клиента. Использование веб-клиента — удобный способ определения главных шаблонов, так как он позволяет выбирать только те шаблоны, которые уже сохранены для соответствующих подсистем (и на данный момент веб-клиент — единственный способ определить главные шаблоны).
Итак, давайте определим главный шаблон для нашей текущей задачи:
1) Перейдите на вкладку «Общие настройки» веб-клиента.
2) В «Редакторе главных шаблонов» нажмите на маленькую кнопку справа от поля «Шаблон TriggerActions».
3) В диалоговом окне выберите шаблон `tutorial1` и подтвердите кнопкой «OK».
4) Если вы выбрали неверный шаблон, откройте диалог снова и выберите другой или используйте значок «x» справа от «Шаблона TriggerAction», чтобы удалить текущий выбор.
5) Повторите шаги для выбора «USB шаблона», снова выберите `tutorial1` (это другой шаблон для подсистемы USB, хотя он имеет то же имя, что и шаблон для TriggerActions).
6) Убедитесь, что правильные шаблоны выбраны для USB и TriggerActions, а все остальные шаблоны оставлены пустыми.
7) Сохраните новый главный шаблон, нажав кнопку «Store» и указав имя `tutorial1`.
Чтобы подтвердить, что шаблон сохранен, вы можете использовать кнопку «Load Stored» — шаблон должен отображаться в списке. Закройте диалог «Load Store».
Теперь нажмите кнопку «Deploy Stored», выберите шаблон с именем `startup` и подтвердите кнопкой «OK».
В отличие от функции «Load Stored», которая загружает сохраненный шаблон в редактор главных шаблонов, функция «Deploy Stored» немедленно применяет все настройки главного шаблона к соответствующим подсистемам P4wnP1 (даже не загружая их в редактор главных шаблонов).
Поскольку главный шаблон `startup` перезаписывает текущие настройки Wi-Fi, возможно, что вы потеряли соединение с веб-клиентом, и вам нужно будет переподключиться к сети Wi-Fi P4wnP1.
Как только вы успешно переподключитесь и проверите текущие настройки USB и текущие TriggerActions, вы увидите, что ранее сохраненные настройки были перезаписаны поднастройками главного шаблона `startup`.
Есть два способа снова развернуть главный шаблон `tutorial1`:
1) Развернуть его с помощью диалога «Deploy Stored» из «Редактора главных шаблонов» (как это было сделано с главным шаблоном `startup` минуту назад).
2) Развернуть его с помощью CLI-клиента командой `P4wnP1_cli template deploy --full tutorial1` (флаг `--full` является псевдонимом главного шаблона).
Возможность развернуть главный шаблон `tutorial1` позволяет нам достичь одну из наших новых целей:
Теперь гарантировано, что конфигурация USB включает функциональность клавиатуры, когда мы загружаем нашу настройку инъекции нажатий клавиш.
Краткое описание того, как это работает:
- Главный шаблон `tutorial1` загружает настройки USB, называемые `tutorial1`, которые включают:
- USB-клавиатуру и USB-мышь
- Главный шаблон `tutorial1` загружает набор TriggerAction с одним действием TriggerAction
- TriggerAction запускает HID-скрипт `tutorial1.js` каждый раз, когда P4wnP1 подключается к USB-хосту
- HIDScript начинает печатать, когда срабатывает триггер `waitLED` (драйвер клавиатуры готов), и завершается после последовательного изменения LED.
Осталась только одна цель: созданная настройка должна применяться при загрузке P4wnP1 A.L.O.A. без необходимости ручной загрузки набора TriggerAction. Настройка должна сохраняться после перезагрузки P4wnP1.
Теперь эту цель можно легко достичь. На вкладке «Общие настройки» веб-клиента представлена карточка под названием *Главный шаблон запуска* (Startup Master Template). Изменение главного шаблона запуска на `tutorial1` в этот момент немедленно вступит в силу и, скорее всего, *разрушит рабочую конфигурацию загрузки P4wnP1 A.L.O.A.".
**Важно: Если в главном шаблоне некоторые подшаблоны оставлены пустыми (например, если не выбран шаблон Bluetooth), соответствующая подсистема не перенастраивается при загрузке главного шаблона. Хотя это удобно для перенастройки во время выполнения без сброса уже работающих подсистем, таких как стек USB или стек Wi-Fi, если это не требуется, главные шаблоны, используемые в качестве шаблона запуска, оставляют подсистемы без определенных шаблонов в НЕОПРЕДЕЛЕННОМ СОСТОЯНИИ. Если, например, не указан допустимый шаблон Wi-Fi, маловероятно, что P4wnP1 A.L.O.A. будет доступен по Wi-Fi после перезагрузки.**
Поэтому перед развертыванием нашего нового главного шаблона `tutorial1` в качестве главного шаблона запуска мы убедимся, что для других подсистем загружены правильные настройки. Сделаем это так:
1) В «Редакторе главных шаблонов» нажмите кнопку «Load Stored» и снова загрузите шаблон `tutorial1` в редактор.
2) В шаблоне должно быть установлено `tutorial1` для «Шаблона TriggerActions» и «USB шаблона».
3) Для «WiFi шаблона» выберите шаблон с именем `startup`.
4) Для «Bluetooth шаблона» выберите шаблон с именем `startup`.
5) Для «Сетевых шаблонов» выберите шаблоны с именами:
1) `bteth_startup`
2) `usbeth_startup`
3) `wlan0_startup_dhcp_server`
6) Перезапишите главный шаблон `tutorial1` новыми настройками (нажмите «Store», введите `tutorial1` и подтвердите кнопкой «OK»).
7) Дважды проверьте, что изменения применены, снова нажав «Load Stored» и выбрав `tutorial1`. Все разделы загруженного главного шаблона должны соответствовать описанному здесь.
Теперь мы готовы развернуть наш новый главный шаблон в качестве главного шаблона запуска. После этого нажмите кнопку «reboot».
После перезагрузки P4wnP1 A.L.O.A. должен автоматически запускать HIDScript (и при этом оставаться доступным по Wi-Fi для перенастройки).
**Поздравляем, все цели достигнуты**
Вы узнали об основных концепциях рабочего процесса P4wnP1 A.L.O.A.
## 3. Куда двигаться дальше
Полную документацию в настоящее время предоставить невозможно. Итак, вот несколько комментариев по темам, которые еще не были затронуты, но их стоит изучить.
### BashScripts
P4wnP1 позволяет запускать Bash-скрипты из TriggerActions. Скрипты, которые можно использовать из TriggerActions, находятся в `/usr/local/P4wnP1/scripts`. Если скрипт вызывается из TriggerAction, несколько аргументов (например, фактический триггер) передаются через переменные bash. Файл `/usr/local/P4wnP1/scripts/trigger-aware.sh` является хорошим примером bash-скрипта, который действует по-разному в зависимости от вызывающего триггера. На этот скрипт стоит обратить внимание, так как он использует все доступные на данный момент «переменные TriggerAction».
### GPIO
В сообществе старой версии P4wnP1 время от времени появлялись аппаратные моды или расширения для Raspberry Pi и вопросы о том, как их интегрировать. Невозможно предоставить универсальное решение этой проблемы. Также не стоит поддерживать весьма специфическое аппаратное расширение, которое используется лишь несколькими людьми. С введением TriggerAction появилась идея поддерживать GPIO как в качестве триггеров (через вход GPIO), так и в качестве действий (выдача сигнала на выходе GPIO). Хотя это не планировалось для первого выпуска, эта функция уже реализована. У меня еще не было времени задокументировать это, и некоторые вещи могут измениться. Функциональность использует библиотеку "periph.io" с некоторыми небольшими расширениями (настраиваемое обнаружение фронтов с пользовательским антидребезгом для GPIO, спасибо @marcaruel за обсуждение).
### nexmon KARMA
Встроенная прошивка Wi-Fi в P4wnP1 A.L.O.A. была модифицирована (с использованием фреймворка nexmon) для поддержки KARMA. Эта функция пока не вошла в ядро (требуется доработка прошивки) и поэтому недоступна из веб-клиента или CLI. Если вы хотите поиграться с функциями KARMA, есть устаревший CLI на Python, который позволяет на лету устанавливать опции KARMA. Python-скрипт можно найти здесь:
`/usr/local/P4wnP1/legacy/karmatool.py`
Совет: Чтобы получить максимальную отдачу от функциональности KARMA, вы должны настроить P4wnP1 A.L.O.A. как точку доступа Wi-Fi без аутентификации, иначе это не будет иметь особого смысла. Для слабого флуда маяками это не требуется, но (статические) пользовательские SSID для маяков ограничены по количеству (экономия ресурсов на чипе Wi-Fi).
Справка 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
```
### WiFi covert channel
Скрытый канал WiFi не был портирован на Go и не является частью ядра P4wnP1. Тем не менее, предоставляется устаревшая функциональность. Для работы скрытого канала необходимо выполнение нескольких условий:
- должна быть применена инъекция нажатий клавиш на целевой клиент для внедрения stage1
- stage1 загружает stage2 через (упрощенную версию) скрытого канала HID, поэтому необходимо предоставить специальное USB HID устройство и запустить специальный сервер скрытого канала HID на P4wnP1 для передачи stage2
- должен быть запущен второй сервер, взаимодействующий с модифицированной прошивкой WiFi, для управления клиентами, подключающимися через скрытый канал WiFi, и предоставления интерактивного доступа к оболочке для этих клиентов (сервер — консольное приложение, предназначенное для запуска в терминальном мультиплексоре, например, `screen`)
Все вышеупомянутые условия могут быть выполнены с использованием набора функций P4wnP1 A.L.O.A., если предоставлены необходимые компоненты (HID-стейджер, сервер скрытого канала WiFi, клиентский агент для доставки).
Выполнение такой задачи с помощью P4wnP1 A.L.O.A. является отличным примером его возможностей. Кроме того, это помогает разграничить, для чего предназначен P4wnP1 A.L.O.A., а для чего нет.
P4wnP1 A.L.O.A. не предназначен для:
- быть «военизированным» инструментом
- предоставлять готовые RTR-пейлоады, которые может выполнить каждый, не понимая, что происходит или какие риски связаны
P4wnP1 A.L.O.A. предназначен для:
- быть гибкой, недорогой, карманной платформой
- служить средством для выполнения задач, подобных описанной здесь
- поддерживать прототипирование, тестирование и выполнение всевозможных задач, связанных с USB, обычно используемых во время пентестов или действий redteam, без предоставления готового статического решения
В определенном смысле папка `/usr/local/P4wnP1/legacy` содержит необходимые внешние инструменты для запуска скрытого канала WiFi (а именно WiFi-сервер, сервер-стейджер скрытого канала HID и клиентский агент скрытого канала WiFi). Эти компоненты можно рассматривать как внешние части (не относятся к ядру P4wnP1 A.L.O.A.).
Кроме того, P4wnP1 A.L.O.A. предоставляет конфигурацию, которая использует данные компоненты для выполнения следующих действий:
- drive-by-атака на хосты Windows для доставки клиентского кода в память для загрузки stage2 через скрытый канал HID на основе инъекции нажатий клавиш (HIDScript)
- запуск инъекции нажатий клавиш сразу после подключения P4wnP1 к USB-хосту (TriggerAction, выполняющий HIDScript)
- запуск стейджера, который доставляет клиентский агент скрытого канала WiFi через скрытый канал HID, как только начинается инъекция нажатий клавиш (TriggerAction, запускающий bash-скрипт, который, в свою очередь, запускает внешний сервер)
- запуск сервера скрытого канала WiFi при необходимости (тот же TriggerAction и BashScript)
- развертывание USB-настройки, предоставляющей USB-клавиатуру (для инъекции нажатий клавиш) и дополнительное raw HID-устройство (служит скрытым каналом для доставки stage2) — настройки USB хранятся в шаблоне настроек
- развертывание WiFi-настройки, обеспечивающей удаленный доступ к P4wnP1 для взаимодействия с CLI-интерфейсом сервера скрытого канала WiFi — настройки WiFi хранятся в шаблоне настроек
- предоставление единой точки входа для развертывания всех необходимых конфигураций одновременно (выполняется с помощью Master Template, который включает правильные настройки WiFi, правильные настройки USB и TriggerActions, необходимые для запуска HIDScript)
Master Template называется «wifi covert channel». Развернув его из вкладки «generic settings» веб-клиента («DEPLOY STORED» из редактора Master Template), P4wnP1 A.L.O.A. будет настроен для выполнения всех описанных шагов.
Как только он будет повторно подключен к USB-хосту, он должен начать ввод stage1, а соответствующие серверы запускаются внутри.
Из SSH-сессии (например, через WiFi) к серверу скрытого канала WiFi можно получить доступ с помощью `screen -d -r wifi_c2` для взаимодействия с клиентами, которые подключились обратно через скрытый канал WiFi.
Поскольку инъекция нажатий клавиш зависит от языковой раскладки USB-хоста, соответствующий HIDScript с именем `wifi_covert_channel.js` имеет переменную `language`, которую можно использовать для настройки используемой раскладки клавиатуры. Кроме того, существует переменная `hide` (по умолчанию false). Если `hide` установлена в true, окно консоли на клиенте скрывается во время ввода stage1. Это, опять же, показывает, насколько сложные задачи могут быть сведены к простой логической переменной благодаря HIDScript и поддерживающему движку JavaScript.
Демонстрация «wifi covert channel», предоставляемая с Master Templates P4wnP1, также может использоваться в качестве Startup Master Template, поскольку доступ по WiFi все еще возможен, и таким образом конфигурацию можно снова изменить удаленно в любое время.
Задействованный BashScript, вызываемый из TriggerAction, является хорошим примером того, насколько гибким может быть CLI-клиент. Поскольку HID-стейджеру необходимо знать, на каком файле устройства прослушивать (том, который представляет собой общее HID-устройство), но эта информация доступна только во время выполнения (зависит от включенных функций USB-гаджета), скрипт запрашивает у CLI сообщить правильное HID-устройство с помощью команды `hidraw=$(P4wnP1_cli usb get device raw)`.
Полный BashScript находится в папке `/usr/local/P4wnP1/scripts`, как и все bash-скрипты, которые должны быть доступны из TriggerActions.
### Bluetooth NAP
P4wnP1 предоставляет сетевую функциональность на основе Bluetooth через протокол инкапсуляции сети Bluetooth (BNEP). Наиболее интересной на данный момент функцией является точка доступа к сети Bluetooth (NAP), которая позволяет удаленный доступ к P4wnP1 по IP через Bluetooth, например, с мобильных устройств.
Чтобы использовать эту функцию, следует знать несколько вещей:
- Сетевой интерфейс Bluetooth, называемый `bteth`, можно настраивать и шаблонизировать, как и другие сетевые интерфейсы (веб-клиент или CLI)
- Чтобы разрешить доступ NAP с Android-мобильного устройства (iPhone не тестировался), мобильное устройство должно не только подключиться, но и P4wnP1 должен выдать правильный IP-адрес для шлюза по умолчанию на интерфейсе `bteth` через DHCP. Это связано с тем, что мобильное устройство хочет использовать NAP в качестве шлюза в Интернет (что и является предполагаемым использованием). Если бы NAP не предоставлял шлюз, Android-мобильное устройство не выполняло бы дальнейших запросов после DHCP D.O.R.A. Самый простой способ обойти это — указать DHCP-серверу предоставить IP-адрес самого интерфейса `bteth` в качестве шлюза по умолчанию (опция DHCP 3). Даже если нет реального вышестоящего соединения, это сработало в моих тестах — поскольку мобильное устройство должно обращаться к шлюзу через связь 3-го уровня, чтобы «связаться с домом». Даже если последующие тесты связи не удаются, работающее соединение 3-го уровня сохраняется. Это позволяет, например, SSH-доступ через Bluetooth. С включенным «High Speed» веб-клиент также работает довольно хорошо.
- Чтобы разрешить сопряжение на основе PIN-кода, необходимо отключить простое безопасное сопряжение (SSP). Если SSP включен, работающий агент сопряжения подтверждает каждый ключ доступа (что означает даже меньшую безопасность, чем при устаревшем PIN-сопряжении, так как любое устройство может подключиться). Возможно, в будущем будет реализован диалог подтверждения для SSP-сопряжения на основе ключа доступа для CLI/веб-клиента, но сейчас это выходит за рамки. Я настоятельно рекомендую отключить «discoverable» и «bondable», если используется SSP, как только целевое устройство было сопряжено.
- Еще один недостаток отключения SSP заключается в том, что «High Speed» не будет доступен для подключений Bluetooth (или для включения High Speed сопряжение должно выполняться с SSP). Без включенного «High Speed» (использует кадры 802.11 для связи) запрос веб-клиента может занять около 10 минут, с включенным High Speed — несколько секунд. Однако использование SSH и CLI-клиента через NAP без «High Speed» должно быть приемлемо.
- Настройки сетевого интерфейса Bluetooth по умолчанию (`bteth_startup`) и настройки Bluetooth по умолчанию (`startup`) должны разрешать доступ «Low Speed» по SSH с устаревшим PIN-сопряжением. PIN-код — `1337`, его можно изменить из веб-клиента.
### Группы TriggerAction
TriggerActions поставляются с удобной возможностью маршрутизации под названием «Groups». Я не успел подготовить демонстрацию этой функции вовремя, но планирую включить пример светодиодного 4-битного двоичного счетчика (с использованием GPIO, тумблера и 4 светодиодов).
Идея групп заключается в следующем:
Предположим, вы хотите иметь 4 TriggerActions (TA), срабатывающих по одному и тому же триггеру (например, «on attached to USB host»). Вы можете добиться этого, создав 4 TA, каждый с триггером «on attached to USB host».
В качестве альтернативы вы можете создать TriggerAction, который отправляет значение `1` в группу с именем `"connected"` при наступлении события «on attached to USB host». Теперь вы определяете другие 4 TriggerActions, которые будут срабатывать при получении значения `1` в группе с именем `"connected"`. Результат будет тем же и пока не имеет особого смысла (на самом деле требуется еще один TriggerAction). Единственный положительный эффект на данный момент — TriggerActions становятся немного более читаемыми благодаря имени группы, которое можно выбирать свободно.
Теперь первая продвинутая вещь, которую можно сделать, — выполнить следующую команду CLI:```
P4wnP1_cli trigger send --group-name=connected --group-value=1
```
Эта команда будет иметь тот же самый эффект, что и хост-действие триггера "on attached to USB host", и все остальные 4 TA, ожидающие значение `1` в группе `connected`, сработают. Как вы, возможно, помните, CLI-клиент может выполняться удалённо (с разных платформ), поэтому его можно использовать для удалённого запуска триггера.
Триггер, реагирующий на "групповые каналы", называется "value on group channel". Более интересный триггер называется "multiple values on group channel". Этот триггер "множественных значений" позволяет прослушивать упорядоченные последовательности значений, или одно из нескольких значений, или все значения в неупорядоченной последовательности, прежде чем сработать.
Допустим, вы хотите запустить BashScript при выполнении этих условий:
- WiFi AP работает
- P4wnP1 подключен к USB-хосту
Вы можете создать TA для обоих событий следующим образом:
1) При "WiFi AP up" --> отправить значение 1 в группу "conditions"
2) При "attached to USB host" --> отправить значение 2 в группу "conditions"
Теперь вы можете развернуть третье действие триггера следующим образом:
- При "multiple values on group channel"; значения (1,2); тип "All (logical AND)" --> запустить bash-скрипт
В такой конфигурации bash-скрипт запустится только в том случае, если оба триггера "condition" сработали.