3

使用 sr() 或 srp() 函数时 - Scapy 如何知道收到的数据包是对我发送的数据包的答复?

我编写了一个模仿 BACNet 的自定义协议。我可以将 WHO_IS 数据包发送到 BACNet 设备,设备以 I_AM 数据包作为应答,由于层绑定,该数据包被正确反汇编,但 sr 函数无法将其识别为应答。如何让 Scapy 接受这些数据包作为答案?

更新:这就是我的图层类的样子。我认为这些answers()方法看起来不错,但它仍然不起作用。answers()在实施这些方法时我可能会误解什么吗?在我的理解self中是指层本身的类,other是接收到的有问题的数据包。因此,为了将有效负载传递到下一个更高层,我传递并使用下一个更高层类other.payload调用该方法。answers()这些层像Ether/IP/UDP/BVLC/NPDU/APDU.

class BVLC(Packet):

    name = "BVLC"
    fields_desc = [
       # many fields
                   ]

    def post_build(self, pkt, pay):
        if self.length == None:                
            pkt = pkt[0:2] + struct.pack('!H', len(pay)+len(pkt)) + pkt[4:]  
        return pkt+pay

    def answers(self, other):
        if not isinstance(other,BVLC):
            return 0
        else:
            return NPDU.answers(other.payload)


class NPDU(Packet):

    name = "NPDU"
    fields_desc = [ 
        # again, many fields
                   ]

    def answers(self, other):
        if not isinstance(other,NPDU):
            return 0
        else:
            return APDU.answers(other.payload)

class APDU(Packet):

    name = "APDU"
    fields_desc = [
          # many fields and the only relevant field in this case
            ConditionalField(
                ByteEnumField(
                    "serviceChoice", None, APDU_Service_Unconfirmed.revDict()),
                    lambda pkt: pkt.pduType == APDU_Type.CONFIRMED_SERVICE_REQUEST or
                                pkt.pduType == APDU_Type.UNCONFIRMED_SERVICE_REQUEST), 
                   ]

    def answers(self, other):
        if not isinstance(other,APDU):
            return 0
        else:
            if self.serviceChoice == APDU_Service_Unconfirmed.WHO_IS and\
               other.serviceChoice == APDU_Service_Unconfirmed.I_AM:
                return 1
        return 0
4

1 回答 1

4

Scapysr只调用recv_packet.answers(sent_packet)每个发送的数据包。因此,您必须def answers()为您的图层实施,请参阅:

def answers(self, other):
    """DEV: true if self is an answer from other"""
    if other.__class__ == self.__class__:
        return self.payload.answers(other.payload)
    return 0

TCP这是原始图层的摘录:

def answers(self, other):
    if not isinstance(other, TCP):
        return 0
    if conf.checkIPsrc:
        if not ((self.sport == other.dport) and
                (self.dport == other.sport)):
            return 0
    if (abs(other.seq-self.ack) > 2+len(other.payload)):
        return 0
    return 1
于 2015-10-16T17:56:04.770 回答