[Python] Knowing the hierarchy when removing fields from protobuf

Discussão em 'Python' iniciado por Stack, Julho 15, 2025.

  1. Stack

    Stack Membro Participativo

    I am trying to remove the top-level field 53 from a protobuf file(captured from YouTube android client) without a .proto file, but I found that the inner field 53 has also been removed.

    protobuf file: https://www.mediafire.com/file/31srltie0btmrjh/input.bin/file

    Code:

    from typing import Tuple

    class ProtobufFieldRemover:
    def __init__(self):
    self.output = bytearray()

    # Read the varint encoded integer and return (value, new position)
    def _read_varint(self, data: bytes, pos: int) -> Tuple[int, int]:
    value = 0
    shift = 0
    while True:
    if pos >= len(data):
    raise ValueError("Invalid varint")
    byte = data[pos]
    value |= (byte & 0x7F) << shift
    pos += 1
    if not (byte & 0x80):
    return value, pos
    shift += 7

    # Encode integers as varint
    def _write_varint(self, value: int) -> bytes:
    result = bytearray()
    while True:
    byte = value & 0x7F
    value >>= 7
    if value:
    result.append(byte | 0x80)
    else:
    result.append(byte)
    break
    return result

    def remove_field_53(self, input_data: bytes) -> bytes:
    removed = False
    self.output = bytearray()
    pos = 0 # pos records the position index in the binary data being processed
    length = len(input_data)
    while pos < length:
    tag, pos = self._read_varint(input_data, pos)
    field_number = tag >> 3
    wire_type = tag & 0x7
    if field_number in {53}: # found field 53, which is at the top level
    print(f"Found top-level field 53.")
    if wire_type == 0: # Varint
    _, pos = self._read_varint(input_data, pos)
    elif wire_type == 1: # 64-bit
    pos += 8
    elif wire_type == 2: # Length-delimited
    length1, pos = self._read_varint(input_data, pos)
    pos += length1
    elif wire_type == 5: # 32-bit
    pos += 4
    removed = True
    else:
    # Fields that need to be preserved
    self.output.extend(self._write_varint(tag))
    if wire_type == 0: # Varint
    value, pos = self._read_varint(input_data, pos)
    self.output.extend(self._write_varint(value))
    elif wire_type == 1: # 64-bit
    self.output.extend(input_data[pos:pos+8])
    pos += 8
    elif wire_type == 2: # Length-delimited
    length1, pos = self._read_varint(input_data, pos)
    self.output.extend(self._write_varint(length1))
    self.output.extend(input_data[pos:pos+length1])
    pos += length1
    elif wire_type == 5: # 32-bit
    self.output.extend(input_data[pos:pos+4])
    pos += 4
    if removed:
    return bytes(self.output)
    return None

    if __name__ == "__main__":
    remover = ProtobufFieldRemover()

    with open("input.bin", "rb") as f:
    pb_data = f.read()

    # Remove field 53
    result = remover.remove_field_53(pb_data)
    if result is not None:
    print("Successfully removed field 53.")
    with open("output.bin", "wb") as f:
    f.write(result)
    else:
    print("53 field not found.")


    After execution, print as follows:

    Found top-level field 53.
    Found top-level field 53.
    Found top-level field 53.
    Successfully removed field 53.

    Continue reading...

Compartilhe esta Página