def get_len(fh): data_len = 0 data_str_len = fh.read_binary(fh.current_offset, 1) if data_str_len == '82': data_len = utils.hex_str_to_int(fh.read_binary(fh.current_offset, 2)) elif data_str_len == '81': data_len = utils.hex_str_to_int(fh.read_binary(fh.current_offset, 1)) else: data_len = utils.hex_str_to_int(data_str_len) return data_len
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
def get_rsa_dgi_len(data): data_len = 0 if data[0:2] == '82': data_len = 2 * utils.hex_str_to_int(data[2:6]) data = data[6:] elif data[0:2] == '81': data_len = 2 * utils.hex_str_to_int(data[2:4]) data = data[4:] else: data_len = 2 * utils.hex_str_to_int(data[0:2]) data = data[2:] return data_len, data
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
def read_int64_reverse(self, offset): '''读取4个字节,全部逆序转换为整形''' data = self.read_binary(offset, 4) hex_str = '' for i in range(0, 8, 2): hex_str += data[6 - i:6 - i + 2] return utils.hex_str_to_int(hex_str)
def read_int_reverse(self, offset): '''读取2字节,逆序转换为整形''' data = self.read_binary(offset, 2) hex_str = '' for i in range(0, 4, 2): hex_str += data[2 - i:2 - i + 2] return utils.hex_str_to_int(hex_str)
def get_next_len(fh): next_data_len = fh.read_binary(fh.current_offset, 1) if next_data_len == '81': next_data_len = fh.read_binary(fh.current_offset, 1) elif next_data_len == '82': next_data_len = fh.read_binary(fh.current_offset, 2) return utils.hex_str_to_int(next_data_len)
def is_need_delete_template(dgi): """ 通过DGI值判断数据中是否包含有模板信息 """ need_remove_prefix = False #检查是否需要删除DGI及模板数据 if utils.is_hex_str(dgi): if utils.hex_str_to_int(dgi) <= 0x0B01: need_remove_prefix = True return need_remove_prefix
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
def parse_sddf_element(sddf_tag, value): """ 分析SDDFElement节点中Value所组成的金邦达DGI 并返回金邦达DGI """ sddf_dgis = [] count = utils.hex_str_to_int(value[0:2]) temp = value[2:] for i in range(count): sddf_dgis.append(sddf_tag[0:4] + temp[i * 4:4 + i * 4]) return sddf_dgis
def _custom_sorted(dgi): number = 0 if dgi.name == 'PSE': return 0x9FFFFF elif dgi.name == 'PPSE': return 0xAFFFFF elif dgi.name == 'A001': #扩展应用应放在8020应用秘钥之前 return 0x8019 elif dgi.name == '9010': #9010需放在8010前面个人化 自主产品 同方 return 0x8009 elif dgi.name == 'Magstrip': return 0x0003 elif dgi.name == 'Aid': return 0x0001 elif dgi.name == 'Aid_2': return 0x0002 elif '_' in dgi.name: value = dgi.name.replace('_', '0') number = utils.hex_str_to_int(value) else: number = utils.hex_str_to_int(dgi.name) return number
def _process_template_and_dgi(dgi,data): int_dgi = utils.hex_str_to_int(dgi) data_len = len(data) if int_dgi <= 0x0B01 and dgi not in no_need_template_70: if data_len >= 0xFF * 2: data = '7082' + utils.get_strlen(data) + data elif data_len > 0x80 * 2: data = '7081' + utils.get_strlen(data) + data else: data = '70' + utils.get_strlen(data) + data if data_len > 0x80 * 2 and is_need_ff00_prefix: dgi += 'FF00' data = dgi + utils.get_strlen(data) + data return data
def read_int64(self, offset): '''读取4字节,并将ASCII转化为整形''' data = self.read_binary(offset, 4) return utils.hex_str_to_int(data)
def read_short(self, offset): '''按二进制顺序读取1字节,转换为整形''' data = self.read_binary(offset, 1) return utils.hex_str_to_int(data)
def _get_install_param(self, data): param_len = utils.hex_str_to_int(data[0:2]) * 2 param = data[2:2 + param_len] data = data[2 + param_len:] return data, param