예제 #1
0
 def exploit(self):
     i = 0
     key_x = ""
     for byte_k in self._status2.get('vin', '12345678901234567'):
         key_x += chr(ord(byte_k) ^ bytes.fromhex(self._status2.get('key', '1122334455667788990011223344556677'))[i])  # XOR with KEY (to get VIN)
         i += 1
     self.frames.extend(ISOTPMessage.generate_can(self._status2['id_command'], [ord(byt) for byt in list(key_x)]))
     return ""
예제 #2
0
    def add_request(self, _id, _service, _subcommand, _data):
        if not _data:
            _data = []

        if _subcommand is None or _subcommand < 0:
            _subcommand = []
        else:
            _subcommand = [_subcommand]
        byte_data = [_service] + _subcommand + _data
        return ISOTPMessage.generate_can(_id, byte_data, self.padding)
예제 #3
0
    def control_start_engine(self):
        i = 0
        key_x = ""
        for byte_k in self._vin:
            key_x += chr(ord(byte_k)
                         ^ ord(self._auth[i]))  # XOR with KEY (to get VIN)
            i += 1

        self.frames.extend(
            ISOTPMessage.generate_can(self._status2['id_command'],
                                      [ord(byt) for byt in list(key_x)]))
        return ""
예제 #4
0
    def do_start(self, args):
        self.queue_messages = []
        self.last = time.clock()

        data = [0, 0, 0, 0, 0, 0, 0, 0]
        if 'body' in args:
            data = list(bytes.fromhex(args['body']))

        iso_mode = self._get_iso_mode(args)

        padding = args.get('padding', None)
        shift = int(args.get('shift', 0x8))

        if 'range' not in args:
            self.dprint(1, "No range specified")
            self._active = False
            self.set_error_text("ERROR: No range specified")
            return
        start, end = args.get('range', [0, 0])
        for i in range(int(start), int(end)):
            if iso_mode == 1:
                iso_list = ISOTPMessage.generate_can(i, data, padding)
                iso_list.reverse()
                self.queue_messages.extend(iso_list)
            elif iso_mode == 0:
                self.queue_messages.append(
                    CANMessage.init_data(i, len(data), data[:8]))
            elif iso_mode == 2:
                for service in args.get('services', []):
                    uds_m = UDSMessage(shift, padding)
                    for service_id in self._get_range(service['service']):
                        # https://github.com/eik00d/CANToolz/issues/93 by @DePierre
                        subservice_ids = service.get('sub', None)
                        if subservice_ids is None:
                            subservice_ids = [None]
                        else:
                            subservice_ids = self._get_range(subservice_ids)
                        for subservice_id in subservice_ids:
                            iso_list = uds_m.add_request(
                                i, service_id, subservice_id,
                                service.get('data', []))
                            iso_list.reverse()
                            self.queue_messages.extend(iso_list)
        self._full = len(self.queue_messages)
        self._last = 0
예제 #5
0
 def fuzz(self, fuzz_list, idf, data, bytes_to_fuzz, level, iso_mode):
     messages = []
     x_data = [] + data
     for byte in fuzz_list:
         x_data[bytes_to_fuzz[level]] = byte
         if level != 0:
             messages.extend(
                 self.fuzz(fuzz_list, idf, x_data, bytes_to_fuzz, level - 1,
                           iso_mode))
         else:
             if iso_mode == 1:
                 iso_list = ISOTPMessage.generate_can(idf, x_data)
                 iso_list.reverse()
                 messages.extend(iso_list)
             else:
                 messages.append(
                     CANMessage.init_data(idf, len(x_data), x_data[:8]))
     return messages
예제 #6
0
class ecu_engine(CANModule):

    name = "Engine emulator for vircar"
    help = """

    This module emulating car engine.

    Init params (example):
    {
        'id_report': 0x79,
        'id_uds': 0x701,
        'uds_shift': 0x08,
        'id_command': 0x71,
        'vin_id': 0x811,
        'vin':'NLXXX6666CW006666',
        'start_uniq_key':'aXdloDoospOidd78%',
        'uds_key':'secret_uds_auth',
        'commands': {
                'rpm_up':'01',
                'rpm_down':'02',
                'init': '',
                'stop': '00'
            }

        'reports_delay': 0.6

    }

    """

    _active = True

    def do_init(self, params):
        self._status2 = params
        self._vin = self._status2.get("vin", "NLXXX6666CW006666")
        self._auth = self._status2.get("start_uniq_key", "tGh&ujKnf5$rFgvc1")
        self._uds_auth = self._status2.get("uds_key", "secret_uds_auth1")
        self._seed = None
        self._uds_auth_done = False
        self._status2.update({'rpm': 0, 'status': 0})
        self.rpm_up = 0
        self.rpm_down = 0
        self.default = 500
        self.current = 0
        self.frames = []
        self.init_sess = None
        self.init_sess2 = None
        self._last_sent = time.process_time()
        self.vin_gen = [time.process_time(), time.process_time(), 0.7, 2.9]

        left = len(self._vin)
        count = int(left / 7) + 1
        if (left % 7) > 0:
            count += 1
        curr = 0
        self.vin = []
        self.count_part = 0
        while left > 0:
            if curr == 0:
                self.vin.append([0, 0, 0, 0, count, 0, 0, left])
                curr += 1
            else:
                part = [
                    ord(byt)
                    for byt in (self._vin[(curr - 1) * 7:(curr - 1) * 7 + 7])
                ]
                self.vin.append([curr] +
                                list(part + list(bytes(7 - len(part)))))
                left += -7
                curr += 1

    def generate_rpm(self):
        if self._status2['status'] == 1:
            self.current += self.rpm_up - self.rpm_down
            self._status2['rpm'] = self.current + random.randrange(-20, 20)
            if self._status2['rpm'] < 150:
                self._status2['status'] = 2  # dead
            elif self._status2['rpm'] > 4500:
                self._status2['status'] = 2  # also dead

        elif self._status2['status'] == 3:
            self._status2['rpm'] = 0

        elif self._status2['status'] == 2:
            self._status2['rpm'] = 0

        self.rpm_up = 0
        self.rpm_down = 0

        if self._status2['status'] in [2, 3, 1]:
            if (time.process_time() - self._last_sent) >= self._status2.get(
                    'reports_delay', 0.5):
                self.frames.append(
                    CANMessage(
                        self._status2.get('id_report', 0xffff), 3,
                        self._status2['status'].to_bytes(1, byteorder='big') +
                        self._status2['rpm'].to_bytes(2, byteorder='big'),
                        False, CANMessage.DataFrame))
                self._last_sent = time.process_time()

    def generate_vin(self):
        curr_t = time.process_time()
        if self.vin_gen[0] == 0 or curr_t - self.vin_gen[0] > self.vin_gen[2]:
            if self.vin_gen[
                    1] == 0 or curr_t - self.vin_gen[1] > self.vin_gen[3]:
                self.frames.append(
                    CANMessage.init_data(self._status2.get('vin_id', 1),
                                         len(self.vin[self.count_part]),
                                         self.vin[self.count_part]))
                self.count_part += 1
                self.vin_gen[1] = curr_t
                if self.count_part == len(self.vin):
                    self.vin_gen[0] = curr_t
                    self.count_part = 0

    # Effect (could be fuzz operation, sniff, filter or whatever)
    def do_effect(self, can_msg, args):
        if self._status2['status'] > 0:
            self.generate_rpm()
        self.generate_vin()
        if args['action'] == 'read' and can_msg.CANData:  # READ
            if self._status2['id_command'] == can_msg.CANFrame.frame_id:
                for cmd, value in self._status2['commands'].items():
                    len_cmd = int(len(str(value)) / 2)

                    if self._status2['status'] != 0 and cmd == "rpm_up":
                        len_cmd2 = len_cmd + 1
                        if can_msg.CANFrame.frame_length == len_cmd2 and can_msg.CANFrame.frame_raw_data[
                                0:len_cmd] == bytes.fromhex(
                                    value
                                )[0:len_cmd] and self._status2['status'] == 1:
                            self.rpm_up += ord(
                                can_msg.CANFrame.
                                frame_raw_data[len_cmd:len_cmd2])
                    elif self._status2['status'] != 0 and cmd == "rpm_down":
                        len_cmd2 = len_cmd + 1
                        if can_msg.CANFrame.frame_length == len_cmd2 and can_msg.CANFrame.frame_raw_data[
                                0:len_cmd] == bytes.fromhex(
                                    value
                                )[0:len_cmd] and self._status2['status'] == 1:
                            self.rpm_down += ord(
                                can_msg.CANFrame.
                                frame_raw_data[len_cmd:len_cmd2])
                    elif self._status2['status'] != 0 and cmd == "stop":
                        if can_msg.CANFrame.frame_length == len_cmd and can_msg.CANFrame.frame_raw_data[
                                0:len_cmd] == bytes.fromhex(value)[0:len_cmd]:
                            self._status2['status'] = 3
                            self.current = 0
                    elif cmd == "init":
                        if not self.init_sess:
                            self.init_sess = ISOTPMessage(
                                can_msg.CANFrame.frame_id)

                        ret = self.init_sess.add_can(can_msg.CANFrame)
                        if ret < 0:
                            self.init_sess = None
                        elif ret == 1:
                            if self.init_sess.message_length != 17:
                                self.init_sess = None
                            else:
                                key = self.init_sess.message_data
                                i = 0
                                vin_x = ""
                                for byte_k in key:
                                    vin_x += chr(byte_k ^ ord(self._auth[i])
                                                 )  # XOR with KEY (to get VIN)
                                    i += 1
                                if vin_x != self._vin:  # auth failed, send error back
                                    self.frames.append(
                                        CANMessage(
                                            self._status2.get(
                                                'id_report',
                                                0xffff), 2, b'\xff\xff', False,
                                            CANMessage.DataFrame))
                                else:  # Auth complite
                                    self._status2['status'] = 1
                                    self.frames.append(
                                        CANMessage(
                                            self._status2.get(
                                                'id_report',
                                                0xffff), 2, b'\xff\x01', False,
                                            CANMessage.DataFrame))
                                    if self.current < 150:
                                        self.current = self.default
                                self.init_sess = None

            elif self._status2['id_uds'] == can_msg.CANFrame.frame_id:
                if not self.init_sess2:
                    self.init_sess2 = ISOTPMessage(can_msg.CANFrame.frame_id)

                ret = self.init_sess2.add_can(can_msg.CANFrame)

                if ret < 0:
                    self.init_sess2 = None
                elif ret == 1:
                    uds_msg = UDSMessage(self._status2.get('uds_shift', 8))
                    uds_msg.add_raw_request(self.init_sess2)
                    if can_msg.CANFrame.frame_id in uds_msg.sessions:
                        if 0x27 in uds_msg.sessions[
                                can_msg.CANFrame.frame_id]:  # Check service
                            if 1 in uds_msg.sessions[
                                    can_msg.CANFrame.
                                    frame_id][0x27]:  # Check sub: SEED request
                                self._seed = [
                                    random.randrange(1, 100),
                                    random.randrange(1, 100),
                                    random.randrange(1, 100),
                                    random.randrange(1, 100)
                                ]
                                # Generate UDS reponse
                                self.frames.extend(
                                    uds_msg.add_request(
                                        self._status2['id_uds'] +
                                        self._status2['uds_shift'],  # ID
                                        0x27 + 0x40,  # Service
                                        0x01,  # Sub function
                                        self._seed))  # data

                            elif 2 in uds_msg.sessions[
                                    can_msg.CANFrame.
                                    frame_id][0x27]:  # Check sub: KEY enter
                                if self._seed is not None:
                                    key_x = ""
                                    key = uds_msg.sessions[
                                        can_msg.CANFrame.frame_id][0x27][2][
                                            'data']  # Read key
                                    i = 0
                                    for byte_k in key:
                                        key_x += chr(byte_k
                                                     ^ self._seed[i % 4])
                                        i += 1
                                    if key_x == self._uds_auth:
                                        self._uds_auth_done = True
                                        self.frames.extend(
                                            uds_msg.add_request(
                                                self._status2['id_uds'] + self.
                                                _status2['uds_shift'],  # ID
                                                0x27 + 0x40,  # Service
                                                0x02,  # Sub function
                                                [0xFF]))  # data
                                    else:
                                        self._uds_auth_done = False
                                        self.frames.extend(
                                            uds_msg.add_request(
                                                self._status2['id_uds'] + self.
                                                _status2['uds_shift'],  # ID
                                                0x27 + 0x40,  # Service
                                                0x02,  # Sub function
                                                [0x00]))  # data
                                self._seed = None
                        elif 0x2e in uds_msg.sessions[
                                can_msg.CANFrame.
                                frame_id] and 0x55 in uds_msg.sessions[
                                    can_msg.CANFrame.
                                    frame_id][0x2e] and uds_msg.sessions[
                                        can_msg.CANFrame.frame_id][0x2e][0x55][
                                            'data'][0] == 0x55:
                            if self._uds_auth_done:
                                new_key = ''.join(
                                    chr(x) for x in uds_msg.sessions[
                                        can_msg.CANFrame.frame_id][0x2e][0x55]
                                    ['data'][1:])
                                if len(new_key) == 17:
                                    self._uds_auth_done = False
                                    self._auth = new_key
                                    self.frames.extend(
                                        uds_msg.add_request(
                                            self._status2['id_uds'] +
                                            self._status2['uds_shift'],  # ID
                                            0x2e + 0x40,  # Service
                                            0x55,  # Sub function
                                            [0x55]))  # data
                                else:
                                    self._uds_auth_done = False
                                    self.frames.extend(
                                        uds_msg.add_request(
                                            self._status2['id_uds'] +
                                            self._status2['uds_shift'],  # ID
                                            0x2e + 0x40,  # Service
                                            0x00,  # Sub function
                                            [0x00]))
                            else:
                                self._uds_auth_done = False
                                self.frames.extend(
                                    uds_msg.add_request(
                                        self._status2['id_uds'] +
                                        self._status2['uds_shift'],  # ID
                                        0x2e + 0x40,  # Service
                                        0x00,  # Sub function
                                        [0x00]))  # data
                    self.init_sess2 = None

        elif args['action'] == 'write' and not can_msg.CANData:
            if len(self.frames) > 0:
                can_msg.CANFrame = self.frames.pop(0)
                can_msg.CANData = True
                can_msg.bus = self._bus
        return can_msg
예제 #7
0
    def do_effect(self, can_msg, args):
        if self._status2['status'] > 0:
            self.generate_rpm()
        self.generate_vin()
        if args['action'] == 'read' and can_msg.CANData:  # READ
            if self._status2['id_command'] == can_msg.CANFrame.frame_id:
                for cmd, value in self._status2['commands'].items():
                    len_cmd = int(len(str(value)) / 2)

                    if self._status2['status'] != 0 and cmd == "rpm_up":
                        len_cmd2 = len_cmd + 1
                        if can_msg.CANFrame.frame_length == len_cmd2 and can_msg.CANFrame.frame_raw_data[
                                0:len_cmd] == bytes.fromhex(
                                    value
                                )[0:len_cmd] and self._status2['status'] == 1:
                            self.rpm_up += ord(
                                can_msg.CANFrame.
                                frame_raw_data[len_cmd:len_cmd2])
                    elif self._status2['status'] != 0 and cmd == "rpm_down":
                        len_cmd2 = len_cmd + 1
                        if can_msg.CANFrame.frame_length == len_cmd2 and can_msg.CANFrame.frame_raw_data[
                                0:len_cmd] == bytes.fromhex(
                                    value
                                )[0:len_cmd] and self._status2['status'] == 1:
                            self.rpm_down += ord(
                                can_msg.CANFrame.
                                frame_raw_data[len_cmd:len_cmd2])
                    elif self._status2['status'] != 0 and cmd == "stop":
                        if can_msg.CANFrame.frame_length == len_cmd and can_msg.CANFrame.frame_raw_data[
                                0:len_cmd] == bytes.fromhex(value)[0:len_cmd]:
                            self._status2['status'] = 3
                            self.current = 0
                    elif cmd == "init":
                        if not self.init_sess:
                            self.init_sess = ISOTPMessage(
                                can_msg.CANFrame.frame_id)

                        ret = self.init_sess.add_can(can_msg.CANFrame)
                        if ret < 0:
                            self.init_sess = None
                        elif ret == 1:
                            if self.init_sess.message_length != 17:
                                self.init_sess = None
                            else:
                                key = self.init_sess.message_data
                                i = 0
                                vin_x = ""
                                for byte_k in key:
                                    vin_x += chr(byte_k ^ ord(self._auth[i])
                                                 )  # XOR with KEY (to get VIN)
                                    i += 1
                                if vin_x != self._vin:  # auth failed, send error back
                                    self.frames.append(
                                        CANMessage(
                                            self._status2.get(
                                                'id_report',
                                                0xffff), 2, b'\xff\xff', False,
                                            CANMessage.DataFrame))
                                else:  # Auth complite
                                    self._status2['status'] = 1
                                    self.frames.append(
                                        CANMessage(
                                            self._status2.get(
                                                'id_report',
                                                0xffff), 2, b'\xff\x01', False,
                                            CANMessage.DataFrame))
                                    if self.current < 150:
                                        self.current = self.default
                                self.init_sess = None

            elif self._status2['id_uds'] == can_msg.CANFrame.frame_id:
                if not self.init_sess2:
                    self.init_sess2 = ISOTPMessage(can_msg.CANFrame.frame_id)

                ret = self.init_sess2.add_can(can_msg.CANFrame)

                if ret < 0:
                    self.init_sess2 = None
                elif ret == 1:
                    uds_msg = UDSMessage(self._status2.get('uds_shift', 8))
                    uds_msg.add_raw_request(self.init_sess2)
                    if can_msg.CANFrame.frame_id in uds_msg.sessions:
                        if 0x27 in uds_msg.sessions[
                                can_msg.CANFrame.frame_id]:  # Check service
                            if 1 in uds_msg.sessions[
                                    can_msg.CANFrame.
                                    frame_id][0x27]:  # Check sub: SEED request
                                self._seed = [
                                    random.randrange(1, 100),
                                    random.randrange(1, 100),
                                    random.randrange(1, 100),
                                    random.randrange(1, 100)
                                ]
                                # Generate UDS reponse
                                self.frames.extend(
                                    uds_msg.add_request(
                                        self._status2['id_uds'] +
                                        self._status2['uds_shift'],  # ID
                                        0x27 + 0x40,  # Service
                                        0x01,  # Sub function
                                        self._seed))  # data

                            elif 2 in uds_msg.sessions[
                                    can_msg.CANFrame.
                                    frame_id][0x27]:  # Check sub: KEY enter
                                if self._seed is not None:
                                    key_x = ""
                                    key = uds_msg.sessions[
                                        can_msg.CANFrame.frame_id][0x27][2][
                                            'data']  # Read key
                                    i = 0
                                    for byte_k in key:
                                        key_x += chr(byte_k
                                                     ^ self._seed[i % 4])
                                        i += 1
                                    if key_x == self._uds_auth:
                                        self._uds_auth_done = True
                                        self.frames.extend(
                                            uds_msg.add_request(
                                                self._status2['id_uds'] + self.
                                                _status2['uds_shift'],  # ID
                                                0x27 + 0x40,  # Service
                                                0x02,  # Sub function
                                                [0xFF]))  # data
                                    else:
                                        self._uds_auth_done = False
                                        self.frames.extend(
                                            uds_msg.add_request(
                                                self._status2['id_uds'] + self.
                                                _status2['uds_shift'],  # ID
                                                0x27 + 0x40,  # Service
                                                0x02,  # Sub function
                                                [0x00]))  # data
                                self._seed = None
                        elif 0x2e in uds_msg.sessions[
                                can_msg.CANFrame.
                                frame_id] and 0x55 in uds_msg.sessions[
                                    can_msg.CANFrame.
                                    frame_id][0x2e] and uds_msg.sessions[
                                        can_msg.CANFrame.frame_id][0x2e][0x55][
                                            'data'][0] == 0x55:
                            if self._uds_auth_done:
                                new_key = ''.join(
                                    chr(x) for x in uds_msg.sessions[
                                        can_msg.CANFrame.frame_id][0x2e][0x55]
                                    ['data'][1:])
                                if len(new_key) == 17:
                                    self._uds_auth_done = False
                                    self._auth = new_key
                                    self.frames.extend(
                                        uds_msg.add_request(
                                            self._status2['id_uds'] +
                                            self._status2['uds_shift'],  # ID
                                            0x2e + 0x40,  # Service
                                            0x55,  # Sub function
                                            [0x55]))  # data
                                else:
                                    self._uds_auth_done = False
                                    self.frames.extend(
                                        uds_msg.add_request(
                                            self._status2['id_uds'] +
                                            self._status2['uds_shift'],  # ID
                                            0x2e + 0x40,  # Service
                                            0x00,  # Sub function
                                            [0x00]))
                            else:
                                self._uds_auth_done = False
                                self.frames.extend(
                                    uds_msg.add_request(
                                        self._status2['id_uds'] +
                                        self._status2['uds_shift'],  # ID
                                        0x2e + 0x40,  # Service
                                        0x00,  # Sub function
                                        [0x00]))  # data
                    self.init_sess2 = None

        elif args['action'] == 'write' and not can_msg.CANData:
            if len(self.frames) > 0:
                can_msg.CANFrame = self.frames.pop(0)
                can_msg.CANData = True
                can_msg.bus = self._bus
        return can_msg
예제 #8
0
    def do_effect(self, can_msg, args):
        if args['action'] == 'read' and can_msg.CANData and can_msg.CANFrame.frame_id == self._status2[
                'id_uds'] + self._status2['uds_shift']:  # READ
            if not self.init_sess2:
                self.init_sess2 = ISOTPMessage(can_msg.CANFrame.frame_id)

                ret = self.init_sess2.add_can(can_msg.CANFrame)

                if ret < 0:
                    self.init_sess2 = None
                elif ret == 1:
                    uds_msg = UDSMessage()
                    uds_msg.add_raw_request(self.init_sess2)
                    if can_msg.CANFrame.frame_id in uds_msg.sessions:
                        if 0x27 + 0x40 in uds_msg.sessions[
                                can_msg.CANFrame.frame_id]:  # Check service
                            if 1 in uds_msg.sessions[
                                    can_msg.CANFrame.frame_id][
                                        0x27 +
                                        0x40]:  # Check sub: SEED request
                                self._seed = uds_msg.sessions[
                                    can_msg.CANFrame.frame_id][0x27 +
                                                               0x40][1]['data']
                                if self.wait_for_auth:
                                    self.call_auth()
                            elif 2 in uds_msg.sessions[
                                    can_msg.CANFrame.
                                    frame_id][0x27 + 0x40] and len(
                                        uds_msg.sessions[
                                            can_msg.CANFrame.frame_id][0x27 +
                                                                       0x40][2]
                                        ['data']) == 1:  # Check sub: KEY enter
                                self.auth_resp_byte = uds_msg.sessions[
                                    can_msg.CANFrame.frame_id][
                                        0x27 + 0x40][2]['data'][0]
                        elif 0x2e + 0x40 in uds_msg.sessions[
                                can_msg.CANFrame.
                                frame_id] and 0x55 in uds_msg.sessions[
                                    can_msg.CANFrame.frame_id][
                                        0x2e + 0x40] and uds_msg.sessions[
                                            can_msg.CANFrame.frame_id][
                                                0x2e +
                                                0x40][0x55]['data'][0] == 0x55:
                            self.record_status = True
                        elif 0x2e + 0x40 in uds_msg.sessions[
                                can_msg.CANFrame.
                                frame_id] and 0x0 in uds_msg.sessions[
                                    can_msg.CANFrame.frame_id][
                                        0x2e + 0x40] and uds_msg.sessions[
                                            can_msg.CANFrame.frame_id][
                                                0x2e +
                                                0x40][0x0]['data'][0:1] == [
                                                    0x0
                                                ]:  # data
                            self.record_status = False
                    self.init_sess2 = None

        if args['action'] == 'write' and not can_msg.CANData:
            if len(self.frames) > 0:
                can_msg.CANFrame = self.frames.pop(0)
                can_msg.CANData = True
                can_msg.bus = self._bus
        return can_msg
예제 #9
0
class uds_tester_ecu_engine(CANModule):

    name = "UDS Tester device emulator"
    help = """

    This module emulating UDS for vircar Engine ECU.

    Init params (example):
    {
        'id_uds': 0x701,
        'uds_shift': 0x08,
        'uds_key':''
    }

    """

    _active = True

    def do_init(self, params):
        self._status2 = params
        self.frames = []
        self.init_sess2 = None
        self._seed = []
        self.auth_resp_byte = 0
        self.record_status = False
        self.wait_for_auth = False

        self.commands['auth'] = Command("UDS Auth", 0, "", self.control_auth,
                                        True)
        self.commands['set_key'] = Command("Set UDS access key", 1, "<key>",
                                           self.set_key, True)
        self.commands['write_id'] = Command("Write parameter (HEX)", 1,
                                            "<ident>, <data>",
                                            self.write_param, True)

    def write_param(self, key):
        uds_msg = UDSMessage()
        (ids, data) = key.split(',')
        ids = list(bytes.fromhex(ids.strip()))
        data = list(bytes.fromhex(data.strip()))
        self.frames.extend(
            uds_msg.add_request(
                self._status2['id_uds'],  # ID
                0x2e,  # Service
                ids[0],  # Sub function
                ids[1:] + data))
        return ""

    def get_status(self):
        return "Current status: " + str(
            self._active
        ) + "\nKEY: " + self._status2['uds_key'] + "\nResponse AUTH: " + str(
            self.auth_resp_byte)

    def set_key(self, key):
        self._status2.update({'uds_key': key.strip()})
        return ""

    def control_auth(self):
        uds_msg = UDSMessage()
        self.frames.extend(
            uds_msg.add_request(
                self._status2['id_uds'],  # ID
                0x27,  # Service
                0x1,  # Sub function
                []))
        self.wait_for_auth = True
        return ""

    def call_auth(self):
        uds_msg = UDSMessage()
        i = 0
        key = []
        for byte_k in self._status2['uds_key']:
            key.append(ord(byte_k) ^ self._seed[i % 4])
            i += 1
        self.frames.extend(
            uds_msg.add_request(
                self._status2['id_uds'],  # ID
                0x27,  # Service
                0x2,  # Sub function
                key))
        self.wait_for_auth = False

    # Effect (could be fuzz operation, sniff, filter or whatever)
    def do_effect(self, can_msg, args):
        if args['action'] == 'read' and can_msg.CANData and can_msg.CANFrame.frame_id == self._status2[
                'id_uds'] + self._status2['uds_shift']:  # READ
            if not self.init_sess2:
                self.init_sess2 = ISOTPMessage(can_msg.CANFrame.frame_id)

                ret = self.init_sess2.add_can(can_msg.CANFrame)

                if ret < 0:
                    self.init_sess2 = None
                elif ret == 1:
                    uds_msg = UDSMessage()
                    uds_msg.add_raw_request(self.init_sess2)
                    if can_msg.CANFrame.frame_id in uds_msg.sessions:
                        if 0x27 + 0x40 in uds_msg.sessions[
                                can_msg.CANFrame.frame_id]:  # Check service
                            if 1 in uds_msg.sessions[
                                    can_msg.CANFrame.frame_id][
                                        0x27 +
                                        0x40]:  # Check sub: SEED request
                                self._seed = uds_msg.sessions[
                                    can_msg.CANFrame.frame_id][0x27 +
                                                               0x40][1]['data']
                                if self.wait_for_auth:
                                    self.call_auth()
                            elif 2 in uds_msg.sessions[
                                    can_msg.CANFrame.
                                    frame_id][0x27 + 0x40] and len(
                                        uds_msg.sessions[
                                            can_msg.CANFrame.frame_id][0x27 +
                                                                       0x40][2]
                                        ['data']) == 1:  # Check sub: KEY enter
                                self.auth_resp_byte = uds_msg.sessions[
                                    can_msg.CANFrame.frame_id][
                                        0x27 + 0x40][2]['data'][0]
                        elif 0x2e + 0x40 in uds_msg.sessions[
                                can_msg.CANFrame.
                                frame_id] and 0x55 in uds_msg.sessions[
                                    can_msg.CANFrame.frame_id][
                                        0x2e + 0x40] and uds_msg.sessions[
                                            can_msg.CANFrame.frame_id][
                                                0x2e +
                                                0x40][0x55]['data'][0] == 0x55:
                            self.record_status = True
                        elif 0x2e + 0x40 in uds_msg.sessions[
                                can_msg.CANFrame.
                                frame_id] and 0x0 in uds_msg.sessions[
                                    can_msg.CANFrame.frame_id][
                                        0x2e + 0x40] and uds_msg.sessions[
                                            can_msg.CANFrame.frame_id][
                                                0x2e +
                                                0x40][0x0]['data'][0:1] == [
                                                    0x0
                                                ]:  # data
                            self.record_status = False
                    self.init_sess2 = None

        if args['action'] == 'write' and not can_msg.CANData:
            if len(self.frames) > 0:
                can_msg.CANFrame = self.frames.pop(0)
                can_msg.CANData = True
                can_msg.bus = self._bus
        return can_msg