# Daten mit Frida melden

Die Funktion zur Datenmeldung mit Frida basiert auf der Persistenzfunktion. Sie können durch Ihr geschriebenes Frida-Skript automatisch Daten von Methodenaufrufen abfangen und diese über unsere spezifische Methode melden. Die Datenmeldefunktion ermöglicht es Ihnen, die vom Skript abgefangenen Daten einfach direkt an Redis oder eine externe HTTP-Schnittstelle hochzuladen. Sie können den Inhalt der gemeldeten Daten über Redis oder die HTTP-Schnittstelle empfangen. Um die Netzwerkleistung zu maximieren, wird auch das Melden von komprimierten Daten (zlib) unterstützt.

```{attention}
Ab Version 9.0 erfordert das von uns verwendete integrierte Frida 17.x, dass Sie frida-java-bridge selbst in Ihr Skript packen, andernfalls treten Fehler wie `Java not defined` auf. Diese Änderung ist eine offizielle Änderung von Frida. Gemäß den offiziellen Änderungshinweisen müssen Sie ein neues Node.js-Projekt erstellen und die Java Bridge einbinden. Details finden Sie unter https://github.com/oleavr/frida-agent-example oder verwenden Sie unser bereitgestelltes `tools/frida_script_generate.py`, um das ursprüngliche JS-Skript neu zu verpacken.
```

## Erstellen eines Melde-Skripts

Im ersten Schritt müssen Sie Ihr Frida-Skript anpassen. Normalerweise verfügen Frida-Skripte über Funktionen wie `send` und `log`, mit denen Sie Daten nach außen senden können. Für FIRERPA müssen Sie eine spezifische Methode verwenden, um Daten zu senden. Im Folgenden wird ein Template-Code von uns zur Demonstration des Abfangens von okhttp-Traffic verwendet. Es handelt sich nur um ein Demonstrationsskript, das Sie möglicherweise nicht direkt verwenden können. Das folgende Skript unterscheidet sich nicht wesentlich von einem herkömmlichen Skript; der einzige Unterschied ist die Verwendung einer `emit`-Methode. Dies ist eine in FIRERPA integrierte Methode, mit der Sie Daten bequem und systematisch nach außen übermitteln können.

```js
Java.perform(function() {
        Java.use("com.android.okhttp.internal.http.HttpEngine").getResponse.implementation = function() {
                var response = this.getResponse()
                var data = {}
                data["url"] = response._request.value._url.value._url.value
                data["body"] = response.body().string()
                emit("report_data", JSON.stringify(data))
                return response
        }
})
```

Die `emit`-Methode hat zwei Parameter: `emit(name, content)`. Dabei steht `name` für den Typ der Daten. Wenn die Meldeadresse auf Redis eingestellt ist, repräsentiert dieser Name den Namen der Redis-Warteschlange. Sie sollten eine möglichst genaue englische Beschreibung verwenden, wie z.B. `product_info`. `content` repräsentiert den Inhalt der Daten; es werden nur die Typen String und Byte-Array (bytes) unterstützt. Im obigen Beispiel haben wir es in einen JSON-String umgewandelt und übermittelt.

Jetzt verstehen Sie das erforderliche Format und die Aufrufanforderungen für das Skriptschreiben, d.h. wie man die durch Hooking erhaltenen Daten nach außen übermittelt. Sie müssen den folgenden Text weiterlesen, um zu erfahren, wie Sie das **Ziel für die Datenmeldung** konfigurieren.

## Ziel für die Datenmeldung

Das Ziel für die Datenmeldung gibt an, wohin die von Ihnen im Skript per `emit` gesendeten Daten gesendet werden sollen. Unterstützte Zieltypen sind HTTP-Schnittstellen, Redis-Warteschlangen und RabbitMQ-Warteschlangen. Es gibt geringfügige Unterschiede zwischen ihnen.

Wenn Sie sich im Allgemeinen nicht um Informationen wie die Datenquelle kümmern müssen, d.h. wenn Sie die **Daten** nicht mit der **Quellmaschine** abgleichen müssen, empfehlen wir die Verwendung einer Redis-Warteschlange. Andernfalls sollten Sie HTTP oder MQTT (v5) verwenden, da wir aufgrund der Eigenschaften dieser beiden Protokolle mehr Metadaten im Protokoll mitführen können, was Ihnen einen genaueren Geräteabgleich ermöglicht.

### Metadaten der Meldung

Für Daten, die an HTTP-Schnittstellen und RabbitMQ-Ziele gemeldet werden, können Sie zusätzlich zu den ursprünglichen Meldedaten auch Metadaten über das Gerät und das Skript auf Protokollebene abrufen. Die im Protokoll enthaltenen Metadaten sind in der folgenden Tabelle aufgeführt.

| Feld        | Beschreibung                                  |
|------------|----------------------------------------|
| application| Paketname der Anwendung (z.B. com.android.settings)                        |
| device     | Geräte-ID (z.B. 67b2a3d7-5004-ea2a-0d44-194de6ede8de)  |
| encode     | Datenkodierung (z.B. none)                                   |
| name       | Datenname (z.B. report_data)                                   |
| script     | Skript-ID (z.B. 7c52530d)                               |
| sequence   | Meldereihenfolge (z.B. 30)                                     |
| timestamp  | Meldezeitpunkt (z.B. 1740023596914)                          |
| user       | ID der Multi-Instanz-Anwendung (z.B. 0)                                      |

```{attention}
Aufgrund der Eigenschaften des Redis-Protokolls enthalten Daten, die an ein Redis-Ziel gemeldet werden, keine der oben genannten Metadaten.
```

`device` ist die eindeutige ID des Geräts. Sie finden sie in der Informationsleiste des Remote-Desktops. Normalerweise ist diese ID eindeutig und fest. Sie können sie verwenden, um Geräte zu kennzeichnen und eine Zuordnung herzustellen. `encode` ist die Datenkodierung. Die Kodierung unterstützt `none` und `zlib`. Wenn die Kodierung zlib ist, müssen Sie zlib verwenden, um den Datenkörper zu dekomprimieren. `name` wird verwendet, um den Typ dieser Meldedaten zu kennzeichnen. Es ist auch der erste Parameter, den Sie bei der Verwendung der `emit`-Methode angeben. `sequence` repräsentiert den Index der Meldedaten. Er beginnt bei 0 und wird bei jeder Meldung inkrementiert. Sie können dieses Feld verwenden, um die Daten zu sortieren oder zu überprüfen, ob Meldungen verloren gegangen sind.


### Zusätzliche Parameter für den Melde-Link

Beim Zusammenstellen des Melde-Links können Sie einige dynamische ID-Parameter im Link angeben. Sie können diese im Format eines Variablen-Platzhalters `${name}` an bestimmten Stellen im Link einfügen. Verwenden Sie es in der Form `http://192.168.1.2/report/${device_id}`. Die unterstützten Variablen sind wie folgt.


| Name      | Beschreibung des Namens |
| ----------- | ----------- |
| device_id      | Eindeutige Geräte-ID       |
| device_id_short   | Eindeutige Geräte-ID (kurze Geräte-ID, BASE62-kodiert)       |
| android_id   | Android-ID        |
| serialno   | ro.serialno        |


### Meldung an HTTP

Sie müssen selbst einen HTTP-Dienst schreiben, der die gemeldeten Daten empfängt. Die HTTP-Meldeschnittstelle muss die POST-Methode implementieren. FIRERPA meldet Daten über POST an die Schnittstelle. Gleichzeitig werden die einzelnen Felder der Metadaten als HTTP-Query-Parameter kodiert, die Sie daraus extrahieren und verarbeiten können. Der Datenkörper wird im Body der POST-Anfrage mitgeführt. FIRERPA führt automatisch 3 Wiederholungsversuche durch, wenn die Statuscodes 502, 503 oder 504 empfangen werden. Wenn Ihr Backend die gemeldeten Daten korrekt empfangen und verarbeitet hat, sollte es den reinen Text `OK` oder `SUCCESS` zurückgeben und den Statuscode auf `200` setzen, um eine erfolgreiche Verarbeitung zu signalisieren.

```{attention}
HTTP-Anfragen sind multithreaded, daher folgen die vom Backend empfangenen Nachrichten möglicherweise nicht der Meldereihenfolge (sequence).
```

```
Beispiel-Melde-Link http://192.168.1.2/report/${device_id}?serialno=${serialno}
Falls eine Passwortauthentifizierung erforderlich ist http://user:password@192.168.1.2/report/${device_id}?serialno=${serialno}
```

### Meldung an MQTT

Bei der Meldung an MQTT sollten Sie die Metadaten aus der `UserProperty` extrahieren. Es unterstützt TLS, Benutzername/Passwort und unidirektionale Zertifikatsvalidierung (Serverzertifikatsprüfung), aber keine bidirektionale Validierung.

```
Beispiel-Melde-Link mqtt://test.mosquitto.org:1883/script/${device_id}/report
Falls eine Passwortauthentifizierung erforderlich ist mqtt://rw:readwrite@test.mosquitto.org:1884/script/${device_id}/report

Falls eine unidirektionale Validierung erforderlich ist mqtts://test.mosquitto.org:8883/script/${device_id}/report?verify=true&ca=LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVBekNDQXV1Z0F3SUJBZ0lVQlkxaGxDR3ZkajROaEJYa1ovdUxVWk5JTEF3d0RRWUpLb1pJaHZjTkFRRUwKQlFBd2daQXhDekFKQmdOVkJBWVRBa2RDTVJjd0ZRWURWUVFJREE1VmJtbDBaV1FnUzJsdVoyUnZiVEVPTUF3RwpBMVVFQnd3RlJHVnlZbmt4RWpBUUJnTlZCQW9NQ1UxdmMzRjFhWFIwYnpFTE1Ba0dBMVVFQ3d3Q1EwRXhGakFVCkJnTlZCQU1NRFcxdmMzRjFhWFIwYnk1dmNtY3hIekFkQmdrcWhraUc5dzBCQ1FFV0VISnZaMlZ5UUdGMFkyaHYKYnk1dmNtY3dIaGNOTWpBd05qQTVNVEV3TmpNNVdoY05NekF3TmpBM01URXdOak01V2pDQmtERUxNQWtHQTFVRQpCaE1DUjBJeEZ6QVZCZ05WQkFnTURsVnVhWFJsWkNCTGFXNW5aRzl0TVE0d0RBWURWUVFIREFWRVpYSmllVEVTCk1CQUdBMVVFQ2d3SlRXOXpjWFZwZEhSdk1Rc3dDUVlEVlFRTERBSkRRVEVXTUJRR0ExVUVBd3dOYlc5emNYVnAKZEhSdkxtOXlaekVmTUIwR0NTcUdTSWIzRFFFSkFSWVFjbTluWlhKQVlYUmphRzl2TG05eVp6Q0NBU0l3RFFZSgpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFNRTBIS21JemZUT3drS0xUM1RISGUrT2JkaXphbVBnClVabUQ2NFRmM3pKZE5lWUdZbjRDRVhieVA2ZnkzdFdjOFMyYm9XNmR6ckg4U2RGZjl1bzMyMEdKQTlCN1UxRlcKVGUzeGRhL0xtM0pGZmFIamtXdzdqQndjYXVRWmpwR0lOSGFwSFJscGlDWnNxdUF0aE9neFc5U2dEZ1lsR3pFQQpzMDZwa0VGaU13K3FEZkxvL3N4RktCNnZRbEZla01lQ3ltakxDYk53UEp5cXloRm1QV3dpby9QRE1ydUJUelBICjNjaW9CbnJKV0tYYzNPalhkTEdGSk9majdwUDBqL2RyMkxINzJlU3Z2M1BRUUZsOTBDWlBGaHJDVWNSSFNTeG8KRTZ5akdPZG56N2Y2UHZlTElCNTc0a1FPUnd0OGVQbjB5aWRyVEMxaWN0aWtFRDNuSFloTVVPVUNBd0VBQWFOVApNRkV3SFFZRFZSME9CQllFRlBWVjZ4QlVGUGlHS0R5bzVWMytIYmg0TjlZU01COEdBMVVkSXdRWU1CYUFGUFZWCjZ4QlVGUGlHS0R5bzVWMytIYmg0TjlZU01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUwKQlFBRGdnRUJBR2E5a1MyMU43MFRoTTYvSGo5RDdtYlZ4S0xCalZXZTJUUHNHZmJsM3JFRGZaK09LUloyajZBQwo2cjdqYjRUWk8zZHpGMnA2ZGdicmxVNzFZLzRLMFRkeklqUmozY1EzS1NtNDFKdlVRMGhaL2MwNGlHRGcveFdmCitwcDU4bmZQQVl3dWVycnVQTldtbFN0V0FYZjBVVHFSdGc0aFFEV0J1VUZESlR1V3V1QnZFWHVkejc0ZWgvd0sKc013ZnUxSEZ2ank1WjBpTURVOFBVRGVwalZvbE9DdWU5YXNobFM0RUI1SUVDZFNSMlRJdG5BSWlJd2lteDgzOQpMZFVkUnVkYWZNdTVUNVhtYTE4Mk9DMC91L3hSbEVtK3R2S0dHbWZGY04wcGlxVmw4T3JTUEJnSWxiKzFJS0pFCm0vWHJpV3IvQ3E0aC9KZkI3TlRzZXpWc2xna0Jhb1U9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
```

Im obigen Link werden die relevanten Daten an `script/${device_id}/report` gesendet. Sie können diese Nachrichten abonnieren, z.B. mit `mosquitto_sub -L mqtt://test.mosquitto.org:1883/script/+/report`.

### Meldung an Redis

Die Meldung an Redis ist relativ einfach. Da keine Metadaten mitgeführt werden, kann die Datenquelle nicht direkt unterschieden werden. Möglicherweise müssen Sie dies durch dynamisches Umschreiben des injizierten Skripts realisieren. Bei der Meldung an Redis wird FIRERPA den Datenkörper direkt über `LPUSH` in die Warteschlange pushen. Im Beispielskript oben werden die gemeldeten Daten beispielsweise in die `report_data`-Warteschlange gepusht.

```{attention}
Es werden nur Redis-Dienste im Standalone-Modus unterstützt, kein Redis-Cluster.
```

```{attention}
Fügen Sie außer im Passwortfeld keine Variablen-Platzhalter in den Redis-Link ein. Der Link ist ein von der Standard-Redis-Bibliothek unterstützter Link; Änderungen an anderen Teilen können zu Parsing-Fehlern führen.
```

```
Beispiel-Melde-Link redis://1.2.3.4/0
Falls eine Passwortauthentifizierung erforderlich ist redis://:password@1.2.3.4/0

TLS + Passwort

rediss://:password@1.2.3.4/0?ssl_ca_data=LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURUVENDQWpXZ0F3SUJBZ0lVUFIvcmcxK0x2aU5tYzNsc0...
```

## Injizieren des Melde-Skripts

Natürlich ist das Abrufen der App-Instanz der erste Schritt. Sie können durch den oben genannten Aufruf eine `app`-Variable erhalten. Sie repräsentiert die Instanz der Anwendung, in die Sie injizieren möchten. Anschließend müssen Sie sie verwenden, um die folgenden Injektions- oder Detach-Operationen fortzusetzen.

```python
app = d.application("com.android.settings")
```

Injizieren Sie das oben genannte Melde-Skript mit der folgenden Schnittstelle in die Anwendung. Wenn Daten abgefangen werden, werden sie an die `report_data`-Warteschlange von Redis übermittelt. Im Beispiel muss Ihr Gerät direkten Zugriff auf die relevanten Dienste unter 192.168.1.10 haben, andernfalls können die Daten nicht gemeldet werden.

```python
app.attach_script(script, emit="redis://192.168.1.10/0")
```

Sie können es auch so einstellen, dann werden Ihre Daten an eine HTTP-Schnittstelle anstatt an Redis übermittelt (HTTPS wird unterstützt).

```python
app.attach_script(script, emit="http://192.168.1.10/dataReport")
```

Wenn die von Ihnen gemeldeten Daten sehr groß sind, kann die Aktivierung der Komprimierung die Durchsatzleistung der Netzwerkübertragung erheblich verbessern. Sie können `encode` verwenden, um die Datenkomprimierung für die Meldung zu aktivieren. Natürlich müssen Sie die gemeldeten Daten anschließend auch dekomprimieren.

```python
app.attach_script(..., encode=DataEncode.DATA_ENCODE_ZLIB)
```

## Dekomprimieren der gemeldeten Daten

Standardmäßig werden die gemeldeten Daten nicht komprimiert. Wenn Sie die Komprimierung für die Meldung aktiviert haben, müssen Sie auf der Empfängerseite die zlib-Kodierung verwenden, um die gemeldeten Daten zu dekomprimieren. Sie können die `decompress`-Methode der offiziellen Python-Bibliothek zlib verwenden, um die gemeldeten Daten bequem zu dekomprimieren.

```python
zlib.decompress(data)
```

## Entfernen des Melde-Skripts

Das Entfernen des Melde-Skripts ist einfach und funktioniert genauso wie bei persistenten Skripten.

```python
app.detach_script()
```