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
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
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
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
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
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)
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)]
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()
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
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
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)
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")
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
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
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)
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))
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)
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()
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)))
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
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
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 ')
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 ')
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
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
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)
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}
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
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)