Beispiel #1
0
    def render(self, filename="SystemStateGraph.gv", view=True):
        # type: (str, bool) -> None
        """
        Renders this Graph as PDF, if `graphviz` is installed.

        :param filename: A filename for the rendered PDF.
        :param view: If True, rendered file will be opened.
        """
        try:
            from graphviz import Digraph
        except ImportError:
            log_interactive.info("Please install graphviz.")
            return

        ps = Digraph(name="SystemStateGraph",
                     node_attr={
                         "fillcolor": "lightgrey",
                         "style": "filled",
                         "shape": "box"
                     },
                     graph_attr={"concentrate": "true"})
        for n in self.nodes:
            ps.node(str(n))

        for e, f in self.__transition_functions.items():
            try:
                desc = "" if f is None else f[1]["desc"]
            except (AttributeError, KeyError):
                desc = ""
            ps.edge(str(e[0]), str(e[1]), label=desc)

        ps.render(filename, view=view)
Beispiel #2
0
    def get_security_access(self, sock, level=1, seed_pkt=None):
        # type: (_SocketUnion, int, Optional[Packet]) -> bool
        log_interactive.info("Try bootloader security access for level %d" %
                             level)
        if seed_pkt is None:
            seed_pkt = self.get_seed_pkt(sock, level)
            if not seed_pkt:
                return False

        if not any(seed_pkt.securitySeed):
            return False

        key_pkt = self.get_key_pkt(seed_pkt, level)
        if key_pkt is None:
            return False

        try:
            res = sock.sr1(key_pkt, timeout=5, verbose=False)
            if sock.closed:
                log_interactive.critical("[-] Socket closed during scan.")
                raise Scapy_Exception("Socket closed during scan")
        except (OSError, ValueError, Scapy_Exception) as e:
            try:
                last_seed_req = self._results[-1].req
                last_state = self._results[-1].state
                if not self._populate_retry(last_state, last_seed_req):
                    log_interactive.critical(
                        "[-] Exception during retry. This is bad")
            except IndexError:
                log_interactive.warning("[-] Couldn't populate retry.")
            raise e

        return self.evaluate_security_access_response(res, seed_pkt, key_pkt)
def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, file_cache=False, iface=None, replay_args=None,  # noqa: E501
              parse_results=False):
    """Send packets at layer 2 using tcpreplay for performance

    :param pps:  packets per second
    :param mpbs: MBits per second
    :param realtime: use packet's timestamp, bending time with real-time value
    :param loop: number of times to process the packet list
    :param file_cache: cache packets in RAM instead of reading from
        disk at each iteration
    :param iface: output interface
    :param replay_args: List of additional tcpreplay args (List[str])
    :param parse_results: Return a dictionary of information
        outputted by tcpreplay (default=False)
    :returns: stdout, stderr, command used
    """
    if iface is None:
        iface = conf.iface
    argv = [conf.prog.tcpreplay, "--intf1=%s" % network_name(iface)]
    if pps is not None:
        argv.append("--pps=%i" % pps)
    elif mbps is not None:
        argv.append("--mbps=%f" % mbps)
    elif realtime is not None:
        argv.append("--multiplier=%f" % realtime)
    else:
        argv.append("--topspeed")

    if loop:
        argv.append("--loop=%i" % loop)
    if file_cache:
        argv.append("--preload-pcap")

    # Check for any additional args we didn't cover.
    if replay_args is not None:
        argv.extend(replay_args)

    f = get_temp_file()
    argv.append(f)
    wrpcap(f, x)
    results = None
    with ContextManagerSubprocess(conf.prog.tcpreplay):
        try:
            cmd = subprocess.Popen(argv, stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        except KeyboardInterrupt:
            log_interactive.info("Interrupted by user")
        except Exception:
            os.unlink(f)
            raise
        else:
            stdout, stderr = cmd.communicate()
            if stderr:
                log_runtime.warning(stderr.decode())
            if parse_results:
                results = _parse_tcpreplay_result(stdout, stderr, argv)
            elif conf.verb > 2:
                log_runtime.info(stdout.decode())
    os.unlink(f)
    return results
Beispiel #4
0
def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, file_cache=False, iface=None):
    """Send packets at layer 2 using tcpreplay for performance
    pps:  packets per second
    mpbs: MBits per second
    realtime: use packet's timestamp, bending time with realtime value
    loop: number of times to process the packet list
    file_cache: cache packets in RAM instead of reading from disk at each iteration
    iface: output interface """
    if iface is None:
        iface = conf.iface
    argv = [conf.prog.tcpreplay, "--intf1=%s" % iface ]
    if pps is not None:
        argv.append("--pps=%i" % pps)
    elif mbps is not None:
        argv.append("--mbps=%f" % mbps)
    elif realtime is not None:
        argv.append("--multiplier=%f" % realtime)
    else:
        argv.append("--topspeed")

    if loop:
        argv.append("--loop=%i" % loop)
        if file_cache:
            argv.append("--enable-file-cache")

    f = get_temp_file()
    argv.append(f)
    wrpcap(f, x)
    try:
        subprocess.check_call(argv)
    except KeyboardInterrupt:
        log_interactive.info("Interrupted by user")
    except Exception,e:
        log_interactive.error("while trying to exec [%s]: %s" % (argv[0],e))
Beispiel #5
0
    def enter_state(self, prev_state, next_state):
        # type: (EcuState, EcuState) -> bool
        """
        Obtains a transition function from the system state graph and executes
        it. On success, the cleanup function is added for a later cleanup of
        the new state.
        :param prev_state: Current state
        :param next_state: Desired state
        :return: True, if state could be changed successful
        """
        edge = (prev_state, next_state)
        funcs = self.state_graph.get_transition_tuple_for_edge(edge)

        if funcs is None:
            log_interactive.error("[!] No transition function for %s", edge)
            return False

        trans_func, trans_kwargs, clean_func = funcs
        state_changed = trans_func(self.socket, self.configuration,
                                   trans_kwargs)
        if state_changed:
            self.target_state = next_state

            if clean_func is not None:
                self.cleanup_functions += [clean_func]
            return True
        else:
            log_interactive.info("[-] Transition for edge %s failed", edge)
            return False
    def has_completed(self, state):
        # type: (EcuState) -> bool
        if not (self.current_test_case.has_completed(state)
                and self.current_test_case.completed):
            # current test_case not fully completed
            # reset completion delay, since new states could have been appeared
            self.__completion_delay = 0
            return False

        # current stage is finished. We have to increase the stage
        if self.__completion_delay < StagedAutomotiveTestCase.__delay_stages:
            # First we wait five more iteration of the executor
            # Maybe one more execution reveals new states of other
            # test_cases
            self.__completion_delay += 1
            return False

        # current test_case is fully completed
        elif self.__stage_index == len(self.__test_cases) - 1:
            # this test_case was the last test_case... nothing to do
            return True

        else:
            # We waited more iterations and no new state appeared,
            # let's enter the next stage
            log_interactive.info("[+] Staged AutomotiveTestCase %s completed",
                                 self.current_test_case.__class__.__name__)
            self.__stage_index += 1
            self.__completion_delay = 0
        return False
Beispiel #7
0
def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, file_cache=False, iface=None, replay_args=None,  # noqa: E501
              parse_results=False):
    """Send packets at layer 2 using tcpreplay for performance
    pps:  packets per second
    mpbs: MBits per second
    realtime: use packet's timestamp, bending time with real-time value
    loop: number of times to process the packet list
    file_cache: cache packets in RAM instead of reading from disk at each iteration  # noqa: E501
    iface: output interface
    replay_args: List of additional tcpreplay args (List[str])
    parse_results: Return a dictionary of information outputted by tcpreplay (default=False)  # noqa: E501
    :returns stdout, stderr, command used"""
    if iface is None:
        iface = conf.iface
    argv = [conf.prog.tcpreplay, "--intf1=%s" % iface]
    if pps is not None:
        argv.append("--pps=%i" % pps)
    elif mbps is not None:
        argv.append("--mbps=%f" % mbps)
    elif realtime is not None:
        argv.append("--multiplier=%f" % realtime)
    else:
        argv.append("--topspeed")

    if loop:
        argv.append("--loop=%i" % loop)
    if file_cache:
        argv.append("--preload-pcap")

    # Check for any additional args we didn't cover.
    if replay_args is not None:
        argv.extend(replay_args)

    f = get_temp_file()
    argv.append(f)
    wrpcap(f, x)
    results = None
    try:
        log_runtime.info(argv)
        with subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as cmd:  # noqa: E501
            stdout, stderr = cmd.communicate()
            log_runtime.info(stdout)
            log_runtime.warning(stderr)
            if parse_results:
                results = _parse_tcpreplay_result(stdout, stderr, argv)

    except KeyboardInterrupt:
        log_interactive.info("Interrupted by user")
    except Exception:
        if conf.interactive:
            log_interactive.error("Cannot execute [%s]", argv[0], exc_info=True)  # noqa: E501
        else:
            raise
    finally:
        os.unlink(f)
        return results
Beispiel #8
0
def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, file_cache=False, iface=None, replay_args=None,  # noqa: E501
              parse_results=False):
    """Send packets at layer 2 using tcpreplay for performance
    pps:  packets per second
    mpbs: MBits per second
    realtime: use packet's timestamp, bending time with real-time value
    loop: number of times to process the packet list
    file_cache: cache packets in RAM instead of reading from disk at each iteration  # noqa: E501
    iface: output interface
    replay_args: List of additional tcpreplay args (List[str])
    parse_results: Return a dictionary of information outputted by tcpreplay (default=False)  # noqa: E501
    :returns stdout, stderr, command used"""
    if iface is None:
        iface = conf.iface
    argv = [conf.prog.tcpreplay, "--intf1=%s" % iface]
    if pps is not None:
        argv.append("--pps=%i" % pps)
    elif mbps is not None:
        argv.append("--mbps=%f" % mbps)
    elif realtime is not None:
        argv.append("--multiplier=%f" % realtime)
    else:
        argv.append("--topspeed")

    if loop:
        argv.append("--loop=%i" % loop)
    if file_cache:
        argv.append("--preload-pcap")

    # Check for any additional args we didn't cover.
    if replay_args is not None:
        argv.extend(replay_args)

    f = get_temp_file()
    argv.append(f)
    wrpcap(f, x)
    results = None
    with ContextManagerSubprocess("sendpfast()", conf.prog.tcpreplay):
        try:
            cmd = subprocess.Popen(argv, stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        except KeyboardInterrupt:
            log_interactive.info("Interrupted by user")
        except Exception:
            os.unlink(f)
            raise
        else:
            stdout, stderr = cmd.communicate()
            if stderr:
                log_runtime.warning(stderr.decode())
            if parse_results:
                results = _parse_tcpreplay_result(stdout, stderr, argv)
            elif conf.verb > 2:
                log_runtime.info(stdout.decode())
    os.unlink(f)
    return results
Beispiel #9
0
    def reset_target(self):
        log_interactive.info("[i] Target reset")
        self.reset_tps()
        if self.reset_handler:
            try:
                self.reset_handler(self)
            except TypeError:
                self.reset_handler()

        self.target_state = ECU_State()
Beispiel #10
0
def save_session(fname="", session=None, pickleProto=-1):
    # type: (str, Optional[Dict[str, Any]], int) -> None
    """Save current Scapy session to the file specified in the fname arg.

    params:
     - fname: file to save the scapy session in
     - session: scapy session to use. If None, the console one will be used
     - pickleProto: pickle proto version (default: -1 = latest)"""
    from scapy import utils
    from scapy.config import conf, ConfClass
    if not fname:
        fname = conf.session
        if not fname:
            conf.session = fname = utils.get_temp_file(keep=True)
    log_interactive.info("Saving session into [%s]", fname)

    if not session:
        try:
            from IPython import get_ipython
            session = get_ipython().user_ns
        except Exception:
            session = six.moves.builtins.__dict__["scapy_session"]

    if not session:
        log_interactive.error("No session found ?!")
        return

    ignore = session.get("_scpybuiltins", [])
    hard_ignore = ["scapy_session", "In", "Out"]
    to_be_saved = session.copy()

    for k in list(to_be_saved):
        i = to_be_saved[k]
        if k[0] == "_":
            del(to_be_saved[k])
        elif hasattr(i, "__module__") and i.__module__.startswith("IPython"):
            del(to_be_saved[k])
        elif isinstance(i, ConfClass):
            del(to_be_saved[k])
        elif k in ignore or k in hard_ignore:
            del(to_be_saved[k])
        elif isinstance(i, (type, types.ModuleType)):
            if k[0] != "_":
                log_interactive.warning("[%s] (%s) can't be saved.", k,
                                        type(to_be_saved[k]))
            del(to_be_saved[k])

    try:
        os.rename(fname, fname + ".bak")
    except OSError:
        pass

    f = gzip.open(fname, "wb")
    six.moves.cPickle.dump(to_be_saved, f, pickleProto)
    f.close()
Beispiel #11
0
 def evaluate_security_access_response(res, seed, key):
     # type: (Optional[Packet], Packet, Optional[Packet]) -> bool
     if res is None or res.service == 0x7f:
         log_interactive.debug(repr(seed))
         log_interactive.debug(repr(key))
         log_interactive.debug(repr(res))
         log_interactive.info("Security access error!")
         return False
     else:
         log_interactive.info("Security access granted!")
         return True
Beispiel #12
0
    def execute(self, socket, state, **kwargs):
        # type: (_SocketUnion, EcuState, Any) -> None
        self.check_kwargs(kwargs)
        timeout = kwargs.pop('timeout', 1)
        execution_time = kwargs.pop("execution_time", 1200)

        state_block_list = kwargs.get('state_block_list', list())

        if state_block_list and state in state_block_list:
            self._state_completed[state] = True
            log_interactive.debug("[i] State %s in block list!", repr(state))
            return

        state_allow_list = kwargs.get('state_allow_list', list())

        if state_allow_list and state not in state_allow_list:
            self._state_completed[state] = True
            log_interactive.debug("[i] State %s not in allow list!",
                                  repr(state))
            return

        it = self.__get_request_iterator(state, **kwargs)

        # log_interactive.debug("[i] Using iterator %s in state %s", it, state)

        start_time = time.time()
        log_interactive.debug("[i] Start execution of enumerator: %s",
                              time.ctime(start_time))

        for req in it:
            res = self.sr1_with_retry_on_error(req, socket, state, timeout)

            self._store_result(state, req, res)

            if self._evaluate_response(state, req, res, **kwargs):
                log_interactive.debug("[i] Stop test_case execution because "
                                      "of response evaluation")
                return

            if (start_time + execution_time) < time.time():
                log_interactive.debug(
                    "[i] Finished execution time of enumerator: %s",
                    time.ctime())
                return

        log_interactive.info("[i] Finished iterator execution")
        self._state_completed[state] = True
        log_interactive.debug("[i] States completed %s",
                              repr(self._state_completed))
Beispiel #13
0
    def reconnect(self):
        # type: () -> None
        if self.reconnect_handler:
            try:
                self.socket.close()
            except Exception as e:
                log_interactive.debug("[i] Exception '%s' during socket.close",
                                      e)

            log_interactive.info("[i] Target reconnect")
            socket = self.reconnect_handler()
            if not isinstance(socket, SingleConversationSocket):
                self.socket = SingleConversationSocket(socket)
            else:
                self.socket = socket
Beispiel #14
0
def save_session(fname=None, session=None, pickleProto=-1):
    """Save current Scapy session to the file specified in the fname arg.

    params:
     - fname: file to save the scapy session in
     - session: scapy session to use. If None, the console one will be used
     - pickleProto: pickle proto version (default: -1 = latest)"""
    from scapy import utils
    from scapy.config import conf, ConfClass
    if fname is None:
        fname = conf.session
        if not fname:
            conf.session = fname = utils.get_temp_file(keep=True)
    log_interactive.info("Use [%s] as session file" % fname)

    if session is None:
        try:
            session = get_ipython().user_ns
        except Exception:
            session = six.moves.builtins.__dict__["scapy_session"]

    to_be_saved = session.copy()
    if "__builtins__" in to_be_saved:
        del (to_be_saved["__builtins__"])

    for k in list(to_be_saved):
        i = to_be_saved[k]
        if hasattr(i, "__module__") and (
                k[0] == "_"
                or i.__module__.startswith("IPython")):  # noqa: E501
            del (to_be_saved[k])
        if isinstance(i, ConfClass):
            del (to_be_saved[k])
        elif isinstance(i, (type, type, types.ModuleType)):
            if k[0] != "_":
                log_interactive.error("[%s] (%s) can't be saved.", k,
                                      type(to_be_saved[k]))  # noqa: E501
            del (to_be_saved[k])

    try:
        os.rename(fname, fname + ".bak")
    except OSError:
        pass

    f = gzip.open(fname, "wb")
    six.moves.cPickle.dump(to_be_saved, f, pickleProto)
    f.close()
    del f
Beispiel #15
0
 def run(self):
     log_interactive.info("Pipe engine thread started.")
     try:
         for p in self.active_pipes:
             p.start()
         sources = self.active_sources
         sources.add(self)
         exhausted = set([])
         RUN = True
         STOP_IF_EXHAUSTED = False
         while RUN and (not STOP_IF_EXHAUSTED or len(sources) > 1):
             fds = select_objects(sources,
                                  2,
                                  customTypes=(AutoSource, PipeEngine))
             for fd in fds:
                 if fd is self:
                     cmd = self._read_cmd()
                     if cmd == "X":
                         RUN = False
                         break
                     elif cmd == "B":
                         STOP_IF_EXHAUSTED = True
                     elif cmd == "A":
                         sources = self.active_sources - exhausted
                         sources.add(self)
                     else:
                         warning(
                             "Unknown internal pipe engine command: %r. Ignoring."
                             % cmd)
                 elif fd in sources:
                     try:
                         fd.deliver()
                     except Exception as e:
                         log_interactive.exception(
                             "piping from %s failed: %s" % (fd.name, e))
                     else:
                         if fd.exhausted():
                             exhausted.add(fd)
                             sources.remove(fd)
     except KeyboardInterrupt:
         pass
     finally:
         try:
             for p in self.active_pipes:
                 p.stop()
         finally:
             self.thread_lock.release()
             log_interactive.info("Pipe engine thread stopped.")
Beispiel #16
0
    def _prepare_negative_response_blacklist(self):
        # type: () -> None
        nrc_dict = defaultdict(int)  # type: Dict[int, int]
        for nr in self.results_with_negative_response:
            nrc_dict[self._get_negative_response_code(nr.resp)] += 1

        total_nr_count = len(self.results_with_negative_response)
        for nrc, nr_count in nrc_dict.items():
            if nrc not in self.negative_response_blacklist and \
                    nr_count > 30 and (nr_count / total_nr_count) > 0.3:
                log_interactive.info("Added NRC 0x%02x to filter", nrc)
                self.negative_response_blacklist.append(nrc)

            if nrc in self.negative_response_blacklist and nr_count < 10:
                log_interactive.info("Removed NRC 0x%02x to filter", nrc)
                self.negative_response_blacklist.remove(nrc)
Beispiel #17
0
    def get_security_access(sock, level=1, seed_pkt=None):
        # type: (_SocketUnion, int, Optional[Packet]) -> bool
        log_interactive.info("Try bootloader security access for level %d" %
                             level)
        if seed_pkt is None:
            seed_pkt = UDS_SAEnumerator.get_seed_pkt(sock, level)
            if not seed_pkt:
                return False

        key_pkt = UDS_SA_XOR_Enumerator.get_key_pkt(seed_pkt, level)
        if key_pkt is None:
            return False

        res = sock.sr1(key_pkt, timeout=5, verbose=False)
        return UDS_SA_XOR_Enumerator.evaluate_security_access_response(
            res, seed_pkt, key_pkt)
Beispiel #18
0
    def execute(self, socket, state, **kwargs):
        # type: (_SocketUnion, EcuState, Any) -> None
        timeout = kwargs.pop('timeout', 1)
        execution_time = kwargs.pop("execution_time", 1200)

        it = self.__get_request_iterator(state, **kwargs)

        # log_interactive.debug("[i] Using iterator %s in state %s", it, state)

        start_time = time.time()
        log_interactive.debug("[i] Start execution of enumerator: %s",
                              time.ctime(start_time))

        for req in it:
            try:
                res = socket.sr1(req, timeout=timeout, verbose=False)
            except (OSError, ValueError, Scapy_Exception) as e:
                if self._retry_pkt[state] is None:
                    log_interactive.debug(
                        "[-] Exception '%s' in execute. Prepare for retry", e)
                    self._retry_pkt[state] = req
                else:
                    log_interactive.critical(
                        "[-] Exception during retry. This is bad")
                raise e

            if socket.closed:
                log_interactive.critical("[-] Socket closed during scan.")
                return

            self._store_result(state, req, res)

            if self._evaluate_response(state, req, res, **kwargs):
                log_interactive.debug("[i] Stop test_case execution because "
                                      "of response evaluation")
                return

            if (start_time + execution_time) < time.time():
                log_interactive.debug(
                    "[i] Finished execution time of enumerator: %s",
                    time.ctime())
                return

        log_interactive.info("[i] Finished iterator execution")
        self._state_completed[state] = True
        log_interactive.debug("[i] States completed %s",
                              repr(self._state_completed))
Beispiel #19
0
    def cleanup_state(self):
        # type: () -> None
        """
        Executes all collected cleanup functions from a traversed path
        :return: None
        """
        for f in self.cleanup_functions:
            if not callable(f):
                continue
            try:
                if not f(self.socket, self.configuration):
                    log_interactive.info("[-] Cleanup function %s failed",
                                         repr(f))
            except (OSError, ValueError, Scapy_Exception) as e:
                log_interactive.critical("[!] Exception during cleanup: %s", e)

        self.cleanup_functions = list()
Beispiel #20
0
 def run(self):
     log_interactive.info("Pipe engine thread started.")
     try:
         for p in self.active_pipes:
             p.start()
         sources = self.active_sources
         sources.add(self.__fdr)
         exhausted = set([])
         RUN = True
         STOP_IF_EXHAUSTED = False
         while RUN and (not STOP_IF_EXHAUSTED or len(sources) > 1):
             fds, fdo, fde = select.select(sources, [], [])
             for fd in fds:
                 if fd is self.__fdr:
                     cmd = os.read(self.__fdr, 1)
                     if cmd == "X":
                         RUN = False
                         break
                     elif cmd == "B":
                         STOP_IF_EXHAUSTED = True
                     elif cmd == "A":
                         sources = self.active_sources-exhausted
                         sources.add(self.__fdr)
                     else:
                         warning(
                             "Unknown internal pipe engine command: %r. Ignoring." % cmd)
                 elif fd in sources:
                     try:
                         fd.deliver()
                     except Exception, e:
                         log_interactive.exception(
                             "piping from %s failed: %s" % (fd.name, e))
                     else:
                         if fd.exhausted():
                             exhausted.add(fd)
                             sources.remove(fd)
     except KeyboardInterrupt:
         pass
     finally:
         try:
             for p in self.active_pipes:
                 p.stop()
         finally:
             self.thread_lock.release()
             log_interactive.info("Pipe engine thread stopped.")
Beispiel #21
0
def save_session(fname=None, session=None, pickleProto=-1):
    """Save current Scapy session to the file specified in the fname arg.

    params:
     - fname: file to save the scapy session in
     - session: scapy session to use. If None, the console one will be used
     - pickleProto: pickle proto version (default: -1 = latest)"""
    from scapy import utils
    if fname is None:
        fname = conf.session
        if not fname:
            conf.session = fname = utils.get_temp_file(keep=True)
    log_interactive.info("Use [%s] as session file" % fname)

    if session is None:
        try:
            session = get_ipython().user_ns
        except:
            session = six.moves.builtins.__dict__["scapy_session"]

    to_be_saved = session.copy()
    if "__builtins__" in to_be_saved:
        del(to_be_saved["__builtins__"])

    for k in list(to_be_saved):
        i = to_be_saved[k]
        if hasattr(i, "__module__") and (k[0] == "_" or i.__module__.startswith("IPython")):
            del(to_be_saved[k])
        if isinstance(i, ConfClass):
            del(to_be_saved[k])
        elif isinstance(i, (type, type, types.ModuleType)):
            if k[0] != "_":
                log_interactive.error("[%s] (%s) can't be saved.", k, type(to_be_saved[k]))
            del(to_be_saved[k])

    try:
         os.rename(fname, fname+".bak")
    except OSError:
         pass
    
    f=gzip.open(fname,"wb")
    six.moves.cPickle.dump(to_be_saved, f, pickleProto)
    f.close()
    del f
Beispiel #22
0
    def get_security_access(sock, level=1, seed_pkt=None, keyfunction=None):
        # type: (_SocketUnion, int, Optional[Packet], Optional[Callable[[int], int]]) -> bool  # noqa: E501
        log_interactive.info("Try bootloader security access for level %d" %
                             level)
        if seed_pkt is None:
            seed_pkt = GMLAN_SAEnumerator.get_seed_pkt(sock, level)
            if not seed_pkt:
                return False

        if keyfunction is None:
            return False

        key_pkt = GMLAN_SAEnumerator.get_key_pkt(seed_pkt, keyfunction, level)
        if key_pkt is None:
            return False

        res = sock.sr1(key_pkt, timeout=5, verbose=False)
        return GMLAN_SAEnumerator.evaluate_security_access_response(
            res, seed_pkt, key_pkt)
Beispiel #23
0
    def get_seed_pkt(sock, level=1):
        # type: (_SocketUnion, int) -> Optional[Packet]
        req = GMLAN() / GMLAN_SA(subfunction=level)
        for _ in range(10):
            seed = sock.sr1(req, timeout=5, verbose=False)
            if seed is None:
                return None
            elif seed.service == 0x7f and \
                    GMLAN_Enumerator._get_negative_response_code(seed) != 0x37:
                log_interactive.info("Security access no seed! NR: %s",
                                     repr(seed))
                return None

            elif seed.service == 0x7f and \
                    GMLAN_Enumerator._get_negative_response_code(seed) == 0x37:
                log_interactive.info("Security access retry to get seed")
                time.sleep(10)
                continue
            else:
                return seed
        return None
Beispiel #24
0
    def get_seed_pkt(sock, level=1, record=b""):
        # type: (_SocketUnion, int, bytes) -> Optional[Packet]
        req = UDS() / UDS_SA(securityAccessType=level,
                             securityAccessDataRecord=record)
        for _ in range(10):
            seed = sock.sr1(req, timeout=5, verbose=False)
            if seed is None:
                return None
            elif seed.service == 0x7f and \
                    UDS_Enumerator._get_negative_response_code(seed) != 0x37:
                log_interactive.info("Security access no seed! NR: %s",
                                     repr(seed))
                return None

            elif seed.service == 0x7f and seed.negativeResponseCode == 0x37:
                log_interactive.info("Security access retry to get seed")
                time.sleep(10)
                continue
            else:
                return seed
        return None
Beispiel #25
0
 def _activate_routing(
         self,
         source_address,  # type: int
         target_address,  # type: int
         activation_type,  # type: int
         reserved_oem=b""  # type: bytes
 ):  # type: (...) -> None
     resp = self.sr1(DoIP(payload_type=0x5,
                          activation_type=activation_type,
                          source_address=source_address,
                          reserved_oem=reserved_oem),
                     verbose=False,
                     timeout=1)
     if resp and resp.payload_type == 0x6 and \
             resp.routing_activation_response == 0x10:
         self.target_address = target_address or \
             resp.logical_address_doip_entity
         log_interactive.info(
             "Routing activation successful! Target address set to: 0x%x",
             self.target_address)
     else:
         log_interactive.error("Routing activation failed! Response: %s",
                               repr(resp))
Beispiel #26
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()
Beispiel #27
0
 def scan(self):
     scan_complete = False
     while not scan_complete:
         scan_complete = True
         log_interactive.info("[i] Scan paths %s", self.get_state_paths())
         for p in self.get_state_paths():
             log_interactive.info("[i] Scan path %s", p)
             final_state = p[-1]
             for e in self.enumerators:
                 if e.state_completed[final_state]:
                     log_interactive.debug("[+] State %s for %s completed",
                                           repr(final_state), e)
                     continue
                 if not self.enter_state_path(p):
                     log_interactive.error("[-] Error entering path %s", p)
                     continue
                 log_interactive.info("[i] EXECUTE SCAN %s for path %s",
                                      e.__class__.__name__, p)
                 self.execute_enumerator(e)
                 scan_complete = False
     self.reset_target()
Beispiel #28
0
 def vprint(self, s=""):
     if self.verbose:
         if conf.interactive:
             log_interactive.info("> %s", s)
         else:
             print("> %s" % s)
Beispiel #29
0
 def vprint(self, s=""):
     if self.verbose:
         log_interactive.info("> %s", s)
Beispiel #30
0
    def execute(self, socket, state, **kwargs):
        # type: (_SocketUnion, EcuState, Any) -> None
        self.check_kwargs(kwargs)
        timeout = kwargs.pop('timeout', 1)
        execution_time = kwargs.pop("execution_time", 1200)

        state_block_list = kwargs.get('state_block_list', list())

        if state_block_list and state in state_block_list:
            self._state_completed[state] = True
            log_interactive.debug("[i] State %s in block list!", repr(state))
            return

        state_allow_list = kwargs.get('state_allow_list', list())

        if state_allow_list and state not in state_allow_list:
            self._state_completed[state] = True
            log_interactive.debug("[i] State %s not in allow list!",
                                  repr(state))
            return

        it = self.__get_request_iterator(state, **kwargs)

        # log_interactive.debug("[i] Using iterator %s in state %s", it, state)

        start_time = time.time()
        log_interactive.debug("[i] Start execution of enumerator: %s",
                              time.ctime(start_time))

        for req in it:
            try:
                res = socket.sr1(req, timeout=timeout, verbose=False)
            except (OSError, ValueError, Scapy_Exception) as e:
                if not self._populate_retry(state, req):
                    log_interactive.critical(
                        "[-] Exception during retry. This is bad")
                raise e

            if socket.closed:
                if not self._populate_retry(state, req):
                    log_interactive.critical(
                        "[-] Socket closed during retry. This is bad")
                log_interactive.critical("[-] Socket closed during scan.")
                raise Scapy_Exception("Socket closed during scan")

            self._store_result(state, req, res)

            if self._evaluate_response(state, req, res, **kwargs):
                log_interactive.debug("[i] Stop test_case execution because "
                                      "of response evaluation")
                return

            if (start_time + execution_time) < time.time():
                log_interactive.debug(
                    "[i] Finished execution time of enumerator: %s",
                    time.ctime())
                return

        log_interactive.info("[i] Finished iterator execution")
        self._state_completed[state] = True
        log_interactive.debug("[i] States completed %s",
                              repr(self._state_completed))
Beispiel #31
0
 def vprint(self, s=""):
     if self.verbose:
         log_interactive.info("> %s", s)
Beispiel #32
0
 def reset_target(self):
     # type: () -> None
     log_interactive.info("[i] Target reset")
     if self.reset_handler:
         self.reset_handler()
     self.target_state = self.__initial_ecu_state
Beispiel #33
0
    def post_execute(self, socket, state, global_configuration):
        # type: (_SocketUnion, EcuState, AutomotiveTestCaseExecutorConfiguration) -> None  # noqa: E501
        if not self._state_completed[state]:
            return

        if not self.random_probe_finished[state]:
            log_interactive.info("[i] Random memory probing finished")
            self.random_probe_finished[state] = True
            for tup in [
                    t for t in self.results_with_positive_response
                    if t.state == state
            ]:
                self.points_of_interest[state].append(
                    (tup.req.memoryAddress, True))
                self.points_of_interest[state].append(
                    (tup.req.memoryAddress, False))

        if not len(self.points_of_interest[state]):
            return

        log_interactive.info(
            "[i] Create %d memory points for sequential probing" %
            len(self.points_of_interest[state]))

        tested_addrs = [tup.req.memoryAddress for tup in self.results]
        pos_addrs = [
            tup.req.memoryAddress
            for tup in self.results_with_positive_response
            if tup.state == state
        ]

        new_requests = list()
        new_points_of_interest = list()

        for poi, upward in self.points_of_interest[state]:
            if poi not in pos_addrs:
                continue
            temp_new_requests = list()
            for i in range(self.probe_width,
                           self.sequential_probes_len + self.probe_width,
                           self.probe_width):
                if upward:
                    new_addr = min(poi + i, self.highest_possible_addr)
                else:
                    new_addr = max(poi - i, 0)

                if new_addr not in tested_addrs:
                    pkt = GMLAN() / GMLAN_RMBA(memoryAddress=new_addr,
                                               memorySize=self.probe_width)
                    temp_new_requests.append(pkt)

            if len(temp_new_requests):
                new_points_of_interest.append(
                    (temp_new_requests[-1].memoryAddress, upward))
                new_requests += temp_new_requests

        self.points_of_interest[state] = list()

        if len(new_requests):
            self._state_completed[state] = False
            self._request_iterators[state] = new_requests
            self.points_of_interest[state] = new_points_of_interest
            log_interactive.info("[i] Created %d pkts for sequential probing" %
                                 len(new_requests))