Die nativen Verknüpfungen auf allen drei Plattformen waren gefunden: der Einstieg in die Geräte-Registrierung, die Stelle, an der das Security SDK den Request abfängt, der native Interceptor, der das ausgehende Paket umschreibt, und die Methoden, die JNI per RegisterNatives dynamisch in der Runtime registriert. Das Frida-Skript war angehängt, die Logs liefen durch, jeder Hook traf zuverlässig. Danach kam der Blick in den Command-Katalog: Nutzbare native App-Endpoints für diese drei Plattformen? Null.
Im selben Projekt gab es auf einer anderen Plattform dagegen 11. Im Feld validiert, bereits in den Code überführt und als vollwertige Commands im Einsatz.
Der Unterschied liegt nicht in der Hook-Technik. Die Hooks treffen alle, das Verbindungsdiagramm ist sauber nachvollzogen. Entscheidend ist eine Schwelle, die viele übersehen: Zwischen einem Hook-Treffer und einer tatsächlich nutzbaren Fähigkeit liegt eine Evidenzstufe. Dieser Beitrag zeigt, wie diese Schwelle gesetzt wird, warum „noch nicht nutzbar“ billiger ist als ein halbfertiger Endpoint und welche Rolle Modelle dabei sinnvollerweise übernehmen.
Ein treffender Hook macht noch keinen Endpoint
Wer Apps reverset, betrachtet „der Hook trifft“ oft schon als Ziellinie. Das Skript hängt an der Zielmethode, im Log stehen Argumente, Rückgabewert und Call Stack. Dieses Gefühl, endlich drin zu sein, ist real – aber es kann gründlich täuschen.
Für den Command-Katalog zählt nicht, ob man hineinschauen kann. Entscheidend ist etwas anderes: Liefert ein Command bei normaler Eingabe zuverlässig einen nicht leeren, korrekt strukturierten Payload, den nachgelagerte Systeme verarbeiten können? Zwischen diesen beiden Zuständen liegt ein weiter Weg.
Der typische Fehlschluss sieht so aus: Alle Hooks treffen, die Kette ist vollständig, im Log lässt sich sogar beobachten, wie die Geräte-Registrierung rausgeht, wie das Security SDK seinen Wert berechnet und wie der native Interceptor den Signature-Header ergänzt. Alles wirkt korrekt. Auf einem echten Gerät liefert die Geräte-Registrierung dann jedoch eine Device-ID mit Nullwert – oder der Detail-Endpoint antwortet mit einem leeren Body. Die Verbindung steht, die Daten fehlen.
Was liegt dann vor? Ein Satz von Sonden, die das interne Verhalten genau dieser App-Version beobachten können. Was nicht vorliegt, ist ein aufrufbarer Endpoint. Wer Ersteres als Letzteres ausliefert, baut allen, die danach damit arbeiten, eine Zeitbombe ein.
Warum eine Plattform 11 Commands hat – und drei andere keinen
Legt man beide Gruppen nebeneinander, wird die entscheidende Schwelle sofort sichtbar.
Kontrollplattform (eine Video-Community-App) | Drei führende Content-Apps | |
|---|---|---|
Hook-Kette | Gefunden und im Feld validiert | Alle gefunden, alle Hooks treffen |
Echter Installationsstatus | Device-Identität ohne Nullwert erhalten | Device-ID mit Nullwert / echtes Geräteprofil fehlt |
Nicht leere Antwort | Strukturierte Detaildaten | Leere Details / leerer Body |
Im Command-Katalog | 11 | 0 |
Die 11 Commands der Kontrollplattform haben nicht einfach die „besseren Hooks“. Jeder einzelne hat die vier Evidenzschwellen aus dem nächsten Abschnitt passiert, bevor er zu einem vollwertigen Python-Command wurde – inklusive strukturierter Validierungsnachweise.
Die drei anderen Plattformen waren keineswegs unbearbeitet. Interception-Schicht des Security SDK, nativer Request-Interceptor und die dynamisch von JNI registrierten Methoden: alles analysiert, die Frida-Hooks bleiben aktiv. Doch solange der echte Installationsstatus nicht durchkommt und die Geräte-Registrierung keine Identität ohne Nullwert liefert, bleibt alles danach leer. Deshalb stehen die nativen App-Commands ehrlich bei 0. Nutzbar ist derzeit ausschließlich der völlig separate Pfad über Web- oder Browser-Transport.
Über das gesamte Projekt hinweg umfasst dieses Paket mobiler Fähigkeiten 32 Einträge. 23 davon sind tatsächlich als Implementierungen angekommen, die übrigen 9 hängen bei „warten auf echtes Geräteprofil“ und kommen nicht vorzeitig in den Katalog. Diese 9 stehen nicht für Scheitern, sondern für Disziplin: Die Kette ist verstanden, die Evidenz reicht noch nicht.
Die vier Evidenzschwellen
Eine App-Fähigkeit muss vier Bedingungen erfüllen, bevor sie in den Command-Katalog darf. Fehlt auch nur eine davon, bleibt sie draußen.
Erstens: echter Installationsstatus. Der Request muss von einer Installationsidentität ohne Nullwert ausgehen, die Upstream anerkennt. Ein Hook-Treffer in einer emulierten Umgebung oder auf einem beschädigten Profil genügt nicht. Liefert die Geräte-Registrierung eine ID mit Nullwert, scheitert genau diese Hürde. Dann hilft auch eine noch so vollständige Kette nicht weiter: Das Ergebnis bleibt leer. An dieser Stelle steckten alle drei Plattformen fest.
Zweitens: eine nicht leere Antwort. Ein offener Request bedeutet nicht automatisch, dass er Daten liefert. Der Request geht raus, der Status ist 200, der Body ist leer. Diese „erfolgreich leere Antwort“ ist gefährlicher als ein Fehler, weil sie jede Prüfung passiert, die nur auf Exceptions schaut. Die Schwelle verlangt vollständige, strukturierte und nicht leere Daten, die direkt weitergegeben werden können.
Drittens: vollständige Fehlerklassifizierung. Eine ausgereifte Fähigkeit muss bei einem Fehlschlag sagen können, warum sie gescheitert ist, statt einen pauschalen Fehler zu werfen. Fehlende Seite, nicht angemeldet, Runtime nicht bereit, leere Antwort: Das sind grundverschiedene Zustände und sie brauchen unterscheidbare Fehlercodes. Ein Command, der nur „fehlgeschlagen“ melden kann, ist nicht katalogreif. Der Aufrufer kann dann weder entscheiden, ob er erneut versuchen, sich neu authentifizieren oder den Vorgang überspringen soll.
Viertens: ein geschlossener, reproduzierbarer Test. Ein einzelner Glückstreffer ist keine Fähigkeit. Derselbe Input muss über denselben Ablauf wiederholt funktionieren, und dieser Erfolg muss als gespeicherte, strukturierte Validierungsevidenz festgehalten werden. Läuft es einmal durch und liefert beim nächsten Mal nichts, kontrollierst du die Kette noch nicht – du hast nur zufällig einmal den passenden Runtime-Zustand erwischt.
Erst wenn alle vier Punkte erfüllt sind, wird die Fähigkeit im Command-Katalog registriert. Bleibt einer offen, ist sie weiterhin ein Research-Asset, kein Endpoint. Genau dieser Unterschied ist der Kern des gesamten Beitrags.
Große Frida-Traces sinnvoll auf Modell-Tiers verteilen
Die Grundlage für die Bewertung dieser vier Schwellen ist der Trace, den Frida erzeugt. Und Frida-Traces eskalieren schnell: Ein paar Dutzend angehängte Methoden, ein vollständiger Durchlauf – schon sind Zehntausende bis Hunderttausende Zeilen normal. Der Großteil davon ist Rauschen aus Polyfills, Heartbeats und fachfremden Modulen.
Den kompletten Dump einem einzelnen Modell mit der Frage „Warum liefert dieser Hook keine Daten?“ zu geben, produziert meist eine pauschale Vermutung. Mit wachsendem Kontext steigt zudem die Gefahr, dass zwei unabhängige Call-Segmente fälschlich miteinander verknüpft werden. Besser ist es, den Trace zu segmentieren und die Abschnitte je nach Aufgabe an unterschiedliche Modell-Tiers zu geben.
Das ist ein Musterbeispiel dafür, Tiers zu kombinieren, statt einfach das stärkste Modell für alles einzusetzen. Die vier Aufgaben verlangen nämlich völlig unterschiedliche Fähigkeiten:
Schritt bei der Frida-Logverarbeitung | Erforderliche Fähigkeit | Wahl | model id |
|---|---|---|---|
Trace einer vollständigen Call-Kette in einem Durchgang lesen | Langer Kontext, gesamte Kette auf einmal erfassen | Kimi K3 |
|
Zehtausende Zeilen markieren (Geräteregistrierung / Netzwerk / Krypto / Rauschen) | Günstig, Tausende Aufrufe bei hoher Parallelität | Claude Sonnet 5 |
|
Bewerten, an welcher der vier Schwellen eine Kette hängt | Starkes Reasoning, trifft eine klare Entscheidung | Claude Opus 5 |
|
Abweichungspunkt zweier Traces vergleichen und leere Antwort erklären | Mittleres Reasoning für Attribution, Begründung anhand konkreter Zeilen | GPT-5.6 Sol |
|
Besonders wichtig ist der Labeling-Schritt. Dabei werden in Zehntausenden Zeilen die Rauschanteile markiert und nur Klassen für Geräte-Registrierung, Krypto und Netzwerk behalten. Das ist reine Fleißarbeit, aber in einer Menge, die sich manuell nicht sinnvoll bewältigen lässt. Diese Art von „einfacher Entscheidung mit extrem hoher Frequenz“ ist genau das Einsatzgebiet des günstigen Tiers. Dafür ein Reasoning-Tier zu verwenden, verbrennt schlicht Geld. Sobald der Log auf einige Hundert gelabelte Zeilen verdichtet ist, übernimmt das Reasoning-Tier die Frage nach der blockierten Schwelle. Das verbessert zugleich Kosten und Präzision.
Den Effekt dieser Aufteilung kann man direkt ausprobieren:
Ein Trace-Segment einer Kette ausschneiden, von einigen Tausend bis zu Zehntausenden Zeilen.
Es zunächst stückweise mit
claude-sonnet-5labeln: Rauschen markieren, Klassen für Geräte-Registrierung, Krypto und Netzwerk behalten.Die gelabelte Zusammenfassung an
claude-opus-5geben und ausgeben lassen, „an welcher der vier Schwellen die Kette aktuell hängt und auf welche Zeilen sich die Evidenz stützt“.Als Kontrolle denselben Roh-Trace komplett in ein einzelnes Modell geben und dieselbe Frage stellen.
Dann nur eines vergleichen: Kommt eine pauschale Vermutung zurück oder eine konkrete Schwelle mit konkreten Zeilen? Genau das ist das Auswahlkriterium.
Ein Hook beobachtet eine App-Version – er ist kein Signer
Warum bleiben die Hooks der drei Plattformen erhalten, werden aber strikt aus dem Command-Katalog herausgehalten? Weil ein Hook eine Sonde ist, kein Signer. Das sind zwei grundverschiedene Dinge.
Ein Hook ist an einen konkreten App-Build gebunden, etwa an Version 32.x. Symbole, Offsets und Methodenlayout, auf die er angewiesen ist, gehören genau zu dieser Version. Veröffentlicht Upstream ein Update, verschiebt sich alles – und der Hook fällt sofort aus. Er ist von Natur aus vergänglich und versionsgebunden. Seine Frage lautet: „Was macht diese Version gerade intern?“ Das ist eine Beobachtungsfrage. Genau dafür sind Instrumentierungswerkzeuge gedacht: Die Frida-Dokumentation beschreibt Interceptor als Mittel, um Aufrufe zur Laufzeit zu beobachten und umzuschreiben. Damit lässt sich sehen, wie eine Funktion aufgerufen wird und welche Argumente sie erhält. Es ist aber kein auslieferbares Artefakt, das „aus einem Input eine Signatur berechnet“.
Ein Signer für den Endpoint-Katalog ist das Gegenteil: stabil, reproduzierbar, eigenständig und CI-fähig. Er beantwortet die wiederverwendbare Fähigkeitsfrage: „Gib mir einen Input, und ich berechne die korrekte Signatur.“ Selbst wenn ein Hook das Gerüst des Signaturalgorithmus klar sichtbar macht, ist das nur der Schritt der Algorithmus-Fingerabdruckanalyse. Bis zu einem eigenständigen Signer fehlen dann immer noch Bereinigung und differenzielle Verifikation.
Das erklärt auch die Reihenfolge in der Bereinigungsleiter: Eine Fähigkeit sollte zunächst um eine direkte, reine Python-Anbindung kämpfen. Erst danach folgt als Fallback ein minimales Signaturfragment auf lokalem Node/V8, und nur widerwillig eine passive Browser-Bridge. Ein Hook steht noch nicht einmal auf dieser Leiter. Er liegt davor, im Bereich „Research“ statt „Implementierung“. Eine versionsgebundene Beobachtungssonde als Signer zu registrieren, hängt das Schild „Implementierung“ an ein halbfertiges Forschungsergebnis.
Research-Assets so archivieren, dass sie nicht verfallen
Einen Hook nicht in den Endpoint-Katalog aufzunehmen heißt nicht, ihn wegzuwerfen. Darin steckt reale Arbeit: Wissen über die Kette, Samples und Validierungsevidenz. Löschen wäre ein Verlust. Entscheidend ist, das Asset sauber zu archivieren – sonst weiß nach zwei Monaten nicht einmal mehr der ursprüngliche Bearbeiter, wie weit der Stand tatsächlich war.
Ein Research-Asset für eine App sollte mindestens diese vier Punkte dokumentieren:
Transporttyp. Läuft die Kette über das native Protokoll, eine lokale Node/V8-Signatur oder eine passive Browser-Bridge? Das bestimmt, wie weit sie später bereinigt werden kann.
Evidenzstufe. Wie viele der vier Schwellen wurden erreicht? Reicht es nur bis „Kette gefunden“? Gibt es einen Installationsstatus ohne Nullwert, aber die Antwort bleibt leer? Oder ist die Antwort nicht leer, aber nicht reproduzierbar? Dieser Punkt zeigt der nächsten Person exakt, was bis zur Nutzbarkeit noch fehlt.
App-Version / Build. An welche Version der Hook gebunden ist. Ohne diese Angabe lässt sich nach einem Upstream-Update nicht unterscheiden, ob der Hook falsch geschrieben wurde oder sich der Build verändert hat.
Sample-Zusammenfassung. Wie Input und Output in diesem Durchlauf aussahen, in einer bereinigten Kopie. Das ist der schnellste Anker, um die Untersuchung später wieder aufzunehmen.
Mit diesen vier Angaben wird eine Kette mit 0 Commands zu einem Asset, das sich weiterentwickeln lässt, statt zu einem Haufen abgelaufener Logs. Gleichzeitig verhindert das die zwei schlechtesten Umgangsweisen: den Hook löschen und so tun, als habe es die Recherche nie gegeben – oder ihn gewaltsam in den Katalog drücken und so tun, als sei er nutzbar. Letzteres ist besonders teuer. Ein Endpoint, der „aufrufbar aussieht, aber tatsächlich leer antwortet“, verteilt seine Kosten auf alle Downstream-Aufrufer, die dem Katalog vertrauen. Sie bauen ihre Integration darauf, implementieren Retries, laufen in leere Daten und verlieren am Ende das Vertrauen in den gesamten Katalog. Eine ehrliche Lücke mit „Research-Asset, 0 Commands“ kostet dagegen nur einmal – eine einzelne Zeile in einer README.
Eine leere Hülle ist teurer als eine Lücke. Hier wird das besonders deutlich.
Ein Key nimmt dem Tier-Splitting die Reibung
Zurück zur Log-Aufteilung aus dem vierten Abschnitt: langer Kontext für den vollständigen Trace, günstiges Tier für Massen-Labeling, Reasoning-Tier für die Klassifizierung, mittleres Reasoning für die Attribution. Vier Tiers von mehreren Anbietern bedeuten normalerweise vier SDKs, vier Auth-Schemata und vier Fehlerformate. Wer Frida-Logs über vier Clients klassifizieren möchte, rechnet das oft durch, verwirft den Aufwand und bearbeitet am Ende Hunderttausende Trace-Zeilen mit einem einzigen Modell – entweder teuer oder unvollständig.
AIReiter beseitigt diese Reibung: ein Key, eine OpenAI-kompatible Schnittstelle, alle vier Tiers dahinter. Der Wechsel erfolgt allein über das Feld model im Request-Body.
# Log labeln: günstiges Tier, Tausende Aufrufe bei hoher Parallelität
curl https://aireiter.com/api/v1/chat/completions \
-H "Authorization: Bearer $AIREITER_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-5",
"messages": [{"role": "user", "content": "<one chunk of trace + labeling instruction>"}]
}'
# Schwelle klassifizieren: auf das Reasoning-Tier wechseln, alles andere bleibt gleich
# "model": "claude-opus-5"
# Gesamte Call-Kette lesen: das Long-Context-Tier
# "model": "kimi-k3"
# Antwortunterschied attribuieren:
# "model": "gpt-5.6-sol"
Wer bereits das OpenAI SDK verwendet, setzt base_url auf https://aireiter.com/api/v1 und muss sonst nichts ändern. Mit dem Anthropic SDK genügt derselbe Key für POST /api/v1/messages.
Die Kostenstruktur dieses Workflows ist ungleich verteilt – und der Rabatt greift genau an der kostspieligen Stelle. Der Trace einer Kette umfasst Zehntausende bis Hunderttausende Zeilen. Das Labeling läuft Chunk für Chunk, sodass für eine Plattform Hunderte oder Tausende claude-sonnet-5-Aufrufe zusammenkommen. Dort liegt der Großteil der Kosten. Long-Context-Aufrufe, die einen kompletten Trace lesen, verarbeiten einige Hunderttausend Tokens pro Input und bilden den nächsten großen Block. Klassifizierung und Attribution sind wenige Aufrufe mit höherem Stückpreis. Der Claude-Rabatt von 30% greift bei Labeling und Schwellenklassifizierung, also den beiden teuersten Teilen. GPT zum halben Preis deckt das Attribution-Tier ab. Long-Context-Lesen läuft auf Kimi K3, das über denselben Key erreichbar ist.
Ohne Anmeldung ausprobieren: Ein Trace-Segment zuerst mit
claude-sonnet-5labeln lassen, dann mitclaude-opus-5klassifizieren und prüfen, ob das Modell direkt auf die blockierte Schwelle zeigen kann, bevor du es einbindest.
Fazit
Beim Reverse Engineering einer App liefert ein treffender Hook die Beobachtungsfähigkeit: „Ich kann sehen, was diese Version intern tut.“ Der Endpoint-Katalog verlangt dagegen Aufruffähigkeit: „Gib mir einen Input, und ich liefere zuverlässig nicht leere, korrekte Daten.“ Dazwischen liegen vier Evidenzschwellen: echter Installationsstatus, nicht leere Antwort, Fehlerklassifizierung und reproduzierbarer Test.
Drei Plattformen vollständig analysiert, alle Hooks treffen, Commands trotzdem bei 0: Das ist kein Scheitern, sondern Disziplin. Wenn der echte Installationsstatus nicht durchkommt, bleibt es ehrlich bei 0. Der Hook wird als Research-Asset archiviert und weitergeführt, sobald das Geräteprofil verfügbar ist.
Die Rolle des Modells in diesem Ablauf ist klar abgegrenzt. Es segmentiert, labelt, klassifiziert und attribuiert Hunderttausende Trace-Zeilen und verdichtet die Frage „Wo hängt diese Kette?“ von einem Nachmittag Log-Lektüre auf wenige Minuten. Die Entscheidung, ob eine Schwelle passiert wurde, liegt am Ende jedoch nicht beim Modell – ebenso wenig wie die Bewertung, ob eine Hypothese beim differenziellen Testen korrekt ist. Sie hängt von den vier festgelegten Kriterien und Evidenz ab, die sich reproduzierbar bestätigt. Wie der gesamte Reverse-Engineering-Workflow Modelle an der richtigen Stelle einsetzt, zeigt der Überblick über die vier Phasen.