2017-05-01 4 views
1

Ich habe die nächste Situation erreicht, ich muss eine neue Protokollschicht in Scapy definieren und eines der Felder hat eine variable Größe (1,2,3 oder 4 Bytes), die davon abhängt die Größe einer anderen spezifischen Ebene. Dies ist die Situation:Scapy - Referenzieren mehrerer Felder von einem FieldLenField

class newLayer(Packet): 
     name = "newLayer fixed header" 
     fields_desc = [ 
      ByteField("msgtype",0), 
       # Some other fields ... 
      FieldLenField("length", XXX), # length of newLayer_specific layer 
         # This field can be 1,2,3 or 4 bytes long depending 
         # on the length of the variable header 
     ] 

class newLayer_specific(Packet): 
     name = "variable header" 
     fields_desc = [ 
       FieldLenField("length2","field1"), # This field is always 2 bytes long 
       StrLenField("field1","",length_from = lambda pkt:pkt.length2), 
       StrLenField("field2","", length_from = lambda pkt:pkt.underlayer.length - pkt.length - 2) 
       # 2 is because the length of the length2 field 

bind_layers(newLayer, newLayer_specific, msgtype=1) 

Ich weiß nicht, wie ich auf die Größe der newLayer_specific Schicht aus dem Bereich length der Schicht newLayer Jeder Vorschlag beziehen kann? Danke im Voraus.

Antwort

1

Da Sie eine unbedingte Layer-Bindung zwischen newLayer und newLayerSpecific verwenden, können wir vielleicht eine einzelne Schicht verwenden. In diesem Fall würde ich die adjust Parameter verwendet Länge hier zu handhaben:

class NewLayer(Packet): 
    name = "NewLayer" 
    fields_desc = [ 
     FieldLenField("length", None, length_of="field2", 
         adjust=lambda pkt, val: val + 2 + len(pkt.field1)), 
     FieldLenField("length_field1", None, length_of="field1"), 
     StrLenField("field1", "", length_from=lambda pkt: pkt.length_field1), 
     StrLenField("field2", "", 
        length_from=lambda pkt: pkt.length - pkt.length_field1 - 2), 
    ] 

Jetzt können wir das Ergebnis testen, indem ausgeführt wird:

NewLayer(field1="test", field2="tototiti") 
str(_) 
NewLayer(_) 

Wenn Ihr erstes Längenfeld eine variable Größe hat, Sie kann einfach FieldLenField durch eine VariableFieldLenField ersetzen, die Sie implementieren müssten (ein Beispiel kann here gefunden werden).

Wenn aus irgendeinem Grunde können Sie nicht oder wollen nicht nur eine Schicht verwenden, hier ist das, was ich vorschlagen: Sie können „schummeln“ mit dem length_of Parameter und verwenden Sie die adjust Parameter, um den Job zu erledigen:

class NewLayer(Packet): 
    name = "NewLayer" 
    fields_desc = [ 
     FieldLenField("length", None, length_of="length", 
         adjust=lambda pkt, x: len(pkt.payload)), 
    ] 

class NewLayerSpecific(Packet): 
    name = "NewLayer Specific" 
    fields_desc = [ 
     FieldLenField("length_field1", None, length_of="field1"), 
     StrLenField("field1", "", length_from=lambda pkt: pkt.length_field1), 
     StrLenField("field2", "", 
        length_from=lambda pkt: (pkt.underlayer.length 
              - pkt.length_field1 - 2), 
     ), 
    ] 

bind_layers(NewLayer, NewLayerSpecific) 

Auch hier können wir testen:

NewLayer()/NewLayerSpecific(field1="test", field2="tototiti") 
str(_) 
NewLayer(_) 
+1

Vielen dank Pierre beiden Lösungen korrekt funktionieren, ehrfürchtiges Wissen! – somarhs

Verwandte Themen