From 42317a7bc46aaeb883eaa95ed4c2aab9f9e5db25 Mon Sep 17 00:00:00 2001 From: Pierre Lalet Date: Sat, 9 Dec 2023 20:21:25 +0100 Subject: [PATCH 1/2] CLI: parallelize mfkey32v2 processes --- CHANGELOG.md | 1 + software/script/chameleon_cli_unit.py | 60 +++++++++++++++++---------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 962ac59f..1b1fc399 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Parallelize mfkey32v2 processes called from CLI (@p-l-) - Added support for mifare classic value block operations (@taichunmin) - Added regression tests (@doegox) - Changed git version to version tag instead of dev tag (@taichunmin) diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index b551bb9c..b3c7e203 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -10,6 +10,7 @@ import serial.tools.list_ports import threading import struct +from multiprocessing import Pool, cpu_count from typing import Union from pathlib import Path from platform import uname @@ -1022,6 +1023,32 @@ def res_value(self, src_blk, src_type, src_key, dst_blk, dst_type, dst_key): print(f" - {CR}Restore fail.{C0}") +_KEY = re.compile("[a-fA-F0-9]{12}", flags=re.MULTILINE) + + +def _run_mfkey32v2(items): + output_str = subprocess.run( + [ + "mfkey32v2.exe" if sys.platform == "win32" else "./mfkey32v2", + items[0]["uid"], + items[0]["nt"], + items[0]["nr"], + items[0]["ar"], + items[1]["nt"], + items[1]["nr"], + items[1]["ar"], + ], + cwd=default_cwd, + capture_output=True, + check=True, + encoding="ascii", + ).stdout + sea_obj = _KEY.search(output_str) + if sea_obj is not None: + return sea_obj[0] + return None + + @hf_mf.command('elog') class HFMFELog(DeviceRequiredUnit): detection_log_size = 18 @@ -1044,30 +1071,19 @@ def decrypt_by_list(self, rs: list): msg3 = " key(s) found" n = 1 keys = set() - for i in range(len(rs)): - item0 = rs[i] - for j in range(i + 1, len(rs)): - item1 = rs[j] + with Pool(cpu_count()) as pool: + for key in pool.imap( + _run_mfkey32v2, + ( + (item0, rs[j]) + for i, item0 in enumerate(rs) + for j in range(i + 1, len(rs)) + ), + ): # TODO: if some keys already recovered, test them on item before running mfkey32 on item # TODO: if some keys already recovered, remove corresponding items - cmd_base = f"{item0['uid']} {item0['nt']} {item0['nr']} {item0['ar']}" - cmd_base += f" {item1['nt']} {item1['nr']} {item1['ar']}" - if sys.platform == "win32": - cmd_recover = f"mfkey32v2.exe {cmd_base}" - else: - cmd_recover = f"./mfkey32v2 {cmd_base}" - # print(cmd_recover) - # Found Key: [e899c526c5cd] - # subprocess.run(cmd_final, cwd=os.path.abspath("../bin/"), shell=True) - process = self.sub_process(cmd_recover) - # wait end - process.wait_process() - # get output - output_str = process.get_output_sync() - # print(output_str) - sea_obj = re.search(r"([a-fA-F0-9]{12})", output_str, flags=re.MULTILINE) - if sea_obj is not None: - keys.add(sea_obj[1]) + if key is not None: + keys.add(key) print(f"{msg1}{n}{msg2}{len(keys)}{msg3}\r", end="") n += 1 print() From cc674f16697384ed93e538aa412b52f6b369f3ea Mon Sep 17 00:00:00 2001 From: Pierre Lalet Date: Fri, 15 Dec 2023 18:07:33 +0100 Subject: [PATCH 2/2] CLI: fix mfkey32v2 call for Windows --- software/script/chameleon_cli_unit.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index b3c7e203..c47487b7 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -1029,7 +1029,7 @@ def res_value(self, src_blk, src_type, src_key, dst_blk, dst_type, dst_key): def _run_mfkey32v2(items): output_str = subprocess.run( [ - "mfkey32v2.exe" if sys.platform == "win32" else "./mfkey32v2", + default_cwd / ("mfkey32v2.exe" if sys.platform == "win32" else "mfkey32v2"), items[0]["uid"], items[0]["nt"], items[0]["nr"], @@ -1038,7 +1038,6 @@ def _run_mfkey32v2(items): items[1]["nr"], items[1]["ar"], ], - cwd=default_cwd, capture_output=True, check=True, encoding="ascii",