BLOG

Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

F5 Miniaturansicht
F5
Veröffentlicht am 17. September 2018


Bei Shape stoßen wir immer wieder auf zahlreiche zweifelhafte JavaScript-Skripte. Wir finden Skripte, die bösartig in Seiten eingeschleust wurden, erhalten von Kunden zur Prüfung eingesandte Beispiele oder entdecken Ressourcen im Web, die sich gezielt mit Teilen unseres Dienstes beschäftigen. Täglich gehen wir diese Skripte detailliert durch, um zu verstehen, was sie tun und wie sie funktionieren. Sie sind meist minimiert, oft verschlüsselt und brauchen mehrere Bearbeitungsschritte, bevor sie wirklich tiefgehend analysiert werden können.

Bis vor Kurzem bestand die einfachste Möglichkeit für diese Analyse darin, entweder lokal zwischengespeicherte Setups zu verwenden, die manuelle Bearbeitungen ermöglichen, oder Proxys zu verwenden, um Inhalte im laufenden Betrieb neu zu schreiben. Die lokale Lösung ist die bequemste, aber Websites lassen sich nicht immer perfekt in andere Umgebungen übertragen und die Benutzer stürzen sich oft in eine lange Liste von Fehlerbehebungen, nur um produktiv zu werden. Proxys sind äußerst flexibel, aber normalerweise umständlich und nicht sehr portabel – jeder hat seine eigene benutzerdefinierte Konfiguration für seine Umgebung und manche Leute sind mit einem Proxy besser vertraut als mit einem anderen. Ich habe begonnen, Chrome und sein Devtools-Protokoll zu verwenden, um in Anfragen und Antworten einzusteigen, während sie auftreten, und sie im laufenden Betrieb zu ändern. Dies ist auf jede Plattform portierbar, auf der Chrome installiert ist, umgeht eine ganze Reihe von Problemen und lässt sich gut in gängige JavaScript-Tools integrieren. In diesem Beitrag erkläre ich, wie man mit dem Devtools-Protokoll von Chrome JavaScript im laufenden Betrieb abfängt und ändert.

Wir verwenden Node, aber ein Großteil des Inhalts lässt sich in die Sprache Ihrer Wahl portieren, vorausgesetzt, Sie haben einfachen Zugriff auf die Devtools-Hooks.

Wenn Sie sich noch nie mit der Skripterstellung für Chrome beschäftigt haben, sollten Sie zunächst wissen, dass Eric Bidelman eine hervorragende Anleitung für die ersten Schritte mit Headless Chrome geschrieben hat. Die dort aufgeführten Tipps gelten sowohl für Headless als auch für GUI Chrome (mit einer Eigenart, auf die ich im nächsten Abschnitt eingehen werde).

Chrome starten

Um dies zu vereinfachen, verwenden wir die Chrome-Launcher -Bibliothek von npm.

Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

Chrome-Launcher macht genau das, was Sie erwarten, und Sie können dieselben Befehlszeilenschalter, die Sie vom Terminal gewohnt sind, unverändert übergeben (eine ausführliche Liste wird hier gepflegt ). Wir übergeben die folgenden Optionen:

–Fenstergröße=1200,800

  • Stellen Sie die Fenstergröße automatisch auf einen sinnvollen Wert ein.

–auto-open-devtools-for-tabs

  • Öffnen Sie die Devtools automatisch, da wir sie häufig verwenden.

–user-data-dir=/tmp/chrome-testing

  • Legen Sie ein konstantes Benutzerdatenverzeichnis fest. (Idealerweise würden wir dies nicht benötigen, aber der Nicht-Headless-Modus unter Mac OSX scheint das Abfangen von Anfragen ohne dieses Flag nicht zuzulassen. Wenn Sie einen besseren Weg kennen, lassen Sie es mich bitte über Twitter wissen!)
Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

Versuchen Sie, Ihr Skript auszuführen, um sicherzustellen, dass Sie Chrome öffnen können. Sie sollten ungefähr Folgendes sehen:

Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

Verwenden des Chrome Devtools-Protokolls

Dies wird auch als „Chrome-Debugger-Protokoll“ bezeichnet und beide Begriffe scheinen in den Dokumenten von Google synonym verwendet zu werden. Installieren Sie zunächst das Paket „chrome-remote-interface“ über npm, das uns praktische Methoden zur Interaktion mit dem Devtools-Protokoll bietet. Halten Sie die Protokolldokumente bereit, wenn Sie tiefer in die Materie eintauchen möchten.

Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

Um das CDP zu verwenden, müssen Sie eine Verbindung zum Debugger-Port herstellen. Da wir die Chrome-Launcher -Bibliothek verwenden, ist dieser bequem über chrome.port zugänglich.

Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

Viele der Domänen im Protokoll müssen zuerst aktiviert werden. Wir beginnen mit der Runtime- Domäne, damit wir uns in die Konsolen-API einklinken und alle Konsolenaufrufe im Browser an die Befehlszeile weiterleiten können.

Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

Wenn Sie Ihr Skript jetzt ausführen, erhalten Sie ein voll funktionsfähiges Chrome-Fenster, das auch alle seine Konsolenmeldungen an Ihr Terminal ausgibt. Das ist an sich schon großartig, insbesondere für Testzwecke!

Abfangen von Anfragen

Zuerst müssen wir registrieren, was wir abfangen wollen, indem wir eine Liste von RequestPatterns an setRequestInterception senden. Du kannst entweder in der „Request“-Phase oder in der „HeadersReceived“-Phase abfangen. Möchtest du die Antwort tatsächlich ändern, warten wir auf „HeadersReceived“. Der Ressourcentyp entspricht den types, die du üblicherweise im Netzwerkbereich der Devtools findest.

Vergessen Sie nicht, die Netzwerkdomäne zu aktivieren, wie Sie es oben bei Runtime getan haben, indem Sie Network.enable() zum selben Array hinzufügen.

Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

Die Registrierung des Ereignishandlers ist relativ unkompliziert und jede abgefangene Anfrage verfügt über eine ​InterceptionId , die verwendet werden kann, um Informationen zur Anfrage abzufragen oder ggf. eine Fortsetzung auszugeben. Hier greifen wir einfach ein und protokollieren jede Anfrage, die wir abfangen, im Terminal.

Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

Ändern von Anforderungen

Um Anfragen zu ändern, müssen wir einige Hilfsbibliotheken installieren, die Base64-Zeichenfolgen kodieren und dekodieren. Es stehen zahlreiche Bibliotheken zur Verfügung. Wählen Sie einfach Ihre eigene aus. Wir verwenden atob und btoa .

Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

Die API zum Verarbeiten der Antworten ist etwas umständlich. Zum Verarbeiten von Antworten müssen Sie Ihre gesamte Antwortlogik in die Anforderungsabfangung einbeziehen (und nicht beispielsweise einfach eine Antwort abfangen) und dann den Textkörper anhand der Abfang-ID abfragen. Dies liegt daran, dass der Textkörper beim Aufruf Ihres Handlers möglicherweise nicht verfügbar ist. So können Sie explizit auf das warten, was Sie suchen. Der Textkörper kann auch Base64-codiert sein, Sie sollten ihn daher prüfen und decodieren, bevor Sie ihn blind weitergeben.

Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

An diesem Punkt können Sie sich mit JavaScript völlig austoben. Ihr Code versetzt Sie in die Mitte einer Antwort, sodass Sie sowohl auf das vollständige angeforderte JavaScript zugreifen als auch Ihre geänderte Antwort zurücksenden können. Eindrucksvoll! Wir optimieren das JS einfach, indem wir am Ende ein console.log anhängen, sodass unser Terminal eine Nachricht erhält, wenn unser geänderter Code im Browser ausgeführt wird.

Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

Wir können nicht einfach nur den geänderten Body weitergeben, da der Inhalt den ursprünglichen Headern widersprechen könnte. Da Sie aktiv testen und optimieren, sollten Sie mit den Grundlagen starten, bevor Sie sich zu sehr um weitere Header-Informationen kümmern. Sie können die Antwort-Header bei Bedarf über ​responseHeaders abrufen, die an den Ereignis-Handler übergeben werden. Für den Anfang erstellen wir jedoch unser eigenes minimales Array, um den Satz später leicht bearbeiten und anpassen zu können.

Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

Zum Senden der neuen Antwort muss eine vollständige, Base64-codierte HTTP-Antwort (einschließlich der HTTP-Statuszeile) erstellt und über eine RawResponse- Eigenschaft im an continueInterceptedRequest übergebenen Objekt gesendet werden.

Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

Wenn Sie nun Ihr Skript ausführen und im Internet navigieren, sehen Sie in Ihrem Terminal etwa Folgendes, da Ihr Skript JavaScript abfängt und auch Ihr geändertes JavaScript im Browser ausgeführt wird und die ​console.log() s durch den Hook nach oben sprudeln, den wir zu Beginn des Tutorials erstellt haben.

Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

Der vollständige Arbeitscode für das Basisbeispiel finden Sie hier:

Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

Wie geht es weiter?

Sie können mit dem hübschen Ausdrucken des Quellcodes beginnen. Dies ist immer eine nützliche Möglichkeit, mit dem Reverse Engineering zu beginnen. Ja, natürlich können Sie dies in den meisten modernen Browsern tun, aber Sie möchten jeden Änderungsschritt selbst steuern, um die Konsistenz über verschiedene Browser und Browserversionen hinweg zu gewährleisten und beim Analysieren der Quelle die Zusammenhänge erkennen zu können. Wenn ich mich in fremden, verschleierten Code vertiefe, benenne ich Variablen und Funktionen gerne um, sobald ich beginne, ihren Zweck zu verstehen. Das sichere Ändern von JavaScript ist keine Kleinigkeit und würde einen eigenen Blog-Beitrag erfordern. Für den Moment können Sie jedoch etwas wie ​unminify verwenden, um gängige Minimierungs- und Verschleierungstechniken rückgängig zu machen.

Sie können unminify über npm installieren und Ihren neuen JavaScript-Body mit einem Aufruf von ​unminify umschließen, um es in Aktion zu sehen:

Abfangen und Ändern von Antworten mit Chrome über das Devtools-Protokoll

Wir werden im nächsten Beitrag tiefer auf die Transformationen eingehen. Wenn Sie Fragen, Kommentare oder andere tolle Tricks haben, kontaktieren Sie mich bitte über Twitter!