From b6fd1a869475c20a96d15d624de3f02863a0067c Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 17 Oct 2020 11:53:26 +0200 Subject: [PATCH 01/20] Need Qt >= 5.1 for qunsetenv --- client/src/proxgui.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/proxgui.cpp b/client/src/proxgui.cpp index cec64d8be..525e64da6 100644 --- a/client/src/proxgui.cpp +++ b/client/src/proxgui.cpp @@ -60,7 +60,9 @@ extern "C" void InitGraphics(int argc, char **argv, char *script_cmds_file, char if (getenv("DISPLAY") == NULL) return; #endif +#if QT_VERSION >= 0x050100 qunsetenv("SESSION_MANAGER"); +#endif main_loop_thread = new WorkerThread(script_cmds_file, script_cmd, stayInCommandLoop); gui = new ProxGuiQT(argc, argv, main_loop_thread); } From c2d5a7d745537ffbeb591963b1b013384b0f4f2a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Oct 2020 16:16:07 +0200 Subject: [PATCH 02/20] cliparser, making sure both hex and string arrays fits into max size of 256 bytes --- client/deps/cliparser/cliparser.c | 60 ++++++++++++++++++------------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/client/deps/cliparser/cliparser.c b/client/deps/cliparser/cliparser.c index cc82fc334..a601e6490 100644 --- a/client/deps/cliparser/cliparser.c +++ b/client/deps/cliparser/cliparser.c @@ -203,34 +203,33 @@ int CLIParserParseStringEx(CLIParserContext *ctx, const char *str, void *vargtab int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) { *datalen = 0; - int ibuf = 0; - uint8_t tmp_buf[512] = {0}; - int res = CLIParamStrToBuf(argstr, tmp_buf, maxdatalen * 2, &ibuf); // *2 because here HEX + int tmplen = 0; + uint8_t tmpstr[(256 * 2) + 1] = {0}; + + // concat all strings in argstr into tmpstr[] + // + int res = CLIParamStrToBuf(argstr, tmpstr, sizeof(tmpstr), &tmplen); if (res) { - printf("Parameter error: buffer overflow.\n"); - fflush(stdout); return res; } - if (ibuf == 0) { + if (tmplen == 0) { return res; } - switch (param_gethex_to_eol((char *)tmp_buf, 0, data, maxdatalen, datalen)) { + res = param_gethex_to_eol((char*)tmpstr, 0, data, maxdatalen, datalen); + switch (res) { case 1: - printf("Parameter error: Invalid HEX value.\n"); - fflush(stdout); - return 1; + printf("Parameter error: Invalid HEX value\n"); + break; case 2: - printf("Parameter error: parameter too large.\n"); - fflush(stdout); - return 2; + printf("Parameter error: parameter too large\n"); + break; case 3: - printf("Parameter error: Hex string must have even number of digits.\n"); - fflush(stdout); - return 3; + printf("Parameter error: Hex string must have EVEN number of digits\n"); + break; } - - return 0; + fflush(stdout); + return res; } int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) { @@ -238,26 +237,37 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int if (!argstr->count) return 0; - uint8_t tmp_buf[512] = {0}; + uint8_t tmpstr[(256 * 2) + 1] = {0}; int ibuf = 0; for (int i = 0; i < argstr->count; i++) { + int len = strlen(argstr->sval[i]); - memcpy(&tmp_buf[ibuf], argstr->sval[i], len); + + if (len > ( (sizeof(tmpstr) / 2 ) - ibuf)) { + printf("Parameter error: string too long (%i chars), expect MAX %zu chars\n", len + ibuf, (sizeof(tmpstr) / 2)); + fflush(stdout); + return 2; + } + + memcpy(&tmpstr[ibuf], argstr->sval[i], len); + ibuf += len; } - tmp_buf[ibuf] = 0; + + ibuf = MIN(ibuf, (sizeof(tmpstr) / 2)); + tmpstr[ibuf] = 0; - if (!ibuf) + if (ibuf == 0) return 0; - if (ibuf + 1 > maxdatalen) { - printf("Parameter error: string too long, expect max %i chars\n", maxdatalen - 1); + if (ibuf > maxdatalen) { + printf("Parameter error: string too long (%i chars), expected MAX %i chars\n", ibuf, maxdatalen); fflush(stdout); return 2; } - memcpy(data, tmp_buf, ibuf + 1); + memcpy(data, tmpstr, ibuf + 1); *datalen = ibuf; return 0; } From 66182ea85c21f78cd0efae91a8a64438ef80fc9f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Oct 2020 16:33:00 +0200 Subject: [PATCH 03/20] lf motorola clone - to properly use cliparser --- client/src/cmdlfmotorola.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/client/src/cmdlfmotorola.c b/client/src/cmdlfmotorola.c index a717e6e89..c7cd16021 100644 --- a/client/src/cmdlfmotorola.c +++ b/client/src/cmdlfmotorola.c @@ -156,26 +156,36 @@ static int CmdMotorolaClone(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf motorola clone", - "Enables cloning of Motorola card with specified uid onto T55x7\n" - "defaults to 64.", - "lf motorola clone a0000000a0002021" + "clone Motorola UID to T55x7 or Q5/T5555 tag\n" + "defaults to 64 bit format", + "lf motorola clone -r a0000000a0002021" ); void *argtable[] = { arg_param_begin, - arg_strx1(NULL, NULL, "", NULL), + arg_strx1("r", "raw", "", "raw bytes"), + arg_lit0("q", "Q5", "optional - specify writing to Q5/T5555 tag"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); CLIGetHexWithReturn(ctx, 1, data, &datalen); + bool is_t5555 = arg_get_lit(ctx, 2); CLIParserFree(ctx); //TODO add selection of chip for Q5 or T55x7 - // data[0] = T5555_FIXED | T5555_SET_BITRATE(32 | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT; + + PrintAndLogEx(INFO, "Target chip " _YELLOW_("%s"), (is_t5555) ? "Q5/T5555" : "T55x7"); // config for Motorola 64 format (RF/32;PSK1 with RF/2; Maxblock=2) - PrintAndLogEx(INFO, "Preparing to clone Motorola 64bit tag with RawID %s", sprint_hex(data, datalen)); - blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT); + PrintAndLogEx(INFO, "Preparing to clone Motorola 64bit tag"); + PrintAndLogEx(INFO, "Using raw " _GREEN_("%s"), sprint_hex_inrow(data, datalen)); + + if (is_t5555) + blocks[0] = T5555_FIXED | T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT; + else + blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT); + + blocks[1] = bytes_to_num(data, 4); blocks[2] = bytes_to_num(data + 4, 4); From 2fbffe08947006e3ace85f34c5cee4e1a764d880 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Oct 2020 16:33:46 +0200 Subject: [PATCH 04/20] hf 14b sim - better help text and must use PUPI --- client/src/cmdhf14b.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index 9056b26a9..85898fe04 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -130,7 +130,6 @@ static int CmdHF14BSim(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf 14b sim", "Simulate a ISO/IEC 14443 type B tag with 4 byte UID / PUPI", - "hf 14b sim\n" "hf 14b sim -u 11AA33BB" ); @@ -139,7 +138,7 @@ static int CmdHF14BSim(const char *Cmd) { arg_strx0("u", "uid", "hex", "4byte UID/PUPI"), arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIExecWithReturn(ctx, Cmd, argtable, false); uint8_t pupi[4]; int n = 0; @@ -150,6 +149,9 @@ static int CmdHF14BSim(const char *Cmd) { PrintAndLogEx(FAILED, "failed to read pupi"); return PM3_EINVARG; } + + PrintAndLogEx(INFO, "Simulate with PUPI : " _GREEN_("%s"), sprint_hex_inrow(pupi, sizeof(pupi))); + PrintAndLogEx(INFO, "Press pm3-button to abort simulation"); clearCommandBuffer(); SendCommandNG(CMD_HF_ISO14443B_SIMULATE, pupi, sizeof(pupi)); return PM3_SUCCESS; From 4d1b0f182eb7b54b60df9a7f89fea5b9b2f49780 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Oct 2020 16:36:58 +0200 Subject: [PATCH 05/20] hf iclass sim - textual --- client/src/cmdhficlass.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 9e61e5d89..4393787ad 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -816,6 +816,8 @@ static int CmdHFiClassSim(const char *Cmd) { case ICLASS_SIM_MODE_CSN_DEFAULT: case ICLASS_SIM_MODE_FULL: default: { + PrintAndLogEx(INFO, "Starting iCLASS simulation"); + PrintAndLogEx(INFO, "press " _YELLOW_("`enter`") " to cancel"); uint8_t numberOfCSNs = 0; clearCommandBuffer(); SendCommandMIX(CMD_HF_ICLASS_SIMULATE, sim_type, numberOfCSNs, 1, CSN, 8); From abaef4de6c7a7846e0767bee849a91f4aa59c6ac Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Oct 2020 17:47:58 +0200 Subject: [PATCH 06/20] hf 15 demod - dont calc crc if we didnt get enough data --- client/src/cmdhf15.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 407815a93..6b1b1a51b 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -766,7 +766,9 @@ static int CmdHF15Demod(const char *Cmd) { for (i = 0; i < k; i++) PrintAndLogEx(SUCCESS, "# %2d: %02x ", i, outBuf[i]); - PrintAndLogEx(SUCCESS, "CRC %04x", Crc15(outBuf, k - 2)); + if (k > 2) { + PrintAndLogEx(SUCCESS, "CRC %04x", Crc15(outBuf, k - 2)); + } return PM3_SUCCESS; } From 3b5cb752a440134e6b4a4014425a9a57b6cd402c Mon Sep 17 00:00:00 2001 From: tcprst Date: Sat, 17 Oct 2020 15:00:07 -0400 Subject: [PATCH 07/20] ST25TA drop field on error & buffer fixes --- client/src/cmdhfst.c | 157 +++++++++++++++++++++++++++++-------------- 1 file changed, 108 insertions(+), 49 deletions(-) diff --git a/client/src/cmdhfst.c b/client/src/cmdhfst.c index 39b47146c..2f94e355b 100644 --- a/client/src/cmdhfst.c +++ b/client/src/cmdhfst.c @@ -215,15 +215,20 @@ int infoHF_ST(void) { int aSELECT_AID_n = 0; param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n); int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } - if (resplen < 2) + if (resplen < 2) { + DropField(); return PM3_ESOFT; + } uint16_t sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); return PM3_ESOFT; } @@ -235,12 +240,15 @@ int infoHF_ST(void) { int aSELECT_FILE_CC_n = 0; param_gethex_to_eol("00a4000c02e103", 0, aSELECT_FILE_CC, sizeof(aSELECT_FILE_CC), &aSELECT_FILE_CC_n); res = ExchangeAPDU14a(aSELECT_FILE_CC, aSELECT_FILE_CC_n, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "Selecting CC file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); return PM3_ESOFT; } @@ -248,12 +256,15 @@ int infoHF_ST(void) { int aREAD_CC_n = 0; param_gethex_to_eol("00b000000f", 0, aREAD_CC, sizeof(aREAD_CC), &aREAD_CC_n); res = ExchangeAPDU14a(aREAD_CC, aREAD_CC_n, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "reading CC file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); return PM3_ESOFT; } @@ -265,12 +276,15 @@ int infoHF_ST(void) { int aSELECT_FILE_SYS_n = 0; param_gethex_to_eol("00a4000c02e101", 0, aSELECT_FILE_SYS, sizeof(aSELECT_FILE_SYS), &aSELECT_FILE_SYS_n); res = ExchangeAPDU14a(aSELECT_FILE_SYS, aSELECT_FILE_SYS_n, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "Selecting system file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); return PM3_ESOFT; } @@ -280,12 +294,15 @@ int infoHF_ST(void) { int aREAD_SYS_n = 0; param_gethex_to_eol("00b0000012", 0, aREAD_SYS, sizeof(aREAD_SYS), &aREAD_SYS_n); res = ExchangeAPDU14a(aREAD_SYS, aREAD_SYS_n, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "reading system file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); return PM3_ESOFT; } print_st_system_info(response, resplen - 2); @@ -340,7 +357,7 @@ static int cmd_hf_st_sim(const char *Cmd) { static int cmd_hf_st_ndef(const char *Cmd) { int pwdlen = 0; - uint8_t pwd[16] = {0}; + uint8_t pwd[16 + 1] = {0}; bool with_pwd = false; CLIParserContext *ctx; @@ -377,15 +394,21 @@ static int cmd_hf_st_ndef(const char *Cmd) { int aSELECT_AID_n = 0; param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n); int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } - if (resplen < 2) + if (resplen < 2) { + DropField(); return PM3_ESOFT; + } uint16_t sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + printf("Dropping field: 3\n"); + DropField(); return PM3_ESOFT; } @@ -397,12 +420,15 @@ static int cmd_hf_st_ndef(const char *Cmd) { int aSELECT_FILE_NDEF_n = 0; param_gethex_to_eol("00a4000c020001", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n); res = ExchangeAPDU14a(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "Selecting NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); return PM3_ESOFT; } @@ -412,8 +438,10 @@ static int cmd_hf_st_ndef(const char *Cmd) { int aVERIFY_n = 0; param_gethex_to_eol("0020000100", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n); res = ExchangeAPDU14a(aVERIFY, aVERIFY_n, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } sw = get_sw(response, resplen); if (sw == 0x6300) { @@ -421,12 +449,15 @@ static int cmd_hf_st_ndef(const char *Cmd) { param_gethex_to_eol("0020000110", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n); memcpy(aVERIFY + aVERIFY_n, pwd, pwdlen); res = ExchangeAPDU14a(aVERIFY, aVERIFY_n + pwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "Verify password failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); return PM3_ESOFT; } } @@ -437,12 +468,15 @@ static int cmd_hf_st_ndef(const char *Cmd) { int aREAD_NDEF_n = 0; param_gethex_to_eol("00b000001d", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n); res = ExchangeAPDU14a(aREAD_NDEF, aREAD_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "reading NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); return PM3_ESOFT; } @@ -453,7 +487,7 @@ static int cmd_hf_st_ndef(const char *Cmd) { static int cmd_hf_st_protect(const char *Cmd) { int pwdlen = 0; - uint8_t pwd[16] = {0}; + uint8_t pwd[16 + 1] = {0}; int statelen = 3; uint8_t state[3] = {0x26, 0, 0x02}; @@ -490,25 +524,23 @@ static int cmd_hf_st_protect(const char *Cmd) { if (enable_protection && disable_protection) { PrintAndLogEx(ERR, "Must specify either enable or disable protection, not both"); return PM3_EINVARG; - } else { - if (enable_protection) { - state[0] = 0x28; - } - if (disable_protection) { - state[0] = 0x26; - } + } + if (enable_protection) { + state[0] = 0x28; } - + if (disable_protection) { + state[0] = 0x26; + } + if (read_protection && write_protection) { PrintAndLogEx(ERR, "Must specify either read or write protection, not both"); return PM3_EINVARG; - } else { - if (read_protection) { - state[2] = 0x01; - } - if (write_protection) { - state[2] = 0x02; - } + } + if (read_protection) { + state[2] = 0x01; + } + if (write_protection) { + state[2] = 0x02; } if (pwdlen != 16) { @@ -526,15 +558,20 @@ static int cmd_hf_st_protect(const char *Cmd) { int aSELECT_AID_n = 0; param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n); int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } - if (resplen < 2) + if (resplen < 2) { + DropField(); return PM3_ESOFT; + } uint16_t sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); return PM3_ESOFT; } @@ -546,12 +583,15 @@ static int cmd_hf_st_protect(const char *Cmd) { int aSELECT_FILE_NDEF_n = 0; param_gethex_to_eol("00a4000c020001", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n); res = ExchangeAPDU14a(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "Selecting NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); return PM3_ESOFT; } @@ -562,12 +602,15 @@ static int cmd_hf_st_protect(const char *Cmd) { param_gethex_to_eol("0020000210", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n); memcpy(aVERIFY + aVERIFY_n, pwd, pwdlen); res = ExchangeAPDU14a(aVERIFY, aVERIFY_n + pwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "Verify password failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); return PM3_ESOFT; } @@ -578,12 +621,15 @@ static int cmd_hf_st_protect(const char *Cmd) { param_gethex_to_eol("00", 0, aPROTECT, sizeof(aPROTECT), &aPROTECT_n); memcpy(aPROTECT + aPROTECT_n, state, statelen); res = ExchangeAPDU14a(aPROTECT, aPROTECT_n + statelen, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "changing protection failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); return PM3_ESOFT; } @@ -596,9 +642,9 @@ static int cmd_hf_st_protect(const char *Cmd) { static int cmd_hf_st_pwd(const char *Cmd) { int pwdlen = 0; - uint8_t pwd[16] = {0}; + uint8_t pwd[16 + 1] = {0}; int newpwdlen = 0; - uint8_t newpwd[16] = {0}; + uint8_t newpwd[16 + 1] = {0}; int changePwdlen = 4; uint8_t changePwd[4] = {0x24, 0x00, 0x01, 0x10}; bool change_read_password = false; @@ -629,15 +675,14 @@ static int cmd_hf_st_pwd(const char *Cmd) { if (change_read_password && change_write_password) { PrintAndLogEx(ERR, "Must specify either read or write, not both"); return PM3_EINVARG; - } else { - if (change_read_password) { - changePwd[2] = 0x01; - } - if (change_write_password) { - changePwd[2] = 0x02; - } } - + if (change_read_password) { + changePwd[2] = 0x01; + } + if (change_write_password) { + changePwd[2] = 0x02; + } + if (pwdlen != 16) { PrintAndLogEx(ERR, "Original write password must be 16 hex bytes"); return PM3_EINVARG; @@ -657,15 +702,20 @@ static int cmd_hf_st_pwd(const char *Cmd) { int aSELECT_AID_n = 0; param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n); int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } - if (resplen < 2) + if (resplen < 2) { + DropField(); return PM3_ESOFT; + } uint16_t sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); return PM3_ESOFT; } @@ -677,12 +727,15 @@ static int cmd_hf_st_pwd(const char *Cmd) { int aSELECT_FILE_NDEF_n = 0; param_gethex_to_eol("00a4000c020001", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n); res = ExchangeAPDU14a(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "Selecting NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); return PM3_ESOFT; } @@ -693,12 +746,15 @@ static int cmd_hf_st_pwd(const char *Cmd) { param_gethex_to_eol("0020000210", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n); memcpy(aVERIFY + aVERIFY_n, pwd, pwdlen); res = ExchangeAPDU14a(aVERIFY, aVERIFY_n + pwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "Verify password failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); return PM3_ESOFT; } @@ -711,12 +767,15 @@ static int cmd_hf_st_pwd(const char *Cmd) { memcpy(aCHG_PWD + aCHG_PWD_n, changePwd, changePwdlen); memcpy(aCHG_PWD + aCHG_PWD_n + changePwdlen, newpwd, newpwdlen); res = ExchangeAPDU14a(aCHG_PWD, aCHG_PWD_n + changePwdlen + newpwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) + if (res) { + DropField(); return res; + } sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "password change failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); return PM3_ESOFT; } PrintAndLogEx(SUCCESS, " %s password changed", ((changePwd[2] & 0x01) == 0x01) ? _YELLOW_("read") : _YELLOW_("write")); From 4a5e58281b3023b6799627576fdb0c1f5b4b5a8c Mon Sep 17 00:00:00 2001 From: tcprst Date: Sat, 17 Oct 2020 15:00:55 -0400 Subject: [PATCH 08/20] remove debug print --- client/src/cmdhfst.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/src/cmdhfst.c b/client/src/cmdhfst.c index 2f94e355b..502e6413a 100644 --- a/client/src/cmdhfst.c +++ b/client/src/cmdhfst.c @@ -407,7 +407,6 @@ static int cmd_hf_st_ndef(const char *Cmd) { uint16_t sw = get_sw(response, resplen); if (sw != 0x9000) { PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - printf("Dropping field: 3\n"); DropField(); return PM3_ESOFT; } From 8c7f1e0609c436c1aeb54d2f041eced2ccebef08 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Oct 2020 23:09:34 +0200 Subject: [PATCH 09/20] fix bad param sanity checks --- client/src/cmdhficlass.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 4393787ad..bd5254c1b 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -1563,7 +1563,7 @@ static int CmdHFiClassDump(const char *Cmd) { } } - if ((use_replay + rawkey + elite) > 0) { + if ((use_replay + rawkey + elite) > 1) { PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'"); errors = true; } @@ -1920,7 +1920,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { if (got_blockno == false) errors = true; - if ((use_replay + rawkey + elite) > 0) { + if ((use_replay + rawkey + elite) > 1) { PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'"); errors = true; } @@ -2252,7 +2252,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { if (got_blockno == false) errors = true; - if ((use_replay + rawkey + elite) > 0) { + if ((use_replay + rawkey + elite) > 1) { PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'"); errors = true; } @@ -2807,6 +2807,12 @@ static void add_key(uint8_t *key) { } } +/* +static int iclass_chk_keys(void) { + return PM3_SUCCESS; +} +*/ + static int CmdHFiClassCheckKeys(const char *Cmd) { // empty string @@ -3290,7 +3296,6 @@ static int CmdHFiClassPermuteKey(const char *Cmd) { uint8_t key[8] = {0}; uint8_t data[16] = {0}; - bool isReverse = false; int len = 0; CLIParserContext *ctx; @@ -3307,7 +3312,7 @@ static int CmdHFiClassPermuteKey(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, false); - isReverse = arg_get_lit(ctx, 1); + bool isReverse = arg_get_lit(ctx, 1); CLIGetHexWithReturn(ctx, 2, data, &len); @@ -3329,6 +3334,28 @@ static int CmdHFiClassPermuteKey(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHFiClassAutopwn(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf iclass autopwn", + "Tries to check keys, if found, dump card and save file", + "hf iclass autopwn\n"); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + + // Check keys. + + // dump + + PrintAndLogEx(INFO, "to be implemented"); + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("operations") " ---------------------"}, {"help", CmdHelp, AlwaysAvailable, "This help"}, @@ -3343,7 +3370,8 @@ static command_t CommandTable[] = { {"wrbl", CmdHFiClass_WriteBlock, IfPm3Iclass, "[options..] Write Picopass / iCLASS block"}, {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("recovery") " ---------------------"}, - {"chk", CmdHFiClassCheckKeys, AlwaysAvailable, "[options..] Check keys"}, + {"autopwn", CmdHFiClassAutopwn, IfPm3Iclass, "[options..] Automatic key recovery tool for iCLASS"}, + {"chk", CmdHFiClassCheckKeys, IfPm3Iclass, "[options..] Check keys"}, {"loclass", CmdHFiClass_loclass, AlwaysAvailable, "[options..] Use loclass to perform bruteforce reader attack"}, {"lookup", CmdHFiClassLookUp, AlwaysAvailable, "[options..] Uses authentication trace to check for key in dictionary file"}, {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("simulation") " ---------------------"}, From 2b77c732b1debdf73b42939d43f7ecc86f720ebe Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Oct 2020 23:10:23 +0200 Subject: [PATCH 10/20] hf 15 demod, and others uses cliparser and different output --- client/src/cmdhf15.c | 230 +++++++++++++++++++++++++++---------------- 1 file changed, 145 insertions(+), 85 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 6b1b1a51b..da433a010 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -34,6 +34,7 @@ #include "crc16.h" // iso15 crc #include "cmddata.h" // getsamples #include "fileutils.h" // savefileEML +#include "cliparser.h" #define FrameSOF Iso15693FrameSOF #define Logic0 Iso15693Logic0 @@ -209,16 +210,6 @@ const productName_t uidmapping[] = { static int CmdHF15Help(const char *Cmd); -static int usage_15_demod(void) { - PrintAndLogEx(NORMAL, "Tries to demodulate / decode ISO15693, from downloaded samples.\n" - "Gather samples with 'hf 15 read' / 'hf 15 record'"); - return PM3_SUCCESS; -} -static int usage_15_samples(void) { - PrintAndLogEx(NORMAL, "Acquire samples as Reader (enables carrier, send inquiry\n" - "and download it to graphbuffer. Try 'hf 15 demod' to try to demodulate/decode signal"); - return PM3_SUCCESS; -} static int usage_15_info(void) { PrintAndLogEx(NORMAL, "Uses the optional command 'get_systeminfo' 0x2B to try and extract information\n" "command may fail, depending on tag.\n" @@ -235,36 +226,7 @@ static int usage_15_info(void) { _YELLOW_("\thf 15 info u")); return PM3_SUCCESS; } -static int usage_15_record(void) { - PrintAndLogEx(NORMAL, "Record activity without enabling carrier"); - return PM3_SUCCESS; -} -static int usage_15_reader(void) { - PrintAndLogEx(NORMAL, "This command identifies a ISO 15693 tag\n" - "\n" - "Usage: hf 15 reader [h]\n" - "Options:\n" - "\th this help\n" - "\t1 read once\n" - "\n" - "Example:\n" - _YELLOW_("\thf 15 reader\n") - _YELLOW_("\thf 15 reader 1\n")); - return PM3_SUCCESS; -} -static int usage_15_sim(void) { - PrintAndLogEx(NORMAL, "Usage: hf 15 sim \n" - "\n" - "Example:\n" - _YELLOW_("\thf 15 sim E016240000000000")); - return PM3_SUCCESS; -} -static int usage_15_findafi(void) { - PrintAndLogEx(NORMAL, "This command attempts to brute force AFI of an ISO15693 tag\n" - "\n" - "Usage: hf 15 findafi"); - return PM3_SUCCESS; -} + static int usage_15_writeafi(void) { PrintAndLogEx(NORMAL, "Usage: hf 15 writeafi \n" "\tuid (either): \n" @@ -358,17 +320,6 @@ static int usage_15_readmulti(void) { "\t 1-6, number of pages"); return PM3_SUCCESS; } -static int usage_15_csetuid(void) { - PrintAndLogEx(NORMAL, "Set UID for magic Chinese card (only works with such cards)\n" - "\n" - "Usage: hf 15 csetuid \n" - "Options:\n" - "\tuid : <8B hex> full UID eg E011223344556677\n" - "\n" - "Example:\n" - _YELLOW_("\thf 15 csetuid E011223344556677")); - return PM3_SUCCESS; -} static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) { @@ -691,17 +642,31 @@ static bool prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t } // Mode 3 -//helptext static int CmdHF15Demod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_15_demod(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 demod", + "Tries to demodulate / decode ISO15693, from downloaded samples.\n" + "Gather samples with 'hf 15 samples' / 'hf 15 sniff'", + "hf 15 demod\n"); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + // The sampling rate is 106.353 ksps/s, for T = 18.8 us int i, j; int max = 0, maxPos = 0; int skip = 4; - if (GraphTraceLen < 1000) return PM3_ESOFT; + if (GraphTraceLen < 1000) { + PrintAndLogEx(FAILED, "Too few samples in GraphBuffer. Need more than 1000"); + PrintAndLogEx(HINT, "Run " _YELLOW_("`hf 15 samples`") " to collect and download data"); + return PM3_ESOFT; + } // First, correlate for SOF for (i = 0; i < 1000; i++) { @@ -719,7 +684,7 @@ static int CmdHF15Demod(const char *Cmd) { i = maxPos + ARRAYLEN(FrameSOF) / skip; int k = 0; - uint8_t outBuf[20]; + uint8_t outBuf[2048] = {0}; memset(outBuf, 0, sizeof(outBuf)); uint8_t mask = 0x01; for (;;) { @@ -746,42 +711,80 @@ static int CmdHF15Demod(const char *Cmd) { } else { i += ARRAYLEN(Logic0) / skip; } + mask <<= 1; if (mask == 0) { k++; mask = 0x01; } + if ((i + (int)ARRAYLEN(FrameEOF)) >= GraphTraceLen) { PrintAndLogEx(INFO, "ran off end!"); break; } + + if (k > 2048) { + PrintAndLogEx(INFO, "ran out of buffer"); + break; + } } if (mask != 0x01) { PrintAndLogEx(WARNING, "Warning, uneven octet! (discard extra bits!)"); PrintAndLogEx(INFO, " mask = %02x", mask); } - PrintAndLogEx(INFO, "%d octets", k); - - for (i = 0; i < k; i++) - PrintAndLogEx(SUCCESS, "# %2d: %02x ", i, outBuf[i]); - - if (k > 2) { - PrintAndLogEx(SUCCESS, "CRC %04x", Crc15(outBuf, k - 2)); + + if ( k == 0 ) { + return PM3_SUCCESS; } + + i = 0; + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "Got %d octets, decoded as following", k); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, " idx | data"); + PrintAndLogEx(SUCCESS, "-----+-------------------------------------------------"); + if ( k / 16 > 0) { + for (; i < k; i += 16) { + PrintAndLogEx(SUCCESS, " %3i | %s", i, sprint_hex(outBuf + i, 16)); + } + } + + uint8_t mod = (k % 16); + if (mod > 0) { + PrintAndLogEx(SUCCESS, " %3i | %s", i, sprint_hex(outBuf + i, mod)); + } + PrintAndLogEx(SUCCESS, "-----+-------------------------------------------------"); + if (k > 2) { + PrintAndLogEx(SUCCESS, "--> CRC %04x", Crc15(outBuf, k - 2)); + } + PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } // * Acquire Samples as Reader (enables carrier, sends inquiry) //helptext static int CmdHF15Samples(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_15_samples(); + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 samples", + "Acquire samples as Reader (enables carrier, send inquiry\n" + "and download it to graphbuffer. Try 'hf 15 demod' to try to demodulate/decode signal", + "hf 15 samples"); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + CLIParserFree(ctx); clearCommandBuffer(); SendCommandNG(CMD_HF_ISO15693_ACQ_RAW_ADC, NULL, 0); getSamples(0, true); + + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 15 demod") "` to decode signal"); return PM3_SUCCESS; } @@ -1042,12 +1045,20 @@ static int CmdHF15Info(const char *Cmd) { return PM3_SUCCESS; } -// Record Activity without enabling carrier -//helptext +// Sniff Activity without enabling carrier static int CmdHF15Sniff(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_15_record(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 sniff", + "Sniff activity without enabling carrier", + "hf 15 sniff\n"); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + PacketResponseNG resp; clearCommandBuffer(); SendCommandNG(CMD_HF_ISO15693_SNIFF, NULL, 0); @@ -1060,10 +1071,23 @@ static int CmdHF15Sniff(const char *Cmd) { } static int CmdHF15Reader(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_15_reader(); - bool loop_read = (cmdp == '1') ? false : true; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 reader", + "This command continues loops and tries to identify ISO 15693 tags\n", + "hf 15 reader\n" + "hf 15 reader -1"); + void *argtable[] = { + arg_param_begin, + arg_lit0("", NULL, "read once"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + bool loop_read = arg_get_lit(ctx, 1); + CLIParserFree(ctx); + + PrintAndLogEx(INFO, "Starting ISO15 reader mode"); + PrintAndLogEx(INFO, "press " _YELLOW_("`enter`") " to cancel"); readHF15Uid(loop_read, true); return PM3_SUCCESS; } @@ -1071,19 +1095,34 @@ static int CmdHF15Reader(const char *Cmd) { // Simulation is still not working very good // helptext static int CmdHF15Sim(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_sim(); + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 sim", + "Simulate a ISO15693 tag\n", + "hf 15 sim -u E011223344556677"); + + void *argtable[] = { + arg_param_begin, + arg_str1("u", "uid", "<8b hex>", "UID eg E011223344556677"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); struct { uint8_t uid[8]; } PACKED payload; + + int uidlen = 0; + CLIGetHexWithReturn(ctx, 1, payload.uid, &uidlen); + CLIParserFree(ctx); - if (param_gethex(Cmd, 0, payload.uid, 16)) { + if (uidlen != 9) { PrintAndLogEx(WARNING, "UID must include 16 HEX symbols"); return PM3_EINVARG; } PrintAndLogEx(SUCCESS, "Starting simulating UID " _YELLOW_("%s"), iso15693_sprintUID(NULL, payload.uid)); + PrintAndLogEx(INFO, "press " _YELLOW_("`enter`") " to cancel"); PacketResponseNG resp; clearCommandBuffer(); @@ -1096,17 +1135,25 @@ static int CmdHF15Sim(const char *Cmd) { // (There is no standard way of reading the AFI, although some tags support this) // helptext static int CmdHF15FindAfi(const char *Cmd) { - PacketResponseNG resp; - uint32_t timeout = 0; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 findafi", + "This command attempts to brute force AFI of an ISO15693 tag\n", + "hf 15 findafi"); - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_15_findafi(); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + CLIParserFree(ctx); PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); clearCommandBuffer(); + PacketResponseNG resp; SendCommandMIX(CMD_HF_ISO15693_FINDAFI, strtol(Cmd, NULL, 0), 0, 0, NULL, 0); + uint32_t timeout = 0; while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { timeout++; @@ -1842,16 +1889,28 @@ static int CmdHF15Restore(const char *Cmd) { */ static int CmdHF15CSetUID(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_csetuid(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 csetuid", + "Set UID for magic Chinese card (only works with such cards)\n", + "hf 15 csetuid -u E011223344556677"); + void *argtable[] = { + arg_param_begin, + arg_str1("u", "uid", "<8b hex>", "UID eg E011223344556677"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); struct { uint8_t uid[8]; } PACKED payload; - - if (param_gethex(Cmd, 0, payload.uid, 16)) { - PrintAndLogEx(WARNING, "UID must include 16 HEX symbols"); + + int uidlen = 0; + CLIGetHexWithReturn(ctx, 1, payload.uid, &uidlen); + CLIParserFree(ctx); + + if (uidlen != 8) { + PrintAndLogEx(WARNING, "UID must include 16 HEX symbols got "); return PM3_EINVARG; } @@ -1874,9 +1933,10 @@ static int CmdHF15CSetUID(const char *Cmd) { PacketResponseNG resp; clearCommandBuffer(); SendCommandNG(CMD_HF_ISO15693_CSETUID, (uint8_t *)&payload, sizeof(payload)); - if (WaitForResponseTimeout(CMD_HF_ISO15693_CSETUID, &resp, 2000) == false) { PrintAndLogEx(WARNING, "timeout while waiting for reply"); + DropField(); + return PM3_ESOFT; } PrintAndLogEx(INFO, "getting updated card details..."); From 41286b823092904fe1367177e99ab9bed31bf2dd Mon Sep 17 00:00:00 2001 From: tcprst Date: Sat, 17 Oct 2020 17:38:49 -0400 Subject: [PATCH 11/20] remove cliparser buffer bandaid --- client/src/cmdhfst.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfst.c b/client/src/cmdhfst.c index 502e6413a..f48db7e73 100644 --- a/client/src/cmdhfst.c +++ b/client/src/cmdhfst.c @@ -357,7 +357,7 @@ static int cmd_hf_st_sim(const char *Cmd) { static int cmd_hf_st_ndef(const char *Cmd) { int pwdlen = 0; - uint8_t pwd[16 + 1] = {0}; + uint8_t pwd[16] = {0}; bool with_pwd = false; CLIParserContext *ctx; @@ -486,7 +486,7 @@ static int cmd_hf_st_ndef(const char *Cmd) { static int cmd_hf_st_protect(const char *Cmd) { int pwdlen = 0; - uint8_t pwd[16 + 1] = {0}; + uint8_t pwd[16] = {0}; int statelen = 3; uint8_t state[3] = {0x26, 0, 0x02}; @@ -641,9 +641,9 @@ static int cmd_hf_st_protect(const char *Cmd) { static int cmd_hf_st_pwd(const char *Cmd) { int pwdlen = 0; - uint8_t pwd[16 + 1] = {0}; + uint8_t pwd[16] = {0}; int newpwdlen = 0; - uint8_t newpwd[16 + 1] = {0}; + uint8_t newpwd[16] = {0}; int changePwdlen = 4; uint8_t changePwd[4] = {0x24, 0x00, 0x01, 0x10}; bool change_read_password = false; From e016582e1fd9f408bb39efcb371668c6a02a130c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 18 Oct 2020 00:15:09 +0200 Subject: [PATCH 12/20] textual --- client/src/cmdhf15.c | 2 +- client/src/cmdhficlass.c | 32 ++++++++++++++++++-------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index da433a010..73a7778a8 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1073,7 +1073,7 @@ static int CmdHF15Sniff(const char *Cmd) { static int CmdHF15Reader(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf 15 reader", - "This command continues loops and tries to identify ISO 15693 tags\n", + "Act as a ISO15693 reader. Look for ISO15693 tags until Enter or the pm3 button is pressed\n", "hf 15 reader\n" "hf 15 reader -1"); diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index bd5254c1b..4e065090c 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -272,17 +272,6 @@ static int usage_hf_iclass_managekeys(void) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } -static int usage_hf_iclass_reader(void) { - PrintAndLogEx(NORMAL, "Act as a iCLASS reader. Look for iCLASS tags until Enter or the pm3 button is pressed\n"); - PrintAndLogEx(NORMAL, "Usage: hf iclass reader [h] [1]\n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h Show this help"); - PrintAndLogEx(NORMAL, " 1 read only 1 tag"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass reader 1")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} static int usage_hf_iclass_loclass(void) { PrintAndLogEx(NORMAL, "Execute the offline part of loclass attack"); PrintAndLogEx(NORMAL, " An iclass dumpfile is assumed to consist of an arbitrary number of"); @@ -875,10 +864,25 @@ int read_iclass_csn(bool loop, bool verbose) { } static int CmdHFiClassReader(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_iclass_reader(); - bool loop_read = (cmdp == '1') ? false : true; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf iclass reader", + "Act as a iCLASS reader. Look for iCLASS tags until Enter or the pm3 button is pressed\n", + "hf iclass reader\n" + "hf iclass reader -1"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("", NULL, "read once"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + bool loop_read = arg_get_lit(ctx, 1); + CLIParserFree(ctx); + + + PrintAndLogEx(INFO, "Starting iCLASS reader mode"); + PrintAndLogEx(INFO, "press " _YELLOW_("`enter`") " to cancel"); return read_iclass_csn(loop_read, true); } From 452323fc11a72c4fcddc2daa6cc2245f32259837 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 18 Oct 2020 00:46:15 +0200 Subject: [PATCH 13/20] take notice of read_once vs looping --- client/src/cmdhf15.c | 6 +++--- client/src/cmdhficlass.c | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 73a7778a8..b4cde234f 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1079,16 +1079,16 @@ static int CmdHF15Reader(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_lit0("", NULL, "read once"), + arg_lit0("1", "one", "read once"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - bool loop_read = arg_get_lit(ctx, 1); + bool read_once = arg_get_lit(ctx, 1); CLIParserFree(ctx); PrintAndLogEx(INFO, "Starting ISO15 reader mode"); PrintAndLogEx(INFO, "press " _YELLOW_("`enter`") " to cancel"); - readHF15Uid(loop_read, true); + readHF15Uid(!read_once, true); return PM3_SUCCESS; } diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 4e065090c..5a5e07373 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -873,17 +873,16 @@ static int CmdHFiClassReader(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_lit0("", NULL, "read once"), + arg_lit0("1", "one", "read once"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - bool loop_read = arg_get_lit(ctx, 1); + bool read_once = arg_get_lit(ctx, 1); CLIParserFree(ctx); - PrintAndLogEx(INFO, "Starting iCLASS reader mode"); PrintAndLogEx(INFO, "press " _YELLOW_("`enter`") " to cancel"); - return read_iclass_csn(loop_read, true); + return read_iclass_csn(!read_once, true); } static int CmdHFiClassELoad(const char *Cmd) { From a36001ca03caef4924a8009421115a58573f92c7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 18 Oct 2020 11:50:20 +0200 Subject: [PATCH 14/20] hf iclass dump/view/decrypt - output redesign --- client/src/cmdhficlass.c | 433 ++++++++++++++++++++++++--------------- 1 file changed, 266 insertions(+), 167 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 5a5e07373..dd025852f 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -424,57 +424,55 @@ uint8_t get_pagemap(const picopass_hdr *hdr) { } static void fuse_config(const picopass_hdr *hdr) { + + uint16_t otp = (hdr->conf.otp[1] << 8 | hdr->conf.otp[0]); + + PrintAndLogEx(INFO, " Raw: " _YELLOW_("%s"), sprint_hex((uint8_t*)&hdr->conf, 8)); + PrintAndLogEx(INFO, " " _YELLOW_("%02X") "..................... App limit", hdr->conf.app_limit); + PrintAndLogEx(INFO, " " _YELLOW_("%04X") " ( %5u )...... OTP", otp, otp); + PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............ Block write lock", hdr->conf.block_writelock); + PrintAndLogEx(INFO, " " _YELLOW_("%02X") "......... Chip", hdr->conf.chip_config); + PrintAndLogEx(INFO, " " _YELLOW_("%02X") "...... Mem", hdr->conf.mem_config); + PrintAndLogEx(INFO, " " _YELLOW_("%02X") "... EAS", hdr->conf.eas); + PrintAndLogEx(INFO, " " _YELLOW_("%02X") " Fuses", hdr->conf.fuses); + uint8_t fuses = hdr->conf.fuses; + PrintAndLogEx(INFO, " Fuses:"); if (isset(fuses, FUSE_FPERS)) - PrintAndLogEx(SUCCESS, " Mode: " _GREEN_("Personalization (programmable)")); + PrintAndLogEx(SUCCESS, " mode..... " _GREEN_("Personalization (programmable)")); else - PrintAndLogEx(SUCCESS, " Mode: " _YELLOW_("Application (locked)")); + PrintAndLogEx(SUCCESS, " mode..... " _YELLOW_("Application (locked)")); if (isset(fuses, FUSE_CODING1)) { - PrintAndLogEx(SUCCESS, "Coding: RFU"); + PrintAndLogEx(SUCCESS, " coding.. RFU"); } else { if (isset(fuses, FUSE_CODING0)) - PrintAndLogEx(SUCCESS, "Coding: " _YELLOW_("ISO 14443-2 B / 15693")); + PrintAndLogEx(SUCCESS, " coding... " _YELLOW_("ISO 14443-2 B / 15693")); else - PrintAndLogEx(SUCCESS, "Coding: " _YELLOW_("ISO 14443-B only")); + PrintAndLogEx(SUCCESS, " coding... " _YELLOW_("ISO 14443-B only")); } uint8_t pagemap = get_pagemap(hdr); switch (pagemap) { case 0x0: - PrintAndLogEx(INFO, " Crypt: No auth possible. Read only if RA is enabled"); + PrintAndLogEx(INFO, " crypt.... No auth possible. Read only if RA is enabled"); break; case 0x1: - PrintAndLogEx(SUCCESS, " Crypt: Non secured page"); + PrintAndLogEx(SUCCESS, " crypt.... Non secured page"); break; case 0x2: - PrintAndLogEx(INFO, " Crypt: Secured page, keys locked"); + PrintAndLogEx(INFO, " crypt.... Secured page, keys locked"); break; case 0x03: - PrintAndLogEx(SUCCESS, " Crypt: Secured page, " _GREEN_("keys not locked")); + PrintAndLogEx(SUCCESS, " crypt.... Secured page, " _GREEN_("keys not locked")); break; } if (isset(fuses, FUSE_RA)) - PrintAndLogEx(SUCCESS, " RA: Read access enabled"); + PrintAndLogEx(SUCCESS, " RA....... Read access enabled (non-secure mode)"); else - PrintAndLogEx(INFO, " RA: Read access not enabled"); - - PrintAndLogEx(INFO, - "App limit " _YELLOW_("0x%02X") ", OTP " _YELLOW_("0x%02X%02X") ", Block write lock " _YELLOW_("0x%02X") - , hdr->conf.app_limit - , hdr->conf.otp[1] - , hdr->conf.otp[0] - , hdr->conf.block_writelock - ); - PrintAndLogEx(INFO, - " Chip " _YELLOW_("0x%02X") ", Mem " _YELLOW_("0x%02X") ", EAS " _YELLOW_("0x%02X") ", Fuses " _YELLOW_("0x%02X") - , hdr->conf.chip_config - , hdr->conf.mem_config - , hdr->conf.eas - , hdr->conf.fuses - ); + PrintAndLogEx(INFO, " RA....... Read access not enabled"); } static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *app_areas, uint8_t *kb) { @@ -535,19 +533,19 @@ static void mem_app_config(const picopass_hdr *hdr) { uint8_t app2_limit = card_app2_limit[type]; uint8_t pagemap = get_pagemap(hdr); - PrintAndLogEx(INFO, "------ " _CYAN_("Memory") " ------"); + PrintAndLogEx(INFO, "-------------------------- " _CYAN_("Memory") " --------------------------"); if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { - PrintAndLogEx(INFO, " %u KBits (%u bytes)", kb, app2_limit * 8); + PrintAndLogEx(INFO, " %u KBits ( " _YELLOW_("%u") " bytes )", kb, app2_limit * 8); PrintAndLogEx(INFO, " Tag has not App Areas"); return; } - PrintAndLogEx(INFO, " %u KBits/%u App Areas (%u bytes)", kb, app_areas, (app2_limit + 1) * 8); + PrintAndLogEx(INFO, " %u KBits/%u App Areas ( " _YELLOW_("%u") " bytes )", kb, app_areas, (app2_limit + 1) * 8); PrintAndLogEx(INFO, " AA1 blocks %u { 0x06 - 0x%02X (06 - %02d) }", app1_limit, app1_limit + 5, app1_limit + 5); PrintAndLogEx(INFO, " AA2 blocks %u { 0x%02X - 0x%02X (%02d - %02d) }", app2_limit - app1_limit, app1_limit + 5 + 1, app2_limit, app1_limit + 5 + 1, app2_limit); - PrintAndLogEx(INFO, "------ " _CYAN_("KeyAccess") " ------"); + PrintAndLogEx(INFO, "------------------------ " _CYAN_("KeyAccess") " -------------------------"); PrintAndLogEx(INFO, " Kd = Debit key (AA1), Kc = Credit key (AA2)"); uint8_t book = isset(mem, 0x20); if (book) { @@ -568,18 +566,18 @@ static void mem_app_config(const picopass_hdr *hdr) { } static void print_picopass_info(const picopass_hdr *hdr) { - PrintAndLogEx(INFO, "------ " _CYAN_("card configuration") " ------"); + PrintAndLogEx(INFO, "-------------------- " _CYAN_("card configuration") " --------------------"); fuse_config(hdr); mem_app_config(hdr); } static void print_picopass_header(const picopass_hdr *hdr) { - PrintAndLogEx(INFO, "------------ " _CYAN_("card") " -------------"); - PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " (uid)", sprint_hex(hdr->csn, sizeof(hdr->csn))); - PrintAndLogEx(SUCCESS, " Config: %s (Card configuration)", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf))); - PrintAndLogEx(SUCCESS, "E-purse: %s (Card challenge, CC)", sprint_hex(hdr->epurse, sizeof(hdr->epurse))); - PrintAndLogEx(SUCCESS, " Kd: %s (Debit key, hidden)", sprint_hex(hdr->key_d, sizeof(hdr->key_d))); - PrintAndLogEx(SUCCESS, " Kc: %s (Credit key, hidden)", sprint_hex(hdr->key_c, sizeof(hdr->key_c))); - PrintAndLogEx(SUCCESS, " AIA: %s (Application Issuer area)", sprint_hex(hdr->app_issuer_area, sizeof(hdr->app_issuer_area))); + PrintAndLogEx(INFO, "--------------------------- " _CYAN_("card") " ---------------------------"); + PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " uid", sprint_hex(hdr->csn, sizeof(hdr->csn))); + PrintAndLogEx(SUCCESS, " Config: %s Card configuration", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf))); + PrintAndLogEx(SUCCESS, "E-purse: %s Card challenge, CC", sprint_hex(hdr->epurse, sizeof(hdr->epurse))); + PrintAndLogEx(SUCCESS, " Kd: %s Debit key, hidden", sprint_hex(hdr->key_d, sizeof(hdr->key_d))); + PrintAndLogEx(SUCCESS, " Kc: %s Credit key, hidden", sprint_hex(hdr->key_c, sizeof(hdr->key_c))); + PrintAndLogEx(SUCCESS, " AIA: %s Application Issuer area", sprint_hex(hdr->app_issuer_area, sizeof(hdr->app_issuer_area))); } static int CmdHFiClassList(const char *Cmd) { @@ -1121,22 +1119,7 @@ static int CmdHFiClassEView(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - uint8_t *csn = dump; - PrintAndLogEx(INFO, "------+----+-------------------------+----------"); - PrintAndLogEx(INFO, " CSN |0x00| " _GREEN_("%s") "|", sprint_hex(csn, 8)); printIclassDumpContents(dump, 1, blocks, bytes); - - /* - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "----+-------------------------+---------"); - PrintAndLogEx(INFO, "blk | data | ascii"); - PrintAndLogEx(INFO, "----+-------------------------+---------"); - for (uint16_t i = 0; i < blocks; i++){ - PrintAndLogEx(INFO, "%03d | %s ", i, sprint_hex_ascii(dump + (i * 8) , 8) ); - } - PrintAndLogEx(INFO, "----+-------------------------+---------"); - PrintAndLogEx(NORMAL, ""); - */ free(dump); return PM3_SUCCESS; } @@ -1290,7 +1273,6 @@ static int CmdHFiClassDecrypt(const char *Cmd) { saveFileEML(fptr, decrypted, decryptedlen, 8); saveFileJSON(fptr, jsfIclass, decrypted, decryptedlen, NULL); - PrintAndLogEx(INFO, "Following output skips CSN / block0"); printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen); PrintAndLogEx(NORMAL, ""); @@ -1785,9 +1767,6 @@ write_dump: PrintAndLogEx(INFO, "Reading AA2 failed. dumping AA1 data to file"); // print the dump - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "------+----+-------------------------+----------"); - PrintAndLogEx(INFO, " CSN |0x00| " _GREEN_("%s") "|", sprint_hex(tag_data, 8)); printIclassDumpContents(tag_data, 1, (bytes_got / 8), bytes_got); // use CSN as filename @@ -2416,9 +2395,20 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e , filemaxblock ); */ + uint8_t pagemap = get_pagemap(hdr); + + int i = startblock; - PrintAndLogEx(INFO, "------+----+-------------------------+----------"); + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, " blk| data | ascii |lck| info"); + PrintAndLogEx(INFO, "----+-------------------------+----------+---+--------------"); + PrintAndLogEx(INFO, "0x00| " _GREEN_("%s") " | | CSN ", sprint_hex_ascii(iclass_dump, 8)); + + if (i != 1) + PrintAndLogEx(INFO, "...."); + while (i <= endblock) { uint8_t *blk = iclass_dump + (i * 8); @@ -2458,10 +2448,28 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e bl_lock = true; } - PrintAndLogEx(INFO, " %c |0x%02X| %s", (bl_lock) ? 'x' : ' ', i, sprint_hex_ascii(blk, 8)); + const char *lockstr = (bl_lock) ? _RED_("x") : " "; + + if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { + const char *info_nonks[] = {"CSN", "Config", "AIA", "User"}; + const char *s = info_nonks[3]; + if (i < 3) { + s = info_nonks[i]; + } + + PrintAndLogEx(INFO, "0x%02X| %s | %s | %s ", i, sprint_hex_ascii(blk, 8), lockstr, s); + } else { + const char *info_ks[] = {"CSN", "Config", "E-purse", "Debit", "Credit", "AIA", "User"}; + const char *s = info_ks[6]; + if (i < 6) { + s = info_ks[i]; + } + PrintAndLogEx(INFO, "0x%02X| %s | %s | %s ", i, sprint_hex_ascii(blk, 8), lockstr, s); + } i++; } - PrintAndLogEx(INFO, "------+----+-------------------------+----------"); + PrintAndLogEx(INFO, "----+-------------------------+----------+---+--------------"); + PrintAndLogEx(NORMAL, ""); } static int CmdHFiClassView(const char *Cmd) { @@ -2505,13 +2513,9 @@ static int CmdHFiClassView(const char *Cmd) { PrintAndLogEx(INFO, "start " _YELLOW_("0x%02x") " end " _YELLOW_("0x%02x"), (startblock == 0) ? 6 : startblock, endblock); } + PrintAndLogEx(NORMAL, ""); print_picopass_header((picopass_hdr *) dump); print_picopass_info((picopass_hdr *) dump); - - PrintAndLogEx(NORMAL, ""); - uint8_t *csn = dump; - PrintAndLogEx(INFO, "------+----+-------------------------+----------"); - PrintAndLogEx(INFO, " CSN |0x00| " _GREEN_("%s") "|", sprint_hex(csn, 8)); printIclassDumpContents(dump, startblock, endblock, bytes_read); free(dump); return PM3_SUCCESS; @@ -2687,12 +2691,15 @@ static int saveKeys(char *filename) { static int printKeys(void) { PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "idx| key"); + PrintAndLogEx(INFO, "---+------------------------"); for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++) { if (memcmp(iClass_Key_Table[i], "\x00\x00\x00\x00\x00\x00\x00\x00", 8) == 0) - PrintAndLogEx(INFO, "%u: %s", i, sprint_hex(iClass_Key_Table[i], 8)); + PrintAndLogEx(INFO, " %u |", i); else - PrintAndLogEx(INFO, "%u: "_YELLOW_("%s"), i, sprint_hex(iClass_Key_Table[i], 8)); + PrintAndLogEx(INFO, " %u | " _YELLOW_("%s"), i, sprint_hex(iClass_Key_Table[i], 8)); } + PrintAndLogEx(INFO, "---+------------------------"); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -2810,111 +2817,15 @@ static void add_key(uint8_t *key) { } } + /* -static int iclass_chk_keys(void) { - return PM3_SUCCESS; -} -*/ - -static int CmdHFiClassCheckKeys(const char *Cmd) { - - // empty string - if (strlen(Cmd) == 0) return usage_hf_iclass_chk(); - - uint8_t CSN[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - // elite key, raw key, standard key - bool use_elite = false; - bool use_raw = false; - bool use_credit_key = false; - bool found_key = false; - //bool found_credit = false; - bool got_csn = false; - bool errors = false; - uint8_t cmdp = 0x00; - - char filename[FILE_PATH_SIZE] = {0}; - uint8_t fileNameLen = 0; - - uint64_t t1 = msclock(); - - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_iclass_chk(); - case 'f': - fileNameLen = param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); - if (fileNameLen < 1) { - PrintAndLogEx(WARNING, _RED_("no filename found after f")); - errors = true; - } - cmdp += 2; - break; - case 'e': - use_elite = true; - cmdp++; - break; - case 'c': - use_credit_key = true; - cmdp++; - break; - case 'r': - use_raw = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - if (errors) return usage_hf_iclass_chk(); - - uint8_t *keyBlock = NULL; - uint32_t keycount = 0; - - // load keys - int res = loadFileDICTIONARY_safe(filename, (void **)&keyBlock, 8, &keycount); - if (res != PM3_SUCCESS || keycount == 0) { - free(keyBlock); - return res; - } +static int iclass_chk_keys(uint8_t *keyBlock, uint32_t keycount) { iclass_premac_t *pre = calloc(keycount, sizeof(iclass_premac_t)); - if (!pre) { - free(keyBlock); + if (pre == NULL) { return PM3_EMALLOC; } - // Get CSN / UID and CCNR - PrintAndLogEx(SUCCESS, "Reading tag CSN / CCNR..."); - for (uint8_t i = 0; i < ICLASS_AUTH_RETRY && !got_csn; i++) { - got_csn = select_only(CSN, CCNR, false); - if (got_csn == false) - PrintAndLogEx(WARNING, "one more try"); - } - - if (got_csn == false) { - PrintAndLogEx(WARNING, "Tried 10 times. Can't select card, aborting..."); - free(keyBlock); - DropField(); - return PM3_ESOFT; - } - - PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s"), sprint_hex(CSN, sizeof(CSN))); - PrintAndLogEx(SUCCESS, " CCNR: " _GREEN_("%s"), sprint_hex(CCNR, sizeof(CCNR))); - - PrintAndLogEx(SUCCESS, "Generating diversified keys %s", (use_elite || use_raw) ? NOLF : ""); - if (use_elite) - PrintAndLogEx(NORMAL, "using " _YELLOW_("elite algo")); - if (use_raw) - PrintAndLogEx(NORMAL, "using " _YELLOW_("raw mode")); - - GenerateMacFrom(CSN, CCNR, use_raw, use_elite, keyBlock, keycount, pre); - - PrintAndLogEx(SUCCESS, "Searching for " _YELLOW_("%s") " key...", (use_credit_key) ? "CREDIT" : "DEBIT"); - // max 42 keys inside USB_COMMAND. 512/4 = 103 mac uint32_t chunksize = keycount > (PM3_CMD_DATA_SIZE / 4) ? (PM3_CMD_DATA_SIZE / 4) : keycount; bool lastChunk = false; @@ -2998,7 +2909,195 @@ static int CmdHFiClassCheckKeys(const char *Cmd) { break; } - } // end chunks of keys + } + return PM3_SUCCESS; +} +*/ + +static int CmdHFiClassCheckKeys(const char *Cmd) { + + // empty string + if (strlen(Cmd) == 0) return usage_hf_iclass_chk(); + + uint8_t CSN[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + // elite key, raw key, standard key + bool use_elite = false; + bool use_raw = false; + bool use_credit_key = false; + bool found_key = false; + //bool found_credit = false; + bool got_csn = false; + bool errors = false; + uint8_t cmdp = 0x00; + + char filename[FILE_PATH_SIZE] = {0}; + uint8_t fileNameLen = 0; + + uint64_t t1 = msclock(); + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_hf_iclass_chk(); + case 'f': + fileNameLen = param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); + if (fileNameLen < 1) { + PrintAndLogEx(WARNING, _RED_("no filename found after f")); + errors = true; + } + cmdp += 2; + break; + case 'e': + use_elite = true; + cmdp++; + break; + case 'c': + use_credit_key = true; + cmdp++; + break; + case 'r': + use_raw = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + if (errors) return usage_hf_iclass_chk(); + + uint8_t *keyBlock = NULL; + uint32_t keycount = 0; + + // load keys + int res = loadFileDICTIONARY_safe(filename, (void **)&keyBlock, 8, &keycount); + if (res != PM3_SUCCESS || keycount == 0) { + free(keyBlock); + return res; + } + + // Get CSN / UID and CCNR + PrintAndLogEx(SUCCESS, "Reading tag CSN / CCNR..."); + for (uint8_t i = 0; i < ICLASS_AUTH_RETRY && !got_csn; i++) { + got_csn = select_only(CSN, CCNR, false); + if (got_csn == false) + PrintAndLogEx(WARNING, "one more try"); + } + + if (got_csn == false) { + PrintAndLogEx(WARNING, "Tried 10 times. Can't select card, aborting..."); + free(keyBlock); + DropField(); + return PM3_ESOFT; + } + + iclass_premac_t *pre = calloc(keycount, sizeof(iclass_premac_t)); + if (pre == NULL) { + return PM3_EMALLOC; + } + + + PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s"), sprint_hex(CSN, sizeof(CSN))); + PrintAndLogEx(SUCCESS, " CCNR: " _GREEN_("%s"), sprint_hex(CCNR, sizeof(CCNR))); + + PrintAndLogEx(SUCCESS, "Generating diversified keys %s", (use_elite || use_raw) ? NOLF : ""); + if (use_elite) + PrintAndLogEx(NORMAL, "using " _YELLOW_("elite algo")); + if (use_raw) + PrintAndLogEx(NORMAL, "using " _YELLOW_("raw mode")); + + GenerateMacFrom(CSN, CCNR, use_raw, use_elite, keyBlock, keycount, pre); + + PrintAndLogEx(SUCCESS, "Searching for " _YELLOW_("%s") " key...", (use_credit_key) ? "CREDIT" : "DEBIT"); + + + // max 42 keys inside USB_COMMAND. 512/4 = 103 mac + uint32_t chunksize = keycount > (PM3_CMD_DATA_SIZE / 4) ? (PM3_CMD_DATA_SIZE / 4) : keycount; + bool lastChunk = false; + + // fast push mode + conn.block_after_ACK = true; + + // keep track of position of found key + uint8_t found_offset = 0; + uint32_t key_offset = 0; + // main keychunk loop + for (key_offset = 0; key_offset < keycount; key_offset += chunksize) { + + uint64_t t2 = msclock(); + uint8_t timeout = 0; + + if (kbd_enter_pressed()) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(WARNING, "Aborted via keyboard!"); + goto out; + } + + uint32_t keys = ((keycount - key_offset) > chunksize) ? chunksize : keycount - key_offset; + + // last chunk? + if (keys == keycount - key_offset) { + lastChunk = true; + // Disable fast mode on last command + conn.block_after_ACK = false; + } + uint32_t flags = lastChunk << 8; + // bit 16 + // - 1 indicates credit key + // - 0 indicates debit key (default) + flags |= (use_credit_key << 16); + + clearCommandBuffer(); + SendCommandOLD(CMD_HF_ICLASS_CHKKEYS, flags, keys, 0, pre + key_offset, 4 * keys); + PacketResponseNG resp; + + bool looped = false; + while (!WaitForResponseTimeout(CMD_HF_ICLASS_CHKKEYS, &resp, 2000)) { + timeout++; + PrintAndLogEx(NORMAL, "." NOLF); + if (timeout > 120) { + PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting..."); + goto out; + } + looped = true; + } + + if (looped) + PrintAndLogEx(NORMAL, ""); + + found_offset = resp.oldarg[1] & 0xFF; + uint8_t isOK = resp.oldarg[0] & 0xFF; + + t2 = msclock() - t2; + switch (isOK) { + case 1: { + found_key = true; + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "Found valid key " _GREEN_("%s") + , sprint_hex(keyBlock + (key_offset + found_offset) * 8, 8) + ); + break; + } + case 0: { + PrintAndLogEx(INPLACE, "Chunk [%d/%d]", key_offset, keycount); + break; + } + case 99: { + } + default: { + break; + } + } + + // both keys found. + if (found_key) { + break; + } + + } out: t1 = msclock() - t1; From c86df6b83d393cf0e438196077c6f82ba7a9282c Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 18 Oct 2020 16:16:09 +0200 Subject: [PATCH 15/20] em 4x05_chk: check if a pwd is really activated to avoid false positives --- client/src/cmdlfem4x05.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index 82e069092..a1999dd9d 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -1095,13 +1095,20 @@ int CmdEM4x05Chk(const char *Cmd) { uint64_t card_id = arg_get_u64_def(ctx, 2, 0); CLIParserFree(ctx); + uint8_t addr = 4; + uint32_t word = 0; + // Test first if a password is required + int status = EM4x05ReadWord_ext(addr, 0, false, &word); + if (status == PM3_SUCCESS) { + PrintAndLogEx(INFO, "Password doesn't seem to be needed to read the tag"); + return PM3_SUCCESS; + } + if (strlen(filename) == 0) { snprintf(filename, sizeof(filename), "t55xx_default_pwds"); } PrintAndLogEx(NORMAL, ""); - uint8_t addr = 4; - uint32_t word = 0; bool found = false; uint64_t t1 = msclock(); @@ -1111,7 +1118,7 @@ int CmdEM4x05Chk(const char *Cmd) { uint32_t pwd = lf_t55xx_white_pwdgen(card_id & 0xFFFFFFFF); PrintAndLogEx(INFO, "testing %08"PRIX32" generated ", pwd); - int status = EM4x05ReadWord_ext(addr, pwd, true, &word); + status = EM4x05ReadWord_ext(addr, pwd, true, &word); if (status == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", pwd); found = true; @@ -1153,7 +1160,7 @@ int CmdEM4x05Chk(const char *Cmd) { PrintAndLogEx(INFO, "testing %08"PRIX32, curr_password); - int status = EM4x05ReadWord_ext(addr, curr_password, 1, &word); + status = EM4x05ReadWord_ext(addr, curr_password, 1, &word); if (status == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", curr_password); found = true; From 95bf65cda94536b420f4e449d33b9cb364c4367c Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 18 Oct 2020 23:46:36 +0200 Subject: [PATCH 16/20] Add EM 4x05 Login --- armsrc/appmain.c | 8 ++++ armsrc/lfops.c | 31 ++++++++++-- armsrc/lfops.h | 1 + client/src/cmdlfem4x05.c | 101 +++++++++++++++++++-------------------- include/pm3_cmd.h | 1 + 5 files changed, 87 insertions(+), 55 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 6b40a3909..02d6f1d23 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -970,6 +970,14 @@ static void PacketReceived(PacketCommandNG *packet) { ); break; } + case CMD_LF_EM4X_LOGIN: { + struct p { + uint32_t password; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + EM4xLogin(payload->password); + break; + } case CMD_LF_EM4X_READWORD: { struct p { uint32_t password; diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 03e322681..de1803690 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -2501,7 +2501,7 @@ static void SendForward(uint8_t fwd_bit_count) { } } -static void EM4xLogin(uint32_t pwd) { +static void EM4xLoginEx(uint32_t pwd) { forward_ptr = forwardLink_data; uint8_t len = Prepare_Cmd(FWD_CMD_LOGIN); len += Prepare_Data(pwd & 0xFFFF, pwd >> 16); @@ -2512,6 +2512,29 @@ static void EM4xLogin(uint32_t pwd) { // 0000 0001 fail } +void EM4xLogin(uint32_t pwd) { + + StartTicks(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + WaitMS(20); + + LED_A_ON(); + + // clear buffer now so it does not interfere with timing later + BigBuf_Clear_ext(false); + + EM4xLoginEx(pwd); + + WaitUS(400); + + DoPartialAcquisition(20, false, 1000, 1000); + + StopTicks(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + reply_ng(CMD_LF_EM4X_LOGIN, PM3_SUCCESS, NULL, 0); + LEDsoff(); +} + void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) { StartTicks(); @@ -2529,7 +2552,7 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) { * 0000 1010 ok * 0000 0001 fail **/ - if (usepwd) EM4xLogin(pwd); + if (usepwd) EM4xLoginEx(pwd); forward_ptr = forwardLink_data; uint8_t len = Prepare_Cmd(FWD_CMD_READ); @@ -2564,7 +2587,7 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) { * 0000 1010 ok. * 0000 0001 fail **/ - if (usepwd) EM4xLogin(pwd); + if (usepwd) EM4xLoginEx(pwd); forward_ptr = forwardLink_data; uint8_t len = Prepare_Cmd(FWD_CMD_WRITE); @@ -2607,7 +2630,7 @@ void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd) { * 0000 1010 ok. * 0000 0001 fail **/ - if (usepwd) EM4xLogin(pwd); + if (usepwd) EM4xLoginEx(pwd); forward_ptr = forwardLink_data; uint8_t len = Prepare_Cmd(FWD_CMD_PROTECT); diff --git a/armsrc/lfops.h b/armsrc/lfops.h index 1c191d65d..bf251ac85 100644 --- a/armsrc/lfops.h +++ b/armsrc/lfops.h @@ -56,6 +56,7 @@ void T55xxDangerousRawTest(uint8_t *data); void TurnReadLFOn(uint32_t delay); +void EM4xLogin(uint32_t pwd); void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd); void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd); void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd); diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index a1999dd9d..75e20e9eb 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -361,6 +361,29 @@ static int demodEM4x05resp(uint32_t *word, bool onlyPreamble) { //////////////// 4205 / 4305 commands +static int EM4x05Login_ext(uint32_t pwd) { + + struct { + uint32_t password; + } PACKED payload; + + payload.password = pwd; + + clearCommandBuffer(); + SendCommandNG(CMD_LF_EM4X_LOGIN, (uint8_t *)&payload, sizeof(payload)); + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_LF_EM4X_LOGIN, &resp, 10000)) { + PrintAndLogEx(WARNING, "(EM4x05Login_ext) timeout while waiting for reply."); + return PM3_ETIMEOUT; + } + + if (downloadSamplesEM() == false) { + return PM3_ESOFT; + } + uint32_t word; + return demodEM4x05resp(&word, true); +} + int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word) { struct { @@ -438,7 +461,6 @@ int CmdEM4x05Dump(const char *Cmd) { if (EM4x05IsBlock0(&block0) == false) return PM3_ESOFT; - bool needReadPwd = true; uint8_t bytes[4] = {0}; uint32_t data[16]; @@ -456,28 +478,32 @@ int CmdEM4x05Dump(const char *Cmd) { em_tech_type_t card_type = em_get_card_type(block0); PrintAndLogEx(INFO, "Found a " _GREEN_("%s") " tag", em_get_card_str(block0)); - PrintAndLogEx(NORMAL, ""); + if (usePwd) { + // Test first if the password is correct + status = EM4x05Login_ext(pwd); + if (status == PM3_SUCCESS) { + PrintAndLogEx(INFO, "Password is " _GREEN_("correct")); + } else if (status == PM3_EFAILED) { + PrintAndLogEx(WARNING, "Password is " _RED_("incorrect") ", will try without password"); + usePwd = false; + } else if (status != PM3_EFAILED) { + PrintAndLogEx(WARNING, "Login attempt: No answer from tag"); + return status; + } + } + + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "Addr | data | ascii |lck| info"); PrintAndLogEx(INFO, "-----+----------+-------+---+-----"); if ( card_type == EM_4205 || card_type == EM_4305 || card_type == EM_UNKNOWN) { - if (usePwd) { - // Test first if a password is required - status = EM4x05ReadWord_ext(EM4305_PROT1_BLOCK, pwd, false, &word); - if (status == PM3_SUCCESS) { - PrintAndLogEx(INFO, "Note that password doesn't seem to be needed"); - needReadPwd = false; - } - } // To flag any blocks locked we need to read blocks 14 and 15 first // dont swap endin until we get block lock flags. status14 = EM4x05ReadWord_ext(EM4305_PROT1_BLOCK, pwd, usePwd, &word); if (status14 == PM3_SUCCESS) { - if (!usePwd) - needReadPwd = false; if ((word & 0x00008000) != 0x00) { lock_bits = word; gotLockBits = true; @@ -503,14 +529,9 @@ int CmdEM4x05Dump(const char *Cmd) { lockbit = (lock_bits >> addr) & 1; if (addr == 2) { if (usePwd) { - if ((needReadPwd) && (success != PM3_ESOFT)) { - data[addr] = BSWAP_32(pwd); - num_to_bytes(pwd, 4, bytes); - PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info[addr]); - } else { - // The pwd is not needed for Login so we're not sure what's the actual content of that block - PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info[addr]); - } + data[addr] = BSWAP_32(pwd); + num_to_bytes(pwd, 4, bytes); + PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info[addr]); } else { data[addr] = 0x00; // Unknown password, but not used to set to zeros PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info[addr]); @@ -550,21 +571,10 @@ int CmdEM4x05Dump(const char *Cmd) { } else if (card_type == EM_4X69) { - if (usePwd) { - // Test first if a password is required - status = EM4x05ReadWord_ext(EM4469_PROT_BLOCK, pwd, false, &word); - if (status == PM3_SUCCESS) { - PrintAndLogEx(INFO, "Note that password doesn't seem to be needed"); - needReadPwd = false; - } - } - // To flag any blocks locked we need to read blocks 14 and 15 first // dont swap endin until we get block lock flags. status14 = EM4x05ReadWord_ext(EM4469_PROT_BLOCK, pwd, usePwd, &word); if (status14 == PM3_SUCCESS) { - if (!usePwd) - needReadPwd = false; if ((word & 0x00008000) != 0x00) { lock_bits = word; gotLockBits = true; @@ -580,14 +590,9 @@ int CmdEM4x05Dump(const char *Cmd) { lockbit = (lock_bits >> addr) & 1; if (addr == 2) { if (usePwd) { - if ((needReadPwd) && (success != PM3_ESOFT)) { - data[addr] = BSWAP_32(pwd); - num_to_bytes(pwd, 4, bytes); - PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info4x69[addr]); - } else { - // The pwd is not needed for Login so we're not sure what's the actual content of that block - PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info4x69[addr]); - } + data[addr] = BSWAP_32(pwd); + num_to_bytes(pwd, 4, bytes); + PrintAndLogEx(INFO, " %02u | %08X | %s | %s | %s", addr, pwd, sprint_ascii(bytes, 4), gotLockBits ? (lockbit ? _RED_("x") : " ") : _YELLOW_("?"), info4x69[addr]); } else { data[addr] = 0x00; // Unknown password, but not used to set to zeros PrintAndLogEx(INFO, " %02u | | | | %-10s " _YELLOW_("write only"), addr, info4x69[addr]); @@ -1095,15 +1100,6 @@ int CmdEM4x05Chk(const char *Cmd) { uint64_t card_id = arg_get_u64_def(ctx, 2, 0); CLIParserFree(ctx); - uint8_t addr = 4; - uint32_t word = 0; - // Test first if a password is required - int status = EM4x05ReadWord_ext(addr, 0, false, &word); - if (status == PM3_SUCCESS) { - PrintAndLogEx(INFO, "Password doesn't seem to be needed to read the tag"); - return PM3_SUCCESS; - } - if (strlen(filename) == 0) { snprintf(filename, sizeof(filename), "t55xx_default_pwds"); } @@ -1118,10 +1114,12 @@ int CmdEM4x05Chk(const char *Cmd) { uint32_t pwd = lf_t55xx_white_pwdgen(card_id & 0xFFFFFFFF); PrintAndLogEx(INFO, "testing %08"PRIX32" generated ", pwd); - status = EM4x05ReadWord_ext(addr, pwd, true, &word); + int status = EM4x05Login_ext(pwd); if (status == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", pwd); found = true; + } else if (status != PM3_EFAILED) { + PrintAndLogEx(WARNING, "No answer from tag"); } } @@ -1131,7 +1129,6 @@ int CmdEM4x05Chk(const char *Cmd) { PrintAndLogEx(INFO, "press " _YELLOW_("'enter'") " to cancel the command"); - word = 0; uint32_t keycount = 0; int res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock, 4, &keycount); @@ -1160,11 +1157,13 @@ int CmdEM4x05Chk(const char *Cmd) { PrintAndLogEx(INFO, "testing %08"PRIX32, curr_password); - status = EM4x05ReadWord_ext(addr, curr_password, 1, &word); + int status = EM4x05Login_ext(curr_password); if (status == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "found valid password [ " _GREEN_("%08"PRIX32) " ]", curr_password); found = true; break; + } else if (status != PM3_EFAILED) { + PrintAndLogEx(WARNING, "No answer from tag"); } } } diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 6fca06786..7fb978d75 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -496,6 +496,7 @@ typedef struct { #define CMD_LF_T55XX_RESET_READ 0x0216 #define CMD_LF_PCF7931_READ 0x0217 #define CMD_LF_PCF7931_WRITE 0x0223 +#define CMD_LF_EM4X_LOGIN 0x0229 #define CMD_LF_EM4X_READWORD 0x0218 #define CMD_LF_EM4X_WRITEWORD 0x0219 #define CMD_LF_EM4X_PROTECTWORD 0x021B From a8ca19bec58c774d7b93e398cab96647c1888bb1 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 19 Oct 2020 00:15:01 +0200 Subject: [PATCH 17/20] EM 4x05: acquire more samples for Login --- armsrc/lfops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index de1803690..6f815afe1 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -2526,8 +2526,8 @@ void EM4xLogin(uint32_t pwd) { EM4xLoginEx(pwd); WaitUS(400); - - DoPartialAcquisition(20, false, 1000, 1000); + // We need to acquire more than needed, to help demodulators finding the proper modulation + DoPartialAcquisition(20, false, 6000, 1000); StopTicks(); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); From dd6044e508b43b59bd38f8f2fbaa8c3cd60dda0e Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 19 Oct 2020 00:51:20 +0200 Subject: [PATCH 18/20] EM4x05: use full preambles --- client/src/cmdlfem4x05.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index 75e20e9eb..2ad3471c6 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -147,7 +147,7 @@ static bool EM_ColParityTest(uint8_t *bs, size_t size, uint8_t rows, uint8_t col return true; } -#define EM_PREAMBLE_LEN 6 +#define EM_PREAMBLE_LEN 8 // download samples from device and copy to Graphbuffer static bool downloadSamplesEM(void) { @@ -178,15 +178,15 @@ static int doPreambleSearch(size_t *startIdx) { return PM3_ESOFT; } - // set size to 9 to only test first 3 positions for the preamble + // set size to 11 to only test first 3 positions for the preamble // do not set it too long else an error preamble followed by 010 could be seen as success. - size_t size = (9 > DemodBufferLen) ? DemodBufferLen : 9; + size_t size = (11 > DemodBufferLen) ? DemodBufferLen : 11; *startIdx = 0; // skip first two 0 bits as they might have been missed in the demod - uint8_t preamble[EM_PREAMBLE_LEN] = {0, 0, 1, 0, 1, 0}; + uint8_t preamble[EM_PREAMBLE_LEN] = {0, 0, 0, 0, 1, 0, 1, 0}; if (!preambleSearchEx(DemodBuffer, preamble, EM_PREAMBLE_LEN, &size, startIdx, true)) { - uint8_t errpreamble[EM_PREAMBLE_LEN] = {0, 0, 0, 0, 0, 1}; + uint8_t errpreamble[EM_PREAMBLE_LEN] = {0, 0, 0, 0, 0, 0, 0, 1}; if (!preambleSearchEx(DemodBuffer, errpreamble, EM_PREAMBLE_LEN, &size, startIdx, true)) { PrintAndLogEx(DEBUG, "DEBUG: Error - EM4305 preamble not found :: %zu", *startIdx); return PM3_ESOFT; From 1731db2f0c0faf028ba178aee4c59d1d6290a993 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 19 Oct 2020 00:51:41 +0200 Subject: [PATCH 19/20] EM4x05: init flipped array --- client/src/cmdlfem4x05.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index 2ad3471c6..4992ab1c8 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -1357,7 +1357,7 @@ int CmdEM4x05Unlock(const char *Cmd) { uint32_t soon = 0; uint32_t late = 0; - em4x05_unlock_item_t flipped[64]; + em4x05_unlock_item_t flipped[64] ={{0,0}}; // // main loop From ae1b4b62b66765cc4009080a11dcfb34af8267f6 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 19 Oct 2020 00:52:21 +0200 Subject: [PATCH 20/20] EM4x05 login & read: don't use threshold for acquisition --- armsrc/lfops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 6f815afe1..4d25bd314 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -2527,7 +2527,7 @@ void EM4xLogin(uint32_t pwd) { WaitUS(400); // We need to acquire more than needed, to help demodulators finding the proper modulation - DoPartialAcquisition(20, false, 6000, 1000); + DoPartialAcquisition(0, false, 6000, 1000); StopTicks(); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); @@ -2562,7 +2562,7 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) { WaitUS(400); - DoPartialAcquisition(20, false, 6000, 1000); + DoPartialAcquisition(0, false, 6000, 1000); StopTicks(); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);