
🕵️ Ferramenta para fazer engenharia reversa de Protocol Buffers com definição desconhecida
Programa simples que pode analisar blobs codificados Google Protobuf (versão 2 ou 3) sem conhecer sua definição acompanhante. Ele imprimirá uma representação colorida e agradável de seu conteúdo. Exemplo:

Como você pode ver, os nomes dos campos são obviamente perdidos, junto com alguns detalhes de alto nível, como:
Mas o protobuf-inspector é capaz de adivinhar corretamente a estrutura da mensagem na maioria das vezes. Quando encontra dados binários embutidos em um campo, primeiro tentará analisá-los como uma mensagem. Se falhar, exibirá os dados como string ou hexdump. Pode cometer erros, especialmente com pequenos blocos.
Ele mostra os campos exatamente na ordem em que são codificados no fio, então pode ser útil para quem deseja se familiarizar com o [formato de fio][] ou para desenvolvedores de parsers, além da engenharia reversa.
Você pode instalar com pip:
pip install protobuf-inspector
Isso instala o comando protobuf_inspector. Execute-o, fornecendo o blob protobuf na entrada padrão:
protobuf_inspector < my-protobuf-blob
Após ler a primeira análise (cega) do blob, você normalmente começa a definir alguns dos campos para que o protobuf-inspector possa analisar melhor seus blobs, até chegar a um ponto em que você tenha uma definição protobuf completa e o parser não precise mais adivinhar nada.
Leia sobre como definir campos aqui.
Se um erro de parsing for encontrado, a análise será interrompida dentro daquele campo, mas continuará inalterada no exterior da hierarquia. O rastreamento da pilha será impresso onde o conteúdo do campo estaria, junto com um hexdump indicando onde a análise foi interrompida naquele bloco, se aplicável.
Então, se você especificou um uint32 e um varint maior for encontrado, você obteria algo como:

Se você especificou que algum campo continha uma mensagem embutida, mas dados inválidos foram encontrados lá, você obteria:

Observe que main.py sairá com status diferente de zero se um ou mais erros de parsing ocorrerem.
Existem alguns truques que você pode usar para economizar tempo ao abordar um blob:
Se você tem certeza de que um varint não usa codificação zig-zag, mas ainda não tem certeza do sinal, deixe-o como varint. Se ele usar codificação zig-zag, use sint64 a menos que você tenha certeza de que é de 32 bits e não de 64 bits.
Se um bloco estiver sendo erroneamente reconhecido como packed chunk ou uma mensagem embutida, ou se você vir algo estranho na mensagem analisada e quiser ver os bytes brutos, especifique um tipo bytes. Por outro lado, se por algum motivo não estiver sendo detectado como uma mensagem embutida e deveria, force-o para message para ver o motivo.
Se você quiser extrair os dados brutos de um bloco para um arquivo para analisá-los melhor, especifique um tipo dump e o protobuf-inspector criará dump.0, dump.1, etc. toda vez que encontrar um blob correspondente.
O protobuf-inspector analisa o blob como uma mensagem do tipo root, mas isso é apenas um padrão. Se você tiver muitos tipos de mensagem definidos, pode passar um nome de tipo como argumento opcional, e o protobuf-inspector usará esse em vez de root:
Exemplo simples:
from protobuf_inspector.types import StandardParser
parser = StandardParser()
with open('my-blob', 'rb') as fh:
output = parser.parse_message(fh, "message")
print(output)
Este projeto não foi inicialmente projetado para uso como biblioteca, no entanto, e sua API pode mudar. Para um exemplo mais complexo, veja protobuf_inspector/__main__.py.
protobuf_inspector request < my-protobuf-blob