hf mfu otptear/pwdgen - now supports cliparser

This commit is contained in:
iceman1001 2021-01-04 11:11:05 +01:00
parent 4603babfe4
commit 38332d2fcf
2 changed files with 137 additions and 167 deletions

View file

@ -42,45 +42,6 @@
static int CmdHelp(const char *Cmd);
static int usage_hf_mfu_pwdgen(void) {
PrintAndLogEx(NORMAL, "Usage: hf mfu pwdgen [h|t] [r] <uid (14 hex symbols)>");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " t : selftest");
PrintAndLogEx(NORMAL, " r : read uid from tag");
PrintAndLogEx(NORMAL, " <uid> : 7 byte UID (optional)");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu pwdgen r"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu pwdgen 11223344556677"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu pwdgen t"));
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}
static int usage_hf_mfu_otp_tearoff(void) {
PrintAndLogEx(NORMAL, "Tear-off test against OTP block (no 3) on MFU tags - More help sooner or later\n");
PrintAndLogEx(NORMAL, "Usage: hf mfu otptear b <block number> i <intervalTime> l <limitTime> s <startTime> d <data before> t <data after>\n");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " b <no> : (optional) block to run the test - default block: 8 (not OTP for safety)");
PrintAndLogEx(NORMAL, " i <time> : (optional) time interval to increase in each test - default 500 us");
PrintAndLogEx(NORMAL, " l <time> : (optional) limit time to run the test - default 3000 us");
PrintAndLogEx(NORMAL, " s <time> : (optional) start time to run the test - default 0 us");
PrintAndLogEx(NORMAL, " d <data> : (optional) data to full-write before trying the OTP test - default 0x00");
PrintAndLogEx(NORMAL, " t <data> : (optional) data to write while running the OTP test - default 0x00");
PrintAndLogEx(NORMAL, " m <data> : (optional) exit criteria, if block matches this value");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " hf mfu otptear b 3");
PrintAndLogEx(NORMAL, " hf mfu otptear b 8 i 100 l 3000 s 1000");
PrintAndLogEx(NORMAL, " hf mfu otptear b 3 i 1 l 200");
PrintAndLogEx(NORMAL, " hf mfu otptear b 3 i 100 l 2500 s 200 d FFFFFFFF t EEEEEEEE");
PrintAndLogEx(NORMAL, " hf mfu otptear b 3 i 100 l 2500 s 200 d FFFFFFFF t EEEEEEEE m 00000000 -> such quite when OTP is reset");
return PM3_SUCCESS;
}
uint8_t default_3des_keys[][16] = {
{ 0x42, 0x52, 0x45, 0x41, 0x4b, 0x4d, 0x45, 0x49, 0x46, 0x59, 0x4f, 0x55, 0x43, 0x41, 0x4e, 0x21 }, // 3des std key
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // all zeroes
@ -2761,14 +2722,39 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) {
}
static int CmdHF14AMfUPwdGen(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfu pwdgen",
"Generate different passwords from known pwdgen algos",
"hf mfu pwdgen -r\n"
"hf mfu pwdgen -t\n"
"hf mfu pwdgen --uid 11223344556677"
);
void *argtable[] = {
arg_param_begin,
arg_str0("u", "uid", "<hex>", "uid (7 bytes)"),
arg_lit0("r", NULL, "read uid from tag"),
arg_lit0("t", NULL, "selftest"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
int u_len = 0;
uint8_t uid[7] = {0x00};
char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_pwdgen();
CLIGetHexWithReturn(ctx, 1, uid, &u_len);
bool use_tag = arg_get_lit(ctx, 2);
bool selftest = arg_get_lit(ctx, 3);
CLIParserFree(ctx);
if (cmdp == 't') return generator_selftest();
if (selftest)
return generator_selftest();
if (cmdp == 'r') {
if (u_len != 7) {
PrintAndLogEx(WARNING, "Key must be 7 hex bytes");
return PM3_EINVARG;
}
if (use_tag) {
// read uid from tag
clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0);
@ -2791,22 +2777,20 @@ static int CmdHF14AMfUPwdGen(const char *Cmd) {
return PM3_ESOFT;
}
memcpy(uid, card.uid, sizeof(uid));
} else {
if (param_gethex(Cmd, 0, uid, 14)) return usage_hf_mfu_pwdgen();
}
PrintAndLogEx(NORMAL, "---------------------------------");
PrintAndLogEx(NORMAL, " Using UID : %s", sprint_hex(uid, 7));
PrintAndLogEx(NORMAL, "---------------------------------");
PrintAndLogEx(NORMAL, " algo | pwd | pack");
PrintAndLogEx(NORMAL, "------+----------+-----");
PrintAndLogEx(NORMAL, " EV1 | %08X | %04X", ul_ev1_pwdgenA(uid), ul_ev1_packgenA(uid));
PrintAndLogEx(NORMAL, " Ami | %08X | %04X", ul_ev1_pwdgenB(uid), ul_ev1_packgenB(uid));
PrintAndLogEx(NORMAL, " LD | %08X | %04X", ul_ev1_pwdgenC(uid), ul_ev1_packgenC(uid));
PrintAndLogEx(NORMAL, " XYZ | %08X | %04X", ul_ev1_pwdgenD(uid), ul_ev1_packgenD(uid));
PrintAndLogEx(NORMAL, "------+----------+-----");
PrintAndLogEx(NORMAL, " Vingcard algo");
PrintAndLogEx(NORMAL, "--------------------");
PrintAndLogEx(INFO, "---------------------------------");
PrintAndLogEx(INFO, " Using UID : %s", sprint_hex(uid, 7));
PrintAndLogEx(INFO, "---------------------------------");
PrintAndLogEx(INFO, " algo | pwd | pack");
PrintAndLogEx(INFO, "------+----------+-----");
PrintAndLogEx(INFO, " EV1 | %08X | %04X", ul_ev1_pwdgenA(uid), ul_ev1_packgenA(uid));
PrintAndLogEx(INFO, " Ami | %08X | %04X", ul_ev1_pwdgenB(uid), ul_ev1_packgenB(uid));
PrintAndLogEx(INFO, " LD | %08X | %04X", ul_ev1_pwdgenC(uid), ul_ev1_packgenC(uid));
PrintAndLogEx(INFO, " XYZ | %08X | %04X", ul_ev1_pwdgenD(uid), ul_ev1_packgenD(uid));
PrintAndLogEx(INFO, "------+----------+-----");
PrintAndLogEx(INFO, " Vingcard algo");
PrintAndLogEx(INFO, "--------------------");
return PM3_SUCCESS;
}
@ -2815,85 +2799,87 @@ static int CmdHF14AMfUPwdGen(const char *Cmd) {
// Moebius et al
//
static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
uint8_t blockNoUint = 8;
uint8_t cmdp = 0;
bool errors = 0, use_match = false;
uint8_t match[4] = {0x00};
uint8_t teardata[8] = {0x00};
uint32_t interval = 500; // time in us
uint32_t timeLimit = 3000; // time in us
uint32_t startTime = 0; // time in us
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfu otptear",
"Tear-off test against OTP block",
"hf mfu otptear -b 3\n"
"hf mfu otptear -b 3 -i 100 -s 1000\n"
"hf mfu otptear -b 3 -i 1 -e 200\n"
"hf mfu otptear -b 3 -i 100 -s 200 -e 2500 -d FFFFFFFF -t EEEEEEEE\n"
"hf mfu otptear -b 3 -i 100 -s 200 -e 2500 -d FFFFFFFF -t EEEEEEEE -m 00000000 -> quite when OTP is reset"
);
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
return usage_hf_mfu_otp_tearoff();
case 'b':
blockNoUint = param_get8(Cmd, cmdp + 1);
if (blockNoUint < 2) {
PrintAndLogEx(WARNING, "Wrong block number");
errors = true;
}
cmdp += 2;
break;
case 'i':
interval = param_get32ex(Cmd, cmdp + 1, interval, 10);
cmdp += 2;
break;
case 'l':
timeLimit = param_get32ex(Cmd, cmdp + 1, timeLimit, 10);
if (timeLimit < interval) {
PrintAndLogEx(WARNING, "Wrong time limit number");
errors = true;
}
if (timeLimit > 43000) {
PrintAndLogEx(WARNING, "You can't set delay out of 1..43000 range!");
errors = true;
}
cmdp += 2;
break;
case 's':
startTime = param_get32ex(Cmd, cmdp + 1, 0, 10);
if (startTime > (timeLimit - interval)) {
PrintAndLogEx(WARNING, "Wrong start time number");
errors = true;
}
cmdp += 2;
break;
case 'd':
if (param_gethex(Cmd, cmdp + 1, teardata, 8)) {
PrintAndLogEx(WARNING, "Block data must include 8 HEX symbols");
errors = true;
}
cmdp += 2;
break;
case 't':
if (param_gethex(Cmd, cmdp + 1, teardata + 4, 8)) {
PrintAndLogEx(WARNING, "Block data must include 8 HEX symbols");
errors = true;
}
cmdp += 2;
break;
case 'm':
if (param_gethex(Cmd, cmdp + 1, match, 8)) {
PrintAndLogEx(WARNING, "Block data must include 8 HEX symbols");
errors = true;
}
use_match = true;
cmdp += 2;
break;
default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
void *argtable[] = {
arg_param_begin,
arg_u64_0("b", "blk", "<dec>", "target block (def 8)"),
arg_u64_0("i", "inc", "<dec>", "increase time steps (def 500 us)"),
arg_u64_0("e", "end", "<dec>", "end time (def 3000 us)"),
arg_u64_0("s", "start", "<dec>", "start time (def 0 us)"),
arg_str0("d", "data", "<hex>", "initialise data before run (4 bytes)"),
arg_str0("t", "test", "<hex>", "test write data (4 bytes)"),
arg_str0("m", "match", "<hex>", "exit criteria, if block matches this value (4 bytes)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, true);
uint8_t blockno = arg_get_u32_def(ctx, 1, 8);
uint32_t steps = arg_get_u32_def(ctx, 2, 500);
uint32_t end = arg_get_u32_def(ctx, 3, 3000);
uint32_t start = arg_get_u32_def(ctx, 4, 0);
int d_len = 0;
uint8_t data[4] = {0x00};
CLIGetHexWithReturn(ctx, 5, data, &d_len);
int t_len = 0;
uint8_t test[4] = {0x00};
CLIGetHexWithReturn(ctx, 6, test, &t_len);
int m_len = 0;
uint8_t match[4] = {0x00};
CLIGetHexWithReturn(ctx, 7, match, &m_len);
bool use_match = (m_len > 0);
CLIParserFree(ctx);
if (blockno < 2) {
PrintAndLogEx(WARNING, "Block number must be larger than 2.");
return PM3_EINVARG;
}
if (end < steps) {
PrintAndLogEx(WARNING, "end time smaller than increase value");
return PM3_EINVARG;
}
if (end > 43000) {
PrintAndLogEx(WARNING, "end time - out of 1 .. 43000 range");
return PM3_EINVARG;
}
if (start > (end - steps)) {
PrintAndLogEx(WARNING, "Start time larger then (end time + steps)");
return PM3_EINVARG;
}
if (errors) return usage_hf_mfu_otp_tearoff();
if (d_len && d_len != 4) {
PrintAndLogEx(WARNING, "data must be 4 hex bytes");
return PM3_EINVARG;
}
if (t_len && t_len != 4) {
PrintAndLogEx(WARNING, "test data must be 4 hex bytes");
return PM3_EINVARG;
}
if (m_len && m_len != 4) {
PrintAndLogEx(WARNING, "match data must be 4 hex bytes");
return PM3_EINVARG;
}
uint8_t teardata[8] = {0x00};
memcpy(teardata, data, sizeof(data));
memcpy(teardata + sizeof(data), test, sizeof(test));
PrintAndLogEx(INFO, "----------------- " _CYAN_("MFU Tear off") " ---------------------");
PrintAndLogEx(INFO, "Starting Tear-off test");
PrintAndLogEx(INFO, "Target block no: %u", blockNoUint);
PrintAndLogEx(INFO, "Target block no: %u", blockno);
PrintAndLogEx(INFO, "Target inital block data : %s", sprint_hex_inrow(teardata, 4));
PrintAndLogEx(INFO, "Target write block data : %s", sprint_hex_inrow(teardata + 4, 4));
PrintAndLogEx(INFO, "----------------------------------------------------");
@ -2901,23 +2887,22 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
bool got_pre = false, got_post = false, lock_on = false;
uint8_t pre[4] = {0};
uint8_t post[4] = {0};
uint32_t actualTime = startTime;
uint32_t current = start;
int phase_clear = -1;
int phase_newwr = -1;
uint8_t retries = 0;
while (actualTime <= (timeLimit - interval)) {
while (current <= (end - steps)) {
if (kbd_enter_pressed()) {
PrintAndLogEx(INFO, "\naborted via keyboard!\n");
break;
}
PrintAndLogEx(INFO, "Using tear-off delay " _GREEN_("%" PRIu32) " us", actualTime);
PrintAndLogEx(INFO, "Using tear-off delay " _GREEN_("%" PRIu32) " us", current);
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFAREU_READBL, blockNoUint, 0, 0, NULL, 0);
SendCommandMIX(CMD_HF_MIFAREU_READBL, blockno, 0, 0, NULL, 0);
PacketResponseNG resp;
got_pre = false;
@ -2930,7 +2915,7 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
}
clearCommandBuffer();
SendCommandMIX(CMD_HF_MFU_OTP_TEAROFF, blockNoUint, actualTime, 0, teardata, 8);
SendCommandMIX(CMD_HF_MFU_OTP_TEAROFF, blockno, current, 0, teardata, 8);
// we be getting ACK that we are silently ignoring here..
@ -2946,7 +2931,7 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
got_post = false;
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFAREU_READBL, blockNoUint, 0, 0, NULL, 0);
SendCommandMIX(CMD_HF_MIFAREU_READBL, blockno, 0, 0, NULL, 0);
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
isOK = resp.oldarg[0] & 0xFF;
if (isOK) {
@ -2965,19 +2950,19 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
if (memcmp(pre, post, sizeof(pre)) == 0) {
PrintAndLogEx(INFO, "Current %02d (0x%02X) %s"
, blockNoUint
, blockNoUint
, blockno
, blockno
, poststr
);
} else {
// skip first message, since its the reset write.
if (actualTime == startTime) {
if (current == start) {
PrintAndLogEx(INFO, "Inital write");
} else {
PrintAndLogEx(INFO, _CYAN_("Tear off occured") " : %02d (0x%02X) %s vs " _RED_("%s")
, blockNoUint
, blockNoUint
, blockno
, blockno
, prestr
, poststr
);
@ -2985,11 +2970,11 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
lock_on = true;
if (phase_clear == -1)
phase_clear = actualTime;
phase_clear = current;
// new write phase must be atleast 100us later..
if (phase_clear > -1 && phase_newwr == -1 && actualTime > (phase_clear + 100))
phase_newwr = actualTime;
if (phase_clear > -1 && phase_newwr == -1 && current > (phase_clear + 100))
phase_newwr = current;
}
}
@ -3017,14 +3002,14 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
PrintAndLogEx(NORMAL, "---------------------------------\n");
}
*/
if (startTime != timeLimit) {
actualTime += interval;
if (start != end) {
current += steps;
} else {
if (lock_on == false) {
if (++retries == 20) {
actualTime++;
timeLimit++;
startTime++;
current++;
end++;
start++;
retries = 0;
PrintAndLogEx(INFO, _CYAN_("Retried %u times, increased delay with 1us"), retries);
}
@ -3603,7 +3588,7 @@ static command_t CommandTable[] = {
{"keygen", CmdHF14AMfUGenDiverseKeys, AlwaysAvailable, "Generate 3DES MIFARE diversified keys"},
{"pwdgen", CmdHF14AMfUPwdGen, AlwaysAvailable, "Generate pwd from known algos"},
{"otptear", CmdHF14AMfuOtpTearoff, IfPm3Iso14443a, "Tear-off test on OTP bits"},
// {"countertear", CmdHF14AMfuEv1CounterTearoff, IfPm3Iso14443a, "Tear-off test on Ev1 Counter bits"},
// {"tear_cnt", CmdHF14AMfuEv1CounterTearoff, IfPm3Iso14443a, "Tear-off test on Ev1/NTAG Counter bits"},
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("operations") " -----------------------"},
{"cauth", CmdHF14AMfUCAuth, IfPm3Iso14443a, "Authentication - Ultralight-C"},
{"dump", CmdHF14AMfUDump, IfPm3Iso14443a, "Dump MIFARE Ultralight family tag to binary file"},

View file

@ -102,22 +102,7 @@ hf mf gen3uid
hf mf gen3blk
hf mf gen3freeze
hf mf ice
hf mfu info
hf mfu dump
hf mfu restore
hf mfu eload
hf mfu rdbl
hf mfu wrbl
hf mfu cauth
hf mfu setpwd
hf mfu setuid
hf mfu sim
hf mfu gen
hf mfu pwdgen
hf mfu otptear
hf mfdes enum
hf mfdes getuid
hf mfdes info
hw connect
hw dbg
hw detectreader