Example #1
0
def _PPIGuessPayloadClass(p, **kargs):
    """ This function tells the PacketListField how it should extract the
        TLVs from the payload.  We pass cls only the length string
        pfh_len says it needs.  If a payload is returned, that means
        part of the string was unused.  This converts to a Raw layer, and
        the remainder of p is added as Raw's payload.  If there is no
        payload, the remainder of p is added as out's payload.
    """
    if len(p) >= 4:
        t, pfh_len = struct.unpack("<HH", p[:4])
        # Find out if the value t is in the dict _ppi_types.
        # If not, return the default TLV class
        cls = getPPIType(t, "default")
        pfh_len += 4
        out = cls(p[:pfh_len], **kargs)
        if (out.payload):
            out.payload = conf.raw_layer(out.payload.load)
            out.payload.underlayer = out
            if (len(p) > pfh_len):
                out.payload.payload = conf.padding_layer(p[pfh_len:])
                out.payload.payload.underlayer = out.payload
        elif (len(p) > pfh_len):
            out.payload = conf.padding_layer(p[pfh_len:])
            out.payload.underlayer = out
    else:
        out = conf.raw_layer(p, **kargs)
    return out
Example #2
0
    def recv(self, x=MTU):
        pkt, sa_ll = self.ins.recvfrom(x)
        if sa_ll[2] == socket.PACKET_OUTGOING:
            return None
        if sa_ll[3] in conf.l2types:
            cls = conf.l2types[sa_ll[3]]
            lvl = 2
        elif sa_ll[1] in conf.l3types:
            cls = conf.l3types[sa_ll[1]]
            lvl = 3
        else:
            cls = conf.default_l2
            warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s", sa_ll[0], sa_ll[1], sa_ll[3], cls.name)  # noqa: E501
            lvl = 3

        try:
            pkt = cls(pkt)
        except KeyboardInterrupt:
            raise
        except Exception:
            if conf.debug_dissector:
                raise
            pkt = conf.raw_layer(pkt)
        if lvl == 2:
            pkt = pkt.payload

        if pkt is not None:
            from scapy.arch import get_last_packet_timestamp
            pkt.time = get_last_packet_timestamp(self.ins)
        return pkt
Example #3
0
    def recv(self, x=MTU):
        pkt, sa_ll = self.ins.recvfrom(x)
        if sa_ll[2] == socket.PACKET_OUTGOING:
            return None
        if sa_ll[3] in conf.l2types:
            cls = conf.l2types[sa_ll[3]]
            lvl = 2
        elif sa_ll[1] in conf.l3types:
            cls = conf.l3types[sa_ll[1]]
            lvl = 3
        else:
            cls = conf.default_l2
            warning(" Impossivel saber o tipo (interface=%s protocol=%#x familia=%i). Usando %s" % (sa_ll[0],sa_ll[1],sa_ll[3],cls.name))
            lvl = 2

        try:
            pkt = cls(pkt)
        except KeyboardInterrupt:
            raise
        except:
            if conf.debug_dissector:
                raise
            pkt = conf.raw_layer(pkt)
        if lvl == 2:
            pkt = pkt.payload
            
        if pkt is not None:
            pkt.time = get_last_packet_timestamp(self.ins)
        return pkt
Example #4
0
        def recv(self, x=MTU):
            ll = self.ins.datalink()
            if ll in conf.l2types:
                cls = conf.l2types[ll]
            else:
                cls = conf.default_l2
                warning(
                    "Unable to guess datalink type (interface=%s linktype=%i). Using %s" % (self.iface, ll, cls.name)
                )

            pkt = self.ins.next()
            if pkt is not None:
                ts, pkt = pkt
            if pkt is None:
                return

            try:
                pkt = cls(pkt)
            except KeyboardInterrupt:
                raise
            except:
                if conf.debug_dissector:
                    raise
                pkt = conf.raw_layer(pkt)
            pkt.time = ts
            return pkt
Example #5
0
 def getfield(self, pkt, s):
     c = l = None
     if self.length_from is not None:
         l = self.length_from(pkt)
     elif self.count_from is not None:
         c = self.count_from(pkt)
         
     lst = []
     ret = ""
     remain = s
     if l is not None:
         remain,ret = s[:l],s[l:]
     while remain:
         if c is not None:
             if c <= 0:
                 break
             c -= 1
         try:
             p = self.m2i(pkt,remain)
         except Exception:
             if conf.debug_dissector:
                 raise
             p = conf.raw_layer(load=remain)
             remain = ""
         else:
             if conf.padding_layer in p:
                 pad = p[conf.padding_layer]
                 remain = pad.load
                 del(pad.underlayer.payload)
             else:
                 remain = ""
         lst.append(p)
     return remain+ret,lst
Example #6
0
 def getfield(self, pkt, s):
     l = self.length_from(pkt)
     try:
         i = self.m2i(pkt, s[:l])
     except Exception:
         if conf.debug_dissector:
             raise
         i = conf.raw_layer(load=s[:l])
     return s[l:],i
Example #7
0
 def m2i(self, pkt, m):
     ret = None
     eap_packet_len = struct.unpack("!H", m[2:4])[0]
     if eap_packet_len < 254:
         # If the EAP packet has not been fragmented, build a Scapy EAP
         # packet from the data.
         ret = EAP(m)
     else:
         ret = conf.raw_layer(m)
     return ret
Example #8
0
 def do_dissect_payload(self, s):
     if s:
         try:
             p = SSLv2(s, _internal=1, _underlayer=self,
                       tls_session = self.tls_session)
         except KeyboardInterrupt:
             raise
         except:
             p = conf.raw_layer(s, _internal=1, _underlayer=self)
         self.add_payload(p)
Example #9
0
 def __div__(self, other):
     if isinstance(other, Packet):
         cloneA = self.copy()
         cloneB = other.copy()
         cloneA.add_payload(cloneB)
         return cloneA
     elif type(other) is str:
         return self/conf.raw_layer(load=other)
     else:
         return other.__rdiv__(self)
Example #10
0
 def recv(self, x=MTU):
     cls, val, ts = self.recv_raw(x)
     if not val or not cls:
         return
     try:
         pkt = cls(val)
     except KeyboardInterrupt:
         raise
     except Exception:
         if conf.debug_dissector:
             raise
         pkt = conf.raw_layer(val)
     pkt.time = ts
     return pkt
Example #11
0
 def recv(self, x=MTU):
     pkt, sa_ll = self.ins.recvfrom(x)
     if sa_ll[2] == socket.PACKET_OUTGOING:
         return None
     try:
         q = self.LL(pkt)
     except KeyboardInterrupt:
         raise
     except:
         if conf.debug_dissector:
             raise
         q = conf.raw_layer(pkt)
     q.time = get_last_packet_timestamp(self.ins)
     return q
Example #12
0
def __gen_send(s,
               x,
               inter=0,
               loop=0,
               count=None,
               verbose=None,
               realtime=None,
               return_packets=False,
               *args,
               **kargs):  # noqa: E501
    if isinstance(x, str):
        x = conf.raw_layer(load=x)
    if not isinstance(x, Gen):
        x = SetGen(x)
    if verbose is None:
        verbose = conf.verb
    n = 0
    if count is not None:
        loop = -count
    elif not loop:
        loop = -1
    if return_packets:
        sent_packets = PacketList()
    try:
        while loop:
            dt0 = None
            for p in x:
                if realtime:
                    ct = time.time()
                    if dt0:
                        st = dt0 + float(p.time) - ct
                        if st > 0:
                            time.sleep(st)
                    else:
                        dt0 = ct - float(p.time)
                s.send(p)
                if return_packets:
                    sent_packets.append(p)
                n += 1
                if verbose:
                    os.write(1, b".")
                time.sleep(inter)
            if loop < 0:
                loop += 1
    except KeyboardInterrupt:
        pass
    if verbose:
        print("\nSent %i packets." % n)
    if return_packets:
        return sent_packets
Example #13
0
 def recv(self, x=MTU):
     cls, val, ts = self.recv_raw(x)
     if not val or not cls:
         return
     try:
         pkt = cls(val)
     except KeyboardInterrupt:
         raise
     except Exception:
         if conf.debug_dissector:
             raise
         pkt = conf.raw_layer(val)
     pkt.time = ts
     return pkt
Example #14
0
 def recv(self, x=MTU):
     pkt, sa_ll = self.ins.recvfrom(x)
     if sa_ll[2] == socket.PACKET_OUTGOING:
         return None
     try:
         q = self.LL(pkt)
     except KeyboardInterrupt:
         raise
     except:
         if conf.debug_dissector:
             raise
         q = conf.raw_layer(pkt)
     q.time = get_last_packet_timestamp(self.ins)
     return q
Example #15
0
class ISAKMP_payload_Proposal(ISAKMP_class):
    name = "IKE proposal"
#    ISAKMP_payload_type = 0
    fields_desc = [
        ByteEnumField("next_payload", None, ISAKMP_payload_type),
        ByteField("res", 0),
        FieldLenField("length", None, "trans", "H", adjust=lambda pkt, x:x + 8),  # noqa: E501
        ByteField("proposal", 1),
        ByteEnumField("proto", 1, {1: "ISAKMP"}),
        FieldLenField("SPIsize", None, "SPI", "B"),
        ByteField("trans_nb", None),
        StrLenField("SPI", "", length_from=lambda x: x.SPIsize),
        PacketLenField("trans", conf.raw_layer(), ISAKMP_payload_Transform, length_from=lambda x: x.length - 8),  # noqa: E501
    ]
Example #16
0
 def do_dissect_payload(self, s):
     """
     Try to dissect the following data as a TLS message.
     Note that overloading .guess_payload_class() would not be enough,
     as the TLS session to be used would get lost.
     """
     if s:
         try:
             p = TLS(s, _internal=1, _underlayer=self,
                     tls_session = self.tls_session)
         except KeyboardInterrupt:
             raise
         except:
             p = conf.raw_layer(s, _internal=1, _underlayer=self)
         self.add_payload(p)
Example #17
0
 def do_dissect_payload(self, s):
     """
     Try to dissect the following data as a TLS message.
     Note that overloading .guess_payload_class() would not be enough,
     as the TLS session to be used would get lost.
     """
     if s:
         try:
             p = TLS(s, _internal=1, _underlayer=self,
                     tls_session=self.tls_session)
         except KeyboardInterrupt:
             raise
         except Exception:
             p = conf.raw_layer(s, _internal=1, _underlayer=self)
         self.add_payload(p)
Example #18
0
 def read_packet(self, size=MTU):
     rp = RawPcapNgReader.read_packet(self, size=size)
     if rp is None:
         return None
     s, (linktype, sec, usec, wirelen) = rp
     try:
         p = conf.l2types[linktype](s)
     except KeyboardInterrupt:
         raise
     except:
         if conf.debug_dissector:
             raise
         p = conf.raw_layer(s)
     p.time = sec + 0.000001 * usec
     return p
Example #19
0
 def read_packet(self, size=MTU):
     rp = RawPcapNgReader.read_packet(self, size=size)
     if rp is None:
         return None
     s, (linktype, sec, usec, wirelen) = rp
     try:
         p = conf.l2types[linktype](s)
     except KeyboardInterrupt:
         raise
     except:
         if conf.debug_dissector:
             raise
         p = conf.raw_layer(s)
     p.time = sec+0.000001*usec
     return p
Example #20
0
 def read_packet(self, size=MTU):
     rp = RawPcapNgReader.read_packet(self, size=size)
     if rp is None:
         return None
     s, (linktype, tsresol, tshigh, tslow, wirelen) = rp
     try:
         p = conf.l2types[linktype](s)
     except KeyboardInterrupt:
         raise
     except:
         if conf.debug_dissector:
             raise
         p = conf.raw_layer(s)
     if tshigh is not None:
         p.time = float((tshigh << 32) + tslow) / tsresol
     return p
Example #21
0
File: utils.py Project: mcpat/scapy
 def read_packet(self, size=MTU):
     rp = RawPcapNgReader.read_packet(self, size=size)
     if rp is None:
         return None
     s, (linktype, tsresol, tshigh, tslow, wirelen) = rp
     try:
         p = conf.l2types[linktype](s)
     except KeyboardInterrupt:
         raise
     except:
         if conf.debug_dissector:
             raise
         p = conf.raw_layer(s)
     if tshigh is not None:
         p.time = float((tshigh << 32) + tslow) / tsresol
     return p
Example #22
0
 def read_packet(self, size=MTU):
     rp = RawPcapReader.read_packet(self, size=size)
     if rp is None:
         return None
     s,(sec,usec,wirelen) = rp
     
     try:
         p = self.LLcls(s)
     except KeyboardInterrupt:
         raise
     except:
         if conf.debug_dissector:
             raise
         p = conf.raw_layer(s)
     p.time = sec + (0.000000001 if self.nano else 0.000001) * usec
     return p
Example #23
0
File: utils.py Project: mcpat/scapy
 def read_packet(self, size=MTU):
     rp = RawPcapReader.read_packet(self, size=size)
     if rp is None:
         return None
     s,(sec,usec,wirelen) = rp
     
     try:
         p = self.LLcls(s)
     except KeyboardInterrupt:
         raise
     except:
         if conf.debug_dissector:
             raise
         p = conf.raw_layer(s)
     p.time = sec + (0.000000001 if self.nano else 0.000001) * usec
     return p
Example #24
0
 def recv(self, x=MTU):
     cls, val, ts = self.recv_raw(x)
     if not val or not cls:
         return
     try:
         pkt = cls(val)
     except KeyboardInterrupt:
         raise
     except Exception:
         if conf.debug_dissector:
             from scapy.sendrecv import debug
             debug.crashed_on = (cls, val)
             raise
         pkt = conf.raw_layer(val)
     pkt.time = ts
     return pkt
Example #25
0
 def do_dissect_payload(self, s):
     if s:
         cls = self.guess_payload_class(s)
         try:
             p = cls(s, _internal=1, _underlayer=self)
         except KeyboardInterrupt:
             raise
         except:
             if conf.debug_dissector:
                 if isinstance(cls,type) and issubclass(cls,Packet):
                     log_runtime.error("%s dissector failed" % cls.name)
                 else:
                     log_runtime.error("%s.guess_payload_class() returned [%s]" % (self.__class__.__name__,repr(cls)))
                 if cls is not None:
                     raise
             p = conf.raw_layer(s, _internal=1, _underlayer=self)
         self.add_payload(p)
Example #26
0
 def add_payload(self, payload):
     if payload is None:
         return
     elif not isinstance(self.payload, NoPayload):
         self.payload.add_payload(payload)
     else:
         if isinstance(payload, Packet):
             self.payload = payload
             payload.add_underlayer(self)
             for t in self.aliastypes:
                 if payload.overload_fields.has_key(t):
                     self.overloaded_fields = payload.overload_fields[t]
                     break
         elif type(payload) is str:
             self.payload = conf.raw_layer(load=payload)
         else:
             raise TypeError("payload must be either 'Packet' or 'str', not [%s]" % repr(payload))
Example #27
0
 def do_dissect_payload(self, s):
     if s:
         cls = self.guess_payload_class(s)
         try:
             p = cls(s, _internal=1, _underlayer=self)
         except KeyboardInterrupt:
             raise
         except:
             if conf.debug_dissector:
                 if isinstance(cls,type) and issubclass(cls,Packet):
                     log_runtime.error("%s dissector failed" % cls.name)
                 else:
                     log_runtime.error("%s.guess_payload_class() returned [%s]" % (self.__class__.__name__,repr(cls)))
                 if cls is not None:
                     raise
             p = conf.raw_layer(s, _internal=1, _underlayer=self)
         self.add_payload(p)
Example #28
0
 def read_packet(self, size=MTU):
     rp = super(PcapReader, self).read_packet(size=size)
     if rp is None:
         return None
     s, pkt_info = rp
     
     try:
         p = self.LLcls(s)
     except KeyboardInterrupt:
         raise
     except:
         if conf.debug_dissector:
             raise
         p = conf.raw_layer(s)
     p.time = pkt_info.sec + (0.000000001 if self.nano else 0.000001) * pkt_info.usec
     p.wirelen = pkt_info.wirelen
     return p
Example #29
0
class IEC104_I_Message_SeqIOA(IEC104_I_Message):
    """
    all information objects share a base information object address field

    sq = 1, see EN 60870-5-101:2003, sec. 7.2.2.1 (p. 33)
    """
    name = 'IEC-104 I APDU (Seq IOA)'

    fields_desc = [
        # APCI
        XByteField('start', IEC104_I_Message.IEC_104_MAGIC),
        FieldLenField("apdu_length",
                      None,
                      fmt="!B",
                      length_of='io',
                      adjust=lambda pkt, x: x + 13),
        IEC104SequenceNumber('tx_seq_num', 0),
        IEC104SequenceNumber('rx_seq_num', 0),

        # ASDU
        ByteEnumField('type_id', 0, IEC104_IO_NAMES),
        BitEnumField('sq', IEC104_I_Message.SQ_FLAG_SEQUENCE, 1,
                     IEC104_I_Message.SQ_FLAGS),
        BitFieldLenField('num_io', None, 7, count_of='io'),
        BitEnumField('test', 0, 1, IEC104_I_Message.TEST_FLAGS),
        BitEnumField('ack', 0, 1, IEC104_I_Message.ACK_FLAGS),
        BitEnumField('cot', 0, 6, CAUSE_OF_TRANSMISSIONS),
        ByteField('origin_address', 0),
        LEShortField('common_asdu_address', 0),
        LEThreeBytesField('information_object_address', 0),
        IEC104ASDUPacketListField('io',
                                  conf.raw_layer(),
                                  _i_msg_io_dispatcher_sequence,
                                  length_from=lambda pkt: pkt.apdu_length - 13)
    ]

    def post_dissect(self, s):
        if self.type_id == IEC104_IO_ID_C_RD_NA_1:

            # IEC104_IO_ID_C_RD_NA_1 has no payload. we will add the layer
            # manually to the stack right now. we do this num_io times
            # as - even if it makes no sense - someone could decide
            # to add more than one read commands in a sequence...
            setattr(self, 'io', [IEC104_IO_C_RD_NA_1()] * self.num_io)

        return s
Example #30
0
def iec104_decode(payload):
    """
    can be used to dissect payload of a TCP connection
    :param payload: the application layer data (IEC104-APDU(s))
    :return: iec104 (I/U/S) message instance, conf.raw_layer() if unknown
    """

    if _iec104_is_i_apdu_seq_ioa(payload):
        return IEC104_I_Message_SeqIOA(payload)
    elif _iec104_is_i_apdu_single_ioa(payload):
        return IEC104_I_Message_SingleIOA(payload)
    elif _iec104_is_s_apdu(payload):
        return IEC104_S_Message(payload)
    elif _iec104_is_u_apdu(payload):
        return IEC104_U_Message(payload)
    else:
        return conf.raw_layer(payload)
Example #31
0
 def add_payload(self, payload):
     if payload is None:
         return
     elif not isinstance(self.payload, NoPayload):
         self.payload.add_payload(payload)
     else:
         if isinstance(payload, Packet):
             self.payload = payload
             payload.add_underlayer(self)
             for t in self.aliastypes:
                 if payload.overload_fields.has_key(t):
                     self.overloaded_fields = payload.overload_fields[t]
                     break
         elif type(payload) is str:
             self.payload = conf.raw_layer(load=payload)
         else:
             raise TypeError("payload must be either 'Packet' or 'str', not [%s]" % repr(payload))
Example #32
0
class ISAKMP_payload_SA(ISAKMP_class):
    name = "ISAKMP SA"
    overload_fields = {ISAKMP: {"next_payload": 1}}
    fields_desc = [
        ByteEnumField("next_payload", None, ISAKMP_payload_type),
        ByteField("res", 0),
        FieldLenField("length",
                      None,
                      "prop",
                      "H",
                      adjust=lambda pkt, x: x + 12),  # noqa: E501
        IntEnumField("DOI", 1, {1: "IPSEC"}),
        IntEnumField("situation", 1, {1: "identity"}),
        PacketLenField("prop",
                       conf.raw_layer(),
                       ISAKMP_payload_Proposal,
                       length_from=lambda x: x.length - 12),  # noqa: E501
    ]
Example #33
0
 def recv(self, x=MTU):
     # type: (int) -> Optional[Packet]
     cls, val, ts = self.recv_raw(x)
     if not val or not cls:
         return None
     try:
         pkt = cls(val)  # type: Packet
     except KeyboardInterrupt:
         raise
     except Exception:
         if conf.debug_dissector:
             from scapy.sendrecv import debug
             debug.crashed_on = (cls, val)
             raise
         pkt = conf.raw_layer(val)
     if ts:
         pkt.time = ts
     return pkt
Example #34
0
    def getfield(self, pkt, s):
        c = l = cls = None
        if self.length_from is not None:
            l = self.length_from(pkt)
        elif self.count_from is not None:
            c = self.count_from(pkt)
        if self.next_cls_cb is not None:
            cls = self.next_cls_cb(pkt, [], None, s)
            c = 1

        lst = []
        ret = b""
        remain = s
        if l is not None:
            remain,ret = s[:l],s[l:]
        while remain:
            if c is not None:
                if c <= 0:
                    break
                c -= 1
            try:
                if cls is not None:
                    p = cls(remain)
                else:
                    p = self.m2i(pkt, remain)
            except Exception:
                if conf.debug_dissector:
                    raise
                p = conf.raw_layer(load=remain)
                remain = b""
            else:
                if conf.padding_layer in p:
                    pad = p[conf.padding_layer]
                    remain = pad.load
                    del(pad.underlayer.payload)
                    if self.next_cls_cb is not None:
                        cls = self.next_cls_cb(pkt, lst, p, remain)
                        if cls is not None:
                            c += 1
                else:
                    remain = b""
            lst.append(p)
        return remain+ret,lst
Example #35
0
    def extract_frames(self, bpf_buffer):
        """Extract all frames from the buffer and stored them in the received list."""  # noqa: E501

        # Ensure that the BPF buffer contains at least the header
        len_bb = len(bpf_buffer)
        if len_bb < 20:  # Note: 20 == sizeof(struct bfp_hdr)
            return

        # Extract useful information from the BPF header
        if FREEBSD or NETBSD:
            # struct bpf_xhdr or struct bpf_hdr32
            bh_tstamp_offset = 16
        else:
            # struct bpf_hdr
            bh_tstamp_offset = 8

        # Parse the BPF header
        bh_caplen = struct.unpack(
            'I',
            bpf_buffer[bh_tstamp_offset:bh_tstamp_offset + 4])[0]  # noqa: E501
        next_offset = bh_tstamp_offset + 4
        bh_datalen = struct.unpack('I', bpf_buffer[next_offset:next_offset +
                                                   4])[0]  # noqa: E501
        next_offset += 4
        bh_hdrlen = struct.unpack('H', bpf_buffer[next_offset:next_offset +
                                                  2])[0]  # noqa: E501
        if bh_datalen == 0:
            return

        # Get and store the Scapy object
        frame_str = bpf_buffer[bh_hdrlen:bh_hdrlen + bh_caplen]
        try:
            pkt = self.guessed_cls(frame_str)
        except Exception:
            if conf.debug_dissector:
                raise
            pkt = conf.raw_layer(frame_str)
        self.received_frames.append(pkt)

        # Extract the next frame
        end = self.bpf_align(bh_hdrlen, bh_caplen)
        if (len_bb - end) >= 20:
            self.extract_frames(bpf_buffer[end:])
Example #36
0
def __gen_send(s, x, inter=0, loop=0, count=None, verbose=None, realtime=None, return_packets=False, *args, **kargs):
    if isinstance(x, str):
        x = conf.raw_layer(load=x)
    if not isinstance(x, Gen):
        x = SetGen(x)
    if verbose is None:
        verbose = conf.verb
    n = 0
    if count is not None:
        loop = -count
    elif not loop:
        loop = -1
    if return_packets:
        sent_packets = plist.PacketList()
    try:
        while loop:
            dt0 = None
            for p in x:
                if realtime:
                    ct = time.time()
                    if dt0:
                        st = dt0+p.time-ct
                        if st > 0:
                            time.sleep(st)
                    else:
                        dt0 = ct-p.time
                s.send(p)
                if return_packets:
                    sent_packets.append(p)
                n += 1
                if verbose:
                    os.write(1,".")
                time.sleep(inter)
            if loop < 0:
                loop += 1
    except KeyboardInterrupt:
        pass
    s.close()
    if verbose:
        print("\nSent %i packets." % n)
    if return_packets:
        return sent_packets
Example #37
0
    def recv(self, x=MTU):
        pkt, sa_ll = self.ins.recvfrom(x)
        if sa_ll[3] in conf.l2types :
            cls = conf.l2types[sa_ll[3]]
        elif sa_ll[1] in conf.l3types:
            cls = conf.l3types[sa_ll[1]]
        else:
            cls = conf.default_l2
            warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s" % (sa_ll[0],sa_ll[1],sa_ll[3],cls.name))

        try:
            pkt = cls(pkt)
        except KeyboardInterrupt:
            raise
        except:
            if conf.debug_dissector:
                raise
            pkt = conf.raw_layer(pkt)
        pkt.time = get_last_packet_timestamp(self.ins)
        return pkt
Example #38
0
    def extract_frames(self, bpf_buffer):
        """Extract all frames from the buffer and stored them in the received list."""  # noqa: E501

        # Ensure that the BPF buffer contains at least the header
        len_bb = len(bpf_buffer)
        if len_bb < 20:  # Note: 20 == sizeof(struct bfp_hdr)
            return

        # Extract useful information from the BPF header
        if FREEBSD or NETBSD:
            # struct bpf_xhdr or struct bpf_hdr32
            bh_tstamp_offset = 16
        else:
            # struct bpf_hdr
            bh_tstamp_offset = 8

        # Parse the BPF header
        bh_caplen = struct.unpack('I', bpf_buffer[bh_tstamp_offset:bh_tstamp_offset + 4])[0]  # noqa: E501
        next_offset = bh_tstamp_offset + 4
        bh_datalen = struct.unpack('I', bpf_buffer[next_offset:next_offset + 4])[0]  # noqa: E501
        next_offset += 4
        bh_hdrlen = struct.unpack('H', bpf_buffer[next_offset:next_offset + 2])[0]  # noqa: E501
        if bh_datalen == 0:
            return

        # Get and store the Scapy object
        frame_str = bpf_buffer[bh_hdrlen:bh_hdrlen + bh_caplen]
        try:
            pkt = self.guessed_cls(frame_str)
        except Exception:
            if conf.debug_dissector:
                raise
            pkt = conf.raw_layer(frame_str)
        self.received_frames.append(pkt)

        # Extract the next frame
        end = self.bpf_align(bh_hdrlen, bh_caplen)
        if (len_bb - end) >= 20:
            self.extract_frames(bpf_buffer[end:])
Example #39
0
class IEC104_I_Message_SingleIOA(IEC104_I_Message):
    """
    every information object contains an individual information object
    address field

    sq = 0, see EN 60870-5-101:2003, sec. 7.2.2.1 (p. 33)
    """
    name = 'IEC-104 I APDU (single IOA)'

    fields_desc = [
        # APCI
        XByteField('start', IEC104_I_Message.IEC_104_MAGIC),
        FieldLenField("apdu_length", None, fmt="!B", length_of='io',
                      adjust=lambda pkt, x: x + 10),

        IEC104SequenceNumber('tx_seq_num', 0),
        IEC104SequenceNumber('rx_seq_num', 0),

        # ASDU
        ByteEnumField('type_id', 0, IEC104_IO_NAMES),

        BitEnumField('sq', IEC104_I_Message.SQ_FLAG_SINGLE, 1,
                     IEC104_I_Message.SQ_FLAGS),
        BitFieldLenField('num_io', None, 7, count_of='io'),

        BitEnumField('test', 0, 1, IEC104_I_Message.TEST_FLAGS),
        BitEnumField('ack', 0, 1, IEC104_I_Message.ACK_FLAGS),
        BitEnumField('cot', 0, 6, CAUSE_OF_TRANSMISSIONS),

        ByteField('origin_address', 0),

        LEShortField('common_asdu_address', 0),

        IEC104ASDUPacketListField('io',
                                  conf.raw_layer(),
                                  _i_msg_io_dispatcher_single,
                                  length_from=lambda pkt: pkt.apdu_length - 10)
    ]
Example #40
0
     def recv(self, x=MTU):
         ll = self.ins.datalink()
         if ll in conf.l2types:
             cls = conf.l2types[ll]
         else:
             cls = conf.default_l2
             warning("Unable to guess datalink type (interface=%s linktype=%i). Using %s", self.iface, ll, cls.name)
 
         pkt = self.ins.next()
         if scapy.arch.WINDOWS and pkt is None:
                 raise PcapTimeoutElapsed
         if pkt is not None:
             ts,pkt = pkt
             try:
                 pkt = cls(pkt)
             except KeyboardInterrupt:
                 raise
             except:
                 if conf.debug_dissector:
                     raise
                 pkt = conf.raw_layer(pkt)
             pkt.time = ts
         return pkt
Example #41
0
    def getfield(self, pkt, s):
        c = l = None
        if self.length_from is not None:
            l = self.length_from(pkt)
        elif self.count_from is not None:
            c = self.count_from(pkt)

        lst = []
        ret = ""
        remain = s
        if l is not None:
            remain, ret = s[:l], s[l:]
        while remain:
            if c is not None:
                if c <= 0:
                    break
                c -= 1
            try:
                p = self.m2i(pkt, remain)
            except Exception:
                if conf.debug_dissector:
                    raise
                p = conf.raw_layer(load=remain)
                remain = ""
            else:
                if conf.padding_layer in p:
                    pad = p[conf.padding_layer]
                    remain = pad.load
                    del (pad.underlayer.payload)
                else:
                    remain = ""
            lst.append(p)
            # Evaluate the stop condition
            if self.stop and self.stop(p):
                break
        return remain + ret, lst
Example #42
0
    def recv(self, x=MTU):
        # type: (int) -> Optional[Packet]
        data, sa_ll, ts = self._recv_raw(self.ins, x)
        if sa_ll[2] == socket.PACKET_OUTGOING:
            return None
        if sa_ll[3] in conf.l2types:
            cls = conf.l2types.num2layer[sa_ll[3]]  # type: Type[Packet]
            lvl = 2
        elif sa_ll[1] in conf.l3types:
            cls = conf.l3types.num2layer[sa_ll[1]]
            lvl = 3
        else:
            cls = conf.default_l2
            warning(
                "Unable to guess type (interface=%s protocol=%#x family=%i). Using %s",
                sa_ll[0], sa_ll[1], sa_ll[3], cls.name)  # noqa: E501
            lvl = 3

        try:
            pkt = cls(data)
        except KeyboardInterrupt:
            raise
        except Exception:
            if conf.debug_dissector:
                raise
            pkt = conf.raw_layer(data)

        if lvl == 2:
            pkt = pkt.payload

        if pkt is not None:
            if ts is None:
                from scapy.arch.linux import get_last_packet_timestamp
                ts = get_last_packet_timestamp(self.ins)
            pkt.time = ts
        return pkt
Example #43
0
     def recv(self,x=MTU):
         ll = self.ins.datalink()
         if ll in conf.l2types:
             cls = conf.l2types[ll]
         else:
             cls = conf.default_l2
             warning("Unable to guess datalink type (interface=%s linktype=%i). Using %s" % (self.iface, ll, cls.name))
 
         pkt = next(self.ins)
         if pkt is not None:
             ts,pkt = pkt
         if pkt is None:
             return
 
         try:
             pkt = cls(pkt)
         except KeyboardInterrupt:
             raise
         except:
             if conf.debug_dissector:
                 raise
             pkt = conf.raw_layer(pkt)
         pkt.time = ts
         return pkt.payload
Example #44
0
File: p0f.py Project: commial/scapy
def p0f_impersonate(pkt, osgenre=None, osdetails=None, signature=None,
                    extrahops=0, mtu=1500, uptime=None):
    """Modifies pkt so that p0f will think it has been sent by a
specific OS.  If osdetails is None, then we randomly pick up a
personality matching osgenre. If osgenre and signature are also None,
we use a local signature (using p0f_getlocalsigs). If signature is
specified (as a tuple), we use the signature.

For now, only TCP Syn packets are supported.
Some specifications of the p0f.fp file are not (yet) implemented."""
    pkt = pkt.copy()
    # pkt = pkt.__class__(raw(pkt))
    while pkt.haslayer(IP) and pkt.haslayer(TCP):
        pkt = pkt.getlayer(IP)
        if isinstance(pkt.payload, TCP):
            break
        pkt = pkt.payload

    if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP):
        raise TypeError("Not a TCP/IP packet")

    db = p0f_selectdb(pkt.payload.flags)
    if osgenre:
        pb = db.get_base()
        if pb is None:
            pb = []
        pb = [x for x in pb if x[6] == osgenre]
        if osdetails:
            pb = [x for x in pb if x[7] == osdetails]
    elif signature:
        pb = [signature]
    else:
        pb = p0f_getlocalsigs()[db]
    if db == p0fr_kdb:
        # 'K' quirk <=> RST+ACK
        if pkt.payload.flags & 0x4 == 0x4:
            pb = [x for x in pb if 'K' in x[5]]
        else:
            pb = [x for x in pb if 'K' not in x[5]]
    if not pb:
        raise Scapy_Exception("No match in the p0f database")
    pers = pb[random.randint(0, len(pb) - 1)]

    # options (we start with options because of MSS)
    # Take the options already set as "hints" to use in the new packet if we
    # can. MSS, WScale and Timestamp can all be wildcarded in a signature, so
    # we'll use the already-set values if they're valid integers.
    orig_opts = dict(pkt.payload.options)
    int_only = lambda val: val if isinstance(val, six.integer_types) else None
    mss_hint = int_only(orig_opts.get('MSS'))
    wscale_hint = int_only(orig_opts.get('WScale'))
    ts_hint = [int_only(o) for o in orig_opts.get('Timestamp', (None, None))]

    options = []
    if pers[4] != '.':
        for opt in pers[4].split(','):
            if opt[0] == 'M':
                # MSS might have a maximum size because of window size
                # specification
                if pers[0][0] == 'S':
                    maxmss = (2**16 - 1) // int(pers[0][1:])
                else:
                    maxmss = (2**16 - 1)
                # disregard hint if out of range
                if mss_hint and not 0 <= mss_hint <= maxmss:
                    mss_hint = None
                # If we have to randomly pick up a value, we cannot use
                # scapy RandXXX() functions, because the value has to be
                # set in case we need it for the window size value. That's
                # why we use random.randint()
                if opt[1:] == '*':
                    if mss_hint is not None:
                        options.append(('MSS', mss_hint))
                    else:
                        options.append(('MSS', random.randint(1, maxmss)))
                elif opt[1] == '%':
                    coef = int(opt[2:])
                    if mss_hint is not None and mss_hint % coef == 0:
                        options.append(('MSS', mss_hint))
                    else:
                        options.append((
                            'MSS', coef * random.randint(1, maxmss // coef)))
                else:
                    options.append(('MSS', int(opt[1:])))
            elif opt[0] == 'W':
                if wscale_hint and not 0 <= wscale_hint < 2**8:
                    wscale_hint = None
                if opt[1:] == '*':
                    if wscale_hint is not None:
                        options.append(('WScale', wscale_hint))
                    else:
                        options.append(('WScale', RandByte()))
                elif opt[1] == '%':
                    coef = int(opt[2:])
                    if wscale_hint is not None and wscale_hint % coef == 0:
                        options.append(('WScale', wscale_hint))
                    else:
                        options.append((
                            'WScale', coef * RandNum(min=1, max=(2**8 - 1) // coef)))  # noqa: E501
                else:
                    options.append(('WScale', int(opt[1:])))
            elif opt == 'T0':
                options.append(('Timestamp', (0, 0)))
            elif opt == 'T':
                # Determine first timestamp.
                if uptime is not None:
                    ts_a = uptime
                elif ts_hint[0] and 0 < ts_hint[0] < 2**32:
                    # Note: if first ts is 0, p0f registers it as "T0" not "T",
                    # hence we don't want to use the hint if it was 0.
                    ts_a = ts_hint[0]
                else:
                    ts_a = random.randint(120, 100 * 60 * 60 * 24 * 365)
                # Determine second timestamp.
                if 'T' not in pers[5]:
                    ts_b = 0
                elif ts_hint[1] and 0 < ts_hint[1] < 2**32:
                    ts_b = ts_hint[1]
                else:
                    # FIXME: RandInt() here does not work (bug (?) in
                    # TCPOptionsField.m2i often raises "OverflowError:
                    # long int too large to convert to int" in:
                    #    oval = struct.pack(ofmt, *oval)"
                    # Actually, this is enough to often raise the error:
                    #    struct.pack('I', RandInt())
                    ts_b = random.randint(1, 2**32 - 1)
                options.append(('Timestamp', (ts_a, ts_b)))
            elif opt == 'S':
                options.append(('SAckOK', ''))
            elif opt == 'N':
                options.append(('NOP', None))
            elif opt == 'E':
                options.append(('EOL', None))
            elif opt[0] == '?':
                if int(opt[1:]) in TCPOptions[0]:
                    optname = TCPOptions[0][int(opt[1:])][0]
                    optstruct = TCPOptions[0][int(opt[1:])][1]
                    options.append((optname,
                                    struct.unpack(optstruct,
                                                  RandString(struct.calcsize(optstruct))._fix())))  # noqa: E501
                else:
                    options.append((int(opt[1:]), ''))
            # FIXME: qqP not handled
            else:
                warning("unhandled TCP option " + opt)
            pkt.payload.options = options

    # window size
    if pers[0] == '*':
        pkt.payload.window = RandShort()
    elif pers[0].isdigit():
        pkt.payload.window = int(pers[0])
    elif pers[0][0] == '%':
        coef = int(pers[0][1:])
        pkt.payload.window = coef * RandNum(min=1, max=(2**16 - 1) // coef)
    elif pers[0][0] == 'T':
        pkt.payload.window = mtu * int(pers[0][1:])
    elif pers[0][0] == 'S':
        # needs MSS set
        mss = [x for x in options if x[0] == 'MSS']
        if not mss:
            raise Scapy_Exception("TCP window value requires MSS, and MSS option not set")  # noqa: E501
        pkt.payload.window = mss[0][1] * int(pers[0][1:])
    else:
        raise Scapy_Exception('Unhandled window size specification')

    # ttl
    pkt.ttl = pers[1] - extrahops
    # DF flag
    pkt.flags |= (2 * pers[2])
    # FIXME: ss (packet size) not handled (how ? may be with D quirk
    # if present)
    # Quirks
    if pers[5] != '.':
        for qq in pers[5]:
            # FIXME: not handled: P, I, X, !
            # T handled with the Timestamp option
            if qq == 'Z':
                pkt.id = 0
            elif qq == 'U':
                pkt.payload.urgptr = RandShort()
            elif qq == 'A':
                pkt.payload.ack = RandInt()
            elif qq == 'F':
                if db == p0fo_kdb:
                    pkt.payload.flags |= 0x20  # U
                else:
                    pkt.payload.flags |= random.choice([8, 32, 40])  # P/U/PU
            elif qq == 'D' and db != p0fo_kdb:
                pkt /= conf.raw_layer(load=RandString(random.randint(1, 10)))  # XXX p0fo.fp  # noqa: E501
            elif qq == 'Q':
                pkt.payload.seq = pkt.payload.ack
            # elif qq == '0': pkt.payload.seq = 0
        # if db == p0fr_kdb:
        # '0' quirk is actually not only for p0fr.fp (see
        # packet2p0f())
    if '0' in pers[5]:
        pkt.payload.seq = 0
    elif pkt.payload.seq == 0:
        pkt.payload.seq = RandInt()

    while pkt.underlayer:
        pkt = pkt.underlayer
    return pkt
Example #45
0
    def post_dissect(self, data):
        """dissect the IPv6 package compressed into this IPHC packet.

        The packet payload needs to be decompressed and depending on the
        arguments, several conversions should be done.
        """

        # uncompress payload
        packet = IPv6()
        packet.version = IPHC_DEFAULT_VERSION
        packet.tc, packet.fl = self._getTrafficClassAndFlowLabel()
        if not self.nh:
            packet.nh = self._nhField
        # HLIM: Hop Limit
        if self.hlim == 0:
            packet.hlim = self._hopLimit
        elif self.hlim == 0x1:
            packet.hlim = 1
        elif self.hlim == 0x2:
            packet.hlim = 64
        else:
            packet.hlim = 255
        # TODO: Payload length can be inferred from lower layers from either the  # noqa: E501
        # 6LoWPAN Fragmentation header or the IEEE802.15.4 header

        packet.src = self.decompressSourceAddr(packet)
        packet.dst = self.decompressDestinyAddr(packet)

        if self.nh == 1:
            # The Next Header field is compressed and the next header is
            # encoded using LOWPAN_NHC

            packet.nh = 0x11  # UDP
            udp = UDP()
            if self.header_compression and \
               self.header_compression & 0x4 == 0x0:
                udp.chksum = self.udpChecksum

            s, d = nhc_port(self)
            if s == 16:
                udp.sport = self.udpSourcePort
            elif s == 8:
                udp.sport = 0xF000 + s
            elif s == 4:
                udp.sport = 0xF0B0 + s
            if d == 16:
                udp.dport = self.udpDestinyPort
            elif d == 8:
                udp.dport = 0xF000 + d
            elif d == 4:
                udp.dport = 0xF0B0 + d

            packet.payload = udp / data
            data = raw(packet)
        # else self.nh == 0 not necessary
        elif self._nhField & 0xE0 == 0xE0:  # IPv6 Extension Header Decompression  # noqa: E501
            warning('Unimplemented: IPv6 Extension Header decompression')  # noqa: E501
            packet.payload = conf.raw_layer(data)
            data = raw(packet)
        else:
            packet.payload = conf.raw_layer(data)
            data = raw(packet)

        return Packet.post_dissect(self, data)
Example #46
0
def p0f_impersonate(pkt, osgenre=None, osdetails=None, signature=None,
                    extrahops=0, mtu=1500, uptime=None):
    """Modifies pkt so that p0f will think it has been sent by a
specific OS.  If osdetails is None, then we randomly pick up a
personality matching osgenre. If osgenre and signature are also None,
we use a local signature (using p0f_getlocalsigs). If signature is
specified (as a tuple), we use the signature.

For now, only TCP Syn packets are supported.
Some specifications of the p0f.fp file are not (yet) implemented."""
    pkt = pkt.copy()
    #pkt = pkt.__class__(str(pkt))
    while pkt.haslayer(IP) and pkt.haslayer(TCP):
        pkt = pkt.getlayer(IP)
        if isinstance(pkt.payload, TCP):
            break
        pkt = pkt.payload
    
    if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP):
        raise TypeError("Not a TCP/IP packet")
    
    if uptime is None:
        uptime = random.randint(120,100*60*60*24*365)
    
    db = p0f_selectdb(pkt.payload.flags)
    if osgenre:
        pb = db.get_base()
        if pb is None:
            pb = []
        #pb = filter(lambda x: x[6] == osgenre, pb)
        pb = [ x for x in pb if x[6] == osgenre ]
        if osdetails:
            #pb = filter(lambda x: x[7] == osdetails, pb)
            pb = [ x for x in pb if x[7] == osdetails ]
    elif signature:
        pb = [signature]
    else:
        pb = p0f_getlocalsigs()[db]
    if db == p0fr_kdb:
        # 'K' quirk <=> RST+ACK
        if pkt.payload.flags & 0x4 == 0x4:
            #pb = filter(lambda x: 'K' in x[5], pb)
            pb = [ x for x in pb if 'K' in x[5] ]
        else:
            #pb = filter(lambda x: 'K' not in x[5], pb)
            pb = [ x for x in pb if 'K' not in x[5] ]
    if not pb:
        raise Scapy_Exception("No match in the p0f database")
    pers = pb[random.randint(0, len(pb) - 1)]
    
    # options (we start with options because of MSS)
    ## TODO: let the options already set if they are valid
    options = []
    if pers[4] != '.':
        for opt in pers[4].split(','):
            if opt[0] == 'M':
                # MSS might have a maximum size because of window size
                # specification
                if pers[0][0] == 'S':
                    maxmss = (2**16-1) / int(pers[0][1:])
                else:
                    maxmss = (2**16-1)
                # If we have to randomly pick up a value, we cannot use
                # scapy RandXXX() functions, because the value has to be
                # set in case we need it for the window size value. That's
                # why we use random.randint()
                if opt[1:] == '*':
                    options.append(('MSS', random.randint(1,maxmss)))
                elif opt[1] == '%':
                    coef = int(opt[2:])
                    options.append(('MSS', coef*random.randint(1,maxmss/coef)))
                else:
                    options.append(('MSS', int(opt[1:])))
            elif opt[0] == 'W':
                if opt[1:] == '*':
                    options.append(('WScale', RandByte()))
                elif opt[1] == '%':
                    coef = int(opt[2:])
                    options.append(('WScale', coef*RandNum(min=1,
                                                           max=(2**8-1)/coef)))
                else:
                    options.append(('WScale', int(opt[1:])))
            elif opt == 'T0':
                options.append(('Timestamp', (0, 0)))
            elif opt == 'T':
                if 'T' in pers[5]:
                    # FIXME: RandInt() here does not work (bug (?) in
                    # TCPOptionsField.m2i often raises "OverflowError:
                    # long int too large to convert to int" in:
                    #    oval = struct.pack(ofmt, *oval)"
                    # Actually, this is enough to often raise the error:
                    #    struct.pack('I', RandInt())
                    options.append(('Timestamp', (uptime, random.randint(1,2**32-1))))
                else:
                    options.append(('Timestamp', (uptime, 0)))
            elif opt == 'S':
                options.append(('SAckOK', ''))
            elif opt == 'N':
                options.append(('NOP', None))
            elif opt == 'E':
                options.append(('EOL', None))
            elif opt[0] == '?':
                if int(opt[1:]) in TCPOptions[0]:
                    optname = TCPOptions[0][int(opt[1:])][0]
                    optstruct = TCPOptions[0][int(opt[1:])][1]
                    options.append((optname,
                                    struct.unpack(optstruct,
                                                  RandString(struct.calcsize(optstruct))._fix())))
                else:
                    options.append((int(opt[1:]), ''))
            ## FIXME: qqP not handled
            else:
                warning("unhandled TCP option " + opt)
            pkt.payload.options = options
    
    # window size
    if pers[0] == '*':
        pkt.payload.window = RandShort()
    elif pers[0].isdigit():
        pkt.payload.window = int(pers[0])
    elif pers[0][0] == '%':
        coef = int(pers[0][1:])
        pkt.payload.window = coef * RandNum(min=1,max=(2**16-1)/coef)
    elif pers[0][0] == 'T':
        pkt.payload.window = mtu * int(pers[0][1:])
    elif pers[0][0] == 'S':
        ## needs MSS set
        #MSS = filter(lambda x: x[0] == 'MSS', options)
        MSS = [ x for x in options if x[0] == 'MSS' ]
        if not MSS:
            raise Scapy_Exception("TCP window value requires MSS, and MSS option not set")
        pkt.payload.window = MSS[0][1] * int(pers[0][1:])
    else:
        raise Scapy_Exception('Unhandled window size specification')
    
    # ttl
    pkt.ttl = pers[1]-extrahops
    # DF flag
    pkt.flags |= (2 * pers[2])
    ## FIXME: ss (packet size) not handled (how ? may be with D quirk
    ## if present)
    # Quirks
    if pers[5] != '.':
        for qq in pers[5]:
            ## FIXME: not handled: P, I, X, !
            # T handled with the Timestamp option
            if qq == 'Z': pkt.id = 0
            elif qq == 'U': pkt.payload.urgptr = RandShort()
            elif qq == 'A': pkt.payload.ack = RandInt()
            elif qq == 'F':
                #if db == p0fo_kdb:
                #    pkt.payload.flags |= 0x20 # U
                #else:
                    pkt.payload.flags |= RandChoice(8, 32, 40) #P / U / PU
            elif qq == 'D' and db != p0fo_kdb:
                pkt /= conf.raw_layer(load=RandString(random.randint(1, 10))) # XXX p0fo.fp
            elif qq == 'Q': pkt.payload.seq = pkt.payload.ack
            #elif qq == '0': pkt.payload.seq = 0
        #if db == p0fr_kdb:
        # '0' quirk is actually not only for p0fr.fp (see
        # packet2p0f())
    if '0' in pers[5]:
        pkt.payload.seq = 0
    elif pkt.payload.seq == 0:
        pkt.payload.seq = RandInt()
    
    while pkt.underlayer:
        pkt = pkt.underlayer
    return pkt
Example #47
0
def __gen_send(s,  # type: SuperSocket
               x,  # type: _PacketIterable
               inter=0,  # type: int
               loop=0,  # type: int
               count=None,  # type: Optional[int]
               verbose=None,  # type: Optional[int]
               realtime=False,  # type: bool
               return_packets=False,  # type: bool
               *args,  # type: Any
               **kargs  # type: Any
               ):
    # type: (...) -> Optional[PacketList]
    """
    An internal function used by send/sendp to actually send the packets,
    implement the send logic...

    It will take care of iterating through the different packets
    """
    if isinstance(x, str):
        x = conf.raw_layer(load=x)
    if not isinstance(x, Gen):
        x = SetGen(x)
    if verbose is None:
        verbose = conf.verb
    n = 0
    if count is not None:
        loop = -count
    elif not loop:
        loop = -1
    sent_packets = PacketList() if return_packets else None
    p = None
    try:
        while loop:
            dt0 = None
            for p in x:
                if realtime:
                    ct = time.time()
                    if dt0:
                        st = dt0 + float(p.time) - ct
                        if st > 0:
                            time.sleep(st)
                    else:
                        dt0 = ct - float(p.time)
                s.send(p)
                if sent_packets is not None:
                    sent_packets.append(p)
                n += 1
                if verbose:
                    os.write(1, b".")
                time.sleep(inter)
            if loop < 0:
                loop += 1
    except KeyboardInterrupt:
        pass
    finally:
        try:
            cast(Packet, x).sent_time = cast(Packet, p).sent_time
        except AttributeError:
            pass
    if verbose:
        print("\nSent %i packets." % n)
    return sent_packets
 def recv(self, x=MTU):
     return conf.raw_layer(self.ins.recv(x))
Example #49
0
    def post_dissect(self, data):
        """dissect the IPv6 package compressed into this IPHC packet.

        The packet payload needs to be decompressed and depending on the
        arguments, several conversions should be done.
        """

        # uncompress payload
        packet = IPv6()
        packet.version = IPHC_DEFAULT_VERSION
        packet.tc, packet.fl = self._getTrafficClassAndFlowLabel()
        if not self.nh:
            packet.nh = self._nhField
        # HLIM: Hop Limit
        if self.hlim == 0:
            packet.hlim = self._hopLimit
        elif self.hlim == 0x1:
            packet.hlim = 1
        elif self.hlim == 0x2:
            packet.hlim = 64
        else:
            packet.hlim = 255
        # TODO: Payload length can be inferred from lower layers from either the  # noqa: E501
        # 6LoWPAN Fragmentation header or the IEEE802.15.4 header

        packet.src = self.decompressSourceAddr(packet)
        packet.dst = self.decompressDestinyAddr(packet)

        if self.nh == 1:
            # The Next Header field is compressed and the next header is
            # encoded using LOWPAN_NHC

            udp = UDP()
            if self.header_compression and \
               self.header_compression & 0x4 == 0x0:
                udp.chksum = self.udpChecksum

            s, d = nhc_port(self)
            if s == 16:
                udp.sport = self.udpSourcePort
            elif s == 8:
                udp.sport = 0xF000 + s
            elif s == 4:
                udp.sport = 0xF0B0 + s
            if d == 16:
                udp.dport = self.udpDestinyPort
            elif d == 8:
                udp.dport = 0xF000 + d
            elif d == 4:
                udp.dport = 0xF0B0 + d

            packet.payload = udp / data
            data = raw(packet)
        # else self.nh == 0 not necessary
        elif self._nhField & 0xE0 == 0xE0:  # IPv6 Extension Header Decompression  # noqa: E501
            warning('Unimplemented: IPv6 Extension Header decompression')  # noqa: E501
            packet.payload = conf.raw_layer(data)
            data = raw(packet)
        else:
            packet.payload = conf.raw_layer(data)
            data = raw(packet)

        return Packet.post_dissect(self, data)
Example #50
0
def p0f_impersonate(pkt,
                    osgenre=None,
                    osdetails=None,
                    signature=None,
                    extrahops=0,
                    mtu=1500,
                    uptime=None):
    """Modifies pkt so that p0f will think it has been sent by a
    specific OS. Either osgenre or signature is required to impersonate.
    If signature is specified (as a raw string), we use the signature.
    signature format:
        "ip_ver:ttl:ip_opt_len:mss:window,wscale:opt_layout:quirks:pay_class"

    If osgenre is specified, we randomly pick a signature with a label
    that matches osgenre (and osdetails, if specified).
    Note: osgenre is case sensitive ("linux" -> "Linux" etc.), and osdetails
    is a substring of a label flavor ("7", "8" and "7 or 8" will
    all match the label "s:win:Windows:7 or 8")

    For now, only TCP SYN/SYN+ACK packets are supported."""
    pkt = validate_packet(pkt)

    if not osgenre and not signature:
        raise ValueError("osgenre or signature is required to impersonate!")

    tcp = pkt[TCP]
    tcp_type = tcp.flags & (0x02 | 0x10)  # SYN / SYN+ACK

    if signature:
        if isinstance(signature, string_types):
            sig, _ = TCP_Signature.from_raw_sig(signature)
        else:
            raise TypeError("Unsupported signature type")
    else:
        if not p0fdb.get_base():
            sigs = []
        else:
            direction = "request" if tcp_type == 0x02 else "response"
            sigs = p0fdb.get_sigs_by_os(direction, osgenre, osdetails)

        # If IPv6 packet, remove IPv4-only signatures and vice versa
        sigs = [s for s in sigs if s.ip_ver == -1 or s.ip_ver == pkt.version]
        if not sigs:
            raise ValueError("No match in the p0f database")
        sig = random.choice(sigs)

    if sig.ip_ver != -1 and pkt.version != sig.ip_ver:
        raise ValueError("Can't convert between IPv4 and IPv6")

    quirks = sig.quirks

    if pkt.version == 4:
        pkt.ttl = sig.ttl - extrahops
        if sig.ip_opt_len != 0:
            # FIXME: Non-zero IPv4 options not handled
            warning("Unhandled IPv4 option field")
        else:
            pkt.options = []

        if "df" in quirks:
            pkt.flags |= 0x02  # set DF flag
            if "id+" in quirks:
                if pkt.id == 0:
                    pkt.id = random.randint(1, 2**16 - 1)
            else:
                pkt.id = 0
        else:
            pkt.flags &= ~(0x02)  # DF flag not set
            if "id-" in quirks:
                pkt.id = 0
            elif pkt.id == 0:
                pkt.id = random.randint(1, 2**16 - 1)
        if "ecn" in quirks:
            pkt.tos |= random.randint(0x01, 0x03)
        pkt.flags = pkt.flags | 0x04 if "0+" in quirks else pkt.flags & ~(0x04)
    else:
        pkt.hlim = sig.ttl - extrahops
        if "flow" in quirks:
            pkt.fl = random.randint(1, 2**20 - 1)
        if "ecn" in quirks:
            pkt.tc |= random.randint(0x01, 0x03)

    # Take the options already set as "hints" to use in the new packet if we
    # can. we'll use the already-set values if they're valid integers.
    def int_only(val):
        return val if isinstance(val, integer_types) else None

    orig_opts = dict(tcp.options)
    mss_hint = int_only(orig_opts.get("MSS"))
    ws_hint = int_only(orig_opts.get("WScale"))
    ts_hint = [int_only(o) for o in orig_opts.get("Timestamp", (None, None))]

    options = []
    for opt in sig.olayout.split(","):
        if opt == "mss":
            # MSS might have a maximum size because of WIN_TYPE_MSS
            if sig.win_type == WIN_TYPE_MSS:
                maxmss = (2**16 - 1) // sig.win
            else:
                maxmss = (2**16 - 1)

            if sig.mss == -1:  # wildcard mss
                if mss_hint and 0 <= mss_hint <= maxmss:
                    options.append(("MSS", mss_hint))
                else:  # invalid hint, generate new value
                    options.append(("MSS", random.randint(100, maxmss)))
            else:
                options.append(("MSS", sig.mss))

        elif opt == "ws":
            if sig.wscale == -1:  # wildcard wscale
                maxws = 2**8
                if "exws" in quirks:  # wscale > 14
                    if ws_hint and 14 < ws_hint < maxws:
                        options.append(("WScale", ws_hint))
                    else:  # invalid hint, generate new value > 14
                        options.append(
                            ("WScale",
                             random.randint(15, maxws - 1)))  # noqa: E501
                else:
                    if ws_hint and 0 <= ws_hint < maxws:
                        options.append(("WScale", ws_hint))
                    else:  # invalid hint, generate new value
                        options.append(("WScale", RandByte()))
            else:
                options.append(("WScale", sig.wscale))

        elif opt == "ts":
            ts1, ts2 = ts_hint

            if "ts1-" in quirks:  # own timestamp specified as zero
                ts1 = 0
            elif uptime is not None:  # if specified uptime, override
                ts1 = uptime
            elif ts1 is None or not (0 < ts1 < 2**32):  # invalid hint
                ts1 = random.randint(120, 100 * 60 * 60 * 24 * 365)

            # non-zero peer timestamp on initial SYN
            if "ts2+" in quirks and tcp_type == 0x02:
                if ts2 is None or not (0 < ts2 < 2**32):  # invalid hint
                    ts2 = random.randint(1, 2**32 - 1)
            else:
                ts2 = 0
            options.append(("Timestamp", (ts1, ts2)))

        elif opt == "nop":
            options.append(("NOP", None))
        elif opt == "sok":
            options.append(("SAckOK", ""))
        elif opt[:3] == "eol":
            options.append(("EOL", None))
            # FIXME: opt+ quirk not handled
            if "opt+" in quirks:
                warning("Unhandled opt+ quirk")
        elif opt == "sack":
            # Randomize SAck value in range of 10 <= val <= 34
            sack_len = random.choice([10, 18, 26, 34]) - 2
            optstruct = "!%iI" % (sack_len // 4)
            rand_val = RandString(struct.calcsize(optstruct))._fix()
            options.append(("SAck", struct.unpack(optstruct, rand_val)))
        else:
            warning("Unhandled TCP option %s", opt)
        tcp.options = options

    if sig.win_type == WIN_TYPE_NORMAL:
        tcp.window = sig.win
    elif sig.win_type == WIN_TYPE_MSS:
        mss = [x for x in options if x[0] == "MSS"]
        if not mss:
            raise ValueError(
                "TCP window value requires MSS, and MSS option not set"
            )  # noqa: E501
        tcp.window = mss[0][1] * sig.win
    elif sig.win_type == WIN_TYPE_MOD:
        tcp.window = sig.win * random.randint(1, (2**16 - 1) // sig.win)
    elif sig.win_type == WIN_TYPE_MTU:
        tcp.window = mtu * sig.win
    elif sig.win_type == WIN_TYPE_ANY:
        tcp.window = RandShort()
    else:
        warning("Unhandled window size specification")

    if "seq-" in quirks:
        tcp.seq = 0
    elif tcp.seq == 0:
        tcp.seq = random.randint(1, 2**32 - 1)

    if "ack+" in quirks:
        tcp.flags &= ~(0x10)  # ACK flag not set
        if tcp.ack == 0:
            tcp.ack = random.randint(1, 2**32 - 1)
    elif "ack-" in quirks:
        tcp.flags |= 0x10  # ACK flag set
        tcp.ack = 0

    if "uptr+" in quirks:
        tcp.flags &= ~(0x020)  # URG flag not set
        if tcp.urgptr == 0:
            tcp.urgptr = random.randint(1, 2**16 - 1)
    elif "urgf+" in quirks:
        tcp.flags |= 0x020  # URG flag used

    tcp.flags = tcp.flags | 0x08 if "pushf+" in quirks else tcp.flags & ~(0x08)

    if sig.pay_class:  # signature has payload
        if not tcp.payload:
            pkt /= conf.raw_layer(load=RandString(random.randint(1, 10)))
    else:
        tcp.payload = NoPayload()

    return pkt
Example #51
0
def p0f_impersonate(pkt, osgenre=None, osdetails=None, signature=None,
                    extrahops=0, mtu=1500, uptime=None):
    """Modifies pkt so that p0f will think it has been sent by a
specific OS.  If osdetails is None, then we randomly pick up a
personality matching osgenre. If osgenre and signature are also None,
we use a local signature (using p0f_getlocalsigs). If signature is
specified (as a tuple), we use the signature.

For now, only TCP Syn packets are supported.
Some specifications of the p0f.fp file are not (yet) implemented."""
    pkt = pkt.copy()
    #pkt = pkt.__class__(raw(pkt))
    while pkt.haslayer(IP) and pkt.haslayer(TCP):
        pkt = pkt.getlayer(IP)
        if isinstance(pkt.payload, TCP):
            break
        pkt = pkt.payload
    
    if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP):
        raise TypeError("Not a TCP/IP packet")

    db = p0f_selectdb(pkt.payload.flags)
    if osgenre:
        pb = db.get_base()
        if pb is None:
            pb = []
        pb = [x for x in pb if x[6] == osgenre]
        if osdetails:
            pb = [x for x in pb if x[7] == osdetails]
    elif signature:
        pb = [signature]
    else:
        pb = p0f_getlocalsigs()[db]
    if db == p0fr_kdb:
        # 'K' quirk <=> RST+ACK
        if pkt.payload.flags & 0x4 == 0x4:
            pb = [x for x in pb if 'K' in x[5]]
        else:
            pb = [x for x in pb if 'K' not in x[5]]
    if not pb:
        raise Scapy_Exception("No match in the p0f database")
    pers = pb[random.randint(0, len(pb) - 1)]
    
    # options (we start with options because of MSS)
    # Take the options already set as "hints" to use in the new packet if we
    # can. MSS, WScale and Timestamp can all be wildcarded in a signature, so
    # we'll use the already-set values if they're valid integers.
    orig_opts = dict(pkt.payload.options)
    int_only = lambda val: val if isinstance(val, six.integer_types) else None
    mss_hint = int_only(orig_opts.get('MSS'))
    wscale_hint = int_only(orig_opts.get('WScale'))
    ts_hint = [int_only(o) for o in orig_opts.get('Timestamp', (None, None))]

    options = []
    if pers[4] != '.':
        for opt in pers[4].split(','):
            if opt[0] == 'M':
                # MSS might have a maximum size because of window size
                # specification
                if pers[0][0] == 'S':
                    maxmss = (2**16-1) // int(pers[0][1:])
                else:
                    maxmss = (2**16-1)
                # disregard hint if out of range
                if mss_hint and not 0 <= mss_hint <= maxmss:
                    mss_hint = None
                # If we have to randomly pick up a value, we cannot use
                # scapy RandXXX() functions, because the value has to be
                # set in case we need it for the window size value. That's
                # why we use random.randint()
                if opt[1:] == '*':
                    if mss_hint is not None:
                        options.append(('MSS', mss_hint))
                    else:
                        options.append(('MSS', random.randint(1, maxmss)))
                elif opt[1] == '%':
                    coef = int(opt[2:])
                    if mss_hint is not None and mss_hint % coef == 0:
                        options.append(('MSS', mss_hint))
                    else:
                        options.append((
                            'MSS', coef*random.randint(1, maxmss//coef)))
                else:
                    options.append(('MSS', int(opt[1:])))
            elif opt[0] == 'W':
                if wscale_hint and not 0 <= wscale_hint < 2**8:
                    wscale_hint = None
                if opt[1:] == '*':
                    if wscale_hint is not None:
                        options.append(('WScale', wscale_hint))
                    else:
                        options.append(('WScale', RandByte()))
                elif opt[1] == '%':
                    coef = int(opt[2:])
                    if wscale_hint is not None and wscale_hint % coef == 0:
                        options.append(('WScale', wscale_hint))
                    else:
                        options.append((
                            'WScale', coef*RandNum(min=1, max=(2**8-1)//coef)))
                else:
                    options.append(('WScale', int(opt[1:])))
            elif opt == 'T0':
                options.append(('Timestamp', (0, 0)))
            elif opt == 'T':
                # Determine first timestamp.
                if uptime is not None:
                    ts_a = uptime
                elif ts_hint[0] and 0 < ts_hint[0] < 2**32:
                    # Note: if first ts is 0, p0f registers it as "T0" not "T",
                    # hence we don't want to use the hint if it was 0.
                    ts_a = ts_hint[0]
                else:
                    ts_a = random.randint(120, 100*60*60*24*365)
                # Determine second timestamp.
                if 'T' not in pers[5]:
                    ts_b = 0
                elif ts_hint[1] and 0 < ts_hint[1] < 2**32:
                    ts_b = ts_hint[1]
                else:
                    # FIXME: RandInt() here does not work (bug (?) in
                    # TCPOptionsField.m2i often raises "OverflowError:
                    # long int too large to convert to int" in:
                    #    oval = struct.pack(ofmt, *oval)"
                    # Actually, this is enough to often raise the error:
                    #    struct.pack('I', RandInt())
                    ts_b = random.randint(1, 2**32-1)
                options.append(('Timestamp', (ts_a, ts_b)))
            elif opt == 'S':
                options.append(('SAckOK', ''))
            elif opt == 'N':
                options.append(('NOP', None))
            elif opt == 'E':
                options.append(('EOL', None))
            elif opt[0] == '?':
                if int(opt[1:]) in TCPOptions[0]:
                    optname = TCPOptions[0][int(opt[1:])][0]
                    optstruct = TCPOptions[0][int(opt[1:])][1]
                    options.append((optname,
                                    struct.unpack(optstruct,
                                                  RandString(struct.calcsize(optstruct))._fix())))
                else:
                    options.append((int(opt[1:]), ''))
            ## FIXME: qqP not handled
            else:
                warning("unhandled TCP option " + opt)
            pkt.payload.options = options
    
    # window size
    if pers[0] == '*':
        pkt.payload.window = RandShort()
    elif pers[0].isdigit():
        pkt.payload.window = int(pers[0])
    elif pers[0][0] == '%':
        coef = int(pers[0][1:])
        pkt.payload.window = coef * RandNum(min=1, max=(2**16-1)//coef)
    elif pers[0][0] == 'T':
        pkt.payload.window = mtu * int(pers[0][1:])
    elif pers[0][0] == 'S':
        ## needs MSS set
        mss = [x for x in options if x[0] == 'MSS']
        if not mss:
            raise Scapy_Exception("TCP window value requires MSS, and MSS option not set")
        pkt.payload.window = mss[0][1] * int(pers[0][1:])
    else:
        raise Scapy_Exception('Unhandled window size specification')
    
    # ttl
    pkt.ttl = pers[1]-extrahops
    # DF flag
    pkt.flags |= (2 * pers[2])
    ## FIXME: ss (packet size) not handled (how ? may be with D quirk
    ## if present)
    # Quirks
    if pers[5] != '.':
        for qq in pers[5]:
            ## FIXME: not handled: P, I, X, !
            # T handled with the Timestamp option
            if qq == 'Z': pkt.id = 0
            elif qq == 'U': pkt.payload.urgptr = RandShort()
            elif qq == 'A': pkt.payload.ack = RandInt()
            elif qq == 'F':
                if db == p0fo_kdb:
                    pkt.payload.flags |= 0x20 # U
                else:
                    pkt.payload.flags |= random.choice([8, 32, 40])  # P/U/PU
            elif qq == 'D' and db != p0fo_kdb:
                pkt /= conf.raw_layer(load=RandString(random.randint(1, 10))) # XXX p0fo.fp
            elif qq == 'Q': pkt.payload.seq = pkt.payload.ack
            #elif qq == '0': pkt.payload.seq = 0
        #if db == p0fr_kdb:
        # '0' quirk is actually not only for p0fr.fp (see
        # packet2p0f())
    if '0' in pers[5]:
        pkt.payload.seq = 0
    elif pkt.payload.seq == 0:
        pkt.payload.seq = RandInt()
    
    while pkt.underlayer:
        pkt = pkt.underlayer
    return pkt
Example #52
0
 def recv(self, x=MTU):
     return conf.raw_layer(self.ins.recv(x))
Example #53
0
 def __rdiv__(self, other):
     if type(other) is str:
         return conf.raw_layer(load=other)/self
     else:
         raise TypeError