Exemple #1
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
    if return_packets:
        sent_packets = PacketList()
    try:
        while loop:
            dt0 = None
            for p in x:
                if realtime:
                    ct = time.time()
                    if dt0:
                        st = dt0 + float(p.time) - ct
                        if st > 0:
                            time.sleep(st)
                    else:
                        dt0 = ct - float(p.time)
                s.send(p)
                if return_packets:
                    sent_packets.append(p)
                n += 1
                if verbose:
                    os.write(1, b".")
                time.sleep(inter)
            if loop < 0:
                loop += 1
    except KeyboardInterrupt:
        pass
    if verbose:
        print("\nSent %i packets." % n)
    if return_packets:
        return sent_packets
    return None
Exemple #2
0
def __gen_send(s,
               x,
               inter=0,
               loop=0,
               count=None,
               verbose=None,
               realtime=None,
               return_packets=False,
               *args,
               **kargs):  # noqa: E501
    if isinstance(x, str):
        x = conf.raw_layer(load=x)
    if not isinstance(x, Gen):
        x = SetGen(x)
    if verbose is None:
        verbose = conf.verb
    n = 0
    if count is not None:
        loop = -count
    elif not loop:
        loop = -1
    if return_packets:
        sent_packets = PacketList()
    try:
        while loop:
            dt0 = None
            for p in x:
                if realtime:
                    ct = time.time()
                    if dt0:
                        st = dt0 + float(p.time) - ct
                        if st > 0:
                            time.sleep(st)
                    else:
                        dt0 = ct - float(p.time)
                s.send(p)
                if return_packets:
                    sent_packets.append(p)
                n += 1
                if verbose:
                    os.write(1, b".")
                time.sleep(inter)
            if loop < 0:
                loop += 1
    except KeyboardInterrupt:
        pass
    if verbose:
        print("\nSent %i packets." % n)
    if return_packets:
        return sent_packets
Exemple #3
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 #4
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 #5
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 #6
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