Beispiel #1
0
def process_dp(dp_file, rule_file):
    fh = FileHandle(dp_file, 'r+')
    cps_list = []
    cps = Cps()
    cps.dp_file_path = dp_file
    app_flag = ''
    while True:
        card_data = fh.read_line()
        if card_data == '':  #数据处理完毕
            break
        elif card_data == '[01]':
            app_flag = '01'
            continue
        elif card_data == '[02]':
            app_flag = '02'
            continue
        elif card_data == '[03]':
            app_flag = '03'
            continue
        elif card_data == '[04]':  #说明这个是双应用数据(Jetco)
            app_flag = '04'
            continue
        dgi = process_data(app_flag, card_data)
        cps.add_dgi(dgi)
    if rule_file is not None:
        cps = process_rule(rule_file, cps)
    cps_list.append(cps)
    return cps_list
Beispiel #2
0
def process_dp(dp_file, rule_file):
    cps_list = []
    fh = FileHandle(dp_file, 'rb+')
    dp_flag = fh.read_binary(fh.current_offset, 7)
    data_len = utils.hex_str_to_int(fh.read_binary(fh.current_offset, 8))
    dgi_count = fh.read_int64(fh.current_offset)
    dgi_list = []
    for i in range(dgi_count):
        dgi_name_len = fh.read_int(fh.current_offset)
        dgi_name = fh.read_str(fh.current_offset, dgi_name_len)
        dgi_list.append(dgi_name)
    card_seq = fh.read_binary(fh.current_offset, 4)
    card_data_len = fh.read_int(fh.current_offset)
    while data_len > fh.current_offset:
        cps = Cps()
        cps.dp_file_path = dp_file
        for item in dgi_list:
            dgi = Dgi()
            start_flag = fh.read_binary(fh.current_offset, 1)
            if start_flag != '86':
                return cps_list
            dgi_len = get_len(fh)
            dgi_name = fh.read_binary(fh.current_offset, 2)
            dgi.name = dgi_name
            dgi_data_len = utils.hex_str_to_int(
                fh.read_binary(fh.current_offset, 1))
            n_dgi_seq = utils.hex_str_to_int(dgi_name)
            if n_dgi_seq <= 0x0B00:  #认为是记录
                template70 = fh.read_binary(fh.current_offset, 1)
                if template70 != '70':
                    return cps_list
                dgi_data_len = get_len(fh)
            dgi_data = fh.read_binary(fh.current_offset, dgi_data_len)
            if item[0:3] == 'PSE':
                dgi = process_pse_and_ppse(dgi_name, dgi_data, 'PSE')
            elif item[0:4] == 'PPSE':
                dgi = process_pse_and_ppse(dgi_name, dgi_data, 'PPSE')
            else:
                if n_dgi_seq <= 0x0B00 or (utils.is_rsa(dgi_name) is False
                                           and utils.is_tlv(dgi_data)):
                    tlvs = utils.parse_tlv(dgi_data)
                    if len(tlvs) > 0 and tlvs[0].is_template is True:
                        value = utils.assemble_tlv(tlvs[0].tag, tlvs[0].value)
                        dgi.add_tag_value(dgi_name, value)
                    else:
                        for tlv in tlvs:
                            value = utils.assemble_tlv(tlv.tag, tlv.value)
                            dgi.add_tag_value(tlv.tag, value)
                else:
                    dgi.add_tag_value(dgi_name, dgi_data)
            cps.add_dgi(dgi)
        if rule_file is not None:
            process_rule(rule_file, cps)
        cps_list.append(cps)
    return cps_list
Beispiel #3
0
def get_cps(cps_file):
    '''
    通过cps文件获取cps数据
    '''
    cps = Cps()
    ini = IniParser(cps_file)
    sections = ini.get_sections()
    for section in sections:
        if section == 'AID_LIST':
            value = ini.get_value(section,section)
            aid_list = value.split(';')
            cps.pse_aid = aid_list[0]
            cps.ppse_aid = aid_list[1]
            cps.first_app_aid = aid_list[2]
            cps.second_app_aid = aid_list[3]
        elif section in ('DGI_LIST','DGI_LIST_2'):
            continue
        else:
            dgi = Dgi()
            dgi.name = section
            options = ini.get_options(section)
            for option in options:
                value = ini.get_value(section,option)
                dgi.add_tag_value(option,value)
            cps.add_dgi(dgi)
    return cps
Beispiel #4
0
def process_card_data(fh, rule_file):
    cps = Cps()
    flag = fh.read_str(fh.current_offset, 6)
    if flag != '000EMV':
        return False, cps
    card_data_len = fh.read_int64(fh.current_offset)
    app_count = utils.hex_str_to_int(fh.read_binary(fh.current_offset, 1))
    for app in range(app_count):
        aid_len = utils.hex_str_to_int(fh.read_binary(fh.current_offset, 1))
        aid = fh.read_binary(fh.current_offset, aid_len)
        app_data_len = fh.read_int64(fh.current_offset)
        dgi_list, encrypt_dgi_list = get_dgi_list(fh)
        Log.info('encrypt dgi list :', encrypt_dgi_list)
        for item in dgi_list:
            card_dgi = Dgi()
            dgi = fh.read_binary(fh.current_offset, 2)
            dgi_len = utils.hex_str_to_int(fh.read_binary(
                fh.current_offset, 1))
            dgi_data = fh.read_binary(fh.current_offset, dgi_len)
            n_dgi = utils.hex_str_to_int(dgi)
            card_dgi.dgi = dgi
            if dgi == '0098' or dgi == '0099':
                dgi = process_pse(dgi, dgi_data)
            elif dgi == '0100':
                dgi = process_ppse(dgi, dgi_data)
            else:
                if n_dgi < 0x0B01:
                    if dgi_data[0:2] != '70':
                        return False, cps
                    if dgi_data[2:4] == '81':
                        dgi_data = dgi_data[6:]
                    else:
                        dgi_data = dgi_data[4:]
                if utils.is_rsa(dgi) is False and utils.is_tlv(dgi_data):
                    tlvs = utils.parse_tlv(dgi_data)
                    if len(tlvs) > 0 and tlvs[0].is_template is True:
                        value = utils.assemble_tlv(tlvs[0].tag, tlvs[0].value)
                        card_dgi.add_tag_value(dgi, value)
                    else:
                        for tlv in tlvs:
                            value = process_tag_decrypt(
                                rule_file, tlv.tag, tlv.value)
                            value = utils.assemble_tlv(tlv.tag, value)
                            card_dgi.add_tag_value(tlv.tag, value)
                else:
                    card_dgi.add_tag_value(dgi, dgi_data)
            cps.add_dgi(card_dgi)
    return True, cps
Beispiel #5
0
def process_dp(dp_file,rule_file):
    fh = FileHandle(dp_file,'r+')
    flag_dc = '[01]'
    flag_ec = '[02]'
    flag_q = '[03]'
    cps_list = []
    while True:
        cps = Cps()
        cps.dp_file_path = dp_file
        card_data = fh.read_line()
        if card_data == '': #数据处理完毕
            break
        index_dc = card_data.find(flag_dc)
        index_ec = card_data.find(flag_ec)
        index_q = card_data.find(flag_q)
        data_dc = card_data[index_dc + len(flag_dc) : index_ec]
        data_ec = card_data[index_ec + len(flag_ec) : index_q]
        data_q = card_data[index_q + len(flag_q) :]
        dgi_dc = process_data(data_dc,'01')
        dgi_ec = process_data(data_ec,'02')
        dgi_q = process_data(data_q,'03')
        cps.add_dgi(dgi_dc)
        cps.add_dgi(dgi_ec)
        cps.add_dgi(dgi_q)
        cps = process_EF02(cps)
        if rule_file is not None:
            cps = process_rule(rule_file,cps)
        cps_list.append(cps)
    return cps_list
Beispiel #6
0
def process_dp(dp_file, rule_file):
    fh = FileHandle(dp_file, 'rb+')
    fh.read(fh.current_offset, 8596)  #reserved
    dgi_list = get_dgi_list(fh)
    file_size = fh.file_size
    cps_list = []
    while fh.current_offset < file_size:
        card_seq = fh.read_int64_reverse(fh.current_offset)
        card_data_total_len = fh.read_int_reverse(fh.current_offset)
        cps = Cps()  #存储单个卡片数据
        cps.dp_file_path = dp_file
        pse_and_ppse_dgi = [
            'Store_PSE_1', 'Store_PSE_2', 'Store_PPSE', 'DGIF001'
        ]
        for dgi_name in dgi_list:
            dgi = Dgi()  #存储单个DGI数据
            if dgi_name in pse_and_ppse_dgi:
                if dgi_name == 'Store_PSE_1':
                    dgi = process_pse_and_ppse(fh, dgi_name, True)
                else:
                    dgi = process_pse_and_ppse(fh, dgi_name, False)
                cps.add_dgi(dgi)
                continue
            dgi_mark = fh.read_binary(fh.current_offset, 1)  #DGI标识
            if dgi_mark != '86':
                return
            next_len = get_next_len(fh)
            dgi_seq = fh.read_binary(fh.current_offset, 2)  #读取DGI序号
            dgi.name = dgi_seq
            next_len = get_next_len(fh)
            n_dgi_seq = utils.hex_str_to_int(dgi_seq)
            if n_dgi_seq <= 0x0B00:  #认为是记录
                template70 = fh.read_binary(fh.current_offset, 1)
                if template70 != '70':
                    return
                next_len = get_next_len(fh)
            dgi_data = fh.read_binary(fh.current_offset, next_len)
            if n_dgi_seq <= 0x0B00 or (dgi_seq not in do_not_parse_tlv_list
                                       and utils.is_tlv(dgi_data)):
                tlvs = utils.parse_tlv(dgi_data)
                if len(tlvs) > 0 and tlvs[0].is_template is True:
                    value = utils.assemble_tlv(tlvs[0].tag, tlvs[0].value)
                    dgi.add_tag_value(dgi_seq, value)
                else:
                    for tlv in tlvs:
                        value = utils.assemble_tlv(tlv.tag, tlv.value)
                        dgi.add_tag_value(tlv.tag, value)
            else:
                dgi.add_tag_value(dgi_seq, dgi_data)
            cps.add_dgi(dgi)
        if rule_file is not None:
            process_rule(rule_file, cps)
            process_rule_A001(rule_file, cps)
            process_rule_eps(rule_file, cps)
        cps_list.append(cps)
    return cps_list
Beispiel #7
0
def process_dp(dp_file, rule_file=None):
    cps_list = []
    xml = XmlParser(dp_file)
    batch_information_header_node = xml.get_first_node(
        xml.root_element, 'batch_information_header')
    dgi_name_list_node = xml.get_first_node(batch_information_header_node,
                                            'dgi_name_list')
    dgi_name_list = xml.get_text(dgi_name_list_node)
    dgi_name_list = dgi_name_list.split(',')
    card_data_nodes = xml.get_child_nodes(xml.root_element, 'card_data')
    for card_data_node in card_data_nodes:
        cps = Cps()
        cps.dp_file_path = dp_file
        # account_node = xml.get_first_node(card_data_node,'PAN')
        # account = xml.get_text(account_node).replace('F','')
        for dgi_name in dgi_name_list:
            dgi_node = xml.get_first_node(card_data_node, dgi_name)
            dgi_text = xml.get_text(dgi_node)
            if dgi_name == 'AID':
                cps.aid = dgi_text[4:]
                continue
            if dgi_name == 'B001' or dgi_name == 'PAN':
                continue
            elif dgi_name in ('Store_PSE_1', 'Store_PSE_2', 'Store_PPSE'):
                dgi = _process_pse_and_ppse(dgi_name, dgi_text)
            else:
                dgi_name = dgi_name[3:]  #默认DGI为DGIXXXX形式
                dgi = _parse_tlv(dgi_name, dgi_text)
                dgi.name = dgi_name
            cps.add_dgi(dgi)
        if rule_file:
            cps = _pre_process_rule(rule_file, cps)
            cps = _process_rsa(cps)
            cps = _process_8000_and_8020(cps)
            cps = _process_8400(cps)
            cps = _process_rule(rule_file, cps)
        cps_list.append(cps)
    return cps_list
Beispiel #8
0
def process_dp(dp_file, rule_file, is_mc_app=False):
    global _is_mc_app
    _is_mc_app = is_mc_app
    cps_list = []
    fh = FileHandle(dp_file, 'rb+')
    dp_header = fh.read_binary(fh.current_offset, 26)
    dgi_count = fh.read_int(fh.current_offset)
    goldpac_dgi_list = []
    for i in range(dgi_count):  #获取sddf dgi个数及所包含数据的长度
        item = GoldpacDgi()
        item.goldpac_dgi = fh.read_binary(fh.current_offset, 4)
        item.data_len = fh.read_int(fh.current_offset)
        goldpac_dgi_list.append(item)
    for item in goldpac_dgi_list:  #获取sddf dgi所包含的数据
        item.data = fh.read_binary(fh.current_offset, item.data_len)
        Log.info(item.goldpac_dgi + ' = ' + item.data)
    xml = XmlParser(rule_file)
    get_aid_list_info(xml)  #获取AID应用列表信息
    sddf_dgi_list = []
    sddf_element_nodes = xml.get_nodes(xml.root_element, 'SDDFElement')
    constans_second_app = has_second_app()
    for node in sddf_element_nodes:
        sddf_tag = xml.get_attribute(node, 'SDDFTag')
        sddf_value = xml.get_attribute(node, 'Value')
        sddf_elements = parse_sddf_element(sddf_tag, sddf_value)
        sddf_dgi_list.extend(sddf_elements)
    cps = Cps()
    cps.dp_file_path = dp_file
    pse_dgi_list, ppse_dgi_list = get_pse_and_ppse_dgi_list(sddf_dgi_list)
    for sddf_tag in sddf_dgi_list:
        if sddf_tag not in pse_dgi_list and sddf_tag not in ppse_dgi_list:  #解析TagLink节点,并生成cps数据
            cps_dgi = parse_sddf_data(xml, sddf_tag, goldpac_dgi_list)
            if cps_dgi != None:
                cps.add_dgi(cps_dgi)
    dgi_8000 = parse_8000(xml, goldpac_dgi_list, False)
    dgi_9000 = parse_9000(xml, goldpac_dgi_list, False)
    cps.add_dgi(dgi_8000)
    cps.add_dgi(dgi_9000)
    if is_mc_app:
        dgi_A006 = parse_A006(xml, goldpac_dgi_list)
        cps.add_dgi(dgi_A006)
        dgi_A016 = Dgi()
        dgi_A016.name = 'A016'
        dgi_A016.add_tag_value('A016', dgi_A006.get_value('A006'))
        dgi_8001 = Dgi()
        dgi_8001.name = '8001'
        dgi_8001.add_tag_value('8001', dgi_8000.get_value('8000'))
        dgi_9001 = Dgi()
        dgi_9001.name = '9001'
        dgi_9001.add_tag_value('9001', dgi_9000.get_value('9000'))
        cps.add_dgi(dgi_8001)
        cps.add_dgi(dgi_9001)
        cps.add_dgi(dgi_A016)
    rsa_dgi_list = split_rsa(xml, goldpac_dgi_list, False)
    for rsa_dgi in rsa_dgi_list:
        cps.add_dgi(rsa_dgi)
    pse_dgi, ppse_dgi = parse_pse_and_ppse(xml, pse_dgi_list, ppse_dgi_list,
                                           goldpac_dgi_list)
    if pse_dgi.is_empty() is False:
        cps.add_dgi(pse_dgi)
    if ppse_dgi.is_empty() is False:
        cps.add_dgi(ppse_dgi)
    if constans_second_app:
        cps = process_jetco_special_dgi(xml, goldpac_dgi_list, cps)
        cps.add_dgi(parse_8000(xml, goldpac_dgi_list, True))
        cps.add_dgi(parse_9000(xml, goldpac_dgi_list, True))
        rsa_dgi_list = split_rsa(xml, goldpac_dgi_list, True)
        for rsa_dgi in rsa_dgi_list:
            cps.add_dgi(rsa_dgi)
    cps_list.append(cps)
    return cps_list
Beispiel #9
0
    def gen_cps(self,
                session_key=None,
                second_session_key=None,
                delete80_list=[]):
        cps = Cps()
        start_perso = False  # 个人化起始行
        app_type = None  # 个人化应用类型
        prevous_req = ''  #保存上一次的数据,对于一条超长数据,需要使用两条store data指令
        prevous_req_len = 0  #
        is_jetco_app = False  #判断是否有jetco应用
        parse_perso_complete = False  #是否已经完成个人化
        has_check_status = False  #是否有检测卡片状态
        has_check_kmc = False  # 是否有检测修改过卡片KMC
        if not delete80_list:
            delete80_list = ['8201', '8202', '8203', '8204', '8205']
        while not self.log_handle.EOF:
            is_encrypted = False
            data = self.log_handle.read_line()  #每次读取一行数据进行分析
            req, resp = self._filter(data)  #过滤非指定的APDU信息,返回请求和响应数据
            if req.startswith('80E60C00'):  #解析安装参数信息
                Log.info(
                    '===================== Check Install Param ====================='
                )
                self._parse_install_cmd(req, resp)
            if req.startswith('00A40400') and not req.startswith(
                    '00A4040008A000000003000000'):
                start_perso = True  #从此行开始认定个人化开始
            if start_perso:
                if req.startswith('00A404000E315041592E5359532E4444463031'):
                    app_type = 'PSE'  #说明接下来是个人化PSE
                    continue
                elif req.startswith('00A404000E325041592E5359532E4444463031'):
                    app_type = 'PPSE'  #接下来个人化PPSE
                    continue
                elif req.startswith('00A40400'):  #应用
                    app_type = 'APP'
                    if req.startswith('00A4040009A00000047400000001'):
                        app_type = "JETCO"
                        is_jetco_app = True  # 这里判断,是因为表示是双应用数据
                    continue
                if app_type:
                    if req.startswith('80E2') and req[4:6] in (
                            '00', '60', '80', 'E0'):  #处理store data 数据
                        if resp != '9000':
                            Log.error('perso error: [APDU: %s][%s]', req, resp)
                            continue
                        #判断是否为加密数据
                        if req[4:6] in ('60', 'E0'):
                            is_encrypted = True
                        # 判断是否已经解析完个人化数据,接下来要判断卡片安全状态和修改KMC
                        if req[4:6] in ('80', 'E0') and app_type == 'APP':
                            parse_perso_complete = True
                        req = req[10:]  # 去掉命令头及长度
                        # 处理仅一条APDU指令发送store data的情况
                        if not prevous_req:
                            dgi_name = req[0:4]  # DGI名称
                            if is_jetco_app:  #默认Jetco为第二应用
                                dgi_name += '_2'
                            req = req[4:]  # 去掉DGI名称

                            # 去掉DGI后面跟随的长度
                            data_len = 0
                            if req[0:4] == 'FF00':
                                data_len = int(req[4:6], 16)
                                req = req[6:]
                            else:
                                data_len = int(req[0:2], 16)
                                req = req[2:]

                            # 如果长度和后面的数据不一致,则说明分两条APDU发送
                            if data_len * 2 != len(req):
                                prevous_req = req
                                prevous_req_len = data_len
                                continue
                        else:  # 处理需要两条APDU指令发送的情况
                            req = prevous_req + req
                            if prevous_req_len * 2 != len(req):
                                Log.error("data len error")
                                return None
                            prevous_req = ''
                            prevous_req_len = 0
                        dgi = None
                        if is_jetco_app:
                            dgi = self.parse_store_data(
                                app_type, dgi_name, req, second_session_key,
                                is_encrypted, delete80_list)
                        else:
                            dgi = self.parse_store_data(
                                app_type, dgi_name, req, session_key,
                                is_encrypted, delete80_list)
                        cps.add_dgi(dgi)
            if parse_perso_complete:
                if req.startswith('80F080'):  # 检测卡片是否设置为安全状态
                    Log.info(
                        '===================== Check Card Status ====================='
                    )
                    has_check_status = True
                    self._parse_set_status_cmd(req, resp)
                if req.startswith('80D8'):  # 检测卡片是否修改KMC
                    Log.info(
                        '===================== Check KMC ====================='
                    )
                    has_check_kmc = True
                    self._parse_modify_kmc(req, resp)
        if not has_check_status:
            Log.info(
                '===================== Check Card Status ====================='
            )
            Log.error('Not set card status during perso card.\n')
        if not has_check_kmc:
            Log.info('===================== Check KMC =====================')
            Log.error('Not modify kmc during perso card.\n')
        return cps