2017-04-30 4 views
2

Ich füge Scapy ein neues Protokoll hinzu und habe Schwierigkeiten mit einem konkreten Feld. Dieses Feld gibt die Länge einer Paketnutzlast an. Das Feld kann 1, 2, 3 oder 4 Byte lang sein, abhängig von der Länge der Nutzlast. Darüber hinaus ist es codiert. Die Art, wie ich herausgefunden habe, ob die Größe des Feldes 1, 2, 3 oder 4 Bytes ist, nimmt das erste Byte des Wertes und wenn es kleiner als 127 ist, wird das Feld durch 1 Byte dargestellt, wenn es größer als ist 127 und weniger als x wird durch 2 Bytes usw. dargestellt (dies liegt an dem Kodieralgorithmus).Scapy - Hinzufügen eines neuen Feldes mit einer dynamischen Länge

So ist das Problem, dass ich diese Feldlänge nicht dynamisch basierend auf dem Wert des ersten Bytes definieren kann. Das erste, was ich versuchte, ist dieses Problem mit ConditionalFields zu behandeln, aber das fühlt sich an wie der falsche Weg.

ConditionalField(ByteField("length",1), lambda pkt:pkt.length <= 127), 
    ConditionalField(ShortField("length",None), lambda pkt:pkt.length > 127),] 

ich glaube, die Lösung ein neues scapy Feld zu definieren ist, aber ich weiß nicht, wie das erste Byte für den Zugriff auf und die Setup-Länge auf dieser Grundlage. Jeder Vorschlag wird geschätzt. Danke im Voraus.

Dekodierungsalgorithmus:

def test(encoded_byte): 
    if((encoded_byte & 128) != 0): 
     return True 
    else: 
     return False 


def decoding(bytes): 
    multiplier = 1 
    value = 0 
    offset = 0 
    condition = True 

    while condition: 
     encoded_byte = bytes[offset] 
     value += (encoded_byte & 127) * multiplier 
     multiplier *= 128 
     if multiplier > 128 ** 3: 
      raise Exception('Malformed Remaining Length') 
     offset += 1 
     condition = test(encoded_byte) 

    return value 
+0

Haben Sie Code, den Sie präsentieren möchten? –

+0

Es gibt die Bedingungsfelder und den Decodierungsalgorithmus, den ich für den Wert des Feldes programmiert habe – somarhs

Antwort

1

Sie benötigen eine eigene field hier mit spezifischen .addfield() und .getfield() Methoden zu implementieren. Basierend auf dem Beispiel, hier ist ein Beispiel, das funktionieren soll:

class VariableFieldLenField(FieldLenField): 
    def addfield(self, pkt, s, val): 
     val = self.i2m(pkt, val) 
     data = [] 
     while val: 
      if val > 127: 
       data.append(val & 127) 
       val /= 127 
      else: 
       data.append(val) 
       lastoffset = len(data) - 1 
       data = "".join(chr(val | (0 if i == lastoffset else 128)) 
           for i, val in enumerate(data)) 
       return s + data 
      if len(data) > 3: 
       raise Scapy_Exception("%s: malformed length field" % 
             self.__class__.__name__) 
    def getfield(self, pkt, s): 
     value = 0 
     for offset, curbyte in enumerate(s): 
      curbyte = ord(curbyte) 
      value += (curbyte & 127) * (128 ** offset) 
      if curbyte & 128 == 0: 
       return s[offset + 1:], value 
      if offset > 2: 
       raise Scapy_Exception("%s: malformed length field" % 
             self.__class__.__name__) 

Jetzt ist der schwierigste Teil der Arbeit erledigt ist, müssen Sie nur eine Schicht zu schaffen, die VariableFieldLenField Feld verwendet:

class NewLayer(Packet): 
    fields_desc = [ 
     VariableFieldLenField("length", None, length_of="data"), 
     StrLenField("data", "", length_from=lambda pkt: pkt.length), 
    ] 

Und jetzt, einige Tests, um alles zu überprüfen, funktioniert wie erwartet:

NewLayer('\x01x') 
str(_) 
NewLayer(_) 
NewLayer(data='x') 
str(_) 
NewLayer(_) 
NewLayer(data='x' * 128) 
str(_) 
NewLayer(_) 
str(NewLayer(data='x' * 16385))[:10] 
NewLayer(str(NewLayer(data='x' * 16385))).length 
Verwandte Themen