Example #1
0
def dcm_discovery(args):
    """
    Scans for diagnostics support by sending session control against different arbitration IDs.

    :param: args: A namespace containing min and max
    """
    min_id = int_from_str_base(args.min)
    max_id = int_from_str_base(args.max)
    with CanActions() as can_wrap:
        print("Starting diagnostics service discovery")

        def response_analyser_wrapper(arb_id):
            print "\rSending diagnostics Tester Present to 0x{0:04x}".format(arb_id),
            stdout.flush()

            def response_analyser(msg):
                # Catch both ok and negative response
                if msg.data[1] in [0x50, 0x7F]:
                    print("\nFound diagnostics at arbitration ID 0x{0:04x}, "
                          "reply at 0x{1:04x}".format(arb_id, msg.arbitration_id))
                    can_wrap.bruteforce_stop()
            return response_analyser

        def none_found(s):
            print("\nDiagnostics service could not be found: {0}".format(s))

        # Message to bruteforce - [length, session control, default session]
        message = insert_message_length([0x10, 0x01])
        can_wrap.bruteforce_arbitration_id(message, response_analyser_wrapper,
                                           min_id=min_id, max_id=max_id, callback_end=none_found)
Example #2
0
def dcm_discovery(args):
    """
    Scans for diagnostics support by sending session control against different arbitration IDs.

    :param: args: A namespace containing min and max
    """
    min_id = int_from_str_base(args.min)
    max_id = int_from_str_base(args.max)
    no_stop = args.nostop

    class Diagnostics:
        found = False

    with CanActions() as can_wrap:
        print("Starting diagnostics service discovery")

        def response_analyser_wrapper(arb_id):
            print "\rSending Diagnostic Session Control to 0x{0:04x}".format(
                arb_id),
            stdout.flush()

            def response_analyser(msg):
                # Catch both ok and negative response
                if len(msg.data) >= 2 and msg.data[1] in [0x50, 0x7F]:
                    Diagnostics.found = True
                    print(
                        "\nFound diagnostics at arbitration ID 0x{0:04x}, "
                        "reply at 0x{1:04x}".format(arb_id,
                                                    msg.arbitration_id))
                    if no_stop == False:
                        can_wrap.bruteforce_stop()

            return response_analyser

        def discovery_finished(s):
            if Diagnostics.found:
                print("\n{0}".format(s))
            else:
                print(
                    "\nDiagnostics service could not be found: {0}".format(s))

        # Message to bruteforce - [length, session control, default session]
        message = insert_message_length([0x10, 0x01])
        can_wrap.bruteforce_arbitration_id(message,
                                           response_analyser_wrapper,
                                           min_id=min_id,
                                           max_id=max_id,
                                           callback_end=discovery_finished)
Example #3
0
def subfunc_discovery(args):
    """
    Scans for subfunctions of a given service.

    :param args: A namespace containing src, dst, service, show and i
    """
    send_arb_id = int_from_str_base(args.src)
    rcv_arb_id = int_from_str_base(args.dst)
    service_id = int_from_str_base(args.service)
    show_data = args.show
    bruteforce_indices = args.i

    # Sanity checks
    all_valid = True
    for i in bruteforce_indices:
        if not 2 <= i <= 7:
            print(
                "Invalid bruteforce index '{0}' - must be in range 2-7".format(
                    i))
            all_valid = False
    if not all_valid:
        return

    with CanActions(arb_id=send_arb_id) as can_wrap:
        found_sub_functions = []
        print("Starting DCM sub-function discovery")

        def response_analyser_wrapper(data):
            print("\rProbing sub-function 0x{0:02x} data {1} (found: {2})".
                  format(service_id, data, len(found_sub_functions)),
                  end="")
            stdout.flush()

            def response_analyser(msg):
                if msg.arbitration_id != rcv_arb_id:
                    return
                # Response queued - do not handle
                if msg.data[:4] == [0x03, 0x7f, service_id, 0x78]:
                    can_wrap.current_delay = 1.0
                    return
                # Catch ok status
                elif msg.data[1] - 0x40 == service_id or \
                        (msg.data[1] == 0x7F and msg.data[3] not in [0x11, 0x12, 0x31, 0x78]):
                    found_sub_functions.append((data, [msg]))
                elif msg.data[0] == 0x10:
                    # If response takes up multiple frames
                    can_wrap.current_delay = 1.0
                    found_sub_functions.append((data, [msg]))
                    if show_data:
                        # Cool, give me the rest
                        can_wrap.send([0x30])
                    else:
                        # Fine, but I don't want the remaining data
                        can_wrap.send([0x32])
                elif show_data and msg.data[0] & 0xF0 == 0x20:
                    # Parts following a 0x30 in multiple frame response (keep waiting)
                    can_wrap.current_delay = 1.0
                    found_sub_functions[-1][1].append(msg)
                else:
                    # We got an answer - no reason to keep waiting
                    can_wrap.current_delay = 0.0

            return response_analyser

        def finished(s):
            print("\nDone: {0}".format(s))

        try:
            # Message to bruteforce - [length, session control, default session]
            message = insert_message_length([service_id, 0x00, 0x00])
            can_wrap.bruteforce_data_new(message,
                                         bruteforce_indices=bruteforce_indices,
                                         callback=response_analyser_wrapper,
                                         callback_done=finished)
            can_wrap.notifier.listeners = []
        finally:
            # Print found functions
            if len(found_sub_functions) > 0:
                print("\n\nFound sub-functions for service 0x{0:02x} ({1}):\n".
                      format(
                          service_id,
                          DCM_SERVICE_NAMES.get(service_id,
                                                "Unknown service")))
                for (sub_function, msgs) in found_sub_functions:
                    print("Sub-function {0}".format(" ".join(sub_function)))
                    if show_data:
                        for message in msgs:
                            print("  {0}".format(message))
            else:
                print("\n\nNo sub-functions were found")
Example #4
0
def dcm_discovery(args):
    """
    Scans for diagnostics support by sending session control against different arbitration IDs.

    :param: args: A namespace containing min and max
    """
    min_id = int_from_str_base(args.min)
    max_id = int_from_str_base(args.max)
    no_stop = args.nostop
    blacklist = [int_from_str_base(b) for b in args.blacklist]

    valid_responses = [0x50, 0x7F]

    def scan_arbitration_ids_to_blacklist(scan_duration):
        print("Scanning for arbitration IDs to blacklist (-autoblacklist)")
        ids_to_blacklist = set()

        def response_handler(msg):
            if msg.data[1] in valid_responses:
                ids_to_blacklist.add(msg.arbitration_id)

        with CanActions() as can_actions:
            # Listen for matches
            can_actions.add_listener(response_handler)
            for i in range(scan_duration, 0, -1):
                print("\r  Scanning... {0} seconds left, {1} found".format(
                    i - 1, len(ids_to_blacklist)),
                      end="")
                stdout.flush()
                time.sleep(1)
            print("")
            can_actions.clear_listeners()
        # Add found matches to blacklist
        for arb_id in ids_to_blacklist:
            blacklist.append(arb_id)

    # Perform automatic blacklist scanning
    if args.autoblacklist > 0:
        scan_arbitration_ids_to_blacklist(args.autoblacklist)

    class Diagnostics:
        found = False

    with CanActions() as can_wrap:
        print("Starting diagnostics service discovery")

        def response_analyser_wrapper(arb_id):
            print("\rSending Diagnostic Session Control to 0x{0:04x}".format(
                arb_id),
                  end="")
            stdout.flush()

            def response_analyser(msg):
                # Ignore blacklisted arbitration IDs
                if msg.arbitration_id in blacklist:
                    return
                # Catch both ok and negative response
                if len(msg.data) >= 2 and msg.data[1] in valid_responses:
                    Diagnostics.found = True
                    print("\nFound diagnostics at arbitration ID 0x{0:04x}, "
                          "reply at 0x{1:04x}".format(arb_id,
                                                      msg.arbitration_id))
                    if not no_stop:
                        can_wrap.bruteforce_stop()

            return response_analyser

        def discovery_finished(s):
            if Diagnostics.found:
                print("\n{0}".format(s))
            else:
                print(
                    "\nDiagnostics service could not be found: {0}".format(s))

        # Message to bruteforce - [length, session control, default session]
        message = insert_message_length([0x10, 0x01])
        can_wrap.bruteforce_arbitration_id(message,
                                           response_analyser_wrapper,
                                           min_id=min_id,
                                           max_id=max_id,
                                           callback_end=discovery_finished)
Example #5
0
def subfunc_discovery(args):
    """
    Scans for subfunctions of a given service.

    :param args: A namespace containing src, dst, service, show and i
    """
    send_arb_id = int_from_str_base(args.src)
    rcv_arb_id = int_from_str_base(args.dst)
    service_id = int_from_str_base(args.service)
    show_data = args.show
    bruteforce_indices = args.i

    with CanActions(arb_id=send_arb_id) as can_wrap:
        found_sub_functions = []
        print("Starting DCM sub-function discovery")

        def response_analyser_wrapper(data):
            print "\rProbing sub-function 0x{0:02x} data {1} (found: {2})".format(
                service_id, data, len(found_sub_functions)),
            stdout.flush()


            def response_analyser(msg):
                if msg.arbitration_id != rcv_arb_id:
                    return
                # Response queued - do not handle
                if msg.data[:4] == [0x03, 0x7f, service_id, 0x78]:
                    can_wrap.current_delay = 1.0
                    return
                # Catch ok status
                elif msg.data[1]-0x40 == service_id or\
                        (msg.data[1] == 0x7F and msg.data[3] not in [0x11, 0x12, 0x31, 0x78]): # TODO - more?
                    found_sub_functions.append((data, [msg]))
                elif msg.data[0] == 0x10:
                    # If response takes up multiple frames
                    can_wrap.current_delay = 1.0
                    found_sub_functions.append((data, [msg]))
                    if show_data:
                        # Cool, give me the rest
                        can_wrap.send([0x30])
                    else:
                        # Fine, but I don't want the remaining data
                        can_wrap.send([0x32])
                elif show_data and msg.data[0] & 0xF0 == 0x20:
                    # Parts following a 0x30 in multiple frame response (keep waiting)
                    can_wrap.current_delay = 1.0
                    found_sub_functions[-1][1].append(msg)
                else:
                    # We've got an answer - no reason to keep waiting
                    can_wrap.current_delay = 0.0
            return response_analyser

        def finished(s):
            print("\nDone: {0}".format(s))

        try:
            # Message to bruteforce - [length, session control, default session]
            message = insert_message_length([service_id, 0x00, 0x00])
            can_wrap.bruteforce_data_new(message, bruteforce_indices=bruteforce_indices, callback=response_analyser_wrapper,
                                     callback_end=finished)
            can_wrap.notifier.listeners = []
        finally:
            # Print found functions
            if len(found_sub_functions) > 0:
                print("\n\nFound sub-functions for service 0x{0:02x} ({1}):\n".format(
                    service_id, DCM_SERVICE_NAMES.get(service_id, "Unknown service")))
                for (sub_function, msgs) in found_sub_functions:
                    print("Sub-function {0}".format(" ".join(sub_function)))
                    if show_data:
                        for msg in msgs:
                            print("  {0}".format(msg))
            else:
                print("\n\nNo sub-functions were found")