From the Wireshark wiki - Protobuf#protocol-dependencies:
Protobuf content is normally dissected by Wireshark from some higher layer dissectors including gRPC or other UDP/TCP based dissectors
There are two TCP streams in the provided pcap file:
Add a Decode As...
entry for a Stream ID 1
TCP port (34727
):
# "Decode As" entries file for Wireshark 4.2.3.
#
# This file is regenerated each time "Decode As" preferences
# are saved within Wireshark. Making manual changes should be safe,
# however.
decode_as_entry: tcp.port,34727,(none),HTTP2
The out of the box protobuf
decode:
Frame 46: 127 bytes on wire (1016 bits), 127 bytes captured (1016 bits) on interface lo, id 0
Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00)
Internet Protocol Version 4, Src: 127.0.0.1, Dst: 127.0.0.1
Transmission Control Protocol, Src Port: 34727, Dst Port: 50051, Seq: 602, Ack: 231, Len: 61
HyperText Transfer Protocol 2
GRPC Message: /export_data.streamDataOut/streamData, Request
Protocol Buffers: /export_data.streamDataOut/streamData,request
Message: export_data.streamDataArgs
[Message Name: export_data.streamDataArgs]
Field(1): Id = 1234 (int64)
[Field Name: Id]
[Field Type: int64 (3)]
.000 1... = Field Number: 1
.... .000 = Wire Type: varint (0)
Value: d209
Int64: 1234
Id: 1234
Field(2): data (bytes)
[Field Name: data]
[Field Type: bytes (12)]
.001 0... = Field Number: 2
.... .010 = Wire Type: Length-delimited (2)
Value Length: 42
Value: 0a0d6d6163446174612e70726f746f12190a1130303a30303a30303a30303a31323a464610eb86b5af06
data: (42 bytes)
Data (42 bytes)
Data: 0a0d6d6163446174612e70726f746f12190a1130303a30303a30303a30303a31323a464610eb86b5af06
Text: \n\rmacData.proto\x12\x19\n\x1100:00:00:00:12:FF\x10놵�\x06
[Length: 42]
Wireshark wiki - Protobuf field subdissectors:
A subdissector can register itself in "protobuf_field" dissector table for parsing the value of the field. The key of record in "protobuf_field" table is the full name of the field.
local protobuf_field_table = DissectorTable.get("protobuf_field")
local png_dissector = Dissector.get("png")
protobuf_field_table:add("tutorial.Person.portrait_image", png_dissector)
In their example, it's to decode a png
. Our goal is to decode an embedded protobuf
:
local protobuf_dissector = Dissector.get("protobuf")
...
pinfo.private["pb_msg_type"] = "message,tutorial.AddressBook"
pcall(Dissector.call, protobuf_dissector, tvb, pinfo, tree)
-- 240313_33954_nested_pb.lua
-- "Am looking for working example for below case where data is serialized as bytes to another protobuf."
-- https://ask.wireshark.org/question/33954/lua-example-for-protobuf-dissector-which-has-protobuf-encoded-within-protobuf/
-- Step 1 - document as you go. See header above and set_plugin_info().
local nested_pb_info =
{
version = "1.0.0",
author = "Good Coder",
description = "Decode nested protobufs",
repository = "Floppy in top drawer"
}
set_plugin_info(nested_pb_info)
do
local protobuf_field_table = DissectorTable.get("protobuf_field")
local protobuf_dissector = Dissector.get("protobuf")
protobuf_message_name_f = Field.new("protobuf.message.name")
encoded_pb_p = Proto("encoded_pb_dissector", "Encoded Protobuf")
encoded_pb_p.dissector = function(tvb, pinfo, subtree)
-- What is the message type for the nested protobufs
local message_type = {
["export_data.streamDataArgs"] = "message,encoded_data.encodeDataInfo",
["encoded_data.encodeDataInfo"] = "message,mac_data.macDataInfo"
}
-- Prevent recursion by only calling on last message name in tree
local message_name = {
["message,encoded_data.encodeDataInfo"] = "encoded_data.encodeDataInfo",
["message,mac_data.macDataInfo"] = "mac_data.macDataInfo"
}
finfo_messages = { protobuf_message_name_f() }
if (#finfo_messages > 0) then
local call_dissector
-- First time we're called there will be no pb_msg_type ...
(more)
Can share a capture file and proto file(s)?
Thanks for the response. I have added both protofiles and the pcap capture dropbox link to the question. Please let me know if more details required.
Do you have lua code for the first encoding? (serviceA.proto)
no, I don't have it. Looking for help here with that.
Link back to a similar question: Protobuf dissector with nested structures