Protobuf est un format de sérialisation développé par Google et utilisé dans un nombre croissant de Android, Web, Desktop et plus d'applications. Il se compose d'un langage pour déclarer les structures de données , qui est ensuite compilée en code ou un autre type de structure en fonction de l'implémentation cible.
PBTK ( Protobuf Toolkit ) est un ensemble de scripts à part entière, accessible via une interface graphique unifiée, qui offre deux caractéristiques principales:
Extraire les structures Protobuf des programmes , les convertir en .proto lisibles, soutenant diverses implémentations:
Modification, redditionnement et fuzzing des données envoyées aux points de terminaison du réseau Protobuf, via une interface graphique pratique qui vous permet de modifier en direct les champs pour un message Protobuf et afficher le résultat.
PBTK nécessite Python ≥ 3,5, PYQT 5, Python-Protobuf 3 et une poignée de programmes exécutables (Chromium, JAD, Dex2Jar ...) pour exécuter des scripts d'extracteur.
Les utilisateurs d'Archlinux peuvent s'installer directement via le package:
$ yay -S pbtk-git
$ pbtk
Sur la plupart des autres distributions, vous voudrez l'exécuter directement:
# For Ubuntu/Debian testing derivates:
$ sudo apt install python3-pip git openjdk-9-jre libqt5x11extras5 python3-pyqt5.qtwebengine python3-pyqt5
$ sudo pip3 install protobuf pyqt5 pyqtwebengine requests websocket-client
$ git clone https://github.com/marin-m/pbtk
$ cd pbtk
$ ./gui.pyWindows est également pris en charge (avec les mêmes modules requis). Une fois que vous avez exécuté l'interface graphique, cela devrait vous avertir de ce qui vous manque en fonction de ce que vous essayez de faire.
L'interface graphique peut être lanchée à travers le script principal:
./gui.py
Les scripts suivants peuvent également être utilisés autonomes, sans GUI:
./extractors/jar_extract.py [-h] input_file [output_dir]
./extractors/from_binary.py [-h] input_file [output_dir]
./extractors/web_extract.py [-h] input_url [output_dir]
Supposons que vous insensiez l'ingénierie d'une application Android. Vous avez exploré un peu l'application avec votre décompulier préféré et vous avez pensé qu'il transporte le protobuf comme des données post-HTTPS d'une manière typique.
Vous ouvrez PBTK et êtes accueillis de manière significative:
La première étape consiste à mettre vos .protos au format de texte. Si vous ciblez une application Android, tomber dans un APK et attendre devrait faire le travail magique! (sauf si c'est une implémentation vraiment exotique)
Cela étant fait, vous passez à ~/.pbtk/protos/<your APK name> (soit via la ligne de commande, soit le bouton en bas de l'écran de bienvenue pour ouvrir votre navigateur de fichier, la façon dont vous préférez). Tous les .protos de l'application sont en effet ici.
De retour dans votre décompilateur, vous êtes tombé sur la classe qui construit des données envoyées au point de terminaison HTTPS qui vous intéresse. Il sérialise le message Protobuf en appelant une classe en code généré.
Cette dernière classe devrait avoir une correspondance parfaite dans votre répertoire .protos (c'est-à-dire com.foo.bar.ab correspondra com/foo/bar/a/b.proto ). Quoi qu'il en soit, le gâteau de son nom devrait vous permettre de le référencer.
C'est génial: la prochaine chose va à l'étape 2 , à sélectionner votre entrée souhaitée .proto et à remplir quelques informations sur votre point de terminaison.
Vous pouvez également donner quelques exemples de données RAW Protobuf, qui ont été envoyées à ce point de terminaison, capturées via Mitmproxy ou Wireshark, et que vous colleras sous une forme codée hexadécimale.
L'étape 3 concerne la partie amusante de cliquer sur les boutons et de voir ce qui se passe! Vous avez une vue d'arbre représentant tous les champs de la structure Protobuf (les champs répétés sont suffixés par "+", les champs requis n'ont pas de cases à cocher).
Planer juste un champ pour se concentrer. Si le champ est un type entier, utilisez la roue de la souris pour l'incrémenter / le décrémenter. Les informations sur l'énumération apparaissent également sur le plan de volant.
C'est ici! Vous pouvez déterminer la signification de chaque champ avec cela. Si vous avez extrait .protos à partir de code minifié, vous pouvez renommer les champs en fonction de ce que vous remarquez qu'ils signifient, en cliquant sur leurs noms.
Bonne inversion! ? ?
PBTK stocke des informations .proto extraites dans ~/.pbtk/protos/ (ou %APPDATA%pbtkprotos sur Windows).
Vous pouvez emménager, déménager, renommer, modifier ou effacer les données de ce répertoire directement via votre navigateur de fichiers régulier et l'éditeur de texte, c'est le moyen attendu de le faire et n'interfère pas avec PBTK.
Les points de terminaison basés sur HTTP sont stockés dans ~/.pbtk/endpoints/ en tant qu'objets JSON. Ces objets sont des tableaux de paires d'informations sur la demande / réponse, qui ressemblent à ceci:
[ {
"request" : {
"transport" : "pburl" ,
"proto" : "www.google.com/VectorTown.proto" ,
"url" : "https://www.google.com/VectorTown" ,
"pb_param" : "pb" ,
"samples" : [ {
"pb" : "!...." ,
"hl" : "fr"
} ]
} ,
"response" : {
"format" : "other"
}
} ] PBTK utilise deux types de modules enfichables en interne: les extracteurs et les transports.
Les extracteurs sont définis dans extractors/*.py . Ils sont définis comme une méthode précédée d'un décorateur, comme ceci:
@ register_extractor ( name = 'my_extractor' ,
desc = 'Extract Protobuf structures from Foobar code (*.foo, *.bar)' ,
depends = { 'binaries' : [ 'foobar-decompiler' ]})
def my_extractor ( path ):
# Load contents of the `path` input file and do your stuff...
# Then, yield extracted .protos using a generator:
for i in do_your_extraction_work ():
yield proto_name + '.proto' , proto_contents
# Other kinds of information can be yield, such as endpoint information or progress to display. Les transports sont définis dans utils/transports.py . Ils sont définis comme une classe précédée d'un décorateur, comme ceci:
@ register_transport (
name = 'my_transport' ,
desc = 'Protobuf as raw POST data' ,
ui_data_form = 'hex strings'
)
class MyTransport ():
def __init__ ( self , pb_param , url ):
self . url = url
def serialize_sample ( self , sample ):
# We got a sample of input data from the user.
# Verify that it is valid in the form described through "ui_data_form" parameter, fail with an exception or return False otherwise.
# Optionally modify this data prior to returning it.
bytes . fromhex ( sample )
return sample
def load_sample ( self , sample , pb_msg ):
# Parse input data into the provided Protobuf object.
pb_msg . ParseFromString ( bytes . fromhex ( sample ))
def perform_request ( self , pb_data , tab_data ):
# Perform a request using the provided URL and Protobuf object, and optionally other transport-specific side data.
return post ( url , pb_data . SerializeToString (), headers = USER_AGENT )Ce qui suit pourrait venir pour d'autres versions:
J'ai essayé de faire de mon mieux pour produire du code soigneusement lisible et commenté (à l'exception des pièces qui se décrivent principalement, comme la connexion des signaux de GUI) pour la plupart des modules, afin que vous puissiez contribuer.
Comme PBTK utilise PYQT, il est publié sous la licence GNU GPL (I, par la présente, etc.), j'aurais probablement choisi quelque chose de domaine public autrement.
Il n'y a pas de règle formalisée pour le cas de lettre du nom du projet, la règle consiste à suivre votre cœur ❤