Merge branch 'master' into master

Signed-off-by: Gary Bell <github@whiteneon.com>
This commit is contained in:
Gary Bell
2024-08-16 20:06:22 -04:00
committed by GitHub
37 changed files with 613 additions and 257 deletions
+4
View File
@@ -5,6 +5,10 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
## [unreleased][unreleased]
- Fixed missing require of ansicolors in `lf_hid_bulkclone_v2.lua` script (@whiteneon)
- Added `lf_t55xx_reset.lua` - a script to aid in quickly resetting t55xx chips (@whiteneon)
- Added more fingerprinting in `hf mf info` (@doegox)
- Added --issue and (--emu)lator support to `hf iclass encode` command (@micsen)
- Added custom CTF Wiegand format from Defcon32 with comments (@micsen)
- Added native output grabbing for Python and Lua: less hacky than `output_grabber.py`, should work on ProxSpace as well (@doegox)
- Changed `hf mf chk/fchk`: added option `--no-default` to skip loading the usual ~61 hardcoded keys (@doegox)
- Fixed `hf mf wipe` to detect properly write errors (@doegox)
- Fixed `hf mf fchk` which was leaving the RF field on when interrupted by keyboard (@doegox)
+1 -1
View File
@@ -394,7 +394,7 @@ ifeq ($(PYTHON_FOUND),1)
endif
#######################################################################################################
# macOS doesn't like this params
# clang doesn't like this params
#MYCFLAGS += --param max-completely-peeled-insns=1000 --param max-completely-peel-times=10000
MYCFLAGS += -O3
+2
View File
@@ -2529,3 +2529,5 @@ bd6af9754c18
60FCB3C42ABF
# key for hotel in greece
722F24F0722F
# STS Hotel 2A
535453535453
@@ -1,3 +0,0 @@
#!/bin/bash
../../pm3 -c "script run testembedded_grab.py" -i
@@ -1,4 +1,13 @@
local pm3 = require("pm3")
p=pm3.pm3()
p:console("hw status")
print(p.name)
p:console("hw version")
for line in p.grabbed_output:gmatch("[^\r\n]+") do
if line:find("Unique ID") or line:find("uC:") then
print(line)
end
end
print("Device:", p.name)
p:console("Rem passthru remark! :coffee:", true)
@@ -2,5 +2,13 @@
import pm3
p=pm3.pm3()
p.console("hw status")
p.console("hw version")
for line in p.grabbed_output.split('\n'):
if "Unique ID" in line:
print(line)
if "uC:" in line:
print(line)
print("Device:", p.name)
p.console("Rem passthru remark! :coffee:", True)
@@ -1,13 +0,0 @@
#!/usr/bin/env python3
import pm3
from output_grabber import OutputGrabber
out = OutputGrabber()
p=pm3.pm3()
print("Device:", p.name)
with out:
p.console("hw status")
for line in out.captured_output.split('\n'):
if "Unique ID" in line:
print(line)
+10 -1
View File
@@ -2,5 +2,14 @@
local pm3 = require("pm3")
p=pm3.pm3("/dev/ttyACM0")
p:console("hw status")
print(p.name)
p:console("hw version")
for line in p.grabbed_output:gmatch("[^\r\n]+") do
if line:find("Unique ID") or line:find("uC:") then
print(line)
end
end
print("Device:", p.name)
p:console("Rem passthru remark! :coffee:", true)
@@ -1,3 +0,0 @@
#!/bin/bash
PYTHONPATH=../../pyscripts ipython3 -i ./test_grab.py
@@ -2,5 +2,13 @@
import pm3
p=pm3.pm3("/dev/ttyACM0")
p.console("hw status")
p.console("hw version")
for line in p.grabbed_output.split('\n'):
if "Unique ID" in line:
print(line)
if "uC:" in line:
print(line)
print("Device:", p.name)
p.console("Rem passthru remark! :coffee:", True)
@@ -1,13 +0,0 @@
#!/usr/bin/env python3
import pm3
from output_grabber import OutputGrabber
out = OutputGrabber()
p=pm3.pm3("/dev/ttyACM0")
print("Device:", p.name)
with out:
p.console("hw status")
for line in out.captured_output.split('\n'):
if "Unique ID" in line:
print(line)
+4 -1
View File
@@ -16,10 +16,13 @@
#ifndef LIBPM3_H
#define LIBPM3_H
#include <stdbool.h>
typedef struct pm3_device pm3;
pm3 *pm3_open(const char *port);
int pm3_console(pm3 *dev, const char *cmd);
int pm3_console(pm3 *dev, const char *cmd, bool passthru);
const char *pm3_grabbed_output_get(pm3 *dev);
const char *pm3_name_get(pm3 *dev);
void pm3_close(pm3 *dev);
pm3 *pm3_get_current_dev(void);
+61 -56
View File
@@ -11,7 +11,7 @@
# * 16 random keys with keyA==keyB in each sector: ~30 min
# * 24 random keys, some reused across sectors: <1 min
#
# Doegox, 2024
# Doegox, 2024, cf https://eprint.iacr.org/2024/1275 for more info
import os
import sys
@@ -19,7 +19,6 @@ import time
import subprocess
import argparse
import pm3
from output_grabber import OutputGrabber
# optional color support
try:
# pip install ansicolors
@@ -33,18 +32,25 @@ BACKDOOR_RF08S = "A396EFA4E24F"
NUM_SECTORS = 16
if os.path.basename(os.path.dirname(os.path.dirname(sys.argv[0]))) == 'client':
# dev setup
TOOLS_PATH = f"{os.path.dirname(sys.argv[0])}/../../tools/mfc/card_only"
TOOLS_PATH = os.path.normpath(os.path.join(f"{os.path.dirname(sys.argv[0])}",
"..", "..", "tools", "mfc", "card_only"))
else:
# assuming installed
TOOLS_PATH = f"{os.path.dirname(sys.argv[0])}/../tools"
TOOLS_PATH = os.path.normpath(os.path.join(f"{os.path.dirname(sys.argv[0])}",
"..", "tools"))
STATICNESTED_1NT = f"{TOOLS_PATH}/staticnested_1nt"
STATICNESTED_2X1NT = f"{TOOLS_PATH}/staticnested_2x1nt_rf08s"
STATICNESTED_2X1NT1KEY = f"{TOOLS_PATH}/staticnested_2x1nt_rf08s_1key"
for bin in [STATICNESTED_1NT, STATICNESTED_2X1NT, STATICNESTED_2X1NT1KEY]:
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):
print(f"Cannot find {bin}, abort!")
exit()
if os.path.isfile(bin + ".exe"):
tools[tool] = bin + ".exe"
else:
print(f"Cannot find {bin}, abort!")
exit()
parser = argparse.ArgumentParser(description='A script combining staticnested* tools '
'to recover all keys from a FM11RF08S card.')
@@ -54,27 +60,24 @@ parser.add_argument('-d', '--debug', action='store_true', help='Enable debug mod
args = parser.parse_args()
start_time = time.time()
out = OutputGrabber()
p = pm3.pm3()
restore_color = False
with out:
p.console("prefs get color")
p.console("prefs set color --off")
for line in out.captured_output.split('\n'):
p.console("prefs get color")
p.console("prefs set color --off")
for line in p.grabbed_output.split('\n'):
if "ansi" in line:
restore_color = True
with out:
p.console("hf 14a read")
p.console("hf 14a read")
uid = None
for line in out.captured_output.split('\n'):
for line in p.grabbed_output.split('\n'):
if "UID:" in line:
uid = int(line[10:].replace(' ', ''), 16)
if uid is None:
print("Card not found")
if restore_color:
with out:
p.console("prefs set color --ansi")
p.console("prefs set color --ansi")
_ = p.grabbed_output
exit()
print("UID: " + color(f"{uid:08X}", fg="green"))
@@ -87,9 +90,8 @@ def print_key(sec, key_type, key):
found_keys = [["", ""] for _ in range(NUM_SECTORS)]
if not args.no_init_check:
print("Checking default keys...")
with out:
p.console("hf mf fchk")
for line in out.captured_output.split('\n'):
p.console("hf mf fchk")
for line in p.grabbed_output.split('\n'):
if "[+] 0" in line:
res = [x.strip() for x in line.split('|')]
sec = int(res[0][4:])
@@ -104,18 +106,17 @@ nt = [["", ""] for _ in range(NUM_SECTORS)]
nt_enc = [["", ""] for _ in range(NUM_SECTORS)]
par_err = [["", ""] for _ in range(NUM_SECTORS)]
print("Getting nonces...")
with out:
for sec in range(NUM_SECTORS):
blk = sec * 4
if found_keys[sec][0] == "" or found_keys[sec][1] == "":
# Even if one key already found, we'll need both nt
for key_type in [0, 1]:
cmd = f"hf mf isen -n1 --blk {blk} -c {key_type+4} --key {BACKDOOR_RF08S}"
p.console(cmd)
cmd += f" --c2 {key_type}"
p.console(cmd)
for sec in range(NUM_SECTORS):
blk = sec * 4
if found_keys[sec][0] == "" or found_keys[sec][1] == "":
# Even if one key already found, we'll need both nt
for key_type in [0, 1]:
cmd = f"hf mf isen -n1 --blk {blk} -c {key_type+4} --key {BACKDOOR_RF08S}"
p.console(cmd)
cmd += f" --c2 {key_type}"
p.console(cmd)
print("Processing traces...")
for line in out.captured_output.split('\n'):
for line in p.grabbed_output.split('\n'):
if "nested cmd: 64" in line or "nested cmd: 65" in line:
sec = int(line[24:26], 16)//4
key_type = int(line[21:23], 16) - 0x64
@@ -128,6 +129,17 @@ for line in out.captured_output.split('\n'):
nt_enc[sec][key_type] = data
data = line[128:136]
par_err[sec][key_type] = data
for sec in range(NUM_SECTORS):
if found_keys[sec][0] == "" or found_keys[sec][1] == "":
for key_type in [0, 1]:
if (nt[sec][key_type] == "" or
nt_enc[sec][key_type] == "" or
par_err[sec][key_type] == ""):
print("Error, could not collect nonces, abort")
if restore_color:
p.console("prefs set color --ansi")
_ = p.grabbed_output
exit()
print("Running staticnested_1nt & 2x1nt when doable...")
keys = [[set(), set()] for _ in range(NUM_SECTORS)]
@@ -140,12 +152,12 @@ for sec in range(NUM_SECTORS):
continue
if found_keys[sec][0] == "" and found_keys[sec][1] == "" and nt[sec][0] != nt[sec][1]:
for key_type in [0, 1]:
cmd = [STATICNESTED_1NT, f"{uid:08X}", f"{sec}",
cmd = [tools["staticnested_1nt"], f"{uid:08X}", f"{sec}",
nt[sec][key_type], nt_enc[sec][key_type], par_err[sec][key_type]]
if args.debug:
print(' '.join(cmd))
subprocess.run(cmd, capture_output=True)
cmd = [STATICNESTED_2X1NT,
cmd = [tools["staticnested_2x1nt"],
f"keys_{uid:08x}_{sec:02}_{nt[sec][0]}.dic", f"keys_{uid:08x}_{sec:02}_{nt[sec][1]}.dic"]
if args.debug:
print(' '.join(cmd))
@@ -165,7 +177,7 @@ for sec in range(NUM_SECTORS):
key_type = 0
else:
key_type = 1
cmd = [STATICNESTED_1NT, f"{uid:08X}", f"{sec}",
cmd = [tools["staticnested_1nt"], f"{uid:08X}", f"{sec}",
nt[sec][key_type], nt_enc[sec][key_type], par_err[sec][key_type]]
if args.debug:
print(' '.join(cmd))
@@ -217,9 +229,8 @@ for sec in range(NUM_SECTORS):
cmd = f"hf mf fchk --blk {sec * 4} -{kt} -f {dic} --no-default"
if args.debug:
print(cmd)
with out:
p.console(cmd)
for line in out.captured_output.split('\n'):
p.console(cmd)
for line in p.grabbed_output.split('\n'):
if "aborted via keyboard" in line:
abort = True
if "found:" in line:
@@ -244,9 +255,8 @@ for sec in range(NUM_SECTORS):
cmd = f"hf mf fchk --blk {sec * 4} -{kt} -f {dic} --no-default"
if args.debug:
print(cmd)
with out:
p.console(cmd)
for line in out.captured_output.split('\n'):
p.console(cmd)
for line in p.grabbed_output.split('\n'):
if "aborted via keyboard" in line:
abort = True
if "found:" in line:
@@ -266,9 +276,8 @@ for sec in range(NUM_SECTORS):
cmd = f"hf mf fchk --blk {sec * 4} -{kt} -f {dic} --no-default"
if args.debug:
print(cmd)
with out:
p.console(cmd)
for line in out.captured_output.split('\n'):
p.console(cmd)
for line in p.grabbed_output.split('\n'):
if "aborted via keyboard" in line:
abort = True
if "found:" in line:
@@ -293,7 +302,7 @@ for sec in range(NUM_SECTORS):
dic = f"keys_{uid:08x}_{sec:02}_{nt[sec][key_type_target]}_filtered.dic"
else:
dic = f"keys_{uid:08x}_{sec:02}_{nt[sec][key_type_target]}.dic"
cmd = [STATICNESTED_2X1NT1KEY, nt[sec][key_type_source], found_keys[sec][key_type_source], dic]
cmd = [tools["staticnested_2x1nt1key"], nt[sec][key_type_source], found_keys[sec][key_type_source], dic]
if args.debug:
print(' '.join(cmd))
result = subprocess.run(cmd, capture_output=True, text=True).stdout
@@ -309,9 +318,8 @@ for sec in range(NUM_SECTORS):
cmd += f" -k {k}"
if args.debug:
print(cmd)
with out:
p.console(cmd)
for line in out.captured_output.split('\n'):
p.console(cmd)
for line in p.grabbed_output.split('\n'):
if "aborted via keyboard" in line:
abort = True
if "found:" in line:
@@ -323,8 +331,8 @@ for sec in range(NUM_SECTORS):
if abort:
break
if restore_color:
with out:
p.console("prefs set color --ansi")
p.console("prefs set color --ansi")
_ = p.grabbed_output
if abort:
print("Brute-forcing phase aborted via keyboard!")
@@ -374,10 +382,7 @@ else:
cmd = f"hf mf fchk -f keys_{uid:08x}.dic --no-default --dump"
if args.debug:
print(cmd)
with out:
p.console(cmd)
for line in out.captured_output.split('\n'):
print(line)
p.console(cmd, passthru = True)
elapsed_time = time.time() - start_time
minutes = int(elapsed_time // 60)
-81
View File
@@ -1,81 +0,0 @@
import os
import sys
import threading
import time
# From https://stackoverflow.com/a/29834357
class OutputGrabber(object):
"""
Class used to grab standard output or another stream.
"""
escape_char = "\b"
def __init__(self, stream=None, threaded=False):
self.origstream = stream
self.threaded = threaded
if self.origstream is None:
self.origstream = sys.stdout
self.origstreamfd = self.origstream.fileno()
self.captured_output = ""
def __enter__(self):
self.start()
return self
def __exit__(self, type, value, traceback):
self.stop()
def start(self):
"""
Start capturing the stream data.
"""
self.captured_output = ""
# Create a pipe so the stream can be captured:
self.pipe_out, self.pipe_in = os.pipe()
# Save a copy of the stream:
self.streamfd = os.dup(self.origstreamfd)
# Replace the original stream with our write pipe:
os.dup2(self.pipe_in, self.origstreamfd)
if self.threaded:
# Start thread that will read the stream:
self.workerThread = threading.Thread(target=self.readOutput)
self.workerThread.start()
# Make sure that the thread is running and os.read() has executed:
time.sleep(0.01)
def stop(self):
"""
Stop capturing the stream data and save the text in `captured_output`.
"""
# Print the escape character to make the readOutput method stop:
self.origstream.write(self.escape_char)
# Flush the stream to make sure all our data goes in before
# the escape character:
self.origstream.flush()
if self.threaded:
# wait until the thread finishes so we are sure that
# we have until the last character:
self.workerThread.join()
else:
self.readOutput()
# Close the pipe:
os.close(self.pipe_in)
os.close(self.pipe_out)
# Restore the original stream:
os.dup2(self.streamfd, self.origstreamfd)
# Close the duplicate stream:
os.close(self.streamfd)
def readOutput(self):
"""
Read the stream data (one byte at a time)
and save the text in `captured_output`.
"""
while True:
char = os.read(self.pipe_out,1).decode(self.origstream.encoding, errors='replace')
if not char or self.escape_char in char:
break
self.captured_output += char
if __name__ == "__main__":
print("This is a library, don't use it as a script")
+9 -11
View File
@@ -1,13 +1,10 @@
# This file was automatically generated by SWIG (http://www.swig.org).
# Version 4.0.2
# This file was automatically generated by SWIG (https://www.swig.org).
# Version 4.2.1
#
# Do not make changes to this file unless you know what you are doing--modify
# Do not make changes to this file unless you know what you are doing - modify
# the SWIG interface file instead.
from sys import version_info as _swig_python_version_info
if _swig_python_version_info < (2, 7, 0):
raise RuntimeError("Python 2.7 or later required")
# Import the low-level C/C++ module
if __package__ or "." in __name__:
from . import _pm3
@@ -29,10 +26,10 @@ def _swig_repr(self):
def _swig_setattr_nondynamic_instance_variable(set):
def set_instance_attr(self, name, value):
if name == "thisown":
self.this.own(value)
elif name == "this":
if name == "this":
set(self, name, value)
elif name == "thisown":
self.this.own(value)
elif hasattr(self, name) and isinstance(getattr(type(self), name), property):
set(self, name, value)
else:
@@ -69,9 +66,10 @@ class pm3(object):
_pm3.pm3_swiginit(self, _pm3.new_pm3(*args))
__swig_destroy__ = _pm3.delete_pm3
def console(self, cmd):
return _pm3.pm3_console(self, cmd)
def console(self, cmd, passthru=False):
return _pm3.pm3_console(self, cmd, passthru)
name = property(_pm3.pm3_name_get)
grabbed_output = property(_pm3.pm3_grabbed_output_get)
# Register pm3 in _pm3:
_pm3.pm3_swigregister(pm3)
+53 -25
View File
@@ -4579,20 +4579,24 @@ static int CmdHFiClassEncode(const char *Cmd) {
"Use either --bin or --wiegand/--fc/--cn",
"hf iclass encode --bin 10001111100000001010100011 --ki 0 -> FC 31 CN 337 (H10301)\n"
"hf iclass encode -w H10301 --fc 31 --cn 337 --ki 0 -> FC 31 CN 337 (H10301)\n"
"hf iclass encode --bin 10001111100000001010100011 --ki 0 --elite -> FC 31 CN 337 (H10301), writing w elite key"
"hf iclass encode --bin 10001111100000001010100011 --ki 0 --elite -> FC 31 CN 337 (H10301), writing w elite key\n"
"hf iclass encode -w H10301 --fc 31 --cn 337 --emu -> Writes the ecoded data to emulator memory\n"
"When using emulator you have to first load a credential into emulator memory"
);
void *argtable[] = {
arg_param_begin,
arg_str0(NULL, "bin", "<bin>", "Binary string i.e 0001001001"),
arg_int1(NULL, "ki", "<dec>", "Key index to select key from memory 'hf iclass managekeys'"),
arg_int0(NULL, "ki", "<dec>", "Key index to select key from memory 'hf iclass managekeys'"),
arg_lit0(NULL, "credit", "key is assumed to be the credit key"),
arg_lit0(NULL, "elite", "elite computations applied to key"),
arg_lit0(NULL, "raw", "no computations applied to key"),
arg_str0(NULL, "enckey", "<hex>", "3DES transport key, 16 hex bytes"),
arg_u64_0(NULL, "fc", "<dec>", "facility code"),
arg_u64_0(NULL, "cn", "<dec>", "card number"),
arg_u64_0(NULL, "issue", "<dec>", "issue level"),
arg_str0("w", "wiegand", "<format>", "see " _YELLOW_("`wiegand list`") " for available formats"),
arg_lit0(NULL, "emu", "Write to emulation memory instead of card"),
arg_lit0(NULL, "shallow", "use shallow (ASK) reader modulation instead of OOK"),
arg_lit0("v", NULL, "verbose (print encoded blocks)"),
arg_param_end
@@ -4605,19 +4609,29 @@ static int CmdHFiClassEncode(const char *Cmd) {
CLIGetStrWithReturn(ctx, 1, bin, &bin_len);
int key_nr = arg_get_int_def(ctx, 2, -1);
bool auth = false;
bool use_emulator_memory = arg_get_lit(ctx, 11);
bool auth = false;
uint8_t key[8] = {0};
if (key_nr >= 0) {
if (key_nr < ICLASS_KEYS_MAX) {
auth = true;
memcpy(key, iClass_Key_Table[key_nr], 8);
PrintAndLogEx(SUCCESS, "Using key[%d] " _GREEN_("%s"), key_nr, sprint_hex(iClass_Key_Table[key_nr], 8));
} else {
PrintAndLogEx(ERR, "Key number is invalid");
CLIParserFree(ctx);
// If we use emulator memory skip key requirement
if (!use_emulator_memory) {
if (key_nr < 0) {
PrintAndLogEx(ERR, "Missing required arg for --ki or --emu");
return PM3_EINVARG;
}
if (key_nr >= 0) {
if (key_nr < ICLASS_KEYS_MAX) {
auth = true;
memcpy(key, iClass_Key_Table[key_nr], 8);
PrintAndLogEx(SUCCESS, "Using key[%d] " _GREEN_("%s"), key_nr, sprint_hex(iClass_Key_Table[key_nr], 8));
} else {
PrintAndLogEx(ERR, "Key number is invalid");
CLIParserFree(ctx);
return PM3_EINVARG;
}
}
}
bool use_credit_key = arg_get_lit(ctx, 3);
@@ -4635,13 +4649,15 @@ static int CmdHFiClassEncode(const char *Cmd) {
memset(&card, 0, sizeof(wiegand_card_t));
card.FacilityCode = arg_get_u32_def(ctx, 7, 0);
card.CardNumber = arg_get_u32_def(ctx, 8, 0);
card.IssueLevel = arg_get_u32_def(ctx, 9, 0);
char format[16] = {0};
int format_len = 0;
CLIParamStrToBuf(arg_get_str(ctx, 9), (uint8_t *)format, sizeof(format), &format_len);
CLIParamStrToBuf(arg_get_str(ctx, 10), (uint8_t *)format, sizeof(format), &format_len);
bool shallow_mod = arg_get_lit(ctx, 10);
bool verbose = arg_get_lit(ctx, 11);
bool shallow_mod = arg_get_lit(ctx, 12);
bool verbose = arg_get_lit(ctx, 13);
CLIParserFree(ctx);
@@ -4669,7 +4685,12 @@ static int CmdHFiClassEncode(const char *Cmd) {
}
if (have_enc_key == false) {
use_sc = IsCardHelperPresent(false);
// The IsCardHelperPresent function clears the emulator memory
if (use_emulator_memory) {
use_sc = false;
} else {
use_sc = IsCardHelperPresent(false);
}
if (use_sc == false) {
size_t keylen = 0;
int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&enckeyptr, &keylen);
@@ -4774,15 +4795,22 @@ static int CmdHFiClassEncode(const char *Cmd) {
int isok = PM3_SUCCESS;
// write
for (uint8_t i = 0; i < 4; i++) {
isok = iclass_write_block(6 + i, credential + (i * 8), NULL, key, use_credit_key, elite, rawkey, false, false, auth, shallow_mod);
switch (isok) {
case PM3_SUCCESS:
PrintAndLogEx(SUCCESS, "Write block %d/0x0%x ( " _GREEN_("ok") " ) --> " _YELLOW_("%s"), 6 + i, 6 + i, sprint_hex_inrow(credential + (i * 8), 8));
break;
default:
PrintAndLogEx(INFO, "Write block %d/0x0%x ( " _RED_("fail") " )", 6 + i, 6 + i);
break;
if (use_emulator_memory) {
uint16_t byte_sent = 0;
iclass_upload_emul(credential, sizeof(credential), 6 * PICOPASS_BLOCK_SIZE, &byte_sent);
PrintAndLogEx(SUCCESS, "uploaded " _YELLOW_("%d") " bytes to emulator memory", byte_sent);
PrintAndLogEx(HINT, "You are now ready to simulate. See " _YELLOW_("`hf iclass sim -h`"));
} else {
for (uint8_t i = 0; i < 4; i++) {
isok = iclass_write_block(6 + i, credential + (i * 8), NULL, key, use_credit_key, elite, rawkey, false, false, auth, shallow_mod);
switch (isok) {
case PM3_SUCCESS:
PrintAndLogEx(SUCCESS, "Write block %d/0x0%x ( " _GREEN_("ok") " ) --> " _YELLOW_("%s"), 6 + i, 6 + i, sprint_hex_inrow(credential + (i * 8), 8));
break;
default:
PrintAndLogEx(INFO, "Write block %d/0x0%x ( " _RED_("fail") " )", 6 + i, 6 + i);
break;
}
}
}
return isok;
@@ -4962,7 +4990,7 @@ static int CmdHFiClassSAM(const char *Cmd) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Wiegand decode");
wiegand_message_t packed = initialize_message_object(top, mid, bot, 0);
wiegand_message_t packed = initialize_message_object(top, mid, bot, strlen(binstr));
HIDTryUnpack(&packed);
PrintAndLogEx(NORMAL, "");
+52 -13
View File
@@ -9512,9 +9512,9 @@ static int CmdHF14AMfInfo(const char *Cmd) {
return PM3_EMALLOC;
}
uint8_t blockdata[MFBLOCK_SIZE] = {0};
res = mfCheckKeys_fast(sectorsCnt, true, true, 1, keycnt, keyBlock, e_sector, false, verbose);
if (res == PM3_SUCCESS || res == PM3_EPARTIAL) {
uint8_t blockdata[MFBLOCK_SIZE] = {0};
if (e_sector[0].foundKey[MF_KEY_A]) {
PrintAndLogEx(SUCCESS, "Sector 0 key A... " _GREEN_("%012" PRIX64), e_sector[0].Key[MF_KEY_A]);
@@ -9539,20 +9539,59 @@ static int CmdHF14AMfInfo(const char *Cmd) {
if (e_sector[1].foundKey[MF_KEY_A]) {
PrintAndLogEx(SUCCESS, "Sector 1 key A... " _GREEN_("%012" PRIX64), e_sector[1].Key[MF_KEY_A]);
}
}
if (fKeyType != 0xFF) {
PrintAndLogEx(SUCCESS, "Block 0.......... %s", sprint_hex(blockdata, MFBLOCK_SIZE));
uint8_t k08s[6] = {0xA3, 0x96, 0xEF, 0xA4, 0xE2, 0x4F};
if (mfReadBlock(0, 4, k08s, blockdata) == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "Backdoor key..... " _RED_("%02X%02X%02X%02X%02X%02X"), k08s[0], k08s[1], k08s[2], k08s[3], k08s[4], k08s[5]);
fKeyType = MF_KEY_BD08S;
}
uint8_t k08[6] = {0xA3, 0x16, 0x67, 0xA8, 0xCE, 0xC1};
if (mfReadBlock(0, 4, k08, blockdata) == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "Backdoor key..... " _RED_("%02X%02X%02X%02X%02X%02X"), k08[0], k08[1], k08[2], k08[3], k08[4], k08[5]);
fKeyType = MF_KEY_BD08;
}
if (fKeyType != 0xFF) {
PrintAndLogEx(SUCCESS, "Block 0.......... %s", sprint_hex(blockdata, MFBLOCK_SIZE));
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Fingerprint"));
if (fKeyType != 0xFF) {
// cards with known backdoor
if (memcmp(blockdata + 8, "\x62\x63\x64\x65\x66\x67\x68\x69", 8) == 0) {
// backdoor might be present, or just a clone reusing Fudan MF data...
PrintAndLogEx(SUCCESS, "Fudan based card");
} else if (card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0
&& (blockdata[8] == 0x03 || blockdata[8] == 0x04) && blockdata[15] == 0x90) {
PrintAndLogEx(SUCCESS, "Fudan FM11RF08S");
} else if (card.sak == 0x08 && memcmp(blockdata + 5, "\x00\x03\x00\x10", 4) == 0
&& blockdata[15] == 0x90) {
PrintAndLogEx(SUCCESS, "Fudan FM11RF08S-7B");
} else if (card.sak == 0x08 && memcmp(blockdata + 5, "\x08\x04\x00", 3) == 0
&& (blockdata[8] >= 0x01 && blockdata[8] <= 0x03) && blockdata[15] == 0x1D) {
PrintAndLogEx(SUCCESS, "Fudan FM11RF08");
} else if (card.sak == 0x88 && memcmp(blockdata + 5, "\x88\x04\x00\x43", 4) == 0) {
PrintAndLogEx(SUCCESS, "Infineon SLE66R35");
} else if (card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x44", 4) == 0) {
PrintAndLogEx(SUCCESS, "NXP MF1ICS5003");
} else if (card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x45", 4) == 0) {
PrintAndLogEx(SUCCESS, "NXP MF1ICS5004");
} else if (fKeyType == MF_KEY_BD08 || fKeyType == MF_KEY_BD08S) {
PrintAndLogEx(SUCCESS, _RED_("Unknown card with backdoor, please report details!"));
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Fingerprint"));
if (
(blockdata[8] == 0x03 && blockdata[15] == 0x90) ||
(blockdata[9] == 0x02 && blockdata[14] == 0x1D) ||
(blockdata[8] == 0x04 && blockdata[15] == 0x90) ||
(memcmp(blockdata + 8, "\x62\x63\x64\x65\x66\x67\x68\x69", 8) == 0)
) {
PrintAndLogEx(SUCCESS, "FUDAN based card");
// other cards
if (card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x46", 4) == 0) {
PrintAndLogEx(SUCCESS, "NXP MF1ICS5005");
} else if (card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x47", 4) == 0) {
PrintAndLogEx(SUCCESS, "NXP MF1ICS5006");
} else if (card.sak == 0x09 && memcmp(blockdata + 5, "\x89\x04\x00\x47", 4) == 0) {
PrintAndLogEx(SUCCESS, "NXP MF1ICS2006");
} else if (card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\x48", 4) == 0) {
PrintAndLogEx(SUCCESS, "NXP MF1ICS5007");
} else if (card.sak == 0x08 && memcmp(blockdata + 5, "\x88\x04\x00\xc0", 4) == 0) {
PrintAndLogEx(SUCCESS, "NXP MF1ICS5035");
}
if (e_sector[1].foundKey[MF_KEY_A] && (e_sector[1].Key[MF_KEY_A] == 0x2A2C13CC242A)) {
+16 -2
View File
@@ -53,18 +53,32 @@ void pm3_close(pm3_device_t *dev) {
msleep(100); // Make sure command is sent before killing client
CloseProxmark(dev);
}
free_grabber();
}
int pm3_console(pm3_device_t *dev, const char *cmd) {
int pm3_console(pm3_device_t *dev, const char *cmd, bool passthru) {
// For now, there is no real device context:
(void) dev;
return CommandReceived(cmd);
uint8_t prev_printAndLog = g_printAndLog;
if (! passthru) {
g_printAndLog |= PRINTANDLOG_GRAB;
g_printAndLog &= ~PRINTANDLOG_PRINT;
}
int ret = CommandReceived(cmd);
g_printAndLog = prev_printAndLog;
return ret;
}
const char *pm3_name_get(pm3_device_t *dev) {
return dev->g_conn->serial_port_name;
}
const char *pm3_grabbed_output_get(pm3_device_t *dev) {
char *tmp = g_grabbed_output.ptr;
g_grabbed_output.idx = 0;
return tmp;
}
pm3_device_t *pm3_get_current_dev(void) {
return g_session.current_device;
}
+9 -1
View File
@@ -8,6 +8,13 @@
/* Strip "pm3_" from API functions for SWIG */
%rename("%(strip:[pm3_])s") "";
%feature("immutable","1") pm3_current_dev;
#ifdef PYWRAP
#include <Python.h>
%typemap(default) bool passthru {
$1 = Py_False;
}
#endif
typedef struct {
%extend {
pm3() {
@@ -30,8 +37,9 @@ typedef struct {
pm3_close($self);
}
}
int console(char *cmd);
int console(char *cmd, bool passthru = false);
char const * const name;
char const * const grabbed_output;
}
} pm3;
//%nodefaultctor device;
+32 -2
View File
@@ -2768,18 +2768,23 @@ static int _wrap_pm3_console(lua_State *L) {
int SWIG_arg = 0;
pm3 *arg1 = (pm3 *) 0 ;
char *arg2 = (char *) 0 ;
bool arg3 = (bool) false ;
int result;
SWIG_check_num_args("pm3::console", 2, 2)
SWIG_check_num_args("pm3::console", 2, 3)
if (!SWIG_isptrtype(L, 1)) SWIG_fail_arg("pm3::console", 1, "pm3 *");
if (!SWIG_lua_isnilstring(L, 2)) SWIG_fail_arg("pm3::console", 2, "char *");
if (lua_gettop(L) >= 3 && !lua_isboolean(L, 3)) SWIG_fail_arg("pm3::console", 3, "bool");
if (!SWIG_IsOK(SWIG_ConvertPtr(L, 1, (void **)&arg1, SWIGTYPE_p_pm3, 0))) {
SWIG_fail_ptr("pm3_console", 1, SWIGTYPE_p_pm3);
}
arg2 = (char *)lua_tostring(L, 2);
result = (int)pm3_console(arg1, arg2);
if (lua_gettop(L) >= 3) {
arg3 = (lua_toboolean(L, 3) != 0);
}
result = (int)pm3_console(arg1, arg2, arg3);
lua_pushnumber(L, (lua_Number) result);
SWIG_arg++;
return SWIG_arg;
@@ -2815,6 +2820,30 @@ fail:
}
static int _wrap_pm3_grabbed_output_get(lua_State *L) {
int SWIG_arg = 0;
pm3 *arg1 = (pm3 *) 0 ;
char *result = 0 ;
SWIG_check_num_args("pm3::grabbed_output", 1, 1)
if (!SWIG_isptrtype(L, 1)) SWIG_fail_arg("pm3::grabbed_output", 1, "pm3 *");
if (!SWIG_IsOK(SWIG_ConvertPtr(L, 1, (void **)&arg1, SWIGTYPE_p_pm3, 0))) {
SWIG_fail_ptr("pm3_grabbed_output_get", 1, SWIGTYPE_p_pm3);
}
result = (char *)pm3_grabbed_output_get(arg1);
lua_pushstring(L, (const char *)result);
SWIG_arg++;
return SWIG_arg;
fail:
SWIGUNUSED;
lua_error(L);
return 0;
}
static void swig_delete_pm3(void *obj) {
pm3 *arg1 = (pm3 *) obj;
delete_pm3(arg1);
@@ -2829,6 +2858,7 @@ static int _proxy__wrap_new_pm3(lua_State *L) {
}
static swig_lua_attribute swig_pm3_attributes[] = {
{ "name", _wrap_pm3_name_get, SWIG_Lua_set_immutable },
{ "grabbed_output", _wrap_pm3_grabbed_output_get, SWIG_Lua_set_immutable },
{0, 0, 0}
};
static swig_lua_method swig_pm3_methods[] = {

Some files were not shown because too many files have changed in this diff Show More