From 84b0ad910a3fc9110b994f79ce7d10f4e69efa6b Mon Sep 17 00:00:00 2001 From: dxl <64101226@qq.com> Date: Thu, 29 Dec 2022 17:36:43 +0800 Subject: [PATCH] New cmd added. --- software/script/chameleon_cli_main.py | 4 +- software/script/chameleon_cli_unit.py | 79 ++++++++++++++++++++++++++- software/script/chameleon_cmd.py | 38 ++++++++++++- 3 files changed, 118 insertions(+), 3 deletions(-) diff --git a/software/script/chameleon_cli_main.py b/software/script/chameleon_cli_main.py index 734bd30..ca81870 100644 --- a/software/script/chameleon_cli_main.py +++ b/software/script/chameleon_cli_main.py @@ -80,6 +80,8 @@ class ChameleonCLI: 'decrypt': new_uint(chameleon_cli_unit.HFMFDetectionDecrypt, "Download log and decrypt keys"), 'help': "Mifare Classic detection log" }, + 'sim': new_uint(chameleon_cli_unit.HFMFSim, "Simulation a mifare classic card"), + 'eload': new_uint(chameleon_cli_unit.HFMFELoad, "Load data to emulator memory"), 'help': "Mifare Classic mini/1/2/4, attack/read/write" }, 'help': "high frequency tag/reader", @@ -88,7 +90,7 @@ class ChameleonCLI: 'em': { 'read': new_uint(chameleon_cli_unit.LFEMRead, "Scan em410x tag and print id"), 'write': new_uint(chameleon_cli_unit.LFEMWriteT55xx, "Write em410x id to t55xx"), - 'sim': new_uint(chameleon_cli_unit.LFEMSim, "Simulation a em410x id card."), + 'sim': new_uint(chameleon_cli_unit.LFEMSim, "Simulation a em410x id card"), 'help': "EM410x read/write/emulator", }, 'help': "low frequency tag/reader", diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index e895076..78d0733 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -604,6 +604,82 @@ class HFMFDetectionDecrypt(DeviceRequiredUnit): return +class HFMFELoad(DeviceRequiredUnit): + + def args_parser(self) -> ArgumentParserNoExit or None: + parser = ArgumentParserNoExit() + parser.add_argument('-f', '--file', type=str, required=True, help="file path") + parser.add_argument('-t', '--type', type=str, required=True, help="content type", choices=['bin', 'hex']) + return parser + + # hf mf eload -f test.bin -t bin + # hf mf eload -f test.eml -t hex + def on_exec(self, args: argparse.Namespace): + file = args.file + content_type = args.type + buffer = bytearray() + + with open(file, mode='rb') as fd: + if content_type == 'bin': + buffer.extend(fd.read()) + if content_type == 'hex': + buffer.extend(bytearray.fromhex(fd.read().decode())) + + if len(buffer) % 16 != 0: + raise Exception("Data block not align for 16 bytes") + if len(buffer) / 16 > 256: + raise Exception("Data block memory overflow") + + index = 0 + block = 0 + while index < len(buffer): + # split a block from buffer + block_data = buffer[index: index + 16] + index += 16 + # load to device + self.cmd_positive.set_mf1_block_data(block, block_data) + print('.', end='') + block += 1 + print("\n - Load success") + + +class HFMFSim(DeviceRequiredUnit): + + def args_parser(self) -> ArgumentParserNoExit or None: + parser = ArgumentParserNoExit() + parser.add_argument('--sak', type=str, required=True, help="Select AcKnowledge(hex)", metavar="hex") + parser.add_argument('--atqa', type=str, required=True, help="Answer To Request(hex)", metavar="hex") + parser.add_argument('--uid', type=str, required=True, help="Unique ID(hex)", metavar="hex") + return parser + + # hf mf sim --sak 08 --atqa 0400 --uid DEADBEEF + def on_exec(self, args: argparse.Namespace): + sak_str: str = args.sak.strip() + atqa_str: str = args.atqa.strip() + uid_str: str = args.uid.strip() + + if re.match('[a-fA-F0-9]{2}', sak_str) is not None: + sak = bytearray.fromhex(sak_str) + else: + raise Exception("SAK must be hex(2byte)") + + if re.match('[a-fA-F0-9]{4}', atqa_str) is not None: + atqa = bytearray.fromhex(atqa_str) + else: + raise Exception("ATQA must be hex(4byte)") + + if re.match('[a-fA-F0-9]+', uid_str) is not None: + uid_len = len(uid_str) + if uid_len != 8 and uid_len != 14 and uid_len != 20: + raise Exception("UID length error") + uid = bytearray.fromhex(uid_str) + else: + raise Exception("UID must be hex") + + self.cmd_positive.set_mf1_anti_collision_res(sak, atqa, uid) + print(" - Set anti-collision resources success") + + class LFEMRead(ReaderRequiredUint): def args_parser(self) -> ArgumentParserNoExit or None: @@ -716,7 +792,8 @@ class HWSlotTagType(TagTypeRequiredUint, SlotIndexRequireUint): # hw slot tagtype -t 2 def on_exec(self, args: argparse.Namespace): tag_type = args.type - self.cmd_positive.set_slot_tag_type(tag_type) + slot_index = args.slot + self.cmd_positive.set_slot_tag_type(slot_index, tag_type) print(f' - Set slot tag type success.') diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index 6777812..f2f97da 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -24,6 +24,9 @@ DATA_CMD_MF1_WRITE_ONE_BLOCK = 2009 DATA_CMD_SCAN_EM410X_TAG = 3000 DATA_CMD_WRITE_EM410X_TO_T5577 = 3001 +DATA_CMD_LOAD_MF1_BLOCK_DATA = 4000 +DATA_CMD_SET_MF1_ANTI_COLLISION_RES = 4001 + DATA_CMD_SET_EM410X_EMU_ID = 5000 DATA_CMD_SET_MF1_DETECTION_ENABLE = 5003 DATA_CMD_GET_MF1_DETECTION_COUNT = 5004 @@ -325,6 +328,32 @@ class BaseChameleonCMD: data.extend(index.to_bytes(4, "big", signed=False)) return self.device.send_cmd_sync(DATA_CMD_GET_MF1_DETECTION_RESULT, 0x00, data) + def set_mf1_block_data(self, block_start: int, block_data: bytearray): + """ + 设置MF1的模拟卡的块数据 + :param block_start: 开始设置块数据的位置,包含此位置 + :param block_data: 要设置的块数据的字节缓冲区,可包含多个块数据,自动从 block_start 递增 + :return: + """ + data = bytearray() + data.append(block_start & 0xFF) + data.extend(block_data) + return self.device.send_cmd_sync(DATA_CMD_LOAD_MF1_BLOCK_DATA, 0x00, data) + + def set_mf1_anti_collision_res(self, sak: bytearray, atqa: bytearray, uid: bytearray): + """ + 设置MF1的模拟卡的防冲撞资源信息 + :param sak: sak字节 + :param atqa: atqa数组 + :param uid: 卡号数组 + :return: + """ + data = bytearray() + data.extend(sak) + data.extend(atqa) + data.extend(uid) + return self.device.send_cmd_sync(DATA_CMD_SET_MF1_ANTI_COLLISION_RES, 0X00, data) + class NegativeResponseError(Exception): """ @@ -439,6 +468,13 @@ class PositiveChameleonCMD(BaseChameleonCMD): self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS) return ret + def set_mf1_block_data(self, block_start: int, data: bytearray): + ret = super(PositiveChameleonCMD, self).set_mf1_block_data(block_start, data) + self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS) + return ret - + def set_mf1_anti_collision_res(self, sak: int, atqa: bytearray, uid: bytearray): + ret = super(PositiveChameleonCMD, self).set_mf1_anti_collision_res(sak, atqa, uid) + self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS) + return ret