Merge branch 'main' into fix-senested-key-recovery

This commit is contained in:
GameTec-live
2025-09-02 19:40:39 +02:00
committed by GitHub
19 changed files with 555 additions and 4 deletions
+69 -1
View File
@@ -494,6 +494,25 @@ class LFHIDIdReadArgsUnit(DeviceRequiredUnit):
def on_exec(self, args: argparse.Namespace):
raise NotImplementedError()
class LFVikingIdArgsUnit(DeviceRequiredUnit):
@staticmethod
def add_card_arg(parser: ArgumentParserNoExit, required=False):
parser.add_argument("--id", type=str, required=required, help="Viking tag id", metavar="<hex>")
return parser
def before_exec(self, args: argparse.Namespace):
if not super().before_exec(args):
return False
if args.id is None or not re.match(r"^[a-fA-F0-9]{8}$", args.id):
raise ArgsParserError("ID must include 8 HEX symbols")
return True
def args_parser(self) -> ArgumentParserNoExit:
raise NotImplementedError("Please implement this")
def on_exec(self, args: argparse.Namespace):
raise NotImplementedError("Please implement this")
class TagTypeArgsUnit(DeviceRequiredUnit):
@staticmethod
def add_type_args(parser: ArgumentParserNoExit):
@@ -525,7 +544,7 @@ lf_em = lf.subgroup('em', 'EM commands')
lf_em_410x = lf_em.subgroup('410x', 'EM410x commands')
lf_hid = lf.subgroup('hid', 'HID commands')
lf_hid_prox = lf_hid.subgroup('prox', 'HID Prox commands')
lf_viking = lf.subgroup('viking', 'Viking commands')
@root.command('clear')
class RootClear(BaseCLIUnit):
@@ -3206,6 +3225,30 @@ class LFHIDProxEconfig(SlotIndexArgsAndGoUnit, LFHIDIdArgsUnit):
print(f" OEM: {CG}{oem}{C0}")
print(f" CN: {CG}{cn}{C0}")
@lf_viking.command('read')
class LFVikingRead(ReaderRequiredUnit):
def args_parser(self) -> ArgumentParserNoExit:
parser = ArgumentParserNoExit()
parser.description = 'Scan Viking tag and print id'
return parser
def on_exec(self, args: argparse.Namespace):
id = self.cmd.viking_scan()
print(f"Viking: {CG}{id.hex()}{C0}")
@lf_viking.command('write')
class LFVikingWriteT55xx(LFVikingIdArgsUnit, ReaderRequiredUnit):
def args_parser(self) -> ArgumentParserNoExit:
parser = ArgumentParserNoExit()
parser.description = 'Write Viking id to t55xx'
return self.add_card_arg(parser, required=True)
def on_exec(self, args: argparse.Namespace):
id_hex = args.id
id_bytes = bytes.fromhex(id_hex)
self.cmd.viking_write_to_t55xx(id_bytes)
print(f" - Viking ID(8H): {id_hex} write done.")
@hw_slot.command('list')
class HWSlotList(DeviceRequiredUnit):
@@ -3327,6 +3370,9 @@ class HWSlotList(DeviceRequiredUnit):
if oem > 0:
print(f' {"OEM:":40}{CY}{oem}{C0}')
print(f' {"CN:":40}{CY}{cn}{C0}')
if lf_tag_type == TagSpecificType.Viking:
id = self.cmd.viking_get_emu_id()
print(f' {"ID:":40}{CY}{id.hex().upper()}{C0}')
if current != selected:
self.cmd.set_active_slot(selected)
@@ -3463,6 +3509,28 @@ class LFEM410xEconfig(SlotIndexArgsAndGoUnit, LFEMIdArgsUnit):
print(' - Get em410x tag id success.')
print(f'ID: {response.hex()}')
@lf_viking.command('econfig')
class LFVikingEconfig(SlotIndexArgsAndGoUnit, LFVikingIdArgsUnit):
def args_parser(self) -> ArgumentParserNoExit:
parser = ArgumentParserNoExit()
parser.description = 'Set emulated Viking card id'
self.add_slot_args(parser)
self.add_card_arg(parser)
return parser
def on_exec(self, args: argparse.Namespace):
if args.id is not None:
slotinfo = self.cmd.get_slot_info()
selected = SlotNumber.from_fw(self.cmd.get_active_slot())
lf_tag_type = TagSpecificType(slotinfo[selected - 1]['lf'])
if lf_tag_type != TagSpecificType.Viking:
print(f"{CR}WARNING{C0}: Slot type not set to Viking.")
self.cmd.viking_set_emu_id(bytes.fromhex(args.id))
print(' - Set Viking tag id success.')
else:
response = self.cmd.viking_get_emu_id()
print(' - Get Viking tag id success.')
print(f'ID: {response.hex().upper()}')
@hw_slot.command('nick')
class HWSlotNick(SlotIndexArgsUnit, SenseTypeArgsUnit):
+47
View File
@@ -475,6 +475,31 @@ class ChameleonCMD:
data = struct.pack(f'!13s4s{4*len(old_keys)}s', id_bytes, new_key, b''.join(old_keys))
return self.device.send_cmd_sync(Command.HIDPROX_WRITE_TO_T55XX, data)
@expect_response(Status.LF_TAG_OK)
def viking_scan(self):
"""
Read the card number of Viking.
:return:
"""
resp = self.device.send_cmd_sync(Command.VIKING_SCAN)
if resp.status == Status.LF_TAG_OK:
resp.parsed = resp.data # uid
return resp
@expect_response(Status.LF_TAG_OK)
def viking_write_to_t55xx(self, id_bytes: bytes):
"""
Write Viking card number into T55XX.
:param id_bytes: ID card number
:return:
"""
if len(id_bytes) != 4:
raise ValueError("The id bytes length must equal 4")
data = struct.pack(f'!4s4s{4*len(old_keys)}s', id_bytes, new_key, b''.join(old_keys))
return self.device.send_cmd_sync(Command.VIKING_WRITE_TO_T55XX, data)
@expect_response(Status.SUCCESS)
def get_slot_info(self):
"""
@@ -610,6 +635,28 @@ class ChameleonCMD:
resp.parsed = struct.unpack('>BIBIBH', resp.data[:13])
return resp
@expect_response(Status.SUCCESS)
def viking_set_emu_id(self, id: bytes):
"""
Set the card number emulated by Viking.
:param id_bytes: byte of the card number
:return:
"""
if len(id) != 4:
raise ValueError("The id bytes length must equal 4")
data = struct.pack('4s', id)
return self.device.send_cmd_sync(Command.VIKING_SET_EMU_ID, data)
@expect_response(Status.SUCCESS)
def viking_get_emu_id(self):
"""
Get the emulated Viking card id
"""
resp = self.device.send_cmd_sync(Command.VIKING_GET_EMU_ID)
resp.parsed = resp.data
return resp
@expect_response(Status.SUCCESS)
def mf1_set_detection_enable(self, enabled: bool):
"""
+7 -1
View File
@@ -78,6 +78,8 @@ class Command(enum.IntEnum):
EM410X_WRITE_TO_T55XX = 3001
HIDPROX_SCAN = 3002
HIDPROX_WRITE_TO_T55XX = 3003
VIKING_SCAN = 3004
VIKING_WRITE_TO_T55XX = 3005
MF1_WRITE_EMU_BLOCK_DATA = 4000
HF14A_SET_ANTI_COLL_DATA = 4001
@@ -126,6 +128,8 @@ class Command(enum.IntEnum):
EM410X_GET_EMU_ID = 5001
HIDPROX_SET_EMU_ID = 5002
HIDPROX_GET_EMU_ID = 5003
VIKING_SET_EMU_ID = 5004
VIKING_GET_EMU_ID = 5005
@enum.unique
@@ -260,7 +264,7 @@ class TagSpecificType(enum.IntEnum):
# PAC/Stanley
# Presco
# Visa2000
# Viking
Viking = 170
# Noralsy
# Jablotron
@@ -347,6 +351,8 @@ class TagSpecificType(enum.IntEnum):
return "EM410X/64"
elif self == TagSpecificType.HIDProx:
return "HIDProx"
elif self == TagSpecificType.Viking:
return "Viking"
elif self == TagSpecificType.MIFARE_Mini:
return "Mifare Mini"
elif self == TagSpecificType.MIFARE_1024: