mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-07-14 09:03:05 -07:00
Add pm3_resources helpers for Python scripts to find tools & dicts
This commit is contained in:
parent
ffbf033937
commit
4e5d68851b
3 changed files with 117 additions and 41 deletions
|
@ -887,7 +887,12 @@ ifneq (,$(INSTALLBIN))
|
||||||
endif
|
endif
|
||||||
ifneq (,$(INSTALLSHARE))
|
ifneq (,$(INSTALLSHARE))
|
||||||
$(Q)$(INSTALLSUDO) $(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
|
$(Q)$(INSTALLSUDO) $(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
|
||||||
|
# hack ahead: inject installation path into pm3_resources.py
|
||||||
|
$(Q)sed -i 's|^TOOLS_PATH \?= \?None|TOOLS_PATH="$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLTOOLSRELPATH)"|' pyscripts/pm3_resources.py
|
||||||
|
$(Q)sed -i 's|^DICTS_PATH \?= \?None|DICTS_PATH="$(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)/dictionaries"|' pyscripts/pm3_resources.py
|
||||||
$(Q)$(INSTALLSUDO) $(CP) $(INSTALLSHARE) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
|
$(Q)$(INSTALLSUDO) $(CP) $(INSTALLSHARE) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)
|
||||||
|
$(Q)sed -i 's|^TOOLS_PATH \?=.*|TOOLS_PATH = None|' pyscripts/pm3_resources.py
|
||||||
|
$(Q)sed -i 's|^DICTS_PATH \?=.*|DICTS_PATH = None|' pyscripts/pm3_resources.py
|
||||||
endif
|
endif
|
||||||
@true
|
@true
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@ import subprocess
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
import pm3
|
import pm3
|
||||||
|
from pm3_resources import find_tool, find_dict
|
||||||
|
|
||||||
# optional color support
|
# optional color support
|
||||||
try:
|
try:
|
||||||
# pip install ansicolors
|
# pip install ansicolors
|
||||||
|
@ -42,38 +44,11 @@ BACKDOOR_KEYS = ["A396EFA4E24F", "A31667A8CEC1", "518B3354E760"]
|
||||||
|
|
||||||
NUM_SECTORS = 16
|
NUM_SECTORS = 16
|
||||||
NUM_EXTRA_SECTORS = 1
|
NUM_EXTRA_SECTORS = 1
|
||||||
DICT_DEF = "mfc_default_keys.dic"
|
|
||||||
DEFAULT_KEYS = set()
|
DEFAULT_KEYS = set()
|
||||||
if __name__ == '__main__':
|
|
||||||
DIR_PATH = os.path.dirname(os.path.abspath(sys.argv[0]))
|
|
||||||
else:
|
|
||||||
DIR_PATH = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
|
|
||||||
if os.path.basename(os.path.dirname(DIR_PATH)) == 'client':
|
staticnested_1nt_path = find_tool("staticnested_1nt")
|
||||||
# dev setup
|
staticnested_2x1nt_path = find_tool("staticnested_2x1nt_rf08s")
|
||||||
TOOLS_PATH = os.path.normpath(os.path.join(DIR_PATH,
|
staticnested_2x1nt1key_path = find_tool("staticnested_2x1nt_rf08s_1key")
|
||||||
"..", "..", "tools", "mfc", "card_only"))
|
|
||||||
DICT_DEF_PATH = os.path.normpath(os.path.join(DIR_PATH,
|
|
||||||
"..", "dictionaries", DICT_DEF))
|
|
||||||
else:
|
|
||||||
# assuming installed
|
|
||||||
TOOLS_PATH = os.path.normpath(os.path.join(DIR_PATH,
|
|
||||||
"..", "tools"))
|
|
||||||
DICT_DEF_PATH = os.path.normpath(os.path.join(DIR_PATH,
|
|
||||||
"dictionaries", DICT_DEF))
|
|
||||||
|
|
||||||
tools = {
|
|
||||||
"staticnested_1nt": os.path.join(f"{TOOLS_PATH}", "staticnested_1nt"),
|
|
||||||
"staticnested_2x1nt": os.path.join(f"{TOOLS_PATH}", "staticnested_2x1nt_rf08s"),
|
|
||||||
"staticnested_2x1nt1key": os.path.join(f"{TOOLS_PATH}", "staticnested_2x1nt_rf08s_1key"),
|
|
||||||
}
|
|
||||||
for tool, bin in tools.items():
|
|
||||||
if not os.path.isfile(bin):
|
|
||||||
if os.path.isfile(bin + ".exe"):
|
|
||||||
tools[tool] = bin + ".exe"
|
|
||||||
else:
|
|
||||||
print(f"Cannot find {bin}, abort!")
|
|
||||||
exit()
|
|
||||||
|
|
||||||
|
|
||||||
def recovery(init_check=False, final_check=False, keep=False, no_oob=False, debug=False, supply_chain=False, quiet=True, keyset=False):
|
def recovery(init_check=False, final_check=False, keep=False, no_oob=False, debug=False, supply_chain=False, quiet=True, keyset=False):
|
||||||
|
@ -193,14 +168,18 @@ def recovery(init_check=False, final_check=False, keep=False, no_oob=False, debu
|
||||||
show("----Step 1: " + color(f"{minutes:2}", fg="yellow") + " minutes " +
|
show("----Step 1: " + color(f"{minutes:2}", fg="yellow") + " minutes " +
|
||||||
color(f"{seconds:2}", fg="yellow") + " seconds -----------")
|
color(f"{seconds:2}", fg="yellow") + " seconds -----------")
|
||||||
|
|
||||||
if os.path.isfile(DICT_DEF_PATH):
|
dict_def = "mfc_default_keys.dic"
|
||||||
show(f"Loading {DICT_DEF}")
|
try:
|
||||||
with open(DICT_DEF_PATH, 'r', encoding='utf-8') as file:
|
dict_path = find_dict(dict_def)
|
||||||
|
with open(dict_path, 'r', encoding='utf-8') as file:
|
||||||
for line in file:
|
for line in file:
|
||||||
if line[0] != '#' and len(line) >= 12:
|
if line[0] != '#' and len(line) >= 12:
|
||||||
DEFAULT_KEYS.add(line[:12])
|
DEFAULT_KEYS.add(line[:12])
|
||||||
else:
|
show(f"Loaded {dict_def}")
|
||||||
show(f"Warning, {DICT_DEF} not found.")
|
except FileNotFoundError:
|
||||||
|
show(f"Warning, {dict_def} not found.")
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception(f"Error loading {dict_def}: {e}")
|
||||||
|
|
||||||
dict_dnwd = None
|
dict_dnwd = None
|
||||||
def_nt = ["" for _ in range(NUM_SECTORS)]
|
def_nt = ["" for _ in range(NUM_SECTORS)]
|
||||||
|
@ -233,12 +212,12 @@ def recovery(init_check=False, final_check=False, keep=False, no_oob=False, debu
|
||||||
continue
|
continue
|
||||||
if found_keys[sec][0] == "" and found_keys[sec][1] == "" and nt[sec][0] != nt[sec][1]:
|
if found_keys[sec][0] == "" and found_keys[sec][1] == "" and nt[sec][0] != nt[sec][1]:
|
||||||
for key_type in [0, 1]:
|
for key_type in [0, 1]:
|
||||||
cmd = [tools["staticnested_1nt"], f"{uid:08X}", f"{real_sec}",
|
cmd = [staticnested_1nt_path, f"{uid:08X}", f"{real_sec}",
|
||||||
nt[sec][key_type], nt_enc[sec][key_type], par_err[sec][key_type]]
|
nt[sec][key_type], nt_enc[sec][key_type], par_err[sec][key_type]]
|
||||||
if debug:
|
if debug:
|
||||||
print(' '.join(cmd))
|
print(' '.join(cmd))
|
||||||
subprocess.run(cmd, capture_output=True)
|
subprocess.run(cmd, capture_output=True)
|
||||||
cmd = [tools["staticnested_2x1nt"],
|
cmd = [staticnested_2x1nt_path,
|
||||||
f"keys_{uid:08x}_{real_sec:02}_{nt[sec][0]}.dic", f"keys_{uid:08x}_{real_sec:02}_{nt[sec][1]}.dic"]
|
f"keys_{uid:08x}_{real_sec:02}_{nt[sec][0]}.dic", f"keys_{uid:08x}_{real_sec:02}_{nt[sec][1]}.dic"]
|
||||||
if debug:
|
if debug:
|
||||||
print(' '.join(cmd))
|
print(' '.join(cmd))
|
||||||
|
@ -254,7 +233,7 @@ def recovery(init_check=False, final_check=False, keep=False, no_oob=False, debu
|
||||||
all_keys.update(keys_set)
|
all_keys.update(keys_set)
|
||||||
if dict_dnwd is not None and sec < NUM_SECTORS:
|
if dict_dnwd is not None and sec < NUM_SECTORS:
|
||||||
# Prioritize keys from supply-chain attack
|
# Prioritize keys from supply-chain attack
|
||||||
cmd = [tools["staticnested_2x1nt1key"], def_nt[sec], "FFFFFFFFFFFF",
|
cmd = [staticnested_2x1nt1key_path, def_nt[sec], "FFFFFFFFFFFF",
|
||||||
f"keys_{uid:08x}_{real_sec:02}_{nt[sec][key_type]}_filtered.dic"]
|
f"keys_{uid:08x}_{real_sec:02}_{nt[sec][key_type]}_filtered.dic"]
|
||||||
if debug:
|
if debug:
|
||||||
print(' '.join(cmd))
|
print(' '.join(cmd))
|
||||||
|
@ -285,7 +264,7 @@ def recovery(init_check=False, final_check=False, keep=False, no_oob=False, debu
|
||||||
key_type = 0
|
key_type = 0
|
||||||
else:
|
else:
|
||||||
key_type = 1
|
key_type = 1
|
||||||
cmd = [tools["staticnested_1nt"], f"{uid:08X}", f"{real_sec}",
|
cmd = [staticnested_1nt_path, f"{uid:08X}", f"{real_sec}",
|
||||||
nt[sec][key_type], nt_enc[sec][key_type], par_err[sec][key_type]]
|
nt[sec][key_type], nt_enc[sec][key_type], par_err[sec][key_type]]
|
||||||
if debug:
|
if debug:
|
||||||
print(' '.join(cmd))
|
print(' '.join(cmd))
|
||||||
|
@ -299,7 +278,7 @@ def recovery(init_check=False, final_check=False, keep=False, no_oob=False, debu
|
||||||
all_keys.update(keys_set)
|
all_keys.update(keys_set)
|
||||||
if dict_dnwd is not None and sec < NUM_SECTORS:
|
if dict_dnwd is not None and sec < NUM_SECTORS:
|
||||||
# Prioritize keys from supply-chain attack
|
# Prioritize keys from supply-chain attack
|
||||||
cmd = [tools["staticnested_2x1nt1key"], def_nt[sec], "FFFFFFFFFFFF",
|
cmd = [staticnested_2x1nt1key_path, def_nt[sec], "FFFFFFFFFFFF",
|
||||||
f"keys_{uid:08x}_{real_sec:02}_{nt[sec][key_type]}.dic"]
|
f"keys_{uid:08x}_{real_sec:02}_{nt[sec][key_type]}.dic"]
|
||||||
if debug:
|
if debug:
|
||||||
print(' '.join(cmd))
|
print(' '.join(cmd))
|
||||||
|
@ -509,7 +488,7 @@ def recovery(init_check=False, final_check=False, keep=False, no_oob=False, debu
|
||||||
dic = f"keys_{uid:08x}_{real_sec:02}_{nt[sec][key_type_target]}_filtered.dic"
|
dic = f"keys_{uid:08x}_{real_sec:02}_{nt[sec][key_type_target]}_filtered.dic"
|
||||||
else:
|
else:
|
||||||
dic = f"keys_{uid:08x}_{real_sec:02}_{nt[sec][key_type_target]}.dic"
|
dic = f"keys_{uid:08x}_{real_sec:02}_{nt[sec][key_type_target]}.dic"
|
||||||
cmd = [tools["staticnested_2x1nt1key"], nt[sec][key_type_source], found_keys[sec][key_type_source], dic]
|
cmd = [staticnested_2x1nt1key_path, nt[sec][key_type_source], found_keys[sec][key_type_source], dic]
|
||||||
if debug:
|
if debug:
|
||||||
print(' '.join(cmd))
|
print(' '.join(cmd))
|
||||||
result = subprocess.run(cmd, capture_output=True, text=True).stdout
|
result = subprocess.run(cmd, capture_output=True, text=True).stdout
|
||||||
|
|
92
client/pyscripts/pm3_resources.py
Normal file
92
client/pyscripts/pm3_resources.py
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
"""
|
||||||
|
Helper library to locate resources for pm3 scripts.
|
||||||
|
|
||||||
|
This module provides functionality to locate tools and dictionaries required
|
||||||
|
for pm3 scripts. It determines the paths based on the directory structure
|
||||||
|
and whether the script is being run in a development setup or an installed setup.
|
||||||
|
|
||||||
|
Functions:
|
||||||
|
find_tool(tool_name):
|
||||||
|
Finds the specified tool in the tools directory.
|
||||||
|
Args:
|
||||||
|
tool_name (str): The name of the tool to find.
|
||||||
|
Returns:
|
||||||
|
str: The full path to the tool if found, otherwise None.
|
||||||
|
|
||||||
|
find_dict(dict_name):
|
||||||
|
Find the specified dictionary in the dicts directory.
|
||||||
|
Args:
|
||||||
|
dict_name (str): The name of the dict to find.
|
||||||
|
Returns:
|
||||||
|
str: The full path to the dict if found, otherwise None.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Install script can hardcode paths in the following variables
|
||||||
|
TOOLS_PATH = None
|
||||||
|
DICTS_PATH = None
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("This is a library, don't use it as a script")
|
||||||
|
exit()
|
||||||
|
|
||||||
|
DIR_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
if TOOLS_PATH is None:
|
||||||
|
if os.path.basename(os.path.dirname(DIR_PATH)) == 'client':
|
||||||
|
# dev setup
|
||||||
|
DEV_TOOLS_PATH = os.path.normpath(os.path.join(DIR_PATH, "..", "..", "tools", "mfc", "card_only"))
|
||||||
|
if os.path.isdir(DEV_TOOLS_PATH):
|
||||||
|
TOOLS_PATH = DEV_TOOLS_PATH
|
||||||
|
|
||||||
|
if TOOLS_PATH is None:
|
||||||
|
# assuming installed without having defined TOOLS_PATH
|
||||||
|
TEST_TOOLS_PATH = os.path.normpath(os.path.join(DIR_PATH, "..", "tools"))
|
||||||
|
if os.path.isdir(TEST_TOOLS_PATH):
|
||||||
|
TOOLS_PATH = TEST_TOOLS_PATH
|
||||||
|
|
||||||
|
|
||||||
|
if DICTS_PATH is None:
|
||||||
|
DEV_DICTS_PATH = os.path.normpath(os.path.join(DIR_PATH, "..", "dictionaries"))
|
||||||
|
if os.path.isdir(DEV_DICTS_PATH):
|
||||||
|
DICTS_PATH = DEV_DICTS_PATH
|
||||||
|
|
||||||
|
|
||||||
|
def find_tool(tool_name):
|
||||||
|
"""Find the specified tool in the tools directory.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
tool_name (str): The name of the tool to find.
|
||||||
|
Returns:
|
||||||
|
str: The full path to the tool if found, otherwise None.
|
||||||
|
"""
|
||||||
|
if TOOLS_PATH is not None:
|
||||||
|
tool = os.path.join(TOOLS_PATH, tool_name)
|
||||||
|
if os.path.isfile(tool):
|
||||||
|
return tool
|
||||||
|
elif os.path.isfile(tool + ".exe"):
|
||||||
|
return tool + ".exe"
|
||||||
|
# if not found, search in the user PATH
|
||||||
|
for path in os.environ["PATH"].split(os.pathsep):
|
||||||
|
env_tool = os.path.join(path, tool_name)
|
||||||
|
if os.path.isfile(env_tool):
|
||||||
|
return env_tool
|
||||||
|
elif os.path.isfile(env_tool + ".exe"):
|
||||||
|
return env_tool + ".exe"
|
||||||
|
raise FileNotFoundError(f"Cannot find {tool_name}, abort!")
|
||||||
|
|
||||||
|
|
||||||
|
def find_dict(dict_name):
|
||||||
|
"""Find the specified dictionary in the dicts directory.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
dict_name (str): The name of the dict to find.
|
||||||
|
Returns:
|
||||||
|
str: The full path to the dict if found, otherwise None.
|
||||||
|
"""
|
||||||
|
if DICTS_PATH is not None:
|
||||||
|
dictionary = os.path.join(DICTS_PATH, dict_name)
|
||||||
|
if os.path.isfile(dictionary):
|
||||||
|
return dictionary
|
||||||
|
raise FileNotFoundError(f"Cannot find {dict_name}, abort!")
|
Loading…
Add table
Add a link
Reference in a new issue