
🕵️ Tool zum Reverse-Engineering von Protocol Buffers mit unbekannter Definition
Einfaches Programm, das Google Protobuf codierte Blobs (Version 2 oder 3) parsen kann, ohne deren zugehörige Definition zu kennen. Es gibt eine schöne, farbige Darstellung ihres Inhalts aus. Beispiel:

Wie man sieht, sind die Feldnamen offensichtlich verloren, zusammen mit einigen High-Level-Details wie:
Aber protobuf-inspector kann die Nachrichtenstruktur meistens korrekt erraten. Wenn es eingebettete Binärdaten in einem Feld findet, versucht es zunächst, diese als Nachricht zu parsen. Schlägt das fehl, werden die Daten als Zeichenkette oder Hexdump angezeigt. Es kann Fehler machen, besonders bei kleinen Stücken.
Es zeigt die Felder in der Reihenfolge an, in der sie im Draht codiert sind, und ist daher für diejenigen nützlich, die sich mit dem [Drahtformat][] vertraut machen wollen, sowie für Parser-Entwickler, zusätzlich zur Rückentwicklung.
Sie können es mit pip installieren:
pip install protobuf-inspector
Dies installiert den Befehl protobuf_inspector. Führen Sie ihn aus, indem Sie den Protobuf-Blob auf stdin geben:
protobuf_inspector < my-protobuf-blob
Nach der ersten (blinden) Analyse des Blobs beginnen Sie normalerweise, einige der Felder zu definieren, damit protobuf-inspector Ihre Blobs besser parsen kann, bis Sie eine vollständige Protobuf-Definition haben und der Parser nichts mehr erraten muss.
Lesen Sie hier über das Definieren von Feldern.
Wenn ein Analysefehler gefunden wird, wird die Analyse innerhalb dieses Feldes gestoppt, läuft aber außerhalb der Hierarchie unbeeinflusst weiter. Der Stacktrace wird an der Stelle ausgegeben, an der der Feldinhalt stehen würde, zusammen mit einem Hexdump, der angibt, wo die Analyse in diesem Stück gestoppt wurde, falls zutreffend.
Wenn Sie also eine uint32 angegeben haben und ein größeres Varint gefunden wird, erhalten Sie etwa:

Wenn Sie angegeben haben, dass ein Feld eine eingebettete Nachricht enthält, dort aber ungültige Daten gefunden wurden, erhalten Sie:

Bitte beachten Sie, dass main.py mit einem Exit-Code ungleich Null beendet wird, wenn einer oder mehrere Analysefehler aufgetreten sind.
Es gibt einige Tricks, die Sie anwenden können, um bei einem Blob Zeit zu sparen:
Wenn Sie sicher sind, dass ein Varint keine Zig-Zag-Codierung verwendet, aber sich über das Vorzeichen noch nicht sicher sind, lassen Sie es als varint. Wenn es die Zig-Zag-Codierung verwendet, verwenden Sie sint64, es sei denn, Sie sind sicher, dass es 32-Bit und nicht 64-Bit ist.
Wenn ein Stück fälschlicherweise als packed chunk oder eingebettete Nachricht erkannt wird, oder wenn Sie etwas Seltsames an der geparsten Nachricht sehen und die Rohdaten sehen möchten, geben Sie einen Typ von bytes an. Wenn es dagegen aus irgendeinem Grund nicht als eingebettete Nachricht erkannt wird und es sollte, erzwingen Sie message, um den Grund zu sehen.
Wenn Sie die Rohdaten eines Stücks zur besseren Analyse in eine Datei extrahieren möchten, geben Sie einen Typ von dump an, und protobuf-inspector erstellt jedes Mal, wenn es einen passenden Blob findet, dump.0, dump.1 usw.
protobuf-inspector parst den Blob standardmäßig als Nachricht vom Typ root, aber das ist nur eine Voreinstellung. Wenn Sie viele Nachrichtentypen definiert haben, können Sie einen Typnamen als optionales Argument übergeben, und protobuf-inspector verwendet diesen anstelle von root:
Einfaches Beispiel:
from protobuf_inspector.types import StandardParser
parser = StandardParser()
with open('my-blob', 'rb') as fh:
output = parser.parse_message(fh, "message")
print(output)
Dieses Projekt wurde jedoch ursprünglich nicht für die Verwendung als Bibliothek entwickelt, und seine API könnte sich ändern. Für ein komplexeres Beispiel siehe protobuf_inspector/__main__.py.
protobuf_inspector request < my-protobuf-blob