
P4wnP1 A.L.O.A. von MaMe82 ist ein Framework, das einen Rapsberry Pi Zero W in eine flexible, kostengünstige Plattform für Pentesting, Red Teaming und physische Engagements ... oder in "A Little Offensive Appliance" verwandelt.
P4wnP1 A.L.O.A. von MaMe82 ist ein Framework, das einen Rapsberry Pi Zero W in eine flexible, kostengünstige Plattform für Pentesting, Red Teaming und physische Einsätze verwandelt ... oder in "A Little Offensive Appliance".
Das neueste Image kann unter dem Reiter "Releases" gefunden werden.
Der einfachste Weg, auf eine frische P4wnP1 A.L.O.A.-Installation zuzugreifen, ist die Verwendung des Webclients über das erzeugte WiFi (der PSK ist MaMe82-P4wnP1, die URL http://172.24.0.1:8000) oder SSH (Standardpasswort toor).
Math für Mausberechnungen usw.)Hier gibt es nicht viel zu sagen, P4wnP1 A.L.O.A. basiert auf KALI Linux, daher sollte alles direkt zur Hand sein (oder per apt installiert werden können)
Wenn Sie also eine Batch-Datei auf einem entfernten Windows-Host verwenden möchten, um P4wnP1 zu konfigurieren ... kein Problem:
host-Parameter zu Ihren Client-Befehlen hinzuObwohl es ursprünglich nicht geplant war, kann P4wnP1 A.L.O.A. mit einem Webclient konfiguriert werden. Auch wenn der Client nicht geplant war, hat er sich zu einem netten Stück Software entwickelt. Tatsächlich hat er sich als das wichtigste Konfigurationstool für P4wnP1 A.L.O.A. etabliert. Der Webclient hat Fähigkeiten, die von der CLI nicht genutzt werden können (Vorlagenspeicherung, Erstellung von "TriggerActions").
Die Kernfunktionen:
STRG+LEERTASTE)Der Automatisierungsansatz der alten P4wnP1-Version (statische Bash-Skripte) konnte nicht mehr verwendet werden.
Der Automatisierungsansatz von P4wnP1 A.L.O.A. musste folgende Anforderungen erfüllen:
Durch die Einführung der sogenannten "TriggerActions" und deren Kombination mit dem Vorlagensystem (persistente Einstellungsspeicherung für alle Subsysteme) konnten alle Anforderungen erfüllt werden. Details zu TriggerActions finden Sie im Abschnitt WorkFlow.
P4wnP1 A.L.O.A. verwendet keine Konzepte wie statische Konfiguration oder Payloads. Tatsächlich hat es überhaupt keinen statischen Workflow.
P4wnP1 A.L.O.A. soll so flexibel wie möglich sein, um die Verwendung in allen möglichen Szenarien zu ermöglichen (einschließlich derer, an die ich bei der Erstellung von P4wnP1 A.L.O.A. nicht denken konnte).
Aber es gibt einige grundlegende Konzepte, die ich in diesem Abschnitt durchgehen möchte. Da es schwierig ist, alles zu erklären, ohne eine ordentliche (Video-)Dokumentation zu erstellen, gehe ich einige häufige Anwendungsfälle und Beispiele durch, um zu erklären, was erklärt werden muss.
Dennoch ist es unwahrscheinlich, dass ich die Zeit habe, eine umfassende Dokumentation zu erstellen. Daher ermutige ich alle, mich mit Tutorials und Ideen zu unterstützen, die wieder in diese README verlinkt werden können
Beginnen wir nun mit einer der grundlegendsten Aufgaben:
Die Mindestanforderung an die Konfiguration, um dieses Ziel zu erreichen, ist:
Die Standardkonfiguration von P4wnP1 (unverändertes Image) erfüllt diese Anforderungen bereits:
MaMe82-P4wnP1172.24.0.1172.16.0.1P4wnP11337172.26.0.1root, das Standardpasswort ist toorHinweis: Die Bereitstellung einer HTTPS-Verbindung liegt derzeit nicht im Rahmen des Projekts. Bitte beachten Sie dies, wenn Sie im Webclient mit sensiblen Daten wie WiFi-Anmeldeinformationen umgehen. Das gesamte Projekt ist nicht auf Sicherheit ausgelegt (und es ist unwahrscheinlich, dass dies jemals eine Anforderung wird). Bitte ergreifen Sie daher geeignete Maßnahmen (z.B. den Zugriff auf den Webclient mit iptables einschränken, wenn der Access Point mit Open Authentication konfiguriert ist; Bluetooth-Discoverability und -Connectability nicht ohne PIN-Schutz aktiviert lassen usw. usw.)
An dieser Stelle gehe ich davon aus:
Um den CLI-Client von der SSH-Sitzung aus auszuführen, gib den folgenden Befehl ein:``` 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.
Der Hilfebildschirm zeigt bereits, dass der CLI-Client verschiedene Befehle verwendet, um mit den verschiedenen Subsystemen von P4wnP1 A.L.O.A. zu interagieren. Die meisten dieser Befehle haben wiederum eigene Unterbefehle. Die Hilfe für jeden Befehl oder Unterbefehl kann durch Anhängen von `-h` an den CLI-Befehl aufgerufen werden:```
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")
Nun, um "Hello world" an den USB-Host auszugeben, könnte der folgende CLI-Befehl verwendet werden:
P4wnP1_cli hid run -c 'type("Hello world")'
Die resultierende Ausgabe in der SSH-Sitzung sollte etwa so aussehen:``` TempFile created: /tmp/HIDscript295065725 Start appending to 'HIDscript295065725' in folder 'TMP' Result: null
Auf dem USB-Host sollte "Hello World" in die Anwendung mit Tastaturfokus eingegeben worden sein.
*Wenn Ihr SSH-Client auf dem USB-Host selbst läuft, landet das eingegebene "Hello world" irgendwo zwischen der resultierenden Ausgabe des CLI-Befehls (es gehört nicht zur Ausgabe, sondern wurde dazwischen eingegeben).*
**Ziel erreicht. Wir haben Tastatureingaben auf das Ziel eingeschleust.**
Viel Lesestoff für eine einfache Aufgabe wie das Einschleusen von Tastatureingaben, aber noch einmal: Dieser Abschnitt dient dazu, grundlegende Konzepte zu erklären.
### 2.2 Fortgeschrittenere Sprachfunktionen von HIDScript
Wenn Sie die Tastatureingabe von "Hello world" erfolgreich ausgeführt haben, ist dies ein guter Zeitpunkt, um einige zusätzliche HIDScript-Funktionen zu erkunden.
Wir kennen bereits den Befehl `type`, aber lassen Sie uns einige fortgeschrittenere HIDScript-Befehle besprechen:
#### Drücken von Sondertasten und Tastenkombinationen
Der Befehl `type` unterstützt das Drücken der Eingabetaste, indem ein "Neue Zeile"-Zeichen in die Eingabezeichenfolge kodiert wird, wie folgt:```
P4wnP1_cli hid run -c 'type("line 1\nline 2\nline 3 followed by pressing RETURN three times\n\n\n")'
Aber was ist mit speziellen Tasten oder Tastenkombinationen?
Der Befehl press kommt zur Hilfe!
Lass uns press verwenden, um CTRL+ALT+DELETE an den USB host zu senden:```
P4wnP1_cli hid run -c 'press("CTRL ALT DELETE")'
*Hinweis: Zwei der Tasten waren Modifikatoren (CTRL und ALT) und nur eine war eine tatsächliche Taste (DELETE)*
Drücken wir die Taste 'A' ohne eine Modifikatortaste:```
P4wnP1_cli hid run -c 'press("A")'
Das resultierende Ergebnis sollte ein Kleinbuchstabe 'a' sein, weil press("A") 'A' als Taste interpretiert. Der Befehl type("A") hingegen versucht, eine Tastenkombination zu drücken, die zu einem Großbuchstaben 'A' als Ausgabezeichen führen sollte.
Kombinieren wir eine Modifikator- und eine Nicht-Modifikatortaste, um ein Großbuchstabe 'A' als Ausgabezeichen zu erzeugen (das Verhalten von type("A") nachzuahmen):```
P4wnP1_cli hid run -c 'press("SHIFT A")'
Dies sollte eine Ausgabe von Großbuchstaben A erzeugt haben.
Es ist wichtig zu verstehen, dass `press` die übergebenen Tastenargumente als Tasten interpretiert, während `type` versucht, die geeigneten Tastenkombinationen zu finden, um die gewünschten Ausgabezeichen zu erzeugen.
In einem letzten Beispiel kombinieren wir `press` und `type`.```
P4wnP1_cli hid run -c 'type("before caps\n"); press("CAPS"); type("after caps\n"); press("CAPS");'
Der letzte Befehl tippte eine Zeichenkette, schaltete FESTSTELLTASTE um, tippte eine weitere Zeichenkette und schaltete FESTSTELLTASTE erneut um. Infolgedessen sollte sich FESTSTELLTASTE im Ausgangszustand befinden (zweimal umgeschaltet), aber eine der Zeichenketten wird in Großbuchstaben getippt, die andere in Kleinbuchstaben, obwohl beide Zeichenketten in Kleinbuchstaben angegeben wurden.
Zusätzliche Anmerkungen zu Tastendrücken mit press:
Ich möchte nicht in die Tiefe der internen Funktionsweise von USB keyboard reports eintauchen, aber einige Dinge sind erwähnenswert, um die Grenzen und Möglichkeiten des press-Befehls (der selbst auf rohen Tastaturberichten basiert) aufzuzeigen:
press bis zu sechs normale oder spezielle Tasten
press("Z") führt zu USB_KEY_Z für das EN_US-Tastaturlayout, erzeugt aber USB_KEY_Y für ein deutsches Layout. Dies entspricht dem Drücken der Hardwaretaste 'Z' auf einer deutschen Tastatur, die ebenfalls USB_KEY_Y produzieren würde.)/usr/local/P4wnP1/keymaps/common.json enthält eine formatierte JSON-Tastenzuordnung mit allen möglichen Tasten (achten Sie darauf, die Datei nicht zu ändern)press-Befehl erzeugt keine Tastensequenz. Alle angegebenen Tasten werden gleichzeitig gedrückt und gleichzeitig losgelassen.press gibt Tasten automatisch frei, das bedeutet, eine Sequenz wie „ALT gedrückt halten, TAB drücken, TAB drücken, ALT loslassen“ ist derzeit nicht möglichDer HIDScript-Befehl zum Ändern des Tastaturlayouts ist layout(<language map name>).
Das folgende Beispiel wechselt das Tastaturlayout zu 'US', tippt etwas und wechselt das Layout zu 'German', bevor es mit dem Tippen fortfährt:``` 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");'
Das Ausgabeergebnis des oben angegebenen Befehls hängt vom verwendeten Tastaturlayout des USB-Hosts ab.
Auf einem Host mit deutschem Tastaturlayout sieht das Ergebnis so aus:```
Tzping with EN?US lazout
Typing with German layout supporting special chars üäö
Auf einem Host mit US-Tastaturlayout sieht es so aus:``` Typing with EN_US layout Tzping with German lazout supporting special chars [';
Bitte beachten Sie, dass die beabsichtigte Ausgabe nur erreicht wird, wenn das Tastaturlayout von P4wnP1 mit dem tatsächlich vom USB-Host verwendeten Tastaturlayout übereinstimmt.
Der Befehl `layout` ermöglicht es, das interne Layout von P4wnP1 an das des Ziel-USB-Hosts anzupassen.
Die Möglichkeit, das Layout mitten in einem laufenden HIDScript zu ändern, könnte nützlich sein: Wer weiß, vielleicht möchten Sie das Tastaturlayout des Zielhosts durch Brute-Force ermitteln, indem Sie Befehle mit wechselnden Layouts ausgeben, bis einer der eingegebenen Befehle den gewünschten Effekt erzielt.
**Wichtig:** Das Layout hat globale Auswirkungen. Das bedeutet, wenn mehrere HIDScripts gleichzeitig ausgeführt werden und eines der Skripte ein neues Layout setzt, sind alle anderen Skripte ebenfalls sofort betroffen.
#### Tippgeschwindigkeit
Standardmäßig injiziert P4wnP1 Tastenanschläge so schnell wie möglich. Abhängig von Ihrem Ziel könnte dies etwas zu viel sein (denken Sie an Gegenmaßnahmen, die Tastenanschlaginjektion basierend auf der Verhaltensanalyse der Tippgeschwindigkeit verhindern). HIDScript unterstützt einen Befehl, um dieses Verhalten zu ändern.
`typingSpeed(delayMillis, jitterMillis)`
Das erste Argument des Befehls `typingSpeed` stellt eine konstante Verzögerung in Millisekunden dar, die zwischen zwei Tastenanschlägen angewendet wird. Das zweite Argument ist ein zusätzlicher Jitter in Millisekunden. Es fügt eine zusätzliche zufällige Verzögerung hinzu, die zwischen 0 und dem angegebenen Jitter in Millisekunden liegt, zur statischen Verzögerung, die mit dem ersten Argument bereitgestellt wird.
Versuchen wir, `typingSpeed` zu verwenden, um das Tippen zu verlangsamen:```
P4wnP1_cli hid run -c 'typingSpeed(100,0); type("Hello world")'
Als nächstes versuchen wir statt einer konstanten Verzögerung einen zufälligen Jitter:``` P4wnP1_cli hid run -c 'typingSpeed(0,500); type("Writing with random jitter up to 500 milliseconds")'
Schließlich konnten wir durch Kombinieren und Anpassen beider Werte eine natürliche Tippgeschwindigkeit simulieren:```
P4wnP1_cli hid run -c 'typingSpeed(100,150); type("Writing with more natural speed")'
Wichtig: Die Tippgeschwindigkeit hat globale Auswirkungen. Das heißt, wenn mehrere HIDScripts gleichzeitig ausgeführt werden und eines der Skripte eine neue Tippgeschwindigkeit festlegt, sind alle anderen Skripte sofort ebenfalls betroffen.
Auf einen LED-Bericht zu warten, genauer gesagt auf LED-Statusänderungen, ist eine der anspruchsvolleren Tastaturfunktionen von HIDScript. Es kann sehr mächtig sein, erfordert aber eine kleine Erklärung.
Ihnen ist vielleicht aufgefallen, dass (abhängig vom Betriebssystem des USB-Hosts) die Tastaturstatusmodifikatoren (NUM LOCK, SCROLL LOCK, CAPS LOCK) über mehrere angeschlossene Tastaturen hinweg gemeinsam genutzt werden. Wenn Sie beispielsweise zwei Tastaturen an einen Windows-Host anschließen und CAPS LOCK auf einer davon umschalten, ändert sich die CAPS-LOCK-LED auf beiden Tastaturen.
Genau dieser Test könnte verwendet werden, um festzustellen, ob die Tastaturstatusmodifikatoren für ein bestimmtes Betriebssystem über alle Tastaturen hinweg gemeinsam genutzt werden.
Falls ein USB-Host diese Art der Statusfreigabe unterstützt (wie beispielsweise Windows), kann die HIDScript-Sprache von P4wnP1 dies nutzen.
Stellen Sie sich folgendes Szenario vor:
P4wnP1 ist an einen USB-Host angeschlossen und Sie möchten Tastaturanschlag-Injection durchführen, aber Sie möchten nicht, dass das HIDScript die Tastatureingaben sofort ausführt. Stattdessen soll das HIDScript warten, bis Sie auf der echten Tastatur des Hosts NUMLOCK, CAPSLOCK oder SCROLLLOCK drücken. Warum? Vielleicht sind Sie im Rahmen eines Einsatzes beschäftigt, jemand ist hereingekommen und Sie möchten nicht, dass genau diese "jemand" sehen kann, wie magisch eine große Anzahl von Zeichen in ein plötzlich aufgetauchtes Konsolenfenster getippt wird. Also warten Sie, bis "jemand" hinausgeht, drücken NUM LOCK, und schließlich wird ein Konsolenfenster angezeigt und eine große Anzahl von Zeichen wird magisch getippt ... Ich denke, Sie haben verstanden.
Das beschriebene Verhalten könnte wie folgt erreicht werden:``` P4wnP1_cli hid run -c 'waitLED(NUM); type("A huge amount of characters\n")'
Wenn Sie den obigen Befehl getestet haben, sollte die Eingabe nur starten, wenn NUM LOCK auf der Hardwaretastatur des USB-Hosts gedrückt ist, aber es kann vorkommen, dass die Tastenanschläge sofort ausgegeben werden, auch wenn NUM LOCK nicht gedrückt wurde (und sich die Tastatur-LED nicht geändert hat).
Dies ist beabsichtigtes Verhalten und der Grund dafür ist ein weiterer Anwendungsfall für den Befehl `waitLED`:
Vielleicht haben Sie bereits andere Tastatur-Scripting-Sprachen und andere USB-Geräte verwendet, die Tastenanschläge einspritzen können. Die meisten dieser Geräte haben ein gemeinsames Problem: Sie wissen nicht, wann Sie mit der Eingabe beginnen sollen!
Wenn Sie sofort nach dem Einschalten des USB-Geräts zu tippen beginnen, hat der USB-Host wahrscheinlich die Geräteaufzählung noch nicht abgeschlossen und somit noch nicht die Tastaturtreiber geladen. Ihre Tastenanschläge gehen letztendlich verloren.
Um dies zu umgehen, könnten Sie eine Verzögerung vor dem Start der Tasteneingabe einfügen. Aber wie lange sollte diese Verzögerung sein? Fünf Sekunden, 10 Sekunden, 30 Sekunden?
Die Antwort ist: Es kommt darauf an! Es hängt davon ab, wie schnell der Host das Gerät aufzählen und den Tastaturtreiber laden kann. Tatsächlich können Sie nicht wissen, wie lange dies dauert, ohne es gegen das eigentliche Ziel zu testen.
Aber wie wir bereits gelernt haben, teilen Betriebssysteme wie Windows den LED-Zustand über mehrere Tastaturen hinweg. Das bedeutet, wenn die NUMLOCK-LED der Host-Tastatur auf EIN gesetzt ist, bevor Sie eine zweite Tastatur anschließen, muss die NUMLOCK-LED auf dieser neuen Tastatur nach dem Anschließen ebenfalls auf EIN gesetzt werden. Wäre die NUM-LOCK-LED ohnehin auf AUS gesetzt, erhält die neu angeschlossene Tastatur den LED-Zustand (in diesem Fall alle LEDs aus). Das Interessante daran ist, dass dieses „LED-Update“ nur vom USB-Host an die angeschlossene Tastatur gesendet werden kann, wenn der Tastaturtreiber vollständig geladen ist (das Senden des LED-Zustands wäre sonst nicht möglich).
Ist das nicht schön? Der USB-Host sagt uns: „Ich bin bereit, Tastenanschläge zu empfangen.“ Es ist nicht nötig, mit anfänglichen Verzögerungen herumzuspielen.
Aber hier ist ein weiteres Problem: Angenommen, wir verbinden P4wnP1 mit einem USB-Host. Wir führen ein HIDScript aus, das mit `waitLED` beginnt, anstatt einer manuell erstellten Verzögerung. Das Tippen beginnt nach dem `waitLED`, aber nichts passiert – unsere Tastenanschläge gehen trotzdem verloren! Warum? Weil wir wahrscheinlich das LED-Zustandsupdate verpasst haben, da es ankam, bevor wir überhaupt unser HIDScript gestartet haben.
Genau diese „Race Condition“ ist der Grund, warum P4wnP1 alle erkannten LED-Zustandsänderungen speichert, es sei denn, mindestens ein HIDScript konsumiert sie durch Aufruf von `waitLED` (oder `waitLEDRepeat`). Dies könnte zu dem zuvor beschriebenen Verhalten führen, bei dem ein `waitLED` sofort zurückkehrt, obwohl keine LED-Änderung aufgetreten ist. Wir wissen jetzt: Die LED-Änderung ist tatsächlich aufgetreten, aber sie könnte viel früher passiert sein (bevor wir überhaupt das HIDScript gestartet haben), weil die Zustandsänderung gespeichert wurde. Wir wissen auch, dass dieses Verhalten notwendig ist, um zu vermeiden, dass LED-Zustandsänderungen verpasst werden, falls `waitLED` verwendet wird, um die „Bereitschaft des Tastaturtreibers des USB-Hosts“ zu testen.
*Hinweis: Es ist erwähnenswert, dass `waitLED` NUR zurückkehrt, wenn der empfangene LED-Zustand von P4wnP1s internem Zustand abweicht. Das bedeutet, selbst wenn wir mit `waitLED(ANY)` auf eine Änderung einer beliebigen LED lauschen, kann es immer noch passieren, dass wir einen anfänglichen LED-Zustand von einem USB-Host empfangen, der sich nicht von P4wnP1s internem Zustand unterscheidet. In diesem Fall würde `waitLED(ANY)` für immer blockieren (oder bis eine echte LED-Änderung eintritt). Dieser Spezialfall kann durch Aufruf von `waitLED(ANY_OR_NONE)` behandelt werden, der zurückkehrt, sobald ein neuer LED-Zustand eintrifft, auch wenn dieser keine Änderung bewirkt.*
**Genug der Erklärungen, kommen wir zur Praxis … bevor wir das tun, müssen wir den Hardware-Aufbau etwas ändern:**
Schließen Sie ein externes Netzteil an den zweiten USB-Port des Raspberry Pi Zero (den äußeren) an. Dies stellt sicher, dass P4wnP1 nicht die Stromversorgung verliert, wenn es vom USB-Host getrennt wird, da es nicht mehr auf Busspannung angewiesen ist. Der USB-Port, der verwendet werden sollte, um P4wnP1 mit dem Ziel-USB-Host zu verbinden, ist der innerste der beiden Ports.
Starten Sie nun das folgende HIDScript```
P4wnP1_cli hid run -c 'while (true) {waitLED(ANY);type("Attached\n");}'
Trennen Sie P4wnP1 vom USB-Host (und stellen Sie sicher, dass es eingeschaltet bleibt)! Schließen Sie es wieder an den USB-Host an ... Jedes Mal, wenn Sie P4wnP1 wieder an den Host anschließen, sollte „Attached“ an den Host getippt werden.
Dies lehrt uns drei Fakten:
waitLED könnte als erster Befehl in Skripten verwendet werden, um mit dem Tippen zu beginnen, sobald der Tastaturtreiber bereit ist.waitLED ist nicht die perfekte Wahl, um HID-Skripte anzuhalten, bis eine LED-ändernde Taste auf dem USB-Host gedrückt wird, da gespeicherte Zustandsänderungen den Befehl auf unerwünschte Weise entsperren könnten.Da wir noch nicht mit dem waitLED-Befehl fertig sind, kümmern wir uns jetzt um den dritten Punkt. Verlassen wir die CLI.
http://172.24.0.1:8000)ms_snake.js ein sehr gutes Beispiel für die Leistungsfähigkeit LED-basierter Trigger ist).Ersetzen Sie das Skript im Editor-Fenster durch das folgende:``` return waitLED(ANY);
Nach dem Klicken auf die Schaltfläche 'Run' sollte auf der rechten Seite des Fensters ein neuer laufender HID-Job erscheinen. Wenn Sie die kleine "info"-Schaltfläche rechts neben dem HIDScript-Job drücken, können Sie Details sehen, wie den Status (sollte laufen), die Job-ID und die VM-ID (dies ist die Nummer der JavaScript-VM, die diesen Job ausführt. Es gibt 8 dieser VMs, sodass 8 HIDScripts parallel laufen könnten).
Wenn nun eine LED-Änderung vom USB-Host ausgegeben wird (durch Umschalten von NUM, CAPS oder SCROLL), sollte der HIDScript-Job enden. Er kann weiterhin unter den "Succeeded"-Jobs gefunden werden.
Wenn Sie die kleine "info"-Schaltfläche erneut drücken, sollten Informationen zum Ergebniswert (als JSON codiert) angezeigt werden, die etwa so aussehen:```
{"ERROR":false,"ERRORTEXT":"","TIMEOUT":false,"NUM":true,"CAPS":false,"SCROLL":false,"COMPOSE":false,"KANA":false}
Also gibt der Befehl waitLED ein JavaScript-Objekt zurück, das wie folgt aussieht:```
{
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)
}
In meinem Fall wurde `NUM` wahr. In Ihrem Fall war es vielleicht `CAPS`. Es spielt keine Rolle, welche LED es war. Was zählt, ist die Tatsache, dass der Rückgabewert die Möglichkeit bietet, die LED-Änderung zu untersuchen, die die Rückkehr des Befehls bewirkt, und somit könnte er verwendet werden, um Verzweigungsentscheidungen in Ihrem HIDScript zu treffen (basierend auf LED-Zustandsänderungen, die von der echten Tastatur des USB-Hosts ausgegeben werden). Versuchen wir ein Beispiel:```
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
}
}
Angenommen, das gegebene Skript läuft bereits, sollte das Drücken von NUM auf dem USB-Host dazu führen, dass "NUM has been toggled" ausgegeben wird, während das Drücken von SCROLL LOCK den getippten Text "SCROLL has been toggled" ergibt. Dieses Verhalten wiederholt sich, bis CAPS LOCK gedrückt wird und die resultierende LED-Änderung die Schleife abbricht und das HIDScript beendet.
Puhhh ... eine Menge Text zu diesem Befehl für einen einzigen HIDScript-Befehl, aber es bleiben noch einige Dinge übrig.
Wir haben Argumente wie NUM, ANY oder ANY_OR_NONE an den waitLED-Befehl übergeben, ohne weitere Erklärung.
waitLED akzeptiert bis zu zwei Argumente:
Das erste Argument, wie Sie vielleicht erraten haben, ist ein Whitelist-Filter für die zu überwachenden LEDs. Gültige Argumente sind:
ANY (auf eine Änderung einer der LEDs reagieren)ANY_OR_NONE (auf jeden neuen LED-Zustand reagieren, auch wenn es keine Änderung gibt)NUM (alle LED-Änderungen ignorieren, außer auf der NUM-LED)CAPS (alle LED-Änderungen ignorieren, außer auf der NUM CAPS)SCROLL (alle LED-Änderungen ignorieren, außer auf der NUM SCROLL)CAPS | NUM, NUM | SCROLLDas zweite Argument, das wir bisher nicht verwendet haben, ist eine Timeout-Dauer in Millisekunden. Wenn während dieser Timeout-Dauer keine LED-Änderung aufgetreten ist, kehrt waitLED zurück und setzt TIMEOUT: true im resultierenden Objekt (zusätzlich wird ERROR auf true gesetzt und ERRORTEXT weist auf einen Timeout hin).
Der folgende Befehl würde auf eine Änderung der NUM-LED warten, das Warten jedoch nach 5 Sekunden abbrechen:``` waitLED(NUM,5000)
Obwohl `waitLED` ein sehr mächtiger Befehl ist, wenn er richtig verwendet wird, hat er nicht bei unserer einfachen Aufgabe geholfen, ein HIDScript robust zu pausieren, bis eine state modifier key auf dem Ziel-USB-Host gedrückt wird (erinnern Sie sich: Wir wollten die Ausführung pausieren, um sicherzustellen, dass die unerwünschte "Person" hinausgeht, bevor die Eingabe beginnt, aber `waitLED` kam gelegentlich zu früh zurück, aufgrund von erhaltenen LED-Zustandsänderungen).
Hier kommt `waitLEDRepeat` ins Spiel und rettet die Situation.
Fügen Sie das folgende Skript in den Editor ein und versuchen Sie, den Befehl zurückkehren zu lassen. Überprüfen Sie danach die HIDScript-Ergebnisse.```
return waitLEDRepeat(ANY)
Sie werden schnell feststellen, dass dieselbe LED mehrmals häufig geändert werden muss, damit der Befehl waitLEDRepeat zurückkehrt. Der Befehl waitLEDRepeat würde nicht zurückkehren, wenn unterschiedliche LEDs ihren Zustand ändern oder wenn die Änderungen auf einer einzelnen LED zu langsam erfolgen.
Das Argument, das an waitLEDRepeat übergeben wird (im Beispiel ANY), dient demselben Zweck wie bei waitLED. Es ist ein Whitelist-Filter. Zum Beispiel würde waitLEDRepeat(NUM) nur bei Änderungen der NUM LOCK LED zurückkehren – egal wie schnell und oft Sie auf die CAPS LOCK-Taste hämmern, es würde nicht zurückkehren, es sei denn, NUM LOCK wird häufig gedrückt.
Standardmäßig muss eine der whitelistierten LEDs dreimal den Zustand ändern, und die Verzögerung zwischen zwei aufeinanderfolgenden Änderungen darf nicht größer als 800 Millisekunden sein, damit waitLEDRepeat zurückkehrt. Dieses Verhalten kann angepasst werden, indem zusätzliche Argumente wie in diesem Beispiel gezeigt übergeben werden:```
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
So interagiert man also mit LED-Reports eines USB-Hosts in HIDScript.
*Hinweis: `waitLEDRepeat` unterscheidet sich nicht von `waitLED`, was das Verbrauchen von erhaltenen LED-Zustandsänderungen betrifft.
Jedenfalls ist es viel schwieriger, es unbeabsichtigt auszulösen.*
Daher ist `waitLEDRepeat` die richtige Wahl, wenn die Aufgabe darin besteht, HIDScripts bis zum Eintreten einer menschlichen Interaktion anzuhalten. Natürlich kann es auch zur Verzweigung verwendet werden, da es dasselbe Rückgabewert-Objekt wie `waitLED` bereitstellt.
Bis zu diesem Punkt haben wir einiges an Wissen über HIDScript erlangt (natürlich nicht über alles, wir haben noch nicht einmal die Maussteuerungsfähigkeiten dieser Skriptsprache betrachtet). Wie auch immer, dieses Tutorial behandelt den Workflow und die grundlegenden Konzepte von P4wnP1 A.L.O.A. Daher sehen wir uns jetzt nicht mit anderen HIDScript-Funktionen weiter und machen weiter.
Fassen wir zusammen, was wir bisher über den Workflow und die Konzepte von P4wnP1 gelernt haben:
- Wir konnten Aktionen wie Tastatureingabe-Injektionen bei Bedarf über den CLI-Client starten.
- Wir konnten das Gleiche über den Webclient erreichen, während wir zusätzliche Kontrolle über HIDScript-Jobs hatten.
- Wenn wir ein externes Netzteil an P4wnP1 A.L.O.A. anschließen, können wir uns an verschiedene USB-Hosts an-/abmelden und bereits gestartete HIDScripts laufen nahtlos weiter.
- Wir konnten den USB-Stack genau nach unseren Bedürfnissen konfigurieren (und seine Konfiguration zur Laufzeit ändern, ohne P4wnP1 neu zu starten).
- Wir konnten Mehrzweck-HIDScripts mit komplexer Logik basierend auf JavaScript schreiben (mit Unterstützung für Funktionen, Schleifen, Verzweigungen usw.)
### 3. Workflow Teil 2 - Templating und TriggerActions
Bevor wir mit den anderen wichtigen Konzepten von P4wnP1 A.L.O.A. fortfahren, verfeinern wir unser erstes Ziel, das darin bestand, „eine Tastatureingabe-Injektion gegen einen USB-Host durchzuführen“:
- Das neue Ziel ist es, „Hello world“ in den Editor eines Windows-USB-Hosts (notepad.exe) einzutippen.
- Der Editor sollte von P4wnP1 geöffnet werden (nicht manuell vom Benutzer).
- Der Editor sollte automatisch geschlossen werden, wenn eine der Tastatur-LEDs des USB-Hosts umgeschaltet wird.
- Jedes Mal, wenn P4wnP1 an den USB-Host angeschlossen wird, sollte dieses Verhalten wiederholt werden (mit externem Netzteil, kein Neustart von P4wnP1).
- Der Vorgang sollte *nur einmal ausgeführt werden*, es sei denn, P4wnP1 wird erneut an den USB-Host angeschlossen, selbst wenn nach dem Start des HIDScripts aufeinanderfolgende Tastatur-LED-Änderungen auftreten.
- Selbst wenn P4wnP1 neu gestartet wird, sollte dasselbe Verhalten wiederherstellbar sein, ohne die Details des Setups erneut von Grund auf neu erstellen zu müssen.
Das Starten von Notepad, das Eintippen von „Hello world“ und das Schließen von Notepad nach einer LED-Änderung könnte mit dem, was wir bisher gelernt haben, erledigt werden. Ein entsprechendes HIDScript könnte etwa so aussehen:```
// 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
Das einzige Neue in diesem Skript ist der delay-Befehl, der nicht viel Erklärung benötigt. Er verzögert die Ausführung um die angegebene Anzahl Millisekunden.
Das Skript könnte in den HIDScript-Editor des Webclients eingefügt und mit „run“ gestartet werden, um es zu testen.
Es sollte wie beabsichtigt funktionieren, also sind wir fast fertig. Um das Skript auch nach einem Neustart wiederverwenden zu können, speichern wir es dauerhaft. Dies kann erreicht werden, indem man im HIDScript-Tab des Webclients auf den „store“-Button klickt. Nach Eingabe eines Namens (wir verwenden vorerst tutorial1) und Bestätigung des Dialogs sollte das HIDScript gespeichert sein. Wir können dies überprüfen, indem wir im Webclient auf den „Load & Replace“-Button klicken. Das gespeicherte Skript sollte in der Liste der gespeicherten Skripte unter dem Namen tutorial1.js erscheinen (die Erweiterung .js wird automatisch angehängt, falls sie nicht bereits im „store“-Dialog angegeben wurde).
Warnung: Wenn im Speicherdialog ein Name einer bereits vorhandenen Datei verwendet wird, wird die entsprechende Datei ohne weitere Nachfrage überschrieben.
Versuchen wir, das gespeicherte Skript mit dem CLI-Client aus einer SSH-Sitzung zu starten, etwa so:``` P4wnP1_cli hid run tutorial1.js
Dies hätte funktionieren sollen. Das bedeutet, es ist möglich, gespeicherte HIDScripts von allen Anwendungen zu starten, die Shell-Befehle unterstützen, oder von einem einfachen Bash-Skript, indem der P4wnP1 A.L.O.A. CLI-Client verwendet wird.
Es wäre sogar möglich, das Skript remote von einem für Windows kompilierten CLI-Client zu starten. Angenommen, der Windows-Host kann P4wnP1 A.L.O.A. über WiFi erreichen und die IP von P4wnP1 ist auf `172.24.0.1` gesetzt, dann würde der entsprechende Befehl wie folgt aussehen:```
P4wnP1_cli.exe --host 172.24.0.1 hid run tutorial1.js
Anmerkung: Zum Zeitpunkt der Erstellung dieses Textes habe ich noch nicht entschieden, ob P4wnP1 A.L.O.A. eine CLI-Binärdatei für jede mögliche Plattform und Architektur ausliefert. Es ist jedoch wahrscheinlich, dass vorkompilierte Versionen für die wichtigsten Plattformen bereitgestellt werden. Falls nicht – das ist kein großes Problem, da die Cross-Kompilierung des Go-Codes des CLI-Clients weniger als eine Minute dauert.
Der nächste Schritt besteht darin, das Skript jedes Mal erneut ausführen zu lassen, wenn P4wnP1 wieder an einen USB-Host angeschlossen wird. Ein Ansatz, den wir bereits verwendet haben, um ein solches Verhalten zu erreichen, bestand darin, alles in eine Schleife zu packen und ein waitLED(ANY_OR_NONE) voranzustellen. Das waitLED(ANY_OR_NONE) stellte sicher, dass die Schleife nur fortgesetzt wird, wenn der Ziel-USB-Host durch Senden einer Aktualisierung des globalen Tastatur-LED-Status signalisiert, dass der Tastaturtreiber bereit ist, Eingaben zu empfangen. Ein entsprechend modifiziertes Skript könnte wie folgt aussehen:```
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 }
Das oben angegebene Skript würde zwar jedes Mal ausgeführt, wenn P4wnP1 an einen USB-Host angeschlossen wird. Aber das Skript ist nicht sehr robust, weil ein zweites `waitLED` eingebaut ist, das darauf wartet, dass notepad.exe wieder geschlossen wird.
Auf diese Weise ergeben sich mehrere Probleme. Wenn P4wnP1 beispielsweise getrennt wird, bevor "Hello world" getippt ist, würde das jetzt blockierende `waitLED` dasjenige vor `press("ALT F4")` sein, und die Ausführung würde an genau dieser Stelle des HIDScripts fortgesetzt, sobald P4wnP1 wieder an einen (möglicherweise anderen) USB-Host angeschlossen wird.
Ein endgültiges Ausschlusskriterium für den gewählten Ansatz ist das folgende Problem: Die Anforderung, dass das Skript nur einmal nach dem Anschließen von P4wnP1 an einen USB-Host ausgeführt werden soll, konnte nicht erfüllt werden, da mehrmaliges Drücken von NUM LOCK das Skript immer wieder neu starten würde.
Wie lösen wir das also?
#### Führen wir TriggerActions ein
Die Lösung des Problems sind sogenannte "TriggerActions". Wie der Name schon sagt, löst dieses Workflow-Konzept von P4wnP1 A.L.O.A. Aktionen basierend auf vordefinierten Triggern aus.
Um eine Vorstellung davon zu bekommen, wovon ich spreche, gehen Sie zur Registerkarte "TRIGGER ACTIONS" im Webclient. Je nach aktueller Konfiguration können dort bereits TriggerActions existieren. Bestehende TriggerActions kümmern uns jetzt nicht.
Klicken Sie auf die Schaltfläche "ADD ONE", und eine neue TriggerAction sollte hinzugefügt und sofort im Bearbeitungsmodus geöffnet werden.
Die neue TriggerAction ist standardmäßig deaktiviert und muss aktiviert werden, um sie bearbeitbar zu machen. Also schalten wir den Aktivierungsschalter um.
Wählen Sie nun aus dem Pulldown-Menü "Trigger" die Option "USB gadget connected to host" aus. Die Aktion sollte eine Voreinstellung von "write log entry" haben. Wir belassen es dabei und klicken auf die Schaltfläche "Update".
Die neu hinzugefügte TriggerAction sollte jetzt in der TriggerActions-Übersicht sichtbar sein (die mit der höchsten ID) und eine Zusammenfassung des ausgewählten Triggers und der ausgewählten Aktion in lesbarer Form anzeigen.
Um zu testen, ob die neu definierte TriggerAction funktioniert, navigieren Sie zur Registerkarte "Event Log" des Webclients.
Stellen Sie sicher, dass Sie den Webclient über WLAN (nicht USB Ethernet) geöffnet haben. Versorgen Sie P4wnP1 mit externer Spannung, trennen Sie es vom USB-Host und schließen Sie es wieder an. Jedes Mal, wenn P4wnP1 an einen USB-Host angeschlossen wird, sollte sofort eine Log-Nachricht an den Client gesendet werden.
Wenn Sie dies einige Male wiederholt haben, ist Ihnen vielleicht aufgefallen, dass der Trigger "USB gadget connected to host" sehr schnell auslöst (oder in einem frühen Stadium der USB-Enumeration). Genauer gesagt: Wenn dieser Trigger auslöst, ist bekannt, dass P4wnP1 mit einem USB-Host verbunden war, aber es gibt keine Garantie, dass der USB-Host alle benötigten USB-Gerätetreiber laden konnte.
**Tatsächlich ist es sehr unwahrscheinlich, dass der USB-Tastaturtreiber geladen ist, wenn der Trigger auslöst. Das müssen wir im Hinterkopf behalten.**
Bevor wir mit unserer Aufgabe fortfahren, führen wir einen zusätzlichen Test durch. Gehen Sie zurück zur Registerkarte "TriggerAction" und drücken Sie die kleine blaue Schaltfläche, die wie ein Stift aussieht, für unsere neu erstellte TriggerAction. Wir landen wieder im Bearbeitungsmodus.
Dieses Mal aktivieren wir die Option `One shot`. Gehen Sie danach zurück zum "Event Log", trennen Sie P4wnP1 erneut vom USB-Host und schließen Sie es wieder an. Dieses Mal sollte die TriggerAction nur einmal auslösen. Egal, wie oft P4wnP1 danach wieder an den USB-Host angeschlossen wird, es sollte keine neue Log-Nachricht erstellt werden, die eine USB-Verbindung anzeigt.
Es ist erwähnenswert, dass eine "One shot" TriggerAction nach dem Auslösen des Triggers nicht gelöscht wird. Stattdessen wird die TriggerAction wieder deaktiviert. Durch erneutes Aktivieren kann eine TriggerAction wiederverwendet werden, ohne sie neu zu definieren. Es geht nichts verloren, bis die rote "Mülleimer"-Schaltfläche einer TriggerAction gedrückt wird, was die betreffende TriggerAction löscht.
**Warnung: Wenn die Lösch-Schaltfläche für eine TriggerAction angeklickt wird, wird die TriggerAction ohne weitere Bestätigung dauerhaft gelöscht.**
An dieser Stelle machen wir das Offensichtliche. Wir bearbeiten die erstellte TriggerAction und wählen "start a HIDScript" anstelle von "write log entry" für die auszuführende Aktion. Zusätzlich deaktivieren wir wieder "one-shot". Ein neues Eingabefeld namens "script name" wird angezeigt. Ein Klick auf dieses Eingabefeld öffnet einen Auswahldialog für alle gespeicherten HIDScripts, einschließlich unseres zuvor erstellten `tutorial1.js` HIDScripts.
*Bevor wir testen, ob das funktioniert, möchte ich eine kurze Anmerkung zur Aktion "write log entry" machen: P4wnP1 A.L.O.A. verfolgt nicht, welche Trigger bereits ausgelöst wurden. Das bedeutet, dass die von einer "write log entry"-Aktion erstellten Logeinträge an alle lauschenden Clients ausgeliefert werden, aber vom P4wnP1-Dienst nicht gespeichert werden (aus verschiedenen Gründen). Der Webclient seinerseits speichert den Logeintrag, bis der Webclient selbst neu geladen wird. Gleiches gilt für Ereignisse, die mit HIDScript-Jobs zusammenhängen. Wenn ein HIDScript endet (mit Erfolg oder Fehler), wird ein Ereignis an alle derzeit geöffneten Webclients gesendet. Zusammenfassend hat jeder Webclient einen Laufzeitzustand, der mehr Informationen enthält als der Kerndienst selbst. Wenn der Laufzeitzustand des Webclients zu groß wird (zu viel Speichernutzung), muss man nur den Client neu laden, um "historische" Zustandsinformationen zu löschen. Wenn der Kerndienst sich genauso verhalten und alle historischen Informationen speichern würde, würde er sehr schnell keine Ressourcen mehr haben. Daher gilt dieses Konzept für die meisten Subsysteme von P4wnP1 A.L.O.A.*
Kehren wir nun zu unserer Aufgabe zurück. Wir haben eine TriggerAction bereit, die unser HIDScript jedes Mal auslösen sollte, wenn P4wnP1 an einen USB-Host angeschlossen wird.
Abhängig vom Ziel-USB-Host funktioniert das mehr oder weniger zuverlässig. In meiner Testumgebung hat es überhaupt nicht funktioniert, und das hat einen Grund:
Sehen wir uns die ersten Zeilen unseres HIDScripts an:```
// 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 ...
Unter Berücksichtigung der Tatsache, dass der Trigger "USB-Gadget verbunden" in der frühen USB-Erkennungsphase ausgelöst wird und der Tastaturtreiber des USB-Hosts noch nicht unbedingt geladen wurde, wird das Problem offensichtlich. Wir müssen dem Skript eine Art Verzögerung voranstellen, um sicherzustellen, dass der Tastaturtreiber aktiv ist (andernfalls würden unsere Tastatureingaben im Nirgendwo landen).
Da wir bereits wissen, dass es nicht möglich ist, die optimale Verzögerung vorherzusagen, verwenden wir den waitLED(ANY_OR_NONE)-Ansatz, der weiter oben erläutert wurde. Das neue Skript sieht wie folgt aus:```
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
Das Speichern des modifizierten Skripts unter dem exakt gleichen Namen (`tutorial1`) überschreibt das vorherige HIDScript ohne weitere Bestätigung, wie bereits erwähnt. Daher besteht keine Notwendigkeit, unsere TriggerAction anzupassen, da sich der HIDScript-Name, auf den sich die TriggerAction bezieht, nicht geändert hat.
Mit dieser kleinen Änderung sollte alles wie gewünscht funktionieren und das Skript sollte jedes Mal ausgelöst werden, wenn wir uns an einen USB-Host anschließen, aber nur einmal ausgeführt werden.
Wenn P4wnP1 nun neu gestartet wird oder die Stromversorgung verliert, würde unser HIDScript überleben, da wir es persistent gespeichert haben, aber die TriggerAction wäre verschwunden. Es versteht sich von selbst, dass TriggerActions ebenfalls persistent gespeichert werden könnten.
Der "Speichern"-Button im Reiter "TriggerAction" funktioniert genau wie der im HIDScript-Editor. Es sei darauf hingewiesen, dass *alle aktuell aktiven TriggerActions* gespeichert werden, wenn der "Speichern"-Dialog bestätigt wird (einschließlich der deaktivierten).
Die bewährte Vorgehensweise ist, alle TriggerActions zu löschen, die nicht zur aktuell fokussierten Aufgabe gehören, bevor gespeichert wird (sie sollten zuvor gespeichert worden sein, falls nötig) und nur die kleine Menge an TriggerActions zu speichern, die für die aktuelle Aufgabe relevant sind, unter Verwendung eines geeigneten Namens. Es gibt zwei Optionen, um gespeicherte TriggerActions wieder in die aktiven zu laden:
- "load & replace" löscht alle aktiven TriggerActions und lädt nur die gespeicherten
- "load & add" behält die bereits aktiven TriggerActions und fügt die gespeicherten hinzu. Somit könnte "load & add" verwendet werden, um einen komplexen TriggerAction-Satz aus kleineren Sätzen aufzubauen. Der resultierende Satz könnte dann wieder gespeichert werden.
Fürs Erste sollten wir nur unsere einzelne TriggerAction speichern, die das HIDScript startet. Der Name, den wir zum Speichern verwenden, ist wieder `tutorial1` und wird nicht mit dem HIDScript namens `tutorial1` kollidieren.
Bestätigen Sie den erfolgreichen Speichervorgang, indem Sie auf den "load&replace"-Button im Reiter "TriggerAction" klicken. Der gespeicherte TriggerAction-Satz sollte in der Liste sein und den Namen `tutorial1` tragen.
**Warnung: Die TriggerAction-"Laden"-Dialoge erlauben das Löschen gespeicherter TriggerActions durch Klicken auf den roten "Mülleimer"-Button neben jeder Aktion. Das Klicken auf den Button löscht den entsprechenden TriggerAction-Satz dauerhaft, ohne weitere Bestätigung**
An diesem Punkt könnten wir unsere TriggerAction sicher aus dem Reiter "TriggerActions" löschen (!!nicht mit dem Mülleimer-Button aus einem der Lade-Dialoge!!).
Wenn die TriggerAction aus den aktiven gelöscht ist, passiert nichts, wenn wir P4wnP1 vom USB-Host trennen und wieder anschließen.
Trotzdem wird der gespeicherte TriggerAction-Satz `tutorial1` Neustarts überdauern und kann jederzeit neu geladen werden.
Anstatt den TriggerAction-Satz über den Webclient neu zu laden, versuchen wir, dies mit dem CLI-Client zu erreichen.
Werfen wir einen kurzen Blick auf den Hilfebildschirm des Unterbefehls `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")
Der Nutzungsbildschirm zeigt, dass TriggerAction-Vorlagen mit dem Flag -t bereitgestellt werden können. Wir führen den folgenden Befehl aus, um den gespeicherten TriggerAction-Satz wiederherzustellen:```
P4wnP1_cli template deploy -t tutorial1
Die TriggerAction, die HIDScript bei USB-Host-Verbindungen auslöst, ist jetzt wieder geladen und sollte im
TriggerActions-Tab des Webclients angezeigt werden. Wenn P4wnP1 A.L.O.A. an einen USB-Host angeschlossen wird, sollte das Skript erneut ausgeführt werden.
Speichern, Laden und Bereitstellen von Vorlagen ist eines der beiden Hauptkonzepte hinter dem Automatisierungsworkflow von P4wnP1,
das andere sind die bereits bekannten TriggerActions. Es ist erwähnenswert, dass nicht nur TriggerAction-Sets als Vorlagen gespeichert und geladen werden können, sondern dass TriggerActions verwendet werden können, um bereits gespeicherte Vorlagen bereitzustellen, falls das sinnvoll ist.
Wenn wir unsere Aufgaben noch einmal betrachten, scheinen alle definierten Anforderungen nun erfüllt zu sein:
- wir haben "Hello world" in den Editor eines Windows-USB-Hosts eingegeben
- der Editor wird von P4wnP1 geöffnet, nicht manuell vom Benutzer
- der Editor wird automatisch geschlossen, sobald eine der Tastatur-LEDs einmal umgeschaltet wird
- jedes Mal, wenn P4wnP1 an einen USB-Host angeschlossen wird, wiederholt sich dieses Verhalten
- das HIDScript wird nur einmal ausgeführt, es sei denn, P4wnP1 wird erneut an den USB-Host angeschlossen, selbst wenn aufeinanderfolgende Tastatur-LED-Änderungen auftreten
- wenn P4wnP1 neu gestartet wird, kann das gleiche Verhalten durch Laden des gespeicherten TriggerAction-Sets (das wiederum auf das gespeicherte HIDScript verweist) wiederhergestellt werden. Dies kann entweder mit einem einzelnen CLI-Befehl oder mit einem einfachen "load&add" oder "load&replace" aus dem Trigger-Action-Tab des Webclients erreicht werden.
Fügen wir noch einmal zusätzliche Ziele hinzu:
- es sollte sichergestellt werden, dass die USB-Konfiguration die Tastaturfunktion aktiviert hat (das aktuelle Setup tut dies nicht und die TriggerAction könnte das HIDScript nicht starten, falls die USB-Tastatur deaktiviert ist)
- das erstellte Setup sollte beim Booten von P4wnP1 A.L.O.A. angewendet werden, ohne dass das TriggerAction-Set manuell geladen werden muss. Das Setup muss einen Neustart von P4wnP1 überstehen.
Um die beiden zusätzlichen Ziele zu erreichen, müssen wir uns in ein neues Thema einarbeiten und ...
#### Master-Vorlagen und Startup-Master-Vorlage einführen
Bevor wir uns mit Master-Vorlagen befassen, machen wir etwas, das wir noch nicht getan haben, weil bisher alles wie gewünscht funktioniert hat: Wir definieren eine gültige USB-Konfiguration passend zu unserer Aufgabe!
- Seriennummer des Geräts: 123456789
- Produktname des Geräts: Auto Writer
- Hersteller des Geräts: The Creator
- Produkt-ID: 0x9876
- Anbieter-ID: 0x1D6B
- aktivierte USB-Funktionen
- HID-Tastatur
- HID-Maus
Werfen wir zunächst einen Blick auf den Verwendungsbildschirm des CLI-Befehls, der verwendet werden kann, um diese Einstellungen bereitzustellen:```
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")
Der Befehl hat eine Reihe von Flags, aber es gibt auch eine Reihe von änderbaren USB-Einstellungen. Das Bereitstellen unseres definierten USB-Setups könnte so mit der CLI erfolgen:``` 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
Das Ergebnis der (längeren) Befehlsausgabe zeigt die resultierenden USB-Einstellungen. Überprüfen wir den "USB settings"-Tab des
Webclients, um zu bestätigen, dass sie übernommen wurden. Alle Änderungen sollten widergespiegelt sein, wenn nichts schiefgegangen ist.
Obwohl es durchaus möglich ist, ein USB-Setup über die CLI zu deployen, bietet die Nutzung des Webclients gegenüber der CLI
einige Vorteile. In diesem Fall:
- das Ändern der Einstellungen über den Webclient ist einfacher und bequemer
- der Webclient hält einen internen Einstellungszustand, was die Definition von USB-Einstellungen ohne tatsächliches Deployen ermöglicht (die
CLI hingegen konnte Einstellungen nur durch Deployen manipulieren. Dies setzt wiederum den gesamten USB-Stack von
P4wnP1 und alle davon abhängigen Funktionen zurück. Z. B. würde ein bereits laufendes HIDScript unterbrochen oder USB-Netzwerkschnittstellen
werden neu bereitgestellt
- die aktuellen Einstellungen des Webclients könnten in einer persistenten Vorlage gespeichert werden, ohne sie vorher zu deployen
- der CLI-Client (derzeit) kann keine USB-Einstellungen speichern
In unserem aktuellen Fall ist es offensichtlich die bessere Wahl, den Webclient für die benötigten Änderungen an den USB-Einstellungen zu verwenden.
Das Gute am CLI-Ansatz (den wir hier bereits verwendet haben): Da die CLI uns gezwungen hat, die USB-Einstellungen zu deployen, konnten wir
bestätigen, dass sie funktionieren, bevor wir sie in einer persistenten Vorlage speichern.
Fahren wir mit dem Speichern der USB-Einstellungen fort:
Wir klicken erneut auf den "store"-Button, diesmal im "USB settings"-Tab. Wieder nennen wir die Vorlage `tutorial1` (es
gibt keinen Konflikt mit der TriggerAction-Vorlage, die unter demselben Namen gespeichert ist, da ein anderer Namensraum für
USB-Einstellungen verwendet wird).
Jetzt haben wir zwei neue und dauerhaft gespeicherte Vorlagen:
1) eine Vorlage für das TriggerAction-Set, genannt `tutorial1`
2) eine Vorlage für die USB-Einstellungen, ebenfalls genannt `tutorial1`
Angenommen, der Zustand (der aktuellen USB-Einstellungen, TriggerActions oder beider) hat sich irgendwie geändert, könnten wir beide
gespeicherten Einstellungen auf einmal neu laden, indem wir den folgenden CLI-Befehl ausführen:```
P4wnP1_cli template deploy --usb tutorial1 --trigger-actions tutorial1
Der Befehl P4wnP1 template deploy könnte eine Vorlage für jedes der Subsysteme von P4wnP1 A.L.O.A. in einem einzigen Durchlauf laden (für das Netzwerk-Subsystem könnten mehrere Vorlagen geladen werden, eine pro Adapter). Das Bereitstellen von Vorlagen für verschiedene Subsysteme wird als eine häufige Aufgabe bei der Arbeit mit P4wnP1 A.L.O.A. angesehen, da es in den meisten Fällen notwendig sein sollte, mehrere Subsysteme neu zu konfigurieren, um ein einzelnes Ziel zu erreichen. Um dem Rechnung zu tragen, wurden sogenannte Master-Vorlagen eingeführt.
Eine Master-Vorlage könnte bestehen aus:
Eine Master-Vorlage könnte mit dem "Master-Vorlagen-Editor" auf der Registerkarte "Allgemeine Einstellungen" des Webclients definiert, gespeichert oder geladen werden. Die Verwendung des Webclients ist eine bequeme Möglichkeit, Master-Vorlagen zu definieren, da er Sie unterstützt, indem er nur die Auswahl von Vorlagen erlaubt, die bereits für die jeweiligen Subsysteme gespeichert wurden (und derzeit ist der Webclient der einzige Weg, um Master-Vorlagen zu definieren).
Definieren wir also eine Master-Vorlage für unsere aktuelle Aufgabe:
tutorial1 aus und bestätigen Sie mit "OK"tutorial1 (dies ist eine andere Vorlage für das USB-Subsystem, obwohl sie denselben Namen wie die für die TriggerActions trägt)tutorial1 angebenUm zu bestätigen, dass die Vorlage gespeichert wurde, können Sie die Schaltfläche "Gespeicherte laden" verwenden – die Vorlage sollte in der Auswahl aufgeführt sein. Schließen Sie den Dialog "Gespeicherte laden" wieder.
Klicken Sie nun auf die Schaltfläche "Gespeicherte bereitstellen", wählen Sie die Vorlage mit dem Namen startup und bestätigen Sie mit "OK".
Im Gegensatz zur Funktion "Gespeicherte laden", die eine gespeicherte Vorlage in den Master-Vorlagen-Editor lädt, wendet die Funktion "Gespeicherte bereitstellen" alle Einstellungen einer Master-Vorlage sofort auf die entsprechenden Subsysteme von P4wnP1 an (ohne sie überhaupt in den Master-Vorlagen-Editor zu laden).
Da die startup-Master-Vorlage die aktuellen WiFi-Einstellungen überschreibt, könnte es passieren, dass Sie die Verbindung zum Webclient verloren haben und sich erneut mit dem P4wnP1-WiFi-Netzwerk verbinden müssen.
Sobald Sie sich erfolgreich wieder verbunden haben und die aktuellen USB-Einstellungen und aktuellen TriggerActions überprüfen, wurden die zuvor gespeicherten Einstellungen durch die Untereinstellungen der startup-Master-Vorlage überschrieben.
Es gibt zwei Möglichkeiten, die tutorial1-Master-Vorlage erneut bereitzustellen:
startup-Master-Vorlage gemacht)P4wnP1_cli template deploy --full tutorial1 (das --full-Flag ist ein Alias für Master-Vorlage)Dadurch, dass wir die Master-Vorlage tutorial1 bereitstellen können, haben wir bereits eines unserer neuen Ziele erreicht:
Es ist sichergestellt, dass die USB-Konfiguration die Tastaturfunktionalität aktiviert hat, wenn wir unser Tastatureingabe-Setup laden.
Eine kurze Zusammenfassung, wie das funktioniert:
tutorial1 lädt USB-Einstellungen namens tutorial1, die Folgendes haben
tutorial1 lädt ein TriggerAction-Set mit einer einzigen TriggerAction
tutorial1.js jedes Mal, wenn P4wnP1 an einen USB-Host angeschlossen wird
waitLED-Trigger ausgelöst wird (Tastaturtreiber bereit) und endet nach einer darauf folgenden LED-ÄnderungDas einzig verbleibende Ziel ist folgendes: Das erstellte Setup sollte beim Booten von P4wnP1 A.L.O.A. angewendet werden, ohne dass das manuelle Laden des TriggerAction-Sets erforderlich ist. Das Setup muss einen Neustart von P4wnP1 überstehen.
Dieses Ziel könnte jetzt ziemlich einfach erreicht werden. Die Registerkarte "Allgemeine Einstellungen" des Webclients zeigt eine Karte namens Startup-Master-Vorlage. Das Ändern der Startup-Master-Vorlage auf tutorial1 an dieser Stelle hätte sofortige Auswirkungen und würde höchstwahrscheinlich die funktionierende Boot-Konfiguration von P4wnP1 A.L.O.A. zerstören.
Wichtig: Wenn eine Master-Vorlage Untervorlagen leer lässt (z. B. wenn keine Bluetooth-Vorlage ausgewählt ist), wird das entsprechende Subsystem nicht neu konfiguriert, wenn die Master-Vorlage geladen wird. Dies ist zwar praktisch für die Laufzeit-Neukonfiguration, ohne bereits laufende Subsysteme wie den USB-Stack oder den WiFi-Stack zurückzusetzen, wenn dies nicht erforderlich ist, aber Master-Vorlagen, die als Startup-Master-Vorlage verwendet werden, hinterlassen Subsysteme ohne definierte Vorlagen in einem UNDEFINIERTEN ZUSTAND. Wenn beispielsweise keine gültige WiFi-Vorlage bereitgestellt wird, ist es unwahrscheinlich, dass P4wnP1 A.L.O.A. nach dem Neustart über WiFi erreichbar ist
Bevor wir unsere neue tutorial1-Master-Vorlage als Startup-Master-Vorlage einsetzen, stellen wir sicher, dass für die anderen Subsysteme korrekte Einstellungen geladen werden. Wir gehen dazu wie folgt vor:
tutorial1-Vorlage erneut in den Editor.tutorial1 für "TriggerActions-Vorlage" und für "USB-Vorlage" gesetzt habenstartup ausstartup ausbteth_startupusbeth_startupwlan0_startup_dhcp_servertutorial1-Master-Vorlage mit den neuen Einstellungen (klicken Sie auf "Speichern", geben Sie tutorial1 ein und bestätigen Sie mit "OK")tutorial1 auswählen. Alle Unterabschnitte der geladenen Master-Vorlage sollten wie hier beschrieben aussehen.Jetzt sind wir bereit, unsere neue Master-Vorlage als Startup-Master-Vorlage einzusetzen. Nachdem wir dies getan haben, klicken wir auf die Schaltfläche "Neustart".
Nach dem Neustart sollte P4wnP1 A.L.O.A. das HIDScript automatisch auslösen (und sollte immer noch über WiFi erreichbar sein, um eine Neukonfiguration zu ermöglichen).
Herzlichen Glückwunsch, alle Ziele erreicht
Sie haben die grundlegenden Workflow-Konzepte von P4wnP1 A.L.O.A. kennengelernt.
Es ist derzeit nicht möglich, eine vollständige Dokumentation bereitzustellen. Hier sind also einige Kommentare zu Themen, die noch nicht behandelt wurden, aber eine Untersuchung wert sind.
P4wnP1 ermöglicht das Ausführen von BashScripts über TriggerActions. Die Skripte, die von TriggerActions verwendbar sind, befinden sich in /usr/local/P4wnP1/scripts. Wenn ein Skript von einer TriggerAction aufgerufen wird, werden mehrere Argumente (wie der eigentliche Trigger) über Bash-Variablen übergeben. Die Datei /usr/local/P4wnP1/scripts/trigger-aware.sh bietet ein gutes Beispiel für ein Bash-Skript, das je nach aufrufendem Trigger unterschiedlich reagiert. Es lohnt sich, einen Blick auf dieses Skript zu werfen, da es alle derzeit verfügbaren "TriggerAction-Variablen" verwendet.
Die Community der alten P4wnP1-Version kam gelegentlich mit Hardware-Mods oder Erweiterungen des Raspberry Pi und der Frage auf, wie man sie integrieren kann. Es ist für mich nicht möglich, eine generische Lösung für dieses Problem bereitzustellen. Es ist auch keine gute Idee, Support für eine sehr spezifische Hardware-Erweiterung zu bieten, die nur von wenigen Leuten genutzt wird. Mit der Einführung von TriggerAction kam die Idee auf, GPIO sowohl als Trigger über GPIO-Eingang als auch als Aktionen, die GPIO-Ausgang ausgeben, zu unterstützen. Obwohl nicht für die erste Veröffentlichung geplant, wurde diese Funktion bereits implementiert. Ich hatte noch keine Zeit, sie zu dokumentieren, und es könnte leicht passieren, dass sich einige Dinge ändern. Die Funktionalität verwendet die "periph.io"-Bibliothek mit einigen kleinen Erweiterungen (angepasste Flankenerkennung mit eigenem Entprellen für GPIO, Danke an @marcaruel für den Austausch hierzu).
Die in P4wnP1 A.L.O.A. enthaltene WiFi-Firmware wurde modifiziert (unter Verwendung des nexmon-Frameworks), um KARMA zu unterstützen. Diese Funktion hat es bisher nicht in den Kern geschafft (erfordert etwas Überarbeitung auf Firmware-Seite) und ist daher weder über den Webclient noch über die CLI verfügbar. Wenn Sie mit den Karma-Funktionen herumspielen möchten, gibt es ein altes Python-CLI, mit dem die KARMA-Optionen im laufenden Betrieb eingestellt werden können. Das Python-Skript finden Sie hier:
/usr/local/P4wnP1/legacy/karmatool.py
Tipp: Um das Beste aus der KARMA-Funktionalität herauszuholen, sollten Sie P4wnP1 A.L.O.A. so einrichten, dass ein WiFi-Zugangspunkt ohne Authentifizierung bereitgestellt wird, da es sonst nicht viel Sinn ergibt. Für armes Beacon-Flooding ist dies nicht erforderlich, aber (statische) benutzerdefinierte SSIDs für Beaconing sind in ihrer Anzahl begrenzt (Ressourcenschonung auf dem WiFi-Chip).
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
Der WiFi-Covert-Channel wurde nicht nach Go portiert und ist nicht Teil des P4wnP1-Kerns. Dennoch wird die Legacy-Funktionalität bereitgestellt. Damit der Covert-Channel läuft, müssen mehrere Bedingungen erfüllt sein:
- Eine Tastatureingabe-Injektion (Keystroke Injection) muss auf dem Ziel-Client durchgeführt werden, um Stage1 zu injizieren.
- Stage1 lädt Stage2 über eine (vereinfachte Version) des HID-Covert-Channels, daher muss ein spezielles USB-HID-Gerät bereitgestellt und ein spezieller HID-Covert-Channel-Server auf P4wnP1 gestartet werden, um Stage2 bereitzustellen.
- Ein zweiter Server muss gestartet werden und mit der modifizierten WiFi-Firmware interagieren, um Clients zu verwalten, die sich über den WiFi-Covert-Channel verbinden, und diesen Clients interaktiven Shell-Zugriff zu bieten (der Server ist eine Konsolenanwendung, die in einem Terminal-Multiplexer wie `screen` ausgeführt werden soll).
Alle zuvor genannten Bedingungen könnten mit dem Funktionsumfang von P4wnP1 A.L.O.A. erfüllt werden, sofern die benötigten Komponenten (HID-Stager, WiFi-Cover-Channel-Server, Client-Agent zur Auslieferung) bereitgestellt werden.
Eine solche Aufgabe mit P4wnP1 A.L.O.A. durchzuführen, ist ein hervorragendes Beispiel für seine Fähigkeiten. Zudem hilft es zu unterscheiden, wofür P4wnP1 A.L.O.A. gedacht ist und wofür nicht.
P4wnP1 A.L.O.A. ist nicht dazu gedacht:
- ein "bewaffnetes" Werkzeug zu sein
- RTR-Payloads bereitzustellen, die von jedem ohne Verständnis der Vorgänge oder der damit verbundenen Risiken ausgeführt werden könnten
P4wnP1 A.L.O.A. ist dazu gedacht:
- eine flexible, kostengünstige, handtellergroße Plattform zu sein
- als Wegbereiter für Aufgaben wie die hier beschriebene zu dienen
- die Prototypenerstellung, das Testen und die Durchführung aller Arten von USB-bezogenen Aufgaben zu unterstützen, die üblicherweise bei Pentest- oder Redteam-Einsätzen verwendet werden, ohne eine fertige statische Lösung bereitzustellen
In gewisser Hinsicht beherbergt der Ordner `/usr/local/P4wnP1/legacy` die benötigten externen Werkzeuge zum Ausführen des WiFi-Covert-Channels (nämlich den WiFi-Server, den HID-Covert-Channel-Stager-Server und den WiFi-Covert-Channel-Client-Agent). Diese Komponenten können als externe Teile betrachtet werden (gehören nicht zum P4wnP1 A.L.O.A.-Kern).
Zusätzlich bietet P4wnP1 A.L.O.A. eine Konfiguration, die die gegebenen Komponenten nutzt, um Folgendes zu tun:
- Drive-by gegen Windows-Hosts, um In-Memory-Client-Code auszuliefern, der Stage2 über den HID-Covert-Channel herunterlädt, basierend auf Keystroke-Injection (HIDScript)
- Starten der Keystroke-Injection, sobald P4wnP1 an einen USB-Host angeschlossen wird (TriggerAction, die HIDScript ausgibt)
- Starten des Stagers, der den WiFi-Covert-Channel-Client-Agent über den HID-Covert-Channel ausliefert, sobald die Keystroke-Injection beginnt (TriggerAction, die ein Bash-Skript ausführt, das wiederum den externen Server startet)
- Starten des WiFi-Cover-Channel-Servers, wenn nötig (gleiche TriggerAction und BashScript)
- Bereitstellen eines USB-Setups, das eine USB-Tastatur (zur Keystroke-Injection) und ein zusätzliches rohes HID-Gerät (dient als Covert-Channel für die Stage2-Auslieferung) bereitstellt – die USB-Einstellungen sind in einer Einstellungsvorlage gespeichert
- Bereitstellen eines WiFi-Setups, das Fernzugriff auf P4wnP1 ermöglicht, um die Interaktion mit dem CLI-Frontend des WiFi-Covert-Channel-Servers zu erlauben – die WiFi-Einstellungen sind in einer Einstellungsvorlage gespeichert
- Bereitstellen eines einzelnen Einstiegspunkts, um alle benötigten Konfigurationen auf einmal bereitzustellen (durchgeführt von einer Master-Vorlage, die aus den richtigen WiFi-Einstellungen, den richtigen USB-Einstellungen und den TriggerActions zum Starten des HIDScripts besteht)
Die Master-Vorlage heißt "wifi covert channel". Durch Bereitstellung über den "generic settings"-Tab des Webclients ("DEPLOY STORED" aus dem Master Template Editor) ist P4wnP1 A.L.O.A. bereit konfiguriert, um alle beschriebenen Schritte auszuführen.
Sobald es wieder an einen USB-Host angeschlossen wird, sollte es beginnen, Stage1 zu tippen und die entsprechenden Server werden intern gestartet.
Von einer SSH-Sitzung (z. B. über WiFi) aus kann der WiFi-Covert-Channel-Server mit `screen -d -r wifi_c2` aufgerufen werden, um mit Clients zu interagieren, die sich über den WiFi-Covert-Channel zurückverbunden haben.
Da die Keystroke-Injection vom Sprachlayout des USB-Hosts abhängt, hat das entsprechende HIDScript namens `wifi_covert_channel.js` eine Variable `language`, mit der das verwendete Tastaturlayout angepasst werden kann. Zusätzlich gibt es eine Variable namens `hide` (standardmäßig false). Wenn `hide` auf true gesetzt wird, wird das Konsolenfenster auf dem Client ausgeblendet, während Stage1 getippt wird. Dies zeigt wiederum, wie komplexe Aufgaben auf eine einfache boolesche Variable reduziert werden können, dank HIDScript und der zugrunde liegenden JavaScript-Engine.
Die mit P4wnP1s Master-Vorlagen bereitgestellte Demo "wifi covert channel" kann auch als Startup-Master-Vorlage verwendet werden, da WiFi-Zugriff weiterhin möglich ist und das Setup daher jederzeit aus der Ferne geändert werden kann.
Das beteiligte BashScript, das von einer TriggerAction aufgerufen wird, ist ein gutes Beispiel dafür, wie flexibel der CLI-Client werden kann. Da der HID-Stager wissen muss, auf welcher Device-Datei er lauschen soll (derjenigen, die das generische HID-Gerät repräsentiert), diese Information aber nur zur Laufzeit verfügbar ist (abhängig von aktivierten USB-Gadget-Funktionen), fordert das Skript den CLI auf, das korrekte HID-Gerät zu melden, indem es `hidraw=$(P4wnP1_cli usb get device raw)` ausführt.
Das vollständige BashScript befindet sich im Ordner `/usr/local/P4wnP1/scripts`, wie alle Bash-Skripte, die von TriggerActions aus zugänglich sein sollen.
### Bluetooth NAP
P4wnP1 bietet Bluetooth-basierte Netzwerkfunktionalität über das Bluetooth Network Encapsulation Protocol (BNEP). Das derzeit interessanteste Merkmal ist der Bluetooth Network Access Point (NAP), der IP-basierten Bluetooth-Fernzugriff auf P4wnP1 ermöglicht, beispielsweise von Mobilgeräten.
Um diese Funktion zu nutzen, sollten einige Dinge bekannt sein:
- Die Bluetooth-Netzwerkschnittstelle namens `bteth` kann wie die anderen Netzwerkschnittstellen konfiguriert und als Vorlage gespeichert werden (Webclient oder CLI)
- Um NAP-Zugriff von einem Android-Mobilgerät aus zu ermöglichen (iPhone nicht getestet), muss das Mobilgerät nicht nur eine Verbindung herstellen, sondern P4wnP1 muss zusätzlich eine passende IP für das Standard-Gateway auf der `bteth`-Schnittstelle per DHCP vergeben. Dies liegt daran, dass das Mobilgerät den NAP als Gateway zum Internet nutzen möchte (was der beabsichtigte Verwendungszweck wäre). Wenn der NAP selbst kein Gateway bereitstellen würde, würde das Android-Mobilgerät nach dem DHCP D.O.R.A. keine weiteren Anfragen mehr stellen. Der einfachste Weg, dies zu umgehen, besteht darin, den DHCP-Server anzuweisen, die IP der `bteth`-Schnittstelle selbst als Standard-Gateway bereitzustellen (DHCP-Option 3). Selbst wenn keine echte Upstream-Verbindung besteht, hat dies während meiner Tests funktioniert – da das Mobilgerät auf Layer 3 mit dem Gateway kommunizieren muss, um sich "nach Hause zu melden". Selbst wenn nachfolgende Konnektivitätstests fehlschlagen, bleibt die funktionierende Layer-3-Verbindung bestehen. Dies ermöglicht beispielsweise SSH-Zugriff über Bluetooth. Mit aktiviertem "High Speed" funktioniert der Webclient ebenfalls recht gut.
- Um PIN-basiertes Pairing zu ermöglichen, muss Simple Secure Pairing (SSP) deaktiviert sein. Wenn SSP aktiviert ist, bestätigt der laufende Pairing-Agent jeden Passkey (was sogar weniger Sicherheit bedeutet als bei Legacy-PIN-Pairing, da jedes Gerät eine Verbindung herstellen kann). Vielleicht wird in Zukunft ein Bestätigungsdialog für SSP-basiertes Passkey-Pairing für den CLI/Webclient implementiert, aber derzeit ist dies außerhalb des Rahmens. Ich empfehle dringend, "discoverable" und "bondable" zu deaktivieren, sobald das gewünschte Gerät gepaart hat, wenn SSP verwendet wird.
- Ein weiterer Nachteil bei deaktiviertem SSP ist, dass "High Speed" nicht für Bluetooth-Verbindungen nutzbar wäre (oder um High Speed zu aktivieren, muss das Pairing mit SSP erfolgen). Ohne aktiviertes "High Speed" (verwendet 802.11-Frames zur Kommunikation) würde es etwa 10 Minuten dauern, den Webclient anzufordern, mit aktiviertem High Speed dauert es einige Sekunden. SSH und der CLI-Client über einen NAP ohne "High Speed" sollten jedoch in Ordnung sein.
- Die standardmäßigen Bluetooth-Netzwerkschnittstelleneinstellungen (`bteth_startup`) und die standardmäßigen Bluetooth-Einstellungen (`startup`) sollten "Low Speed"-Zugriff über SSH mit Legacy-PIN-Pairing ermöglichen. Die PIN ist `1337` und kann über den Webclient geändert werden.
### TriggerAction Groups
Die TriggerActions bieten eine nette Gruppierungsmöglichkeit namens "Groups". Ich habe es nicht rechtzeitig geschafft, eine Feature-Demo zu erstellen, aber ich plane, ein Beispiel für einen LED-basierten 4-Bit-Binärzähler (unter Verwendung von GPIOs, einem Kippschalter und 4 LEDs) aufzunehmen.
Die Idee hinter den Gruppen ist die folgende:
Nehmen wir an, Sie möchten 4 TriggerActions (TAs) haben, die beim genau gleichen Trigger ausgelöst werden (z. B. "on attached to USB host"). Sie könnten dies erreichen, indem Sie 4 TAs erstellen, jede mit dem Trigger "on attached to USB host".
Alternativ könnten Sie eine TriggerAction erstellen, die den Wert `1` an eine Gruppe namens `"connected"` sendet, wenn "on attached to USB host" eintritt. Nun definieren Sie Ihre anderen 4 TriggerActions so, dass sie ausgelöst werden, wenn der Wert `1` in einer Gruppe namens `"connected"` empfangen wird. Das Ergebnis wäre dasselbe und ergibt vorerst nicht allzu viel Sinn (tatsächlich benötigt es eine zusätzliche TriggerAction). Der einzige positive Effekt ist vorerst, dass die TriggerActions durch den frei wählbaren Gruppennamen etwas lesbarer sind.
Nun könnten Sie als erste fortgeschrittene Aktion den folgenden CLI-Befehl ausführen:```
P4wnP1_cli trigger send --group-name=connected --group-value=1
Dieser Befehl hätte exakt den gleichen Effekt wie die „an USB-Host angeschlossen“ Host-TriggerAction und alle 4 anderen TAs, die auf den Wert 1 in der Gruppe connected warten, würden auslösen. Wie du dich vielleicht erinnerst, kann der CLI-Client remote (von verschiedenen Plattformen aus) ausgeführt werden, sodass er verwendet werden kann, um Trigger remote auszulösen.
Der Trigger, der auf „Gruppenkanäle“ reagiert, heißt „Wert auf Gruppenkanal“. Der interessantere Trigger heißt „mehrere Werte auf Gruppenkanal“. Dieser „mehrere Werte“-Trigger erlaubt es, auf geordnete Wertesequenzen, einen von mehreren Werten oder alle Werte in einer ungeordneten Sequenz zu lauschen, bevor er auslöst.
Angenommen, du möchtest ein BashScript auslösen, wenn diese Bedingungen erfüllt sind:
Du könntest TAs für beide Ereignisse wie folgt erstellen:
Nun könntest du eine dritte TriggerAction wie folgt bereitstellen:
In dieser Konfiguration würde das Bash-Skript nur starten, wenn beide „conditions“-Trigger ausgelöst haben.
Wenn „exakte geordnete Sequenz“ statt „Alle (logisches UND)“ als Typ verwendet worden wäre, würde das Bash-Skript nur starten, wenn der WiFi-AP vor dem USB-verbunden-Trigger aktiv wurde (nicht umgekehrt). In Kombination mit GPIO-Triggern könnte dies beispielsweise verwendet werden, um Aktionen basierend auf der Eingabe eines einfachen PIN-Pads auszulösen.
Ich bin sicher, du hast einige gute Nutzungsideen für „Gruppen“-Kanäle.
Erwähnenswert:
Der CLI-Client kann einen blockierenden Wartevorgang durchführen, bis ein bestimmter Wert auf einem „Gruppenkanal“ ankommt, mit einem Befehl wie diesem:``` P4wnP1_cli trigger wait --group-name=waitgroup --group-value=1
Dies könnte verwendet werden, um Skripte von TriggerActions aus zu steuern, unter Nutzung der CLI (mit ihrer vollen Leistungsfähigkeit wie GPIO).
In Arbeit, fehlende Abschnitte:
- HIDScript-Trigger-Variablen (Variablen, die an HIDScripts übergeben werden, die von TriggerActions ausgelöst werden)
- HIDScript-Hilfsfunktionen (PowerShell-Funktionen)
- HIDScript Demo Snake (Maus)
- USB-Massenspeicher (genimg-Helfer)
## 4. Rettung: Hilfe, ich kann P4wnP1 A.L.O.A. nicht erreichen, da ich die Konfiguration vermasselt habe
P4wnP1 A.L.O.A. schützt Sie nicht vor Fehlkonfigurationen, die es unbrauchbar machen (so wie eine Root-Konsole Sie nicht davor schützt, `rm -rf /` auszuführen).
Falls Sie alles vermasselt haben, hier einige Ideen, wie Sie die Dinge wieder in Ordnung bringen können:
### Datenbanksicherung
Bevor Sie kritische Änderungen an einer noch funktionierenden P4wnP1-Konfiguration vornehmen, erstellen Sie eine Datenbanksicherung. Dies kann entweder über den Reiter „Generic Settings“ des Webclients oder über die CLI mit dem Befehl `P4wnP1_cli db backup` erfolgen. Die Sicherung wird im Ordner `/usr/local/P4wnP1/db` unter dem gewählten Namen gespeichert. Die Funktion „Restore“ oder der Befehl `P4wnP1_cli db restore` kann verwendet werden, um eine bestimmte Sicherung wiederherzustellen. Eine Sicherung enthält alle gespeicherten Vorlagen (USB, WiFi, Netzwerk, Bluetooth, TriggerActions, MasterTemplates) und die eingestellte Startup-Master-Vorlage. Die Sicherung enthält keine HIDScripts oder BashScripts, da beide als Dateien gespeichert werden, um eine einfache Bearbeitung zu ermöglichen.
### Ich habe kein Backup und habe alles vermasselt
Wenn P4wnP1 A.L.O.A. startet, prüft es, ob eine Datenbank existiert. Wenn die Datenbank nicht existiert, wird eine neue Datenbank basierend auf einer initialen Sicherung gefüllt, die mit P4wnP1 A.L.O.A. ausgeliefert wird. Die initiale Sicherung befindet sich unter `/usr/local/P4wnP1/db/init.db` und **sollte niemals gelöscht oder überschrieben werden**. Um P4wnP1 zu zwingen, die Datenbank neu zu erstellen, muss die aktuelle Datenbank gelöscht werden. Dies kann erreicht werden, indem die SD-Karte von P4wnP1 A.L.O.A. auf einem System gemountet wird, das EXT-Partitionen beschreiben kann. Sobald dies erledigt ist, löschen Sie den Ordner `/usr/local/P4wnP1/store` von der Root-Partition der SD-Karte. Dadurch wird die Datenbank gelöscht und die Neuerstellung erzwungen, sobald P4wnP1 erneut gestartet wird.
### Ich habe ein Backup, kann aber nicht auf P4wnP1 zugreifen, um es wiederherzustellen
Wenn Sie eine vorhandene Datenbank nicht wiederherstellen können, weil Sie keinen Zugriff haben, können Sie dennoch die Schritte aus „Ich habe kein Backup und habe alles vermasselt“ befolgen. Zusätzlich zum Löschen von `/usr/local/P4wnP1/store` ersetzen Sie die Datei `/usr/local/P4wnP1/db/init.db` durch die aus Ihrer Sicherung (stellen Sie sicher, dass Sie eine Sicherungskopie von init.db haben). Dadurch sollte Ihre benutzerdefinierte Datenbank beim nächsten Neustart von P4wnP1 neu erstellt werden.
### Ich habe die Startup-Master-Vorlage meines Backups vermasselt
Wenn Sie ein Backup haben, bei dem die Startup-Master-Vorlage nicht funktioniert. Sie müssen einige zusätzliche Schritte durchführen, da es nicht möglich ist, die Startup-Vorlage direkt in einem Backup zu ändern. Befolgen Sie zunächst die Schritte aus „Ich habe kein Backup und habe alles vermasselt“, um die initiale P4wnP1-Datenbank neu zu erstellen. Nach einem Neustart von P4wnP1 sollten Sie wieder in der Lage sein, auf den Webclient von P4wnP1 zuzugreifen. Gehen Sie zu den „Generic Settings“ und stellen Sie Ihr eigenes Backup wieder her (das mit der falschen Startup-Master-Vorlage). Die „Startup-Master-Vorlage“ sollte Ihre „kaputte“ Master-Vorlage als ausgewählt anzeigen. Falls dies nicht der Fall ist, laden Sie den Browser-Tab mit der Webclient-Anwendung neu. Navigieren Sie erneut zum Reiter „Generic Settings“ und wählen Sie eine Startup-Master-Vorlage aus, von der bekannt ist, dass sie funktioniert. An diesem Punkt sollten Sie bereit für einen Neustart sein.
### Nichts davon hat geholfen
Entschuldigung, es scheint, als müssten Sie Ihre P4wnP1 A.L.O.A. SD-Karte aus einem sauberen Image neu erstellen.
## 5. Danksagungen
In Bearbeitung, zufällige Reihenfolge
- @JohanBrandhorst (enger Austausch zu gRPC-web über gopherjs, extrem schnelle Implementierung von „WebSocket für Server-Streaming“, Feature-Anfrage)
- @steevdave, @_binkybear (Kali-Build-Skripte, Diskussion, laufender Austausch)
- @Re4sonKernel (Unterstützung bei der Migration von P4wnP1-Kernel-Änderungen in ein gut gewartetes und populäres Repository, Zusammenarbeit an Bluez-Fixes)
- @SymbianSyMoh (Inspiration für die erneute Auslösung von HID-Angriffen ohne Neustart)
- @quasarframework (könnte dies unter Drittanbieter-Bibliotheken auflisten, aber die hier geleistete Arbeit ist unglaublich; das Aussehen und Gefühl des P4wnP1-Webclients basiert mehr oder weniger auf Standardkomponenten dieser wunderschönen Bibliothek)
- @CyberArms (einer der frühesten Unterstützer von P4wnP1, Autor des besten Tutorials und sogar von Büchern zu solchen Themen)
- @LucaBongiorni (nicht nur einer der frühesten Unterstützer, er macht in Hardware, was ich nur in Software machen kann; er hält Vorträge zum USB-Thema und würdigt Open-Source-Lösungen, alles in allem ein großartiger Typ und eine Inspiration)
- @evilsocket (sein Blogeintrag hat mich zu Go gebracht, ein großartiger OSS-Entwickler, lesen Sie seinen Code und Sie wissen, was ich meine)
- @RoganDawes und @Singe von @SensePost (inspirierende Leute)
- @Swiftb0y (früher Unterstützer, Schöpfer des „alten“ P4wnP1-Wikis, früher Tester für Ideen zu P4wnP1 A.L.O.A.)
- @marcaruel (Diskussion über GPIO-Flankenerkennung mit periph.io)
## 6. Aufgaben und Unterstützung
Dies ist keine umfassende ToDo-Liste, aber es gibt noch einige Meilensteine, und ich würde mich über Community-Unterstützung dabei freuen.
- Portierung der vollständigen HID-Covert-Channel-Funktionalität zum Go-Kern (damit bin ich auf mich allein gestellt)
- **Bluetooth-Konfigurationsbefehl für die CLI hinzufügen**
- Zusätzliche Tastaturlayouts erstellen (derzeit werden br, de, es, fr, gb, it, ru und us unterstützt)
- Bluetooth-Funktionalität erweitern, um Verbindung zu anderen erkennbaren Geräten zu ermöglichen (Authentifizierung und Vertrauen)
- WiFi-KARMA-Funktionalität vom dedizierten Python-Tool in den P4wnP1-Kern verschieben (mit Webclient-Unterstützung)
- Vollständige Dokumentation für HIDScript erstellen (im Grunde fehlt nur der Maus-Teil)
- Vollständige Dokumentation für P4wnP1 erstellen (in der Hoffnung auf die Community)
- Eine verbleibende Abhängigkeit vom Docker-Netlink entfernen (siehe README des Ordners `netlink`)
Hinweis zu Bluetooth:
P4wnP1 arbeitet mit benutzerdefinierten Bindungen an die Bluez-API. Obwohl die Bluez-API Low Energy (GATT, Emulation von Peripheriegeräten usw.) unterstützt, ist nicht geplant, diese Funktionalität in P4wnP1 A.L.O.A. zu integrieren.
Hinweis zu Nexmon:
P4wnP1 nutzt nexmon. Die meisten Leute kennen nexmon als eine Firmware-Modifikation, die es erlaubt, den Monitor-Modus und Paket-Injektion für Broadcom-WiFi-Chips (einschließlich des BCM43430a1, der im Raspberry Pi Zero W verwendet wird) zu aktivieren. Aber nexmon ist mehr: es ist ein Framework, das es erlaubt, ARM-Firmware-Binärdateien (nach ein wenig Reverse Engineering) zu modifizieren, mit Patches, die in hochsprachlichem C-Code geschrieben sind. P4wnP1 verwendet dieses Framework, um benutzerdefinierte Patches auf die WiFi-Firmware anzuwenden, die hardwarebasierten KARMA-Support sowie Firmware- (und Treiber-) Unterstützung für den WiFi-Covert-Channel ermöglichen. Es ist nicht das Ziel dieser Modifikationen, einen ordnungsgemäßen Monitor-Modus oder Injektionsunterstützung für die eingebaute WiFi-Schnittstelle bereitzustellen. Obwohl die alte nexmon-Monitor-Mode-Funktionalität in der aktuellen WiFi-Firmware enthalten ist, wird sie als „fehlerhaft“ betrachtet, da sie die von P4wnP1 verwendete Standard-WiFi-Funktionalität stört (Abstürze, wenn die Schnittstelle im Station-Modus verwendet wird usw.).
## 7. Copyright
P4wnP1 A.L.O.A.
Copyright (C) 2018 Marcus Mengs
Dieses Programm ist freie Software: Sie können es weiterverbreiten und/oder modifizieren
unter den Bedingungen der GNU General Public License, wie sie von der Free Software
Foundation veröffentlicht wurde, entweder Version 3 der Lizenz oder (nach Ihrer Wahl)
jeder späteren Version.
Dieses Programm wird in der Hoffnung verbreitet, dass es nützlich sein wird, aber OHNE
JEDE GEWÄHRLEISTUNG; ohne sogar die stillschweigende Garantie der MARKTGÄNGIGKEIT oder
EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
Sie sollten eine Kopie der GNU General Public License zusammen mit diesem Programm
erhalten haben. Falls nicht, siehe <http://www.gnu.org/licenses/>.