2017-05-01 2 views
1

J'ai atteint la prochaine situation, j'ai besoin de définir une nouvelle couche de protocole dans Scapy et l'un des champs a une taille variable (1,2,3 ou 4 octets) qui dépend de la taille de l'autre couche spécifique. Telle est la situation:Scapy - Référencement de plusieurs champs d'un 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) 

Je sais ne pas comment je peux faire référence à la taille de la couche newLayer_specific du champ length de la couche newLayer Toute suggestion? Merci d'avance.

Répondre

1

Étant donné que vous utilisez une liaison de couche inconditionnelle entre newLayer et newLayerSpecific, nous pouvons peut-être utiliser une seule couche. Dans ce cas, j'utiliser le paramètre adjust pour gérer ici longueur:

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), 
    ] 

Maintenant, nous pouvons tester le résultat en cours d'exécution:

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

Si votre premier champ de longueur a une taille variable, peut juste remplacer FieldLenField avec un VariableFieldLenField que vous auriez à mettre en œuvre (un exemple peut être trouvé here).

Si, pour une raison quelconque, vous ne pouvez pas ou ne voulez pas utiliser une seule couche, voici ce que je propose: vous pouvez « tricher » avec le paramètre length_of et utiliser le paramètre adjust pour faire le travail:

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) 

Encore une fois, nous pouvons tester:

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

Beaucoup de grâce Pierre les deux solutions fonctionnent correctement, les connaissances génial! – somarhs