Пример #1
0
    def get_new_edge(
        self,
        socket,  # type: _SocketUnion
        config  # type: AutomotiveTestCaseExecutorConfiguration
    ):
        # type: (...) -> Optional[_Edge]
        """
        Basic identification of a new edge. The last response is evaluated.
        If this response packet can modify the state of an Ecu, this new
        state is returned, otherwise None.

        :param socket: Socket to the DUT (unused)
        :param config: Global configuration of the executor (unused)
        :return: tuple of old EcuState and new EcuState, or None
        """
        try:
            state, req, resp, _, _ = cast(ServiceEnumerator, self).results[-1]
        except IndexError:
            return None

        if resp is not None and EcuState.is_modifier_pkt(resp):
            new_state = EcuState.get_modified_ecu_state(resp, req, state)
            if new_state == state:
                return None
            else:
                edge = (state, new_state)
                self._edge_requests[edge] = req
                return edge
        else:
            return None
Пример #2
0
    def __new__(cls,
                name,  # type: str
                bases,  # type: Tuple[type, ...]
                dct  # type: Dict[str, Any]
                ):
        # type: (...) -> Type[ASN1_Class]
        for b in bases:
            for k, v in six.iteritems(b.__dict__):
                if k not in dct and isinstance(v, ASN1Tag):
                    dct[k] = v.clone()

        rdict = {}
        for k, v in six.iteritems(dct):
            if isinstance(v, int):
                v = ASN1Tag(k, v)
                dct[k] = v
                rdict[v] = v
            elif isinstance(v, ASN1Tag):
                rdict[v] = v
        dct["__rdict__"] = rdict

        ncls = cast('Type[ASN1_Class]',
                    type.__new__(cls, name, bases, dct))
        for v in six.itervalues(ncls.__dict__):
            if isinstance(v, ASN1Tag):
                # overwrite ASN1Tag contexts, even cloned ones
                v.context = ncls
        return ncls
Пример #3
0
def sr1flood(
        x,  # type: _PacketIterable
        promisc=None,  # type: Optional[bool]
        filter=None,  # type: Optional[str]
        iface=None,  # type: Optional[_GlobInterfaceType]
        nofilter=0,  # type: int
        *args,  # type: Any
        **kargs  # type: Any
):
    # type: (...) -> Optional[Packet]
    """Flood and receive packets at layer 3 and return only the first answer

    :param prn:      function applied to packets received
    :param verbose:  set verbosity level
    :param nofilter: put 1 to avoid use of BPF filters
    :param filter:   provide a BPF filter
    :param iface:    listen answers only on the given interface
    """
    iface = resolve_iface(iface or conf.iface)
    s = iface.l3socket()(promisc=promisc,
                         filter=filter,
                         nofilter=nofilter,
                         iface=iface)  # noqa: E501
    ans, _ = sndrcvflood(s, x, *args, **kargs)
    s.close()
    if len(ans) > 0:
        return cast(Packet, ans[0][1])
    return None
Пример #4
0
def GMLAN_TransferData(sock,
                       addr,
                       payload,
                       maxmsglen=None,
                       timeout=None,
                       verbose=None,
                       retry=0):  # noqa: E501
    # type: (ISOTPSocket, int, bytes, Optional[int], Optional[int], Optional[bool], int) -> bool  # noqa: E501
    """ Send TransferData message.

    Usually used after calling RequestDownload.

    :param sock: socket to send the message on.
    :param addr: destination memory address on the ECU.
    :param payload: data to be sent.
    :param maxmsglen: maximum length of a single iso-tp message.
                      default: maximum length
    :param timeout: timeout for sending, receiving or sniffing packages.
    :param verbose: set verbosity level.
    :param retry: number of retries in case of failure.
    :return: True on success.
    """
    if verbose is None:
        verbose = conf.verb > 0

    retry = abs(retry)
    startretry = retry

    scheme = conf.contribs['GMLAN']['GMLAN_ECU_AddressingScheme']
    if addr < 0 or addr >= 2**(8 * scheme):
        warning("Error: Invalid address %s for scheme %s", hex(addr),
                str(scheme))
        return False

    # max size of dataRecord according to gmlan protocol
    if maxmsglen is None or maxmsglen <= 0 or maxmsglen > (4093 - scheme):
        maxmsglen = (4093 - scheme)

    maxmsglen = cast(int, maxmsglen)

    for i in range(0, len(payload), maxmsglen):
        retry = startretry
        while True:
            if len(payload[i:]) > maxmsglen:
                transdata = payload[i:i + maxmsglen]
            else:
                transdata = payload[i:]
            pkt = GMLAN() / GMLAN_TD(startingAddress=addr + i,
                                     dataRecord=transdata)
            resp = sock.sr1(pkt, timeout=timeout, verbose=0)
            if _check_response(resp, verbose):
                break
            retry -= 1
            if retry >= 0:
                if verbose:
                    print("Retrying..")
            else:
                return False

    return True
Пример #5
0
 def _iter(obj=cast(SndRcvList, obj)):
     # type: (SndRcvList) -> Iterator[Packet]
     for s, r in obj:
         if s.sent_time:
             s.time = s.sent_time
         yield s
         yield r
Пример #6
0
 def do_dec(
         cls,
         s,  # type: bytes
         context=None,  # type: Optional[Type[ASN1_Class]]
         safe=False  # type: bool
 ):
     # type: (...) -> Tuple[ASN1_Object[Any], bytes]
     if context is not None:
         _context = context
     else:
         _context = cls.tag.context
     cls.check_string(s)
     p, remainder = BER_id_dec(s)
     if p not in _context:  # type: ignore
         t = s
         if len(t) > 18:
             t = t[:15] + b"..."
         raise BER_Decoding_Error("Unknown prefix [%02x] for [%r]" % (p, t),
                                  remaining=s)
     tag = _context[p]  # type: ignore
     codec = cast('Type[BERcodec_Object[_K]]',
                  tag.get_codec(ASN1_Codecs.BER))
     if codec == BERcodec_Object:
         # Value type defined as Unknown
         l, s = BER_num_dec(remainder)
         return ASN1_BADTAG(s[:l]), s[l:]
     return codec.dec(s, _context, safe)
Пример #7
0
    def addfield(self, pkt, s, val):
        # type: (Packet, bytes, Optional[Union[int, float]]) -> bytes
        if not isinstance(pkt, SignalPacket):
            raise Scapy_Exception("Only use SignalFields in a SignalPacket")

        val = self.i2m(pkt, val)

        if self._is_little_endian():
            msb_pos = self.start + self.size - 1
            lsb_pos = self.start
            shift = lsb_pos
            fmt = "<Q"
        else:
            msb_pos = self.start
            lsb_pos = self._lsb_lookup(self.start, self.size)
            shift = (64 - self._msb_lookup(msb_pos) - self.size)
            fmt = ">Q"

        field_len = max(msb_pos, lsb_pos) // 8 + 1
        if len(s) < field_len:
            s += b"\x00" * (field_len - len(s))

        if self._is_float_number():
            int_val = struct.unpack(self.fmt[0] + "I",
                                    struct.pack(self.fmt, val))[0]  # type: int
        elif self._is_signed_number():
            int_val = self._convert_to_unsigned(int(val), self.size)
        else:
            int_val = cast(int, val)

        pkt_val = struct.unpack(fmt, (s + b"\x00" * 8)[:8])[0]
        pkt_val |= int_val << shift
        tmp_s = struct.pack(fmt, pkt_val)
        return tmp_s[:len(s)]
Пример #8
0
 def get_transition_function(self, socket, edge):
     # type: (_SocketUnion, _Edge) -> Optional[_TransitionTuple]
     try:
         test_case = cast(StateGenerator, self.current_test_case)
         return test_case.get_transition_function(socket, edge)
     except AttributeError:
         return None
    def svgdump(self, filename=None, **kargs):
        # type: (Optional[str], **Any) -> None
        """
        svgdump(filename=None, layer_shift=0, rebuild=1)

        Creates an SVG file describing a packet. If filename is not provided a
        temporary file is created and gs is called.

        :param filename: the file's filename
        """
        from scapy.config import conf
        from scapy.utils import get_temp_file, ContextManagerSubprocess
        canvas = self.canvas_dump(**kargs)
        if filename is None:
            fname = cast(str,
                         get_temp_file(autoext=kargs.get("suffix", ".svg")))
            canvas.writeSVGfile(fname)
            if WINDOWS and conf.prog.svgreader is None:
                os.startfile(fname)
            else:
                with ContextManagerSubprocess(conf.prog.svgreader):
                    subprocess.Popen([conf.prog.svgreader, fname])
        else:
            canvas.writeSVGfile(filename)
        print()
Пример #10
0
 def get_generated_test_case(self):
     # type: () -> Optional[AutomotiveTestCaseABC]
     try:
         test_case = cast(TestCaseGenerator, self.current_test_case)
         return test_case.get_generated_test_case()
     except AttributeError:
         return None
Пример #11
0
 def get_new_edge(self, socket, config):
     # type: (_SocketUnion, AutomotiveTestCaseExecutorConfiguration) -> Optional[_Edge]   # noqa: E501
     try:
         test_case = cast(StateGenerator, self.current_test_case)
         return test_case.get_new_edge(socket, config)
     except AttributeError:
         return None
Пример #12
0
 def pre_execute(self, socket, state, global_configuration):
     # type: (_SocketUnion, EcuState, AutomotiveTestCaseExecutorConfiguration) -> None  # noqa: E501
     if cast(ServiceEnumerator, self)._retry_pkt[state] is not None:
         # this is a retry execute. Wait much longer than usual because
         # a required time delay not expired could have been received
         # on the previous attempt
         time.sleep(11)
Пример #13
0
    def add_test_case(self, test_case):
        # type: (Union[AutomotiveTestCaseABC, Type[AutomotiveTestCaseABC], StagedAutomotiveTestCase, Type[StagedAutomotiveTestCase]]) -> None  # noqa: E501
        if inspect.isclass(test_case):
            test_case_class = cast(
                Union[Type[AutomotiveTestCaseABC],
                      Type[StagedAutomotiveTestCase]], test_case)
            if issubclass(test_case_class, StagedAutomotiveTestCase):
                self.add_test_case(test_case_class())  # type: ignore
            elif issubclass(test_case_class, AutomotiveTestCaseABC):
                self.add_test_case(test_case_class())
            else:
                raise TypeError("Provided class is not in "
                                "Union[Type[AutomotiveTestCaseABC], "
                                "Type[StagedAutomotiveTestCase]]")

        elif isinstance(test_case, AutomotiveTestCaseABC):
            self.test_cases.append(test_case)
            self._generate_test_case_config(test_case.__class__)
            if isinstance(test_case, StagedAutomotiveTestCase):
                self.stages.append(test_case)
                for tc in test_case.test_cases:
                    self.staged_test_cases.append(tc)
                    self._generate_test_case_config(tc.__class__)
        else:
            raise TypeError(
                "Provided instance or class of "
                "StagedAutomotiveTestCase or AutomotiveTestCaseABC")
Пример #14
0
 def __new__(
         cls,
         name,  # type: str
         bases,  # type: Tuple[type, ...]
         dct  # type: Dict[str, Any]
 ):
     # type: (...) -> Type['AnsweringMachine[_T]']
     obj = cast('Type[AnsweringMachine[_T]]',
                super(ReferenceAM, cls).__new__(cls, name, bases, dct))
     try:
         import inspect
         obj.__signature__ = inspect.signature(  # type: ignore
             obj.parse_options)
     except (ImportError, AttributeError):
         pass
     if obj.function_name:
         func = lambda obj=obj, *args, **kargs: obj(*args, **kargs)(
         )  # type: ignore  # noqa: E501
         # Inject signature
         func.__name__ = func.__qualname__ = obj.function_name
         try:
             func.__signature__ = obj.__signature__  # type: ignore
         except (AttributeError):
             pass
         globals()[obj.function_name] = func
     return obj
Пример #15
0
    def get_key_pkt(seed, level=1):
        # type: (Packet, int) -> Optional[Packet]

        def key_function_int(s):
            # type: (int) -> int
            return 0xffffffff & ~s

        def key_function_short(s):
            # type: (int) -> int
            return 0xffff & ~s

        try:
            s = seed.securitySeed
        except AttributeError:
            return None

        fmt = None
        key_function = None  # Optional[Callable[[int], int]]

        if len(s) == 2:
            fmt = "H"
            key_function = key_function_short

        if len(s) == 4:
            fmt = "I"
            key_function = key_function_int

        if key_function is not None and fmt is not None:
            key = struct.pack(fmt, key_function(struct.unpack(fmt, s)[0]))
            return cast(
                Packet,
                UDS() / UDS_SA(securityAccessType=level + 1, securityKey=key))
        else:
            return None
Пример #16
0
 def m2i(self, pkt, s):
     # type: (ASN1_Packet, bytes) -> Tuple[ASN1_Object[Any], bytes]
     """
     First we have to retrieve the appropriate choice.
     Then we extract the field/packet, according to this choice.
     """
     if len(s) == 0:
         raise ASN1_Error("ASN1F_CHOICE: got empty string")
     _, s = BER_tagging_dec(s,
                            hidden_tag=self.ASN1_tag,
                            explicit_tag=self.explicit_tag)
     tag, _ = BER_id_dec(s)
     if tag in self.choices:
         choice = self.choices[tag]
     else:
         if tag & 0x1f in self.choices:  # Try resolve only the tag number
             choice = self.choices[tag & 0x1f]
         elif self.flexible_tag:
             choice = ASN1F_field
         else:
             raise ASN1_Error("ASN1F_CHOICE: unexpected field in '%s' "
                              "(tag %s not in possible tags %s)" %
                              (self.name, tag, list(self.choices.keys())))
     if hasattr(choice, "ASN1_root"):
         choice = cast('ASN1_Packet', choice)
         # we don't want to import ASN1_Packet in this module...
         return self.extract_packet(choice, s, _underlayer=pkt)
     elif isinstance(choice, type):
         return choice(self.name, b"").m2i(pkt, s)
     else:
         # XXX check properly if this is an ASN1F_PACKET
         return choice.m2i(pkt, s)
Пример #17
0
 def _get_initial_requests(self, **kwargs):
     # type: (Any) -> Iterable[Packet]
     control_type = kwargs.pop("scan_range", range(0x100))
     return cast(
         Iterable[Packet],
         UDS() / UDS_CC(controlType=control_type,
                        communicationType0=1,
                        communicationType2=15))
Пример #18
0
 def __init__(self, filename, interface=None):
     # type: (str, Optional[Union[List[str], str]]) -> None
     self.filename, self.f = self.open(filename)
     self.ifilter = None  # type: Optional[List[str]]
     if interface is not None:
         if isinstance(interface, six.string_types):
             self.ifilter = [interface]
         else:
             self.ifilter = cast(List[str], interface)
Пример #19
0
    def scan(self, timeout=None):
        # type: (Optional[int]) -> None
        """
        Executes all testcases for a given time.
        :param timeout: Time for execution.
        :return: None
        """
        kill_time = time.time() + (timeout or 0xffffffff)
        while kill_time > time.time():
            test_case_executed = False
            log_interactive.debug("[i] Scan paths %s", self.state_paths)
            for p, test_case in product(self.state_paths,
                                        self.configuration.test_cases):
                log_interactive.info("[i] Scan path %s", p)
                terminate = kill_time < time.time()
                if terminate:
                    log_interactive.debug(
                        "[-] Execution time exceeded. Terminating scan!")
                    break

                final_state = p[-1]
                if test_case.has_completed(final_state):
                    log_interactive.debug("[+] State %s for %s completed",
                                          repr(final_state), test_case)
                    continue

                try:
                    if not self.enter_state_path(p):
                        log_interactive.error("[-] Error entering path %s", p)
                        continue
                    log_interactive.info("[i] Execute %s for path %s",
                                         str(test_case), p)
                    self.execute_test_case(test_case)
                    test_case_executed = True
                except (OSError, ValueError, Scapy_Exception) as e:
                    log_interactive.critical("[-] Exception: %s", e)
                    if self.configuration.debug:
                        raise e
                    if isinstance(e, OSError):
                        log_interactive.critical(
                            "[-] OSError occurred, closing socket")
                        self.socket.close()
                    if cast(SuperSocket, self.socket).closed and \
                            self.reconnect_handler is None:
                        log_interactive.critical(
                            "Socket went down. Need to leave scan")
                        raise e
                finally:
                    self.cleanup_state()

            if not test_case_executed:
                log_interactive.info(
                    "[i] Execute failure or scan completed. Exit scan!")
                break

        self.cleanup_state()
        self.reset_target()
Пример #20
0
    def get_key_pkt(seed, keyfunction, level=1):
        # type: (Packet, Callable[[int], int], int) -> Optional[Packet]
        try:
            s = seed.securitySeed
        except AttributeError:
            return None

        return cast(Packet, GMLAN() / GMLAN_SA(subfunction=level + 1,
                                               securityKey=keyfunction(s)))
Пример #21
0
def srp1(*args, **kargs):
    # type: (*Packet, **Any) -> Optional[Packet]
    """
    Send and receive packets at layer 2 and return only the first answer
    """
    ans, _ = srp(*args, **kargs)
    if len(ans) > 0:
        return cast(Packet, ans[0][1])
    return None
Пример #22
0
 def __getattr__(self, attr):
     # type: (str) -> _K
     try:
         return object.__getattribute__(self, attr)  # type: ignore
     except AttributeError:
         for k, v in six.iteritems(self.d):
             if self.ident(v) == attr:
                 return cast(_K, k)
     raise AttributeError
Пример #23
0
    def __init__(self,
                 can_socket=None,  # type: Optional["CANSocket"]
                 tx_id=0,  # type: int
                 rx_id=0,  # type: int
                 ext_address=None,  # type: Optional[int]
                 rx_ext_address=None,  # type: Optional[int]
                 bs=0,  # type: int
                 stmin=0,  # type: int
                 padding=False,  # type: bool
                 listen_only=False,  # type: bool
                 basecls=ISOTP  # type: Type[Packet]
                 ):
        # type: (...) -> None

        if six.PY3 and LINUX and isinstance(can_socket, six.string_types):
            from scapy.contrib.cansocket_native import NativeCANSocket
            can_socket = NativeCANSocket(can_socket)
        elif isinstance(can_socket, six.string_types):
            raise Scapy_Exception("Provide a CANSocket object instead")

        self.ext_address = ext_address
        self.rx_ext_address = rx_ext_address or ext_address
        self.tx_id = tx_id
        self.rx_id = rx_id

        impl = ISOTPSocketImplementation(
            can_socket,
            tx_id=self.tx_id,
            rx_id=self.rx_id,
            padding=padding,
            ext_address=self.ext_address,
            rx_ext_address=self.rx_ext_address,
            bs=bs,
            stmin=stmin,
            listen_only=listen_only
        )

        # Cast for compatibility to functions from SuperSocket.
        self.ins = cast(socket.socket, impl)
        self.outs = cast(socket.socket, impl)
        self.impl = impl
        self.basecls = basecls
        if basecls is None:
            warning('Provide a basecls ')
Пример #24
0
    def __init__(self,
                 can_socket=None,  # type: Optional["CANSocket"]
                 sid=0,  # type: int
                 did=0,  # type: int
                 extended_addr=None,  # type: Optional[int]
                 extended_rx_addr=None,  # type: Optional[int]
                 rx_block_size=0,  # type: int
                 stmin=0,  # type: int
                 padding=False,  # type: bool
                 listen_only=False,  # type: bool
                 basecls=ISOTP  # type: Type[Packet]
                 ):
        # type: (...) -> None

        if six.PY3 and LINUX and isinstance(can_socket, six.string_types):
            from scapy.contrib.cansocket_native import NativeCANSocket
            can_socket = NativeCANSocket(can_socket)
        elif isinstance(can_socket, six.string_types):
            raise Scapy_Exception("Provide a CANSocket object instead")

        self.exsrc = extended_addr
        self.exdst = extended_rx_addr
        self.src = sid
        self.dst = did

        impl = ISOTPSocketImplementation(
            can_socket,
            src_id=sid,
            dst_id=did,
            padding=padding,
            extended_addr=extended_addr,
            extended_rx_addr=extended_rx_addr,
            rx_block_size=rx_block_size,
            stmin=stmin,
            listen_only=listen_only
        )

        # Cast for compatibility to functions from SuperSocket.
        self.ins = cast(socket.socket, impl)
        self.outs = cast(socket.socket, impl)
        self.impl = impl
        self.basecls = basecls
        if basecls is None:
            warning('Provide a basecls ')
Пример #25
0
    def _compute_statistics(self):
        # type: () -> List[Tuple[str, str, str]]
        data_sets = [("all", self._results)]

        for state in self._state_completed.keys():
            data_sets.append(
                (repr(state), [r for r in self._results if r.state == state]))

        stats = list()  # type: List[Tuple[str, str, str]]

        for desc, data in data_sets:
            answered = [
                cast(_AutomotiveTestCaseFilteredScanResult, r) for r in data
                if r.resp is not None and r.resp_ts is not None
            ]
            unanswered = [r for r in data if r.resp is None]
            answertimes = [
                float(x.resp_ts) - float(x.req_ts) for x in answered
            ]
            answertimes_nr = [
                float(x.resp_ts) - float(x.req_ts) for x in answered
                if x.resp.service == 0x7f
            ]
            answertimes_pr = [
                float(x.resp_ts) - float(x.req_ts) for x in answered
                if x.resp.service != 0x7f
            ]

            nrs = [r.resp for r in answered if r.resp.service == 0x7f]
            stats.append((desc, "num_answered", str(len(answered))))
            stats.append((desc, "num_unanswered", str(len(unanswered))))
            stats.append((desc, "num_negative_resps", str(len(nrs))))

            for postfix, times in zip(
                ["", "_nr", "_pr"],
                [answertimes, answertimes_nr, answertimes_pr]):
                try:
                    ma = str(round(max(times), 5))
                except ValueError:
                    ma = "-"

                try:
                    mi = str(round(min(times), 5))
                except ValueError:
                    mi = "-"

                try:
                    avg = str(round(sum(times) / len(times), 5))
                except (ValueError, ZeroDivisionError):
                    avg = "-"

                stats.append((desc, "answertime_min" + postfix, mi))
                stats.append((desc, "answertime_max" + postfix, ma))
                stats.append((desc, "answertime_avg" + postfix, avg))

        return stats
Пример #26
0
Файл: ecu.py Проект: vtky/scapy
 def __eq__(self, other):
     # type: (object) -> bool
     other = cast(EcuState, other)
     if len(self.__dict__) != len(other.__dict__):
         return False
     try:
         return all(self.__dict__[k] == other.__dict__[k]
                    for k in self.__dict__.keys())
     except KeyError:
         return False
Пример #27
0
def load_ethertypes(filename):
    # type: (Optional[str]) -> EtherDA
    """"Parse /etc/ethertypes and return values as a dictionary.
    If unavailable, use the copy bundled with Scapy."""
    from scapy.libs.ethertypes import DATA
    prot = load_protocols(filename or "Scapy's backup ETHER_TYPES",
                          _fallback=DATA,
                          _integer_base=16,
                          _cls=EtherDA)
    return cast(EtherDA, prot)
Пример #28
0
    def __connector_start_to_rest(rc_start, _rc_stop):
        # type: (AutomotiveTestCaseABC, AutomotiveTestCaseABC) -> Dict[str, Any]  # noqa: E501
        rc_start = cast(UDS_Enumerator, rc_start)
        identifiers_with_pr = [resp.routineIdentifier for _, _, resp, _, _
                               in rc_start.results_with_positive_response]
        scan_range = UDS_RCSelectiveEnumerator.points_to_ranges(
            identifiers_with_pr)

        return {"type_list": [2, 3],
                "scan_range": scan_range}
Пример #29
0
 def __new__(cls,
             name,  # type: str
             bases,  # type: Tuple[type, ...]
             dct  # type: Dict[str, Any]
             ):
     # type: (...) -> Type[Pipe]
     c = cast('Type[Pipe]',
              super(_PipeMeta, cls).__new__(cls, name, bases, dct))
     PipeEngine.pipes[name] = c
     return c
Пример #30
0
    def __init__(self, **kwargs):
        # type: (Dict[str, Any]) -> None

        self.basecls = None  # type: Optional[Type[Packet]]
        try:
            self.basecls = cast(Type[Packet], kwargs.pop("basecls"))
        except KeyError:
            self.basecls = CAN

        self.can_iface = SocketWrapper(**kwargs)