Heim >Backend-Entwicklung >Golang >Wie kann ich unbekannte Protobuf-Nachrichten ohne Typinformationen analysieren?

Wie kann ich unbekannte Protobuf-Nachrichten ohne Typinformationen analysieren?

Patricia Arquette
Patricia ArquetteOriginal
2024-11-28 01:36:10619Durchsuche

How Can I Parse Unknown Protobuf Messages Without Type Information?

Demarshalling unbekannter Proto-Nachrichten ohne Typinformationen

Während die proto.Unmarshal()-Methode von Protobuf einen bekannten Nachrichtentyp erfordert, stellen unbekannte Nachrichten eine Herausforderung dar . Mit dem Protowire-Paket können wir jedoch begrenzte Informationen extrahieren.

Ansatz:

  1. Verwenden Sie protowire.ConsumeField(), um die unbekannte Nachrichtennutzlast zu durchlaufen.
  2. Identifizieren Sie den Feldtyp, der in Frage kommt sein:

    • Varint
    • Fixed64
    • Bytes
    • StartGroup
    • Fixed32
  3. Parsen Sie die Feldnutzlast basierend auf ihrer Typ.
  4. Behandeln Sie Unternachrichten durch rekursives Parsen ihrer Nutzlasten.

Datenmodell:

type Field struct {
    Tag Tag
    Val Val
}

type Tag struct {
    Num int32
    Type protowire.Type
}

type Val struct {
    Payload interface{}
    Length int
}

Parser:

func parseUnknown(b []byte) []Field {
    // Iteratively consume and parse fields
    for len(b) > 0 {
        // Read field tag and length
        n, t, fieldlen := protowire.ConsumeField(b)
        if fieldlen < 1 {
            return nil
        }
        field := Field{Tag: Tag{Num: int32(n), Type: t}}

        // Read and process tag and value content
        _, _, taglen := protowire.ConsumeTag(b[:fieldlen])
        if taglen < 1 {
            return nil
        }
        var v interface{}
        var vlen int
        switch t {
            case protowire.VarintType:
                v, vlen = protowire.ConsumeVarint(b[taglen:fieldlen])
            case protowire.Fixed64Type:
                v, vlen = protowire.ConsumeFixed64(b[taglen:fieldlen])
            case protowire.BytesType:
                v, vlen = protowire.ConsumeBytes(b[taglen:fieldlen])
                sub := parseUnknown(v.([]byte))
                if sub != nil {
                    v = sub
                }
            case protowire.StartGroupType:
                v, vlen = protowire.ConsumeGroup(n, b[taglen:fieldlen])
                sub := parseUnknown(v.([]byte))
                if sub != nil {
                    v = sub
                }
            case protowire.Fixed32Type:
                v, vlen = protowire.ConsumeFixed32(b[taglen:fieldlen])
        }
        if vlen < 1 {
            return nil
        }

        field.Val = Val{Payload: v, Length: vlen - taglen}
        fields = append(fields, field)
        b = b[fieldlen:]
    }
    return fields
}

Beispiel (Nachrichtenstruktur):

message Foo {
  string a = 1;
  string b = 2;
  Bar bar = 3;
}

message Bar {
  string c = 1;
}

Beispiel (geparste Ausgabe):

main.Field{Tag:main.Tag{Num:1, Type:2}, Val:main.Val{Payload:[]uint8{0x41}, Length:1}}
main.Field{Tag:main.Tag{Num:2, Type:2}, Val:main.Val{Payload:[]uint8{0x42}, Length:1}}
main.Field{Tag:main.Tag{Num:1, Type:2}, Val:main.Val{Payload:[]uint8{0x43}, Length:1}}
main.Field{Tag:main.Tag{Num:3, Type:2}, Val:main.Val{Payload:[]main.Field{main.Field{Tag:main.Tag{Num:1, Type:2}, Val:main.Val{Payload:[]uint8{0x43}, Length:1}}}, Length:3}}

Überlegungen:

  • Unternachrichten: Rekursives Parsen von Bytes Nutzdaten, die als Nachrichten identifiziert wurden.
  • Wiederholte Felder: Wird basierend auf identischen Feld-Tag-Nummern behandelt.
  • Karten: Vermutlich ähnlich zu wiederholten k /v-Paare.
  • Oneofs:Union-Typ-Informationen gehen verloren, nur die Der tatsächliche Wert wird analysiert.

Dieser Code bietet zwar keine vollständige Lösung in Produktionsqualität, bietet jedoch eine Methode zum Parsen unbekannter Proto-Nutzlasten unter Beibehaltung einiger semantischer Informationen.

Das obige ist der detaillierte Inhalt vonWie kann ich unbekannte Protobuf-Nachrichten ohne Typinformationen analysieren?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn