Skip to main content

Reverse packed Google Protobuf payload.

Project description

PyPI - Python Version PyPI Package Tests codecov

Reverse packed Google Protobuf payload

Restore packed Google Protobuf message and reveal its value according to packed types. For example, you have a packed Protobuf message represented as a byte string:

# Encoded varint value -1 (signed int) or 1 (unsigned int)
08 01

By using a revpbuf package you may decode that to the following:

Field 1 - type <WireType.Varint>
	sint: -1
	uint: 1

Python code that does such a conversion:

from revpbuf import parser

proto_payload = bytes.fromhex("0801")
message_repr = parser.parse_proto(proto_payload)

Right now you have a message representation that you may print:

class Printer(BaseProtoPrinter):
    def __init__(self):
        self.level = 0

    def visit(self, ty: Union[FieldDescriptor, BaseTypeRepr]) -> str:
        if isinstance(ty, FieldDescriptor):
            return self._visit_field_descriptor(ty)
        else:
            fields = ty.get_fields()

            if not any([f for f in fields if f[0] == "sub-msg"]):
                return self._visit_non_chunk(ty, fields)
            else:
                return self._visit_chunk(ty, fields)

    def _visit_field_descriptor(self, ty: FieldDescriptor) -> str:
        tabs = "\t" * self.level
        result = f"{tabs}Field {ty.field_no} - type <{ty.wire_type}>{os.linesep}"

        return result

    def _visit_non_chunk(
        self, _ty: BaseTypeRepr, fields: Sequence[Union[str, Any]]
    ) -> str:
        tabs_field = "\t" * (self.level + 1)
        result = f"{os.linesep}".join(
            [f"{tabs_field}{field[0]}: {field[1]}" for field in fields]
        )

        return f"{result}{os.linesep}"

    def _visit_chunk(
        self, _ty: BaseTypeRepr, fields: Sequence[Union[str, Any]]
    ) -> str:
        tabs_field = "\t" * (self.level + 1)
        str_stream = io.StringIO()

        for field in fields:
            if field[0] != "sub-msg":
                result = f"{tabs_field}{field[0]}: {field[1]}{os.linesep}"
                str_stream.write(result)
            else:
                if field[1] is not None:
                    result = f"{tabs_field}{field[0]}:{os.linesep}"
                    str_stream.write(result)
                    self.level += 2

                    for sub_msg_field in field[1].fields:
                        result = sub_msg_field.field_desc.accept(self)

                        if result is not None:
                            str_stream.write(result)

                        result = sub_msg_field.field_repr.accept(self)

                        if result is not None:
                            str_stream.write(result)

                    self.level -= 2

        return str_stream.getvalue()

# ...
def proto_print(message: MessageRepr) -> str:
    printer = Printer()
    str_stream = io.StringIO()

    for field in message.fields:
        str_stream.write(field.field_desc.accept(printer))
        str_stream.write(field.field_repr.accept(printer))

    return str_stream.getvalue()

proto_print(message_repr)

That would output the example field representation above:

Field 1 - type <WireType.Varint>
	sint: -1
	uint: 1

Example application may be found here

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

revpbuf-0.1.1.tar.gz (6.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

revpbuf-0.1.1-py2.py3-none-any.whl (6.3 kB view details)

Uploaded Python 2Python 3

File details

Details for the file revpbuf-0.1.1.tar.gz.

File metadata

  • Download URL: revpbuf-0.1.1.tar.gz
  • Upload date:
  • Size: 6.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/50.3.0 requests-toolbelt/0.9.1 tqdm/4.49.0 CPython/3.8.5

File hashes

Hashes for revpbuf-0.1.1.tar.gz
Algorithm Hash digest
SHA256 cf2268c65ba7183bd1e56e4edb8a0c9bbaf67d8758e40aa0cf67f112903d1531
MD5 6320b1d2c06aa9ceafb88aed200e9fb7
BLAKE2b-256 8eba447fc7e5d113dc9db500b835b279efb9da8a932c45ee38be76b29408a37a

See more details on using hashes here.

File details

Details for the file revpbuf-0.1.1-py2.py3-none-any.whl.

File metadata

  • Download URL: revpbuf-0.1.1-py2.py3-none-any.whl
  • Upload date:
  • Size: 6.3 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/50.3.0 requests-toolbelt/0.9.1 tqdm/4.49.0 CPython/3.8.5

File hashes

Hashes for revpbuf-0.1.1-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 64e603637cfac93e5de885ba2e6a7e80f54f736c56d1281cd78cb144e0824a22
MD5 07926c95b5569f0233ad88a1d32aaab4
BLAKE2b-256 2b99257ed198635d222ffa3abf42ff25e57b1937e2c24ff48ed9332855b5b84f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page