Exemple #1
0
 def __init__(self, res=None, name="Traceroute", stats=None):
     PacketList.__init__(self, res, name, stats)
     self.graphdef = None
     self.graphASres = 0
     self.padding = 0
     self.hloc = None
     self.nloc = None
Exemple #2
0
    def _update_supported_responses(self, pkt):
        self._unanswered_packets += PacketList([pkt])
        answered, unanswered = self._unanswered_packets.sr()
        for _, resp in answered:
            ecu_resp = ECUResponse(session=self.current_session,
                                   security_level=self.current_security_level,
                                   responses=resp)

            if ecu_resp not in self._supported_responses:
                if self.verbose:
                    print("[+] ", repr(ecu_resp))
                self._supported_responses.append(ecu_resp)
            else:
                if self.verbose:
                    print("[-] ", repr(ecu_resp))
        self._unanswered_packets = unanswered
Exemple #3
0
    def read_all(self, count=-1):
        # type: (int) -> PacketList
        """Read a specific number or all packets from a candump file.

        :param count: Specify a specific number of packets to be read.
                      All packets can be read by count=-1.
        :return: A PacketList object containing read CAN messages
        """
        res = []
        while count != 0:
            try:
                p = self.read_packet()
                if p is None:
                    continue
            except EOFError:
                break
            count -= 1
            res.append(p)
        return PacketList(res, name=os.path.basename(self.filename))
Exemple #4
0
def defragment(plist):
    """defrag(plist) -> plist defragmented as much as possible """
    frags = {}
    final = []

    pos = 0
    for p in plist:
        p._defrag_pos = pos
        pos += 1
        if IP in p:
            ip = p[IP]
            if ip.frag != 0 or ip.flags & 1:
                ip = p[IP]
                uniq = (ip.id,ip.src,ip.dst,ip.proto)
                if uniq in frags:
                    frags[uniq].append(p)
                else:
                    frags[uniq] = [p]
                continue
        final.append(p)

    defrag = []
    missfrag = []
    for lst in frags.itervalues():
        lst.sort(lambda x,y:cmp(x.frag, y.frag))
        p = lst[0]
        if p.frag > 0:
            missfrag += lst
            continue
        p = p.copy()
        if Padding in p:
            del(p[Padding].underlayer.payload)
        ip = p[IP]
        if ip.len is None or ip.ihl is None:
            clen = len(ip.payload)
        else:
            clen = ip.len - (ip.ihl<<2)
        txt = Raw()
        for q in lst[1:]:
            if clen != q.frag<<3:
                if clen > q.frag<<3:
                    warning("Fragment overlap (%i > %i) %r || %r ||  %r" % (clen, q.frag<<3, p,txt,q))
                missfrag += lst
                txt = None
                break
            if q[IP].len is None or q[IP].ihl is None:
                clen += len(q[IP].payload)
            else:
                clen += q[IP].len - (q[IP].ihl<<2)
            if Padding in q:
                del(q[Padding].underlayer.payload)
            txt.add_payload(q[IP].payload.copy())
            
        if txt is None:
            continue

        ip.flags &= ~1 # !MF
        del(ip.chksum)
        del(ip.len)
        p = p/txt
        p._defrag_pos = lst[-1]._defrag_pos
        defrag.append(p)
    defrag2=[]
    for p in defrag:
        q = p.__class__(str(p))
        q._defrag_pos = p._defrag_pos
        defrag2.append(q)
    final += defrag2
    final += missfrag
    final.sort(lambda x,y: cmp(x._defrag_pos, y._defrag_pos))
    for p in final:
        del(p._defrag_pos)

    if hasattr(plist, "listname"):
        name = "Defragmented %s" % plist.listname
    else:
        name = "Defragmented"
        
    
    return PacketList(final, name=name)
Exemple #5
0
    def processTcpPacket(dumb,queue,print_counter,counter_val):
	logging.warning("In function : processTcpPacket")
	counter_create_issue= 0
	lst=[]
	i=0
	while 1:
		counter_create_issue = counter_create_issue + 1
		#try:
		if True:
		    if (queue.qsize != 0 ):
			lst.append(queue.get())
			Packet=PacketList(lst,"Sniffed")
			pkt_type=get_packet_type(Packet[i])
			#print " My packet type is "
			#print pkt_type 	
			if (pkt_type==SYNACK_NO):
				send_ack_packet(Packet[i])
				send_bgp_open( Packet[i] )
			elif (pkt_type==SYN_NO):
				#dumbi=0
				send_syn_ack_packet(Packet[i])
			elif (pkt_type==ACK_NO):
				dumbi = 0
			elif (pkt_type==FIN):
				send_tcp_fin_set(Packet[i])
			elif (pkt_type==CONT_FIN):
				send_tcp_fin_set(Packet[i])
			elif (pkt_type==CONT_FIN_ACK):
				dumbi = 0
				send_tcp_fin_set(Packet[i])
			elif (pkt_type==CONT_PSH_ACK):
				send_ack_packet(Packet[i])
			else :
				logging.warning("Received Packet with Flag set : " + str(pkt_type))

			bgp_pkt_type=get_bgp_packet_type(Packet[i])

			if (bgp_pkt_type==BGP_OPEN):
				logging.warning("Got a Bgp open")
				if host_info.has_key(Packet[i][IP].dst) == True:
					if host_info[Packet[i][IP].dst]['state'] == 0:  # REMOVE COMMENT HERE
						send_bgp_open(Packet[i])
			elif (bgp_pkt_type==BGP_KEEPALIVE):
				dumbi = 0
				send_bgp_keepalive(Packet[i])
				if True:
					Packet[i].seq=Packet[i].seq
					Packet[i].ack=int(Packet[i].ack)+19
					send_bgp_update(Packet[i])
					if counter_create_issue / 100 > 0:
						counter_create_issue= 0
						send_bgp_open(Packet[i])
			elif (bgp_pkt_type==BGP_UPDATE):
				dumbi=0
				print "recv bgp update"
				send_bgp_update(Packet[i])
				#recv_bgp_update(Packet[i])
			elif (bgp_pkt_type==BGP_NOTIFY):
				dumbi=0
				print "recv notify"
				send_tcp_syn_pkts(1,int(Packet[i].dport)+2,BURST_TIMER)
				#recv_bgp_notify(Packet[i])
			elif (bgp_pkt_type==None):
				dumbi = 0
			else :
				logging.warning("Received Packet with Flag set : " + str(bgp_pkt_type))
			lst.pop()
Exemple #6
0
def __sr_loop(srfunc,  # type: Callable[..., Tuple[SndRcvList, PacketList]]
              pkts,  # type: _PacketIterable
              prn=lambda x: x[1].summary(),  # type: Callable[[QueryAnswer], Any]  # noqa: E501
              prnfail=lambda x: x.summary(),  # type: Callable[[Packet], Any]
              inter=1,  # type: int
              timeout=None,  # type: Optional[int]
              count=None,  # type: Optional[int]
              verbose=None,  # type: Optional[int]
              store=1,  # type: int
              *args,  # type: Any
              **kargs  # type: Any
              ):
    # type: (...) -> Tuple[SndRcvList, PacketList]
    n = 0
    r = 0
    ct = conf.color_theme
    if verbose is None:
        verbose = conf.verb
    parity = 0
    ans = []  # type: List[QueryAnswer]
    unans = []  # type: List[Packet]
    if timeout is None:
        timeout = min(2 * inter, 5)
    try:
        while True:
            parity ^= 1
            col = [ct.even, ct.odd][parity]
            if count is not None:
                if count == 0:
                    break
                count -= 1
            start = time.time()
            if verbose > 1:
                print("\rsend...\r", end=' ')
            res = srfunc(pkts, timeout=timeout, verbose=0, chainCC=True, *args, **kargs)  # noqa: E501
            n += len(res[0]) + len(res[1])
            r += len(res[0])
            if verbose > 1 and prn and len(res[0]) > 0:
                msg = "RECV %i:" % len(res[0])
                print("\r" + ct.success(msg), end=' ')
                for p in res[0]:
                    print(col(prn(p)))
                    print(" " * len(msg), end=' ')
            if verbose > 1 and prnfail and len(res[1]) > 0:
                msg = "fail %i:" % len(res[1])
                print("\r" + ct.fail(msg), end=' ')
                for p in res[1]:
                    print(col(prnfail(p)))
                    print(" " * len(msg), end=' ')
            if verbose > 1 and not (prn or prnfail):
                print("recv:%i  fail:%i" % tuple(map(len, res[:2])))
            if store:
                ans += res[0]
                unans += res[1]
            end = time.time()
            if end - start < inter:
                time.sleep(inter + start - end)
    except KeyboardInterrupt:
        pass

    if verbose and n > 0:
        print(ct.normal("\nSent %i packets, received %i packets. %3.1f%% hits." % (n, r, 100.0 * r / n)))  # noqa: E501
    return SndRcvList(ans), PacketList(unans)
    def __init__(self, res=None, name="Dot11List", stats=None):
        if stats is None:
            stats = conf.stats_dot11_protocols

        PacketList.__init__(self, res, name, stats)
Exemple #8
0
 def get_threading_plist():
     temp = Vault.__threading_packet_list
     Vault.__threading_packet_list = PacketList()
     return temp
Exemple #9
0
    def __init__(self,
                 pks,  # type: SuperSocket
                 pkt,  # type: _PacketIterable
                 timeout=None,  # type: Optional[int]
                 inter=0,  # type: int
                 verbose=None,  # type: Optional[int]
                 chainCC=False,  # type: bool
                 retry=0,  # type: int
                 multi=False,  # type: bool
                 rcv_pks=None,  # type: Optional[SuperSocket]
                 prebuild=False,  # type: bool
                 _flood=None,  # type: Optional[Tuple[int, Callable[[], None]]]  # noqa: E501
                 threaded=False,  # type: bool
                 session=None  # type: Optional[_GlobSessionType]
                 ):
        # type: (...) -> None
        # Instantiate all arguments
        if verbose is None:
            verbose = conf.verb
        if conf.debug_match:
            debug.recv = PacketList([], "Received")
            debug.sent = PacketList([], "Sent")
            debug.match = SndRcvList([], "Matched")
        self.nbrecv = 0
        self.ans = []  # type: List[QueryAnswer]
        self.pks = pks
        self.rcv_pks = rcv_pks or pks
        self.inter = inter
        self.verbose = verbose
        self.chainCC = chainCC
        self.multi = multi
        self.timeout = timeout
        self.session = session
        # Instantiate packet holders
        if _flood:
            self.tobesent = pkt  # type: Union[_PacketIterable, SetGen[Packet]]
            self.notans = _flood[0]
        else:
            if isinstance(pkt, types.GeneratorType) or prebuild:
                self.tobesent = list(pkt)
                self.notans = len(self.tobesent)
            else:
                self.tobesent = (
                    SetGen(pkt) if not isinstance(pkt, Gen) else pkt
                )
                self.notans = self.tobesent.__iterlen__()

        if retry < 0:
            autostop = retry = -retry
        else:
            autostop = 0

        if timeout is not None and timeout < 0:
            self.timeout = None

        while retry >= 0:
            self.hsent = {}  # type: Dict[bytes, List[Packet]]

            if threaded or _flood:
                # Send packets in thread.
                # https://github.com/secdev/scapy/issues/1791
                snd_thread = Thread(
                    target=self._sndrcv_snd
                )
                snd_thread.setDaemon(True)

                # Start routine with callback
                self._sndrcv_rcv(snd_thread.start)

                # Ended. Let's close gracefully
                if _flood:
                    # Flood: stop send thread
                    _flood[1]()
                snd_thread.join()
            else:
                self._sndrcv_rcv(self._sndrcv_snd)

            if multi:
                remain = [
                    p for p in itertools.chain(*six.itervalues(self.hsent))
                    if not hasattr(p, '_answered')
                ]
            else:
                remain = list(itertools.chain(*six.itervalues(self.hsent)))

            if autostop and len(remain) > 0 and \
               len(remain) != len(self.tobesent):
                retry = autostop

            self.tobesent = remain
            if len(self.tobesent) == 0:
                break
            retry -= 1

        if conf.debug_match:
            debug.sent = PacketList(remain[:], "Sent")
            debug.match = SndRcvList(self.ans[:])

        # Clean the ans list to delete the field _answered
        if multi:
            for snd, _ in self.ans:
                if hasattr(snd, '_answered'):
                    del snd._answered

        if verbose:
            print(
                "\nReceived %i packets, got %i answers, "
                "remaining %i packets" % (
                    self.nbrecv + len(self.ans), len(self.ans), self.notans
                )
            )

        self.ans_result = SndRcvList(self.ans)
        self.unans_result = PacketList(remain, "Unanswered")
Exemple #10
0
def sndrcvflood(pks,
                pkt,
                inter=0,
                verbose=None,
                chainCC=False,
                store_unanswered=True,
                process=None,
                timeout=None):
    if not verbose:
        verbose = conf.verb
    listable = (isinstance(pkt, Packet)
                and pkt.__iterlen__() == 1) or isinstance(pkt,
                                                          list)  # noqa: E501
    tobesent = pkt

    use_prn_mode = False
    _storage_policy = None
    if process is not None:
        use_prn_mode = True
        _storage_policy = lambda x, y: process(x, y)

    stopevent = threading.Event()
    count_packets = six.moves.queue.Queue()
    hsent = {}
    timessent = {} if listable else None

    def send_in_loop(tobesent, stopevent, count_packets=count_packets):
        """Infinite generator that produces the same packet until stopevent is triggered."""  # noqa: E501
        while True:
            for p in tobesent:
                if stopevent.is_set():
                    return
                count_packets.put(0)
                yield p

    infinite_gen = send_in_loop(tobesent, stopevent)

    def _timeout(timeout):
        stopevent.wait(timeout)
        stopevent.set()

    timeout_thread = threading.Thread(target=_timeout, args=(timeout, ))
    timeout_thread.setDaemon(True)
    timeout_thread.start()

    # We don't use _sndrcv_snd verbose (it messes the logs up as in a thread that ends after receiving)  # noqa: E501
    thread = threading.Thread(target=_sndrcv_snd,
                              args=(pks, None, inter, False, infinite_gen,
                                    hsent, timessent, stopevent))
    thread.setDaemon(True)
    thread.start()

    hsent, ans, nbrecv, notans = _sndrcv_rcv(pks,
                                             hsent,
                                             stopevent,
                                             0,
                                             len(tobesent),
                                             verbose,
                                             chainCC,
                                             False,
                                             _storage_policy=_storage_policy)
    thread.join()

    # Restore time_sent to original packets
    if listable:
        i = 0
        for p in (pkt if isinstance(pkt, list) else [pkt]):
            p.sent_time = timessent[i]
            i += 1

    if process is not None:
        ans = [(x, process(y)) for (x, y) in ans]  # Apply process

    if store_unanswered:
        if use_prn_mode:
            remain = [
                process(x, None)
                for x in itertools.chain(*six.itervalues(hsent))
            ]  # noqa: E501
        else:
            remain = list(itertools.chain(*six.itervalues(hsent)))

    if verbose:
        print(
            "\nReceived %i packets, got %i answers, remaining %i packets. Sent a total of %i packets."
            % (nbrecv + len(ans), len(ans), notans,
               count_packets.qsize()))  # noqa: E501
    count_packets.empty()
    del count_packets

    ans_result = ans if use_prn_mode else SndRcvList(ans)
    unans_result = remain if use_prn_mode else (
        None if not store_unanswered else PacketList(remain, "Unanswered")
    )  # noqa: E501
    return ans_result, unans_result
Exemple #11
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
Exemple #12
0
def __gen_send_mod(s,
                   x,
                   inter=0,
                   loop=0,
                   count=None,
                   verbose=None,
                   realtime=None,
                   return_packets=False,
                   port_random_flag=False,
                   size_random_flag=False,
                   src_random_flag=False,
                   specific_subnet_random=False,
                   source_addr='Default',
                   pcktcount=None,
                   log=None,
                   *args,
                   **kargs):  # noqa: E501
    totaltimeelapsedns = 0.0
    totaltimeelapseds = 0.0
    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:
        startVelkoSec = time.time()
        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

                if (p.proto == 1):
                    p.type = int(random.randrange(0, 255))
                    p.code = int(random.randrange(0, 255))
                if (port_random_flag):
                    targ_port = int(random.randrange(0, 65535))
                    p.dport = targ_port
                if (size_random_flag):
                    packet_size = int(
                        random.randrange(0, 6550)
                    )  # 7 I removed 7 because there seems to be some boundary crossing(bleeding)
                    p.add_payload((str(_generatePacket(packet_size))).encode())
                if (src_random_flag):
                    p.src = socket.inet_ntoa(
                        struct.pack('>I', random.randint(1, 0xffffffff)))
                elif (specific_subnet_random):
                    try:
                        subnet = IPv4Network(source_addr)
                        bits = random.getrandbits(subnet.max_prefixlen -
                                                  subnet.prefixlen)
                        p.src = str(IPv4Address(subnet.network_address + bits))

                    except ValueError:
                        print("Something is wrong!sendrcv ")

                if ((n % int(pcktcount)) == 0):

                    endVelkoSec = time.time()
                    totaltimeelapseds += (endVelkoSec - startVelkoSec)

                    print("\n+++TIMESTAMP+++\nTimestamp taken after:", n,
                          "packets")

                    #print('{:%Y-%m-%d_%H:%M:%S}'.format(datetime.datetime.now())+"\n")
                    print((datetime.datetime.now()
                           ).strftime('%Y-%m-%d %H:%M:%S.%f')[:-2] +
                          " (UTC)\n")
                    print("TIME(s): ", (endVelkoSec - startVelkoSec))
                    print("TIME(ns): ",
                          (endVelkoSec - startVelkoSec) * 1000000000)
                    print("TOTAL TIME(s): ", totaltimeelapseds)
                    print(
                        "+++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
                    )


#LOG SECTION
# file_name=log
# f = open(file_name, 'a+')
# f.write("\n+++TIMESTAMP+++\nTimestamp taken after: "+str(n)+"\n")
# f.write(datetime.datetime.utcnow().strftime('%Y-%m-%d %H-%M-%S_%f')[:-2]+" (UTC)\n")
# f.write("TIME(ns): "+str((endVelkoSec - startVelkoSec)*1000000000)+"\n")
# f.write("TIME(s): "+ str(endVelkoSec-startVelkoSec)+"\n")
# f.write("TOTAL TIME ELAPSED(s): "+str(totaltimeelapseds)+"\n")
# f.write("\n===WholePacket===\n")
# tmp=p.show(dump=True)
# f.write(str(tmp))
# f.close()
# TODO: Should log only if log is activated

#log_packet(p,log)
#END LOG SECTION
                s.send(p)
                if (p.proto == 1):
                    print(
                        datetime.datetime.utcnow().strftime(
                            '%Y-%m-%d_%H-%M-%S_%f')[:-2] + "(UTC)\t", "proto",
                        p.proto, "\tsrc", p.src, "\tdst", p.dst, "\tcode",
                        p.code, "\ttype", p.type, "\tLength(b)", len(p))
                else:
                    print(
                        datetime.datetime.utcnow().strftime(
                            '%Y-%m-%d_%H-%M-%S_%f')[:-2] + "(UTC)\t", "proto",
                        p.proto, "\tsrc", p.src, "\tsport", p.sport, "\tdst",
                        p.dst, "\tdport", p.dport, "\tLength(b)", len(p))
                # time.sleep(5)
                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
Exemple #13
0
def sndrcv(pks,
           pkt,
           timeout=None,
           inter=0,
           verbose=None,
           chainCC=False,
           retry=0,
           multi=False,
           rcv_pks=None,
           store_unanswered=True,
           process=None,
           prebuild=False):
    """Scapy raw function to send a packet and receive its answer.
    WARNING: This is an internal function. Using sr/srp/sr1/srp is
    more appropriate in many cases.
    """
    if verbose is None:
        verbose = conf.verb
    use_prn_mode = False
    _storage_policy = None
    if process is not None:
        use_prn_mode = True
        _storage_policy = lambda x, y: process(x, y)
    debug.recv = PacketList([], "Unanswered")
    debug.sent = PacketList([], "Sent")
    debug.match = SndRcvList([])
    nbrecv = 0
    ans = []
    listable = (isinstance(pkt, Packet)
                and pkt.__iterlen__() == 1) or isinstance(pkt,
                                                          list)  # noqa: E501
    # do it here to fix random fields, so that parent and child have the same
    if isinstance(pkt, types.GeneratorType) or prebuild:
        tobesent = [p for p in pkt]
        notans = len(tobesent)
    else:
        tobesent = SetGen(pkt) if not isinstance(pkt, Gen) else pkt
        notans = tobesent.__iterlen__()

    if retry < 0:
        autostop = retry = -retry
    else:
        autostop = 0

    while retry >= 0:
        if timeout is not None and timeout < 0:
            timeout = None
        stopevent = threading.Event()

        hsent = {}
        timessent = {} if listable else None

        _sndrcv_snd(pks, timeout, inter, verbose, tobesent, hsent, timessent,
                    stopevent)

        hsent, newans, nbrecv, notans = _sndrcv_rcv(
            (rcv_pks or pks),
            hsent,
            stopevent,
            nbrecv,
            notans,
            verbose,
            chainCC,
            multi,
            _storage_policy=_storage_policy,
        )

        ans.extend(newans)

        # Restore time_sent to original packets
        if listable:
            i = 0
            for p in (pkt if isinstance(pkt, list) else [pkt]):
                p.sent_time = timessent[i]
                i += 1

        if store_unanswered:
            remain = list(itertools.chain(*six.itervalues(hsent)))
            if multi:
                remain = [p for p in remain if not hasattr(p, '_answered')]

            if autostop and len(remain) > 0 and len(remain) != len(tobesent):
                retry = autostop

            tobesent = remain
            if len(tobesent) == 0:
                break
        else:
            remain = []
        retry -= 1

    if conf.debug_match:
        debug.sent = PacketList(remain[:], "Sent")
        debug.match = SndRcvList(ans[:])

    # Clean the ans list to delete the field _answered
    if multi:
        for snd, _ in ans:
            if hasattr(snd, '_answered'):
                del snd._answered

    if verbose:
        print("\nReceived %i packets, got %i answers, remaining %i packets" %
              (nbrecv + len(ans), len(ans), notans))  # noqa: E501

    if store_unanswered and use_prn_mode:
        remain = [process(x, None) for x in remain]

    ans_result = ans if use_prn_mode else SndRcvList(ans)
    unans_result = remain if use_prn_mode else (
        None if not store_unanswered else PacketList(remain, "Unanswered")
    )  # noqa: E501
    return ans_result, unans_result
Exemple #14
0
class Escapy:
    """
    Insanely good wrapper for scapy. Aids in asynchronous sniffing and
    extracting data in scapy.packets
    """
    __packet_values = (int, float, str, bytes, bool, list, tuple, set, dict,
                       type(None))
    __explicit_layers = [HTTPRequest, HTTPResponse]
    __cap = PacketList()

    @staticmethod
    def async_sniff(action=None, count=0, store=False):
        """
        Sniffs packets asynchronously
        """
        # prepare for a fresh run (threading safety)
        Escapy.__cap = PacketList

        # enable monitor mode on linux based systems
        monitor_mode = not os_name == "nt"
        logger.info(f"Monitor Mode: [{monitor_mode}]")

        Escapy.__cap = AsyncSniffer(prn=action,
                                    monitor=monitor_mode,
                                    count=count,
                                    store=store)
        Escapy.__cap.start()

    @staticmethod
    def stop():
        """
        Stop async_sniff()
        """
        Escapy.__cap.stop()
        Escapy.__cap.join()

    @staticmethod
    def get_cap():
        """
        Returns the scapy async_sniff "thread"
        """
        return Escapy.__cap

    @staticmethod
    def load_cap(file_name) -> PacketList:
        """
        Load .cap into scapy.plist
        """
        try:
            cap = rdpcap(f"{CAP_PATH}{file_name}{CAP_EXTENSION}")
            logger.info(f"\"{file_name}{CAP_EXTENSION}\" loaded")
            return cap
        except FileNotFoundError as error:
            logger.warning(f"{type(error).__name__}: \"{format(error)}\"")

    @staticmethod
    def save_cap(file_name, cap) -> bool:
        """
        Save scapy.plist into .cap
        """
        try:
            wrpcap(f"{CAP_PATH}{file_name}{CAP_EXTENSION}", cap)
            logger.info(f"\"{file_name}{CAP_EXTENSION}\" saved")
        except FileNotFoundError as error:
            logger.warning(f"{type(error).__name__}: \"{format(error)}\"")

    @staticmethod
    def convert_packet(packet, *args, explicit_layers=[]) -> OrderedDict:
        """
        Converts "scapy.layers.l2.Ether" to a dictionary form factor
        """
        explicit_layers = Escapy.__explicit_layers + explicit_layers
        packet_dict = OrderedDict()
        count = 0

        # default scapy layers
        while (layer := packet.getlayer(count)):
            count += 1

            # if layer is not required
            if len(args) != 0 and layer.name not in args:
                continue

            # if layer returns no data
            if (layer_dict := Escapy.__layer_dict(layer)) is None:
                continue

            # concatenate dictionaries
            packet_dict = {**packet_dict, **layer_dict}
Exemple #15
0
def sndrcv(pks,
           pkt,
           timeout=None,
           inter=0,
           verbose=None,
           chainCC=False,
           retry=0,
           multi=False,
           rcv_pks=None,
           store_unanswered=True,
           process=None,
           prebuild=False):
    """Scapy raw function to send a packet and receive its answer.
    WARNING: This is an internal function. Using sr/srp/sr1/srp is
    more appropriate in many cases.

    pks: SuperSocket instance to send/receive packets
    pkt: the packet to send
    rcv_pks: if set, will be used instead of pks to receive packets. packets will still  # noqa: E501
             be sent through pks
    nofilter: put 1 to avoid use of BPF filters
    retry:    if positive, how many times to resend unanswered packets
              if negative, how many times to retry when no more packets are answered  # noqa: E501
    timeout:  how much time to wait after the last packet has been sent
    verbose:  set verbosity level
    multi:    whether to accept multiple answers for the same stimulus
    store_unanswered: whether to store not-answered packets or not. Default True.  # noqa: E501
                      setting it to False will increase speed, and will return None  # noqa: E501
                      as the unans list.
    process:  if specified, only result from process(pkt) will be stored.
              the function should follow the following format:
                lambda sent, received: (func(sent), func2(received))
              if the packet is unanswered, `received` will be None.
              if `store_unanswered` is False, the function won't be called on un-answered packets.  # noqa: E501
    prebuild: pre-build the packets before starting to send them. Default to False. Automatically used  # noqa: E501
              when a generator is passed as the packet
    """
    if verbose is None:
        verbose = conf.verb
    use_prn_mode = False
    _storage_policy = None
    if process is not None:
        use_prn_mode = True
        _storage_policy = lambda x, y: process(x, y)
    debug.recv = PacketList([], "Unanswered")
    debug.sent = PacketList([], "Sent")
    debug.match = SndRcvList([])
    nbrecv = 0
    ans = []
    listable = (isinstance(pkt, Packet)
                and pkt.__iterlen__() == 1) or isinstance(pkt,
                                                          list)  # noqa: E501
    # do it here to fix random fields, so that parent and child have the same
    if isinstance(pkt, types.GeneratorType) or prebuild:
        tobesent = [p for p in pkt]
        notans = len(tobesent)
    else:
        tobesent = SetGen(pkt) if not isinstance(pkt, Gen) else pkt
        notans = tobesent.__iterlen__()

    if retry < 0:
        autostop = retry = -retry
    else:
        autostop = 0

    while retry >= 0:
        if timeout is not None and timeout < 0:
            timeout = None
        stopevent = threading.Event()

        hsent = {}
        timessent = {} if listable else None

        thread = threading.Thread(
            target=_sndrcv_snd,
            args=(pks, timeout, inter, verbose, tobesent, hsent, timessent,
                  stopevent),  # noqa: E501
        )
        thread.setDaemon(True)
        thread.start()

        hsent, newans, nbrecv, notans = _sndrcv_rcv(
            (rcv_pks or pks),
            hsent,
            stopevent,
            nbrecv,
            notans,
            verbose,
            chainCC,
            multi,  # noqa: E501
            _storage_policy=_storage_policy,
        )
        thread.join()

        ans.extend(newans)

        # Restore time_sent to original packets
        if listable:
            i = 0
            for p in (pkt if isinstance(pkt, list) else [pkt]):
                p.sent_time = timessent[i]
                i += 1

        if store_unanswered:
            remain = list(itertools.chain(*six.itervalues(hsent)))
            if multi:
                remain = [p for p in remain if not hasattr(p, '_answered')]

            if autostop and len(remain) > 0 and len(remain) != len(tobesent):
                retry = autostop

            tobesent = remain
            if len(tobesent) == 0:
                break
        else:
            remain = []
        retry -= 1

    if conf.debug_match:
        debug.sent = PacketList(remain[:], "Sent")
        debug.match = SndRcvList(ans[:])

    # Clean the ans list to delete the field _answered
    if multi:
        for snd, _ in ans:
            if hasattr(snd, '_answered'):
                del snd._answered

    if verbose:
        print("\nReceived %i packets, got %i answers, remaining %i packets" %
              (nbrecv + len(ans), len(ans), notans))  # noqa: E501

    if store_unanswered and use_prn_mode:
        remain = [process(x, None) for x in remain]

    ans_result = ans if use_prn_mode else SndRcvList(ans)
    unans_result = remain if use_prn_mode else (
        None if not store_unanswered else PacketList(remain, "Unanswered")
    )  # noqa: E501
    return ans_result, unans_result
Exemple #16
0
 def get_saving_plist():
     temp = Vault.__saving_packet_list
     Vault.__saving_packet_list = PacketList()
     return temp
 def toPacketList(self):
     return PacketList(self.lst, "Sniffed")
Exemple #18
0
class Ecu(object):
    """An Ecu object can be used to
        * track the states of an Ecu.
        * to log all modification to an Ecu.
        * to extract supported responses of a real Ecu.

    Example:
        >>> print("This ecu logs, tracks and creates supported responses")
        >>> my_virtual_ecu = Ecu()
        >>> my_virtual_ecu.update(PacketList([...]))
        >>> my_virtual_ecu.supported_responses
        >>> print("Another ecu just tracks")
        >>> my_tracking_ecu = Ecu(logging=False, store_supported_responses=False)
        >>> my_tracking_ecu.update(PacketList([...]))
        >>> print("Another ecu just logs all modifications to it")
        >>> my_logging_ecu = Ecu(verbose=False, store_supported_responses=False)
        >>> my_logging_ecu.update(PacketList([...]))
        >>> my_logging_ecu.log
        >>> print("Another ecu just creates supported responses")
        >>> my_response_ecu = Ecu(verbose=False, logging=False)
        >>> my_response_ecu.update(PacketList([...]))
        >>> my_response_ecu.supported_responses

    Parameters to initialize an Ecu object

    :param logging: Turn logging on or off. Default is on.
    :param verbose: Turn tracking on or off. Default is on.
    :param store_supported_responses: Create a list of supported responses if True.
    :param lookahead: Configuration for lookahead when computing supported responses
    """    # noqa: E501
    def __init__(self, logging=True, verbose=True,
                 store_supported_responses=True, lookahead=10):
        # type: (bool, bool, bool, int) -> None
        self.state = EcuState()
        self.verbose = verbose
        self.logging = logging
        self.store_supported_responses = store_supported_responses
        self.lookahead = lookahead
        self.log = defaultdict(list)  # type: Dict[str, List[Any]]
        self.__supported_responses = list()  # type: List[EcuResponse]
        self.__unanswered_packets = PacketList()

    def reset(self):
        # type: () -> None
        """
        Resets the internal state to a default EcuState.
        """
        self.state = EcuState(session=1)

    def update(self, p):
        # type: (Union[Packet, PacketList]) -> None
        """
        Processes a Packet or a list of Packets, according to the chosen
        configuration.
        :param p: Packet or list of Packets
        """
        if isinstance(p, PacketList):
            for pkt in p:
                self.update(pkt)
        elif not isinstance(p, Packet):
            raise TypeError("Provide a Packet object for an update")
        else:
            self.__update(p)

    def __update(self, pkt):
        # type: (Packet) -> None
        """
        Processes a Packet according to the chosen configuration.
        :param pkt: Packet to be processed
        """
        if self.verbose:
            print(repr(self), repr(pkt))
        if self.logging:
            self.__update_log(pkt)
        self.__update_supported_responses(pkt)

    def __update_log(self, pkt):
        # type: (Packet) -> None
        """
        Checks if a packet or a layer of this packet supports the function
        `get_log`. If `get_log` is supported, this function will be executed
        and the returned log information is stored in the intern log of this
        Ecu object.
        :param pkt: A Packet to be processed for log information.
        """
        for layer in pkt.layers():
            if not hasattr(layer, "get_log"):
                continue
            try:
                log_key, log_value = layer.get_log(pkt)
            except TypeError:
                log_key, log_value = layer.get_log.im_func(pkt)

            self.log[log_key].append((pkt.time, log_value))

    def __update_supported_responses(self, pkt):
        # type: (Packet) -> None
        """
        Stores a given packet as supported response, if a matching request
        packet is found in a list of the latest unanswered packets. For
        performance improvements, this list of unanswered packets only contains
        a fixed number of packets, defined by the `lookahead` parameter of
        this Ecu.
        :param pkt: Packet to be processed.
        """
        self.__unanswered_packets.append(pkt)
        reduced_plist = self.__unanswered_packets[-self.lookahead:]
        answered, unanswered = reduced_plist.sr(lookahead=self.lookahead)
        self.__unanswered_packets = unanswered

        for req, resp in answered:
            added = False
            current_state = copy.copy(self.state)
            EcuState.get_modified_ecu_state(resp, req, self.state, True)

            if not self.store_supported_responses:
                continue

            for sup_resp in self.__supported_responses:
                if resp == sup_resp.key_response:
                    if sup_resp.states is not None and \
                            self.state not in sup_resp.states:
                        sup_resp.states.append(current_state)
                    added = True
                    break

            if added:
                continue

            ecu_resp = EcuResponse(current_state, responses=resp)
            if self.verbose:
                print("[+] ", repr(ecu_resp))
            self.__supported_responses.append(ecu_resp)

    @staticmethod
    def sort_key_func(resp):
        # type: (EcuResponse) -> Tuple[bool, int, int, int]
        """
        This sorts responses in the following order:
        1. Positive responses first
        2. Lower ServiceIDs first
        3. Less supported states first
        4. Longer (more specific) responses first
        :param resp: EcuResponse to be sorted
        :return: Tuple as sort key
        """
        first_layer = cast(Packet, resp.key_response[0])  # type: ignore
        service = orb(bytes(first_layer)[0])
        return (service == 0x7f,
                service,
                0xffffffff - len(resp.states or []),
                0xffffffff - len(resp.key_response))

    @property
    def supported_responses(self):
        # type: () -> List[EcuResponse]
        """
        Returns a sorted list of supported responses. The sort is done in a way
        to provide the best possible results, if this list of supported
        responses is used to simulate an real world Ecu with the
        EcuAnsweringMachine object.
        :return: A sorted list of EcuResponse objects
        """
        self.__supported_responses.sort(key=self.sort_key_func)
        return self.__supported_responses

    @property
    def unanswered_packets(self):
        # type: () -> PacketList
        """
        A list of all unanswered packets, which were processed by this Ecu
        object.
        :return: PacketList of unanswered packets
        """
        return self.__unanswered_packets

    def __repr__(self):
        # type: () -> str
        return repr(self.state)

    @staticmethod
    def extend_pkt_with_logging(cls):
        # type: (Type[Packet]) -> Callable[[Callable[[Packet], Tuple[str, Any]]], None]  # noqa: E501
        """
        Decorator to add a function as 'get_log' method to a given
        class. This allows dynamic modifications and additions to a protocol.
        :param cls: A packet class to be modified
        :return: Decorator function
        """

        def decorator_function(f):
            # type: (Callable[[Packet], Tuple[str, Any]]) -> None
            setattr(cls, "get_log", f)

        return decorator_function
Exemple #19
0
 def toPacketList(self):
     # type: () -> PacketList
     if self._supersession:
         return PacketList(self._supersession.lst, "Sniffed")
     else:
         return PacketList(self.lst, "Sniffed")
Exemple #20
0
    def __init__(self,
                 pks,
                 pkt,
                 timeout=None,
                 inter=0,
                 verbose=None,
                 chainCC=False,
                 retry=0,
                 multi=False,
                 rcv_pks=None,
                 prebuild=False,
                 _flood=None):
        # Instantiate all arguments
        if verbose is None:
            verbose = conf.verb
        if conf.debug_match:
            debug.recv = PacketList([], "Received")
            debug.sent = PacketList([], "Sent")
            debug.match = SndRcvList([], "Matched")
        self.nbrecv = 0
        self.ans = []
        self.pks = pks
        self.rcv_pks = rcv_pks or pks
        self.inter = inter
        self.verbose = verbose
        self.chainCC = chainCC
        self.multi = multi
        self.timeout = timeout
        # Instantiate packet holders
        if _flood:
            self.tobesent = pkt
            self.notans = _flood[0]
        else:
            if isinstance(pkt, types.GeneratorType) or prebuild:
                self.tobesent = [p for p in pkt]
                self.notans = len(self.tobesent)
            else:
                self.tobesent = (SetGen(pkt)
                                 if not isinstance(pkt, Gen) else pkt)
                self.notans = self.tobesent.__iterlen__()

        if retry < 0:
            autostop = retry = -retry
        else:
            autostop = 0

        if timeout is not None and timeout < 0:
            self.timeout = None

        while retry >= 0:
            self.hsent = {}

            # Send packets in thread.
            # https://github.com/secdev/scapy/issues/1791
            snd_thread = Thread(target=self._sndrcv_snd)
            snd_thread.setDaemon(True)

            # Start routine with callback
            self._sndrcv_rcv(snd_thread.start)

            # Ended. Let's close gracefully
            if _flood:
                # Flood: stop send thread
                _flood[1]()
            snd_thread.join()

            if multi:
                remain = [
                    p for p in itertools.chain(*six.itervalues(self.hsent))
                    if not hasattr(p, '_answered')
                ]
            else:
                remain = list(itertools.chain(*six.itervalues(self.hsent)))

            if autostop and len(remain) > 0 and \
               len(remain) != len(self.tobesent):
                retry = autostop

            self.tobesent = remain
            if len(self.tobesent) == 0:
                break
            retry -= 1

        if conf.debug_match:
            debug.sent = PacketList(remain[:], "Sent")
            debug.match = SndRcvList(self.ans[:])

        # Clean the ans list to delete the field _answered
        if multi:
            for snd, _ in self.ans:
                if hasattr(snd, '_answered'):
                    del snd._answered

        if verbose:
            print("\nReceived %i packets, got %i answers, "
                  "remaining %i packets" %
                  (self.nbrecv + len(self.ans), len(self.ans), self.notans))

        self.ans_result = SndRcvList(self.ans)
        self.unans_result = PacketList(remain, "Unanswered")
Exemple #21
0
    def get_capture(self,
                    expected_count=None,
                    remark=None,
                    timeout=1,
                    filter_out_fn=is_ipv6_misc):
        """ Get captured packets

        :param expected_count: expected number of packets to capture, if None,
                               then self.test.packet_count_for_dst_pg_idx is
                               used to lookup the expected count
        :param remark: remark printed into debug logs
        :param timeout: how long to wait for packets
        :param filter_out_fn: filter applied to each packet, packets for which
                              the filter returns True are removed from capture
        :returns: iterable packets
        """
        remaining_time = timeout
        capture = None
        name = self.name if remark is None else "%s (%s)" % (self.name, remark)
        based_on = "based on provided argument"
        if expected_count is None:
            expected_count = \
                self.test.get_packet_count_for_if_idx(self.sw_if_index)
            based_on = "based on stored packet_infos"
            if expected_count == 0:
                raise Exception(
                    "Internal error, expected packet count for %s is 0!" %
                    name)
        self.test.logger.debug("Expecting to capture %s (%s) packets on %s" %
                               (expected_count, based_on, name))
        while remaining_time > 0:
            before = time.time()
            capture = self._get_capture(remaining_time, filter_out_fn)
            elapsed_time = time.time() - before
            if capture:
                if len(capture.res) == expected_count:
                    # bingo, got the packets we expected
                    return capture
                elif len(capture.res) > expected_count:
                    self.test.logger.error(
                        ppc("Unexpected packets captured:", capture))
                    break
                else:
                    self.test.logger.debug("Partial capture containing %s "
                                           "packets doesn't match expected "
                                           "count %s (yet?)" %
                                           (len(capture.res), expected_count))
            elif expected_count == 0:
                # bingo, got None as we expected - return empty capture
                return PacketList()
            remaining_time -= elapsed_time
        if capture:
            self.generate_debug_aid("count-mismatch")
            if len(capture) > 0 and 0 == expected_count:
                rem = f"\n{remark}" if remark else ""
                raise UnexpectedPacketError(
                    capture[0],
                    f"\n({len(capture)} packets captured in total){rem}")
            raise Exception("Captured packets mismatch, captured %s packets, "
                            "expected %s packets on %s" %
                            (len(capture.res), expected_count, name))
        else:
            raise Exception("No packets captured on %s" % name)
Exemple #22
0
class Vault:

    __runtime_name = None
    __saving = False
    __threading_packet_list = PacketList()
    __saving_packet_list = PacketList()
    __mapping = Counter()
    __packet_count = 0
    __session_dict = {}
    __session_header = []
    __flagged_dict = {}
    __carved_files = []

    @staticmethod
    def set_runtime_name(runtime_name):
        Vault.__runtime_name = runtime_name

    @staticmethod
    def get_runtime_name():
        return Vault.__runtime_name

    @staticmethod
    def set_saving(saving):
        Vault.__saving = saving

    @staticmethod
    def get_saving():
        return Vault.__saving

    @staticmethod
    def refresh():
        Vault.__threading_packet_list = PacketList()
        Vault.__mapping = Counter()
        Vault.__packet_count = 0
        Vault.__session_dict = {}
        Vault.__session_header = []
        Vault.__flagged_dict = {}
        Vault.__carved_files = []

    @staticmethod
    def update_mapping(packet):
        try:
            tmp = sorted([packet[0][1].src, packet[0][1].dst])
            key = f"{tmp[0]},{tmp[1]}"
            Vault.__mapping.update([key])
            logger.debug(f"Packet #{sum(Vault.__mapping.values())}:" +
                         f"{packet[0][1].src} ==> {packet[0][1].dst}")
        except AttributeError:
            tmp = sorted([packet[0][0].src, packet[0][0].dst])
            key = f"{tmp[0]},{tmp[1]}"
            Vault.__mapping.update([key])
            logger.debug(f"Packet #{sum(Vault.__mapping.values())}:" +
                         f"{packet[0][0].src} ==> {packet[0][0].dst}")

    @staticmethod
    def get_mapping():
        ip_list = []
        for key in Vault.__mapping:
            ip1, ip2 = key.split(',')
            ip_list.append(ip1)
            ip_list.append(ip2)

        return Vault.__mapping, list(set(ip_list))

    @staticmethod
    def plist_append(packet):
        # increment total packet count
        Vault.__packet_count += 1
        Vault.__threading_packet_list.append(packet)
        if Vault.__saving:
            Vault.__saving_packet_list.append(packet)

    @staticmethod
    def get_threading_plist():
        temp = Vault.__threading_packet_list
        Vault.__threading_packet_list = PacketList()
        return temp

    @staticmethod
    def get_saving_plist():
        temp = Vault.__saving_packet_list
        Vault.__saving_packet_list = PacketList()
        return temp

    @staticmethod
    def get_sessions(reset=False):
        if not reset:
            return Vault.__session_dict
        temp = Vault.__session_dict
        Vault.__session_dict = {}
        return temp

    @staticmethod
    def add_session(stream_dict):
        for header, plist in stream_dict.items():
            Vault.__session_header += [header] if header not in\
                Vault.__session_header else []
            Vault.__session_dict[header] = Vault.__session_dict[header] +\
                plist if header in Vault.__session_dict else plist

    @staticmethod
    def get_session_headers():
        return Vault.__session_header

    @staticmethod
    def get_total_packet_count():
        return Vault.__packet_count

    @staticmethod
    def get_flagged() -> dict:
        return Vault.__flagged_dict

    @staticmethod
    def set_flagged(flagged_dict):
        Vault.__flagged_dict.update(flagged_dict)

    @staticmethod
    def add_carved_file(session_header, timestamp, filename, cont_type):
        Vault.__carved_files.append(
            (session_header, timestamp, filename, cont_type))

    @staticmethod
    def get_carved_files() -> list:
        return Vault.__carved_files
Exemple #23
0
def ip_defragment(plist):
    """defrag(plist) -> plist defragmented as much as possible """
    frags = defaultdict(lambda: [])
    final = []

    pos = 0
    for p in plist:
        p._defrag_pos = pos
        pos += 1
        if IP in p:
            ip = p[IP]
            if ip.frag != 0 or ip.flags & 1:
                ip = p[IP]
                uniq = (ip.id, ip.src, ip.dst, ip.proto)
                frags[uniq].append(p)
                continue
        final.append(p)

    pbar = tqdm(total=len(frags), desc="IP defrag(1/2) ")
    defrag = []
    missfrag = []
    for lst in six.itervalues(frags):
        pbar.update(1)
        lst.sort(key=lambda x: x.frag)
        p = lst[0]
        lastp = lst[-1]
        if p.frag > 0 or lastp.flags & 1 != 0:  # first or last fragment missing
            missfrag += lst
            continue
        p = p.copy()
        if conf.padding_layer in p:
            del (p[conf.padding_layer].underlayer.payload)
        ip = p[IP]
        if ip.len is None or ip.ihl is None:
            clen = len(ip.payload)
        else:
            clen = ip.len - (ip.ihl << 2)
        txt = conf.raw_layer()
        for q in lst[1:]:
            if clen != q.frag << 3:  # Wrong fragmentation offset
                if clen > q.frag << 3:
                    warning("Fragment overlap (%i > %i) %r || %r ||  %r" %
                            (clen, q.frag << 3, p, txt, q))
                missfrag += lst
                break
            if q[IP].len is None or q[IP].ihl is None:
                clen += len(q[IP].payload)
            else:
                clen += q[IP].len - (q[IP].ihl << 2)
            if conf.padding_layer in q:
                del (q[conf.padding_layer].underlayer.payload)
            txt.add_payload(q[IP].payload.copy())
        else:
            ip.flags &= ~1  # !MF
            del (ip.chksum)
            del (ip.len)
            p = p / txt
            p._defrag_pos = max(x._defrag_pos for x in lst)
            defrag.append(p)
    pbar.close()
    defrag2 = []
    for p in tqdm(defrag, desc="IP defrag(2/2) "):
        q = p.__class__(raw(p))
        q._defrag_pos = p._defrag_pos
        defrag2.append(q)
    final += defrag2
    final += missfrag
    final.sort(key=lambda x: x._defrag_pos)
    for p in final:
        del (p._defrag_pos)

    if hasattr(plist, "listname"):
        name = "Defragmented %s" % plist.listname
    else:
        name = "Defragmented"

    return PacketList(final, name=name)
Exemple #24
0
        deserialized_data = json.loads(data)
        if not re.search(flag_re, deserialized_data['Description']):
            new_packets.append(packet)
            continue

        deserialized_data['Description'] = args.flag
        new_json = json.dumps(deserialized_data, indent=4).encode()
        new_data = xor_data(new_json, key)
        new_length = xor_data(key, len(new_data).to_bytes(2, 'big'))
        new_payload = key + new_length + new_data

        # checksum isn't validated by scapy upon rebuilt unless the property is missing
        del packet['IP'].len
        del packet['IP'].chksum
        del packet['TCP'].chksum

        raw_payload.load = new_payload
        packet['TCP'].payload = raw_payload
        packet['TCP'].explicit = tcp_packet.explicit
        new_packet = l2.Ether(packet.build())
        new_packet['TCP'].time = tcp_packet.time
        new_packet.time = packet.time
        new_packets.append(new_packet)
    else:
        new_packets.append(packet)
new_plist = PacketList(new_packets)
wrpcap(args.output, new_plist)
print(
    f"Dumped the modified capture to {args.output}; be sure to verify with ctf-solve.py!"
)
Exemple #25
0
    def __init__(self, res=None, name="Dot11List", stats=None):
        if stats is None:
            stats = conf.stats_dot11_protocols

        PacketList.__init__(self, res, name, stats)
class Conversation(object):
    def __init__(self, packets, localport=50002, remoteport=4172, isUDP=True):
        '''
		Initialise a conversation from a pcap file or a list otherwise obtained from scapy 
		using scapy.rdpcap (also available as udpanal.rdpcap).
		
		Args:
		* packets - either string representing relative or absolute filename for pcap file
					or PacketList object returned by rdpcap
		* localport - the UDP port you communicated from
		* remoteport - the UDP port you are communicating with
		* isUDP - for future use when TCP & SCTP are also implemented
		'''
        if type(packets) == type(''):
            pktlist = rdpcap(packets)
        elif type(PacketList()) == type(packets):
            pktlist = packets  # re-initialise, take the penalty to kill that annoying 'filter multiplicity)
        else:
            self = packets

        self.lport = localport
        self.rport = remoteport

        if isUDP:
            pktlist = pktlist.filter(lambda x: x.haslayer(UDP))
            pktlist = pktlist.filter(
                lambda x: x.getlayer(UDP).dport == self.lport or x.getlayer(
                    UDP).sport == self.lport or x.getlayer(UDP).dport == self.
                rport or x.getlayer(UDP).sport == self.rport)
            self.pktlist = PacketList(pktlist)
        self.count = len(self.pktlist)
        return

    def __getitem__(self, y):
        re

    def fromLocal(
        self,
        asConvo=True
    ):  # asConvo = False just returns packetlist which is more efficient.
        '''
		Returns a conversation object or PacketList containing only packets sent from the local port.
		It optionally takes an argument which if true returns the result as a conversation object or a
		filtered PacketList object (for speed or list customisation before creating conversation).
		'''
        m = self.pktlist.filter(lambda x: x[UDP].sport == self.lport)
        if asConvo: return Conversation(m)
        else: return m

    def fromRemote(self, asConvo=True):
        '''
		Works as fromLocal, but packets coming from the remote side.
		'''
        m = self.pktlist.filter(lambda x: x[UDP].sport == self.rport)
        if asConvo: return Conversation(m)
        else: return m

    def fromEither(self, asConvo=True):
        '''
		Works as fromLocal, but includes packets originating either local or remotely.
		'''
        m = self.pktlist.filter(
            lambda x: x[UDP].sport == self.lport or x[UDP].sport == self.rport)
        if asConvo: return Conversation(m)
        else: return m

    def subrange(self, end, start=0, asConvo=True):
        '''
		Select a range of packets by position index.
		'''
        m = self.pktlist[start:end]
        if asConvo: return Conversation(m)
        else: return m

    def size(self):
        '''
		Returns the size (in bytes) of each UDP payload in the Conversation as a numpy array.
		'''
        plens = np.array([len(c[Raw].load) for c in self.pktlist])
        return plens

    def sizes(self):
        '''
		Returns the set of sizes (in bytes) of packet payloads.
		'''
        return set(self.size())

    def sizeIs(self, size, asConvo=True):
        '''
		Returns a filtered PacketList object containing only those packets with payloads of the specified size.
		'''
        m = self.pktlist.filter(lambda x: len(x[Raw].load) == size)
        if asConvo: return Conversation(m)
        else: return m

    def sizeBelow(self, size, asConvo=True):
        '''
		Returns a filtered PacketList object containing only those packets with payloads smaller than or equal to size
		'''
        m = self.pktlist.filter(lambda x: len(x[Raw].load) <= size)
        if asConvo: return Conversation(m)
        else: return m

    def sizeAbove(self, size, asConvo=True):
        '''
		Returns a filtered PacketList object containing only those packets with payloads larger than or equal to the specified number of bytes.
		'''
        m = self.pktlist.filter(lambda x: len(x[Raw].load) >= size)
        if asConvo: return Conversation(m)
        else: return m

    def sizeHistogram(self, plot=True):
        '''
		Simplifies the procss of displaying histograms of payload sizes. This is a useful way to classify packets.
		If plot = True, it will display the histogram, else it will return the tuple ( counts, bins ).
		
		If you want finer grained control just import pylab as pl and get cracking!
		'''
        if plot:
            pl.hist(self.size())
            pl.show()
        else:
            return pl.histogram(self.size())

    def statePlot(self,
                  bucketwidth,
                  offsets,
                  filename='state.dot',
                  display=True):
        '''
		bucketwidth is the number of bytes in each section of the packet. Offset selects which section is of interest.
		The result of this function is a graph where the nodes are packet states and the directed arcs show numbered
		transitions between states.
		
		Beware, if there are a large number of states and indices the graph will likely be indecipherable if it
		even generates. Choose the values wisely.
		
		In future this will be more useful, based on multiple lengths using a scapy dissection definition.
		For now a spec for byte samples and offsets is all you get. Tools will be included to look at bit patterns
		in order to determine the existence and properties of individual flags.  However, at this stage, that should
		be both trivial and irrelevant.'''

        statesamples = Samples(self,
                               bucketwidth * (np.array(offsets).max() + 1),
                               bucketwidth)
        valuesetlist = []
        valueslist = []
        for o in offsets:
            valueset = statesamples.asHexSet(o)
            print valueset
            valuesetlist.append(valueset)
            valueslist.append(statesamples.asHex(o))

        nodelist = [n for n in it.product(*valuesetlist)]
        G = nx.MultiDiGraph()
        G.add_nodes_from(nodelist)
        for i in range(len(valueslist[0]) - 1):
            nodetuple = []
            for j in range(len(offsets)):
                nodetuple.append(valueslist[j][i])
            thisnodetuple = tuple(nodetuple)
            nodetuple = []
            for j in range(len(offsets)):
                nodetuple.append(valueslist[j][i + 1])
            nextnodetuple = tuple(nodetuple)
            # before adding edge, color according to local or remote origin
            if self.pktlist[i][UDP].sport == self.lport: edgecolour = 'green'
            if self.pktlist[i][UDP].sport == self.rport: edgecolour = 'blue'
            G.add_edge(thisnodetuple, nextnodetuple, label=i, color=edgecolour)
        # clean out unused states from graph
        for n in G.nodes():
            if G.neighbors(n) == []: G.remove_node(n)
        GA = nx.to_agraph(G)
        GA.edge_attr['penwidth'] = 3.0
        GA.layout()
        GA.write(filename)
        if display:
            Popen(['xdot', filename])
        return
Exemple #27
0
class debug:
    recv = PacketList([], "Received")
    sent = PacketList([], "Sent")
    match = SndRcvList([], "Matched")
    crashed_on = None  # type: Optional[Tuple[Type[Packet], bytes]]
Exemple #28
0
class Automaton:
    states = {}  # type: Dict[str, _StateWrapper]
    state = None  # type: ATMT.NewStateRequested
    recv_conditions = {}  # type: Dict[str, List[_StateWrapper]]
    conditions = {}  # type: Dict[str, List[_StateWrapper]]
    ioevents = {}  # type: Dict[str, List[_StateWrapper]]
    timeout = {
    }  # type: Dict[str, List[Tuple[int, _StateWrapper]]] # noqa: E501
    actions = {}  # type: Dict[str, List[_StateWrapper]]
    initial_states = []  # type: List[_StateWrapper]
    stop_states = []  # type: List[_StateWrapper]
    ionames = []  # type: List[str]
    iosupersockets = []  # type: List[SuperSocket]

    # Internals
    def __init__(self, *args, **kargs):
        # type: (Any, Any) -> None
        external_fd = kargs.pop("external_fd", {})
        self.send_sock_class = kargs.pop("ll", conf.L3socket)
        self.recv_sock_class = kargs.pop("recvsock", conf.L2listen)
        self.is_atmt_socket = kargs.pop("is_atmt_socket", False)
        self.started = threading.Lock()
        self.threadid = None  # type: Optional[int]
        self.breakpointed = None
        self.breakpoints = set()  # type: Set[_StateWrapper]
        self.interception_points = set()  # type: Set[_StateWrapper]
        self.intercepted_packet = None  # type: Union[None, Packet]
        self.debug_level = 0
        self.init_args = args
        self.init_kargs = kargs
        self.io = type.__new__(type, "IOnamespace", (), {})
        self.oi = type.__new__(type, "IOnamespace", (), {})
        self.cmdin = ObjectPipe[Message]("cmdin")
        self.cmdout = ObjectPipe[Message]("cmdout")
        self.ioin = {}
        self.ioout = {}
        self.packets = PacketList()  # type: PacketList
        for n in self.__class__.ionames:
            extfd = external_fd.get(n)
            if not isinstance(extfd, tuple):
                extfd = (extfd, extfd)
            ioin, ioout = extfd
            if ioin is None:
                ioin = ObjectPipe("ioin")
            else:
                ioin = self._IO_fdwrapper(ioin, None)
            if ioout is None:
                ioout = ObjectPipe("ioout")
            else:
                ioout = self._IO_fdwrapper(None, ioout)

            self.ioin[n] = ioin
            self.ioout[n] = ioout
            ioin.ioname = n
            ioout.ioname = n
            setattr(self.io, n, self._IO_mixer(ioout, ioin))
            setattr(self.oi, n, self._IO_mixer(ioin, ioout))

        for stname in self.states:
            setattr(self, stname, _instance_state(getattr(self, stname)))

        self.start()

    def parse_args(self, debug=0, store=1, **kargs):
        # type: (int, int, Any) -> None
        self.debug_level = debug
        if debug:
            conf.logLevel = logging.DEBUG
        self.socket_kargs = kargs
        self.store_packets = store

    def master_filter(self, pkt):
        # type: (Packet) -> bool
        return True

    def my_send(self, pkt):
        # type: (Packet) -> None
        self.send_sock.send(pkt)

    # Utility classes and exceptions
    class _IO_fdwrapper:
        def __init__(
            self,
            rd,  # type: Union[int, ObjectPipe[bytes], None]
            wr  # type: Union[int, ObjectPipe[bytes], None]
        ):
            # type: (...) -> None
            if rd is not None and not isinstance(rd, (int, ObjectPipe)):
                rd = rd.fileno()  # type: ignore
            if wr is not None and not isinstance(wr, (int, ObjectPipe)):
                wr = wr.fileno()  # type: ignore
            self.rd = rd
            self.wr = wr

        def fileno(self):
            # type: () -> int
            if isinstance(self.rd, ObjectPipe):
                return self.rd.fileno()
            elif isinstance(self.rd, int):
                return self.rd
            return 0

        def read(self, n=65535):
            # type: (int) -> Optional[bytes]
            if isinstance(self.rd, ObjectPipe):
                return self.rd.recv(n)
            elif isinstance(self.rd, int):
                return os.read(self.rd, n)
            return None

        def write(self, msg):
            # type: (bytes) -> int
            if isinstance(self.wr, ObjectPipe):
                return self.wr.send(msg)
            elif isinstance(self.wr, int):
                return os.write(self.wr, msg)
            return 0

        def recv(self, n=65535):
            # type: (int) -> Optional[bytes]
            return self.read(n)

        def send(self, msg):
            # type: (bytes) -> int
            return self.write(msg)

    class _IO_mixer:
        def __init__(
                self,
                rd,  # type: ObjectPipe[Any]
                wr,  # type: ObjectPipe[Any]
        ):
            # type: (...) -> None
            self.rd = rd
            self.wr = wr

        def fileno(self):
            # type: () -> Any
            if isinstance(self.rd, ObjectPipe):
                return self.rd.fileno()
            return self.rd

        def recv(self, n=None):
            # type: (Optional[int]) -> Any
            return self.rd.recv(n)

        def read(self, n=None):
            # type: (Optional[int]) -> Any
            return self.recv(n)

        def send(self, msg):
            # type: (str) -> int
            return self.wr.send(msg)

        def write(self, msg):
            # type: (str) -> int
            return self.send(msg)

    class AutomatonException(Exception):
        def __init__(self, msg, state=None, result=None):
            # type: (str, Optional[Message], Optional[str]) -> None
            Exception.__init__(self, msg)
            self.state = state
            self.result = result

    class AutomatonError(AutomatonException):
        pass

    class ErrorState(AutomatonException):
        pass

    class Stuck(AutomatonException):
        pass

    class AutomatonStopped(AutomatonException):
        pass

    class Breakpoint(AutomatonStopped):
        pass

    class Singlestep(AutomatonStopped):
        pass

    class InterceptionPoint(AutomatonStopped):
        def __init__(self, msg, state=None, result=None, packet=None):
            # type: (str, Optional[Message], Optional[str], Optional[str]) -> None  # noqa: E501
            Automaton.AutomatonStopped.__init__(self,
                                                msg,
                                                state=state,
                                                result=result)  # noqa: E501
            self.packet = packet

    class CommandMessage(AutomatonException):
        pass

    # Services
    def debug(self, lvl, msg):
        # type: (int, str) -> None
        if self.debug_level >= lvl:
            log_runtime.debug(msg)

    def send(self, pkt):
        # type: (Packet) -> None
        if self.state.state in self.interception_points:
            self.debug(3, "INTERCEPT: packet intercepted: %s" % pkt.summary())
            self.intercepted_packet = pkt
            self.cmdout.send(
                Message(type=_ATMT_Command.INTERCEPT,
                        state=self.state,
                        pkt=pkt))
            cmd = self.cmdin.recv()
            if not cmd:
                self.debug(3, "CANCELLED")
                return
            self.intercepted_packet = None
            if cmd.type == _ATMT_Command.REJECT:
                self.debug(3, "INTERCEPT: packet rejected")
                return
            elif cmd.type == _ATMT_Command.REPLACE:
                pkt = cmd.pkt
                self.debug(3, "INTERCEPT: packet replaced by: %s" %
                           pkt.summary())  # noqa: E501
            elif cmd.type == _ATMT_Command.ACCEPT:
                self.debug(3, "INTERCEPT: packet accepted")
            else:
                raise self.AutomatonError("INTERCEPT: unknown verdict: %r" %
                                          cmd.type)  # noqa: E501
        self.my_send(pkt)
        self.debug(3, "SENT : %s" % pkt.summary())

        if self.store_packets:
            self.packets.append(pkt.copy())

    def __iter__(self):
        # type: () -> Automaton
        return self

    def __del__(self):
        # type: () -> None
        self.stop()

    def _run_condition(self, cond, *args, **kargs):
        # type: (_StateWrapper, Any, Any) -> None
        try:
            self.debug(5, "Trying %s [%s]" %
                       (cond.atmt_type, cond.atmt_condname))  # noqa: E501
            cond(self, *args, **kargs)
        except ATMT.NewStateRequested as state_req:
            self.debug(2, "%s [%s] taken to state [%s]" %
                       (cond.atmt_type, cond.atmt_condname,
                        state_req.state))  # noqa: E501
            if cond.atmt_type == ATMT.RECV:
                if self.store_packets:
                    self.packets.append(args[0])
            for action in self.actions[cond.atmt_condname]:
                self.debug(2, "   + Running action [%s]" % action.__name__)
                action(self, *state_req.action_args, **state_req.action_kargs)
            raise
        except Exception as e:
            self.debug(2, "%s [%s] raised exception [%s]" %
                       (cond.atmt_type, cond.atmt_condname, e))  # noqa: E501
            raise
        else:
            self.debug(2, "%s [%s] not taken" %
                       (cond.atmt_type, cond.atmt_condname))  # noqa: E501

    def _do_start(self, *args, **kargs):
        # type: (Any, Any) -> None
        ready = threading.Event()
        _t = threading.Thread(target=self._do_control,
                              args=(ready, ) + (args),
                              kwargs=kargs,
                              name="scapy.automaton _do_start")
        _t.daemon = True
        _t.start()
        ready.wait()

    def _do_control(self, ready, *args, **kargs):
        # type: (threading.Event, Any, Any) -> None
        with self.started:
            self.threadid = threading.current_thread().ident
            if self.threadid is None:
                self.threadid = 0

            # Update default parameters
            a = args + self.init_args[len(args):]
            k = self.init_kargs.copy()
            k.update(kargs)
            self.parse_args(*a, **k)

            # Start the automaton
            self.state = self.initial_states[0](self)
            self.send_sock = self.send_sock_class(**self.socket_kargs)
            self.listen_sock = self.recv_sock_class(**self.socket_kargs)
            self.packets = PacketList(name="session[%s]" %
                                      self.__class__.__name__)  # noqa: E501

            singlestep = True
            iterator = self._do_iter()
            self.debug(3, "Starting control thread [tid=%i]" % self.threadid)
            # Sync threads
            ready.set()
            try:
                while True:
                    c = self.cmdin.recv()
                    if c is None:
                        return None
                    self.debug(5, "Received command %s" % c.type)
                    if c.type == _ATMT_Command.RUN:
                        singlestep = False
                    elif c.type == _ATMT_Command.NEXT:
                        singlestep = True
                    elif c.type == _ATMT_Command.FREEZE:
                        continue
                    elif c.type == _ATMT_Command.STOP:
                        if self.stop_states:
                            # There is a stop state
                            self.state = self.stop_states[0](self)
                            iterator = self._do_iter()
                        else:
                            # Act as FORCESTOP
                            break
                    elif c.type == _ATMT_Command.FORCESTOP:
                        break
                    while True:
                        state = next(iterator)
                        if isinstance(state, self.CommandMessage):
                            break
                        elif isinstance(state, self.Breakpoint):
                            c = Message(type=_ATMT_Command.BREAKPOINT,
                                        state=state)  # noqa: E501
                            self.cmdout.send(c)
                            break
                        if singlestep:
                            c = Message(type=_ATMT_Command.SINGLESTEP,
                                        state=state)  # noqa: E501
                            self.cmdout.send(c)
                            break
            except (StopIteration, RuntimeError):
                c = Message(type=_ATMT_Command.END,
                            result=self.final_state_output)
                self.cmdout.send(c)
            except Exception as e:
                exc_info = sys.exc_info()
                self.debug(
                    3, "Transferring exception from tid=%i:\n%s" %
                    (self.threadid,
                     traceback.format_exception(*exc_info)))  # noqa: E501
                m = Message(type=_ATMT_Command.EXCEPTION,
                            exception=e,
                            exc_info=exc_info)  # noqa: E501
                self.cmdout.send(m)
            self.debug(3, "Stopping control thread (tid=%i)" % self.threadid)
            self.threadid = None

    def _do_iter(self):
        # type: () -> Iterator[Union[Automaton.AutomatonException, Automaton.AutomatonStopped, ATMT.NewStateRequested, None]] # noqa: E501
        while True:
            try:
                self.debug(1, "## state=[%s]" % self.state.state)

                # Entering a new state. First, call new state function
                if self.state.state in self.breakpoints and self.state.state != self.breakpointed:  # noqa: E501
                    self.breakpointed = self.state.state
                    yield self.Breakpoint(
                        "breakpoint triggered on state %s" %
                        self.state.state,  # noqa: E501
                        state=self.state.state)
                self.breakpointed = None
                state_output = self.state.run()
                if self.state.error:
                    raise self.ErrorState(
                        "Reached %s: [%r]" %
                        (self.state.state, state_output),  # noqa: E501
                        result=state_output,
                        state=self.state.state)  # noqa: E501
                if self.state.final:
                    self.final_state_output = state_output
                    return

                if state_output is None:
                    state_output = ()
                elif not isinstance(state_output, list):
                    state_output = state_output,

                # If there are commandMessage, we should skip immediate
                # conditions.
                if not select_objects([self.cmdin], 0):
                    # Then check immediate conditions
                    for cond in self.conditions[self.state.state]:
                        self._run_condition(cond, *state_output)

                    # If still there and no conditions left, we are stuck!
                    if (len(self.recv_conditions[self.state.state]) == 0
                            and len(self.ioevents[self.state.state]) == 0
                            and len(self.timeout[self.state.state]) == 1):
                        raise self.Stuck("stuck in [%s]" % self.state.state,
                                         state=self.state.state,
                                         result=state_output)

                # Finally listen and pay attention to timeouts
                expirations = iter(self.timeout[self.state.state])
                next_timeout, timeout_func = next(expirations)
                t0 = time.time()

                fds = [self.cmdin]
                if len(self.recv_conditions[self.state.state]) > 0:
                    fds.append(self.listen_sock)
                for ioev in self.ioevents[self.state.state]:
                    fds.append(self.ioin[ioev.atmt_ioname])
                while True:
                    t = time.time() - t0
                    if next_timeout is not None:
                        if next_timeout <= t:
                            self._run_condition(timeout_func, *state_output)
                            next_timeout, timeout_func = next(expirations)
                    if next_timeout is None:
                        remain = 0
                    else:
                        remain = next_timeout - t

                    self.debug(5, "Select on %r" % fds)
                    r = select_objects(fds, remain)
                    self.debug(5, "Selected %r" % r)
                    for fd in r:
                        self.debug(5, "Looking at %r" % fd)
                        if fd == self.cmdin:
                            yield self.CommandMessage(
                                "Received command message")  # noqa: E501
                        elif fd == self.listen_sock:
                            pkt = self.listen_sock.recv(MTU)
                            if pkt is not None:
                                if self.master_filter(pkt):
                                    self.debug(3, "RECVD: %s" %
                                               pkt.summary())  # noqa: E501
                                    for rcvcond in self.recv_conditions[
                                            self.state.state]:  # noqa: E501
                                        self._run_condition(
                                            rcvcond, pkt,
                                            *state_output)  # noqa: E501
                                else:
                                    self.debug(4, "FILTR: %s" %
                                               pkt.summary())  # noqa: E501
                        else:
                            self.debug(3, "IOEVENT on %s" % fd.ioname)
                            for ioevt in self.ioevents[self.state.state]:
                                if ioevt.atmt_ioname == fd.ioname:
                                    self._run_condition(
                                        ioevt, fd, *state_output)  # noqa: E501

            except ATMT.NewStateRequested as state_req:
                self.debug(2, "switching from [%s] to [%s]" %
                           (self.state.state, state_req.state))  # noqa: E501
                self.state = state_req
                yield state_req

    def __repr__(self):
        # type: () -> str
        return "<Automaton %s [%s]>" % (self.__class__.__name__, [
            "HALTED", "RUNNING"
        ][self.started.locked()])

    # Public API
    def add_interception_points(self, *ipts):
        # type: (Any) -> None
        for ipt in ipts:
            if hasattr(ipt, "atmt_state"):
                ipt = ipt.atmt_state
            self.interception_points.add(ipt)

    def remove_interception_points(self, *ipts):
        # type: (Any) -> None
        for ipt in ipts:
            if hasattr(ipt, "atmt_state"):
                ipt = ipt.atmt_state
            self.interception_points.discard(ipt)

    def add_breakpoints(self, *bps):
        # type: (Any) -> None
        for bp in bps:
            if hasattr(bp, "atmt_state"):
                bp = bp.atmt_state
            self.breakpoints.add(bp)

    def remove_breakpoints(self, *bps):
        # type: (Any) -> None
        for bp in bps:
            if hasattr(bp, "atmt_state"):
                bp = bp.atmt_state
            self.breakpoints.discard(bp)

    def start(self, *args, **kargs):
        # type: (Any, Any) -> None
        if not self.started.locked():
            self._do_start(*args, **kargs)

    def run(
            self,
            resume=None,  # type: Optional[Message]
            wait=True  # type: Optional[bool]
    ):
        # type: (...) -> Any
        if resume is None:
            resume = Message(type=_ATMT_Command.RUN)
        self.cmdin.send(resume)
        if wait:
            try:
                c = self.cmdout.recv()
                if c is None:
                    return None
            except KeyboardInterrupt:
                self.cmdin.send(Message(type=_ATMT_Command.FREEZE))
                return None
            if c.type == _ATMT_Command.END:
                return c.result
            elif c.type == _ATMT_Command.INTERCEPT:
                raise self.InterceptionPoint("packet intercepted",
                                             state=c.state.state,
                                             packet=c.pkt)  # noqa: E501
            elif c.type == _ATMT_Command.SINGLESTEP:
                raise self.Singlestep("singlestep state=[%s]" % c.state.state,
                                      state=c.state.state)  # noqa: E501
            elif c.type == _ATMT_Command.BREAKPOINT:
                raise self.Breakpoint("breakpoint triggered on state [%s]" %
                                      c.state.state,
                                      state=c.state.state)  # noqa: E501
            elif c.type == _ATMT_Command.EXCEPTION:
                six.reraise(c.exc_info[0], c.exc_info[1], c.exc_info[2])
        return None

    def runbg(self, resume=None, wait=False):
        # type: (Optional[Message], Optional[bool]) -> None
        self.run(resume, wait)

    def next(self):
        # type: () -> Any
        return self.run(resume=Message(type=_ATMT_Command.NEXT))

    __next__ = next

    def _flush_inout(self):
        # type: () -> None
        with self.started:
            # Flush command pipes
            while True:
                r = select_objects([self.cmdin, self.cmdout], 0)
                if not r:
                    break
                for fd in r:
                    fd.recv()

    def stop(self):
        # type: () -> None
        self.cmdin.send(Message(type=_ATMT_Command.STOP))
        self._flush_inout()

    def forcestop(self):
        # type: () -> None
        self.cmdin.send(Message(type=_ATMT_Command.FORCESTOP))
        self._flush_inout()

    def restart(self, *args, **kargs):
        # type: (Any, Any) -> None
        self.stop()
        self.start(*args, **kargs)

    def accept_packet(
            self,
            pkt=None,  # type: Optional[Packet]
            wait=False  # type: Optional[bool]
    ):
        # type: (...) -> Any
        rsm = Message()
        if pkt is None:
            rsm.type = _ATMT_Command.ACCEPT
        else:
            rsm.type = _ATMT_Command.REPLACE
            rsm.pkt = pkt
        return self.run(resume=rsm, wait=wait)

    def reject_packet(
            self,
            wait=False  # type: Optional[bool]
    ):
        # type: (...) -> Any
        rsm = Message(type=_ATMT_Command.REJECT)
        return self.run(resume=rsm, wait=wait)
Exemple #29
0
class Ecu(object):
    """A ECU object can be used to
            - track the states of an ECU.
            - to log all modification to an ECU
            - to extract supported responses of a real ECU

           Usage:
           >>> print("This ecu logs, tracks and creates supported responses")
           >>> my_virtual_ecu = Ecu()
           >>> my_virtual_ecu.update(PacketList([...]))
           >>> my_virtual_ecu.supported_responses
           >>> print("Another ecu just tracks")
           >>> my_tracking_ecu = Ecu(logging=False, store_supported_responses=False)  # noqa: E501
           >>> my_tracking_ecu.update(PacketList([...]))
           >>> print("Another ecu just logs all modifications to it")
           >>> my_logging_ecu = Ecu(verbose=False, store_supported_responses=False)  # noqa: E501
           >>> my_logging_ecu.update(PacketList([...]))
           >>> my_logging_ecu.log
           >>> print("Another ecu just creates supported responses")
           >>> my_response_ecu = Ecu(verbose=False, logging=False)
           >>> my_response_ecu.update(PacketList([...]))
           >>> my_response_ecu.supported_responses
       """
    def __init__(self,
                 init_session=None,
                 init_security_level=None,
                 init_communication_control=None,
                 logging=True,
                 verbose=True,
                 store_supported_responses=True):
        """
        Initialize an Ecu object

        :param init_session: An initial session
        :param init_security_level: An initial security level
        :param init_communication_control: An initial communication control
                                           setting
        :param logging: Turn logging on or off. Default is on.
        :param verbose: Turn tracking on or off. Default is on.
        :param store_supported_responses: Turn creation of supported responses
                                          on or off. Default is on.
        """
        self.state = EcuState(session=init_session or 1,
                              security_level=init_security_level or 0,
                              communication_control=init_communication_control
                              or 0)
        self.verbose = verbose
        self.logging = logging
        self.store_supported_responses = store_supported_responses
        self.log = defaultdict(list)
        self._supported_responses = list()
        self._unanswered_packets = PacketList()

    @property
    def current_session(self):
        return self.state.session

    @current_session.setter
    def current_session(self, ses):
        self.state.session = ses

    @property
    def current_security_level(self):
        return self.state.security_level

    @current_security_level.setter
    def current_security_level(self, sec):
        self.state.security_level = sec

    @property
    def communication_control(self):
        return self.state.communication_control

    @communication_control.setter
    def communication_control(self, cc):
        self.state.communication_control = cc

    def reset(self):
        self.state.reset()
        self.state.session = 1
        self.state.security_level = 0
        self.state.communication_control = 0

    def update(self, p):
        if isinstance(p, PacketList):
            for pkt in p:
                self._update(pkt)
        elif not isinstance(p, Packet):
            raise Scapy_Exception("Provide a Packet object for an update")
        else:
            self._update(p)

    def _update(self, pkt):
        if self.verbose:
            print(repr(self), repr(pkt))
        if self.store_supported_responses:
            self._update_supported_responses(pkt)
        if self.logging:
            self._update_log(pkt)
        self._update_internal_state(pkt)

    def _update_log(self, pkt):
        for layer in pkt.layers():
            if hasattr(layer, "get_log"):
                log_key, log_value = layer.get_log(pkt)
                self.log[log_key].append((pkt.time, log_value))

    def _update_internal_state(self, pkt):
        for layer in pkt.layers():
            if hasattr(layer, "modifies_ecu_state"):
                layer.modifies_ecu_state(pkt, self)

    def _update_supported_responses(self, pkt):
        self._unanswered_packets += PacketList([pkt])
        answered, unanswered = self._unanswered_packets.sr()
        for _, resp in answered:
            ecu_resp = EcuResponse(session=self.current_session,
                                   security_level=self.current_security_level,
                                   responses=resp)

            if ecu_resp not in self._supported_responses:
                if self.verbose:
                    print("[+] ", repr(ecu_resp))
                self._supported_responses.append(ecu_resp)
            else:
                if self.verbose:
                    print("[-] ", repr(ecu_resp))
        self._unanswered_packets = unanswered

    @property
    def supported_responses(self):
        # This sorts responses in the following order:
        # 1. Positive responses first
        # 2. Lower ServiceID first
        # 3. Longer (more specific) responses first
        self._supported_responses.sort(
            key=lambda x: (x.responses[0].service == 0x7f, x.responses[0].
                           service, 0xffffffff - len(x.responses[0])))
        return self._supported_responses

    @property
    def unanswered_packets(self):
        return self._unanswered_packets

    def __repr__(self):
        return "ses: %03d  sec: %03d  cc: %d" % (self.current_session,
                                                 self.current_security_level,
                                                 self.communication_control)
Exemple #30
0
    def _do_control(self, ready, *args, **kargs):
        # type: (threading.Event, Any, Any) -> None
        with self.started:
            self.threadid = threading.current_thread().ident
            if self.threadid is None:
                self.threadid = 0

            # Update default parameters
            a = args + self.init_args[len(args):]
            k = self.init_kargs.copy()
            k.update(kargs)
            self.parse_args(*a, **k)

            # Start the automaton
            self.state = self.initial_states[0](self)
            self.send_sock = self.send_sock_class(**self.socket_kargs)
            self.listen_sock = self.recv_sock_class(**self.socket_kargs)
            self.packets = PacketList(name="session[%s]" %
                                      self.__class__.__name__)  # noqa: E501

            singlestep = True
            iterator = self._do_iter()
            self.debug(3, "Starting control thread [tid=%i]" % self.threadid)
            # Sync threads
            ready.set()
            try:
                while True:
                    c = self.cmdin.recv()
                    if c is None:
                        return None
                    self.debug(5, "Received command %s" % c.type)
                    if c.type == _ATMT_Command.RUN:
                        singlestep = False
                    elif c.type == _ATMT_Command.NEXT:
                        singlestep = True
                    elif c.type == _ATMT_Command.FREEZE:
                        continue
                    elif c.type == _ATMT_Command.STOP:
                        if self.stop_states:
                            # There is a stop state
                            self.state = self.stop_states[0](self)
                            iterator = self._do_iter()
                        else:
                            # Act as FORCESTOP
                            break
                    elif c.type == _ATMT_Command.FORCESTOP:
                        break
                    while True:
                        state = next(iterator)
                        if isinstance(state, self.CommandMessage):
                            break
                        elif isinstance(state, self.Breakpoint):
                            c = Message(type=_ATMT_Command.BREAKPOINT,
                                        state=state)  # noqa: E501
                            self.cmdout.send(c)
                            break
                        if singlestep:
                            c = Message(type=_ATMT_Command.SINGLESTEP,
                                        state=state)  # noqa: E501
                            self.cmdout.send(c)
                            break
            except (StopIteration, RuntimeError):
                c = Message(type=_ATMT_Command.END,
                            result=self.final_state_output)
                self.cmdout.send(c)
            except Exception as e:
                exc_info = sys.exc_info()
                self.debug(
                    3, "Transferring exception from tid=%i:\n%s" %
                    (self.threadid,
                     traceback.format_exception(*exc_info)))  # noqa: E501
                m = Message(type=_ATMT_Command.EXCEPTION,
                            exception=e,
                            exc_info=exc_info)  # noqa: E501
                self.cmdout.send(m)
            self.debug(3, "Stopping control thread (tid=%i)" % self.threadid)
            self.threadid = None
Exemple #31
0
    def _do_control(self, ready, *args, **kargs):
        with self.started:
            self.threadid = threading.currentThread().ident

            # Update default parameters
            a = args + self.init_args[len(args):]
            k = self.init_kargs.copy()
            k.update(kargs)
            self.parse_args(*a, **k)

            # Start the automaton
            self.state = self.initial_states[0](self)
            self.send_sock = self.send_sock_class()
            self.listen_sock = self.recv_sock_class(**self.socket_kargs)
            self.packets = PacketList(name="session[%s]" %
                                      self.__class__.__name__)

            singlestep = True
            iterator = self._do_iter()
            self.debug(3, "Starting control thread [tid=%i]" % self.threadid)
            # Sync threads
            ready.set()
            try:
                while True:
                    c = self.cmdin.recv()
                    self.debug(5, "Received command %s" % c.type)
                    if c.type == _ATMT_Command.RUN:
                        singlestep = False
                    elif c.type == _ATMT_Command.NEXT:
                        singlestep = True
                    elif c.type == _ATMT_Command.FREEZE:
                        continue
                    elif c.type == _ATMT_Command.STOP:
                        break
                    while True:
                        state = next(iterator)
                        if isinstance(state, self.CommandMessage):
                            break
                        elif isinstance(state, self.Breakpoint):
                            c = Message(type=_ATMT_Command.BREAKPOINT,
                                        state=state)
                            self.cmdout.send(c)
                            break
                        if singlestep:
                            c = Message(type=_ATMT_Command.SINGLESTEP,
                                        state=state)
                            self.cmdout.send(c)
                            break
            except StopIteration as e:
                c = Message(type=_ATMT_Command.END, result=e.args[0])
                self.cmdout.send(c)
            except Exception as e:
                exc_info = sys.exc_info()
                self.debug(
                    3, "Transfering exception from tid=%i:\n%s" %
                    (self.threadid, traceback.format_exc(exc_info)))
                m = Message(type=_ATMT_Command.EXCEPTION,
                            exception=e,
                            exc_info=exc_info)
                self.cmdout.send(m)
            self.debug(3, "Stopping control thread (tid=%i)" % self.threadid)
            self.threadid = None
Exemple #32
0
def defrag(plist):
    """defrag(plist) -> ([not fragmented], [defragmented],
                  [ [bad fragments], [bad fragments], ... ])"""
    frags = {}
    nofrag = PacketList()
    for p in plist:
        ip = p[IP]
        if IP not in p:
            nofrag.append(p)
            continue
        if ip.frag == 0 and ip.flags & 1 == 0:
            nofrag.append(p)
            continue
        uniq = (ip.id,ip.src,ip.dst,ip.proto)
        if uniq in frags:
            frags[uniq].append(p)
        else:
            frags[uniq] = PacketList([p])
    defrag = []
    missfrag = []
    for lst in frags.itervalues():
        lst.sort(lambda x,y:cmp(x.frag, y.frag))
        p = lst[0]
        if p.frag > 0:
            missfrag.append(lst)
            continue
        p = p.copy()
        if Padding in p:
            del(p[Padding].underlayer.payload)
        ip = p[IP]
        if ip.len is None or ip.ihl is None:
            clen = len(ip.payload)
        else:
            clen = ip.len - (ip.ihl<<2)
        txt = Raw()
        for q in lst[1:]:
            if clen != q.frag<<3:
                if clen > q.frag<<3:
                    warning("Fragment overlap (%i > %i) %r || %r ||  %r" % (clen, q.frag<<3, p,txt,q))
                missfrag.append(lst)
                txt = None
                break
            if q[IP].len is None or q[IP].ihl is None:
                clen += len(q[IP].payload)
            else:
                clen += q[IP].len - (q[IP].ihl<<2)
            if Padding in q:
                del(q[Padding].underlayer.payload)
            txt.add_payload(q[IP].payload.copy())
            
        if txt is None:
            continue

        ip.flags &= ~1 # !MF
        del(ip.chksum)
        del(ip.len)
        p = p/txt
        defrag.append(p)
    defrag2=PacketList()
    for p in defrag:
        defrag2.append(p.__class__(str(p)))
    return nofrag,defrag2,missfrag