From c3cc3b2a80a12aae82c2a82b57a0ebdcb888f0c9 Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 22 Dec 2020 02:22:28 +0300 Subject: [PATCH 001/173] emrtd: split lds tag det to a different func and improve emrtd_lds_get_data_by_tag --- client/src/cmdhfemrtd.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 30eb4667f..1aa6079ad 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -622,8 +622,15 @@ static int emrtd_read_file(uint8_t *dataout, int *dataoutlen, uint8_t *kenc, uin return true; } +static int emrtd_lds_determine_tag_length(uint8_t tag) { + if ((tag == 0x5F) || (tag == 0x7F)) { + return 2; + } + return 1; +} + static bool emrtd_lds_get_data_by_tag(uint8_t *datain, int datainlen, uint8_t *dataout, int *dataoutlen, int tag1, int tag2, bool twobytetag) { - int offset = 1; + int offset = emrtd_lds_determine_tag_length(*datain); offset += emrtd_get_asn1_field_length(datain, datainlen, offset); int e_idlen = 0; @@ -632,11 +639,7 @@ static bool emrtd_lds_get_data_by_tag(uint8_t *datain, int datainlen, uint8_t *d while (offset < datainlen) { PrintAndLogEx(DEBUG, "emrtd_lds_get_data_by_tag, offset: %i, data: %X", offset, *(datain + offset)); // Determine element ID length to set as offset on asn1datalength - if ((*(datain + offset) == 0x5F) || (*(datain + offset) == 0x7F)) { - e_idlen = 2; - } else { - e_idlen = 1; - } + e_idlen = emrtd_lds_determine_tag_length(*(datain + offset)); // Get the length of the element e_datalen = emrtd_get_asn1_data_length(datain + offset, datainlen - offset, e_idlen); From a05bdecaaf41ba201e571d3ee667123efe3c72d5 Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 22 Dec 2020 02:28:37 +0300 Subject: [PATCH 002/173] emrtd: make top tag skipping on emrtd_lds_get_data_by_tag optional --- client/src/cmdhfemrtd.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 1aa6079ad..e31c326fa 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -629,9 +629,13 @@ static int emrtd_lds_determine_tag_length(uint8_t tag) { return 1; } -static bool emrtd_lds_get_data_by_tag(uint8_t *datain, int datainlen, uint8_t *dataout, int *dataoutlen, int tag1, int tag2, bool twobytetag) { - int offset = emrtd_lds_determine_tag_length(*datain); - offset += emrtd_get_asn1_field_length(datain, datainlen, offset); +static bool emrtd_lds_get_data_by_tag(uint8_t *datain, int datainlen, uint8_t *dataout, int *dataoutlen, int tag1, int tag2, bool twobytetag, bool skiptoptag) { + int offset = 0; + + if (skiptoptag) { + offset += emrtd_lds_determine_tag_length(*datain); + offset += emrtd_get_asn1_field_length(datain, datainlen, offset); + } int e_idlen = 0; int e_datalen = 0; @@ -714,7 +718,7 @@ static int emrtd_dump_ef_dg5(uint8_t *file_contents, size_t file_length) { int datalen = 0; // If we can't find image in EF_DG5, return false. - if (emrtd_lds_get_data_by_tag(file_contents, file_length, data, &datalen, 0x5F, 0x40, true) == false) { + if (emrtd_lds_get_data_by_tag(file_contents, file_length, data, &datalen, 0x5F, 0x40, true, true) == false) { return PM3_ESOFT; } @@ -732,7 +736,7 @@ static int emrtd_dump_ef_dg7(uint8_t *file_contents, size_t file_length) { int datalen = 0; // If we can't find image in EF_DG7, return false. - if (emrtd_lds_get_data_by_tag(file_contents, file_length, data, &datalen, 0x5F, 0x42, true) == false) { + if (emrtd_lds_get_data_by_tag(file_contents, file_length, data, &datalen, 0x5F, 0x42, true, true) == false) { return PM3_ESOFT; } @@ -998,7 +1002,7 @@ int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab uint8_t filelist[50]; int filelistlen = 0; - if (!emrtd_lds_get_data_by_tag(response, resplen, filelist, &filelistlen, 0x5c, 0x00, false)) { + if (!emrtd_lds_get_data_by_tag(response, resplen, filelist, &filelistlen, 0x5c, 0x00, false, true)) { PrintAndLogEx(ERR, "Failed to read file list from EF_COM."); DropField(); return PM3_ESOFT; @@ -1224,7 +1228,7 @@ static void emrtd_print_unknown_timestamp_5f85(uint8_t *data) { static int emrtd_print_ef_com_info(uint8_t *data, size_t datalen) { uint8_t filelist[50]; int filelistlen = 0; - int res = emrtd_lds_get_data_by_tag(data, datalen, filelist, &filelistlen, 0x5c, 0x00, false); + int res = emrtd_lds_get_data_by_tag(data, datalen, filelist, &filelistlen, 0x5c, 0x00, false, true); if (!res) { PrintAndLogEx(ERR, "Failed to read file list from EF_COM."); return PM3_ESOFT; @@ -1255,7 +1259,7 @@ static int emrtd_print_ef_dg1_info(uint8_t *data, size_t datalen) { char mrz[90] = { 0x00 }; int mrzlen = 0; - if (!emrtd_lds_get_data_by_tag(data, datalen, (uint8_t *) mrz, &mrzlen, 0x5f, 0x1f, true)) { + if (!emrtd_lds_get_data_by_tag(data, datalen, (uint8_t *) mrz, &mrzlen, 0x5f, 0x1f, true, true)) { PrintAndLogEx(ERR, "Failed to read MRZ from EF_DG1."); return PM3_ESOFT; } @@ -1337,13 +1341,13 @@ static int emrtd_print_ef_dg11_info(uint8_t *data, size_t datalen) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_DG11") " -------------------"); - if (!emrtd_lds_get_data_by_tag(data, datalen, taglist, &taglistlen, 0x5c, 0x00, false)) { + if (!emrtd_lds_get_data_by_tag(data, datalen, taglist, &taglistlen, 0x5c, 0x00, false, true)) { PrintAndLogEx(ERR, "Failed to read file list from EF_DG11."); return PM3_ESOFT; } for (int i = 0; i < taglistlen; i++) { - emrtd_lds_get_data_by_tag(data, datalen, tagdata, &tagdatalen, taglist[i], taglist[i + 1], taglist[i] == 0x5f); + emrtd_lds_get_data_by_tag(data, datalen, tagdata, &tagdatalen, taglist[i], taglist[i + 1], taglist[i] == 0x5f, true); // Don't bother with empty tags if (tagdatalen == 0) { continue; @@ -1416,13 +1420,13 @@ static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_DG12") " -------------------"); - if (!emrtd_lds_get_data_by_tag(data, datalen, taglist, &taglistlen, 0x5c, 0x00, false)) { + if (!emrtd_lds_get_data_by_tag(data, datalen, taglist, &taglistlen, 0x5c, 0x00, false, true)) { PrintAndLogEx(ERR, "Failed to read file list from EF_DG12."); return PM3_ESOFT; } for (int i = 0; i < taglistlen; i++) { - emrtd_lds_get_data_by_tag(data, datalen, tagdata, &tagdatalen, taglist[i], taglist[i + 1], taglist[i] == 0x5f); + emrtd_lds_get_data_by_tag(data, datalen, tagdata, &tagdatalen, taglist[i], taglist[i + 1], taglist[i] == 0x5f, true); // Don't bother with empty tags if (tagdatalen == 0) { continue; @@ -1524,7 +1528,7 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab uint8_t filelist[50]; int filelistlen = 0; - if (!emrtd_lds_get_data_by_tag(response, resplen, filelist, &filelistlen, 0x5c, 0x00, false)) { + if (!emrtd_lds_get_data_by_tag(response, resplen, filelist, &filelistlen, 0x5c, 0x00, false, true)) { PrintAndLogEx(ERR, "Failed to read file list from EF_COM."); DropField(); return PM3_ESOFT; @@ -1574,7 +1578,7 @@ int infoHF_EMRTD_offline(const char *path) { uint8_t filelist[50]; int filelistlen = 0; - res = emrtd_lds_get_data_by_tag(data, datalen, filelist, &filelistlen, 0x5c, 0x00, false); + res = emrtd_lds_get_data_by_tag(data, datalen, filelist, &filelistlen, 0x5c, 0x00, false, true); if (!res) { PrintAndLogEx(ERR, "Failed to read file list from EF_COM."); free(data); From 8c1e4168cfe2a81c54aa62f93f634751092d9665 Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 22 Dec 2020 02:30:26 +0300 Subject: [PATCH 003/173] emrtd: make style pass --- client/src/cmdhfemrtd.c | 43 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index e31c326fa..d0b3527af 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -61,7 +61,7 @@ static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen); static int emrtd_print_ef_sod_info(uint8_t *data, size_t datalen); typedef enum { // list must match dg_table - EF_COM=0, + EF_COM = 0, EF_DG1, EF_DG2, EF_DG3, @@ -109,7 +109,7 @@ static emrtd_dg_t dg_table[] = { }; static emrtd_dg_t *emrtd_tag_to_dg(uint8_t tag) { - for (int dgi=0; dg_table[dgi].filename != NULL; dgi++) { + for (int dgi = 0; dg_table[dgi].filename != NULL; dgi++) { if (dg_table[dgi].tag == tag) { return &dg_table[dgi]; } @@ -117,7 +117,7 @@ static emrtd_dg_t *emrtd_tag_to_dg(uint8_t tag) { return NULL; } static emrtd_dg_t *emrtd_fileid_to_dg(const char *file_id) { - for (int dgi=0; dg_table[dgi].filename != NULL; dgi++) { + for (int dgi = 0; dg_table[dgi].filename != NULL; dgi++) { if (strcmp(dg_table[dgi].fileid, file_id) == 0) { return &dg_table[dgi]; } @@ -698,7 +698,7 @@ static int emrtd_dump_ef_dg2(uint8_t *file_contents, size_t file_length) { // Note: Doing file_length - 6 to account for the longest data we're checking. for (offset = 0; offset < file_length - 6; offset++) { if ((file_contents[offset] == 0xFF && file_contents[offset + 1] == 0xD8 && file_contents[offset + 2] == 0xFF && file_contents[offset + 3] == 0xE0) || - (file_contents[offset] == 0x00 && file_contents[offset + 1] == 0x00 && file_contents[offset + 2] == 0x00 && file_contents[offset + 3] == 0x0C && file_contents[offset + 4] == 0x6A && file_contents[offset + 5] == 0x50)) { + (file_contents[offset] == 0x00 && file_contents[offset + 1] == 0x00 && file_contents[offset + 2] == 0x00 && file_contents[offset + 3] == 0x0C && file_contents[offset + 4] == 0x6A && file_contents[offset + 5] == 0x50)) { datalen = file_length - offset; break; } @@ -752,7 +752,7 @@ static int emrtd_dump_ef_dg7(uint8_t *file_contents, size_t file_length) { static int emrtd_dump_ef_sod(uint8_t *file_contents, size_t file_length) { int fieldlen = emrtd_get_asn1_field_length(file_contents, file_length, 1); int datalen = emrtd_get_asn1_data_length(file_contents, file_length, 1); - + if (fieldlen + 1 > EMRTD_MAX_FILE_SIZE) { PrintAndLogEx(ERR, "error (emrtd_dump_ef_sod) fieldlen out-of-bounds"); return PM3_SUCCESS; @@ -773,7 +773,7 @@ static bool emrtd_dump_file(uint8_t *ks_enc, uint8_t *ks_mac, uint8_t *ssc, cons PrintAndLogEx(INFO, "Read %s, len: %i.", name, resplen); PrintAndLogEx(DEBUG, "Contents (may be incomplete over 2k chars): %s", sprint_hex_inrow(response, resplen)); saveFile(name, ".BIN", response, resplen); - emrtd_dg_t * dg = emrtd_fileid_to_dg(file); + emrtd_dg_t *dg = emrtd_fileid_to_dg(file); if ((dg != NULL) && (dg->dumper != NULL)) { dg->dumper(response, resplen); } @@ -785,7 +785,7 @@ static void rng(int length, uint8_t *dataout) { //for (int i = 0; i < (length / 4); i++) { // num_to_bytes(prng_successor(msclock() + i, 32), 4, &dataout[i * 4]); //} - memset(dataout, 0x00, length); + memset(dataout, 0x00, length); } static bool emrtd_do_bac(char *documentnumber, char *dob, char *expiry, uint8_t *ssc, uint8_t *ks_enc, uint8_t *ks_mac, bool use_14b) { @@ -1013,7 +1013,7 @@ int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab filelist[filelistlen++] = 0x77; // Dump all files in the file list for (int i = 0; i < filelistlen; i++) { - emrtd_dg_t * dg = emrtd_tag_to_dg(filelist[i]); + emrtd_dg_t *dg = emrtd_tag_to_dg(filelist[i]); if (dg == NULL) { PrintAndLogEx(INFO, "File tag not found, skipping: %02X", filelist[i]); continue; @@ -1034,9 +1034,9 @@ static bool emrtd_compare_check_digit(char *datain, int datalen, char expected_c uint8_t check_digit = emrtd_calculate_check_digit(tempdata) + 0x30; bool res = check_digit == expected_check_digit; PrintAndLogEx(DEBUG, "emrtd_compare_check_digit, expected %c == %c calculated ( %s )" - , expected_check_digit - , check_digit - , (res) ? _GREEN_("ok") : _RED_("fail")); + , expected_check_digit + , check_digit + , (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -1238,7 +1238,7 @@ static int emrtd_print_ef_com_info(uint8_t *data, size_t datalen) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_COM") " --------------------"); for (int i = 0; i < filelistlen; i++) { - emrtd_dg_t * dg = emrtd_tag_to_dg(filelist[i]); + emrtd_dg_t *dg = emrtd_tag_to_dg(filelist[i]); if (dg == NULL) { PrintAndLogEx(INFO, "File tag not found, skipping: %02X", filelist[i]); continue; @@ -1520,7 +1520,7 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab } int res = emrtd_print_ef_com_info(response, resplen); - if ( res != PM3_SUCCESS) { + if (res != PM3_SUCCESS) { DropField(); return res; } @@ -1537,7 +1537,7 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab filelist[filelistlen++] = 0x77; // Dump all files in the file list for (int i = 0; i < filelistlen; i++) { - emrtd_dg_t * dg = emrtd_tag_to_dg(filelist[i]); + emrtd_dg_t *dg = emrtd_tag_to_dg(filelist[i]); if (dg == NULL) { PrintAndLogEx(INFO, "File tag not found, skipping: %02X", filelist[i]); continue; @@ -1570,7 +1570,7 @@ int infoHF_EMRTD_offline(const char *path) { } int res = emrtd_print_ef_com_info(data, datalen); - if ( res != PM3_SUCCESS) { + if (res != PM3_SUCCESS) { free(data); free(filepath); return res; @@ -1590,7 +1590,7 @@ int infoHF_EMRTD_offline(const char *path) { filelist[filelistlen++] = 0x77; // Read files in the file list for (int i = 0; i < filelistlen; i++) { - emrtd_dg_t * dg = emrtd_tag_to_dg(filelist[i]); + emrtd_dg_t *dg = emrtd_tag_to_dg(filelist[i]); if (dg == NULL) { PrintAndLogEx(INFO, "File tag not found, skipping: %02X", filelist[i]); continue; @@ -1599,8 +1599,7 @@ int infoHF_EMRTD_offline(const char *path) { strcpy(filepath, path); strncat(filepath, PATHSEP, 2); strcat(filepath, dg->filename); - if (loadFile_safeEx(filepath, ".BIN", (void **)&data, (size_t *)&datalen, false) == PM3_SUCCESS) - { + if (loadFile_safeEx(filepath, ".BIN", (void **)&data, (size_t *)&datalen, false) == PM3_SUCCESS) { // we won't halt on parsing errors if (dg->parser != NULL) dg->parser(data, datalen); @@ -1669,7 +1668,7 @@ static int cmd_hf_emrtd_dump(const char *Cmd) { memset(docnum + slen, '<', 9 - slen); } } - + if (CLIParamStrToBuf(arg_get_str(ctx, 2), dob, 6, &slen) != 0 || slen == 0) { BAC = false; } else { @@ -1679,7 +1678,7 @@ static int cmd_hf_emrtd_dump(const char *Cmd) { error = true; } } - + if (CLIParamStrToBuf(arg_get_str(ctx, 3), expiry, 6, &slen) != 0 || slen == 0) { BAC = false; } else { @@ -1755,7 +1754,7 @@ static int cmd_hf_emrtd_info(const char *Cmd) { memset(docnum + slen, '<', 9 - slen); } } - + if (CLIParamStrToBuf(arg_get_str(ctx, 2), dob, 6, &slen) != 0 || slen == 0) { BAC = false; } else { @@ -1765,7 +1764,7 @@ static int cmd_hf_emrtd_info(const char *Cmd) { error = true; } } - + if (CLIParamStrToBuf(arg_get_str(ctx, 3), expiry, 6, &slen) != 0 || slen == 0) { BAC = false; } else { From b505c5f4d8e7823c3a2c474e63e375412ec57505 Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 22 Dec 2020 05:01:42 +0300 Subject: [PATCH 004/173] emrtd: Read file hash data from EF_SOD --- client/src/cmdhfemrtd.c | 76 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 8 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index d0b3527af..4e3bfc575 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -203,9 +203,9 @@ static char emrtd_calculate_check_digit(char *data) { } static int emrtd_get_asn1_data_length(uint8_t *datain, int datainlen, int offset) { - PrintAndLogEx(DEBUG, "asn1datalength, datain: %s", sprint_hex_inrow(datain, datainlen)); + PrintAndLogEx(DEBUG, "asn1 datalength, datain: %s", sprint_hex_inrow(datain, datainlen)); int lenfield = (int) * (datain + offset); - PrintAndLogEx(DEBUG, "asn1datalength, lenfield: %i", lenfield); + PrintAndLogEx(DEBUG, "asn1 datalength, lenfield: %02X", lenfield); if (lenfield <= 0x7f) { return lenfield; } else if (lenfield == 0x81) { @@ -221,7 +221,7 @@ static int emrtd_get_asn1_data_length(uint8_t *datain, int datainlen, int offset static int emrtd_get_asn1_field_length(uint8_t *datain, int datainlen, int offset) { PrintAndLogEx(DEBUG, "asn1 fieldlength, datain: %s", sprint_hex_inrow(datain, datainlen)); int lenfield = (int) * (datain + offset); - PrintAndLogEx(DEBUG, "asn1 fieldlength, thing: %i", lenfield); + PrintAndLogEx(DEBUG, "asn1 fieldlength, lenfield: %02X", lenfield); if (lenfield <= 0x7F) { return 1; } else if (lenfield == 0x81) { @@ -629,10 +629,10 @@ static int emrtd_lds_determine_tag_length(uint8_t tag) { return 1; } -static bool emrtd_lds_get_data_by_tag(uint8_t *datain, int datainlen, uint8_t *dataout, int *dataoutlen, int tag1, int tag2, bool twobytetag, bool skiptoptag) { +static bool emrtd_lds_get_data_by_tag(uint8_t *datain, int datainlen, uint8_t *dataout, int *dataoutlen, int tag1, int tag2, bool twobytetag, bool entertoptag) { int offset = 0; - if (skiptoptag) { + if (entertoptag) { offset += emrtd_lds_determine_tag_length(*datain); offset += emrtd_get_asn1_field_length(datain, datainlen, offset); } @@ -651,6 +651,8 @@ static bool emrtd_lds_get_data_by_tag(uint8_t *datain, int datainlen, uint8_t *d // Get the length of the element's length e_fieldlen = emrtd_get_asn1_field_length(datain + offset, datainlen - offset, e_idlen); + PrintAndLogEx(DEBUG, "emrtd_lds_get_data_by_tag, e_idlen: %02X, e_datalen: %02X, e_fieldlen: %02X", e_idlen, e_datalen, e_fieldlen); + // If the element is what we're looking for, get the data and return true if (*(datain + offset) == tag1 && (!twobytetag || *(datain + offset + 1) == tag2)) { if (datainlen > e_datalen) { @@ -1477,10 +1479,68 @@ static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen) { return PM3_SUCCESS; } +static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_t *dataout, size_t *dataoutlen) { + // very very very very cursed code. + uint8_t top[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t signeddata[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t emrtdsigcontainer[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t emrtdsig[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t emrtdsigtext[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + size_t toplen, signeddatalen, emrtdsigcontainerlen, emrtdsiglen, emrtdsigtextlen = 0; + + if (!emrtd_lds_get_data_by_tag(data, (int) datalen, top, (int *) &toplen, 0x30, 0x00, false, true)) { + PrintAndLogEx(ERR, "Failed to read top from EF_SOD."); + return false; + } + + PrintAndLogEx(DEBUG, "top: %s.", sprint_hex_inrow(top, toplen)); + + if (!emrtd_lds_get_data_by_tag(top, (int) toplen, signeddata, (int *) &signeddatalen, 0xA0, 0x00, false, false)) { + PrintAndLogEx(ERR, "Failed to read signedData from EF_SOD."); + return false; + } + + PrintAndLogEx(DEBUG, "signeddata: %s.", sprint_hex_inrow(signeddata, signeddatalen)); + + // Do true on reading into the tag as it's a "sequence" + if (!emrtd_lds_get_data_by_tag(signeddata, (int) signeddatalen, emrtdsigcontainer, (int *) &emrtdsigcontainerlen, 0x30, 0x00, false, true)) { + PrintAndLogEx(ERR, "Failed to read eMRTDSignature container from EF_SOD."); + return false; + } + + PrintAndLogEx(DEBUG, "emrtdsigcontainer: %s.", sprint_hex_inrow(emrtdsigcontainer, emrtdsigcontainerlen)); + + if (!emrtd_lds_get_data_by_tag(emrtdsigcontainer, (int) emrtdsigcontainerlen, emrtdsig, (int *) &emrtdsiglen, 0xA0, 0x00, false, false)) { + PrintAndLogEx(ERR, "Failed to read eMRTDSignature from EF_SOD."); + return false; + } + + PrintAndLogEx(DEBUG, "emrtdsig: %s.", sprint_hex_inrow(emrtdsig, emrtdsiglen)); + + // TODO: Not doing memcpy here, it didn't work, fix it somehow + if (!emrtd_lds_get_data_by_tag(emrtdsig, (int) emrtdsiglen, emrtdsigtext, (int *) &emrtdsigtextlen, 0x04, 0x00, false, false)) { + PrintAndLogEx(ERR, "Failed to read eMRTDSignature (text) from EF_SOD."); + return false; + } + memcpy(dataout, emrtdsigtext, emrtdsigtextlen); + *dataoutlen = emrtdsigtextlen; + return PM3_SUCCESS; +} + static int emrtd_print_ef_sod_info(uint8_t *data, size_t datalen) { -// PrintAndLogEx(NORMAL, ""); -// PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_SOD") " --------------------"); -// PrintAndLogEx(WARNING, "TODO"); + uint8_t emrtdsig[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + // size_t emrtdsiglen, e_datalen, e_fieldlen = 0; + size_t emrtdsiglen = 0; + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_SOD") " --------------------"); + + if (emrtd_ef_sod_extract_signatures(data, datalen, emrtdsig, &emrtdsiglen) != PM3_SUCCESS) { + return false; + } + // TODO: parse this + PrintAndLogEx(INFO, "hash data: %s", sprint_hex_inrow(emrtdsig, emrtdsiglen)); + return PM3_SUCCESS; } From f1a8345faccca4e18795c7c9e9fab1ca39a1aa70 Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 22 Dec 2020 05:29:37 +0300 Subject: [PATCH 005/173] emrtd: Add a skip feature to emrtd_lds_get_data_by_tag --- client/src/cmdhfemrtd.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 4e3bfc575..d92dfb19a 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -629,8 +629,9 @@ static int emrtd_lds_determine_tag_length(uint8_t tag) { return 1; } -static bool emrtd_lds_get_data_by_tag(uint8_t *datain, int datainlen, uint8_t *dataout, int *dataoutlen, int tag1, int tag2, bool twobytetag, bool entertoptag) { +static bool emrtd_lds_get_data_by_tag(uint8_t *datain, int datainlen, uint8_t *dataout, int *dataoutlen, int tag1, int tag2, bool twobytetag, bool entertoptag, int skiptagcount) { int offset = 0; + int skipcounter = 0; if (entertoptag) { offset += emrtd_lds_determine_tag_length(*datain); @@ -655,7 +656,9 @@ static bool emrtd_lds_get_data_by_tag(uint8_t *datain, int datainlen, uint8_t *d // If the element is what we're looking for, get the data and return true if (*(datain + offset) == tag1 && (!twobytetag || *(datain + offset + 1) == tag2)) { - if (datainlen > e_datalen) { + if (skipcounter < skiptagcount) { + skipcounter += 1; + } else if (datainlen > e_datalen) { *dataoutlen = e_datalen; memcpy(dataout, datain + offset + e_idlen + e_fieldlen, e_datalen); return true; @@ -720,7 +723,7 @@ static int emrtd_dump_ef_dg5(uint8_t *file_contents, size_t file_length) { int datalen = 0; // If we can't find image in EF_DG5, return false. - if (emrtd_lds_get_data_by_tag(file_contents, file_length, data, &datalen, 0x5F, 0x40, true, true) == false) { + if (emrtd_lds_get_data_by_tag(file_contents, file_length, data, &datalen, 0x5F, 0x40, true, true, 0) == false) { return PM3_ESOFT; } @@ -738,7 +741,7 @@ static int emrtd_dump_ef_dg7(uint8_t *file_contents, size_t file_length) { int datalen = 0; // If we can't find image in EF_DG7, return false. - if (emrtd_lds_get_data_by_tag(file_contents, file_length, data, &datalen, 0x5F, 0x42, true, true) == false) { + if (emrtd_lds_get_data_by_tag(file_contents, file_length, data, &datalen, 0x5F, 0x42, true, true, 0) == false) { return PM3_ESOFT; } @@ -1004,7 +1007,7 @@ int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab uint8_t filelist[50]; int filelistlen = 0; - if (!emrtd_lds_get_data_by_tag(response, resplen, filelist, &filelistlen, 0x5c, 0x00, false, true)) { + if (!emrtd_lds_get_data_by_tag(response, resplen, filelist, &filelistlen, 0x5c, 0x00, false, true, 0)) { PrintAndLogEx(ERR, "Failed to read file list from EF_COM."); DropField(); return PM3_ESOFT; @@ -1230,7 +1233,7 @@ static void emrtd_print_unknown_timestamp_5f85(uint8_t *data) { static int emrtd_print_ef_com_info(uint8_t *data, size_t datalen) { uint8_t filelist[50]; int filelistlen = 0; - int res = emrtd_lds_get_data_by_tag(data, datalen, filelist, &filelistlen, 0x5c, 0x00, false, true); + int res = emrtd_lds_get_data_by_tag(data, datalen, filelist, &filelistlen, 0x5c, 0x00, false, true, 0); if (!res) { PrintAndLogEx(ERR, "Failed to read file list from EF_COM."); return PM3_ESOFT; @@ -1261,7 +1264,7 @@ static int emrtd_print_ef_dg1_info(uint8_t *data, size_t datalen) { char mrz[90] = { 0x00 }; int mrzlen = 0; - if (!emrtd_lds_get_data_by_tag(data, datalen, (uint8_t *) mrz, &mrzlen, 0x5f, 0x1f, true, true)) { + if (!emrtd_lds_get_data_by_tag(data, datalen, (uint8_t *) mrz, &mrzlen, 0x5f, 0x1f, true, true, 0)) { PrintAndLogEx(ERR, "Failed to read MRZ from EF_DG1."); return PM3_ESOFT; } @@ -1343,13 +1346,13 @@ static int emrtd_print_ef_dg11_info(uint8_t *data, size_t datalen) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_DG11") " -------------------"); - if (!emrtd_lds_get_data_by_tag(data, datalen, taglist, &taglistlen, 0x5c, 0x00, false, true)) { + if (!emrtd_lds_get_data_by_tag(data, datalen, taglist, &taglistlen, 0x5c, 0x00, false, true, 0)) { PrintAndLogEx(ERR, "Failed to read file list from EF_DG11."); return PM3_ESOFT; } for (int i = 0; i < taglistlen; i++) { - emrtd_lds_get_data_by_tag(data, datalen, tagdata, &tagdatalen, taglist[i], taglist[i + 1], taglist[i] == 0x5f, true); + emrtd_lds_get_data_by_tag(data, datalen, tagdata, &tagdatalen, taglist[i], taglist[i + 1], taglist[i] == 0x5f, true, 0); // Don't bother with empty tags if (tagdatalen == 0) { continue; @@ -1422,13 +1425,13 @@ static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_DG12") " -------------------"); - if (!emrtd_lds_get_data_by_tag(data, datalen, taglist, &taglistlen, 0x5c, 0x00, false, true)) { + if (!emrtd_lds_get_data_by_tag(data, datalen, taglist, &taglistlen, 0x5c, 0x00, false, true, 0)) { PrintAndLogEx(ERR, "Failed to read file list from EF_DG12."); return PM3_ESOFT; } for (int i = 0; i < taglistlen; i++) { - emrtd_lds_get_data_by_tag(data, datalen, tagdata, &tagdatalen, taglist[i], taglist[i + 1], taglist[i] == 0x5f, true); + emrtd_lds_get_data_by_tag(data, datalen, tagdata, &tagdatalen, taglist[i], taglist[i + 1], taglist[i] == 0x5f, true, 0); // Don't bother with empty tags if (tagdatalen == 0) { continue; @@ -1488,14 +1491,14 @@ static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_ uint8_t emrtdsigtext[EMRTD_MAX_FILE_SIZE] = { 0x00 }; size_t toplen, signeddatalen, emrtdsigcontainerlen, emrtdsiglen, emrtdsigtextlen = 0; - if (!emrtd_lds_get_data_by_tag(data, (int) datalen, top, (int *) &toplen, 0x30, 0x00, false, true)) { + if (!emrtd_lds_get_data_by_tag(data, (int) datalen, top, (int *) &toplen, 0x30, 0x00, false, true, 0)) { PrintAndLogEx(ERR, "Failed to read top from EF_SOD."); return false; } PrintAndLogEx(DEBUG, "top: %s.", sprint_hex_inrow(top, toplen)); - if (!emrtd_lds_get_data_by_tag(top, (int) toplen, signeddata, (int *) &signeddatalen, 0xA0, 0x00, false, false)) { + if (!emrtd_lds_get_data_by_tag(top, (int) toplen, signeddata, (int *) &signeddatalen, 0xA0, 0x00, false, false, 0)) { PrintAndLogEx(ERR, "Failed to read signedData from EF_SOD."); return false; } @@ -1503,14 +1506,14 @@ static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_ PrintAndLogEx(DEBUG, "signeddata: %s.", sprint_hex_inrow(signeddata, signeddatalen)); // Do true on reading into the tag as it's a "sequence" - if (!emrtd_lds_get_data_by_tag(signeddata, (int) signeddatalen, emrtdsigcontainer, (int *) &emrtdsigcontainerlen, 0x30, 0x00, false, true)) { + if (!emrtd_lds_get_data_by_tag(signeddata, (int) signeddatalen, emrtdsigcontainer, (int *) &emrtdsigcontainerlen, 0x30, 0x00, false, true, 0)) { PrintAndLogEx(ERR, "Failed to read eMRTDSignature container from EF_SOD."); return false; } PrintAndLogEx(DEBUG, "emrtdsigcontainer: %s.", sprint_hex_inrow(emrtdsigcontainer, emrtdsigcontainerlen)); - if (!emrtd_lds_get_data_by_tag(emrtdsigcontainer, (int) emrtdsigcontainerlen, emrtdsig, (int *) &emrtdsiglen, 0xA0, 0x00, false, false)) { + if (!emrtd_lds_get_data_by_tag(emrtdsigcontainer, (int) emrtdsigcontainerlen, emrtdsig, (int *) &emrtdsiglen, 0xA0, 0x00, false, false, 0)) { PrintAndLogEx(ERR, "Failed to read eMRTDSignature from EF_SOD."); return false; } @@ -1518,7 +1521,7 @@ static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_ PrintAndLogEx(DEBUG, "emrtdsig: %s.", sprint_hex_inrow(emrtdsig, emrtdsiglen)); // TODO: Not doing memcpy here, it didn't work, fix it somehow - if (!emrtd_lds_get_data_by_tag(emrtdsig, (int) emrtdsiglen, emrtdsigtext, (int *) &emrtdsigtextlen, 0x04, 0x00, false, false)) { + if (!emrtd_lds_get_data_by_tag(emrtdsig, (int) emrtdsiglen, emrtdsigtext, (int *) &emrtdsigtextlen, 0x04, 0x00, false, false, 0)) { PrintAndLogEx(ERR, "Failed to read eMRTDSignature (text) from EF_SOD."); return false; } @@ -1588,7 +1591,7 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab uint8_t filelist[50]; int filelistlen = 0; - if (!emrtd_lds_get_data_by_tag(response, resplen, filelist, &filelistlen, 0x5c, 0x00, false, true)) { + if (!emrtd_lds_get_data_by_tag(response, resplen, filelist, &filelistlen, 0x5c, 0x00, false, true, 0)) { PrintAndLogEx(ERR, "Failed to read file list from EF_COM."); DropField(); return PM3_ESOFT; @@ -1638,7 +1641,7 @@ int infoHF_EMRTD_offline(const char *path) { uint8_t filelist[50]; int filelistlen = 0; - res = emrtd_lds_get_data_by_tag(data, datalen, filelist, &filelistlen, 0x5c, 0x00, false, true); + res = emrtd_lds_get_data_by_tag(data, datalen, filelist, &filelistlen, 0x5c, 0x00, false, true, 0); if (!res) { PrintAndLogEx(ERR, "Failed to read file list from EF_COM."); free(data); From c3ed99e3883c04a0e0aef09128605cb5adce9a02 Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 22 Dec 2020 05:52:48 +0300 Subject: [PATCH 006/173] emrtd: Parse hashes on EF_SOD --- client/src/cmdhfemrtd.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index d92dfb19a..3203b4932 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1532,8 +1532,19 @@ static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_ static int emrtd_print_ef_sod_info(uint8_t *data, size_t datalen) { uint8_t emrtdsig[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t hashlist[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t hash[65] = { 0x00 }; + size_t hashlen = 0; + + uint8_t hashidstr[4] = { 0x00 }; + size_t hashidstrlen = 0; + // size_t emrtdsiglen, e_datalen, e_fieldlen = 0; size_t emrtdsiglen = 0; + size_t hashlistlen = 0; + size_t e_datalen = 0; + size_t e_fieldlen = 0; + size_t offset = 0; PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_SOD") " --------------------"); @@ -1541,8 +1552,33 @@ static int emrtd_print_ef_sod_info(uint8_t *data, size_t datalen) { if (emrtd_ef_sod_extract_signatures(data, datalen, emrtdsig, &emrtdsiglen) != PM3_SUCCESS) { return false; } - // TODO: parse this - PrintAndLogEx(INFO, "hash data: %s", sprint_hex_inrow(emrtdsig, emrtdsiglen)); + + PrintAndLogEx(DEBUG, "hash data: %s", sprint_hex_inrow(emrtdsig, emrtdsiglen)); + + if (!emrtd_lds_get_data_by_tag(emrtdsig, (int) emrtdsiglen, hashlist, (int *) &hashlistlen, 0x30, 0x00, false, true, 1)) { + PrintAndLogEx(ERR, "Failed to read hash list from EF_SOD."); + return false; + } + + PrintAndLogEx(DEBUG, "hash list: %s", sprint_hex_inrow(hashlist, hashlistlen)); + + while (offset < hashlistlen) { + // Get the length of the element + e_datalen = emrtd_get_asn1_data_length(hashlist + offset, hashlistlen - offset, 1); + + // Get the length of the element's length + e_fieldlen = emrtd_get_asn1_field_length(hashlist + offset, hashlistlen - offset, 1); + + switch (hashlist[offset]) { + case 0x30: + emrtd_lds_get_data_by_tag(hashlist + offset + e_fieldlen + 1, (int) e_datalen, hashidstr, (int *) &hashidstrlen, 0x02, 0x00, false, false, 0); + emrtd_lds_get_data_by_tag(hashlist + offset + e_fieldlen + 1, (int) e_datalen, hash, (int *) &hashlen, 0x04, 0x00, false, false, 0); + PrintAndLogEx(SUCCESS, "Hash for EF_DG%i: %s", hashidstr[0], sprint_hex_inrow(hash, hashlen)); + break; + } + // + 1 for length of ID + offset += 1 + e_datalen + e_fieldlen; + } return PM3_SUCCESS; } From 0272a3b63eaca1bde5f5093ebd2bb5c3572142c5 Mon Sep 17 00:00:00 2001 From: Ave Date: Wed, 23 Dec 2020 22:27:05 +0300 Subject: [PATCH 007/173] emrtd: Move a lot of size values from int to size_t --- client/src/cmdhfemrtd.c | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 3203b4932..0c9de0cac 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -629,7 +629,7 @@ static int emrtd_lds_determine_tag_length(uint8_t tag) { return 1; } -static bool emrtd_lds_get_data_by_tag(uint8_t *datain, int datainlen, uint8_t *dataout, int *dataoutlen, int tag1, int tag2, bool twobytetag, bool entertoptag, int skiptagcount) { +static bool emrtd_lds_get_data_by_tag(uint8_t *datain, size_t datainlen, uint8_t *dataout, size_t *dataoutlen, int tag1, int tag2, bool twobytetag, bool entertoptag, size_t skiptagcount) { int offset = 0; int skipcounter = 0; @@ -720,7 +720,7 @@ static int emrtd_dump_ef_dg2(uint8_t *file_contents, size_t file_length) { static int emrtd_dump_ef_dg5(uint8_t *file_contents, size_t file_length) { uint8_t data[EMRTD_MAX_FILE_SIZE]; - int datalen = 0; + size_t datalen = 0; // If we can't find image in EF_DG5, return false. if (emrtd_lds_get_data_by_tag(file_contents, file_length, data, &datalen, 0x5F, 0x40, true, true, 0) == false) { @@ -738,7 +738,7 @@ static int emrtd_dump_ef_dg5(uint8_t *file_contents, size_t file_length) { static int emrtd_dump_ef_dg7(uint8_t *file_contents, size_t file_length) { uint8_t data[EMRTD_MAX_FILE_SIZE]; - int datalen = 0; + size_t datalen = 0; // If we can't find image in EF_DG7, return false. if (emrtd_lds_get_data_by_tag(file_contents, file_length, data, &datalen, 0x5F, 0x42, true, true, 0) == false) { @@ -1005,7 +1005,7 @@ int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab saveFile(dg_table[EF_COM].filename, ".BIN", response, resplen); uint8_t filelist[50]; - int filelistlen = 0; + size_t filelistlen = 0; if (!emrtd_lds_get_data_by_tag(response, resplen, filelist, &filelistlen, 0x5c, 0x00, false, true, 0)) { PrintAndLogEx(ERR, "Failed to read file list from EF_COM."); @@ -1017,7 +1017,7 @@ int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab // Add EF_SOD to the list filelist[filelistlen++] = 0x77; // Dump all files in the file list - for (int i = 0; i < filelistlen; i++) { + for (size_t i = 0; i < filelistlen; i++) { emrtd_dg_t *dg = emrtd_tag_to_dg(filelist[i]); if (dg == NULL) { PrintAndLogEx(INFO, "File tag not found, skipping: %02X", filelist[i]); @@ -1232,7 +1232,7 @@ static void emrtd_print_unknown_timestamp_5f85(uint8_t *data) { static int emrtd_print_ef_com_info(uint8_t *data, size_t datalen) { uint8_t filelist[50]; - int filelistlen = 0; + size_t filelistlen = 0; int res = emrtd_lds_get_data_by_tag(data, datalen, filelist, &filelistlen, 0x5c, 0x00, false, true, 0); if (!res) { PrintAndLogEx(ERR, "Failed to read file list from EF_COM."); @@ -1262,7 +1262,7 @@ static int emrtd_print_ef_dg1_info(uint8_t *data, size_t datalen) { // MRZ on TD1 is 90 characters, 30 on each row. // MRZ on TD3 is 88 characters, 44 on each row. char mrz[90] = { 0x00 }; - int mrzlen = 0; + size_t mrzlen = 0; if (!emrtd_lds_get_data_by_tag(data, datalen, (uint8_t *) mrz, &mrzlen, 0x5f, 0x1f, true, true, 0)) { PrintAndLogEx(ERR, "Failed to read MRZ from EF_DG1."); @@ -1339,9 +1339,9 @@ static int emrtd_print_ef_dg1_info(uint8_t *data, size_t datalen) { static int emrtd_print_ef_dg11_info(uint8_t *data, size_t datalen) { uint8_t taglist[100] = { 0x00 }; - int taglistlen = 0; + size_t taglistlen = 0; uint8_t tagdata[1000] = { 0x00 }; - int tagdatalen = 0; + size_t tagdatalen = 0; PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_DG11") " -------------------"); @@ -1418,9 +1418,9 @@ static int emrtd_print_ef_dg11_info(uint8_t *data, size_t datalen) { static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen) { uint8_t taglist[100] = { 0x00 }; - int taglistlen = 0; + size_t taglistlen = 0; uint8_t tagdata[1000] = { 0x00 }; - int tagdatalen = 0; + size_t tagdatalen = 0; PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_DG12") " -------------------"); @@ -1491,14 +1491,14 @@ static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_ uint8_t emrtdsigtext[EMRTD_MAX_FILE_SIZE] = { 0x00 }; size_t toplen, signeddatalen, emrtdsigcontainerlen, emrtdsiglen, emrtdsigtextlen = 0; - if (!emrtd_lds_get_data_by_tag(data, (int) datalen, top, (int *) &toplen, 0x30, 0x00, false, true, 0)) { + if (!emrtd_lds_get_data_by_tag(data, datalen, top, &toplen, 0x30, 0x00, false, true, 0)) { PrintAndLogEx(ERR, "Failed to read top from EF_SOD."); return false; } PrintAndLogEx(DEBUG, "top: %s.", sprint_hex_inrow(top, toplen)); - if (!emrtd_lds_get_data_by_tag(top, (int) toplen, signeddata, (int *) &signeddatalen, 0xA0, 0x00, false, false, 0)) { + if (!emrtd_lds_get_data_by_tag(top, toplen, signeddata, &signeddatalen, 0xA0, 0x00, false, false, 0)) { PrintAndLogEx(ERR, "Failed to read signedData from EF_SOD."); return false; } @@ -1506,14 +1506,14 @@ static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_ PrintAndLogEx(DEBUG, "signeddata: %s.", sprint_hex_inrow(signeddata, signeddatalen)); // Do true on reading into the tag as it's a "sequence" - if (!emrtd_lds_get_data_by_tag(signeddata, (int) signeddatalen, emrtdsigcontainer, (int *) &emrtdsigcontainerlen, 0x30, 0x00, false, true, 0)) { + if (!emrtd_lds_get_data_by_tag(signeddata, signeddatalen, emrtdsigcontainer, &emrtdsigcontainerlen, 0x30, 0x00, false, true, 0)) { PrintAndLogEx(ERR, "Failed to read eMRTDSignature container from EF_SOD."); return false; } PrintAndLogEx(DEBUG, "emrtdsigcontainer: %s.", sprint_hex_inrow(emrtdsigcontainer, emrtdsigcontainerlen)); - if (!emrtd_lds_get_data_by_tag(emrtdsigcontainer, (int) emrtdsigcontainerlen, emrtdsig, (int *) &emrtdsiglen, 0xA0, 0x00, false, false, 0)) { + if (!emrtd_lds_get_data_by_tag(emrtdsigcontainer, emrtdsigcontainerlen, emrtdsig, &emrtdsiglen, 0xA0, 0x00, false, false, 0)) { PrintAndLogEx(ERR, "Failed to read eMRTDSignature from EF_SOD."); return false; } @@ -1521,7 +1521,7 @@ static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_ PrintAndLogEx(DEBUG, "emrtdsig: %s.", sprint_hex_inrow(emrtdsig, emrtdsiglen)); // TODO: Not doing memcpy here, it didn't work, fix it somehow - if (!emrtd_lds_get_data_by_tag(emrtdsig, (int) emrtdsiglen, emrtdsigtext, (int *) &emrtdsigtextlen, 0x04, 0x00, false, false, 0)) { + if (!emrtd_lds_get_data_by_tag(emrtdsig, emrtdsiglen, emrtdsigtext, &emrtdsigtextlen, 0x04, 0x00, false, false, 0)) { PrintAndLogEx(ERR, "Failed to read eMRTDSignature (text) from EF_SOD."); return false; } @@ -1555,7 +1555,7 @@ static int emrtd_print_ef_sod_info(uint8_t *data, size_t datalen) { PrintAndLogEx(DEBUG, "hash data: %s", sprint_hex_inrow(emrtdsig, emrtdsiglen)); - if (!emrtd_lds_get_data_by_tag(emrtdsig, (int) emrtdsiglen, hashlist, (int *) &hashlistlen, 0x30, 0x00, false, true, 1)) { + if (!emrtd_lds_get_data_by_tag(emrtdsig, emrtdsiglen, hashlist, &hashlistlen, 0x30, 0x00, false, true, 1)) { PrintAndLogEx(ERR, "Failed to read hash list from EF_SOD."); return false; } @@ -1571,8 +1571,8 @@ static int emrtd_print_ef_sod_info(uint8_t *data, size_t datalen) { switch (hashlist[offset]) { case 0x30: - emrtd_lds_get_data_by_tag(hashlist + offset + e_fieldlen + 1, (int) e_datalen, hashidstr, (int *) &hashidstrlen, 0x02, 0x00, false, false, 0); - emrtd_lds_get_data_by_tag(hashlist + offset + e_fieldlen + 1, (int) e_datalen, hash, (int *) &hashlen, 0x04, 0x00, false, false, 0); + emrtd_lds_get_data_by_tag(hashlist + offset + e_fieldlen + 1, e_datalen, hashidstr, &hashidstrlen, 0x02, 0x00, false, false, 0); + emrtd_lds_get_data_by_tag(hashlist + offset + e_fieldlen + 1, e_datalen, hash, &hashlen, 0x04, 0x00, false, false, 0); PrintAndLogEx(SUCCESS, "Hash for EF_DG%i: %s", hashidstr[0], sprint_hex_inrow(hash, hashlen)); break; } @@ -1625,7 +1625,7 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab } uint8_t filelist[50]; - int filelistlen = 0; + size_t filelistlen = 0; if (!emrtd_lds_get_data_by_tag(response, resplen, filelist, &filelistlen, 0x5c, 0x00, false, true, 0)) { PrintAndLogEx(ERR, "Failed to read file list from EF_COM."); @@ -1676,7 +1676,7 @@ int infoHF_EMRTD_offline(const char *path) { } uint8_t filelist[50]; - int filelistlen = 0; + size_t filelistlen = 0; res = emrtd_lds_get_data_by_tag(data, datalen, filelist, &filelistlen, 0x5c, 0x00, false, true, 0); if (!res) { PrintAndLogEx(ERR, "Failed to read file list from EF_COM."); From 4962cb84ecc73bbc6e54a92fa0240fa582b7c7d1 Mon Sep 17 00:00:00 2001 From: Ave Date: Wed, 23 Dec 2020 22:37:51 +0300 Subject: [PATCH 008/173] emrtd: Note that MRZ option is for passports (TD3) only --- client/src/cmdhfemrtd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index d90c7e79e..499b06c1a 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1831,7 +1831,7 @@ static int cmd_hf_emrtd_info(const char *Cmd) { arg_str0("n", "documentnumber", "", "document number, up to 9 chars"), arg_str0("d", "dateofbirth", "", "date of birth in YYMMDD format"), arg_str0("e", "expiry", "", "expiry in YYMMDD format"), - arg_str0("m", "mrz", "<[0-9A-Z<]>", "2nd line of MRZ, 44 chars"), + arg_str0("m", "mrz", "<[0-9A-Z<]>", "2nd line of MRZ, 44 chars (passports only)"), arg_str0(NULL, "path", "", "display info from offline dump stored in dirpath"), arg_param_end }; From 9987ebf53493df280d9ef04e4e3efecc201f97b4 Mon Sep 17 00:00:00 2001 From: Ave Date: Wed, 23 Dec 2020 23:08:34 +0300 Subject: [PATCH 009/173] emrtd: Use memcmp for JPEG headers --- client/src/cmdhfemrtd.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 499b06c1a..1a51ea427 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -693,17 +693,19 @@ static bool emrtd_select_and_read(uint8_t *dataout, int *dataoutlen, const char return true; } +const uint8_t jpeg_header[4] = { 0xFF, 0xD8, 0xFF, 0xE0 }; +const uint8_t jpeg2k_header[6] = { 0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50 }; + static int emrtd_dump_ef_dg2(uint8_t *file_contents, size_t file_length) { int offset, datalen = 0; // This is a hacky impl that just looks for the image header. I'll improve it eventually. // based on mrpkey.py - // FF D8 FF E0 -> JPEG - // 00 00 00 0C 6A 50 -> JPEG 2000 // Note: Doing file_length - 6 to account for the longest data we're checking. + // Checks first byte before the rest to reduce overhead for (offset = 0; offset < file_length - 6; offset++) { - if ((file_contents[offset] == 0xFF && file_contents[offset + 1] == 0xD8 && file_contents[offset + 2] == 0xFF && file_contents[offset + 3] == 0xE0) || - (file_contents[offset] == 0x00 && file_contents[offset + 1] == 0x00 && file_contents[offset + 2] == 0x00 && file_contents[offset + 3] == 0x0C && file_contents[offset + 4] == 0x6A && file_contents[offset + 5] == 0x50)) { + if ((file_contents[offset] == 0xFF && memcmp(jpeg_header, file_contents + offset, 4) != 0) || + (file_contents[offset] == 0x00 && memcmp(jpeg2k_header, file_contents + offset, 6) != 0)) { datalen = file_length - offset; break; } From f26e027e23259f247c87efc6ffc998ff80b07624 Mon Sep 17 00:00:00 2001 From: Ave Date: Wed, 23 Dec 2020 23:13:13 +0300 Subject: [PATCH 010/173] gitignore: Ignore emrtd dumps --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 081c0f8e8..94b4c221b 100644 --- a/.gitignore +++ b/.gitignore @@ -98,6 +98,7 @@ tools/andrew/* tools/jtag_openocd/openocd_configuration ppls patches/* *- Copy.* +/EF_* client/lualibs/mfc_default_keys.lua client/lualibs/pm3_cmd.lua From a1762fa4a30dde35e92d2f0c5164aa3c5d59c948 Mon Sep 17 00:00:00 2001 From: Ave Date: Wed, 23 Dec 2020 23:21:54 +0300 Subject: [PATCH 011/173] emrtd: Mark biometrics as EAC-only and introduce the concept --- client/src/cmdhfemrtd.c | 48 ++++++++++++++++++++--------------------- client/src/cmdhfemrtd.h | 1 + 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 1a51ea427..fa669f103 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -84,28 +84,28 @@ typedef enum { // list must match dg_table } emrtd_dg_enum; static emrtd_dg_t dg_table[] = { -// tag fileid filename desc pace req fast parser dumper - {0x60, "011E", "EF_COM", "Header and Data Group Presence Information", false, true, true, emrtd_print_ef_com_info, NULL}, - {0x61, "0101", "EF_DG1", "Details recorded in MRZ", false, true, true, emrtd_print_ef_dg1_info, NULL}, - {0x75, "0102", "EF_DG2", "Encoded Face", false, true, false, NULL, emrtd_dump_ef_dg2}, - {0x63, "0103", "EF_DG3", "Encoded Finger(s)", true, false, false, NULL, NULL}, - {0x76, "0104", "EF_DG4", "Encoded Eye(s)", true, false, false, NULL, NULL}, - {0x65, "0105", "EF_DG5", "Displayed Portrait", false, false, false, NULL, emrtd_dump_ef_dg5}, - {0x66, "0106", "EF_DG6", "Reserved for Future Use", false, false, false, NULL, NULL}, - {0x67, "0107", "EF_DG7", "Displayed Signature or Usual Mark", false, false, false, NULL, emrtd_dump_ef_dg7}, - {0x68, "0108", "EF_DG8", "Data Feature(s)", false, false, true, NULL, NULL}, - {0x69, "0109", "EF_DG9", "Structure Feature(s)", false, false, true, NULL, NULL}, - {0x6a, "010A", "EF_DG10", "Substance Feature(s)", false, false, true, NULL, NULL}, - {0x6b, "010B", "EF_DG11", "Additional Personal Detail(s)", false, false, true, emrtd_print_ef_dg11_info, NULL}, - {0x6c, "010C", "EF_DG12", "Additional Document Detail(s)", false, false, true, emrtd_print_ef_dg12_info, NULL}, - {0x6d, "010D", "EF_DG13", "Optional Detail(s)", false, false, true, NULL, NULL}, - {0x6e, "010E", "EF_DG14", "Security Options", false, false, true, NULL, NULL}, - {0x6f, "010F", "EF_DG15", "Active Authentication Public Key Info", false, false, true, NULL, NULL}, - {0x70, "0110", "EF_DG16", "Person(s) to Notify", false, false, true, NULL, NULL}, - {0x77, "011D", "EF_SOD", "Document Security Object", false, false, true, emrtd_print_ef_sod_info, emrtd_dump_ef_sod}, - {0xff, "011C", "EF_CardAccess", "PACE SecurityInfos", true, true, true, NULL, NULL}, - {0xff, "011D", "EF_CardSecurity", "PACE SecurityInfos for Chip Authentication Mapping", true, false, true, NULL, NULL}, - {0x00, NULL, NULL, NULL, false, false, false, NULL, NULL} +// tag fileid filename desc pace eac req fast parser dumper + {0x60, "011E", "EF_COM", "Header and Data Group Presence Information", false, false, true, true, emrtd_print_ef_com_info, NULL}, + {0x61, "0101", "EF_DG1", "Details recorded in MRZ", false, false, true, true, emrtd_print_ef_dg1_info, NULL}, + {0x75, "0102", "EF_DG2", "Encoded Face", false, false, true, false, NULL, emrtd_dump_ef_dg2}, + {0x63, "0103", "EF_DG3", "Encoded Finger(s)", false, true, false, false, NULL, NULL}, + {0x76, "0104", "EF_DG4", "Encoded Eye(s)", false, true, false, false, NULL, NULL}, + {0x65, "0105", "EF_DG5", "Displayed Portrait", false, false, false, false, NULL, emrtd_dump_ef_dg5}, + {0x66, "0106", "EF_DG6", "Reserved for Future Use", false, false, false, false, NULL, NULL}, + {0x67, "0107", "EF_DG7", "Displayed Signature or Usual Mark", false, false, false, false, NULL, emrtd_dump_ef_dg7}, + {0x68, "0108", "EF_DG8", "Data Feature(s)", false, false, false, true, NULL, NULL}, + {0x69, "0109", "EF_DG9", "Structure Feature(s)", false, false, false, true, NULL, NULL}, + {0x6a, "010A", "EF_DG10", "Substance Feature(s)", false, false, false, true, NULL, NULL}, + {0x6b, "010B", "EF_DG11", "Additional Personal Detail(s)", false, false, false, true, emrtd_print_ef_dg11_info, NULL}, + {0x6c, "010C", "EF_DG12", "Additional Document Detail(s)", false, false, false, true, emrtd_print_ef_dg12_info, NULL}, + {0x6d, "010D", "EF_DG13", "Optional Detail(s)", false, false, false, true, NULL, NULL}, + {0x6e, "010E", "EF_DG14", "Security Options", false, false, false, true, NULL, NULL}, + {0x6f, "010F", "EF_DG15", "Active Authentication Public Key Info", false, false, false, true, NULL, NULL}, + {0x70, "0110", "EF_DG16", "Person(s) to Notify", false, false, false, true, NULL, NULL}, + {0x77, "011D", "EF_SOD", "Document Security Object", false, false, false, true, emrtd_print_ef_sod_info, emrtd_dump_ef_sod}, + {0xff, "011C", "EF_CardAccess", "PACE SecurityInfos", true, false, true, true, NULL, NULL}, + {0xff, "011D", "EF_CardSecurity", "PACE SecurityInfos for Chip Authentication Mapping", true, false, false, true, NULL, NULL}, + {0x00, NULL, NULL, NULL, false, false, false, false, NULL, NULL} }; static emrtd_dg_t *emrtd_tag_to_dg(uint8_t tag) { @@ -1026,7 +1026,7 @@ int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab continue; } PrintAndLogEx(DEBUG, "Current file: %s", dg->filename); - if (!dg->pace) { + if (!dg->pace && !dg->eac) { emrtd_dump_file(ks_enc, ks_mac, ssc, dg->fileid, dg->filename, BAC, use_14b); } } @@ -1643,7 +1643,7 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab PrintAndLogEx(INFO, "File tag not found, skipping: %02X", filelist[i]); continue; } - if (dg->fastdump && !dg->pace) { + if (dg->fastdump && !dg->pace && !dg->eac) { if (emrtd_select_and_read(response, &resplen, dg->fileid, ks_enc, ks_mac, ssc, BAC, use_14b)) { if (dg->parser != NULL) dg->parser(response, resplen); diff --git a/client/src/cmdhfemrtd.h b/client/src/cmdhfemrtd.h index 9df7846ad..bcae56538 100644 --- a/client/src/cmdhfemrtd.h +++ b/client/src/cmdhfemrtd.h @@ -19,6 +19,7 @@ typedef struct emrtd_dg_s { const char *filename; const char *desc; bool pace; + bool eac; // EAC only (we can't dump these) bool required; // some are required only if PACE bool fastdump; // fast to dump int (*parser)(uint8_t *data, size_t datalen); From 9e7d515c37d1303de07b635b0e0682ddb4a8303c Mon Sep 17 00:00:00 2001 From: Ave Date: Wed, 23 Dec 2020 23:52:31 +0300 Subject: [PATCH 012/173] emrtd info: Don't print EF_SOD info --- client/src/cmdhfemrtd.c | 163 ++++++++++++++++++++-------------------- 1 file changed, 81 insertions(+), 82 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index fa669f103..88a79707a 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -58,7 +58,6 @@ static int emrtd_print_ef_com_info(uint8_t *data, size_t datalen); static int emrtd_print_ef_dg1_info(uint8_t *data, size_t datalen); static int emrtd_print_ef_dg11_info(uint8_t *data, size_t datalen); static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen); -static int emrtd_print_ef_sod_info(uint8_t *data, size_t datalen); typedef enum { // list must match dg_table EF_COM = 0, @@ -102,7 +101,7 @@ static emrtd_dg_t dg_table[] = { {0x6e, "010E", "EF_DG14", "Security Options", false, false, false, true, NULL, NULL}, {0x6f, "010F", "EF_DG15", "Active Authentication Public Key Info", false, false, false, true, NULL, NULL}, {0x70, "0110", "EF_DG16", "Person(s) to Notify", false, false, false, true, NULL, NULL}, - {0x77, "011D", "EF_SOD", "Document Security Object", false, false, false, true, emrtd_print_ef_sod_info, emrtd_dump_ef_sod}, + {0x77, "011D", "EF_SOD", "Document Security Object", false, false, false, false, NULL, emrtd_dump_ef_sod}, {0xff, "011C", "EF_CardAccess", "PACE SecurityInfos", true, false, true, true, NULL, NULL}, {0xff, "011D", "EF_CardSecurity", "PACE SecurityInfos for Chip Authentication Mapping", true, false, false, true, NULL, NULL}, {0x00, NULL, NULL, NULL, false, false, false, false, NULL, NULL} @@ -1484,106 +1483,106 @@ static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen) { return PM3_SUCCESS; } -static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_t *dataout, size_t *dataoutlen) { - // very very very very cursed code. - uint8_t top[EMRTD_MAX_FILE_SIZE] = { 0x00 }; - uint8_t signeddata[EMRTD_MAX_FILE_SIZE] = { 0x00 }; - uint8_t emrtdsigcontainer[EMRTD_MAX_FILE_SIZE] = { 0x00 }; - uint8_t emrtdsig[EMRTD_MAX_FILE_SIZE] = { 0x00 }; - uint8_t emrtdsigtext[EMRTD_MAX_FILE_SIZE] = { 0x00 }; - size_t toplen, signeddatalen, emrtdsigcontainerlen, emrtdsiglen, emrtdsigtextlen = 0; +// static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_t *dataout, size_t *dataoutlen) { +// // very very very very cursed code. +// uint8_t top[EMRTD_MAX_FILE_SIZE] = { 0x00 }; +// uint8_t signeddata[EMRTD_MAX_FILE_SIZE] = { 0x00 }; +// uint8_t emrtdsigcontainer[EMRTD_MAX_FILE_SIZE] = { 0x00 }; +// uint8_t emrtdsig[EMRTD_MAX_FILE_SIZE] = { 0x00 }; +// uint8_t emrtdsigtext[EMRTD_MAX_FILE_SIZE] = { 0x00 }; +// size_t toplen, signeddatalen, emrtdsigcontainerlen, emrtdsiglen, emrtdsigtextlen = 0; - if (!emrtd_lds_get_data_by_tag(data, datalen, top, &toplen, 0x30, 0x00, false, true, 0)) { - PrintAndLogEx(ERR, "Failed to read top from EF_SOD."); - return false; - } +// if (!emrtd_lds_get_data_by_tag(data, datalen, top, &toplen, 0x30, 0x00, false, true, 0)) { +// PrintAndLogEx(ERR, "Failed to read top from EF_SOD."); +// return false; +// } - PrintAndLogEx(DEBUG, "top: %s.", sprint_hex_inrow(top, toplen)); +// PrintAndLogEx(DEBUG, "top: %s.", sprint_hex_inrow(top, toplen)); - if (!emrtd_lds_get_data_by_tag(top, toplen, signeddata, &signeddatalen, 0xA0, 0x00, false, false, 0)) { - PrintAndLogEx(ERR, "Failed to read signedData from EF_SOD."); - return false; - } +// if (!emrtd_lds_get_data_by_tag(top, toplen, signeddata, &signeddatalen, 0xA0, 0x00, false, false, 0)) { +// PrintAndLogEx(ERR, "Failed to read signedData from EF_SOD."); +// return false; +// } - PrintAndLogEx(DEBUG, "signeddata: %s.", sprint_hex_inrow(signeddata, signeddatalen)); +// PrintAndLogEx(DEBUG, "signeddata: %s.", sprint_hex_inrow(signeddata, signeddatalen)); - // Do true on reading into the tag as it's a "sequence" - if (!emrtd_lds_get_data_by_tag(signeddata, signeddatalen, emrtdsigcontainer, &emrtdsigcontainerlen, 0x30, 0x00, false, true, 0)) { - PrintAndLogEx(ERR, "Failed to read eMRTDSignature container from EF_SOD."); - return false; - } +// // Do true on reading into the tag as it's a "sequence" +// if (!emrtd_lds_get_data_by_tag(signeddata, signeddatalen, emrtdsigcontainer, &emrtdsigcontainerlen, 0x30, 0x00, false, true, 0)) { +// PrintAndLogEx(ERR, "Failed to read eMRTDSignature container from EF_SOD."); +// return false; +// } - PrintAndLogEx(DEBUG, "emrtdsigcontainer: %s.", sprint_hex_inrow(emrtdsigcontainer, emrtdsigcontainerlen)); +// PrintAndLogEx(DEBUG, "emrtdsigcontainer: %s.", sprint_hex_inrow(emrtdsigcontainer, emrtdsigcontainerlen)); - if (!emrtd_lds_get_data_by_tag(emrtdsigcontainer, emrtdsigcontainerlen, emrtdsig, &emrtdsiglen, 0xA0, 0x00, false, false, 0)) { - PrintAndLogEx(ERR, "Failed to read eMRTDSignature from EF_SOD."); - return false; - } +// if (!emrtd_lds_get_data_by_tag(emrtdsigcontainer, emrtdsigcontainerlen, emrtdsig, &emrtdsiglen, 0xA0, 0x00, false, false, 0)) { +// PrintAndLogEx(ERR, "Failed to read eMRTDSignature from EF_SOD."); +// return false; +// } - PrintAndLogEx(DEBUG, "emrtdsig: %s.", sprint_hex_inrow(emrtdsig, emrtdsiglen)); +// PrintAndLogEx(DEBUG, "emrtdsig: %s.", sprint_hex_inrow(emrtdsig, emrtdsiglen)); - // TODO: Not doing memcpy here, it didn't work, fix it somehow - if (!emrtd_lds_get_data_by_tag(emrtdsig, emrtdsiglen, emrtdsigtext, &emrtdsigtextlen, 0x04, 0x00, false, false, 0)) { - PrintAndLogEx(ERR, "Failed to read eMRTDSignature (text) from EF_SOD."); - return false; - } - memcpy(dataout, emrtdsigtext, emrtdsigtextlen); - *dataoutlen = emrtdsigtextlen; - return PM3_SUCCESS; -} +// // TODO: Not doing memcpy here, it didn't work, fix it somehow +// if (!emrtd_lds_get_data_by_tag(emrtdsig, emrtdsiglen, emrtdsigtext, &emrtdsigtextlen, 0x04, 0x00, false, false, 0)) { +// PrintAndLogEx(ERR, "Failed to read eMRTDSignature (text) from EF_SOD."); +// return false; +// } +// memcpy(dataout, emrtdsigtext, emrtdsigtextlen); +// *dataoutlen = emrtdsigtextlen; +// return PM3_SUCCESS; +// } -static int emrtd_print_ef_sod_info(uint8_t *data, size_t datalen) { - uint8_t emrtdsig[EMRTD_MAX_FILE_SIZE] = { 0x00 }; - uint8_t hashlist[EMRTD_MAX_FILE_SIZE] = { 0x00 }; - uint8_t hash[65] = { 0x00 }; - size_t hashlen = 0; +// static int emrtd_print_ef_sod_info(uint8_t *data, size_t datalen) { +// uint8_t emrtdsig[EMRTD_MAX_FILE_SIZE] = { 0x00 }; +// uint8_t hashlist[EMRTD_MAX_FILE_SIZE] = { 0x00 }; +// uint8_t hash[65] = { 0x00 }; +// size_t hashlen = 0; - uint8_t hashidstr[4] = { 0x00 }; - size_t hashidstrlen = 0; +// uint8_t hashidstr[4] = { 0x00 }; +// size_t hashidstrlen = 0; - // size_t emrtdsiglen, e_datalen, e_fieldlen = 0; - size_t emrtdsiglen = 0; - size_t hashlistlen = 0; - size_t e_datalen = 0; - size_t e_fieldlen = 0; - size_t offset = 0; +// // size_t emrtdsiglen, e_datalen, e_fieldlen = 0; +// size_t emrtdsiglen = 0; +// size_t hashlistlen = 0; +// size_t e_datalen = 0; +// size_t e_fieldlen = 0; +// size_t offset = 0; - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_SOD") " --------------------"); +// PrintAndLogEx(NORMAL, ""); +// PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_SOD") " --------------------"); - if (emrtd_ef_sod_extract_signatures(data, datalen, emrtdsig, &emrtdsiglen) != PM3_SUCCESS) { - return false; - } +// if (emrtd_ef_sod_extract_signatures(data, datalen, emrtdsig, &emrtdsiglen) != PM3_SUCCESS) { +// return false; +// } - PrintAndLogEx(DEBUG, "hash data: %s", sprint_hex_inrow(emrtdsig, emrtdsiglen)); +// PrintAndLogEx(DEBUG, "hash data: %s", sprint_hex_inrow(emrtdsig, emrtdsiglen)); - if (!emrtd_lds_get_data_by_tag(emrtdsig, emrtdsiglen, hashlist, &hashlistlen, 0x30, 0x00, false, true, 1)) { - PrintAndLogEx(ERR, "Failed to read hash list from EF_SOD."); - return false; - } +// if (!emrtd_lds_get_data_by_tag(emrtdsig, emrtdsiglen, hashlist, &hashlistlen, 0x30, 0x00, false, true, 1)) { +// PrintAndLogEx(ERR, "Failed to read hash list from EF_SOD."); +// return false; +// } - PrintAndLogEx(DEBUG, "hash list: %s", sprint_hex_inrow(hashlist, hashlistlen)); +// PrintAndLogEx(DEBUG, "hash list: %s", sprint_hex_inrow(hashlist, hashlistlen)); - while (offset < hashlistlen) { - // Get the length of the element - e_datalen = emrtd_get_asn1_data_length(hashlist + offset, hashlistlen - offset, 1); +// while (offset < hashlistlen) { +// // Get the length of the element +// e_datalen = emrtd_get_asn1_data_length(hashlist + offset, hashlistlen - offset, 1); - // Get the length of the element's length - e_fieldlen = emrtd_get_asn1_field_length(hashlist + offset, hashlistlen - offset, 1); +// // Get the length of the element's length +// e_fieldlen = emrtd_get_asn1_field_length(hashlist + offset, hashlistlen - offset, 1); - switch (hashlist[offset]) { - case 0x30: - emrtd_lds_get_data_by_tag(hashlist + offset + e_fieldlen + 1, e_datalen, hashidstr, &hashidstrlen, 0x02, 0x00, false, false, 0); - emrtd_lds_get_data_by_tag(hashlist + offset + e_fieldlen + 1, e_datalen, hash, &hashlen, 0x04, 0x00, false, false, 0); - PrintAndLogEx(SUCCESS, "Hash for EF_DG%i: %s", hashidstr[0], sprint_hex_inrow(hash, hashlen)); - break; - } - // + 1 for length of ID - offset += 1 + e_datalen + e_fieldlen; - } +// switch (hashlist[offset]) { +// case 0x30: +// emrtd_lds_get_data_by_tag(hashlist + offset + e_fieldlen + 1, e_datalen, hashidstr, &hashidstrlen, 0x02, 0x00, false, false, 0); +// emrtd_lds_get_data_by_tag(hashlist + offset + e_fieldlen + 1, e_datalen, hash, &hashlen, 0x04, 0x00, false, false, 0); +// PrintAndLogEx(SUCCESS, "Hash for EF_DG%i: %s", hashidstr[0], sprint_hex_inrow(hash, hashlen)); +// break; +// } +// // + 1 for length of ID +// offset += 1 + e_datalen + e_fieldlen; +// } - return PM3_SUCCESS; -} +// return PM3_SUCCESS; +// } int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_available) { uint8_t response[EMRTD_MAX_FILE_SIZE] = { 0x00 }; @@ -1696,7 +1695,7 @@ int infoHF_EMRTD_offline(const char *path) { PrintAndLogEx(INFO, "File tag not found, skipping: %02X", filelist[i]); continue; } - if (!dg->pace) { + if (!dg->pace && !dg->eac) { strcpy(filepath, path); strncat(filepath, PATHSEP, 2); strcat(filepath, dg->filename); From 9007629213890eb523eaa648b6c2a3a4cc7c6ebf Mon Sep 17 00:00:00 2001 From: ikarus Date: Sun, 27 Dec 2020 15:44:59 +0100 Subject: [PATCH 013/173] apdufind: filter reoccurring SWs & reset filed on tractive errors. --- client/src/cmdhf14a.c | 60 ++++++++++++++++++++++++++++--------------- client/src/ui.c | 2 +- 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index d4418ee62..fd03d60a4 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -2135,15 +2135,26 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { } static uint16_t get_sw(uint8_t *d, uint8_t n) { - if (n < 2) + if (n < 2) { return 0; - + } n -= 2; return d[n] * 0x0100 + d[n + 1]; } +static uint64_t inc_sw_error_occurence(uint16_t sw, uint64_t all_sw[256][256]) { + uint8_t sw1 = (uint8_t)(sw >> 8); + uint8_t sw2 = (uint8_t)(0xff & sw); + if (sw1 == 0x90 && sw2 == 0x00) { + return 0; // Don't count successes. + } + if (sw1 == 0x6d && sw2 == 0x00) { + return 0xffffffffffffffffULL; // Always max "Instruction not supported". + } + return ++all_sw[sw1][sw2]; +} + static int CmdHf14AFindapdu(const char *Cmd) { - // TODO: What response values should be considerd "valid" or "instersting" (worth dispalying)? // TODO: Option to select AID/File (and skip INS 0xA4). // TODO: Validate the decoding of the APDU (not specific to this command, check // https://cardwerk.com/smartcards/smartcard_standard_ISO7816-4_5_basic_organizations.aspx#chap5_3_2). @@ -2161,12 +2172,13 @@ static int CmdHf14AFindapdu(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("c", "cla", "", "Start value of CLASS (1 hex byte)"), - arg_str0("i", "ins", "", "Start value of INSTRUCTION (1 hex byte)"), - arg_str0(NULL, "p1", "", "Start value of P1 (1 hex byte)"), - arg_str0(NULL, "p2", "", "Start value of P2 (1 hex byte)"), - arg_u64_0("r", "reset", "", "Minimum secondes before resetting the tag (to prevent timeout issues). Default is 5 minutes"), - arg_lit0("v", "verbose", "Verbose output"), + arg_str0("c", "cla", "", "Start value of CLASS (1 hex byte)"), + arg_str0("i", "ins", "", "Start value of INSTRUCTION (1 hex byte)"), + arg_str0(NULL, "p1", "", "Start value of P1 (1 hex byte)"), + arg_str0(NULL, "p2", "", "Start value of P2 (1 hex byte)"), + arg_u64_0("r", "reset", "", "Minimum secondes before resetting the tag (to prevent timeout issues). Default is 5 minutes"), + arg_u64_0("e", "error-limit", "", "Maximum times an status word other than 0x9000 or 0x6D00 is shown. Default is 500."), + arg_lit0("v", "verbose", "Verbose output"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -2184,7 +2196,8 @@ static int CmdHf14AFindapdu(const char *Cmd) { uint8_t p2_arg[1] = {0}; CLIGetHexWithReturn(ctx, 4, p2_arg, &p2_len); uint64_t reset_time = arg_get_u64_def(ctx, 5, 5 * 60); // Reset every 5 minutes. - bool verbose = arg_get_lit(ctx, 6); + uint64_t error_limit = arg_get_u64_def(ctx, 6, 500); + bool verbose = arg_get_lit(ctx, 7); CLIParserFree(ctx); @@ -2211,6 +2224,8 @@ static int CmdHf14AFindapdu(const char *Cmd) { PrintAndLogEx(INFO, "Press " _GREEN_("") " to exit"); bool inc_p1 = true; + uint64_t all_sw[256][256] = {0}; + uint64_t sw_occurences = 0; uint64_t t_start = msclock(); uint64_t t_last_reset = msclock(); @@ -2233,33 +2248,38 @@ static int CmdHf14AFindapdu(const char *Cmd) { int command_n = sizeof(command); res = ExchangeAPDU14a(command, command_n, activate_field, keep_field_on, response, sizeof(response), &response_n); if (res) { + DropField(); + activate_field = true; continue; } + uint16_t sw = get_sw(response, response_n); + sw_occurences = inc_sw_error_occurence(sw, all_sw); // Was there and length error? If so, try with Le length (case 2 instad of case 1, // https://stackoverflow.com/a/30679558). Le = 0x00 will get interpreted as extended length APDU // with Le being 0x0100. - uint16_t sw = get_sw(response, response_n); bool command_with_le = false; if (sw == 0x6700) { - PrintAndLogEx(INFO, "Got response for APDU \"%02X%02X%02X%02X\": %04X (%s)", cla, ins, p1, p2, - sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - PrintAndLogEx(INFO, "Resending current command with Le = 0x0100 (extended length APDU)"); + if (sw_occurences < error_limit) { + PrintAndLogEx(INFO, "Got response for APDU \"%02X%02X%02X%02X\": %04X (%s)", cla, ins, p1, p2, + sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLogEx(INFO, "Resending current command with Le = 0x0100 (extended length APDU)"); + } uint8_t command2[7] = {cla, ins, p1, p2, 0x00}; int command2_n = sizeof(command2); res = ExchangeAPDU14a(command2, command2_n, activate_field, keep_field_on, response, sizeof(response), &response_n); if (res) { + DropField(); + activate_field = true; continue; } + sw = get_sw(response, response_n); + sw_occurences = inc_sw_error_occurence(sw, all_sw); command_with_le = true; } - // Check response. - sw = get_sw(response, response_n); - if (sw != 0x6a86 && - sw != 0x6986 && - sw != 0x6d00 - ) { + // Show response. + if (sw_occurences < error_limit) { if (command_with_le) { PrintAndLogEx(INFO, "Got response for APDU \"%02X%02X%02X%02X00\": %04X (%s)", cla, ins, p1, p2, sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); diff --git a/client/src/ui.c b/client/src/ui.c index 391279e52..b7e63e7dd 100644 --- a/client/src/ui.c +++ b/client/src/ui.c @@ -689,7 +689,7 @@ void print_progress(size_t count, uint64_t max, barMode_t style) { char *cbar = calloc(collen, sizeof(uint8_t)); // Add colors - if ( session.supports_colors ) { + if (session.supports_colors) { int p60 = unit * (width * 60 / 100); int p20 = unit * (width * 20 / 100); snprintf(cbar, collen, _GREEN_("%.*s"), p60, bar); From 28df590fc845f24bbc9c32542a5ca9fcd31eaf4f Mon Sep 17 00:00:00 2001 From: ikarus Date: Sun, 27 Dec 2020 20:20:19 +0100 Subject: [PATCH 014/173] apdufind: added option to skip instrcutions. (This helps if a tag might be locked permanently with a certain instruction. You can just skip it.) --- client/src/cmdhf14a.c | 26 +++++++++++++++++++------- doc/commands.md | 4 ++-- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index fd03d60a4..f66b29e1c 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -2159,7 +2159,6 @@ static int CmdHf14AFindapdu(const char *Cmd) { // TODO: Validate the decoding of the APDU (not specific to this command, check // https://cardwerk.com/smartcards/smartcard_standard_ISO7816-4_5_basic_organizations.aspx#chap5_3_2). // TODO: Check all cases (APDUs) with no data bytes (no/short/extended length). - // TODO: Option to blacklist instructions (or whole APDUs). CLIParserContext *ctx; CLIParserInit(&ctx, "hf 14a apdufind", "Enumerate APDU's of ISO7816 protocol to find valid CLS/INS/P1P2 commands.\n" @@ -2168,6 +2167,7 @@ static int CmdHf14AFindapdu(const char *Cmd) { "Tag must be on antenna before running.", "hf 14a apdufind\n" "hf 14a apdufind --cla 80\n" + "hf 14a apdufind --cla 80 --error-limit 20 --skip-ins a4 --skip-ins b0\n" ); void *argtable[] = { @@ -2177,7 +2177,8 @@ static int CmdHf14AFindapdu(const char *Cmd) { arg_str0(NULL, "p1", "", "Start value of P1 (1 hex byte)"), arg_str0(NULL, "p2", "", "Start value of P2 (1 hex byte)"), arg_u64_0("r", "reset", "", "Minimum secondes before resetting the tag (to prevent timeout issues). Default is 5 minutes"), - arg_u64_0("e", "error-limit", "", "Maximum times an status word other than 0x9000 or 0x6D00 is shown. Default is 500."), + arg_u64_0("e", "error-limit", "", "Maximum times an status word other than 0x9000 or 0x6D00 is shown. Default is 256."), + arg_strx0("s", "skip-ins", "", "Do not test an instructions (can be specifed multiple times)"), arg_lit0("v", "verbose", "Verbose output"), arg_param_end }; @@ -2195,9 +2196,12 @@ static int CmdHf14AFindapdu(const char *Cmd) { int p2_len = 0; uint8_t p2_arg[1] = {0}; CLIGetHexWithReturn(ctx, 4, p2_arg, &p2_len); - uint64_t reset_time = arg_get_u64_def(ctx, 5, 5 * 60); // Reset every 5 minutes. - uint64_t error_limit = arg_get_u64_def(ctx, 6, 500); - bool verbose = arg_get_lit(ctx, 7); + uint64_t reset_time = arg_get_u64_def(ctx, 5, 5 * 60); + uint64_t error_limit = arg_get_u64_def(ctx, 6, 256); + int ignore_ins_len = 0; + uint8_t ignore_ins_arg[250] = {0}; + CLIGetHexWithReturn(ctx, 7, ignore_ins_arg, &ignore_ins_len); + bool verbose = arg_get_lit(ctx, 8); CLIParserFree(ctx); @@ -2239,6 +2243,13 @@ static int CmdHf14AFindapdu(const char *Cmd) { goto out; } + // Skip/Ignore this instrctuion? + for (int i = 0; i < ignore_ins_len; i++) { + if (ins == ignore_ins_arg[i]) { + goto next_ins; + } + } + if (verbose) { PrintAndLogEx(INFO, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla, ins, p1, p2); } @@ -2250,7 +2261,7 @@ static int CmdHf14AFindapdu(const char *Cmd) { if (res) { DropField(); activate_field = true; - continue; + goto next_ins; } uint16_t sw = get_sw(response, response_n); sw_occurences = inc_sw_error_occurence(sw, all_sw); @@ -2271,7 +2282,7 @@ static int CmdHf14AFindapdu(const char *Cmd) { if (res) { DropField(); activate_field = true; - continue; + goto next_ins; } sw = get_sw(response, response_n); sw_occurences = inc_sw_error_occurence(sw, all_sw); @@ -2293,6 +2304,7 @@ static int CmdHf14AFindapdu(const char *Cmd) { sprint_ascii(response, response_n - 2)); } } +next_ins: activate_field = false; // Do not reativate the filed until the next reset. } while (++ins != ins_arg[0]); // Increment P1/P2 in an alternating fashion. diff --git a/doc/commands.md b/doc/commands.md index e1e445296..991f4a590 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -198,8 +198,8 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`hf epa help `|Y |`This help` -|`hf epa cnonces `|N |` Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses` -|`hf epa preplay `|N |` Perform PACE protocol by replaying given APDUs` +|`hf epa cnonces `|N |`Acquire encrypted PACE nonces of specific size` +|`hf epa preplay `|N |`Perform PACE protocol by replaying given APDUs` ### hf emrtd From 4494c47e5fe53c6f249e6d0e00a8d3a48c93f354 Mon Sep 17 00:00:00 2001 From: ikarus Date: Sun, 27 Dec 2020 20:31:30 +0100 Subject: [PATCH 015/173] reverted the faulty edits by make style to doc/commands.md. --- doc/commands.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/commands.md b/doc/commands.md index 991f4a590..e1e445296 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -198,8 +198,8 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`hf epa help `|Y |`This help` -|`hf epa cnonces `|N |`Acquire encrypted PACE nonces of specific size` -|`hf epa preplay `|N |`Perform PACE protocol by replaying given APDUs` +|`hf epa cnonces `|N |` Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses` +|`hf epa preplay `|N |` Perform PACE protocol by replaying given APDUs` ### hf emrtd From 8233b2c914b775e5976b841cd2699d18383b5d55 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 28 Dec 2020 13:36:37 +0100 Subject: [PATCH 016/173] script now supports Gen1a, Gen1b, Gen2 type of MIFARE Ultralight family uid changeable cards --- client/luascripts/hf_mfu_setuid.lua | 44 ++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/client/luascripts/hf_mfu_setuid.lua b/client/luascripts/hf_mfu_setuid.lua index 86bef09c3..f64d5cfab 100644 --- a/client/luascripts/hf_mfu_setuid.lua +++ b/client/luascripts/hf_mfu_setuid.lua @@ -4,26 +4,32 @@ local ansicolors = require('ansicolors') copyright = '' author = "Iceman" -version = 'v1.0.2' +version = 'v1.0.3' desc = [[ This script tries to set UID on a mifare Ultralight magic card which either - answers to chinese backdoor commands - brickable magic tag (must write in one session) + + It defaults to GEN1A type of uid changeable card. ]] example = [[ - -- backdoor magic tag + -- backdoor magic tag (gen1a) script run hf_mfu_setuid -u 11223344556677 - -- brickable magic tag + -- backdoor magic tag (gen1b) script run hf_mfu_setuid -b -u 11223344556677 + + -- brickable magic tag (gen2) + script run hf_mfu_setuid -2 -u 11223344556677 ]] usage = [[ -script run hf_mfu_setuid [-h] [-b] [-u ] +script run hf_mfu_setuid [-h] [-b] [-2] [-u ] ]] arguments = [[ -h : this help -u : UID (14 hexsymbols) - -b : write to brickable magic tag + -b : write to magic tag GEN1B + -2 : write to brickable magic tag GEN2 ]] local DEBUG = true @@ -65,23 +71,33 @@ local function help() end -- --- Set UID on magic command enabled -function magicUID(b0, b1, b2) +function magicUID(b0, b1, b2, isgen1a) - print('Using backdoor Magic tag function') + if isgen1a then + print('Using backdoor Magic tag (gen1a) function') + else + print('Using backdoor Magic tag (gen1b) function') + end -- write block 0 core.console('hf 14a raw -k -a -b 7 40') - core.console('hf 14a raw -k -a 43') + if isgen1a then + core.console('hf 14a raw -k -a 43') + end core.console('hf 14a raw -c -a A200'..b0) -- write block 1 core.console('hf 14a raw -k -a -b 7 40') - core.console('hf 14a raw -k -a 43') + if isgen1a then + core.console('hf 14a raw -k -a 43') + end core.console('hf 14a raw -c -a A201'..b1) -- write block 2 core.console('hf 14a raw -k -a -b 7 40') - core.console('hf 14a raw -k -a 43') + if isgen1a then + core.console('hf 14a raw -k -a 43') + end core.console('hf 14a raw -c -a A202'..b2) end -- @@ -113,10 +129,11 @@ function main(args) local tagtype = 1 -- Read the parameters - for o, a in getopt.getopt(args, 'hu:b') do + for o, a in getopt.getopt(args, 'hu:b2') do if o == 'h' then return help() end if o == 'u' then uid = a end if o == 'b' then tagtype = 2 end + if o == '2' then tagtype = 3 end end -- uid string checks @@ -137,10 +154,11 @@ function main(args) core.clearCommandBuffer() - if tagtype == 2 then + if tagtype == 3 then brickableUID(block0, block1, block2) else - magicUID(block0, block1, block2) + local is_gen1a = (tagtype == 1) + magicUID(block0, block1, block2, is_gen1a) end --halt From 201e2506b2e8c3d9a5c23893305effb6155f815f Mon Sep 17 00:00:00 2001 From: ikarus Date: Mon, 28 Dec 2020 15:38:35 +0100 Subject: [PATCH 017/173] apdufind: fixed bug which prevented a retry, if there was an error. --- client/src/cmdhf14a.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index f66b29e1c..150b49fee 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -2228,6 +2228,7 @@ static int CmdHf14AFindapdu(const char *Cmd) { PrintAndLogEx(INFO, "Press " _GREEN_("") " to exit"); bool inc_p1 = true; + bool skip_ins = false; uint64_t all_sw[256][256] = {0}; uint64_t sw_occurences = 0; uint64_t t_start = msclock(); @@ -2237,6 +2238,7 @@ static int CmdHf14AFindapdu(const char *Cmd) { do { do { do { +retry_ins: // Exit (was the Enter key pressed)? if (kbd_enter_pressed()) { PrintAndLogEx(INFO, "User interrupted detected. Aborting"); @@ -2246,9 +2248,14 @@ static int CmdHf14AFindapdu(const char *Cmd) { // Skip/Ignore this instrctuion? for (int i = 0; i < ignore_ins_len; i++) { if (ins == ignore_ins_arg[i]) { - goto next_ins; + skip_ins = true; + break; } } + if (skip_ins) { + skip_ins = false; + continue; + } if (verbose) { PrintAndLogEx(INFO, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla, ins, p1, p2); @@ -2261,7 +2268,7 @@ static int CmdHf14AFindapdu(const char *Cmd) { if (res) { DropField(); activate_field = true; - goto next_ins; + goto retry_ins; } uint16_t sw = get_sw(response, response_n); sw_occurences = inc_sw_error_occurence(sw, all_sw); @@ -2282,7 +2289,7 @@ static int CmdHf14AFindapdu(const char *Cmd) { if (res) { DropField(); activate_field = true; - goto next_ins; + goto retry_ins; } sw = get_sw(response, response_n); sw_occurences = inc_sw_error_occurence(sw, all_sw); @@ -2291,11 +2298,15 @@ static int CmdHf14AFindapdu(const char *Cmd) { // Show response. if (sw_occurences < error_limit) { + logLevel_t log_level = INFO; + if (sw == 0x9000) { + log_level = SUCCESS; + } if (command_with_le) { - PrintAndLogEx(INFO, "Got response for APDU \"%02X%02X%02X%02X00\": %04X (%s)", cla, ins, p1, p2, + PrintAndLogEx(log_level, "Got response for APDU \"%02X%02X%02X%02X00\": %04X (%s)", cla, ins, p1, p2, sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); } else { - PrintAndLogEx(INFO, "Got response for APDU \"%02X%02X%02X%02X\": %04X (%s)", cla, ins, p1, p2, + PrintAndLogEx(log_level, "Got response for APDU \"%02X%02X%02X%02X\": %04X (%s)", cla, ins, p1, p2, sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); } // Show response data. @@ -2304,7 +2315,6 @@ static int CmdHf14AFindapdu(const char *Cmd) { sprint_ascii(response, response_n - 2)); } } -next_ins: activate_field = false; // Do not reativate the filed until the next reset. } while (++ins != ins_arg[0]); // Increment P1/P2 in an alternating fashion. From 59e6658753d40c40ea7d4b0a6d0f23e7f9ee9762 Mon Sep 17 00:00:00 2001 From: ikarus Date: Mon, 28 Dec 2020 19:14:29 +0100 Subject: [PATCH 018/173] apdufind: added option to find Le=0 commands (case 2S) --- client/src/cmdhf14a.c | 81 +++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 53 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 150b49fee..29d3afa65 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -2156,18 +2156,17 @@ static uint64_t inc_sw_error_occurence(uint16_t sw, uint64_t all_sw[256][256]) { static int CmdHf14AFindapdu(const char *Cmd) { // TODO: Option to select AID/File (and skip INS 0xA4). - // TODO: Validate the decoding of the APDU (not specific to this command, check - // https://cardwerk.com/smartcards/smartcard_standard_ISO7816-4_5_basic_organizations.aspx#chap5_3_2). - // TODO: Check all cases (APDUs) with no data bytes (no/short/extended length). + // TODO: Check all instructions with extended APDUs if the card support it. + // TODO: Option to reset tag before every command. CLIParserContext *ctx; CLIParserInit(&ctx, "hf 14a apdufind", - "Enumerate APDU's of ISO7816 protocol to find valid CLS/INS/P1P2 commands.\n" + "Enumerate APDU's of ISO7816 protocol to find valid CLS/INS/P1/P2 commands.\n" "It loops all 256 possible values for each byte.\n" - "The loop oder is INS -> P1/P2 (alternating) -> CLA\n" + "The loop oder is INS -> P1/P2 (alternating) -> CLA.\n" "Tag must be on antenna before running.", "hf 14a apdufind\n" "hf 14a apdufind --cla 80\n" - "hf 14a apdufind --cla 80 --error-limit 20 --skip-ins a4 --skip-ins b0\n" + "hf 14a apdufind --cla 80 --error-limit 20 --skip-ins a4 --skip-ins b0 --with-le\n" ); void *argtable[] = { @@ -2177,8 +2176,9 @@ static int CmdHf14AFindapdu(const char *Cmd) { arg_str0(NULL, "p1", "", "Start value of P1 (1 hex byte)"), arg_str0(NULL, "p2", "", "Start value of P2 (1 hex byte)"), arg_u64_0("r", "reset", "", "Minimum secondes before resetting the tag (to prevent timeout issues). Default is 5 minutes"), - arg_u64_0("e", "error-limit", "", "Maximum times an status word other than 0x9000 or 0x6D00 is shown. Default is 256."), + arg_u64_0("e", "error-limit", "", "Maximum times an status word other than 0x9000 or 0x6D00 is shown. Default is 512."), arg_strx0("s", "skip-ins", "", "Do not test an instructions (can be specifed multiple times)"), + arg_lit0("l", "with-le", "Serach for APDUs with Le=0 (case 2S) as well"), arg_lit0("v", "verbose", "Verbose output"), arg_param_end }; @@ -2197,11 +2197,12 @@ static int CmdHf14AFindapdu(const char *Cmd) { uint8_t p2_arg[1] = {0}; CLIGetHexWithReturn(ctx, 4, p2_arg, &p2_len); uint64_t reset_time = arg_get_u64_def(ctx, 5, 5 * 60); - uint64_t error_limit = arg_get_u64_def(ctx, 6, 256); + uint64_t error_limit = arg_get_u64_def(ctx, 6, 512); int ignore_ins_len = 0; uint8_t ignore_ins_arg[250] = {0}; CLIGetHexWithReturn(ctx, 7, ignore_ins_arg, &ignore_ins_len); - bool verbose = arg_get_lit(ctx, 8); + bool with_le = arg_get_lit(ctx, 8); + bool verbose = arg_get_lit(ctx, 9); CLIParserFree(ctx); @@ -2261,58 +2262,32 @@ retry_ins: PrintAndLogEx(INFO, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla, ins, p1, p2); } - // Send APDU. - uint8_t command[4] = {cla, ins, p1, p2}; - int command_n = sizeof(command); - res = ExchangeAPDU14a(command, command_n, activate_field, keep_field_on, response, sizeof(response), &response_n); - if (res) { - DropField(); - activate_field = true; - goto retry_ins; - } - uint16_t sw = get_sw(response, response_n); - sw_occurences = inc_sw_error_occurence(sw, all_sw); - - // Was there and length error? If so, try with Le length (case 2 instad of case 1, - // https://stackoverflow.com/a/30679558). Le = 0x00 will get interpreted as extended length APDU - // with Le being 0x0100. - bool command_with_le = false; - if (sw == 0x6700) { - if (sw_occurences < error_limit) { - PrintAndLogEx(INFO, "Got response for APDU \"%02X%02X%02X%02X\": %04X (%s)", cla, ins, p1, p2, - sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - PrintAndLogEx(INFO, "Resending current command with Le = 0x0100 (extended length APDU)"); - } - uint8_t command2[7] = {cla, ins, p1, p2, 0x00}; - int command2_n = sizeof(command2); - res = ExchangeAPDU14a(command2, command2_n, activate_field, keep_field_on, response, sizeof(response), &response_n); + // Send APDU without Le (case 1) and with Le = 0 (case 2S), if "with-le" was set. + uint8_t command[5] = {cla, ins, p1, p2, 0x00}; + int command_n = 4; + for (int i = 0; i < 1 + with_le; i++) { + // Send APDU. + res = ExchangeAPDU14a(command, command_n + i, activate_field, keep_field_on, response, sizeof(response), &response_n); if (res) { DropField(); activate_field = true; goto retry_ins; } - sw = get_sw(response, response_n); + uint16_t sw = get_sw(response, response_n); sw_occurences = inc_sw_error_occurence(sw, all_sw); - command_with_le = true; - } - // Show response. - if (sw_occurences < error_limit) { - logLevel_t log_level = INFO; - if (sw == 0x9000) { - log_level = SUCCESS; - } - if (command_with_le) { - PrintAndLogEx(log_level, "Got response for APDU \"%02X%02X%02X%02X00\": %04X (%s)", cla, ins, p1, p2, + // Show response. + if (sw_occurences < error_limit) { + logLevel_t log_level = INFO; + if (sw == 0x9000) { + log_level = SUCCESS; + } + PrintAndLogEx(log_level, "Got response for APDU \"%s\": %04X (%s)", sprint_hex_inrow(command, command_n + i), sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - } else { - PrintAndLogEx(log_level, "Got response for APDU \"%02X%02X%02X%02X\": %04X (%s)", cla, ins, p1, p2, - sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - } - // Show response data. - if (response_n > 2) { - PrintAndLogEx(SUCCESS, "Response data is: %s | %s", sprint_hex_inrow(response, response_n - 2), - sprint_ascii(response, response_n - 2)); + if (response_n > 2) { + PrintAndLogEx(SUCCESS, "Response data is: %s | %s", sprint_hex_inrow(response, response_n - 2), + sprint_ascii(response, response_n - 2)); + } } } activate_field = false; // Do not reativate the filed until the next reset. From 11567dc2e35cb556a32f40496124952b7a3fa824 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Mon, 28 Dec 2020 22:48:41 +0100 Subject: [PATCH 019/173] Added option for running with uncompressed .data section. Thanks @doegox --- armsrc/Makefile | 4 ++++ armsrc/appmain.c | 11 ++++++++++- armsrc/start.c | 20 +++++++++++++++++--- common_arm/Makefile.hal | 3 +++ 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/armsrc/Makefile b/armsrc/Makefile index 46ba4f027..074380058 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -217,8 +217,12 @@ $(OBJDIR)/fullimage.data.o: $(OBJDIR)/fullimage.data.bin.z $(Q)$(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=compressed_data $^ $@ $(OBJDIR)/fullimage.elf: $(OBJDIR)/fullimage.nodata.o $(OBJDIR)/fullimage.data.o +ifneq ($(SKIP_COMPRESSION),1) $(info [=] LD $@) $(Q)$(CC) $(CROSS_LDFLAGS) -Wl,-T,ldscript,-e,_osimage_entry,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ +else + $(Q)$(CP) $(OBJDIR)/fullimage.stage1.elf $@ +endif tarbin: $(OBJS) $(info TAR $@) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index fe8566363..b4c3d6a30 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -257,6 +257,9 @@ void ReadMem(int addr) { /* osimage version information is linked in, cf commonutil.h */ /* bootrom version information is pointed to from _bootphase1_version_pointer */ extern char *_bootphase1_version_pointer, _flash_start, _flash_end, __data_src_start__; +#ifdef WITH_NO_COMPRESSION +extern char *_bootrom_end, _bootrom_start, __os_size__; +#endif static void SendVersion(void) { char temp[PM3_CMD_DATA_SIZE - 12]; /* Limited data payload in USB packets */ char VersionString[PM3_CMD_DATA_SIZE - 12] = { '\0' }; @@ -295,9 +298,11 @@ static void SendVersion(void) { strncat(VersionString, "\n ", sizeof(VersionString) - strlen(VersionString) - 1); } } +#ifndef WITH_NO_COMPRESSION // Send Chip ID and used flash memory uint32_t text_and_rodata_section_size = (uint32_t)&__data_src_start__ - (uint32_t)&_flash_start; uint32_t compressed_data_section_size = common_area.arg1; +#endif struct p { uint32_t id; @@ -308,7 +313,11 @@ static void SendVersion(void) { struct p payload; payload.id = *(AT91C_DBGU_CIDR); - payload.section_size = text_and_rodata_section_size + compressed_data_section_size; +#ifdef WITH_NO_COMPRESSION + payload.section_size = (uint32_t)&_bootrom_end - (uint32_t)&_bootrom_start + (uint32_t)&__os_size__; +#else + payload.section_size = text_and_rodata_section_size + compressed_data_section_size; +#endif payload.versionstr_len = strlen(VersionString) + 1; memcpy(payload.versionstr, VersionString, payload.versionstr_len); diff --git a/armsrc/start.c b/armsrc/start.c index 70eee5063..542b9f3f4 100644 --- a/armsrc/start.c +++ b/armsrc/start.c @@ -14,14 +14,16 @@ #include "proxmark3_arm.h" #include "appmain.h" +#ifndef WITH_NO_COMPRESSION #include "lz4.h" +#endif #include "BigBuf.h" #include "string.h" extern struct common_area common_area; extern char __data_src_start__, __data_start__, __data_end__, __bss_start__, __bss_end__; - +#ifndef WITH_NO_COMPRESSION static void uncompress_data_section(void) { int avail_in; memcpy(&avail_in, &__data_src_start__, sizeof(int)); @@ -35,6 +37,7 @@ static void uncompress_data_section(void) { // save the size of the compressed data section common_area.arg1 = avail_in; } +#endif void __attribute__((section(".startos"))) Vector(void); void Vector(void) { @@ -47,12 +50,23 @@ void Vector(void) { common_area.version = 1; } common_area.flags.osimage_present = 1; - - uncompress_data_section(); + +#ifdef WITH_NO_COMPRESSION + /* Set up data segment: Copy from flash to ram */ + char *src = &__data_src_start__; + char *dst = &__data_start__; + char *end = &__data_end__; + while(dst < end) *dst++ = *src++; + dst = &__bss_start__; + end = &__bss_end__; +#else + uncompress_data_section(); /* Set up (that is: clear) BSS. */ char *dst = &__bss_start__; char *end = &__bss_end__; +#endif + while (dst < end) *dst++ = 0; AppMain(); diff --git a/common_arm/Makefile.hal b/common_arm/Makefile.hal index 24d31261e..bfbe56d34 100644 --- a/common_arm/Makefile.hal +++ b/common_arm/Makefile.hal @@ -137,6 +137,9 @@ endif ifneq ($(SKIP_HFPLOT),1) PLATFORM_DEFS += -DWITH_HFPLOT endif +ifeq ($(SKIP_COMPRESSION),1) + PLATFORM_DEFS += -DWITH_NO_COMPRESSION +endif # Standalone mode ifneq ($(strip $(filter $(PLATFORM_DEFS),$(STANDALONE_REQ_DEFS))),$(strip $(STANDALONE_REQ_DEFS))) From bdb384f7b7417a08368ab6cc2a3cfed918641481 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Mon, 28 Dec 2020 22:57:58 +0100 Subject: [PATCH 020/173] Fix for the Makefile.platform file --- armsrc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/Makefile b/armsrc/Makefile index 074380058..019d10820 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -217,7 +217,7 @@ $(OBJDIR)/fullimage.data.o: $(OBJDIR)/fullimage.data.bin.z $(Q)$(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=compressed_data $^ $@ $(OBJDIR)/fullimage.elf: $(OBJDIR)/fullimage.nodata.o $(OBJDIR)/fullimage.data.o -ifneq ($(SKIP_COMPRESSION),1) +ifeq (,$(findstring WITH_NO_COMPRESSION,$(APP_CFLAGS))) $(info [=] LD $@) $(Q)$(CC) $(CROSS_LDFLAGS) -Wl,-T,ldscript,-e,_osimage_entry,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ else From 7e2b10d413fb38965359e1bd1a91352bbf251bdf Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 29 Dec 2020 01:55:18 +0300 Subject: [PATCH 021/173] emrtd info (offline): Add basic hash verification support --- client/src/cmdhfemrtd.c | 235 ++++++++++++++++++++++------------------ client/src/cmdhfemrtd.h | 1 + 2 files changed, 131 insertions(+), 105 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 88a79707a..a088bfc7f 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -20,6 +20,7 @@ #include "protocols.h" // definitions of ISO14A/7816 protocol #include "emv/apduinfo.h" // GetAPDUCodeDescription #include "sha1.h" // KSeed calculation etc +#include "crypto/libpcrypto.h" // Hash calculation (sha256), TODO: AES too #include "mifare/desfire_crypto.h" // des_encrypt/des_decrypt #include "des.h" // mbedtls_des_key_set_parity #include "cmdhf14b.h" // exchange_14b_apdu @@ -83,28 +84,28 @@ typedef enum { // list must match dg_table } emrtd_dg_enum; static emrtd_dg_t dg_table[] = { -// tag fileid filename desc pace eac req fast parser dumper - {0x60, "011E", "EF_COM", "Header and Data Group Presence Information", false, false, true, true, emrtd_print_ef_com_info, NULL}, - {0x61, "0101", "EF_DG1", "Details recorded in MRZ", false, false, true, true, emrtd_print_ef_dg1_info, NULL}, - {0x75, "0102", "EF_DG2", "Encoded Face", false, false, true, false, NULL, emrtd_dump_ef_dg2}, - {0x63, "0103", "EF_DG3", "Encoded Finger(s)", false, true, false, false, NULL, NULL}, - {0x76, "0104", "EF_DG4", "Encoded Eye(s)", false, true, false, false, NULL, NULL}, - {0x65, "0105", "EF_DG5", "Displayed Portrait", false, false, false, false, NULL, emrtd_dump_ef_dg5}, - {0x66, "0106", "EF_DG6", "Reserved for Future Use", false, false, false, false, NULL, NULL}, - {0x67, "0107", "EF_DG7", "Displayed Signature or Usual Mark", false, false, false, false, NULL, emrtd_dump_ef_dg7}, - {0x68, "0108", "EF_DG8", "Data Feature(s)", false, false, false, true, NULL, NULL}, - {0x69, "0109", "EF_DG9", "Structure Feature(s)", false, false, false, true, NULL, NULL}, - {0x6a, "010A", "EF_DG10", "Substance Feature(s)", false, false, false, true, NULL, NULL}, - {0x6b, "010B", "EF_DG11", "Additional Personal Detail(s)", false, false, false, true, emrtd_print_ef_dg11_info, NULL}, - {0x6c, "010C", "EF_DG12", "Additional Document Detail(s)", false, false, false, true, emrtd_print_ef_dg12_info, NULL}, - {0x6d, "010D", "EF_DG13", "Optional Detail(s)", false, false, false, true, NULL, NULL}, - {0x6e, "010E", "EF_DG14", "Security Options", false, false, false, true, NULL, NULL}, - {0x6f, "010F", "EF_DG15", "Active Authentication Public Key Info", false, false, false, true, NULL, NULL}, - {0x70, "0110", "EF_DG16", "Person(s) to Notify", false, false, false, true, NULL, NULL}, - {0x77, "011D", "EF_SOD", "Document Security Object", false, false, false, false, NULL, emrtd_dump_ef_sod}, - {0xff, "011C", "EF_CardAccess", "PACE SecurityInfos", true, false, true, true, NULL, NULL}, - {0xff, "011D", "EF_CardSecurity", "PACE SecurityInfos for Chip Authentication Mapping", true, false, false, true, NULL, NULL}, - {0x00, NULL, NULL, NULL, false, false, false, false, NULL, NULL} +// tag dg# fileid filename desc pace eac req fast parser dumper + {0x60, 0, "011E", "EF_COM", "Header and Data Group Presence Information", false, false, true, true, emrtd_print_ef_com_info, NULL}, + {0x61, 1, "0101", "EF_DG1", "Details recorded in MRZ", false, false, true, true, emrtd_print_ef_dg1_info, NULL}, + {0x75, 2, "0102", "EF_DG2", "Encoded Face", false, false, true, false, NULL, emrtd_dump_ef_dg2}, + {0x63, 3, "0103", "EF_DG3", "Encoded Finger(s)", false, true, false, false, NULL, NULL}, + {0x76, 4, "0104", "EF_DG4", "Encoded Eye(s)", false, true, false, false, NULL, NULL}, + {0x65, 5, "0105", "EF_DG5", "Displayed Portrait", false, false, false, false, NULL, emrtd_dump_ef_dg5}, + {0x66, 6, "0106", "EF_DG6", "Reserved for Future Use", false, false, false, false, NULL, NULL}, + {0x67, 7, "0107", "EF_DG7", "Displayed Signature or Usual Mark", false, false, false, false, NULL, emrtd_dump_ef_dg7}, + {0x68, 8, "0108", "EF_DG8", "Data Feature(s)", false, false, false, true, NULL, NULL}, + {0x69, 9, "0109", "EF_DG9", "Structure Feature(s)", false, false, false, true, NULL, NULL}, + {0x6a, 10, "010A", "EF_DG10", "Substance Feature(s)", false, false, false, true, NULL, NULL}, + {0x6b, 11, "010B", "EF_DG11", "Additional Personal Detail(s)", false, false, false, true, emrtd_print_ef_dg11_info, NULL}, + {0x6c, 12, "010C", "EF_DG12", "Additional Document Detail(s)", false, false, false, true, emrtd_print_ef_dg12_info, NULL}, + {0x6d, 13, "010D", "EF_DG13", "Optional Detail(s)", false, false, false, true, NULL, NULL}, + {0x6e, 14, "010E", "EF_DG14", "Security Options", false, false, false, true, NULL, NULL}, + {0x6f, 15, "010F", "EF_DG15", "Active Authentication Public Key Info", false, false, false, true, NULL, NULL}, + {0x70, 16, "0110", "EF_DG16", "Person(s) to Notify", false, false, false, true, NULL, NULL}, + {0x77, 0, "011D", "EF_SOD", "Document Security Object", false, false, false, false, NULL, emrtd_dump_ef_sod}, + {0xff, 0, "011C", "EF_CardAccess", "PACE SecurityInfos", true, false, true, true, NULL, NULL}, + {0xff, 0, "011D", "EF_CardSecurity", "PACE SecurityInfos for Chip Authentication Mapping", true, false, false, true, NULL, NULL}, + {0x00, 0, NULL, NULL, NULL, false, false, false, false, NULL, NULL} }; static emrtd_dg_t *emrtd_tag_to_dg(uint8_t tag) { @@ -1483,106 +1484,105 @@ static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen) { return PM3_SUCCESS; } -// static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_t *dataout, size_t *dataoutlen) { -// // very very very very cursed code. -// uint8_t top[EMRTD_MAX_FILE_SIZE] = { 0x00 }; -// uint8_t signeddata[EMRTD_MAX_FILE_SIZE] = { 0x00 }; -// uint8_t emrtdsigcontainer[EMRTD_MAX_FILE_SIZE] = { 0x00 }; -// uint8_t emrtdsig[EMRTD_MAX_FILE_SIZE] = { 0x00 }; -// uint8_t emrtdsigtext[EMRTD_MAX_FILE_SIZE] = { 0x00 }; -// size_t toplen, signeddatalen, emrtdsigcontainerlen, emrtdsiglen, emrtdsigtextlen = 0; +static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_t *dataout, size_t *dataoutlen) { + // very very very very cursed code. + uint8_t top[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t signeddata[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t emrtdsigcontainer[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t emrtdsig[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t emrtdsigtext[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + size_t toplen, signeddatalen, emrtdsigcontainerlen, emrtdsiglen, emrtdsigtextlen = 0; -// if (!emrtd_lds_get_data_by_tag(data, datalen, top, &toplen, 0x30, 0x00, false, true, 0)) { -// PrintAndLogEx(ERR, "Failed to read top from EF_SOD."); -// return false; -// } + if (!emrtd_lds_get_data_by_tag(data, datalen, top, &toplen, 0x30, 0x00, false, true, 0)) { + PrintAndLogEx(ERR, "Failed to read top from EF_SOD."); + return false; + } -// PrintAndLogEx(DEBUG, "top: %s.", sprint_hex_inrow(top, toplen)); + PrintAndLogEx(DEBUG, "top: %s.", sprint_hex_inrow(top, toplen)); -// if (!emrtd_lds_get_data_by_tag(top, toplen, signeddata, &signeddatalen, 0xA0, 0x00, false, false, 0)) { -// PrintAndLogEx(ERR, "Failed to read signedData from EF_SOD."); -// return false; -// } + if (!emrtd_lds_get_data_by_tag(top, toplen, signeddata, &signeddatalen, 0xA0, 0x00, false, false, 0)) { + PrintAndLogEx(ERR, "Failed to read signedData from EF_SOD."); + return false; + } -// PrintAndLogEx(DEBUG, "signeddata: %s.", sprint_hex_inrow(signeddata, signeddatalen)); + PrintAndLogEx(DEBUG, "signeddata: %s.", sprint_hex_inrow(signeddata, signeddatalen)); -// // Do true on reading into the tag as it's a "sequence" -// if (!emrtd_lds_get_data_by_tag(signeddata, signeddatalen, emrtdsigcontainer, &emrtdsigcontainerlen, 0x30, 0x00, false, true, 0)) { -// PrintAndLogEx(ERR, "Failed to read eMRTDSignature container from EF_SOD."); -// return false; -// } + // Do true on reading into the tag as it's a "sequence" + if (!emrtd_lds_get_data_by_tag(signeddata, signeddatalen, emrtdsigcontainer, &emrtdsigcontainerlen, 0x30, 0x00, false, true, 0)) { + PrintAndLogEx(ERR, "Failed to read eMRTDSignature container from EF_SOD."); + return false; + } -// PrintAndLogEx(DEBUG, "emrtdsigcontainer: %s.", sprint_hex_inrow(emrtdsigcontainer, emrtdsigcontainerlen)); + PrintAndLogEx(DEBUG, "emrtdsigcontainer: %s.", sprint_hex_inrow(emrtdsigcontainer, emrtdsigcontainerlen)); -// if (!emrtd_lds_get_data_by_tag(emrtdsigcontainer, emrtdsigcontainerlen, emrtdsig, &emrtdsiglen, 0xA0, 0x00, false, false, 0)) { -// PrintAndLogEx(ERR, "Failed to read eMRTDSignature from EF_SOD."); -// return false; -// } + if (!emrtd_lds_get_data_by_tag(emrtdsigcontainer, emrtdsigcontainerlen, emrtdsig, &emrtdsiglen, 0xA0, 0x00, false, false, 0)) { + PrintAndLogEx(ERR, "Failed to read eMRTDSignature from EF_SOD."); + return false; + } -// PrintAndLogEx(DEBUG, "emrtdsig: %s.", sprint_hex_inrow(emrtdsig, emrtdsiglen)); + PrintAndLogEx(DEBUG, "emrtdsig: %s.", sprint_hex_inrow(emrtdsig, emrtdsiglen)); -// // TODO: Not doing memcpy here, it didn't work, fix it somehow -// if (!emrtd_lds_get_data_by_tag(emrtdsig, emrtdsiglen, emrtdsigtext, &emrtdsigtextlen, 0x04, 0x00, false, false, 0)) { -// PrintAndLogEx(ERR, "Failed to read eMRTDSignature (text) from EF_SOD."); -// return false; -// } -// memcpy(dataout, emrtdsigtext, emrtdsigtextlen); -// *dataoutlen = emrtdsigtextlen; -// return PM3_SUCCESS; -// } + // TODO: Not doing memcpy here, it didn't work, fix it somehow + if (!emrtd_lds_get_data_by_tag(emrtdsig, emrtdsiglen, emrtdsigtext, &emrtdsigtextlen, 0x04, 0x00, false, false, 0)) { + PrintAndLogEx(ERR, "Failed to read eMRTDSignature (text) from EF_SOD."); + return false; + } + memcpy(dataout, emrtdsigtext, emrtdsigtextlen); + *dataoutlen = emrtdsigtextlen; + return PM3_SUCCESS; +} -// static int emrtd_print_ef_sod_info(uint8_t *data, size_t datalen) { -// uint8_t emrtdsig[EMRTD_MAX_FILE_SIZE] = { 0x00 }; -// uint8_t hashlist[EMRTD_MAX_FILE_SIZE] = { 0x00 }; -// uint8_t hash[65] = { 0x00 }; -// size_t hashlen = 0; +static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *hashes) { + uint8_t emrtdsig[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t hashlist[EMRTD_MAX_FILE_SIZE] = { 0x00 }; + uint8_t hash[65] = { 0x00 }; + size_t hashlen = 0; -// uint8_t hashidstr[4] = { 0x00 }; -// size_t hashidstrlen = 0; + uint8_t hashidstr[4] = { 0x00 }; + size_t hashidstrlen = 0; -// // size_t emrtdsiglen, e_datalen, e_fieldlen = 0; -// size_t emrtdsiglen = 0; -// size_t hashlistlen = 0; -// size_t e_datalen = 0; -// size_t e_fieldlen = 0; -// size_t offset = 0; + // size_t emrtdsiglen, e_datalen, e_fieldlen = 0; + size_t emrtdsiglen = 0; + size_t hashlistlen = 0; + size_t e_datalen = 0; + size_t e_fieldlen = 0; + size_t offset = 0; -// PrintAndLogEx(NORMAL, ""); -// PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_SOD") " --------------------"); + if (emrtd_ef_sod_extract_signatures(data, datalen, emrtdsig, &emrtdsiglen) != PM3_SUCCESS) { + return false; + } -// if (emrtd_ef_sod_extract_signatures(data, datalen, emrtdsig, &emrtdsiglen) != PM3_SUCCESS) { -// return false; -// } + PrintAndLogEx(DEBUG, "hash data: %s", sprint_hex_inrow(emrtdsig, emrtdsiglen)); -// PrintAndLogEx(DEBUG, "hash data: %s", sprint_hex_inrow(emrtdsig, emrtdsiglen)); + if (!emrtd_lds_get_data_by_tag(emrtdsig, emrtdsiglen, hashlist, &hashlistlen, 0x30, 0x00, false, true, 1)) { + PrintAndLogEx(ERR, "Failed to read hash list from EF_SOD."); + return false; + } -// if (!emrtd_lds_get_data_by_tag(emrtdsig, emrtdsiglen, hashlist, &hashlistlen, 0x30, 0x00, false, true, 1)) { -// PrintAndLogEx(ERR, "Failed to read hash list from EF_SOD."); -// return false; -// } + PrintAndLogEx(DEBUG, "hash list: %s", sprint_hex_inrow(hashlist, hashlistlen)); -// PrintAndLogEx(DEBUG, "hash list: %s", sprint_hex_inrow(hashlist, hashlistlen)); + while (offset < hashlistlen) { + // Get the length of the element + e_datalen = emrtd_get_asn1_data_length(hashlist + offset, hashlistlen - offset, 1); -// while (offset < hashlistlen) { -// // Get the length of the element -// e_datalen = emrtd_get_asn1_data_length(hashlist + offset, hashlistlen - offset, 1); + // Get the length of the element's length + e_fieldlen = emrtd_get_asn1_field_length(hashlist + offset, hashlistlen - offset, 1); -// // Get the length of the element's length -// e_fieldlen = emrtd_get_asn1_field_length(hashlist + offset, hashlistlen - offset, 1); + switch (hashlist[offset]) { + case 0x30: + emrtd_lds_get_data_by_tag(hashlist + offset + e_fieldlen + 1, e_datalen, hashidstr, &hashidstrlen, 0x02, 0x00, false, false, 0); + emrtd_lds_get_data_by_tag(hashlist + offset + e_fieldlen + 1, e_datalen, hash, &hashlen, 0x04, 0x00, false, false, 0); + if (hashlen <= 64) { // TODO: This is for coverity, account for it. + memcpy(hashes + (hashidstr[0] * 64), hash, hashlen); + } + break; + } + // + 1 for length of ID + offset += 1 + e_datalen + e_fieldlen; + } -// switch (hashlist[offset]) { -// case 0x30: -// emrtd_lds_get_data_by_tag(hashlist + offset + e_fieldlen + 1, e_datalen, hashidstr, &hashidstrlen, 0x02, 0x00, false, false, 0); -// emrtd_lds_get_data_by_tag(hashlist + offset + e_fieldlen + 1, e_datalen, hash, &hashlen, 0x04, 0x00, false, false, 0); -// PrintAndLogEx(SUCCESS, "Hash for EF_DG%i: %s", hashidstr[0], sprint_hex_inrow(hash, hashlen)); -// break; -// } -// // + 1 for length of ID -// offset += 1 + e_datalen + e_fieldlen; -// } - -// return PM3_SUCCESS; -// } + return PM3_SUCCESS; +} int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_available) { uint8_t response[EMRTD_MAX_FILE_SIZE] = { 0x00 }; @@ -1633,8 +1633,9 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab DropField(); return PM3_ESOFT; } + // TODO: DROP THIS TOO A LA OFFLINE // Add EF_SOD to the list - filelist[filelistlen++] = 0x77; + // filelist[filelistlen++] = 0x77; // Dump all files in the file list for (int i = 0; i < filelistlen; i++) { emrtd_dg_t *dg = emrtd_tag_to_dg(filelist[i]); @@ -1686,8 +1687,26 @@ int infoHF_EMRTD_offline(const char *path) { return PM3_ESOFT; } free(data); - // Add EF_SOD to the list - filelist[filelistlen++] = 0x77; + + uint8_t dg_hashes[20][64]; + uint8_t hash_out[64]; + + strcpy(filepath, path); + strncat(filepath, PATHSEP, 2); + strcat(filepath, dg_table[EF_SOD].filename); + + if (loadFile_safeEx(filepath, ".BIN", (void **)&data, (size_t *)&datalen, false) != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Failed to read EF_SOD."); + free(filepath); + return PM3_ESOFT; + } + + res = emrtd_parse_ef_sod_hashes(data, datalen, *dg_hashes); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Failed to read hash list from EF_SOD. Hash checks will fail."); + } + free(data); + // Read files in the file list for (int i = 0; i < filelistlen; i++) { emrtd_dg_t *dg = emrtd_tag_to_dg(filelist[i]); @@ -1703,6 +1722,12 @@ int infoHF_EMRTD_offline(const char *path) { // we won't halt on parsing errors if (dg->parser != NULL) dg->parser(data, datalen); + sha512hash(data, datalen, hash_out); + if (memcmp(dg_hashes[dg->dgnum], hash_out, 64) == 0) { + PrintAndLogEx(SUCCESS, _GREEN_("Hash verification passed for EF_DG%i."), dg->dgnum); + } else { + PrintAndLogEx(ERR, _RED_("Hash verification failed for EF_DG%i."), dg->dgnum); + } free(data); } } diff --git a/client/src/cmdhfemrtd.h b/client/src/cmdhfemrtd.h index bcae56538..72f5f44b9 100644 --- a/client/src/cmdhfemrtd.h +++ b/client/src/cmdhfemrtd.h @@ -15,6 +15,7 @@ typedef struct emrtd_dg_s { uint8_t tag; + uint8_t dgnum; const char *fileid; const char *filename; const char *desc; From dbe5d9ac9a219265738645ec694ee93666441123 Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 29 Dec 2020 02:08:30 +0300 Subject: [PATCH 022/173] emrtd info (online): Add basic hash verification support --- client/src/cmdhfemrtd.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index a088bfc7f..2235dc60b 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1633,9 +1633,22 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab DropField(); return PM3_ESOFT; } - // TODO: DROP THIS TOO A LA OFFLINE - // Add EF_SOD to the list - // filelist[filelistlen++] = 0x77; + + // Grab the hash list + uint8_t dg_hashes[16][64]; + uint8_t hash_out[64]; + + if (!emrtd_select_and_read(response, &resplen, dg_table[EF_SOD].fileid, ks_enc, ks_mac, ssc, BAC, use_14b)) { + PrintAndLogEx(ERR, "Failed to read EF_SOD."); + DropField(); + return PM3_ESOFT; + } + + res = emrtd_parse_ef_sod_hashes(response, resplen, *dg_hashes); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Failed to read hash list from EF_SOD. Hash checks will fail."); + } + // Dump all files in the file list for (int i = 0; i < filelistlen; i++) { emrtd_dg_t *dg = emrtd_tag_to_dg(filelist[i]); @@ -1647,6 +1660,14 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab if (emrtd_select_and_read(response, &resplen, dg->fileid, ks_enc, ks_mac, ssc, BAC, use_14b)) { if (dg->parser != NULL) dg->parser(response, resplen); + + // Check file hash + sha512hash(response, resplen, hash_out); + if (memcmp(dg_hashes[dg->dgnum], hash_out, 64) == 0) { + PrintAndLogEx(SUCCESS, _GREEN_("Hash verification passed for EF_DG%i."), dg->dgnum); + } else { + PrintAndLogEx(ERR, _RED_("Hash verification failed for EF_DG%i."), dg->dgnum); + } } } } @@ -1688,7 +1709,8 @@ int infoHF_EMRTD_offline(const char *path) { } free(data); - uint8_t dg_hashes[20][64]; + // Grab the hash list + uint8_t dg_hashes[16][64]; uint8_t hash_out[64]; strcpy(filepath, path); @@ -1722,6 +1744,8 @@ int infoHF_EMRTD_offline(const char *path) { // we won't halt on parsing errors if (dg->parser != NULL) dg->parser(data, datalen); + + // Check file hash sha512hash(data, datalen, hash_out); if (memcmp(dg_hashes[dg->dgnum], hash_out, 64) == 0) { PrintAndLogEx(SUCCESS, _GREEN_("Hash verification passed for EF_DG%i."), dg->dgnum); From 5a9d47476591458e69f9dcfb9c2f6a6c8a0db76d Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 29 Dec 2020 02:15:15 +0300 Subject: [PATCH 023/173] emrtd: Better coverity bits for hash verif --- client/src/cmdhfemrtd.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 2235dc60b..770fde28f 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1532,16 +1532,15 @@ static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_ return PM3_SUCCESS; } -static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *hashes) { +static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *hashes, int *hashalgo) { uint8_t emrtdsig[EMRTD_MAX_FILE_SIZE] = { 0x00 }; uint8_t hashlist[EMRTD_MAX_FILE_SIZE] = { 0x00 }; - uint8_t hash[65] = { 0x00 }; + uint8_t hash[64] = { 0x00 }; size_t hashlen = 0; uint8_t hashidstr[4] = { 0x00 }; size_t hashidstrlen = 0; - // size_t emrtdsiglen, e_datalen, e_fieldlen = 0; size_t emrtdsiglen = 0; size_t hashlistlen = 0; size_t e_datalen = 0; @@ -1572,8 +1571,10 @@ static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *has case 0x30: emrtd_lds_get_data_by_tag(hashlist + offset + e_fieldlen + 1, e_datalen, hashidstr, &hashidstrlen, 0x02, 0x00, false, false, 0); emrtd_lds_get_data_by_tag(hashlist + offset + e_fieldlen + 1, e_datalen, hash, &hashlen, 0x04, 0x00, false, false, 0); - if (hashlen <= 64) { // TODO: This is for coverity, account for it. + if (hashlen <= 64) { memcpy(hashes + (hashidstr[0] * 64), hash, hashlen); + } else { + PrintAndLogEx(ERR, "error (emrtd_parse_ef_sod_hashes) hashlen out-of-bounds"); } break; } From 8b9c6a15f174651e407a77ff843daa19bb68ee87 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 00:44:06 +0100 Subject: [PATCH 024/173] VSCode debugging test --- .vscode/launch.json | 16 +++++++++++++++- .vscode/tasks.json | 8 ++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index f6a030c7c..65619a2a3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -55,7 +55,21 @@ "name": "PATH","value": "${workspaceFolder}/../../msys2/mingw64/bin;${workspaceFolder}/../../msys2/usr/local/bin;${workspaceFolder}/../../msys2/usr/bin;${workspaceFolder}/../../msys2/bin" }] } - } + },{ + "type": "cortex-debug", + "request": "launch", + "name": "Debug J-Link", + "cwd": "${workspaceRoot}", + "preLaunchTask": "fullimage: clean & make", + "executable": "${workspaceRoot}/armsrc/obj/fullimage.stage1.elf", + "serverpath": "/opt/SEGGER/JLink/JLinkGDBServerCLExe", + "servertype": "jlink", + "device": "AT91SAM7S512", + "interface": "jtag", + "serialNumber": "", //If you have more than one J-Link probe, add the serial number here. + "runToMain": true, + "armToolchainPath": "/usr/bin/" + } ], "inputs": [ { diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 7354a8a2d..4cc21841d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -143,6 +143,14 @@ } }, "problemMatcher": [] + },{ + "label": "fullimage: clean & make", + "type": "shell", + "command": "make armsrc/clean && make armsrc/all SKIP_COMPRESSION=1 DEBUG=1", + "problemMatcher": [ + "$gcc" + ], + "group": "build", } ], "inputs": [ From 637e0179756243477a143c7767ddd175af3bcf77 Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 29 Dec 2020 03:39:01 +0300 Subject: [PATCH 025/173] emrtd: Support SHA256 --- client/src/cmdhfemrtd.c | 47 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 770fde28f..e782e43ab 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1532,6 +1532,29 @@ static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_ return PM3_SUCCESS; } +static const uint8_t emrtd_hashalgo_sha256[] = {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01}; +static const uint8_t emrtd_hashalgo_sha512[] = {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03}; + +static int emrtd_parse_ef_sod_hash_algo(uint8_t *data, size_t datalen, int *hashalgo) { + uint8_t hashalgoset[64] = { 0x00 }; + size_t hashalgosetlen = 0; + + if (!emrtd_lds_get_data_by_tag(data, datalen, hashalgoset, &hashalgosetlen, 0x30, 0x00, false, true, 0)) { + PrintAndLogEx(ERR, "Failed to read hash algo set from EF_SOD."); + return false; + } + + PrintAndLogEx(DEBUG, "hash algo set: %s", sprint_hex_inrow(hashalgoset, hashalgosetlen)); + + if (memcmp(emrtd_hashalgo_sha256, hashalgoset, 11) == 0) { + *hashalgo = 1; + } else if (memcmp(emrtd_hashalgo_sha512, hashalgoset, 11) == 0) { + *hashalgo = 3; + } + + return PM3_SUCCESS; +} + static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *hashes, int *hashalgo) { uint8_t emrtdsig[EMRTD_MAX_FILE_SIZE] = { 0x00 }; uint8_t hashlist[EMRTD_MAX_FILE_SIZE] = { 0x00 }; @@ -1553,6 +1576,8 @@ static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *has PrintAndLogEx(DEBUG, "hash data: %s", sprint_hex_inrow(emrtdsig, emrtdsiglen)); + emrtd_parse_ef_sod_hash_algo(emrtdsig, emrtdsiglen, hashalgo); + if (!emrtd_lds_get_data_by_tag(emrtdsig, emrtdsiglen, hashlist, &hashlistlen, 0x30, 0x00, false, true, 1)) { PrintAndLogEx(ERR, "Failed to read hash list from EF_SOD."); return false; @@ -1638,6 +1663,7 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab // Grab the hash list uint8_t dg_hashes[16][64]; uint8_t hash_out[64]; + int hash_algo = 0; if (!emrtd_select_and_read(response, &resplen, dg_table[EF_SOD].fileid, ks_enc, ks_mac, ssc, BAC, use_14b)) { PrintAndLogEx(ERR, "Failed to read EF_SOD."); @@ -1645,7 +1671,7 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab return PM3_ESOFT; } - res = emrtd_parse_ef_sod_hashes(response, resplen, *dg_hashes); + res = emrtd_parse_ef_sod_hashes(response, resplen, *dg_hashes, &hash_algo); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Failed to read hash list from EF_SOD. Hash checks will fail."); } @@ -1663,7 +1689,13 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab dg->parser(response, resplen); // Check file hash - sha512hash(response, resplen, hash_out); + memset(hash_out, 0, 64); + if (hash_algo == 1) { + sha256hash(response, resplen, hash_out); + } else if (hash_algo == 3) { + sha512hash(response, resplen, hash_out); + } + if (memcmp(dg_hashes[dg->dgnum], hash_out, 64) == 0) { PrintAndLogEx(SUCCESS, _GREEN_("Hash verification passed for EF_DG%i."), dg->dgnum); } else { @@ -1713,6 +1745,7 @@ int infoHF_EMRTD_offline(const char *path) { // Grab the hash list uint8_t dg_hashes[16][64]; uint8_t hash_out[64]; + int hash_algo = 0; strcpy(filepath, path); strncat(filepath, PATHSEP, 2); @@ -1724,7 +1757,7 @@ int infoHF_EMRTD_offline(const char *path) { return PM3_ESOFT; } - res = emrtd_parse_ef_sod_hashes(data, datalen, *dg_hashes); + res = emrtd_parse_ef_sod_hashes(data, datalen, *dg_hashes, &hash_algo); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Failed to read hash list from EF_SOD. Hash checks will fail."); } @@ -1747,7 +1780,13 @@ int infoHF_EMRTD_offline(const char *path) { dg->parser(data, datalen); // Check file hash - sha512hash(data, datalen, hash_out); + memset(hash_out, 0, 64); + if (hash_algo == 1) { + sha256hash(data, datalen, hash_out); + } else if (hash_algo == 3) { + sha512hash(data, datalen, hash_out); + } + if (memcmp(dg_hashes[dg->dgnum], hash_out, 64) == 0) { PrintAndLogEx(SUCCESS, _GREEN_("Hash verification passed for EF_DG%i."), dg->dgnum); } else { From f47b617a58c6851da9a456c56adb8f5170bae6e6 Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 29 Dec 2020 03:51:30 +0300 Subject: [PATCH 026/173] emrtd: Check emrtd_parse_ef_sod_hash_algo output --- client/src/cmdhfemrtd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index e782e43ab..089bb6633 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1550,6 +1550,9 @@ static int emrtd_parse_ef_sod_hash_algo(uint8_t *data, size_t datalen, int *hash *hashalgo = 1; } else if (memcmp(emrtd_hashalgo_sha512, hashalgoset, 11) == 0) { *hashalgo = 3; + } else { + *hashalgo = 0; + return PM3_ESOFT; } return PM3_SUCCESS; @@ -1576,7 +1579,9 @@ static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *has PrintAndLogEx(DEBUG, "hash data: %s", sprint_hex_inrow(emrtdsig, emrtdsiglen)); - emrtd_parse_ef_sod_hash_algo(emrtdsig, emrtdsiglen, hashalgo); + if (emrtd_parse_ef_sod_hash_algo(emrtdsig, emrtdsiglen, hashalgo) != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Failed to parse hash list. Unknown algo?"); + } if (!emrtd_lds_get_data_by_tag(emrtdsig, emrtdsiglen, hashlist, &hashlistlen, 0x30, 0x00, false, true, 1)) { PrintAndLogEx(ERR, "Failed to read hash list from EF_SOD."); From bc8c52931bd65816e30109b283f0c70700881777 Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 29 Dec 2020 04:01:15 +0300 Subject: [PATCH 027/173] emrtd: Split DG hash calc into emrtd_calc_dg_hash --- client/src/cmdhfemrtd.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 089bb6633..43a2adeb8 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1532,6 +1532,7 @@ static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_ return PM3_SUCCESS; } +// https://security.stackexchange.com/questions/131241/where-do-magic-constants-for-signature-algorithms-come-from static const uint8_t emrtd_hashalgo_sha256[] = {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01}; static const uint8_t emrtd_hashalgo_sha512[] = {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03}; @@ -1615,6 +1616,16 @@ static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *has return PM3_SUCCESS; } +static void emrtd_calc_dg_hash(uint8_t *data, size_t datalen, uint8_t *hash_out, int hash_algo) { + memset(hash_out, 0, 64); + + if (hash_algo == 1) { + sha256hash(data, datalen, hash_out); + } else if (hash_algo == 3) { + sha512hash(data, datalen, hash_out); + } +} + int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_available) { uint8_t response[EMRTD_MAX_FILE_SIZE] = { 0x00 }; int resplen = 0; @@ -1694,12 +1705,7 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab dg->parser(response, resplen); // Check file hash - memset(hash_out, 0, 64); - if (hash_algo == 1) { - sha256hash(response, resplen, hash_out); - } else if (hash_algo == 3) { - sha512hash(response, resplen, hash_out); - } + emrtd_calc_dg_hash(response, resplen, hash_out, hash_algo); if (memcmp(dg_hashes[dg->dgnum], hash_out, 64) == 0) { PrintAndLogEx(SUCCESS, _GREEN_("Hash verification passed for EF_DG%i."), dg->dgnum); @@ -1785,12 +1791,7 @@ int infoHF_EMRTD_offline(const char *path) { dg->parser(data, datalen); // Check file hash - memset(hash_out, 0, 64); - if (hash_algo == 1) { - sha256hash(data, datalen, hash_out); - } else if (hash_algo == 3) { - sha512hash(data, datalen, hash_out); - } + emrtd_calc_dg_hash(data, datalen, hash_out, hash_algo); if (memcmp(dg_hashes[dg->dgnum], hash_out, 64) == 0) { PrintAndLogEx(SUCCESS, _GREEN_("Hash verification passed for EF_DG%i."), dg->dgnum); From aae3426f8e6f08079ae5648c336c1d5d33c47318 Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 29 Dec 2020 04:09:53 +0300 Subject: [PATCH 028/173] emrtd: Adjust an include comment --- client/src/cmdhfemrtd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 43a2adeb8..32c2c9e23 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -20,7 +20,7 @@ #include "protocols.h" // definitions of ISO14A/7816 protocol #include "emv/apduinfo.h" // GetAPDUCodeDescription #include "sha1.h" // KSeed calculation etc -#include "crypto/libpcrypto.h" // Hash calculation (sha256), TODO: AES too +#include "crypto/libpcrypto.h" // Hash calculation (sha256, sha512) #include "mifare/desfire_crypto.h" // des_encrypt/des_decrypt #include "des.h" // mbedtls_des_key_set_parity #include "cmdhf14b.h" // exchange_14b_apdu From 2c5c58d128e9d7ddc2cdb2a4f7c1a76ffefa807a Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 29 Dec 2020 04:20:48 +0300 Subject: [PATCH 029/173] emrtd: Remove 'very very very very cursed' comment --- client/src/cmdhfemrtd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 32c2c9e23..08c53467b 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1485,7 +1485,6 @@ static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen) { } static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_t *dataout, size_t *dataoutlen) { - // very very very very cursed code. uint8_t top[EMRTD_MAX_FILE_SIZE] = { 0x00 }; uint8_t signeddata[EMRTD_MAX_FILE_SIZE] = { 0x00 }; uint8_t emrtdsigcontainer[EMRTD_MAX_FILE_SIZE] = { 0x00 }; From 8c29c4231be80b41bc4ee2a31921f4d0c847d9e4 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 03:30:57 +0100 Subject: [PATCH 030/173] Allow generation of debug information when using no compression --- common_arm/Makefile.hal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common_arm/Makefile.hal b/common_arm/Makefile.hal index bfbe56d34..b6519e4ab 100644 --- a/common_arm/Makefile.hal +++ b/common_arm/Makefile.hal @@ -138,7 +138,7 @@ ifneq ($(SKIP_HFPLOT),1) PLATFORM_DEFS += -DWITH_HFPLOT endif ifeq ($(SKIP_COMPRESSION),1) - PLATFORM_DEFS += -DWITH_NO_COMPRESSION + PLATFORM_DEFS += -DWITH_NO_COMPRESSION -g endif # Standalone mode From 654996eeee4f3cd8f1895aa90c57ffc48b04ae63 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 03:39:59 +0100 Subject: [PATCH 031/173] Fixed debugger waiting for main --- .vscode/launch.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 65619a2a3..d1c5d6ff8 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -58,7 +58,7 @@ },{ "type": "cortex-debug", "request": "launch", - "name": "Debug J-Link", + "name": "Firmware debug", "cwd": "${workspaceRoot}", "preLaunchTask": "fullimage: clean & make", "executable": "${workspaceRoot}/armsrc/obj/fullimage.stage1.elf", @@ -67,7 +67,7 @@ "device": "AT91SAM7S512", "interface": "jtag", "serialNumber": "", //If you have more than one J-Link probe, add the serial number here. - "runToMain": true, + "runToMain": false, "armToolchainPath": "/usr/bin/" } ], From 6d6f3d9f1a1bf7296dad3e654407b832464285cf Mon Sep 17 00:00:00 2001 From: tcprst Date: Mon, 28 Dec 2020 23:00:10 -0500 Subject: [PATCH 032/173] hf 14a sniff, reader - now use cliparser --- client/src/cmdhf14a.c | 110 ++++++++++++++++++++++------------------- doc/cliparser_todo.txt | 2 - 2 files changed, 58 insertions(+), 54 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 150b49fee..5419239b1 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -236,26 +236,6 @@ static int usage_hf_14a_sim(void) { PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a sim t 1 u 112233445566778899AA")); return PM3_SUCCESS; } -static int usage_hf_14a_sniff(void) { - PrintAndLogEx(NORMAL, "Collect data from the field and save into command buffer."); - PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf 14a list'"); - PrintAndLogEx(NORMAL, "Usage: hf 14a sniff [c][r]"); - PrintAndLogEx(NORMAL, "c - triggered by first data from card"); - PrintAndLogEx(NORMAL, "r - triggered by first 7-bit request from reader (REQ,WUP,...)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a sniff c r")); - return PM3_SUCCESS; -} - -static int usage_hf_14a_reader(void) { - PrintAndLogEx(NORMAL, "Usage: hf 14a reader [k|s|x] [3]"); - PrintAndLogEx(NORMAL, " k keep the field active after command executed"); - PrintAndLogEx(NORMAL, " s silent (no messages)"); - PrintAndLogEx(NORMAL, " x just drop the signal field"); - PrintAndLogEx(NORMAL, " 3 ISO14443-3 select only (skip RATS)"); - PrintAndLogEx(NORMAL, " @ continuous mode. Updates hf plot as well"); - return PM3_SUCCESS; -} static int CmdHF14AList(const char *Cmd) { char args[128] = {0}; @@ -462,37 +442,44 @@ int Hf14443_4aGetCardData(iso14a_card_select_t *card) { } static int CmdHF14AReader(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 14a reader", + "Reader for ISO 14443A based tags", + "hf 14a reader -@ <- Continuous mode"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("k", "keep", "keep the field active after command executed"), + arg_lit0("s", "silent", "silent (no messages)"), + arg_lit0(NULL, "drop", "just drop the signal field"), + arg_lit0(NULL, "skip", "ISO14443-3 select only (skip RATS)"), + arg_lit0("@", NULL, "optional - continuous reader mode"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool disconnectAfter = true; + if (arg_get_lit(ctx, 1)) { + disconnectAfter = false; + } + + bool silent = arg_get_lit(ctx, 2); uint32_t cm = ISO14A_CONNECT; - bool disconnectAfter = true, silent = false, continuous = false; - int cmdp = 0; - int res = PM3_SUCCESS; - while (param_getchar(Cmd, cmdp) != 0x00) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_14a_reader(); - case '3': - cm |= ISO14A_NO_RATS; - break; - case 'k': - disconnectAfter = false; - break; - case 's': - silent = true; - break; - case 'x': - cm &= ~ISO14A_CONNECT; - break; - case '@': - continuous = true; - break; - default: - PrintAndLogEx(WARNING, "Unknown command."); - return PM3_EINVARG; - } - cmdp++; + if (arg_get_lit(ctx, 3)) { + cm &= ~ISO14A_CONNECT; } + if (arg_get_lit(ctx, 4)) { + cm |= ISO14A_NO_RATS; + } + + bool continuous = arg_get_lit(ctx, 5); + + CLIParserFree(ctx); + + int res = PM3_SUCCESS; + if (!disconnectAfter) cm |= ISO14A_NO_DISCONNECT; if (continuous) { @@ -768,13 +755,32 @@ int CmdHF14ASim(const char *Cmd) { } int CmdHF14ASniff(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 14a sniff", + "Collect data from the field and save into command buffer.\n" + "Buffer accessible from command 'hf 14a list'", + " hf 14a sniff -c -r"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("c", "card", "triggered by first data from card"), + arg_lit0("r", "reader", "triggered by first 7-bit request from reader (REQ,WUP,...)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + uint8_t param = 0; - for (uint8_t i = 0; i < 2; i++) { - uint8_t ctmp = tolower(param_getchar(Cmd, i)); - if (ctmp == 'h') return usage_hf_14a_sniff(); - if (ctmp == 'c') param |= 0x01; - if (ctmp == 'r') param |= 0x02; + + if (arg_get_lit(ctx, 1)) { + param |= 0x01; } + + if (arg_get_lit(ctx, 2)) { + param |= 0x02; + } + + CLIParserFree(ctx); + clearCommandBuffer(); SendCommandNG(CMD_HF_ISO14443A_SNIFF, (uint8_t *)¶m, sizeof(uint8_t)); return PM3_SUCCESS; diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 7e333911b..c9dcf077c 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -41,10 +41,8 @@ data print data samples data setdebugmode data tune -hf 14a reader hf 14a cuids hf 14a sim -hf 14a sniff hf 14a config hf 14b sriwrite hf 15 dump From 2124ef52893d95a251337f385af3ca1d4542e566 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 05:01:29 +0100 Subject: [PATCH 033/173] Added firmware configuration for wsl --- .vscode/launch.json | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index d1c5d6ff8..abd2cd775 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -58,10 +58,10 @@ },{ "type": "cortex-debug", "request": "launch", - "name": "Firmware debug", + "name": "(Linux) Firmware debug", "cwd": "${workspaceRoot}", "preLaunchTask": "fullimage: clean & make", - "executable": "${workspaceRoot}/armsrc/obj/fullimage.stage1.elf", + "executable": "${workspaceRoot}/armsrc/obj/fullimage.elf", "serverpath": "/opt/SEGGER/JLink/JLinkGDBServerCLExe", "servertype": "jlink", "device": "AT91SAM7S512", @@ -69,7 +69,21 @@ "serialNumber": "", //If you have more than one J-Link probe, add the serial number here. "runToMain": false, "armToolchainPath": "/usr/bin/" - } + },{ + "type": "cortex-debug", + "request": "launch", + "name": "(WSL) Firmware debug", + "cwd": "${workspaceRoot}", + "preLaunchTask": "fullimage: clean & make", + "executable": "${workspaceRoot}/armsrc/obj/fullimage.elf", + "serverpath": "/mnt/c/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe", + "servertype": "jlink", + "device": "AT91SAM7S512", + "interface": "jtag", + "serialNumber": "", //If you have more than one J-Link probe, add the serial number here. + "runToMain": false, + "armToolchainPath": "/usr/bin/" + } ], "inputs": [ { From 9e224b011b6655e5de59c102731461ffa9adb152 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 14:55:31 +0100 Subject: [PATCH 034/173] Template files for vscode --- .gitignore | 5 + .vscode/extensions.json | 10 ++ .vscode/launch.json | 108 -------------- .vscode/launch_linux.json | 70 +++++++++ .vscode/launch_ps.json | 45 ++++++ .vscode/launch_wsl.json | 70 +++++++++ .vscode/setup.sh | 4 + .vscode/{tasks.json => tasks_linux.json} | 0 .vscode/tasks_ps.json | 177 +++++++++++++++++++++++ .vscode/tasks_wsl.json | 177 +++++++++++++++++++++++ 10 files changed, 558 insertions(+), 108 deletions(-) create mode 100644 .vscode/extensions.json delete mode 100644 .vscode/launch.json create mode 100644 .vscode/launch_linux.json create mode 100644 .vscode/launch_ps.json create mode 100644 .vscode/launch_wsl.json create mode 100644 .vscode/setup.sh rename .vscode/{tasks.json => tasks_linux.json} (100%) create mode 100644 .vscode/tasks_ps.json create mode 100644 .vscode/tasks_wsl.json diff --git a/.gitignore b/.gitignore index 081c0f8e8..1b27c52a3 100644 --- a/.gitignore +++ b/.gitignore @@ -108,3 +108,8 @@ fpga_version_info.c # .tmp files are created during compilation *.tmp + +#VSCode files +!.vscode/*.json +.vscode/launch.json +.vscode/tasks.json \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..85b3997e2 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "ms-vscode.cpptools", + "austin.code-gnu-global", + "marus25.cortex-debug", + "augustocdias.tasks-shell-input" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index abd2cd775..000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "(gdb) Attach", - "type": "cppdbg", - "request": "attach", - "program": "${cwd}/client/proxmark3", - //"processId": "${command:pickProcess}", - "processId": "${input:ProcessID}", - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ], - "windows": { - "processId": "${input:ProcessIDWindows}", - "miDebuggerPath": "${workspaceFolder}/../../msys2/mingw64/bin/gdb.exe", - "externalConsole": true,//for ProxSpace externalConsole=true is required, because the internal cosole stops updating after a while - "environment": [{ - "name": "PATH","value": "${workspaceFolder}/../../msys2/mingw64/bin;${workspaceFolder}/../../msys2/usr/local/bin;${workspaceFolder}/../../msys2/usr/bin;${workspaceFolder}/../../msys2/bin" - }] - } - },{ - "name": "(gdb) Build & Launch", - "type": "cppdbg", - "request": "launch", - "program": "${cwd}/client/proxmark3", - "args": ["/dev/ttyACM0"], - "stopAtEntry": false, - "cwd": "${workspaceFolder}", - "environment": [], - "externalConsole": false, - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ], - "preLaunchTask": "client: Debug: clean & make", - "miDebuggerPath": "/usr/bin/gdb", - "windows": { - "args": ["COM5"], - "miDebuggerPath": "${workspaceFolder}/../../msys2/mingw64/bin/gdb.exe", - "externalConsole": true,//for ProxSpace externalConsole=true is required, because the internal cosole stops updating after a while - "environment": [{ - "name": "PATH","value": "${workspaceFolder}/../../msys2/mingw64/bin;${workspaceFolder}/../../msys2/usr/local/bin;${workspaceFolder}/../../msys2/usr/bin;${workspaceFolder}/../../msys2/bin" - }] - } - },{ - "type": "cortex-debug", - "request": "launch", - "name": "(Linux) Firmware debug", - "cwd": "${workspaceRoot}", - "preLaunchTask": "fullimage: clean & make", - "executable": "${workspaceRoot}/armsrc/obj/fullimage.elf", - "serverpath": "/opt/SEGGER/JLink/JLinkGDBServerCLExe", - "servertype": "jlink", - "device": "AT91SAM7S512", - "interface": "jtag", - "serialNumber": "", //If you have more than one J-Link probe, add the serial number here. - "runToMain": false, - "armToolchainPath": "/usr/bin/" - },{ - "type": "cortex-debug", - "request": "launch", - "name": "(WSL) Firmware debug", - "cwd": "${workspaceRoot}", - "preLaunchTask": "fullimage: clean & make", - "executable": "${workspaceRoot}/armsrc/obj/fullimage.elf", - "serverpath": "/mnt/c/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe", - "servertype": "jlink", - "device": "AT91SAM7S512", - "interface": "jtag", - "serialNumber": "", //If you have more than one J-Link probe, add the serial number here. - "runToMain": false, - "armToolchainPath": "/usr/bin/" - } - ], - "inputs": [ - { - // Using Extension "Tasks Shell Input" https://marketplace.visualstudio.com/items?itemName=augustocdias.tasks-shell-input - "id": "ProcessID", - "type": "command", - "command": "shellCommand.execute", - "args": { - "command": "pgrep -n proxmark3", - } - - },{ - "id": "ProcessIDWindows", - "type": "command", - "command": "shellCommand.execute", - "args": { - "command": "${workspaceFolder}/../../runme64.bat -c \"cat /proc/$(pgrep -n proxmark3)/winpid\"", - } - - } - ] -} \ No newline at end of file diff --git a/.vscode/launch_linux.json b/.vscode/launch_linux.json new file mode 100644 index 000000000..0f60495a6 --- /dev/null +++ b/.vscode/launch_linux.json @@ -0,0 +1,70 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Client: (gdb) Build & Launch", + "type": "cppdbg", + "request": "launch", + "program": "${cwd}/client/proxmark3", + "args": ["${SerialPort}"], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "client: Debug: clean & make", + "miDebuggerPath": "${DebuggerPath}" + },{ + "name": "Client: (gdb) Attach", + "type": "cppdbg", + "request": "attach", + "program": "${cwd}/client/proxmark3", + //"processId": "${command:pickProcess}", + "processId": "${input:ProcessID}", + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + },{ + "name": "Firmware: (J-Link) Build & Launch", + "type": "cortex-debug", + "request": "launch", + "cwd": "${workspaceRoot}", + "preLaunchTask": "fullimage: clean & make", + "executable": "${workspaceRoot}/armsrc/obj/fullimage.elf", + "serverpath": "${JLinkServerPath}", + "servertype": "jlink", + "device": "AT91SAM7S${DeviceMem}", + "interface": "jtag", + "serialNumber": "", //If you have more than one J-Link probe, add the serial number here. + "runToMain": false, + "armToolchainPath": "/usr/bin/" + } + ], + "inputs": [ + { + // Using Extension "Tasks Shell Input" https://marketplace.visualstudio.com/items?itemName=augustocdias.tasks-shell-input + "id": "ProcessID", + "type": "command", + "command": "shellCommand.execute", + "args": { + "command": "pgrep -n proxmark3", + } + + } + ] +} \ No newline at end of file diff --git a/.vscode/launch_ps.json b/.vscode/launch_ps.json new file mode 100644 index 000000000..8794ef76e --- /dev/null +++ b/.vscode/launch_ps.json @@ -0,0 +1,45 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Client: (gdb) Build & Launch", + "type": "cppdbg", + "request": "launch", + "program": "${cwd}/client/proxmark3", + "args": ["${SerialPort}"], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [ + "name": "PATH","value": "${workspaceFolder}/../../msys2/mingw64/bin;${workspaceFolder}/../../msys2/usr/local/bin;${workspaceFolder}/../../msys2/usr/bin;${workspaceFolder}/../../msys2/bin" + ], + "externalConsole": true,//for ProxSpace externalConsole=true is required, because the internal cosole stops updating after a while + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "client: Debug: clean & make", + "miDebuggerPath": "${DebuggerPath}" + },{ + "name": "Firmware: (J-Link) Build & Launch", + "type": "cortex-debug", + "request": "launch", + "cwd": "${workspaceRoot}", + "preLaunchTask": "fullimage: clean & make", + "executable": "${workspaceRoot}/armsrc/obj/fullimage.elf", + "serverpath": "${JLinkServerPath}", + "servertype": "jlink", + "device": "AT91SAM7S${DeviceMem}", + "interface": "jtag", + "serialNumber": "", //If you have more than one J-Link probe, add the serial number here. + "runToMain": false, + "armToolchainPath": "/usr/bin/" + } + ] +} \ No newline at end of file diff --git a/.vscode/launch_wsl.json b/.vscode/launch_wsl.json new file mode 100644 index 000000000..0f60495a6 --- /dev/null +++ b/.vscode/launch_wsl.json @@ -0,0 +1,70 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Client: (gdb) Build & Launch", + "type": "cppdbg", + "request": "launch", + "program": "${cwd}/client/proxmark3", + "args": ["${SerialPort}"], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "client: Debug: clean & make", + "miDebuggerPath": "${DebuggerPath}" + },{ + "name": "Client: (gdb) Attach", + "type": "cppdbg", + "request": "attach", + "program": "${cwd}/client/proxmark3", + //"processId": "${command:pickProcess}", + "processId": "${input:ProcessID}", + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + },{ + "name": "Firmware: (J-Link) Build & Launch", + "type": "cortex-debug", + "request": "launch", + "cwd": "${workspaceRoot}", + "preLaunchTask": "fullimage: clean & make", + "executable": "${workspaceRoot}/armsrc/obj/fullimage.elf", + "serverpath": "${JLinkServerPath}", + "servertype": "jlink", + "device": "AT91SAM7S${DeviceMem}", + "interface": "jtag", + "serialNumber": "", //If you have more than one J-Link probe, add the serial number here. + "runToMain": false, + "armToolchainPath": "/usr/bin/" + } + ], + "inputs": [ + { + // Using Extension "Tasks Shell Input" https://marketplace.visualstudio.com/items?itemName=augustocdias.tasks-shell-input + "id": "ProcessID", + "type": "command", + "command": "shellCommand.execute", + "args": { + "command": "pgrep -n proxmark3", + } + + } + ] +} \ No newline at end of file diff --git a/.vscode/setup.sh b/.vscode/setup.sh new file mode 100644 index 000000000..b439f2cbd --- /dev/null +++ b/.vscode/setup.sh @@ -0,0 +1,4 @@ +export SerialPort="/dev/ttyACM0" +export DebuggerPath="/usr/bin/gdb" +export JLinkServerPath="/opt/SEGGER/JLink/JLinkGDBServerCLExe" +export DeviceMem="512" \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks_linux.json similarity index 100% rename from .vscode/tasks.json rename to .vscode/tasks_linux.json diff --git a/.vscode/tasks_ps.json b/.vscode/tasks_ps.json new file mode 100644 index 000000000..4cc21841d --- /dev/null +++ b/.vscode/tasks_ps.json @@ -0,0 +1,177 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "all: Make & run", + "type": "shell", + "command": "make -j && ./pm3", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "choose: Make", + "type": "shell", + "command": "make ${input:componentType} -j", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, + "problemMatcher": [ + "$gcc" + ], + "group": "build", + }, + { + "label": "client: Debug: make", + "type": "shell", + "command": "make client -j DEBUG=1", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, + "problemMatcher": [ + "$gcc" + ], + "group": "build", + }, + { + "label": "client: Debug: clean & make", + "type": "shell", + "command": "make client/clean && make client -j DEBUG=1", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, + "problemMatcher": [ + "$gcc" + ], + "group": "build", + }, + { + "label": "fullimage: Make & Flash", + "type": "shell", + "command": "make fullimage && ./pm3-flash-fullimage", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, + "problemMatcher": [] + }, + { + "label": "BOOTROM: Make & Flash", + "type": "shell", + "command": "make bootrom && ./pm3-flash-bootrom", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, + "problemMatcher": [] + }, + { + "label": "Run client", + "type": "shell", + "command": "./pm3", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, + "problemMatcher": [] + },{ + "label": "fullimage: clean & make", + "type": "shell", + "command": "make armsrc/clean && make armsrc/all SKIP_COMPRESSION=1 DEBUG=1", + "problemMatcher": [ + "$gcc" + ], + "group": "build", + } + ], + "inputs": [ + { + "type": "pickString", + "id": "componentType", + "description": "What Makefile target do you want to execute?", + "options": [ + "all", + "client", + "bootrom", + "fullimage", + "recovery", + "clean", + "install", + "uninstall", + "style", + "miscchecks", + "check", + ], + "default": "all" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks_wsl.json b/.vscode/tasks_wsl.json new file mode 100644 index 000000000..4cc21841d --- /dev/null +++ b/.vscode/tasks_wsl.json @@ -0,0 +1,177 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "all: Make & run", + "type": "shell", + "command": "make -j && ./pm3", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "choose: Make", + "type": "shell", + "command": "make ${input:componentType} -j", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, + "problemMatcher": [ + "$gcc" + ], + "group": "build", + }, + { + "label": "client: Debug: make", + "type": "shell", + "command": "make client -j DEBUG=1", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, + "problemMatcher": [ + "$gcc" + ], + "group": "build", + }, + { + "label": "client: Debug: clean & make", + "type": "shell", + "command": "make client/clean && make client -j DEBUG=1", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, + "problemMatcher": [ + "$gcc" + ], + "group": "build", + }, + { + "label": "fullimage: Make & Flash", + "type": "shell", + "command": "make fullimage && ./pm3-flash-fullimage", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, + "problemMatcher": [] + }, + { + "label": "BOOTROM: Make & Flash", + "type": "shell", + "command": "make bootrom && ./pm3-flash-bootrom", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, + "problemMatcher": [] + }, + { + "label": "Run client", + "type": "shell", + "command": "./pm3", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, + "problemMatcher": [] + },{ + "label": "fullimage: clean & make", + "type": "shell", + "command": "make armsrc/clean && make armsrc/all SKIP_COMPRESSION=1 DEBUG=1", + "problemMatcher": [ + "$gcc" + ], + "group": "build", + } + ], + "inputs": [ + { + "type": "pickString", + "id": "componentType", + "description": "What Makefile target do you want to execute?", + "options": [ + "all", + "client", + "bootrom", + "fullimage", + "recovery", + "clean", + "install", + "uninstall", + "style", + "miscchecks", + "check", + ], + "default": "all" + } + ] +} \ No newline at end of file From 040520d865486184e0165779a16f7774414277ee Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 29 Dec 2020 17:56:29 +0300 Subject: [PATCH 035/173] emrtd: Improve hashing logic, support SHA1 --- client/src/cmdhfemrtd.c | 86 +++++++++++++++++++--------------- client/src/cmdhfemrtd.h | 8 ++++ client/src/crypto/libpcrypto.c | 10 ++++ client/src/crypto/libpcrypto.h | 1 + 4 files changed, 68 insertions(+), 37 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 08c53467b..e563ac7fa 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -19,8 +19,7 @@ #include "cmdhf14a.h" // ExchangeAPDU14a #include "protocols.h" // definitions of ISO14A/7816 protocol #include "emv/apduinfo.h" // GetAPDUCodeDescription -#include "sha1.h" // KSeed calculation etc -#include "crypto/libpcrypto.h" // Hash calculation (sha256, sha512) +#include "crypto/libpcrypto.h" // Hash calculation (sha1, sha256, sha512) #include "mifare/desfire_crypto.h" // des_encrypt/des_decrypt #include "des.h" // mbedtls_des_key_set_parity #include "cmdhf14b.h" // exchange_14b_apdu @@ -108,6 +107,16 @@ static emrtd_dg_t dg_table[] = { {0x00, 0, NULL, NULL, NULL, false, false, false, false, NULL, NULL} }; +// https://security.stackexchange.com/questions/131241/where-do-magic-constants-for-signature-algorithms-come-from +// https://tools.ietf.org/html/rfc3447#page-43 +static emrtd_hashalg_t hashalg_table[] = { +// name hash func len len descriptor + {"SHA-1", sha1hash, 20, 9, {0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00}}, + {"SHA-256", sha256hash, 32, 11, {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01}}, + {"SHA-512", sha512hash, 64, 11, {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03}}, + {NULL, NULL, 0, 0, {}} +}; + static emrtd_dg_t *emrtd_tag_to_dg(uint8_t tag) { for (int dgi = 0; dg_table[dgi].filename != NULL; dgi++) { if (dg_table[dgi].tag == tag) { @@ -339,7 +348,7 @@ static void emrtd_deskey(uint8_t *seed, const uint8_t *type, int length, uint8_t // SHA1 the key unsigned char key[64]; - mbedtls_sha1(data, length + 4, key); + sha1hash(data, length + 4, key); PrintAndLogEx(DEBUG, "key............... %s", sprint_hex_inrow(key, length + 4)); // Set parity bits @@ -822,7 +831,7 @@ static bool emrtd_do_bac(char *documentnumber, char *dob, char *expiry, uint8_t PrintAndLogEx(DEBUG, "kmrz.............. " _GREEN_("%s"), kmrz); uint8_t kseed[20] = { 0x00 }; - mbedtls_sha1((unsigned char *)kmrz, strlen(kmrz), kseed); + sha1hash((unsigned char *)kmrz, strlen(kmrz), kseed); PrintAndLogEx(DEBUG, "kseed (sha1)...... %s ", sprint_hex_inrow(kseed, 16)); emrtd_deskey(kseed, KENC_type, 16, kenc); @@ -1531,10 +1540,6 @@ static int emrtd_ef_sod_extract_signatures(uint8_t *data, size_t datalen, uint8_ return PM3_SUCCESS; } -// https://security.stackexchange.com/questions/131241/where-do-magic-constants-for-signature-algorithms-come-from -static const uint8_t emrtd_hashalgo_sha256[] = {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01}; -static const uint8_t emrtd_hashalgo_sha512[] = {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03}; - static int emrtd_parse_ef_sod_hash_algo(uint8_t *data, size_t datalen, int *hashalgo) { uint8_t hashalgoset[64] = { 0x00 }; size_t hashalgosetlen = 0; @@ -1546,16 +1551,23 @@ static int emrtd_parse_ef_sod_hash_algo(uint8_t *data, size_t datalen, int *hash PrintAndLogEx(DEBUG, "hash algo set: %s", sprint_hex_inrow(hashalgoset, hashalgosetlen)); - if (memcmp(emrtd_hashalgo_sha256, hashalgoset, 11) == 0) { - *hashalgo = 1; - } else if (memcmp(emrtd_hashalgo_sha512, hashalgoset, 11) == 0) { - *hashalgo = 3; - } else { - *hashalgo = 0; - return PM3_ESOFT; + for (int hashi = 0; hashalg_table[hashi].name != NULL; hashi++) { + PrintAndLogEx(DEBUG, "trying: %s", hashalg_table[hashi].name); + // We're only interested in checking if the length matches to avoid memory shenanigans + if (hashalg_table[hashi].descriptorlen != hashalgosetlen) { + PrintAndLogEx(DEBUG, "len mismatch: %i", hashalgosetlen); + continue; + } + + if (memcmp(hashalg_table[hashi].descriptor, hashalgoset, hashalgosetlen) == 0) { + *hashalgo = hashi; + return PM3_SUCCESS; + } } - return PM3_SUCCESS; + // Return hash algo 0 if we can't find anything + *hashalgo = -1; + return PM3_ESOFT; } static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *hashes, int *hashalgo) { @@ -1580,7 +1592,7 @@ static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *has PrintAndLogEx(DEBUG, "hash data: %s", sprint_hex_inrow(emrtdsig, emrtdsiglen)); if (emrtd_parse_ef_sod_hash_algo(emrtdsig, emrtdsiglen, hashalgo) != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Failed to parse hash list. Unknown algo?"); + PrintAndLogEx(ERR, "Failed to parse hash list (Unknown algo?). Hash verification won't be available."); } if (!emrtd_lds_get_data_by_tag(emrtdsig, emrtdsiglen, hashlist, &hashlistlen, 0x30, 0x00, false, true, 1)) { @@ -1615,16 +1627,6 @@ static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *has return PM3_SUCCESS; } -static void emrtd_calc_dg_hash(uint8_t *data, size_t datalen, uint8_t *hash_out, int hash_algo) { - memset(hash_out, 0, 64); - - if (hash_algo == 1) { - sha256hash(data, datalen, hash_out); - } else if (hash_algo == 3) { - sha512hash(data, datalen, hash_out); - } -} - int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_available) { uint8_t response[EMRTD_MAX_FILE_SIZE] = { 0x00 }; int resplen = 0; @@ -1703,13 +1705,18 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab if (dg->parser != NULL) dg->parser(response, resplen); + PrintAndLogEx(DEBUG, "EF_DG%i hash algo: %i", dg->dgnum, hash_algo); // Check file hash - emrtd_calc_dg_hash(response, resplen, hash_out, hash_algo); + if (hash_algo != -1) { + PrintAndLogEx(DEBUG, "EF_DG%i hash on EF_SOD: %s", dg->dgnum, sprint_hex_inrow(dg_hashes[dg->dgnum], hashalg_table[hash_algo].hashlen)); + hashalg_table[hash_algo].hasher(response, resplen, hash_out); + PrintAndLogEx(DEBUG, "EF_DG%i hash calc: %s", dg->dgnum, sprint_hex_inrow(hash_out, hashalg_table[hash_algo].hashlen)); - if (memcmp(dg_hashes[dg->dgnum], hash_out, 64) == 0) { - PrintAndLogEx(SUCCESS, _GREEN_("Hash verification passed for EF_DG%i."), dg->dgnum); - } else { - PrintAndLogEx(ERR, _RED_("Hash verification failed for EF_DG%i."), dg->dgnum); + if (memcmp(dg_hashes[dg->dgnum], hash_out, hashalg_table[hash_algo].hashlen) == 0) { + PrintAndLogEx(SUCCESS, _GREEN_("Hash verification passed for EF_DG%i."), dg->dgnum); + } else { + PrintAndLogEx(ERR, _RED_("Hash verification failed for EF_DG%i."), dg->dgnum); + } } } } @@ -1789,13 +1796,18 @@ int infoHF_EMRTD_offline(const char *path) { if (dg->parser != NULL) dg->parser(data, datalen); + PrintAndLogEx(DEBUG, "EF_DG%i hash algo: %i", dg->dgnum, hash_algo); // Check file hash - emrtd_calc_dg_hash(data, datalen, hash_out, hash_algo); + if (hash_algo != -1) { + PrintAndLogEx(DEBUG, "EF_DG%i hash on EF_SOD: %s", dg->dgnum, sprint_hex_inrow(dg_hashes[dg->dgnum], hashalg_table[hash_algo].hashlen)); + hashalg_table[hash_algo].hasher(data, datalen, hash_out); + PrintAndLogEx(DEBUG, "EF_DG%i hash calc: %s", dg->dgnum, sprint_hex_inrow(hash_out, hashalg_table[hash_algo].hashlen)); - if (memcmp(dg_hashes[dg->dgnum], hash_out, 64) == 0) { - PrintAndLogEx(SUCCESS, _GREEN_("Hash verification passed for EF_DG%i."), dg->dgnum); - } else { - PrintAndLogEx(ERR, _RED_("Hash verification failed for EF_DG%i."), dg->dgnum); + if (memcmp(dg_hashes[dg->dgnum], hash_out, hashalg_table[hash_algo].hashlen) == 0) { + PrintAndLogEx(SUCCESS, _GREEN_("Hash verification passed for EF_DG%i."), dg->dgnum); + } else { + PrintAndLogEx(ERR, _RED_("Hash verification failed for EF_DG%i."), dg->dgnum); + } } free(data); } diff --git a/client/src/cmdhfemrtd.h b/client/src/cmdhfemrtd.h index 72f5f44b9..f7bd64945 100644 --- a/client/src/cmdhfemrtd.h +++ b/client/src/cmdhfemrtd.h @@ -27,6 +27,14 @@ typedef struct emrtd_dg_s { int (*dumper)(uint8_t *data, size_t datalen); } emrtd_dg_t; +typedef struct emrtd_hashalg_s { + const char *name; + int (*hasher)(uint8_t *datain, int datainlen, uint8_t *dataout); + size_t hashlen; + size_t descriptorlen; + const uint8_t descriptor[15]; +} emrtd_hashalg_t; + int CmdHFeMRTD(const char *Cmd); int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_available); diff --git a/client/src/crypto/libpcrypto.c b/client/src/crypto/libpcrypto.c index cb73b3f5c..5c5455bf6 100644 --- a/client/src/crypto/libpcrypto.c +++ b/client/src/crypto/libpcrypto.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -93,6 +94,15 @@ static int fixed_rand(void *rng_state, unsigned char *output, size_t len) { return 0; } +int sha1hash(uint8_t *input, int length, uint8_t *hash) { + if (!hash || !input) + return 1; + + mbedtls_sha1(input, length, hash); + + return 0; +} + int sha256hash(uint8_t *input, int length, uint8_t *hash) { if (!hash || !input) return 1; diff --git a/client/src/crypto/libpcrypto.h b/client/src/crypto/libpcrypto.h index b4307f454..099fd4423 100644 --- a/client/src/crypto/libpcrypto.h +++ b/client/src/crypto/libpcrypto.h @@ -21,6 +21,7 @@ int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int l int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length); int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length); +int sha1hash(uint8_t *input, int length, uint8_t *hash); int sha256hash(uint8_t *input, int length, uint8_t *hash); int sha512hash(uint8_t *input, int length, uint8_t *hash); From 6f316b8e29559d260f1f3be2ca8b3ce0dd5708f0 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 16:38:02 +0100 Subject: [PATCH 036/173] detect serial port --- .vscode/setup.sh | 69 +++++++++++++++++++++++++++++++++++++++++++++--- pm3 | 45 +++++++++++++++++-------------- 2 files changed, 90 insertions(+), 24 deletions(-) diff --git a/.vscode/setup.sh b/.vscode/setup.sh index b439f2cbd..ee8476d11 100644 --- a/.vscode/setup.sh +++ b/.vscode/setup.sh @@ -1,4 +1,65 @@ -export SerialPort="/dev/ttyACM0" -export DebuggerPath="/usr/bin/gdb" -export JLinkServerPath="/opt/SEGGER/JLink/JLinkGDBServerCLExe" -export DeviceMem="512" \ No newline at end of file +#!/bin/bash +############################### +# Linux # +# Uncomment to override # +############################### +#export SerialPort="/dev/ttyACM0" +#export DebuggerPath="/usr/bin/gdb" +#export JLinkServerPath="/opt/SEGGER/JLink/JLinkGDBServerCLExe" + +############################### +# WSL # +# Uncomment to override # +############################### +#export SerialPort="/dev/ttyS4" +#export DebuggerPath="/usr/bin/gdb" +#export JLinkServerPath="/mnt/c/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe" + +############################### +# ProxSpace # +# Uncomment to override # +############################### +#export SerialPort="COM5" +#export DebuggerPath="${workspaceFolder}/../../msys2/mingw64/bin/gdb.exe" +#export JLinkServerPath="c/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe" + +#Debugging on 256KB systems is not recommended +#This option does not override PLATFORM_SIZE +export DeviceMem="512" + + +VSCODEPATH=$(dirname "$0") + +function get_serial_port { + if [ -z "$SerialPort" ]; then + pm3list=$($VSCODEPATH/../pm3 --list 2>/dev/null) + #Use first port listed + SerialPort=$(echo $pm3list | head -n 1 | cut -c 4-) + if [ -z "$SerialPort" ]; then + echo >&2 "[!!] No serial port found, please set SerialPort manually" + exit 1 + fi + fi + + echo "Using $SerialPort as port" +} + + +HOSTOS=$(uname | awk '{print toupper($0)}') +if [ "$HOSTOS" = "LINUX" ]; then + if uname -a|grep -q Microsoft; then + echo "WSL" + else + echo "LINUX" + fi +elif [ "$HOSTOS" = "DARWIN" ]; then + echo >&2 "[!!] MacOS not supported, sorry!" + exit 1 +elif [[ "$HOSTOS" =~ MINGW(32|64)_NT* ]]; then + echo "ProxSpace" +else + echo >&2 "[!!] Host OS not recognized, abort: $HOSTOS" + exit 1 +fi + +get_serial_port \ No newline at end of file diff --git a/pm3 b/pm3 index 0d3b9863a..1ee2ebeb8 100755 --- a/pm3 +++ b/pm3 @@ -14,27 +14,32 @@ PM3PATH=$(dirname "$0") EVALENV="" FULLIMAGE="fullimage.elf" BOOTIMAGE="bootrom.elf" -# try pm3 dirs in current repo workdir -if [ -d "$PM3PATH/client/" ]; then - if [ -x "$PM3PATH/client/proxmark3" ]; then - CLIENT="$PM3PATH/client/proxmark3" - elif [ -x "$PM3PATH/client/build/proxmark3" ]; then - CLIENT="$PM3PATH/client/build/proxmark3" - else - echo >&2 "[!!] In devel workdir but no executable found, did you compile it?" - exit 1 - fi - # Devel mode: point to workdir pm3.py module - EVALENV+=" PYTHONPATH=$PM3PATH/client/src" -# try install dir -elif [ -x "$PM3PATH/proxmark3" ]; then - CLIENT="$PM3PATH/proxmark3" - EVALENV+=" PYTHONPATH=$PM3PATH/../share/proxmark3/pyscripts/" - # or /usr/[local/]lib/python3/dist-packages/pm3.py ? -else -# hope it's installed somehow, still not sure where fw images and pm3.py are... - CLIENT="proxmark3" + +#Skip check if --list is used +if [ ! "$1" == "--list" ]; then + # try pm3 dirs in current repo workdir + if [ -d "$PM3PATH/client/" ]; then + if [ -x "$PM3PATH/client/proxmark3" ]; then + CLIENT="$PM3PATH/client/proxmark3" + elif [ -x "$PM3PATH/client/build/proxmark3" ]; then + CLIENT="$PM3PATH/client/build/proxmark3" + else + echo >&2 "[!!] In devel workdir but no executable found, did you compile it?" + exit 1 + fi + # Devel mode: point to workdir pm3.py module + EVALENV+=" PYTHONPATH=$PM3PATH/client/src" + # try install dir + elif [ -x "$PM3PATH/proxmark3" ]; then + CLIENT="$PM3PATH/proxmark3" + EVALENV+=" PYTHONPATH=$PM3PATH/../share/proxmark3/pyscripts/" + # or /usr/[local/]lib/python3/dist-packages/pm3.py ? + else + # hope it's installed somehow, still not sure where fw images and pm3.py are... + CLIENT="proxmark3" + fi fi + # LeakSanitizer suppressions if [ -e .lsan_suppressions ]; then EVALENV+=" LSAN_OPTIONS=suppressions=.lsan_suppressions" From 71ac6369d8661bb8c9903638b94545ea11eba3b9 Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 29 Dec 2020 18:42:29 +0300 Subject: [PATCH 037/173] emrtd: Account for hash algo quirks --- client/src/cmdhfemrtd.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index e563ac7fa..4ed1732b4 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -111,7 +111,7 @@ static emrtd_dg_t dg_table[] = { // https://tools.ietf.org/html/rfc3447#page-43 static emrtd_hashalg_t hashalg_table[] = { // name hash func len len descriptor - {"SHA-1", sha1hash, 20, 9, {0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00}}, + {"SHA-1", sha1hash, 20, 7, {0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A}}, {"SHA-256", sha256hash, 32, 11, {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01}}, {"SHA-512", sha512hash, 64, 11, {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03}}, {NULL, NULL, 0, 0, {}} @@ -1551,6 +1551,12 @@ static int emrtd_parse_ef_sod_hash_algo(uint8_t *data, size_t datalen, int *hash PrintAndLogEx(DEBUG, "hash algo set: %s", sprint_hex_inrow(hashalgoset, hashalgosetlen)); + // If last two bytes are 05 00, ignore them. + // https://wf.lavatech.top/ave-but-random/emrtd-data-quirks#EF_SOD + if (hashalgoset[hashalgosetlen - 2] == 0x05 && hashalgoset[hashalgosetlen - 1] == 0x00) { + hashalgosetlen -= 2; + } + for (int hashi = 0; hashalg_table[hashi].name != NULL; hashi++) { PrintAndLogEx(DEBUG, "trying: %s", hashalg_table[hashi].name); // We're only interested in checking if the length matches to avoid memory shenanigans @@ -1565,8 +1571,9 @@ static int emrtd_parse_ef_sod_hash_algo(uint8_t *data, size_t datalen, int *hash } } - // Return hash algo 0 if we can't find anything + // Return hash algo -1 if we can't find anything *hashalgo = -1; + PrintAndLogEx(ERR, "Failed to parse hash list (Unknown algo: %s). Hash verification won't be available.", sprint_hex_inrow(hashalgoset, hashalgosetlen)); return PM3_ESOFT; } @@ -1591,9 +1598,7 @@ static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *has PrintAndLogEx(DEBUG, "hash data: %s", sprint_hex_inrow(emrtdsig, emrtdsiglen)); - if (emrtd_parse_ef_sod_hash_algo(emrtdsig, emrtdsiglen, hashalgo) != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Failed to parse hash list (Unknown algo?). Hash verification won't be available."); - } + emrtd_parse_ef_sod_hash_algo(emrtdsig, emrtdsiglen, hashalgo); if (!emrtd_lds_get_data_by_tag(emrtdsig, emrtdsiglen, hashlist, &hashlistlen, 0x30, 0x00, false, true, 1)) { PrintAndLogEx(ERR, "Failed to read hash list from EF_SOD."); From d1ec96ed41a55e80fac58a75cbbb54cca66ac4f6 Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 29 Dec 2020 19:13:10 +0300 Subject: [PATCH 038/173] emrtd: Ensure that emrtd_parse_ef_sod_hash_algo returns -1 on errors too --- client/src/cmdhfemrtd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 4ed1732b4..6b966cfad 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1544,6 +1544,9 @@ static int emrtd_parse_ef_sod_hash_algo(uint8_t *data, size_t datalen, int *hash uint8_t hashalgoset[64] = { 0x00 }; size_t hashalgosetlen = 0; + // We'll return hash algo -1 if we can't find anything + *hashalgo = -1; + if (!emrtd_lds_get_data_by_tag(data, datalen, hashalgoset, &hashalgosetlen, 0x30, 0x00, false, true, 0)) { PrintAndLogEx(ERR, "Failed to read hash algo set from EF_SOD."); return false; @@ -1571,8 +1574,6 @@ static int emrtd_parse_ef_sod_hash_algo(uint8_t *data, size_t datalen, int *hash } } - // Return hash algo -1 if we can't find anything - *hashalgo = -1; PrintAndLogEx(ERR, "Failed to parse hash list (Unknown algo: %s). Hash verification won't be available.", sprint_hex_inrow(hashalgoset, hashalgosetlen)); return PM3_ESOFT; } From 5f5e8758ab44d9a20bf2d42bcb6233ba24f501f0 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 17:22:09 +0100 Subject: [PATCH 039/173] Setup for WSL/Linux done --- .gitignore | 5 +- .vscode/setup.sh | 81 ++++++++++++++++++++--- .vscode/{ => templates}/launch_linux.json | 0 .vscode/{ => templates}/launch_ps.json | 0 .vscode/{ => templates}/launch_wsl.json | 0 .vscode/{ => templates}/tasks_linux.json | 0 .vscode/{ => templates}/tasks_ps.json | 0 .vscode/{ => templates}/tasks_wsl.json | 0 8 files changed, 75 insertions(+), 11 deletions(-) rename .vscode/{ => templates}/launch_linux.json (100%) rename .vscode/{ => templates}/launch_ps.json (100%) rename .vscode/{ => templates}/launch_wsl.json (100%) rename .vscode/{ => templates}/tasks_linux.json (100%) rename .vscode/{ => templates}/tasks_ps.json (100%) rename .vscode/{ => templates}/tasks_wsl.json (100%) diff --git a/.gitignore b/.gitignore index 1b27c52a3..125dc536e 100644 --- a/.gitignore +++ b/.gitignore @@ -110,6 +110,5 @@ fpga_version_info.c *.tmp #VSCode files -!.vscode/*.json -.vscode/launch.json -.vscode/tasks.json \ No newline at end of file +!.vscode/templates/*.json +!.vscode/extensions.json \ No newline at end of file diff --git a/.vscode/setup.sh b/.vscode/setup.sh index ee8476d11..93f7144f2 100644 --- a/.vscode/setup.sh +++ b/.vscode/setup.sh @@ -30,7 +30,7 @@ export DeviceMem="512" VSCODEPATH=$(dirname "$0") -function get_serial_port { +function setup_serial_port { if [ -z "$SerialPort" ]; then pm3list=$($VSCODEPATH/../pm3 --list 2>/dev/null) #Use first port listed @@ -40,26 +40,91 @@ function get_serial_port { exit 1 fi fi - echo "Using $SerialPort as port" } +function setup_gdb_linux { + if [ -z "$DebuggerPath" ]; then + export DebuggerPath="/usr/bin/gdb" + fi + if [ ! -x "$DebuggerPath" ]; then + echo >&2 "[!!] gdb not found, please set DebuggerPath manually" + exit 1 + fi +} + +function setup_jlink_linux { + if [ -z "$JLinkServerPath" ]; then + export JLinkServerPath="/opt/SEGGER/JLink/JLinkGDBServerCLExe" + fi + if [ ! -x "$JLinkServerPath" ]; then + echo >&2 "[!!] JLinkGDBServerCLExe not found, please set JLinkServerPath manually" + exit 1 + fi + +} + +function setup_jlink_wsl { + if [ -z "$JLinkServerPath" ]; then + export JLinkServerPath="/mnt/c/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe" + fi + if [ ! -x "$JLinkServerPath" ]; then + echo >&2 "[!!] JLinkGDBServerCLExe not found, please set JLinkServerPath manually" + exit 1 + fi +} + +function setup_wsl { + setup_serial_port + setup_gdb_linux + setup_jlink_wsl + cp "$VSCODEPATH/templates/tasks_wsl.json" "$VSCODEPATH/tasks.json" + envsubst <"$VSCODEPATH/templates/launch_wsl.json" > "$VSCODEPATH/launch.json" +} + +function setup_linux { + setup_serial_port + setup_gdb_linux + setup_jlink_linux + cp "$VSCODEPATH/templates/tasks_linux.json" "$VSCODEPATH/tasks.json" + envsubst <"$VSCODEPATH/templates/launch_linux.json" > "$VSCODEPATH/launch.json" +} + +function setup_ps { + setup_serial_port + if [ -z "$JLinkServerPath" ]; then + export JLinkServerPath="c/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe" + fi +} + +if [ -f "$VSCODEPATH/launch.json" ] || [ -f "$VSCODEPATH/tasks.json" ]; then + read -p "Existing configuration found, do you want to override it? " -n 1 -r + if [[ $REPLY =~ ^[Yy]$ ]] + then + rm "$VSCODEPATH/launch.json.bak" 2> /dev/null + rm "$VSCODEPATH/tasks.json.bak" 2> /dev/null + mv "$VSCODEPATH/launch.json" "$VSCODEPATH/launch.json.bak" 2> /dev/null + mv "$VSCODEPATH/tasks.json" "$VSCODEPATH/tasks.json.bak" 2> /dev/null + else + echo >&2 "[!!] user abort" + exit 1 + fi + +fi HOSTOS=$(uname | awk '{print toupper($0)}') if [ "$HOSTOS" = "LINUX" ]; then if uname -a|grep -q Microsoft; then - echo "WSL" + setup_wsl else - echo "LINUX" + setup_linux fi elif [ "$HOSTOS" = "DARWIN" ]; then echo >&2 "[!!] MacOS not supported, sorry!" exit 1 elif [[ "$HOSTOS" =~ MINGW(32|64)_NT* ]]; then - echo "ProxSpace" + setup_ps else echo >&2 "[!!] Host OS not recognized, abort: $HOSTOS" exit 1 -fi - -get_serial_port \ No newline at end of file +fi \ No newline at end of file diff --git a/.vscode/launch_linux.json b/.vscode/templates/launch_linux.json similarity index 100% rename from .vscode/launch_linux.json rename to .vscode/templates/launch_linux.json diff --git a/.vscode/launch_ps.json b/.vscode/templates/launch_ps.json similarity index 100% rename from .vscode/launch_ps.json rename to .vscode/templates/launch_ps.json diff --git a/.vscode/launch_wsl.json b/.vscode/templates/launch_wsl.json similarity index 100% rename from .vscode/launch_wsl.json rename to .vscode/templates/launch_wsl.json diff --git a/.vscode/tasks_linux.json b/.vscode/templates/tasks_linux.json similarity index 100% rename from .vscode/tasks_linux.json rename to .vscode/templates/tasks_linux.json diff --git a/.vscode/tasks_ps.json b/.vscode/templates/tasks_ps.json similarity index 100% rename from .vscode/tasks_ps.json rename to .vscode/templates/tasks_ps.json diff --git a/.vscode/tasks_wsl.json b/.vscode/templates/tasks_wsl.json similarity index 100% rename from .vscode/tasks_wsl.json rename to .vscode/templates/tasks_wsl.json From a14b5f7b5fbde1aec5c5359ded808fd056d5c38a Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 29 Dec 2020 19:24:44 +0300 Subject: [PATCH 040/173] emrtd: Employ a workaround for data length of 0x80 This is to make US passport hashes read properly. https://wf.lavatech.top/ave-but-random/emrtd-data-quirks#EF_SOD --- client/src/cmdhfemrtd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 6b966cfad..fa9c936e9 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -217,6 +217,11 @@ static int emrtd_get_asn1_data_length(uint8_t *datain, int datainlen, int offset PrintAndLogEx(DEBUG, "asn1 datalength, lenfield: %02X", lenfield); if (lenfield <= 0x7f) { return lenfield; + } else if (lenfield == 0x80) { + // TODO: 0x80 means indeterminate. + // Giving rest of the file is a workaround, nothing more, nothing less. + // More at https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/ + return datainlen; } else if (lenfield == 0x81) { return ((int) * (datain + offset + 1)); } else if (lenfield == 0x82) { @@ -231,7 +236,7 @@ static int emrtd_get_asn1_field_length(uint8_t *datain, int datainlen, int offse PrintAndLogEx(DEBUG, "asn1 fieldlength, datain: %s", sprint_hex_inrow(datain, datainlen)); int lenfield = (int) * (datain + offset); PrintAndLogEx(DEBUG, "asn1 fieldlength, lenfield: %02X", lenfield); - if (lenfield <= 0x7F) { + if (lenfield <= 0x80) { return 1; } else if (lenfield == 0x81) { return 2; From f3f47a66e965276f3df44ae4d18c41d7ef27225e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 29 Dec 2020 17:25:48 +0100 Subject: [PATCH 041/173] hf mfu info - now supports cliparser, fixed magic detection output, fixed ntag counter output --- client/src/cmdhfmfu.c | 303 ++++++++++++++++++++++++++---------------- client/src/cmdhfmfu.h | 3 + 2 files changed, 188 insertions(+), 118 deletions(-) diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index c69de053b..639429fba 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -13,6 +13,7 @@ #include "commonutil.h" #include "crypto/libpcrypto.h" #include "des.h" +#include "aes.h" #include "cmdhfmf.h" #include "cmdhf14a.h" #include "comms.h" @@ -23,7 +24,6 @@ #include "cliparser.h" #include "cmdmain.h" - #define MAX_UL_BLOCKS 0x0F #define MAX_ULC_BLOCKS 0x2F #define MAX_ULEV1a_BLOCKS 0x13 @@ -42,26 +42,6 @@ static int CmdHelp(const char *Cmd); -static int usage_hf_mfu_info(void) { - PrintAndLogEx(NORMAL, "It gathers information about the tag and tries to detect what kind it is."); - PrintAndLogEx(NORMAL, "Sometimes the tags are locked down, and you may need a key to be able to read the information"); - PrintAndLogEx(NORMAL, "The following tags can be identified:\n"); - PrintAndLogEx(NORMAL, "Ultralight, Ultralight-C, Ultralight EV1, NTAG 203, NTAG 210,"); - PrintAndLogEx(NORMAL, "NTAG 212, NTAG 213, NTAG 215, NTAG 216, NTAG I2C 1K & 2K"); - PrintAndLogEx(NORMAL, "my-d, my-d NFC, my-d move, my-d move NFC\n"); - PrintAndLogEx(NORMAL, "Usage: hf mfu info k l"); - PrintAndLogEx(NORMAL, " Options : "); - PrintAndLogEx(NORMAL, " k : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); - PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu info")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu info k 00112233445566778899AABBCCDDEEFF")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu info k AABBCCDD")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} - static int usage_hf_mfu_dump(void) { PrintAndLogEx(NORMAL, "Reads all pages from Ultralight, Ultralight-C, Ultralight EV1"); PrintAndLogEx(NORMAL, "NTAG 203, NTAG 210, NTAG 212, NTAG 213, NTAG 215, NTAG 216"); @@ -684,62 +664,80 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces) { if (spaces > 10) spaces = 10; + + char typestr[100]; + memset(typestr, 0x00, sizeof(typestr)); + if (tagtype & UL) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("MIFARE Ultralight (MF0ICU1) %s"), spaces, "", (tagtype & MAGIC) ? "" : ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight (MF0ICU1)s"), spaces, ""); else if (tagtype & UL_C) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("MIFARE Ultralight C (MF0ULC) %s"), spaces, "", (tagtype & MAGIC) ? "" : ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight C (MF0ULC)"), spaces, ""); else if (tagtype & UL_NANO_40) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("MIFARE Ultralight Nano 40bytes (MF0UNH00)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight Nano 40bytes (MF0UNH00)"), spaces, ""); else if (tagtype & UL_EV1_48) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 48bytes (MF0UL1101)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 48bytes (MF0UL1101)"), spaces, ""); else if (tagtype & UL_EV1_128) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 128bytes (MF0UL2101)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 128bytes (MF0UL2101)"), spaces, ""); else if (tagtype & UL_EV1) - PrintAndLogEx(NORMAL, "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 UNKNOWN"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 UNKNOWN"), spaces, ""); else if (tagtype & NTAG) - PrintAndLogEx(NORMAL, "%*sTYPE: " _YELLOW_("NTAG UNKNOWN"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG UNKNOWN"), spaces, ""); else if (tagtype & NTAG_203) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 203 144bytes (NT2H0301F0DT)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 203 144bytes (NT2H0301F0DT)"), spaces, ""); else if (tagtype & NTAG_210) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 210 48bytes (NT2L1011G0DU)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 210 48bytes (NT2L1011G0DU)"), spaces, ""); else if (tagtype & NTAG_212) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 212 128bytes (NT2L1211G0DU)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 212 128bytes (NT2L1211G0DU)"), spaces, ""); else if (tagtype & NTAG_213) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 213 144bytes (NT2H1311G0DU)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 213 144bytes (NT2H1311G0DU)"), spaces, ""); else if (tagtype & NTAG_213_F) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 213F 144bytes (NT2H1311F0DTL)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 213F 144bytes (NT2H1311F0DTL)"), spaces, ""); else if (tagtype & NTAG_213_C) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 213C 144bytes (NT2H1311C1DTL)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 213C 144bytes (NT2H1311C1DTL)"), spaces, ""); else if (tagtype & NTAG_213_TT) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 213TT 144bytes (NT2H1311TTDU)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 213TT 144bytes (NT2H1311TTDU)"), spaces, ""); else if (tagtype & NTAG_215) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 215 504bytes (NT2H1511G0DU)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 215 504bytes (NT2H1511G0DU)"), spaces, ""); else if (tagtype & NTAG_216) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 216 888bytes (NT2H1611G0DU)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 216 888bytes (NT2H1611G0DU)"), spaces, ""); else if (tagtype & NTAG_216_F) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 216F 888bytes (NT2H1611F0DTL)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 216F 888bytes (NT2H1611F0DTL)"), spaces, ""); else if (tagtype & NTAG_I2C_1K) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG I2C 888bytes (NT3H1101FHK)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG I2C 888bytes (NT3H1101FHK)"), spaces, ""); else if (tagtype & NTAG_I2C_2K) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG I2C 1904bytes (NT3H1201FHK)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG I2C 1904bytes (NT3H1201FHK)"), spaces, ""); else if (tagtype & NTAG_I2C_1K_PLUS) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG I2C plus 888bytes (NT3H2111FHK)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG I2C plus 888bytes (NT3H2111FHK)"), spaces, ""); else if (tagtype & NTAG_I2C_2K_PLUS) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG I2C plus 1912bytes (NT3H2211FHK)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG I2C plus 1912bytes (NT3H2211FHK)"), spaces, ""); else if (tagtype & MY_D) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 (SLE 66RxxS)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 (SLE 66RxxS)"), spaces, ""); else if (tagtype & MY_D_NFC) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 NFC (SLE 66RxxP)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 NFC (SLE 66RxxP)"), spaces, ""); else if (tagtype & MY_D_MOVE) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move (SLE 66R01P)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move (SLE 66R01P)"), spaces, ""); else if (tagtype & MY_D_MOVE_NFC) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move NFC (SLE 66R01P)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move NFC (SLE 66R01P)"), spaces, ""); else if (tagtype & MY_D_MOVE_LEAN) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move lean (SLE 66R01L)"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move lean (SLE 66R01L)"), spaces, ""); else if (tagtype & FUDAN_UL) - PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("FUDAN Ultralight Compatible (or other compatible) %s"), spaces, "", (tagtype & MAGIC) ? "" : ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("FUDAN Ultralight Compatible (or other compatible)"), spaces, ""); else - PrintAndLogEx(NORMAL, "%*sTYPE: " _YELLOW_("Unknown %06x"), spaces, "", tagtype); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("Unknown %06x"), spaces, "", tagtype); + + bool ismagic = ((tagtype & MAGIC) == MAGIC); + if (ismagic) + snprintf(typestr + strlen(typestr), 4, " ("); + + snprintf(typestr + strlen(typestr) , sizeof(typestr) - strlen(typestr), " %s ", (tagtype & MAGIC) ? _GREEN_("magic") : ""); + tagtype ^= MAGIC; + snprintf(typestr + strlen(typestr) , sizeof(typestr) - strlen(typestr), "%s", (tagtype & MAGIC_1A) ? _GREEN_("Gen 1a") : ""); + snprintf(typestr + strlen(typestr) , sizeof(typestr) - strlen(typestr), "%s", (tagtype & MAGIC_1B) ? _GREEN_("Gen 1b") : ""); + + if (ismagic) + snprintf(typestr + strlen(typestr), 4, " )"); + + PrintAndLogEx(SUCCESS, "%s", typestr); return PM3_SUCCESS; } @@ -895,7 +893,10 @@ static int ulev1_print_counters(void) { len = ulev1_readCounter(i, counter, sizeof(counter)); if (len == 3) { PrintAndLogEx(INFO, " [%0d]: %s", i, sprint_hex(counter, 3)); - PrintAndLogEx(SUCCESS, " - %02X tearing (%s)", tear[0], (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("failure")); + PrintAndLogEx(SUCCESS, " - %02X tearing (%s)" + , tear[0] + , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail") + ); } } return len; @@ -983,7 +984,7 @@ static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *sig if (is_valid == false || i == ARRAYLEN(nxp_mfu_public_keys)) { PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1"); PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len)); - PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed")); + PrintAndLogEx(SUCCESS, " Signature verification (" _RED_("fail") ")"); return PM3_ESOFT; } @@ -991,7 +992,7 @@ static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *sig PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfu_public_keys[i].value); PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1"); PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len)); - PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful")); + PrintAndLogEx(SUCCESS, " Signature verification (" _GREEN_("successful") ")" ); return PM3_SUCCESS; } @@ -1021,7 +1022,10 @@ static int ntag_print_counter(void) { len = ulev1_readCounter(0x02, counter, sizeof(counter)); (void)len; PrintAndLogEx(INFO, " [02]: %s", sprint_hex(counter, 3)); - PrintAndLogEx(SUCCESS, " - %02X tearing (" _GREEN_("%s")")", tear[0], (tear[0] == 0xBD) ? "ok" : "failure"); + PrintAndLogEx(SUCCESS, " - %02X tearing (%s)" + , tear[0] + , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail") + ); return len; } @@ -1057,12 +1061,34 @@ static int ul_magic_test(void) { // 2) make a wrong length write to page0, and see if tag answers with ACK/NACK: iso14a_card_select_t card; - if (!ul_select(&card)) + if (ul_select(&card) == false) return UL_ERROR; + int status = ul_comp_write(0, NULL, 0); DropField(); if (status == 0) return MAGIC; + + // check for GEN1A, GEN1B and NTAG21x + uint8_t is_generation = 0; + PacketResponseNG resp; + clearCommandBuffer(); + uint8_t payload[] = { 0 }; + SendCommandNG(CMD_HF_MIFARE_CIDENT, payload, sizeof(payload)); + if (WaitForResponseTimeout(CMD_HF_MIFARE_CIDENT, &resp, 1500)) { + if (resp.status == PM3_SUCCESS) + is_generation = resp.data.asBytes[0]; + } + switch (is_generation) { + case MAGIC_GEN_1A: + return MAGIC_1A; + case MAGIC_GEN_1B: + return MAGIC_1B; + case MAGIC_NTAG21X: + return MAGIC_NTAG; + default: + break; + } return 0; } @@ -1071,7 +1097,8 @@ uint32_t GetHF14AMfU_Type(void) { TagTypeUL_t tagtype = UNKNOWN; iso14a_card_select_t card; - if (!ul_select(&card)) return UL_ERROR; + if (ul_select(&card) == false) + return UL_ERROR; // Ultralight - ATQA / SAK if (card.atqa[1] != 0x00 || card.atqa[0] != 0x44 || card.sak != 0x00) { @@ -1177,7 +1204,8 @@ uint32_t GetHF14AMfU_Type(void) { tagtype = UL_C; } else { // need to re-select after authentication error - if (!ul_select(&card)) return UL_ERROR; + if (ul_select(&card) == false) + return UL_ERROR; uint8_t data[16] = {0x00}; // read page 0x26-0x29 (last valid ntag203 page) @@ -1222,7 +1250,9 @@ uint32_t GetHF14AMfU_Type(void) { } tagtype |= ul_magic_test(); - if (tagtype == (UNKNOWN | MAGIC)) tagtype = (UL_MAGIC); + if (tagtype == (UNKNOWN | MAGIC)) { + tagtype = (UL_MAGIC); + } return tagtype; } // @@ -1230,56 +1260,53 @@ uint32_t GetHF14AMfU_Type(void) { // static int CmdHF14AMfUInfo(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfu info", + "Get info about MIFARE Ultralight Family styled tag.\n" + "Sometimes the tags are locked down, and you may need a key to be able to read the information", + "hf mfu info\n" + "hf mfu info k AABBCCDD\n" + "hf mfu info k 00112233445566778899AABBCCDDEEFF" + ); + + void *argtable[] = { + arg_param_begin, + arg_str0("k", "key", "", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"), + arg_lit0("l", NULL, "swap entered key's endianness"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int ak_len = 0; + uint8_t authenticationkey[16] = {0x00}; + CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len); + bool swap_endian = arg_get_lit(ctx, 2); + CLIParserFree(ctx); + + if (ak_len) { + if (ak_len != 16 || ak_len != 8) { + PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); + return PM3_EINVARG; + } + } + + bool has_auth_key = false; + if (ak_len > 0) + has_auth_key = true; + uint8_t authlim = 0xff; uint8_t data[16] = {0x00}; iso14a_card_select_t card; int status; - bool errors = false; - bool hasAuthKey = false; - bool locked = false; - bool swapEndian = false; - uint8_t cmdp = 0; - uint8_t dataLen = 0; - uint8_t authenticationkey[16] = {0x00}; uint8_t *authkeyptr = authenticationkey; uint8_t pwd[4] = {0, 0, 0, 0}; uint8_t *key = pwd; uint8_t pack[4] = {0, 0, 0, 0}; int len; - char tempStr[50]; - - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_mfu_info(); - case 'k': - dataLen = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr)); - if (dataLen == 32 || dataLen == 8) { //ul-c or ev1/ntag key length - errors = param_gethex(tempStr, 0, authenticationkey, dataLen); - dataLen /= 2; // handled as bytes from now on - } else { - PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); - errors = true; - } - cmdp += 2; - hasAuthKey = true; - break; - case 'l': - swapEndian = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter: " _RED_("'%c'"), param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors) return usage_hf_mfu_info(); - TagTypeUL_t tagtype = GetHF14AMfU_Type(); - if (tagtype == UL_ERROR) return PM3_ESOFT; + if (tagtype == UL_ERROR) + return PM3_ESOFT; PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " --------------------------"); @@ -1287,10 +1314,15 @@ static int CmdHF14AMfUInfo(const char *Cmd) { ul_print_type(tagtype, 6); // Swap endianness - if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4); + if (swap_endian && has_auth_key) { + authkeyptr = SwapEndian64(authenticationkey, ak_len, (ak_len == 16) ? 8 : 4); + } - if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; + if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) { + return PM3_ESOFT; + } + bool locked = false; // read pages 0,1,2,3 (should read 4pages) status = ul_read(0, data, sizeof(data)); if (status == -1) { @@ -1329,12 +1361,16 @@ static int CmdHF14AMfUInfo(const char *Cmd) { PrintAndLogEx(ERR, "Error: tag didn't answer to READ magic"); return PM3_ESOFT; } - if (status == 16) ulc_print_3deskey(ulc_deskey); + if (status == 16) { + ulc_print_3deskey(ulc_deskey); + } } else { DropField(); // if we called info with key, just return - if (hasAuthKey) return PM3_SUCCESS; + if (has_auth_key) { + return PM3_SUCCESS; + } // also try to diversify default keys.. look into CmdHF14AMfGenDiverseKeys if (try_default_3des_keys(&key)) { @@ -1353,7 +1389,9 @@ static int CmdHF14AMfUInfo(const char *Cmd) { if ((tagtype & (UL_EV1_48 | UL_EV1_128 | UL_EV1))) { if (ulev1_print_counters() != 3) { // failed - re-select - if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; + if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) { + return PM3_ESOFT; + } } } @@ -1361,7 +1399,9 @@ static int CmdHF14AMfUInfo(const char *Cmd) { if ((tagtype & (NTAG_213 | NTAG_213_F | NTAG_213_C | NTAG_213_TT | NTAG_215 | NTAG_216))) { if (ntag_print_counter()) { // failed - re-select - if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; + if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) { + return PM3_ESOFT; + } } } @@ -1378,7 +1418,9 @@ static int CmdHF14AMfUInfo(const char *Cmd) { ulev1_print_signature(tagtype, card.uid, ulev1_signature, sizeof(ulev1_signature)); } else { // re-select - if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; + if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) { + return PM3_ESOFT; + } } // Get Version @@ -1392,7 +1434,9 @@ static int CmdHF14AMfUInfo(const char *Cmd) { ulev1_print_version(version); } else { locked = true; - if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; + if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) { + return PM3_ESOFT; + } } uint8_t startconfigblock = 0; @@ -1416,7 +1460,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { // save AUTHENTICATION LIMITS for later: authlim = (ulev1_conf[4] & 0x07); // add pwd / pack if used from cli - if (hasAuthKey) { + if (has_auth_key) { memcpy(ulev1_conf + 8, authkeyptr, 4); memcpy(ulev1_conf + 12, pack, 2); } @@ -1428,57 +1472,67 @@ static int CmdHF14AMfUInfo(const char *Cmd) { // 0 = limitless. // 1-7 = limit. No automatic tries then. // hasAuthKey, if we was called with key, skip test. - if (!authlim && !hasAuthKey) { + if (!authlim && !has_auth_key) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, "--- " _CYAN_("Known EV1/NTAG passwords")); // test pwd gen A num_to_bytes(ul_ev1_pwdgenA(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") "|| Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); goto out; } - if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; + if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) { + return PM3_ESOFT; + } // test pwd gen B num_to_bytes(ul_ev1_pwdgenB(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " || Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); goto out; } - if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; + if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) { + return PM3_ESOFT; + } // test pwd gen C num_to_bytes(ul_ev1_pwdgenC(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " || Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); goto out; } - if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; + if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) { + return PM3_ESOFT; + } // test pwd gen D num_to_bytes(ul_ev1_pwdgenD(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(SUCCESS, "Found a default password:" _GREEN_("%s") " || Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found a default password:" _GREEN_("%s") " Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); goto out; } - if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; + if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) { + return PM3_ESOFT; + } for (uint8_t i = 0; i < ARRAYLEN(default_pwd_pack); ++i) { key = default_pwd_pack[i]; len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " || Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); break; } else { - if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; + if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) { + return PM3_ESOFT; + } } } if (len < 1) { @@ -1492,7 +1546,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { out: DropField(); if (locked) { - PrintAndLogEx(INFO, "\nTag appears to be locked, try using the key to get more info"); + PrintAndLogEx(INFO, "\nTag appears to be locked, try using a key to get more info"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu pwdgen r`") " to get see known pwd gen algo suggestions"); } PrintAndLogEx(NORMAL, ""); @@ -2709,7 +2763,6 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { uint8_t dkeyB[8] = { 0x00 }; uint8_t masterkey[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; - uint8_t mix[8] = { 0x00 }; uint8_t divkey[8] = { 0x00 }; @@ -2774,6 +2827,20 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { PrintAndLogEx(SUCCESS, "Mifare Pwd :\t %s", sprint_hex(newpwd, sizeof(newpwd))); mbedtls_des3_free(&ctx); + + mbedtls_aes_context ctx_aes; + uint8_t aes_iv[16] = { 0x00 }; + uint8_t aes_masterkey[] = { 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }; + uint8_t aes_input[16] = {0x01, 0x04, 0x2A, 0x2E, 0x19, 0x70, 0x1C, 0x80, 0x01, 0x04, 0x2A, 0x2E, 0x19, 0x70, 0x1C, 0x80}; + uint8_t aes_output[16] = {0x00}; + mbedtls_aes_setkey_enc(&ctx_aes, aes_masterkey, 128); + mbedtls_aes_crypt_cbc(&ctx_aes, MBEDTLS_AES_ENCRYPT, 16, aes_iv, aes_input, aes_output); + mbedtls_aes_free(&ctx_aes); + + PrintAndLogEx(SUCCESS, "\n-- AES version"); + PrintAndLogEx(SUCCESS, "Mifare AES m :\t %s", sprint_hex(aes_masterkey, sizeof(aes_masterkey))); + PrintAndLogEx(SUCCESS, "Mifare Div :\t %s", sprint_hex(aes_output, sizeof(aes_output))); + // next. from the diversify_key method. return PM3_SUCCESS; } diff --git a/client/src/cmdhfmfu.h b/client/src/cmdhfmfu.h index d59389434..e3eae9e79 100644 --- a/client/src/cmdhfmfu.h +++ b/client/src/cmdhfmfu.h @@ -59,6 +59,9 @@ typedef enum TAGTYPE_UL { UL_NANO_40 = 0x2000000, NTAG_213_TT = 0x4000000, NTAG_213_C = 0x8000000, + MAGIC_1A = 0x10000000 | MAGIC, + MAGIC_1B = 0x20000000 | MAGIC, + MAGIC_NTAG = 0x40000000 | MAGIC, UL_MAGIC = UL | MAGIC, UL_C_MAGIC = UL_C | MAGIC, UL_ERROR = 0xFFFFFF, From 9c43f8e44f379dd5f244f0bbaa3a2730d8d61276 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 17:50:43 +0100 Subject: [PATCH 042/173] Updated wsl instructions --- .../Windows-Installation-Instructions.md | 39 ++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md index ea0505268..6d4477de2 100644 --- a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md @@ -149,18 +149,31 @@ Note that it may take a quite long time for a freshly plugged Proxmark3 to be vi Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). -## Color text on windows 10 -In later versions of windows 10 you may be able to get color to work by setting this registry key -``` -[HKEY_CURRENT_USER\Console] - "VirtualTerminalLevel"=dword:00000001 -``` -You also need to disable "use legacy console" in the cmd.exe properties, or set the following registry key -``` -[HKEY_CURRENT_USER\Console] - "ForceV2"=dword:00000001 -``` -After making these changes, you will need to start a new command prompt (cmd.exe) to ensure its using the new settings. -If after making these changes (and restarting proxmark3.exe) you get extra characters and no color text, set either key to 0 or enable legacy mode again (and restart the command prompt). +## (Optional) Visual Studio Code debugging +Download and install [J-Link Software and Documentation pack for Windows](https://www.segger.com/downloads/jlink/JLink_Windows.exe) + +Enter WSL prompt (`wsl` or `start windows terminal`) and from there, follow the [Linux Installation Instructions](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) for Ubuntu, summarized here below: + +Install dependencies +```sh +sudo apt-get install --no-install-recommends binutils-arm-none-eabi gdb openocd gdb-multiarch +``` + +The J-Link debugger requires `arm-none-eabi-gdb` which was replaced with `gdb-multiarch`. In order to use the J-Link debugger link `arm-none-eabi-gdb` to `gdb-multiarch`: +```sh +sudo ln -s /usr/bin/gdb-multiarch /usr/bin/arm-none-eabi-gdb +``` + +Setup the Visual Studio Code configuration, by going into your project folder and run: +```sh +./.vscode/setup.sh +``` + +and launch Visual Studio Code +```sh +code . +``` +_note_ +Please install the recommended Visual Studio Code extensions in order for debugging to work. From 800e68d9933bc084e321eed8590ef1862740bc39 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 17:54:49 +0100 Subject: [PATCH 043/173] Missing step --- .../Windows-Installation-Instructions.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md index 6d4477de2..1cf1f43c9 100644 --- a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md @@ -152,6 +152,8 @@ Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmar ## (Optional) Visual Studio Code debugging +Download and install [Visual Studio Code](https://code.visualstudio.com/) + Download and install [J-Link Software and Documentation pack for Windows](https://www.segger.com/downloads/jlink/JLink_Windows.exe) Enter WSL prompt (`wsl` or `start windows terminal`) and from there, follow the [Linux Installation Instructions](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) for Ubuntu, summarized here below: From ff4acf70059d86e0bc63a6094a719e3b8b3c06e1 Mon Sep 17 00:00:00 2001 From: Ave Date: Tue, 29 Dec 2020 20:05:50 +0300 Subject: [PATCH 044/173] emrtd: Improve comment on USA quirk workaround --- client/src/cmdhfemrtd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index fa9c936e9..670ea804d 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -218,9 +218,9 @@ static int emrtd_get_asn1_data_length(uint8_t *datain, int datainlen, int offset if (lenfield <= 0x7f) { return lenfield; } else if (lenfield == 0x80) { - // TODO: 0x80 means indeterminate. + // TODO: 0x80 means indeterminate, and this impl is a workaround. // Giving rest of the file is a workaround, nothing more, nothing less. - // More at https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/ + // https://wf.lavatech.top/ave-but-random/emrtd-data-quirks#EF_SOD return datainlen; } else if (lenfield == 0x81) { return ((int) * (datain + offset + 1)); From d1a6164a10221fd92794adf872e2d34262ab3360 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 18:08:35 +0100 Subject: [PATCH 045/173] Updated linux instructions --- .../Linux-Installation-Instructions.md | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md index 18164398a..aa5cf9042 100644 --- a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md @@ -25,13 +25,16 @@ Install the requirements ```sh sudo apt-get install --no-install-recommends git ca-certificates build-essential pkg-config \ -libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev +libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev \ +binutils-arm-none-eabi gdb openocd gdb-multiarch ``` If you don't need the native Bluetooth support in the client, you can skip the installation of `libbluetooth-dev`. If you don't need the graphical components of the Proxmark3 client (such as in `hw tune`), you can skip the installation of `qtbase5-dev`. +If you don't need the debugging packages, you can skip the installation of `binutils-arm-none-eabi`,`gdb`,`openocd` and `gdb-multiarch`. + If you get some (non blocking) error at runtime such as _Gtk-Message: Failed to load module "canberra-gtk-module"_ you may have to install `libcanberra-gtk-module`. ## On ArchLinux @@ -112,3 +115,25 @@ It must return `ok`. Otherwise this means you've got a permission problem to fix # Compile and use the project Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). + + +## (Optional) Visual Studio Code debugging + +Download and install [Visual Studio Code](https://code.visualstudio.com/) + +Download and install [J-Link Software and Documentation pack](https://www.segger.com/downloads/jlink) + +On some systems `arm-none-eabi-gdb` was replaced with `gdb-multiarch`. In order to use the J-Link debugger you need to link `arm-none-eabi-gdb` to `gdb-multiarch`: +```sh +ln -s /usr/bin/gdb-multiarch /usr/bin/arm-none-eabi-gdb +``` + +Setup the Visual Studio Code configuration, by going into your project folder and run: +```sh +./.vscode/setup.sh +``` + +now launch Visual Studio Code and open your project folder + +_note_ +Please install the recommended Visual Studio Code extensions in order for debugging to work. From c58b1043b8ca8b9dfb0a0c80ed5ac917502a4cea Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 18:15:09 +0100 Subject: [PATCH 046/173] Make setup executable --- .vscode/setup.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 .vscode/setup.sh diff --git a/.vscode/setup.sh b/.vscode/setup.sh old mode 100644 new mode 100755 From cc2b36430dece96f66d0f877ccb55f55fc328d77 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 18:26:51 +0100 Subject: [PATCH 047/173] Fixed removing all variables --- .vscode/setup.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.vscode/setup.sh b/.vscode/setup.sh index 93f7144f2..3e76e03ae 100755 --- a/.vscode/setup.sh +++ b/.vscode/setup.sh @@ -79,7 +79,7 @@ function setup_wsl { setup_gdb_linux setup_jlink_wsl cp "$VSCODEPATH/templates/tasks_wsl.json" "$VSCODEPATH/tasks.json" - envsubst <"$VSCODEPATH/templates/launch_wsl.json" > "$VSCODEPATH/launch.json" + envsubst '${SerialPort} ${DebuggerPath} ${JLinkServerPath} ${DeviceMem}' <"$VSCODEPATH/templates/launch_wsl.json" > "$VSCODEPATH/launch.json" } function setup_linux { @@ -87,7 +87,7 @@ function setup_linux { setup_gdb_linux setup_jlink_linux cp "$VSCODEPATH/templates/tasks_linux.json" "$VSCODEPATH/tasks.json" - envsubst <"$VSCODEPATH/templates/launch_linux.json" > "$VSCODEPATH/launch.json" + envsubst '${SerialPort} ${DebuggerPath} ${JLinkServerPath} ${DeviceMem}' <"$VSCODEPATH/templates/launch_linux.json" > "$VSCODEPATH/launch.json" } function setup_ps { From 7c982c7785bbfe45b6d5b783fd5b3e7e04c127fb Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 18:32:22 +0100 Subject: [PATCH 048/173] Print config --- .vscode/setup.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.vscode/setup.sh b/.vscode/setup.sh index 3e76e03ae..1cfd3b9b6 100755 --- a/.vscode/setup.sh +++ b/.vscode/setup.sh @@ -30,6 +30,13 @@ export DeviceMem="512" VSCODEPATH=$(dirname "$0") +function print_config { + echo "Updating with following configuration:" + echo "SerialPort: $SerialPort" + echo "DebuggerPath: $DebuggerPath" + echo "JLinkServerPath: $JLinkServerPath" +} + function setup_serial_port { if [ -z "$SerialPort" ]; then pm3list=$($VSCODEPATH/../pm3 --list 2>/dev/null) @@ -40,7 +47,6 @@ function setup_serial_port { exit 1 fi fi - echo "Using $SerialPort as port" } function setup_gdb_linux { @@ -78,6 +84,7 @@ function setup_wsl { setup_serial_port setup_gdb_linux setup_jlink_wsl + print_config cp "$VSCODEPATH/templates/tasks_wsl.json" "$VSCODEPATH/tasks.json" envsubst '${SerialPort} ${DebuggerPath} ${JLinkServerPath} ${DeviceMem}' <"$VSCODEPATH/templates/launch_wsl.json" > "$VSCODEPATH/launch.json" } @@ -86,6 +93,7 @@ function setup_linux { setup_serial_port setup_gdb_linux setup_jlink_linux + print_config cp "$VSCODEPATH/templates/tasks_linux.json" "$VSCODEPATH/tasks.json" envsubst '${SerialPort} ${DebuggerPath} ${JLinkServerPath} ${DeviceMem}' <"$VSCODEPATH/templates/launch_linux.json" > "$VSCODEPATH/launch.json" } @@ -95,6 +103,7 @@ function setup_ps { if [ -z "$JLinkServerPath" ]; then export JLinkServerPath="c/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe" fi + print_config } if [ -f "$VSCODEPATH/launch.json" ] || [ -f "$VSCODEPATH/tasks.json" ]; then From a103628a351f84521e82521185f8edd18e84612d Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 20:43:24 +0100 Subject: [PATCH 049/173] ProxSpace debugging --- .gitignore | 3 +- .vscode/setup.sh | 32 +++-- .vscode/tasks.json | 102 ++++++++++++++++ .vscode/templates/launch_linux.json | 2 +- .vscode/templates/launch_ps.json | 11 +- .vscode/templates/launch_wsl.json | 2 +- .vscode/templates/tasks_linux.json | 177 ---------------------------- .vscode/templates/tasks_ps.json | 177 ---------------------------- .vscode/templates/tasks_wsl.json | 177 ---------------------------- 9 files changed, 135 insertions(+), 548 deletions(-) create mode 100644 .vscode/tasks.json delete mode 100644 .vscode/templates/tasks_linux.json delete mode 100644 .vscode/templates/tasks_ps.json delete mode 100644 .vscode/templates/tasks_wsl.json diff --git a/.gitignore b/.gitignore index 125dc536e..e1f694327 100644 --- a/.gitignore +++ b/.gitignore @@ -111,4 +111,5 @@ fpga_version_info.c #VSCode files !.vscode/templates/*.json -!.vscode/extensions.json \ No newline at end of file +!.vscode/extensions.json +!.vscode/tasks.json \ No newline at end of file diff --git a/.vscode/setup.sh b/.vscode/setup.sh index 1cfd3b9b6..1dc3b5237 100755 --- a/.vscode/setup.sh +++ b/.vscode/setup.sh @@ -21,7 +21,7 @@ ############################### #export SerialPort="COM5" #export DebuggerPath="${workspaceFolder}/../../msys2/mingw64/bin/gdb.exe" -#export JLinkServerPath="c/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe" +#export JLinkServerPath="/c/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe" #Debugging on 256KB systems is not recommended #This option does not override PLATFORM_SIZE @@ -59,6 +59,12 @@ function setup_gdb_linux { fi } +function setup_gdb_ps { + if [ -z "$DebuggerPath" ]; then + export DebuggerPath="${workspaceFolder}/../../msys2/mingw64/bin/gdb.exe" + fi +} + function setup_jlink_linux { if [ -z "$JLinkServerPath" ]; then export JLinkServerPath="/opt/SEGGER/JLink/JLinkGDBServerCLExe" @@ -75,7 +81,17 @@ function setup_jlink_wsl { export JLinkServerPath="/mnt/c/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe" fi if [ ! -x "$JLinkServerPath" ]; then - echo >&2 "[!!] JLinkGDBServerCLExe not found, please set JLinkServerPath manually" + echo >&2 "[!!] JLinkGDBServerCL.exe not found, please set JLinkServerPath manually" + exit 1 + fi +} + +function setup_jlink_ps { + if [ -z "$JLinkServerPath" ]; then + export JLinkServerPath="/c/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe" + fi + if [ ! -x "$JLinkServerPath" ]; then + echo >&2 "[!!] JLinkGDBServerCL.exe not found, please set JLinkServerPath manually" exit 1 fi } @@ -85,7 +101,6 @@ function setup_wsl { setup_gdb_linux setup_jlink_wsl print_config - cp "$VSCODEPATH/templates/tasks_wsl.json" "$VSCODEPATH/tasks.json" envsubst '${SerialPort} ${DebuggerPath} ${JLinkServerPath} ${DeviceMem}' <"$VSCODEPATH/templates/launch_wsl.json" > "$VSCODEPATH/launch.json" } @@ -94,26 +109,23 @@ function setup_linux { setup_gdb_linux setup_jlink_linux print_config - cp "$VSCODEPATH/templates/tasks_linux.json" "$VSCODEPATH/tasks.json" envsubst '${SerialPort} ${DebuggerPath} ${JLinkServerPath} ${DeviceMem}' <"$VSCODEPATH/templates/launch_linux.json" > "$VSCODEPATH/launch.json" } function setup_ps { setup_serial_port - if [ -z "$JLinkServerPath" ]; then - export JLinkServerPath="c/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe" - fi + setup_gdb_ps + setup_jlink_ps print_config + envsubst '${SerialPort} ${DebuggerPath} ${JLinkServerPath} ${DeviceMem}' <"$VSCODEPATH/templates/launch_ps.json" > "$VSCODEPATH/launch.json" } -if [ -f "$VSCODEPATH/launch.json" ] || [ -f "$VSCODEPATH/tasks.json" ]; then +if [ -f "$VSCODEPATH/launch.json" ]; then read -p "Existing configuration found, do you want to override it? " -n 1 -r if [[ $REPLY =~ ^[Yy]$ ]] then rm "$VSCODEPATH/launch.json.bak" 2> /dev/null - rm "$VSCODEPATH/tasks.json.bak" 2> /dev/null mv "$VSCODEPATH/launch.json" "$VSCODEPATH/launch.json.bak" 2> /dev/null - mv "$VSCODEPATH/tasks.json" "$VSCODEPATH/tasks.json.bak" 2> /dev/null else echo >&2 "[!!] user abort" exit 1 diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..463377982 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,102 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "windows": { + "options": { + "cwd": "${workspaceFolder}", + "env": { + "PATH": "${workspaceFolder}/../../msys2/mingw64/bin;${workspaceFolder}/../../msys2/usr/local/bin;${workspaceFolder}/../../msys2/usr/bin;${workspaceFolder}/../../msys2/bin", + "MSYSTEM": "MINGW64" + } + } + }, + "tasks": [ + { + "label": "all: Make & run", + "type": "shell", + "command": "make -j && ./pm3", + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "choose: Make", + "type": "shell", + "command": "make ${input:componentType} -j", + "problemMatcher": [ + "$gcc" + ], + "group": "build", + }, + { + "label": "client: Debug: make", + "type": "shell", + "command": "make client -j DEBUG=1", + "problemMatcher": [ + "$gcc" + ], + "group": "build", + }, + { + "label": "client: Debug: clean & make", + "type": "shell", + "command": "make client/clean && make client -j DEBUG=1", + "problemMatcher": [ + "$gcc" + ], + "group": "build", + }, + { + "label": "fullimage: Make & Flash", + "type": "shell", + "command": "make fullimage && ./pm3-flash-fullimage", + "problemMatcher": [] + }, + { + "label": "BOOTROM: Make & Flash", + "type": "shell", + "command": "make bootrom && ./pm3-flash-bootrom", + "problemMatcher": [] + }, + { + "label": "Run client", + "type": "shell", + "command": "./pm3", + "problemMatcher": [] + },{ + "label": "fullimage: clean & make debug", + "type": "shell", + "command": "make armsrc/clean && make armsrc/all SKIP_COMPRESSION=1 DEBUG=1", + "problemMatcher": [ + "$gcc" + ], + "group": "build", + } + ], + "inputs": [ + { + "type": "pickString", + "id": "componentType", + "description": "What Makefile target do you want to execute?", + "options": [ + "all", + "client", + "bootrom", + "fullimage", + "recovery", + "clean", + "install", + "uninstall", + "style", + "miscchecks", + "check", + ], + "default": "all" + } + ] +} \ No newline at end of file diff --git a/.vscode/templates/launch_linux.json b/.vscode/templates/launch_linux.json index 0f60495a6..5239c6bda 100644 --- a/.vscode/templates/launch_linux.json +++ b/.vscode/templates/launch_linux.json @@ -44,7 +44,7 @@ "type": "cortex-debug", "request": "launch", "cwd": "${workspaceRoot}", - "preLaunchTask": "fullimage: clean & make", + "preLaunchTask": "fullimage: clean & make debug", "executable": "${workspaceRoot}/armsrc/obj/fullimage.elf", "serverpath": "${JLinkServerPath}", "servertype": "jlink", diff --git a/.vscode/templates/launch_ps.json b/.vscode/templates/launch_ps.json index 8794ef76e..28b724f7b 100644 --- a/.vscode/templates/launch_ps.json +++ b/.vscode/templates/launch_ps.json @@ -3,6 +3,13 @@ // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", + "options": { + "cwd": "${workspaceFolder}", + "env": { + "PATH": "${workspaceFolder}/../../msys2/mingw64/bin;${workspaceFolder}/../../msys2/usr/local/bin;${workspaceFolder}/../../msys2/usr/bin;${workspaceFolder}/../../msys2/bin", + "MSYSTEM": "MINGW64" + } + }, "configurations": [ { "name": "Client: (gdb) Build & Launch", @@ -11,10 +18,6 @@ "program": "${cwd}/client/proxmark3", "args": ["${SerialPort}"], "stopAtEntry": false, - "cwd": "${workspaceFolder}", - "environment": [ - "name": "PATH","value": "${workspaceFolder}/../../msys2/mingw64/bin;${workspaceFolder}/../../msys2/usr/local/bin;${workspaceFolder}/../../msys2/usr/bin;${workspaceFolder}/../../msys2/bin" - ], "externalConsole": true,//for ProxSpace externalConsole=true is required, because the internal cosole stops updating after a while "MIMode": "gdb", "setupCommands": [ diff --git a/.vscode/templates/launch_wsl.json b/.vscode/templates/launch_wsl.json index 0f60495a6..5239c6bda 100644 --- a/.vscode/templates/launch_wsl.json +++ b/.vscode/templates/launch_wsl.json @@ -44,7 +44,7 @@ "type": "cortex-debug", "request": "launch", "cwd": "${workspaceRoot}", - "preLaunchTask": "fullimage: clean & make", + "preLaunchTask": "fullimage: clean & make debug", "executable": "${workspaceRoot}/armsrc/obj/fullimage.elf", "serverpath": "${JLinkServerPath}", "servertype": "jlink", diff --git a/.vscode/templates/tasks_linux.json b/.vscode/templates/tasks_linux.json deleted file mode 100644 index 4cc21841d..000000000 --- a/.vscode/templates/tasks_linux.json +++ /dev/null @@ -1,177 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "tasks": [ - { - "label": "all: Make & run", - "type": "shell", - "command": "make -j && ./pm3", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [ - "$gcc" - ], - "group": { - "kind": "build", - "isDefault": true - } - }, - { - "label": "choose: Make", - "type": "shell", - "command": "make ${input:componentType} -j", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [ - "$gcc" - ], - "group": "build", - }, - { - "label": "client: Debug: make", - "type": "shell", - "command": "make client -j DEBUG=1", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [ - "$gcc" - ], - "group": "build", - }, - { - "label": "client: Debug: clean & make", - "type": "shell", - "command": "make client/clean && make client -j DEBUG=1", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [ - "$gcc" - ], - "group": "build", - }, - { - "label": "fullimage: Make & Flash", - "type": "shell", - "command": "make fullimage && ./pm3-flash-fullimage", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [] - }, - { - "label": "BOOTROM: Make & Flash", - "type": "shell", - "command": "make bootrom && ./pm3-flash-bootrom", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [] - }, - { - "label": "Run client", - "type": "shell", - "command": "./pm3", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [] - },{ - "label": "fullimage: clean & make", - "type": "shell", - "command": "make armsrc/clean && make armsrc/all SKIP_COMPRESSION=1 DEBUG=1", - "problemMatcher": [ - "$gcc" - ], - "group": "build", - } - ], - "inputs": [ - { - "type": "pickString", - "id": "componentType", - "description": "What Makefile target do you want to execute?", - "options": [ - "all", - "client", - "bootrom", - "fullimage", - "recovery", - "clean", - "install", - "uninstall", - "style", - "miscchecks", - "check", - ], - "default": "all" - } - ] -} \ No newline at end of file diff --git a/.vscode/templates/tasks_ps.json b/.vscode/templates/tasks_ps.json deleted file mode 100644 index 4cc21841d..000000000 --- a/.vscode/templates/tasks_ps.json +++ /dev/null @@ -1,177 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "tasks": [ - { - "label": "all: Make & run", - "type": "shell", - "command": "make -j && ./pm3", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [ - "$gcc" - ], - "group": { - "kind": "build", - "isDefault": true - } - }, - { - "label": "choose: Make", - "type": "shell", - "command": "make ${input:componentType} -j", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [ - "$gcc" - ], - "group": "build", - }, - { - "label": "client: Debug: make", - "type": "shell", - "command": "make client -j DEBUG=1", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [ - "$gcc" - ], - "group": "build", - }, - { - "label": "client: Debug: clean & make", - "type": "shell", - "command": "make client/clean && make client -j DEBUG=1", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [ - "$gcc" - ], - "group": "build", - }, - { - "label": "fullimage: Make & Flash", - "type": "shell", - "command": "make fullimage && ./pm3-flash-fullimage", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [] - }, - { - "label": "BOOTROM: Make & Flash", - "type": "shell", - "command": "make bootrom && ./pm3-flash-bootrom", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [] - }, - { - "label": "Run client", - "type": "shell", - "command": "./pm3", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [] - },{ - "label": "fullimage: clean & make", - "type": "shell", - "command": "make armsrc/clean && make armsrc/all SKIP_COMPRESSION=1 DEBUG=1", - "problemMatcher": [ - "$gcc" - ], - "group": "build", - } - ], - "inputs": [ - { - "type": "pickString", - "id": "componentType", - "description": "What Makefile target do you want to execute?", - "options": [ - "all", - "client", - "bootrom", - "fullimage", - "recovery", - "clean", - "install", - "uninstall", - "style", - "miscchecks", - "check", - ], - "default": "all" - } - ] -} \ No newline at end of file diff --git a/.vscode/templates/tasks_wsl.json b/.vscode/templates/tasks_wsl.json deleted file mode 100644 index 4cc21841d..000000000 --- a/.vscode/templates/tasks_wsl.json +++ /dev/null @@ -1,177 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "tasks": [ - { - "label": "all: Make & run", - "type": "shell", - "command": "make -j && ./pm3", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [ - "$gcc" - ], - "group": { - "kind": "build", - "isDefault": true - } - }, - { - "label": "choose: Make", - "type": "shell", - "command": "make ${input:componentType} -j", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [ - "$gcc" - ], - "group": "build", - }, - { - "label": "client: Debug: make", - "type": "shell", - "command": "make client -j DEBUG=1", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [ - "$gcc" - ], - "group": "build", - }, - { - "label": "client: Debug: clean & make", - "type": "shell", - "command": "make client/clean && make client -j DEBUG=1", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [ - "$gcc" - ], - "group": "build", - }, - { - "label": "fullimage: Make & Flash", - "type": "shell", - "command": "make fullimage && ./pm3-flash-fullimage", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [] - }, - { - "label": "BOOTROM: Make & Flash", - "type": "shell", - "command": "make bootrom && ./pm3-flash-bootrom", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [] - }, - { - "label": "Run client", - "type": "shell", - "command": "./pm3", - "windows": { - "options": { - "cwd": "${workspaceFolder}/../..", - "shell": { - "executable": "${workspaceFolder}/../../runme64.bat", - "args": [ - "-c \"cd ${workspaceFolderBasename} &&" - ], - - } - } - }, - "problemMatcher": [] - },{ - "label": "fullimage: clean & make", - "type": "shell", - "command": "make armsrc/clean && make armsrc/all SKIP_COMPRESSION=1 DEBUG=1", - "problemMatcher": [ - "$gcc" - ], - "group": "build", - } - ], - "inputs": [ - { - "type": "pickString", - "id": "componentType", - "description": "What Makefile target do you want to execute?", - "options": [ - "all", - "client", - "bootrom", - "fullimage", - "recovery", - "clean", - "install", - "uninstall", - "style", - "miscchecks", - "check", - ], - "default": "all" - } - ] -} \ No newline at end of file From 7357d17c8c298042f7ac05341fa71b5d300ef4e6 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 21:02:23 +0100 Subject: [PATCH 050/173] ProxSpace path fixes --- .vscode/setup.sh | 13 +++---------- .vscode/templates/launch_ps.json | 7 ++++--- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/.vscode/setup.sh b/.vscode/setup.sh index 1dc3b5237..3b652a6b8 100755 --- a/.vscode/setup.sh +++ b/.vscode/setup.sh @@ -20,8 +20,7 @@ # Uncomment to override # ############################### #export SerialPort="COM5" -#export DebuggerPath="${workspaceFolder}/../../msys2/mingw64/bin/gdb.exe" -#export JLinkServerPath="/c/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe" +#export JLinkServerPath="C:/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe" #Debugging on 256KB systems is not recommended #This option does not override PLATFORM_SIZE @@ -59,12 +58,6 @@ function setup_gdb_linux { fi } -function setup_gdb_ps { - if [ -z "$DebuggerPath" ]; then - export DebuggerPath="${workspaceFolder}/../../msys2/mingw64/bin/gdb.exe" - fi -} - function setup_jlink_linux { if [ -z "$JLinkServerPath" ]; then export JLinkServerPath="/opt/SEGGER/JLink/JLinkGDBServerCLExe" @@ -88,9 +81,9 @@ function setup_jlink_wsl { function setup_jlink_ps { if [ -z "$JLinkServerPath" ]; then - export JLinkServerPath="/c/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe" + export JLinkServerPath="c:/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe" fi - if [ ! -x "$JLinkServerPath" ]; then + if [ ! -x $(cygpath \"$JLinkServerPath\") ]; then echo >&2 "[!!] JLinkGDBServerCL.exe not found, please set JLinkServerPath manually" exit 1 fi diff --git a/.vscode/templates/launch_ps.json b/.vscode/templates/launch_ps.json index 28b724f7b..045b3d6c5 100644 --- a/.vscode/templates/launch_ps.json +++ b/.vscode/templates/launch_ps.json @@ -15,6 +15,7 @@ "name": "Client: (gdb) Build & Launch", "type": "cppdbg", "request": "launch", + "cwd": "${workspaceFolder}", "program": "${cwd}/client/proxmark3", "args": ["${SerialPort}"], "stopAtEntry": false, @@ -28,13 +29,13 @@ } ], "preLaunchTask": "client: Debug: clean & make", - "miDebuggerPath": "${DebuggerPath}" + "miDebuggerPath": "${workspaceFolder}/../../msys2/mingw64/bin/gdb.exe" },{ "name": "Firmware: (J-Link) Build & Launch", "type": "cortex-debug", "request": "launch", "cwd": "${workspaceRoot}", - "preLaunchTask": "fullimage: clean & make", + "preLaunchTask": "fullimage: clean & make debug", "executable": "${workspaceRoot}/armsrc/obj/fullimage.elf", "serverpath": "${JLinkServerPath}", "servertype": "jlink", @@ -42,7 +43,7 @@ "interface": "jtag", "serialNumber": "", //If you have more than one J-Link probe, add the serial number here. "runToMain": false, - "armToolchainPath": "/usr/bin/" + "armToolchainPath": "${workspaceFolder}/../../msys2/mingw64/bin" } ] } \ No newline at end of file From 3f7e9c8f8279c93a666ff8779cf5317086ce6bc8 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 21:10:16 +0100 Subject: [PATCH 051/173] Windows path check --- .vscode/setup.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.vscode/setup.sh b/.vscode/setup.sh index 3b652a6b8..cdfb77e8f 100755 --- a/.vscode/setup.sh +++ b/.vscode/setup.sh @@ -83,7 +83,8 @@ function setup_jlink_ps { if [ -z "$JLinkServerPath" ]; then export JLinkServerPath="c:/Program Files (x86)/SEGGER/JLink/JLinkGDBServerCL.exe" fi - if [ ! -x $(cygpath \"$JLinkServerPath\") ]; then + jlinkpath=$(cygpath "$JLinkServerPath") + if [ ! -x "$jlinkpath" ]; then echo >&2 "[!!] JLinkGDBServerCL.exe not found, please set JLinkServerPath manually" exit 1 fi @@ -107,10 +108,10 @@ function setup_linux { function setup_ps { setup_serial_port - setup_gdb_ps setup_jlink_ps + export DebuggerPath="Using ProxSpace gbd" print_config - envsubst '${SerialPort} ${DebuggerPath} ${JLinkServerPath} ${DeviceMem}' <"$VSCODEPATH/templates/launch_ps.json" > "$VSCODEPATH/launch.json" + envsubst '${SerialPort} ${JLinkServerPath} ${DeviceMem}' <"$VSCODEPATH/templates/launch_ps.json" > "$VSCODEPATH/launch.json" } if [ -f "$VSCODEPATH/launch.json" ]; then From c4729670b6c6c79fc968710b18a2b7a2f0860c8d Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 21:37:01 +0100 Subject: [PATCH 052/173] Fixed serial port not parsing --- .vscode/setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/setup.sh b/.vscode/setup.sh index cdfb77e8f..70672b924 100755 --- a/.vscode/setup.sh +++ b/.vscode/setup.sh @@ -40,7 +40,7 @@ function setup_serial_port { if [ -z "$SerialPort" ]; then pm3list=$($VSCODEPATH/../pm3 --list 2>/dev/null) #Use first port listed - SerialPort=$(echo $pm3list | head -n 1 | cut -c 4-) + export SerialPort=$(echo $pm3list | head -n 1 | cut -c 4-) if [ -z "$SerialPort" ]; then echo >&2 "[!!] No serial port found, please set SerialPort manually" exit 1 From db43f55b98ecef1092b066dae09f468e962a5cb6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 29 Dec 2020 21:38:02 +0100 Subject: [PATCH 053/173] hf mfu wrbl - now supports cliparser --- client/src/cmdhfmfu.c | 185 +++++++++++++++++++----------------------- 1 file changed, 84 insertions(+), 101 deletions(-) diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 639429fba..0dbc93998 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -99,21 +99,6 @@ static int usage_hf_mfu_rdbl(void) { return PM3_SUCCESS; } -static int usage_hf_mfu_wrbl(void) { - PrintAndLogEx(NORMAL, "Write a block. It autodetects card type.\n"); - PrintAndLogEx(NORMAL, "Usage: hf mfu wrbl b d k l\n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " b : block to write"); - PrintAndLogEx(NORMAL, " d : block data - (8 or 32 hex symbols, 32 hex symbols will do a compatibility write)"); - PrintAndLogEx(NORMAL, " k : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); - PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu wrbl b 0 d 01234567")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu wrbl b 0 d 01234567 k AABBCCDD")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} static int usage_hf_mfu_eload(void) { PrintAndLogEx(NORMAL, "It loads emul dump from the file " _YELLOW_("`filename.eml`")); @@ -1265,8 +1250,8 @@ static int CmdHF14AMfUInfo(const char *Cmd) { "Get info about MIFARE Ultralight Family styled tag.\n" "Sometimes the tags are locked down, and you may need a key to be able to read the information", "hf mfu info\n" - "hf mfu info k AABBCCDD\n" - "hf mfu info k 00112233445566778899AABBCCDDEEFF" + "hf mfu info -k AABBCCDD\n" + "hf mfu info --key 00112233445566778899AABBCCDDEEFF" ); void *argtable[] = { @@ -1284,7 +1269,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { CLIParserFree(ctx); if (ak_len) { - if (ak_len != 16 || ak_len != 8) { + if (ak_len != 16 && ak_len != 8) { PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); return PM3_EINVARG; } @@ -1558,81 +1543,63 @@ out: // static int CmdHF14AMfUWrBl(const char *Cmd) { - int blockNo = -1; - bool errors = false; - bool hasAuthKey = false; - bool hasPwdKey = false; - bool swapEndian = false; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfu wrbl", + "Write a block. It autodetects card type.", + "hf mfu wrbl -b 0 -d 01234567\n" + "hf mfu wrbl -b 0 -d 01234567 -k AABBCCDD\n" + "hf mfu wrbl -b 0 -d 01234567 -k 00112233445566778899AABBCCDDEEFF" + ); - uint8_t cmdp = 0; - uint8_t keylen = 0; - uint8_t blockdata[16] = {0x00}; - uint8_t data[16] = {0x00}; - uint8_t datalen = 4; + void *argtable[] = { + arg_param_begin, + arg_str0("k", "key", "", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"), + arg_lit0("l", NULL, "swap entered key's endianness"), + arg_int1("b", "block", "", "block number to write"), + arg_str1("d", "data", "", "block data (4 or 16 hex bytes, 16 hex bytes will do a compatibility write)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int ak_len = 0; uint8_t authenticationkey[16] = {0x00}; + CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len); + bool swap_endian = arg_get_lit(ctx, 2); + + int blockno = arg_get_int_def(ctx, 3, -1); + + int datalen = 0; + uint8_t data[16] = {0x00}; + CLIGetHexWithReturn(ctx, 4, data, &datalen); + CLIParserFree(ctx); + + bool has_auth_key = false; + bool has_pwd = false; + if (ak_len == 16) { + has_auth_key = true; + } else if (ak_len == 4) { + has_pwd = true; + } else if (ak_len != 0){ + PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); + return PM3_EINVARG; + } + + if (blockno < 0) { + PrintAndLogEx(WARNING, "Wrong block number"); + return PM3_EINVARG; + } + + if (datalen != 16 && datalen != 4) { + PrintAndLogEx(WARNING, "Wrong data length. Expect 16 or 4, got %d", datalen); + return PM3_EINVARG; + } + uint8_t *authKeyPtr = authenticationkey; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_mfu_wrbl(); - case 'k': - // EV1/NTAG size key - keylen = param_gethex(Cmd, cmdp + 1, data, 8); - if (!keylen) { - memcpy(authenticationkey, data, 4); - cmdp += 2; - hasPwdKey = true; - break; - } - // UL-C size key - keylen = param_gethex(Cmd, cmdp + 1, data, 32); - if (!keylen) { - memcpy(authenticationkey, data, 16); - cmdp += 2; - hasAuthKey = true; - break; - } - PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); - errors = true; - break; - case 'b': - blockNo = param_get8(Cmd, cmdp + 1); - if (blockNo < 0) { - PrintAndLogEx(WARNING, "Wrong block number"); - errors = true; - } - cmdp += 2; - break; - case 'l': - swapEndian = true; - cmdp++; - break; - case 'd': - if (param_gethex(Cmd, cmdp + 1, blockdata, 8)) { - if (param_gethex(Cmd, cmdp + 1, blockdata, 32)) { - PrintAndLogEx(WARNING, "Block data must include 8 or 32 HEX symbols"); - errors = true; - break; - } else { - datalen = 16; - } - } - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter: " _RED_("'%c'"), param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors || cmdp == 0) return usage_hf_mfu_wrbl(); - - if (blockNo == -1) return usage_hf_mfu_wrbl(); // starting with getting tagtype TagTypeUL_t tagtype = GetHF14AMfU_Type(); - if (tagtype == UL_ERROR) return -1; + if (tagtype == UL_ERROR) + return PM3_ESOFT; uint8_t maxblockno = 0; for (uint8_t idx = 0; idx < ARRAYLEN(UL_TYPES_ARRAY); idx++) { @@ -1641,39 +1608,55 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { break; } } - if (blockNo > maxblockno) { + if (blockno > maxblockno) { PrintAndLogEx(WARNING, "block number too large. Max block is %u/0x%02X \n", maxblockno, maxblockno); - return usage_hf_mfu_wrbl(); + return PM3_EINVARG; } // Swap endianness - if (swapEndian && hasAuthKey) authKeyPtr = SwapEndian64(authenticationkey, 16, 8); - if (swapEndian && hasPwdKey) authKeyPtr = SwapEndian64(authenticationkey, 4, 4); + if (swap_endian) { + if (has_auth_key) + authKeyPtr = SwapEndian64(authenticationkey, 16, 8); - if (blockNo <= 3) - PrintAndLogEx(NORMAL, "Special Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4)); + if (has_pwd) + authKeyPtr = SwapEndian64(authenticationkey, 4, 4); + } + + if (blockno <= 3) + PrintAndLogEx(INFO, "Special block: %0d (0x%02X) [ %s]", blockno, blockno, sprint_hex(data, datalen)); else - PrintAndLogEx(NORMAL, "Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4)); + PrintAndLogEx(INFO, "Block: %0d (0x%02X) [ %s]", blockno, blockno, sprint_hex(data, datalen)); + if (ak_len) { + PrintAndLogEx(INFO, "Using %s %s", (ak_len == 16) ? "3des" : "pwd", sprint_hex(authenticationkey, ak_len)); + } + //Send write Block + + // 4 or 16. uint8_t cmddata[32]; - memcpy(cmddata, blockdata, datalen); + memcpy(cmddata, data, datalen); + + // 0 - no pwd/key, no authentication + // 1 - 3des key (16 bytes) + // 2 - pwd (4 bytes) uint8_t keytype = 0; - if (hasAuthKey) { + size_t cmdlen = datalen; + if (has_auth_key) { keytype = 1; memcpy(cmddata + datalen, authKeyPtr, 16); - datalen += 16; - } else if (hasPwdKey) { + cmdlen += 16; + } else if (has_pwd) { keytype = 2; memcpy(cmddata + datalen, authKeyPtr, 4); - datalen += 4; + cmdlen += 4; } clearCommandBuffer(); if (datalen == 16) { - SendCommandMIX(CMD_HF_MIFAREU_WRITEBL_COMPAT, blockNo, keytype, 0, cmddata, datalen); + SendCommandMIX(CMD_HF_MIFAREU_WRITEBL_COMPAT, blockno, keytype, 0, cmddata, cmdlen); } else { - SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, blockNo, keytype, 0, cmddata, datalen); + SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, blockno, keytype, 0, cmddata, cmdlen); } PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { From 3396eeefdd371dacb6444d3228ff8aa9b3bfcec6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 29 Dec 2020 21:41:15 +0100 Subject: [PATCH 054/173] missing quote, Thanks @aveao for pointing it out! --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b7e942f58..3fd900b42 100644 --- a/Makefile +++ b/Makefile @@ -169,7 +169,7 @@ help: @echo "+ fpga_compress - Make tools/fpga_compress" @echo @echo "+ style - Apply some automated source code formatting rules" - @echo "+ cliparser - Generate cliparser TODO + @echo "+ cliparser - Generate cliparser TODO" @echo "+ check - Run offline tests. Set CHECKARGS to pass arguments to the test script" @echo "+ .../check - Run offline tests against specific target. See above." @echo "+ miscchecks - Detect various encoding issues in source code" From 9bd73c4c0ad826f144ab5096d71cd275d0e5ccc5 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Tue, 29 Dec 2020 21:43:29 +0100 Subject: [PATCH 055/173] Updated installation instructions for ProxSpace --- .../Windows-Installation-Instructions.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md index 1cf1f43c9..80f5b4d5c 100644 --- a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md @@ -64,6 +64,24 @@ To use the compiled client, the only differences are that executables end with ` Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). +## (Optional) Visual Studio Code debugging + +Download and install [Visual Studio Code](https://code.visualstudio.com/) + +Download and install [J-Link Software and Documentation pack for Windows](https://www.segger.com/downloads/jlink/JLink_Windows.exe) + +Enter PorxSpace (`runme64.bat`) and enter your project folder. + +Setup the Visual Studio Code configuration, by running: +```sh +./.vscode/setup.sh +``` + +now launch Visual Studio Code and open your project folder + +_note_ +Please install the recommended Visual Studio Code extensions in order for debugging to work. + # Installing on Windows with WSL 1 WSL 1 requires to run on Windows 10 version 1709 or above. Previous windows versions didn't have support for COM ports. From d8c8de3204a442bc7c0099f158dee1b963d49cb7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 29 Dec 2020 22:47:50 +0100 Subject: [PATCH 056/173] hf mfu rdbl - now uses cliparser --- client/src/cmdhfmfu.c | 147 ++++++++++++++++++------------------------ 1 file changed, 63 insertions(+), 84 deletions(-) diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 0dbc93998..a85e9aaf3 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -83,23 +83,6 @@ static int usage_hf_mfu_restore(void) { return PM3_SUCCESS; } -static int usage_hf_mfu_rdbl(void) { - PrintAndLogEx(NORMAL, "Read a block and print. It autodetects card type.\n"); - PrintAndLogEx(NORMAL, "Usage: hf mfu rdbl b k l\n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " b : block to read"); - PrintAndLogEx(NORMAL, " k : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); - PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu rdbl b 0")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu rdbl b 0 k 00112233445566778899AABBCCDDEEFF")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu rdbl b 0 k AABBCCDD")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} - - static int usage_hf_mfu_eload(void) { PrintAndLogEx(NORMAL, "It loads emul dump from the file " _YELLOW_("`filename.eml`")); PrintAndLogEx(NORMAL, "Hint: See " _YELLOW_("`script run hf_mfu_dumptoemulator`") " to convert the .bin to the eml"); @@ -1628,7 +1611,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { PrintAndLogEx(INFO, "Block: %0d (0x%02X) [ %s]", blockno, blockno, sprint_hex(data, datalen)); if (ak_len) { - PrintAndLogEx(INFO, "Using %s %s", (ak_len == 16) ? "3des" : "pwd", sprint_hex(authenticationkey, ak_len)); + PrintAndLogEx(INFO, "Using %s " _GREEN_("%s"), (ak_len == 16) ? "3des" : "pwd", sprint_hex(authenticationkey, ak_len)); } //Send write Block @@ -1673,66 +1656,52 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { // static int CmdHF14AMfURdBl(const char *Cmd) { - int blockNo = -1; - bool errors = false; - bool hasAuthKey = false; - bool hasPwdKey = false; - bool swapEndian = false; - uint8_t cmdp = 0; - uint8_t keylen = 0; - uint8_t data[16] = {0x00}; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfu rdbl", + "Read a block and print. It autodetects card type.", + "hf mfu rdbl -b 0\n" + "hf mfu rdbl -b 0 -k AABBCCDD\n" + "hf mfu rdbl -b 0 --key 00112233445566778899AABBCCDDEEFF" + ); + + void *argtable[] = { + arg_param_begin, + arg_str0("k", "key", "", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"), + arg_lit0("l", NULL, "swap entered key's endianness"), + arg_int1("b", "block", "", "block number to write"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int ak_len = 0; uint8_t authenticationkey[16] = {0x00}; + CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len); + bool swap_endian = arg_get_lit(ctx, 2); + int blockno = arg_get_int_def(ctx, 3, -1); + CLIParserFree(ctx); + + bool has_auth_key = false; + bool has_pwd = false; + if (ak_len == 16) { + has_auth_key = true; + } else if (ak_len == 4) { + has_pwd = true; + } else if (ak_len != 0){ + PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); + return PM3_EINVARG; + } + + if (blockno < 0) { + PrintAndLogEx(WARNING, "Wrong block number"); + return PM3_EINVARG; + } + uint8_t *authKeyPtr = authenticationkey; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_mfu_rdbl(); - case 'k': - // EV1/NTAG size key - keylen = param_gethex(Cmd, cmdp + 1, data, 8); - if (!keylen) { - memcpy(authenticationkey, data, 4); - cmdp += 2; - hasPwdKey = true; - break; - } - // UL-C size key - keylen = param_gethex(Cmd, cmdp + 1, data, 32); - if (!keylen) { - memcpy(authenticationkey, data, 16); - cmdp += 2; - hasAuthKey = true; - break; - } - PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); - errors = true; - break; - case 'b': - blockNo = param_get8(Cmd, cmdp + 1); - if (blockNo < 0) { - PrintAndLogEx(WARNING, "Wrong block number"); - errors = true; - } - cmdp += 2; - break; - case 'l': - swapEndian = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter: " _RED_("'%c'"), param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors || cmdp == 0) return usage_hf_mfu_rdbl(); - - if (blockNo == -1) return usage_hf_mfu_rdbl(); // start with getting tagtype TagTypeUL_t tagtype = GetHF14AMfU_Type(); - if (tagtype == UL_ERROR) return -1; + if (tagtype == UL_ERROR) + return PM3_ESOFT; uint8_t maxblockno = 0; for (uint8_t idx = 0; idx < ARRAYLEN(UL_TYPES_ARRAY); idx++) { @@ -1741,43 +1710,53 @@ static int CmdHF14AMfURdBl(const char *Cmd) { break; } } - if (blockNo > maxblockno) { + if (blockno > maxblockno) { PrintAndLogEx(WARNING, "block number to large. Max block is %u/0x%02X \n", maxblockno, maxblockno); - return usage_hf_mfu_rdbl(); + return PM3_EINVARG; } // Swap endianness - if (swapEndian && hasAuthKey) authKeyPtr = SwapEndian64(authenticationkey, 16, 8); - if (swapEndian && hasPwdKey) authKeyPtr = SwapEndian64(authenticationkey, 4, 4); + if (swap_endian) { + if (has_auth_key) + authKeyPtr = SwapEndian64(authenticationkey, ak_len, 8); + + if (has_pwd) + authKeyPtr = SwapEndian64(authenticationkey, ak_len, 4); + } + + if (ak_len) { + PrintAndLogEx(INFO, "Using %s " _GREEN_("%s"), (ak_len == 16) ? "3des" : "pwd", sprint_hex(authenticationkey, ak_len)); + } //Read Block uint8_t keytype = 0; uint8_t datalen = 0; - if (hasAuthKey) { + if (has_auth_key) { keytype = 1; datalen = 16; - } else if (hasPwdKey) { + } else if (has_pwd) { keytype = 2; datalen = 4; } clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFAREU_READBL, blockNo, keytype, 0, authKeyPtr, datalen); + SendCommandMIX(CMD_HF_MIFAREU_READBL, blockno, keytype, 0, authKeyPtr, datalen); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { uint8_t isOK = resp.oldarg[0] & 0xff; if (isOK) { uint8_t *d = resp.data.asBytes; - PrintAndLogEx(NORMAL, "\nBlock# | Data | Ascii"); - PrintAndLogEx(NORMAL, "-----------------------------"); - PrintAndLogEx(NORMAL, "%02d/0x%02X | %s| %s\n", blockNo, blockNo, sprint_hex(d, 4), sprint_ascii(d, 4)); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "Block# | Data | Ascii"); + PrintAndLogEx(INFO, "-----------------------------"); + PrintAndLogEx(INFO, "%02d/0x%02X | %s| %s\n", blockno, blockno, sprint_hex(d, 4), sprint_ascii(d, 4)); } else { PrintAndLogEx(WARNING, "Failed reading block: (%02x)", isOK); } } else { PrintAndLogEx(WARNING, "Command execute time-out"); } - return 0; + return PM3_SUCCESS; } void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage) { From 8c803edfd2b42cd173d3a22615d5ae74e6e703b5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 29 Dec 2020 23:36:38 +0100 Subject: [PATCH 057/173] hf mfu dump - now uses cliparser --- client/src/cmdhfmfu.c | 211 +++++++++++++++++++----------------------- 1 file changed, 94 insertions(+), 117 deletions(-) diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index a85e9aaf3..2c89cdf73 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -42,28 +42,6 @@ static int CmdHelp(const char *Cmd); -static int usage_hf_mfu_dump(void) { - PrintAndLogEx(NORMAL, "Reads all pages from Ultralight, Ultralight-C, Ultralight EV1"); - PrintAndLogEx(NORMAL, "NTAG 203, NTAG 210, NTAG 212, NTAG 213, NTAG 215, NTAG 216"); - PrintAndLogEx(NORMAL, "and saves binary dump into the file " _YELLOW_("`filename.bin`") " or " _YELLOW_("`cardUID.bin`")); - PrintAndLogEx(NORMAL, "It autodetects card type.\n"); - PrintAndLogEx(NORMAL, "Usage: hf mfu dump k l f p q <#pages>"); - PrintAndLogEx(NORMAL, " Options :"); - PrintAndLogEx(NORMAL, " k : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); - PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); - PrintAndLogEx(NORMAL, " f : " _YELLOW_("filename w/o .bin") " to save the dump as"); - PrintAndLogEx(NORMAL, " p : starting Page number to manually set a page to start the dump at"); - PrintAndLogEx(NORMAL, " q : number of Pages to manually set how many pages to dump"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu dump")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu dump f myfile")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu dump k 00112233445566778899AABBCCDDEEFF")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu dump k AABBCCDD")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} - static int usage_hf_mfu_restore(void) { PrintAndLogEx(NORMAL, "Restore dumpfile onto card."); PrintAndLogEx(NORMAL, "Usage: hf mfu restore [h] [l] [s] k n "); @@ -1911,83 +1889,78 @@ void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage) { // Read and Dump Card Contents, using auto detection of tag size. static int CmdHF14AMfUDump(const char *Cmd) { - int fileNameLen = 0; - char filename[FILE_PATH_SIZE] = {0x00}; - char *fptr = filename; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfu dump", + "Reads all pages from Ultralight, Ultralight-C, Ultralight EV1\n" + "NTAG 203, NTAG 210, NTAG 212, NTAG 213, NTAG 215, NTAG 216\n" + "and saves data into binary/json files.\n" + "It autodetects card type.", + "hf mfu dump -f myfile -> dump whole tag, save to `myfile.bin`\n" + "hf mfu dump -k AABBCCDD -> dump whole tag using pwd AABBCCDD\n" + "hf mfu dump -p 10 -> start at page 10 and dump rest of blocks\n" + "hf mfu dump -p 10 -q 2 -> start at page 10 and dump two blocks\n" + "hf mfu dump --key 00112233445566778899AABBCCDDEEFF" + ); - uint8_t data[1024] = {0x00}; - memset(data, 0x00, sizeof(data)); + void *argtable[] = { + arg_param_begin, + arg_str0("f", "file", "", "specify a filename for dump file"), + arg_str0("k", "key", "", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"), + arg_lit0("l", NULL, "swap entered key's endianness"), + arg_int0("p", "page", "", "manually set start page number to start from"), + arg_int0("q", "qty", "", "manually set number of pages to dump"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); - bool hasAuthKey = false; - int pages = 16; - uint8_t dataLen = 0; - uint8_t cmdp = 0; + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + + int ak_len = 0; uint8_t authenticationkey[16] = {0x00}; - memset(authenticationkey, 0x00, sizeof(authenticationkey)); uint8_t *authKeyPtr = authenticationkey; + CLIGetHexWithReturn(ctx, 2, authenticationkey, &ak_len); + bool swap_endian = arg_get_lit(ctx, 3); + int start_page = arg_get_int_def(ctx, 4, 0); + int pages = arg_get_int_def(ctx, 5, 16); + CLIParserFree(ctx); - bool errors = false; - bool swapEndian = false; - bool manualPages = false; - uint8_t startPage = 0; - uint8_t card_mem_size = 0; - char tempStr[50]; - - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_mfu_dump(); - case 'k': - dataLen = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr)); - if (dataLen == 32 || dataLen == 8) { //ul-c or ev1/ntag key length - errors = param_gethex(tempStr, 0, authenticationkey, dataLen); - dataLen /= 2; - } else { - PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); - errors = true; - } - cmdp += 2; - hasAuthKey = true; - break; - case 'l': - swapEndian = true; - cmdp++; - break; - case 'f': - fileNameLen = param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); - if (fileNameLen > FILE_PATH_SIZE - 5) - fileNameLen = FILE_PATH_SIZE - 5; - cmdp += 2; - break; - case 'p': //set start page - startPage = param_get8(Cmd, cmdp + 1); - manualPages = true; - cmdp += 2; - break; - case 'q': - pages = param_get8(Cmd, cmdp + 1); - cmdp += 2; - manualPages = true; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter: " _RED_("'%c'"), param_getchar(Cmd, cmdp)); - errors = true; - break; - } + bool has_auth_key = false; + bool has_pwd = false; + if (ak_len == 16) { + has_auth_key = true; + } else if (ak_len == 4) { + has_pwd = true; + } else if (ak_len != 0){ + PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); + return PM3_EINVARG; } - //Validations - if (errors) return usage_hf_mfu_dump(); + bool manual_pages = false; + if ( start_page > 0) + manual_pages = true; - //if we entered a key in little endian and set the swapEndian switch - switch it... - if (swapEndian && hasAuthKey) - authKeyPtr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4); + if (pages != 16) + manual_pages = true; + + uint8_t card_mem_size = 0; + + // Swap endianness + if (swap_endian) { + if (has_auth_key) + authKeyPtr = SwapEndian64(authenticationkey, ak_len, 8); + + if (has_pwd) + authKeyPtr = SwapEndian64(authenticationkey, ak_len, 4); + } TagTypeUL_t tagtype = GetHF14AMfU_Type(); - if (tagtype == UL_ERROR) return -1; + if (tagtype == UL_ERROR) + return PM3_ESOFT; //get number of pages to read - if (!manualPages) { + if (manual_pages == false) { for (uint8_t idx = 0; idx < ARRAYLEN(UL_TYPES_ARRAY); idx++) { if (tagtype & UL_TYPES_ARRAY[idx]) { //add one as maxblks starts at 0 @@ -1999,7 +1972,7 @@ static int CmdHF14AMfUDump(const char *Cmd) { ul_print_type(tagtype, 0); PrintAndLogEx(SUCCESS, "Reading tag memory..."); uint8_t keytype = 0; - if (hasAuthKey) { + if (has_auth_key) { if (tagtype & UL_C) keytype = 1; //UL_C auth else @@ -2007,34 +1980,38 @@ static int CmdHF14AMfUDump(const char *Cmd) { } clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFAREU_READCARD, startPage, pages, keytype, authKeyPtr, dataLen); + SendCommandMIX(CMD_HF_MIFAREU_READCARD, start_page, pages, keytype, authKeyPtr, ak_len); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { PrintAndLogEx(WARNING, "Command execute time-out"); - return 1; + return PM3_ETIMEOUT; } if (resp.oldarg[0] != 1) { PrintAndLogEx(WARNING, "Failed dumping card"); - return 1; + return PM3_ESOFT; } + // read all memory + uint8_t data[1024] = {0x00}; + memset(data, 0x00, sizeof(data)); + uint32_t startindex = resp.oldarg[2]; - uint32_t bufferSize = resp.oldarg[1]; - if (bufferSize > sizeof(data)) { + uint32_t buffer_size = resp.oldarg[1]; + if (buffer_size > sizeof(data)) { PrintAndLogEx(FAILED, "Data exceeded Buffer size!"); - bufferSize = sizeof(data); + buffer_size = sizeof(data); } - if (!GetFromDevice(BIG_BUF, data, bufferSize, startindex, NULL, 0, NULL, 2500, false)) { + if (!GetFromDevice(BIG_BUF, data, buffer_size, startindex, NULL, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "command execution time out"); - return 1; + return PM3_ETIMEOUT; } - bool is_partial = (pages != bufferSize / 4); + bool is_partial = (pages != buffer_size / 4); - pages = bufferSize / 4; + pages = buffer_size / 4; iso14a_card_select_t card; mfu_dump_t dump_file_data; @@ -2063,9 +2040,9 @@ static int CmdHF14AMfUDump(const char *Cmd) { memcpy(data + (pages * 4) - 4, get_pack, sizeof(get_pack)); } - if (hasAuthKey) { + if (has_auth_key) { uint8_t dummy_pack[] = {0, 0}; - ul_auth_select(&card, tagtype, hasAuthKey, authKeyPtr, dummy_pack, sizeof(dummy_pack)); + ul_auth_select(&card, tagtype, has_auth_key, authKeyPtr, dummy_pack, sizeof(dummy_pack)); } else { ul_select(&card); } @@ -2083,17 +2060,17 @@ static int CmdHF14AMfUDump(const char *Cmd) { // NTAG can have nfc counter pwd protection enabled for (; n < 3; n++) { - if (hasAuthKey) { + if (has_auth_key) { uint8_t dummy_pack[] = {0, 0}; - ul_auth_select(&card, tagtype, hasAuthKey, authKeyPtr, dummy_pack, sizeof(dummy_pack)); + ul_auth_select(&card, tagtype, has_auth_key, authKeyPtr, dummy_pack, sizeof(dummy_pack)); } else { ul_select(&card); } ulev1_readCounter(n, &get_counter_tearing[n][0], 3); - if (hasAuthKey) { + if (has_auth_key) { uint8_t dummy_pack[] = {0, 0}; - ul_auth_select(&card, tagtype, hasAuthKey, authKeyPtr, dummy_pack, sizeof(dummy_pack)); + ul_auth_select(&card, tagtype, has_auth_key, authKeyPtr, dummy_pack, sizeof(dummy_pack)); } else { ul_select(&card); } @@ -2102,9 +2079,9 @@ static int CmdHF14AMfUDump(const char *Cmd) { DropField(); - if (hasAuthKey) { + if (has_auth_key) { uint8_t dummy_pack[] = {0, 0}; - ul_auth_select(&card, tagtype, hasAuthKey, authKeyPtr, dummy_pack, sizeof(dummy_pack)); + ul_auth_select(&card, tagtype, has_auth_key, authKeyPtr, dummy_pack, sizeof(dummy_pack)); } else ul_select(&card); @@ -2114,21 +2091,21 @@ static int CmdHF14AMfUDump(const char *Cmd) { // format and add keys to block dump output // only add keys if not partial read, and complete pages read - if (!is_partial && pages == card_mem_size && hasAuthKey) { + if (!is_partial && pages == card_mem_size && has_auth_key) { // if we didn't swapendian before - do it now for the sprint_hex call // NOTE: default entry is bigendian (unless swapped), sprint_hex outputs little endian // need to swap to keep it the same - if (!swapEndian) { - authKeyPtr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4); + if (swap_endian == false) { + authKeyPtr = SwapEndian64(authenticationkey, ak_len, (ak_len == 16) ? 8 : 4); } else { authKeyPtr = authenticationkey; } if (tagtype & UL_C) { //add 4 pages - memcpy(data + pages * 4, authKeyPtr, dataLen); - pages += dataLen / 4; + memcpy(data + pages * 4, authKeyPtr, ak_len); + pages += ak_len / 4; } else { // 2nd page from end - memcpy(data + (pages * 4) - 8, authenticationkey, dataLen); + memcpy(data + (pages * 4) - 8, authenticationkey, ak_len); } } @@ -2140,17 +2117,17 @@ static int CmdHF14AMfUDump(const char *Cmd) { memcpy(dump_file_data.counter_tearing, get_counter_tearing, sizeof(dump_file_data.counter_tearing)); memcpy(dump_file_data.data, data, pages * 4); - printMFUdumpEx(&dump_file_data, pages, startPage); + printMFUdumpEx(&dump_file_data, pages, start_page); // user supplied filename? - if (fileNameLen < 1) { + if (fnlen < 1) { PrintAndLogEx(INFO, "Using UID as filename"); uint8_t uid[7] = {0}; memcpy(uid, (uint8_t *)&dump_file_data.data, 3); memcpy(uid + 3, (uint8_t *)&dump_file_data.data + 4, 4); - fptr += sprintf(fptr, "hf-mfu-"); - FillFileNameByUID(fptr, uid, "-dump", sizeof(uid)); + strcat(filename, "hf-mfu-"); + FillFileNameByUID(filename, uid, "-dump", sizeof(uid)); } uint16_t datalen = pages * 4 + MFU_DUMP_PREFIX_LENGTH; saveFile(filename, ".bin", (uint8_t *)&dump_file_data, datalen); @@ -2159,7 +2136,7 @@ static int CmdHF14AMfUDump(const char *Cmd) { if (is_partial) PrintAndLogEx(WARNING, "Partial dump created. (%d of %d blocks)", pages, card_mem_size); - return 0; + return PM3_SUCCESS; } static void wait4response(uint8_t b) { From 483707a45ac05ad162705f3022ec6a3e4b09dbd3 Mon Sep 17 00:00:00 2001 From: gator96100 Date: Wed, 30 Dec 2020 00:00:39 +0100 Subject: [PATCH 058/173] Moved vscode instructions --- .../Linux-Installation-Instructions.md | 27 +------ .../VSCode-Installation-Instructions.md | 72 +++++++++++++++++++ .../Windows-Installation-Instructions.md | 48 ------------- 3 files changed, 73 insertions(+), 74 deletions(-) create mode 100644 doc/md/Installation_Instructions/VSCode-Installation-Instructions.md diff --git a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md index aa5cf9042..18164398a 100644 --- a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md @@ -25,16 +25,13 @@ Install the requirements ```sh sudo apt-get install --no-install-recommends git ca-certificates build-essential pkg-config \ -libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev \ -binutils-arm-none-eabi gdb openocd gdb-multiarch +libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev ``` If you don't need the native Bluetooth support in the client, you can skip the installation of `libbluetooth-dev`. If you don't need the graphical components of the Proxmark3 client (such as in `hw tune`), you can skip the installation of `qtbase5-dev`. -If you don't need the debugging packages, you can skip the installation of `binutils-arm-none-eabi`,`gdb`,`openocd` and `gdb-multiarch`. - If you get some (non blocking) error at runtime such as _Gtk-Message: Failed to load module "canberra-gtk-module"_ you may have to install `libcanberra-gtk-module`. ## On ArchLinux @@ -115,25 +112,3 @@ It must return `ok`. Otherwise this means you've got a permission problem to fix # Compile and use the project Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). - - -## (Optional) Visual Studio Code debugging - -Download and install [Visual Studio Code](https://code.visualstudio.com/) - -Download and install [J-Link Software and Documentation pack](https://www.segger.com/downloads/jlink) - -On some systems `arm-none-eabi-gdb` was replaced with `gdb-multiarch`. In order to use the J-Link debugger you need to link `arm-none-eabi-gdb` to `gdb-multiarch`: -```sh -ln -s /usr/bin/gdb-multiarch /usr/bin/arm-none-eabi-gdb -``` - -Setup the Visual Studio Code configuration, by going into your project folder and run: -```sh -./.vscode/setup.sh -``` - -now launch Visual Studio Code and open your project folder - -_note_ -Please install the recommended Visual Studio Code extensions in order for debugging to work. diff --git a/doc/md/Installation_Instructions/VSCode-Installation-Instructions.md b/doc/md/Installation_Instructions/VSCode-Installation-Instructions.md new file mode 100644 index 000000000..079f301f6 --- /dev/null +++ b/doc/md/Installation_Instructions/VSCode-Installation-Instructions.md @@ -0,0 +1,72 @@ +# Visual Studio Code for debugging + +Download and install [Visual Studio Code](https://code.visualstudio.com/) + +Download and install [J-Link Software and Documentation pack](https://www.segger.com/downloads/jlink) + + +## Debian / Ubuntu / Kali / ParrotOS / Raspbian + +Install dependencies + +```sh +sudo apt-get install --no-install-recommends binutils-arm-none-eabi gdb openocd gdb-multiarch +``` + +On some systems `arm-none-eabi-gdb` was replaced with `gdb-multiarch`. In order to use the J-Link debugger you need to link `arm-none-eabi-gdb` to `gdb-multiarch`: +```sh +ln -s /usr/bin/gdb-multiarch /usr/bin/arm-none-eabi-gdb +``` + +Setup the Visual Studio Code configuration, by going into your project folder and run: +```sh +./.vscode/setup.sh +``` + +now launch Visual Studio Code and open your project folder + + +## Windows: WSL + +Enter WSL prompt (`wsl` or `start windows terminal`) + +Install dependencies +```sh +sudo apt-get install --no-install-recommends binutils-arm-none-eabi gdb openocd gdb-multiarch +``` + +The J-Link debugger requires `arm-none-eabi-gdb` which was replaced with `gdb-multiarch`. In order to use the J-Link debugger link `arm-none-eabi-gdb` to `gdb-multiarch`: +```sh +sudo ln -s /usr/bin/gdb-multiarch /usr/bin/arm-none-eabi-gdb +``` + +Setup the Visual Studio Code configuration, by going into your project folder and run: +```sh +./.vscode/setup.sh +``` + +and launch Visual Studio Code +```sh +code . +``` + + +## Windows: ProxSpace + +Download and install [Visual Studio Code](https://code.visualstudio.com/) + +Download and install [J-Link Software and Documentation pack for Windows](https://www.segger.com/downloads/jlink/JLink_Windows.exe) + +Enter PorxSpace (`runme64.bat`) and enter your project folder. + +Setup the Visual Studio Code configuration, by running: +```sh +./.vscode/setup.sh +``` + +now launch Visual Studio Code and open your project folder + + + +_note_ +Please install the recommended Visual Studio Code extensions in order for debugging to work. \ No newline at end of file diff --git a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md index 80f5b4d5c..6000f42f2 100644 --- a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md @@ -64,24 +64,6 @@ To use the compiled client, the only differences are that executables end with ` Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). -## (Optional) Visual Studio Code debugging - -Download and install [Visual Studio Code](https://code.visualstudio.com/) - -Download and install [J-Link Software and Documentation pack for Windows](https://www.segger.com/downloads/jlink/JLink_Windows.exe) - -Enter PorxSpace (`runme64.bat`) and enter your project folder. - -Setup the Visual Studio Code configuration, by running: -```sh -./.vscode/setup.sh -``` - -now launch Visual Studio Code and open your project folder - -_note_ -Please install the recommended Visual Studio Code extensions in order for debugging to work. - # Installing on Windows with WSL 1 WSL 1 requires to run on Windows 10 version 1709 or above. Previous windows versions didn't have support for COM ports. @@ -167,33 +149,3 @@ Note that it may take a quite long time for a freshly plugged Proxmark3 to be vi Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). - -## (Optional) Visual Studio Code debugging - -Download and install [Visual Studio Code](https://code.visualstudio.com/) - -Download and install [J-Link Software and Documentation pack for Windows](https://www.segger.com/downloads/jlink/JLink_Windows.exe) - -Enter WSL prompt (`wsl` or `start windows terminal`) and from there, follow the [Linux Installation Instructions](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) for Ubuntu, summarized here below: - -Install dependencies -```sh -sudo apt-get install --no-install-recommends binutils-arm-none-eabi gdb openocd gdb-multiarch -``` - -The J-Link debugger requires `arm-none-eabi-gdb` which was replaced with `gdb-multiarch`. In order to use the J-Link debugger link `arm-none-eabi-gdb` to `gdb-multiarch`: -```sh -sudo ln -s /usr/bin/gdb-multiarch /usr/bin/arm-none-eabi-gdb -``` - -Setup the Visual Studio Code configuration, by going into your project folder and run: -```sh -./.vscode/setup.sh -``` - -and launch Visual Studio Code -```sh -code . -``` -_note_ -Please install the recommended Visual Studio Code extensions in order for debugging to work. From f4c632bd313172ea7620f565f8ae048d3dbb262e Mon Sep 17 00:00:00 2001 From: gator96100 Date: Wed, 30 Dec 2020 00:19:21 +0100 Subject: [PATCH 059/173] Added DEBUG_ARM flag --- .vscode/tasks.json | 2 +- Makefile.defs | 5 +++++ common_arm/Makefile.hal | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 463377982..67f0f235e 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -71,7 +71,7 @@ },{ "label": "fullimage: clean & make debug", "type": "shell", - "command": "make armsrc/clean && make armsrc/all SKIP_COMPRESSION=1 DEBUG=1", + "command": "make armsrc/clean && make armsrc/all DEBUG_ARM=1", "problemMatcher": [ "$gcc" ], diff --git a/Makefile.defs b/Makefile.defs index 48567214b..b86b477aa 100644 --- a/Makefile.defs +++ b/Makefile.defs @@ -66,6 +66,11 @@ else DEFCFLAGS = -Wall -Werror -O3 -fstrict-aliasing -pipe DEFLDFLAGS = endif + +ifeq ($(DEBUG_ARM),1) + APP_CFLAGS += -g + SKIP_COMPRESSION=1 +endif # Next ones are activated only if SANITIZE=1 ifeq ($(SANITIZE),1) DEFCFLAGS += -g -fsanitize=address -fno-omit-frame-pointer diff --git a/common_arm/Makefile.hal b/common_arm/Makefile.hal index b6519e4ab..bfbe56d34 100644 --- a/common_arm/Makefile.hal +++ b/common_arm/Makefile.hal @@ -138,7 +138,7 @@ ifneq ($(SKIP_HFPLOT),1) PLATFORM_DEFS += -DWITH_HFPLOT endif ifeq ($(SKIP_COMPRESSION),1) - PLATFORM_DEFS += -DWITH_NO_COMPRESSION -g + PLATFORM_DEFS += -DWITH_NO_COMPRESSION endif # Standalone mode From e3710bbdddb4121497d7df30c1816caeb6ee3b90 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 30 Dec 2020 01:13:17 +0100 Subject: [PATCH 060/173] update doc --- doc/md/Development/Makefile-vs-CMake.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/md/Development/Makefile-vs-CMake.md b/doc/md/Development/Makefile-vs-CMake.md index 6fa95066c..1a7a0ddb5 100644 --- a/doc/md/Development/Makefile-vs-CMake.md +++ b/doc/md/Development/Makefile-vs-CMake.md @@ -15,6 +15,7 @@ At the moment both are maintained because they don't perfectly overlap yet. |-----|---|---|---| | verbose | `V=1` | `VERBOSE=1` | | | debug build | `DEBUG=1` | `-DCMAKE_BUILD_TYPE=Debug` | client only | +| ARM debug build | `DEBUG_ARM=1` | **no** | for use with JLink and VSCode | | warnings management | yes (1) | **no** | (1) cf Makefile.defs | | extra GCC warnings | GCCEXTRA=1 | **no** | | | extra Clang warnings | CLANGEXTRA=1 | **no** | only on host | @@ -83,7 +84,13 @@ At the moment both are maintained because they don't perfectly overlap yet. `makefile` only at the moment -`PLATFORM`, `PLATFORM_EXTRAS`, `DESTDIR`, `PREFIX`, `FWTAG` +Supposedly via `Makefile.platform`: + +`PLATFORM`, `PLATFORM_SIZE`, `PLATFORM_EXTRAS`, `SKIP_*`, `STANDALONE` + +Other: + +`DESTDIR`, `PREFIX`, `FWTAG` ## Global From 0f833018254edf1bfba08ba68df0f9e030f713ae Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 30 Dec 2020 01:30:30 +0100 Subject: [PATCH 061/173] update doc --- doc/md/Development/Makefile-vs-CMake.md | 32 ++++++++++++++++++------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/doc/md/Development/Makefile-vs-CMake.md b/doc/md/Development/Makefile-vs-CMake.md index 1a7a0ddb5..675ba0e96 100644 --- a/doc/md/Development/Makefile-vs-CMake.md +++ b/doc/md/Development/Makefile-vs-CMake.md @@ -15,11 +15,10 @@ At the moment both are maintained because they don't perfectly overlap yet. |-----|---|---|---| | verbose | `V=1` | `VERBOSE=1` | | | debug build | `DEBUG=1` | `-DCMAKE_BUILD_TYPE=Debug` | client only | -| ARM debug build | `DEBUG_ARM=1` | **no** | for use with JLink and VSCode | | warnings management | yes (1) | **no** | (1) cf Makefile.defs | -| extra GCC warnings | GCCEXTRA=1 | **no** | | -| extra Clang warnings | CLANGEXTRA=1 | **no** | only on host | -| AddressSanitize | SANITIZE=1 | **no** | only on host | +| extra GCC warnings | `GCCEXTRA=1` | **no** | | +| extra Clang warnings | `CLANGEXTRA=1` | **no** | only on host | +| AddressSanitize | `SANITIZE=1` | **no** | only on host | | compilation | in place | in build dir | | | user `CFLAGS`/`LDFLAGS` | envvars honored (1) | envvars honored (2) | (1) also `LDLIBS` and `INCLUDES_CLIENT` for more tuning (2) only at first cmake call | | Mingw gnu printf | `_ISOC99_SOURCE` | `_ISOC99_SOURCE` | and in cbor.h: `__attribute__((format (__MINGW_PRINTF_FORMAT, 2, 3)))`| @@ -78,19 +77,34 @@ At the moment both are maintained because they don't perfectly overlap yet. `makefile` only at the moment -`SKIPGPU` +| Feature | Makefile | Remarks | +|-----|---|---| +| Skip GPU-dependent code | `SKIPGPU=1` | to skip ht2crack5gpu tool when compiling the hitag2crack toolsuite | ## ARM `makefile` only at the moment -Supposedly via `Makefile.platform`: +### Features to be used via `Makefile.platform`: -`PLATFORM`, `PLATFORM_SIZE`, `PLATFORM_EXTRAS`, `SKIP_*`, `STANDALONE` +`SKIP_*`, `STANDALONE` -Other: +| Feature | Makefile | Remarks | +|-----|---|---| +| Platform choice | `PLATFORM=` | values: `PM3RDV4`, `PM3OTHER` | +| Platform size | `PLATFORM_SIZE=` | values: `256`, `512` | +| Platform extras | `PLATFORM_EXTRAS=` | values: `BTADDON`, `FPC_USART_DEV` | +| Skip LF/HF techs in the firmware | `SKIP_`*`=1` | see `common_arm/Makefile.hal` for a list | +| Standalone mode choice | `STANDALONE=` | see `doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md` for a list | -`DESTDIR`, `PREFIX`, `FWTAG` +### Other features: + +| Feature | Makefile | Remarks | +|-----|---|---| +| ARM debug build | `DEBUG_ARM=1` | to be used with JLink and VSCode | +| Install dest dir | `DESTDIR=` | for maintainers | +| Install prefix dir | `PREFIX=` | for maintainers | +| Tag firmware image | `FWTAG=` | for maintainers | ## Global From a0e110941a502bc2135f53b1883c655ba117c331 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 30 Dec 2020 01:31:40 +0100 Subject: [PATCH 062/173] make style --- armsrc/appmain.c | 4 +-- armsrc/start.c | 12 ++++----- client/luascripts/hf_mfu_setuid.lua | 10 ++++---- client/src/cmdhfmfu.c | 40 ++++++++++++++--------------- doc/commands.md | 4 +-- 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index b4c3d6a30..480a8632b 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -314,9 +314,9 @@ static void SendVersion(void) { struct p payload; payload.id = *(AT91C_DBGU_CIDR); #ifdef WITH_NO_COMPRESSION - payload.section_size = (uint32_t)&_bootrom_end - (uint32_t)&_bootrom_start + (uint32_t)&__os_size__; + payload.section_size = (uint32_t)&_bootrom_end - (uint32_t)&_bootrom_start + (uint32_t)&__os_size__; #else - payload.section_size = text_and_rodata_section_size + compressed_data_section_size; + payload.section_size = text_and_rodata_section_size + compressed_data_section_size; #endif payload.versionstr_len = strlen(VersionString) + 1; memcpy(payload.versionstr, VersionString, payload.versionstr_len); diff --git a/armsrc/start.c b/armsrc/start.c index 542b9f3f4..011742447 100644 --- a/armsrc/start.c +++ b/armsrc/start.c @@ -50,23 +50,23 @@ void Vector(void) { common_area.version = 1; } common_area.flags.osimage_present = 1; - + #ifdef WITH_NO_COMPRESSION - /* Set up data segment: Copy from flash to ram */ + /* Set up data segment: Copy from flash to ram */ char *src = &__data_src_start__; char *dst = &__data_start__; char *end = &__data_end__; - while(dst < end) *dst++ = *src++; - dst = &__bss_start__; + while (dst < end) *dst++ = *src++; + dst = &__bss_start__; end = &__bss_end__; #else - uncompress_data_section(); + uncompress_data_section(); /* Set up (that is: clear) BSS. */ char *dst = &__bss_start__; char *end = &__bss_end__; #endif - + while (dst < end) *dst++ = 0; AppMain(); diff --git a/client/luascripts/hf_mfu_setuid.lua b/client/luascripts/hf_mfu_setuid.lua index f64d5cfab..921563ed6 100644 --- a/client/luascripts/hf_mfu_setuid.lua +++ b/client/luascripts/hf_mfu_setuid.lua @@ -73,7 +73,7 @@ end --- Set UID on magic command enabled function magicUID(b0, b1, b2, isgen1a) - if isgen1a then + if isgen1a then print('Using backdoor Magic tag (gen1a) function') else print('Using backdoor Magic tag (gen1b) function') @@ -81,21 +81,21 @@ function magicUID(b0, b1, b2, isgen1a) -- write block 0 core.console('hf 14a raw -k -a -b 7 40') - if isgen1a then + if isgen1a then core.console('hf 14a raw -k -a 43') end core.console('hf 14a raw -c -a A200'..b0) -- write block 1 core.console('hf 14a raw -k -a -b 7 40') - if isgen1a then + if isgen1a then core.console('hf 14a raw -k -a 43') end core.console('hf 14a raw -c -a A201'..b1) -- write block 2 core.console('hf 14a raw -k -a -b 7 40') - if isgen1a then + if isgen1a then core.console('hf 14a raw -k -a 43') end core.console('hf 14a raw -c -a A202'..b2) @@ -154,7 +154,7 @@ function main(args) core.clearCommandBuffer() - if tagtype == 3 then + if tagtype == 3 then brickableUID(block0, block1, block2) else local is_gen1a = (tagtype == 1) diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 2c89cdf73..2a32e0a8d 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -675,10 +675,10 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces) { if (ismagic) snprintf(typestr + strlen(typestr), 4, " ("); - snprintf(typestr + strlen(typestr) , sizeof(typestr) - strlen(typestr), " %s ", (tagtype & MAGIC) ? _GREEN_("magic") : ""); + snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), " %s ", (tagtype & MAGIC) ? _GREEN_("magic") : ""); tagtype ^= MAGIC; - snprintf(typestr + strlen(typestr) , sizeof(typestr) - strlen(typestr), "%s", (tagtype & MAGIC_1A) ? _GREEN_("Gen 1a") : ""); - snprintf(typestr + strlen(typestr) , sizeof(typestr) - strlen(typestr), "%s", (tagtype & MAGIC_1B) ? _GREEN_("Gen 1b") : ""); + snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", (tagtype & MAGIC_1A) ? _GREEN_("Gen 1a") : ""); + snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", (tagtype & MAGIC_1B) ? _GREEN_("Gen 1b") : ""); if (ismagic) snprintf(typestr + strlen(typestr), 4, " )"); @@ -840,9 +840,9 @@ static int ulev1_print_counters(void) { if (len == 3) { PrintAndLogEx(INFO, " [%0d]: %s", i, sprint_hex(counter, 3)); PrintAndLogEx(SUCCESS, " - %02X tearing (%s)" - , tear[0] - , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail") - ); + , tear[0] + , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail") + ); } } return len; @@ -938,7 +938,7 @@ static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *sig PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfu_public_keys[i].value); PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1"); PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len)); - PrintAndLogEx(SUCCESS, " Signature verification (" _GREEN_("successful") ")" ); + PrintAndLogEx(SUCCESS, " Signature verification (" _GREEN_("successful") ")"); return PM3_SUCCESS; } @@ -969,9 +969,9 @@ static int ntag_print_counter(void) { (void)len; PrintAndLogEx(INFO, " [02]: %s", sprint_hex(counter, 3)); PrintAndLogEx(SUCCESS, " - %02X tearing (%s)" - , tear[0] - , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail") - ); + , tear[0] + , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail") + ); return len; } @@ -1513,7 +1513,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { ); void *argtable[] = { - arg_param_begin, + arg_param_begin, arg_str0("k", "key", "", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"), arg_lit0("l", NULL, "swap entered key's endianness"), arg_int1("b", "block", "", "block number to write"), @@ -1540,7 +1540,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { has_auth_key = true; } else if (ak_len == 4) { has_pwd = true; - } else if (ak_len != 0){ + } else if (ak_len != 0) { PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); return PM3_EINVARG; } @@ -1559,7 +1559,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { // starting with getting tagtype TagTypeUL_t tagtype = GetHF14AMfU_Type(); - if (tagtype == UL_ERROR) + if (tagtype == UL_ERROR) return PM3_ESOFT; uint8_t maxblockno = 0; @@ -1576,7 +1576,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { // Swap endianness if (swap_endian) { - if (has_auth_key) + if (has_auth_key) authKeyPtr = SwapEndian64(authenticationkey, 16, 8); if (has_pwd) @@ -1591,7 +1591,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { if (ak_len) { PrintAndLogEx(INFO, "Using %s " _GREEN_("%s"), (ak_len == 16) ? "3des" : "pwd", sprint_hex(authenticationkey, ak_len)); } - + //Send write Block // 4 or 16. @@ -1643,7 +1643,7 @@ static int CmdHF14AMfURdBl(const char *Cmd) { ); void *argtable[] = { - arg_param_begin, + arg_param_begin, arg_str0("k", "key", "", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"), arg_lit0("l", NULL, "swap entered key's endianness"), arg_int1("b", "block", "", "block number to write"), @@ -1664,7 +1664,7 @@ static int CmdHF14AMfURdBl(const char *Cmd) { has_auth_key = true; } else if (ak_len == 4) { has_pwd = true; - } else if (ak_len != 0){ + } else if (ak_len != 0) { PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); return PM3_EINVARG; } @@ -1704,7 +1704,7 @@ static int CmdHF14AMfURdBl(const char *Cmd) { if (ak_len) { PrintAndLogEx(INFO, "Using %s " _GREEN_("%s"), (ak_len == 16) ? "3des" : "pwd", sprint_hex(authenticationkey, ak_len)); - } + } //Read Block uint8_t keytype = 0; @@ -1932,13 +1932,13 @@ static int CmdHF14AMfUDump(const char *Cmd) { has_auth_key = true; } else if (ak_len == 4) { has_pwd = true; - } else if (ak_len != 0){ + } else if (ak_len != 0) { PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); return PM3_EINVARG; } bool manual_pages = false; - if ( start_page > 0) + if (start_page > 0) manual_pages = true; if (pages != 16) diff --git a/doc/commands.md b/doc/commands.md index e1e445296..991f4a590 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -198,8 +198,8 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`hf epa help `|Y |`This help` -|`hf epa cnonces `|N |` Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses` -|`hf epa preplay `|N |` Perform PACE protocol by replaying given APDUs` +|`hf epa cnonces `|N |`Acquire encrypted PACE nonces of specific size` +|`hf epa preplay `|N |`Perform PACE protocol by replaying given APDUs` ### hf emrtd From b0f122528df093c2df5dd9dccb2ce3a1988dc069 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 30 Dec 2020 01:36:44 +0100 Subject: [PATCH 063/173] minor --- armsrc/start.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/armsrc/start.c b/armsrc/start.c index 011742447..062a83eb9 100644 --- a/armsrc/start.c +++ b/armsrc/start.c @@ -51,23 +51,20 @@ void Vector(void) { } common_area.flags.osimage_present = 1; -#ifdef WITH_NO_COMPRESSION /* Set up data segment: Copy from flash to ram */ - char *src = &__data_src_start__; - char *dst = &__data_start__; - char *end = &__data_end__; - while (dst < end) *dst++ = *src++; - dst = &__bss_start__; - end = &__bss_end__; +#ifdef WITH_NO_COMPRESSION + char *data_src = &__data_src_start__; + char *data_dst = &__data_start__; + char *data_end = &__data_end__; + while (data_dst < data_end) *data_dst++ = *data_src++; #else uncompress_data_section(); - - /* Set up (that is: clear) BSS. */ - char *dst = &__bss_start__; - char *end = &__bss_end__; #endif - while (dst < end) *dst++ = 0; + /* Set up (that is: clear) BSS. */ + char *bss_dst = &__bss_start__; + char *bss_end = &__bss_end__; + while (bss_dst < bss_end) *bss_dst++ = 0; AppMain(); } From 49990ab11d01f1758e3723a6b0f74ee5a9ebc0ad Mon Sep 17 00:00:00 2001 From: tcprst Date: Tue, 29 Dec 2020 20:58:13 -0500 Subject: [PATCH 064/173] hf 14a cuids, sim - now use cliparser --- client/luascripts/hf_mf_uidbruteforce.lua | 4 +- client/src/cmdhf14a.c | 177 ++++++++++------------ client/src/cmdhfst.c | 2 +- doc/cliparser_todo.txt | 2 - doc/commands.md | 4 +- tools/pm3_amii_bin2eml.pl | 4 +- 6 files changed, 87 insertions(+), 106 deletions(-) diff --git a/client/luascripts/hf_mf_uidbruteforce.lua b/client/luascripts/hf_mf_uidbruteforce.lua index fc85b63bb..548898606 100644 --- a/client/luascripts/hf_mf_uidbruteforce.lua +++ b/client/luascripts/hf_mf_uidbruteforce.lua @@ -99,10 +99,10 @@ local function main(args) local command = '' if mftype == 'mfc' then - command = 'hf 14a sim t 1 u %014x' + command = 'hf 14a sim -t 1 -u %014x' msg('Bruteforcing Mifare Classic card numbers') elseif mftype == 'mfu' then - command = 'hf 14a sim t 2 u %014x' + command = 'hf 14a sim -t 2 -u %014x' msg('Bruteforcing Mifare Ultralight card numbers') else return print(usage) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 3cee04ecf..8a6ce45ef 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -209,34 +209,6 @@ static int usage_hf_14a_config(void) { return PM3_SUCCESS; } -static int usage_hf_14a_sim(void) { - PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"); - PrintAndLogEx(NORMAL, "Usage: hf 14a sim [h] t u [n ] [x] [e] [v]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " t : 1 = MIFARE Classic 1k"); - PrintAndLogEx(NORMAL, " 2 = MIFARE Ultralight"); - PrintAndLogEx(NORMAL, " 3 = MIFARE Desfire"); - PrintAndLogEx(NORMAL, " 4 = ISO/IEC 14443-4"); - PrintAndLogEx(NORMAL, " 5 = MIFARE Tnp3xxx"); - PrintAndLogEx(NORMAL, " 6 = MIFARE Mini"); - PrintAndLogEx(NORMAL, " 7 = AMIIBO (NTAG 215), pack 0x8080"); - PrintAndLogEx(NORMAL, " 8 = MIFARE Classic 4k"); - PrintAndLogEx(NORMAL, " 9 = FM11RF005SH Shanghai Metro"); - PrintAndLogEx(NORMAL, " 10 = JCOP 31/41 Rothult"); - PrintAndLogEx(NORMAL, " u : 4, 7 or 10 byte UID"); - PrintAndLogEx(NORMAL, " n : (Optional) Exit simulation after blocks have been read by reader. 0 = infinite"); - PrintAndLogEx(NORMAL, " x : (Optional) Performs the 'reader attack', nr/ar attack against a reader"); - PrintAndLogEx(NORMAL, " e : (Optional) Fill simulator keys from found keys"); - PrintAndLogEx(NORMAL, " v : (Optional) Verbose"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a sim t 1 u 11223344 x")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a sim t 1 u 11223344")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a sim t 1 u 11223344556677")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a sim t 1 u 112233445566778899AA")); - return PM3_SUCCESS; -} - static int CmdHF14AList(const char *Cmd) { char args[128] = {0}; if (strlen(Cmd) == 0) { @@ -595,10 +567,23 @@ static int CmdHF14AInfo(const char *Cmd) { // Collect ISO14443 Type A UIDs static int CmdHF14ACUIDs(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 14a cuids", + "Collect n>0 ISO14443-a UIDs in one go", + "hf 14a cuids -n 5 <-- Collect 5 UIDs"); + + void *argtable[] = { + arg_param_begin, + arg_int0("n", "num", "", "Number of UIDs to collect"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + // requested number of UIDs - int n = atoi(Cmd); // collect at least 1 (e.g. if no parameter was given) - n = n > 0 ? n : 1; + int n = arg_get_int_def(ctx, 1, 1); + + CLIParserFree(ctx); uint64_t t1 = msclock(); PrintAndLogEx(SUCCESS, "collecting %d UIDs", n); @@ -633,83 +618,81 @@ static int CmdHF14ACUIDs(const char *Cmd) { PrintAndLogEx(SUCCESS, "end: %" PRIu64 " seconds", (msclock() - t1) / 1000); return 1; } + // ## simulate iso14443a tag int CmdHF14ASim(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 14a sim", + "Simulate ISO/IEC 14443 type A tag with 4,7 or 10 byte UID", + "hf 14a sim -t 1 --uid 11223344 -> MIFARE Classic 1k\n" + "hf 14a sim -t 2 -> MIFARE Ultralight\n" + "hf 14a sim -t 3 -> MIFARE Desfire\n" + "hf 14a sim -t 4 -> ISO/IEC 14443-4\n" + "hf 14a sim -t 5 -> MIFARE Tnp3xxx\n" + "hf 14a sim -t 6 -> MIFARE Mini\n" + "hf 14a sim -t 7 -> AMIIBO (NTAG 215), pack 0x8080\n" + "hf 14a sim -t 8 -> MIFARE Classic 4k\n" + "hf 14a sim -t 9 -> FM11RF005SH Shanghai Metro\n" + "hf 14a sim -t 10 -> ST25TA IKEA Rothult\n"); - int uidlen = 0; - uint8_t flags = 0, tagtype = 1, cmdp = 0; - uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + void *argtable[] = { + arg_param_begin, + arg_int1("t", "type", "<1-10> ", "Simulation type to use"), + arg_str0("u", "uid", "", "4, 7 or 10 byte UID"), + arg_int0("n", "num", "", "Exit simulation after blocks have been read by reader. 0 = infinite"), + arg_lit0(NULL, "nr", "Performs the 'reader attack', nr/ar attack against a reader"), + arg_lit0(NULL, "sk", "Fill simulator keys from found keys"), + arg_lit0("v", "verbose", "verbose output"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int tagtype = arg_get_int(ctx, 1); + + int uid_len = 0; + uint8_t uid[10] = {0}; + CLIGetHexWithReturn(ctx, 2, uid, &uid_len); + + uint8_t flags = 0; bool useUIDfromEML = true; - bool setEmulatorMem = false; - bool verbose = false; - bool errors = false; - sector_t *k_sector = NULL; - uint8_t k_sectorsCount = 40; - uint8_t exitAfterNReads = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_14a_sim(); - case 't': - // Retrieve the tag type - tagtype = param_get8ex(Cmd, cmdp + 1, 0, 10); - if (tagtype == 0) - errors = true; - cmdp += 2; + if (uid_len > 0) { + switch (uid_len) { + case 10: + flags |= FLAG_10B_UID_IN_DATA; break; - case 'u': - // Retrieve the full 4,7,10 byte long uid - param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen); - uidlen >>= 1; - switch (uidlen) { - case 10: - flags |= FLAG_10B_UID_IN_DATA; - break; - case 7: - flags |= FLAG_7B_UID_IN_DATA; - break; - case 4: - flags |= FLAG_4B_UID_IN_DATA; - break; - default: - errors = true; - break; - } - if (!errors) { - PrintAndLogEx(SUCCESS, "Emulating " _YELLOW_("ISO/IEC 14443 type A tag")" with " _GREEN_("%d byte UID (%s)"), uidlen, sprint_hex(uid, uidlen)); - useUIDfromEML = false; - } - cmdp += 2; + case 7: + flags |= FLAG_7B_UID_IN_DATA; break; - case 'n': - exitAfterNReads = param_get8(Cmd, cmdp + 1); - cmdp += 2; - break; - case 'v': - verbose = true; - cmdp++; - break; - case 'x': - flags |= FLAG_NR_AR_ATTACK; - cmdp++; - break; - case 'e': - setEmulatorMem = true; - cmdp++; + case 4: + flags |= FLAG_4B_UID_IN_DATA; break; default: - PrintAndLogEx(WARNING, "Unknown parameter " _RED_("'%c'"), param_getchar(Cmd, cmdp)); - errors = true; - break; + PrintAndLogEx(ERR, "Please specify a 4, 7, or 10 byte UID"); + CLIParserFree(ctx); + return PM3_EINVARG; } + PrintAndLogEx(SUCCESS, "Emulating " _YELLOW_("ISO/IEC 14443 type A tag")" with " _GREEN_("%d byte UID (%s)"), uid_len, sprint_hex(uid, uid_len)); + useUIDfromEML = false; } - //Validations - if (errors || cmdp == 0) return usage_hf_14a_sim(); + uint8_t exitAfterNReads = arg_get_int(ctx, 3); - if (useUIDfromEML) + if (arg_get_lit(ctx, 4)) { + flags |= FLAG_NR_AR_ATTACK; + } + + bool setEmulatorMem = arg_get_lit(ctx, 5); + bool verbose = arg_get_lit(ctx, 6); + + CLIParserFree(ctx); + + sector_t *k_sector = NULL; + uint8_t k_sectorsCount = 40; + + if (useUIDfromEML) { flags |= FLAG_UID_IN_EMUL; + } struct { uint8_t tagtype; @@ -721,7 +704,7 @@ int CmdHF14ASim(const char *Cmd) { payload.tagtype = tagtype; payload.flags = flags; payload.exitAfter = exitAfterNReads; - memcpy(payload.uid, uid, uidlen); + memcpy(payload.uid, uid, uid_len); clearCommandBuffer(); SendCommandNG(CMD_HF_ISO14443A_SIMULATE, (uint8_t *)&payload, sizeof(payload)); @@ -2327,11 +2310,11 @@ out: static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"list", CmdHF14AList, AlwaysAvailable, "List ISO 14443-a history"}, + {"list", CmdHF14AList, AlwaysAvailable, "List ISO 14443-a history"}, {"info", CmdHF14AInfo, IfPm3Iso14443a, "Tag information"}, {"reader", CmdHF14AReader, IfPm3Iso14443a, "Act like an ISO14443-a reader"}, - {"cuids", CmdHF14ACUIDs, IfPm3Iso14443a, " Collect n>0 ISO14443-a UIDs in one go"}, - {"sim", CmdHF14ASim, IfPm3Iso14443a, " -- Simulate ISO 14443-a tag"}, + {"cuids", CmdHF14ACUIDs, IfPm3Iso14443a, "Collect n>0 ISO14443-a UIDs in one go"}, + {"sim", CmdHF14ASim, IfPm3Iso14443a, "Simulate ISO 14443-a tag"}, {"sniff", CmdHF14ASniff, IfPm3Iso14443a, "sniff ISO 14443-a traffic"}, {"apdu", CmdHF14AAPDU, IfPm3Iso14443a, "Send ISO 14443-4 APDU to tag"}, {"chaining", CmdHF14AChaining, IfPm3Iso14443a, "Control ISO 14443-4 input chaining"}, diff --git a/client/src/cmdhfst.c b/client/src/cmdhfst.c index 89633de8a..5fc151cc0 100644 --- a/client/src/cmdhfst.c +++ b/client/src/cmdhfst.c @@ -351,7 +351,7 @@ static int cmd_hf_st_sim(const char *Cmd) { } char param[40]; - snprintf(param, sizeof(param), "t 10 u %s", sprint_hex_inrow(uid, uidlen)); + snprintf(param, sizeof(param), "-t 10 -u %s", sprint_hex_inrow(uid, uidlen)); return CmdHF14ASim(param); } diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index c9dcf077c..0a5e5c77e 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -41,8 +41,6 @@ data print data samples data setdebugmode data tune -hf 14a cuids -hf 14a sim hf 14a config hf 14b sriwrite hf 15 dump diff --git a/doc/commands.md b/doc/commands.md index 991f4a590..f10e7a2bf 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -134,8 +134,8 @@ Check column "offline" for their availability. |`hf 14a list `|Y |`List ISO 14443-a history` |`hf 14a info `|N |`Tag information` |`hf 14a reader `|N |`Act like an ISO14443-a reader` -|`hf 14a cuids `|N |` Collect n>0 ISO14443-a UIDs in one go` -|`hf 14a sim `|N |` -- Simulate ISO 14443-a tag` +|`hf 14a cuids `|N |`Collect n>0 ISO14443-a UIDs in one go` +|`hf 14a sim `|N |`Simulate ISO 14443-a tag` |`hf 14a sniff `|N |`sniff ISO 14443-a traffic` |`hf 14a apdu `|N |`Send ISO 14443-4 APDU to tag` |`hf 14a chaining `|N |`Control ISO 14443-4 input chaining` diff --git a/tools/pm3_amii_bin2eml.pl b/tools/pm3_amii_bin2eml.pl index 35c95e8e4..c8e8d4f46 100755 --- a/tools/pm3_amii_bin2eml.pl +++ b/tools/pm3_amii_bin2eml.pl @@ -7,7 +7,7 @@ # -samy kamkar 05/28/2017 # # hf mf eload u FILENAME_MINUS_EML -# hf 14a sim t 7 u UID +# hf 14a sim -t 7 -u UID # perl -lne 'chomp; s/\s+(\S+)$//;$f=$1;if($f=~s/-(\S+)//){$g=hex($1);}else{$g=hex($f)}$f=hex($f); for$m($f..$g){print "0x" . substr(unpack("H4",pack("n",$m)),1) ." => \"$_\","}' /tmp/game >> game2 # perl -lne 'if(/^(\S.*?)\s+\w?\w\w\w\w(\s*-\s*\w?\w\w\w\w)?\s*$/){$l=$1} s/(\w{4,5}\s*-\s*)?(\w{4,5})$//; $a=$1;$b=$2; $b=hex($b); $a=$a?hex($a):$b; for$m($a..$b){print "0x" . substr(unpack("H4",pack("n",$m)),0) ." => \"$l\","}' /tmp/g2 @@ -685,7 +685,7 @@ $uid = uc $uid; #print STDERR "amiitool -d -k ../client/amiitool/key_retail.bin -i $input -o $input.decrypted\n"; $input =~ s/\....$//; print STDERR "hf mf eload u $input\n"; -print STDERR "hf 14a sim t 7 u $uid\n"; +print STDERR "hf 14a sim -t 7 -u $uid\n"; __DATA__ From 714470877af87f8be0870d8b141ef762692e1310 Mon Sep 17 00:00:00 2001 From: tcprst Date: Tue, 29 Dec 2020 21:12:11 -0500 Subject: [PATCH 065/173] lf em 410x - textual --- client/src/cmdlfem410x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdlfem410x.c b/client/src/cmdlfem410x.c index c8b11a9db..c2ee95a9d 100644 --- a/client/src/cmdlfem410x.c +++ b/client/src/cmdlfem410x.c @@ -585,8 +585,8 @@ static int CmdEM410xClone(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf em 410x clone", "Writes EM410x ID to a T55x7 or Q5/T5555 tag", - "lf em 410x clone --id 0F0368568B -> write id to T55x7 tag\n" - "lf em 410x clone --id 0F0368568B --q5 -> write id to Q5/T5555 tag" + "lf em 410x clone --uid 0F0368568B -> write id to T55x7 tag\n" + "lf em 410x clone --uid 0F0368568B --q5 -> write id to Q5/T5555 tag" ); void *argtable[] = { From 2679ea098091957713fce12a510a6b43d0b4db7d Mon Sep 17 00:00:00 2001 From: Ave Date: Wed, 30 Dec 2020 05:50:25 +0300 Subject: [PATCH 066/173] emrtd info: Split EF_SOD into a separate section (only on offline) --- client/src/cmdhfemrtd.c | 66 ++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 670ea804d..0a98c58b9 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1689,8 +1689,8 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab } // Grab the hash list - uint8_t dg_hashes[16][64]; - uint8_t hash_out[64]; + uint8_t dg_hashes_sod[17][64] = { 0x00 }; + uint8_t dg_hashes_calc[17][64] = { 0x00 }; int hash_algo = 0; if (!emrtd_select_and_read(response, &resplen, dg_table[EF_SOD].fileid, ks_enc, ks_mac, ssc, BAC, use_14b)) { @@ -1699,7 +1699,7 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab return PM3_ESOFT; } - res = emrtd_parse_ef_sod_hashes(response, resplen, *dg_hashes, &hash_algo); + res = emrtd_parse_ef_sod_hashes(response, resplen, *dg_hashes_sod, &hash_algo); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Failed to read hash list from EF_SOD. Hash checks will fail."); } @@ -1719,15 +1719,9 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab PrintAndLogEx(DEBUG, "EF_DG%i hash algo: %i", dg->dgnum, hash_algo); // Check file hash if (hash_algo != -1) { - PrintAndLogEx(DEBUG, "EF_DG%i hash on EF_SOD: %s", dg->dgnum, sprint_hex_inrow(dg_hashes[dg->dgnum], hashalg_table[hash_algo].hashlen)); - hashalg_table[hash_algo].hasher(response, resplen, hash_out); - PrintAndLogEx(DEBUG, "EF_DG%i hash calc: %s", dg->dgnum, sprint_hex_inrow(hash_out, hashalg_table[hash_algo].hashlen)); - - if (memcmp(dg_hashes[dg->dgnum], hash_out, hashalg_table[hash_algo].hashlen) == 0) { - PrintAndLogEx(SUCCESS, _GREEN_("Hash verification passed for EF_DG%i."), dg->dgnum); - } else { - PrintAndLogEx(ERR, _RED_("Hash verification failed for EF_DG%i."), dg->dgnum); - } + PrintAndLogEx(DEBUG, "EF_DG%i hash on EF_SOD: %s", dg->dgnum, sprint_hex_inrow(dg_hashes_sod[dg->dgnum], hashalg_table[hash_algo].hashlen)); + hashalg_table[hash_algo].hasher(response, resplen, dg_hashes_calc[dg->dgnum]); + PrintAndLogEx(DEBUG, "EF_DG%i hash calc: %s", dg->dgnum, sprint_hex_inrow(dg_hashes_calc[dg->dgnum], hashalg_table[hash_algo].hashlen)); } } } @@ -1771,8 +1765,8 @@ int infoHF_EMRTD_offline(const char *path) { free(data); // Grab the hash list - uint8_t dg_hashes[16][64]; - uint8_t hash_out[64]; + uint8_t dg_hashes_sod[17][64] = { 0x00 }; + uint8_t dg_hashes_calc[17][64] = { 0x00 }; int hash_algo = 0; strcpy(filepath, path); @@ -1785,7 +1779,7 @@ int infoHF_EMRTD_offline(const char *path) { return PM3_ESOFT; } - res = emrtd_parse_ef_sod_hashes(data, datalen, *dg_hashes, &hash_algo); + res = emrtd_parse_ef_sod_hashes(data, datalen, *dg_hashes_sod, &hash_algo); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Failed to read hash list from EF_SOD. Hash checks will fail."); } @@ -1810,21 +1804,45 @@ int infoHF_EMRTD_offline(const char *path) { PrintAndLogEx(DEBUG, "EF_DG%i hash algo: %i", dg->dgnum, hash_algo); // Check file hash if (hash_algo != -1) { - PrintAndLogEx(DEBUG, "EF_DG%i hash on EF_SOD: %s", dg->dgnum, sprint_hex_inrow(dg_hashes[dg->dgnum], hashalg_table[hash_algo].hashlen)); - hashalg_table[hash_algo].hasher(data, datalen, hash_out); - PrintAndLogEx(DEBUG, "EF_DG%i hash calc: %s", dg->dgnum, sprint_hex_inrow(hash_out, hashalg_table[hash_algo].hashlen)); - - if (memcmp(dg_hashes[dg->dgnum], hash_out, hashalg_table[hash_algo].hashlen) == 0) { - PrintAndLogEx(SUCCESS, _GREEN_("Hash verification passed for EF_DG%i."), dg->dgnum); - } else { - PrintAndLogEx(ERR, _RED_("Hash verification failed for EF_DG%i."), dg->dgnum); - } + PrintAndLogEx(DEBUG, "EF_DG%i hash on EF_SOD: %s", dg->dgnum, sprint_hex_inrow(dg_hashes_sod[dg->dgnum], hashalg_table[hash_algo].hashlen)); + hashalg_table[hash_algo].hasher(data, datalen, dg_hashes_calc[dg->dgnum]); + PrintAndLogEx(DEBUG, "EF_DG%i hash calc: %s", dg->dgnum, sprint_hex_inrow(dg_hashes_calc[dg->dgnum], hashalg_table[hash_algo].hashlen)); } free(data); } } } free(filepath); + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_SOD") " --------------------"); + + if (hash_algo == -1) { + PrintAndLogEx(SUCCESS, "Hash algorithm: " _YELLOW_("Unknown")); + } else { + PrintAndLogEx(SUCCESS, "Hash algorithm: " _YELLOW_("%s"), hashalg_table[hash_algo].name); + + uint8_t all_zeroes[64] = { 0x00 }; + bool calc_all_zero, sod_all_zero, hash_matches; + for (int i = 1; i <= 16; i++) { + calc_all_zero = (memcmp(dg_hashes_calc[i], all_zeroes, hashalg_table[hash_algo].hashlen) == 0); + sod_all_zero = (memcmp(dg_hashes_sod[i], all_zeroes, hashalg_table[hash_algo].hashlen) == 0); + hash_matches = (memcmp(dg_hashes_sod[i], dg_hashes_calc[i], hashalg_table[hash_algo].hashlen) == 0); + // Ignore files we don't haven't read and lack hashes to + if (calc_all_zero == true && sod_all_zero == true) { + continue; + } else if (calc_all_zero == true) { + PrintAndLogEx(SUCCESS, "EF_DG%i: " _YELLOW_("File read access denied, but is in EF_SOD"), i); + } else if (sod_all_zero == true) { + PrintAndLogEx(SUCCESS, "EF_DG%i: " _YELLOW_("File not in EF_SOD"), i); + } else if (hash_matches == false) { + PrintAndLogEx(SUCCESS, "EF_DG%i: " _RED_("Invalid"), i); + } else { + PrintAndLogEx(SUCCESS, "EF_DG%i: " _GREEN_("Valid"), i); + } + } + } + return PM3_SUCCESS; } From 80f035f7ab0087acdcc330074c6cbfdb189b75c2 Mon Sep 17 00:00:00 2001 From: Ave Date: Wed, 30 Dec 2020 05:57:11 +0300 Subject: [PATCH 067/173] emrtd info: Improve EF_SOD wording --- client/src/cmdhfemrtd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 0a98c58b9..72832b112 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1832,9 +1832,9 @@ int infoHF_EMRTD_offline(const char *path) { if (calc_all_zero == true && sod_all_zero == true) { continue; } else if (calc_all_zero == true) { - PrintAndLogEx(SUCCESS, "EF_DG%i: " _YELLOW_("File read access denied, but is in EF_SOD"), i); + PrintAndLogEx(SUCCESS, "EF_DG%i: " _YELLOW_("File couldn't be read, but is in EF_SOD."), i); } else if (sod_all_zero == true) { - PrintAndLogEx(SUCCESS, "EF_DG%i: " _YELLOW_("File not in EF_SOD"), i); + PrintAndLogEx(SUCCESS, "EF_DG%i: " _YELLOW_("File is not in EF_SOD."), i); } else if (hash_matches == false) { PrintAndLogEx(SUCCESS, "EF_DG%i: " _RED_("Invalid"), i); } else { From 9f29a839a789842343a3ad0135f3f8c6f4c24708 Mon Sep 17 00:00:00 2001 From: Ave Date: Wed, 30 Dec 2020 06:03:12 +0300 Subject: [PATCH 068/173] emrtd info: Move EF_SOD print to a func, also add to online --- client/src/cmdhfemrtd.c | 65 +++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 72832b112..8789656a5 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1638,6 +1638,39 @@ static int emrtd_parse_ef_sod_hashes(uint8_t *data, size_t datalen, uint8_t *has return PM3_SUCCESS; } +static int emrtd_print_ef_sod_info(uint8_t *dg_hashes_calc, uint8_t *dg_hashes_sod, int hash_algo) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_SOD") " --------------------"); + + if (hash_algo == -1) { + PrintAndLogEx(SUCCESS, "Hash algorithm: " _YELLOW_("Unknown")); + } else { + PrintAndLogEx(SUCCESS, "Hash algorithm: " _YELLOW_("%s"), hashalg_table[hash_algo].name); + + uint8_t all_zeroes[64] = { 0x00 }; + bool calc_all_zero, sod_all_zero, hash_matches; + for (int i = 1; i <= 16; i++) { + calc_all_zero = (memcmp(dg_hashes_calc + (i * 64), all_zeroes, hashalg_table[hash_algo].hashlen) == 0); + sod_all_zero = (memcmp(dg_hashes_sod + (i * 64), all_zeroes, hashalg_table[hash_algo].hashlen) == 0); + hash_matches = (memcmp(dg_hashes_sod + (i * 64), dg_hashes_calc + (i * 64), hashalg_table[hash_algo].hashlen) == 0); + // Ignore files we don't haven't read and lack hashes to + if (calc_all_zero == true && sod_all_zero == true) { + continue; + } else if (calc_all_zero == true) { + PrintAndLogEx(SUCCESS, "EF_DG%i: " _YELLOW_("File couldn't be read, but is in EF_SOD."), i); + } else if (sod_all_zero == true) { + PrintAndLogEx(SUCCESS, "EF_DG%i: " _YELLOW_("File is not in EF_SOD."), i); + } else if (hash_matches == false) { + PrintAndLogEx(SUCCESS, "EF_DG%i: " _RED_("Invalid"), i); + } else { + PrintAndLogEx(SUCCESS, "EF_DG%i: " _GREEN_("Valid"), i); + } + } + } + + return PM3_SUCCESS; +} + int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_available) { uint8_t response[EMRTD_MAX_FILE_SIZE] = { 0x00 }; int resplen = 0; @@ -1727,6 +1760,9 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab } } DropField(); + + emrtd_print_ef_sod_info(*dg_hashes_calc, *dg_hashes_sod, hash_algo); + return PM3_SUCCESS; } @@ -1814,34 +1850,7 @@ int infoHF_EMRTD_offline(const char *path) { } free(filepath); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "-------------------- " _CYAN_("EF_SOD") " --------------------"); - - if (hash_algo == -1) { - PrintAndLogEx(SUCCESS, "Hash algorithm: " _YELLOW_("Unknown")); - } else { - PrintAndLogEx(SUCCESS, "Hash algorithm: " _YELLOW_("%s"), hashalg_table[hash_algo].name); - - uint8_t all_zeroes[64] = { 0x00 }; - bool calc_all_zero, sod_all_zero, hash_matches; - for (int i = 1; i <= 16; i++) { - calc_all_zero = (memcmp(dg_hashes_calc[i], all_zeroes, hashalg_table[hash_algo].hashlen) == 0); - sod_all_zero = (memcmp(dg_hashes_sod[i], all_zeroes, hashalg_table[hash_algo].hashlen) == 0); - hash_matches = (memcmp(dg_hashes_sod[i], dg_hashes_calc[i], hashalg_table[hash_algo].hashlen) == 0); - // Ignore files we don't haven't read and lack hashes to - if (calc_all_zero == true && sod_all_zero == true) { - continue; - } else if (calc_all_zero == true) { - PrintAndLogEx(SUCCESS, "EF_DG%i: " _YELLOW_("File couldn't be read, but is in EF_SOD."), i); - } else if (sod_all_zero == true) { - PrintAndLogEx(SUCCESS, "EF_DG%i: " _YELLOW_("File is not in EF_SOD."), i); - } else if (hash_matches == false) { - PrintAndLogEx(SUCCESS, "EF_DG%i: " _RED_("Invalid"), i); - } else { - PrintAndLogEx(SUCCESS, "EF_DG%i: " _GREEN_("Valid"), i); - } - } - } + emrtd_print_ef_sod_info(*dg_hashes_calc, *dg_hashes_sod, hash_algo); return PM3_SUCCESS; } From 5d250339dd7a2d5c5c51b0ba7136ea66539cf300 Mon Sep 17 00:00:00 2001 From: Ave Date: Wed, 30 Dec 2020 06:37:01 +0300 Subject: [PATCH 069/173] emrtd dump: Allow specifying a dump folder --- client/src/cmdhfemrtd.c | 101 ++++++++++++++++++++++++++++++++-------- client/src/cmdhfemrtd.h | 4 +- 2 files changed, 83 insertions(+), 22 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 670ea804d..1f9916041 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -50,10 +50,10 @@ const uint8_t KENC_type[4] = {0x00, 0x00, 0x00, 0x01}; const uint8_t KMAC_type[4] = {0x00, 0x00, 0x00, 0x02}; -static int emrtd_dump_ef_dg2(uint8_t *file_contents, size_t file_length); -static int emrtd_dump_ef_dg5(uint8_t *file_contents, size_t file_length); -static int emrtd_dump_ef_dg7(uint8_t *file_contents, size_t file_length); -static int emrtd_dump_ef_sod(uint8_t *file_contents, size_t file_length); +static int emrtd_dump_ef_dg2(uint8_t *file_contents, size_t file_length, const char *path); +static int emrtd_dump_ef_dg5(uint8_t *file_contents, size_t file_length, const char *path); +static int emrtd_dump_ef_dg7(uint8_t *file_contents, size_t file_length, const char *path); +static int emrtd_dump_ef_sod(uint8_t *file_contents, size_t file_length, const char *path); static int emrtd_print_ef_com_info(uint8_t *data, size_t datalen); static int emrtd_print_ef_dg1_info(uint8_t *data, size_t datalen); static int emrtd_print_ef_dg11_info(uint8_t *data, size_t datalen); @@ -710,7 +710,7 @@ static bool emrtd_select_and_read(uint8_t *dataout, int *dataoutlen, const char const uint8_t jpeg_header[4] = { 0xFF, 0xD8, 0xFF, 0xE0 }; const uint8_t jpeg2k_header[6] = { 0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50 }; -static int emrtd_dump_ef_dg2(uint8_t *file_contents, size_t file_length) { +static int emrtd_dump_ef_dg2(uint8_t *file_contents, size_t file_length, const char *path) { int offset, datalen = 0; // This is a hacky impl that just looks for the image header. I'll improve it eventually. @@ -730,11 +730,20 @@ static int emrtd_dump_ef_dg2(uint8_t *file_contents, size_t file_length) { return PM3_ESOFT; } - saveFile(dg_table[EF_DG2].filename, file_contents[offset] == 0xFF ? ".jpg" : ".jp2", file_contents + offset, datalen); + char *filepath = calloc(strlen(path) + 100, sizeof(char)); + if (filepath == NULL) + return PM3_EMALLOC; + strcpy(filepath, path); + strncat(filepath, PATHSEP, 2); + strcat(filepath, dg_table[EF_DG2].filename); + + saveFile(filepath, file_contents[offset] == 0xFF ? ".jpg" : ".jp2", file_contents + offset, datalen); + + free(filepath); return PM3_SUCCESS; } -static int emrtd_dump_ef_dg5(uint8_t *file_contents, size_t file_length) { +static int emrtd_dump_ef_dg5(uint8_t *file_contents, size_t file_length, const char *path) { uint8_t data[EMRTD_MAX_FILE_SIZE]; size_t datalen = 0; @@ -744,7 +753,16 @@ static int emrtd_dump_ef_dg5(uint8_t *file_contents, size_t file_length) { } if (datalen < EMRTD_MAX_FILE_SIZE) { - saveFile(dg_table[EF_DG5].filename, data[0] == 0xFF ? ".jpg" : ".jp2", data, datalen); + char *filepath = calloc(strlen(path) + 100, sizeof(char)); + if (filepath == NULL) + return PM3_EMALLOC; + strcpy(filepath, path); + strncat(filepath, PATHSEP, 2); + strcat(filepath, dg_table[EF_DG5].filename); + + saveFile(filepath, data[0] == 0xFF ? ".jpg" : ".jp2", data, datalen); + + free(filepath); } else { PrintAndLogEx(ERR, "error (emrtd_dump_ef_dg5) datalen out-of-bounds"); return PM3_ESOFT; @@ -752,7 +770,7 @@ static int emrtd_dump_ef_dg5(uint8_t *file_contents, size_t file_length) { return PM3_SUCCESS; } -static int emrtd_dump_ef_dg7(uint8_t *file_contents, size_t file_length) { +static int emrtd_dump_ef_dg7(uint8_t *file_contents, size_t file_length, const char *path) { uint8_t data[EMRTD_MAX_FILE_SIZE]; size_t datalen = 0; @@ -762,7 +780,16 @@ static int emrtd_dump_ef_dg7(uint8_t *file_contents, size_t file_length) { } if (datalen < EMRTD_MAX_FILE_SIZE) { - saveFile(dg_table[EF_DG7].filename, data[0] == 0xFF ? ".jpg" : ".jp2", data, datalen); + char *filepath = calloc(strlen(path) + 100, sizeof(char)); + if (filepath == NULL) + return PM3_EMALLOC; + strcpy(filepath, path); + strncat(filepath, PATHSEP, 2); + strcat(filepath, dg_table[EF_DG7].filename); + + saveFile(filepath, data[0] == 0xFF ? ".jpg" : ".jp2", data, datalen); + + free(filepath); } else { PrintAndLogEx(ERR, "error (emrtd_dump_ef_dg7) datalen out-of-bounds"); return PM3_ESOFT; @@ -770,7 +797,7 @@ static int emrtd_dump_ef_dg7(uint8_t *file_contents, size_t file_length) { return PM3_SUCCESS; } -static int emrtd_dump_ef_sod(uint8_t *file_contents, size_t file_length) { +static int emrtd_dump_ef_sod(uint8_t *file_contents, size_t file_length, const char *path) { int fieldlen = emrtd_get_asn1_field_length(file_contents, file_length, 1); int datalen = emrtd_get_asn1_data_length(file_contents, file_length, 1); @@ -779,11 +806,19 @@ static int emrtd_dump_ef_sod(uint8_t *file_contents, size_t file_length) { return PM3_SUCCESS; } - saveFile(dg_table[EF_SOD].filename, ".p7b", file_contents + fieldlen + 1, datalen); + char *filepath = calloc(strlen(path) + 100, sizeof(char)); + if (filepath == NULL) + return PM3_EMALLOC; + strcpy(filepath, path); + strncat(filepath, PATHSEP, 2); + strcat(filepath, dg_table[EF_SOD].filename); + + saveFile(filepath, ".p7b", file_contents + fieldlen + 1, datalen); + free(filepath); return PM3_ESOFT; } -static bool emrtd_dump_file(uint8_t *ks_enc, uint8_t *ks_mac, uint8_t *ssc, const char *file, const char *name, bool use_secure, bool use_14b) { +static bool emrtd_dump_file(uint8_t *ks_enc, uint8_t *ks_mac, uint8_t *ssc, const char *file, const char *name, bool use_secure, bool use_14b, const char *path) { uint8_t response[EMRTD_MAX_FILE_SIZE]; int resplen = 0; @@ -791,13 +826,22 @@ static bool emrtd_dump_file(uint8_t *ks_enc, uint8_t *ks_mac, uint8_t *ssc, cons return false; } + char *filepath = calloc(strlen(path) + 100, sizeof(char)); + if (filepath == NULL) + return PM3_EMALLOC; + strcpy(filepath, path); + strncat(filepath, PATHSEP, 2); + strcat(filepath, name); + PrintAndLogEx(INFO, "Read %s, len: %i.", name, resplen); PrintAndLogEx(DEBUG, "Contents (may be incomplete over 2k chars): %s", sprint_hex_inrow(response, resplen)); - saveFile(name, ".BIN", response, resplen); + saveFile(filepath, ".BIN", response, resplen); emrtd_dg_t *dg = emrtd_fileid_to_dg(file); if ((dg != NULL) && (dg->dumper != NULL)) { - dg->dumper(response, resplen); + dg->dumper(response, resplen, path); } + + free(filepath); return true; } @@ -983,7 +1027,7 @@ static bool emrtd_do_auth(char *documentnumber, char *dob, char *expiry, bool BA return true; } -int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_available) { +int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_available, const char *path) { uint8_t response[EMRTD_MAX_FILE_SIZE] = { 0x00 }; int resplen = 0; uint8_t ssc[8] = { 0x00 }; @@ -999,7 +1043,7 @@ int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab } // Dump EF_CardAccess (if available) - if (!emrtd_dump_file(ks_enc, ks_mac, ssc, dg_table[EF_CardAccess].fileid, dg_table[EF_CardAccess].filename, BAC, use_14b)) { + if (!emrtd_dump_file(ks_enc, ks_mac, ssc, dg_table[EF_CardAccess].fileid, dg_table[EF_CardAccess].filename, BAC, use_14b, path)) { PrintAndLogEx(INFO, "Couldn't dump EF_CardAccess, card does not support PACE."); PrintAndLogEx(HINT, "This is expected behavior for cards without PACE, and isn't something to be worried about."); } @@ -1016,9 +1060,20 @@ int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab DropField(); return PM3_ESOFT; } + + + char *filepath = calloc(strlen(path) + 100, sizeof(char)); + if (filepath == NULL) + return PM3_EMALLOC; + strcpy(filepath, path); + strncat(filepath, PATHSEP, 2); + strcat(filepath, dg_table[EF_COM].filename); + PrintAndLogEx(INFO, "Read EF_COM, len: %i.", resplen); PrintAndLogEx(DEBUG, "Contents (may be incomplete over 2k chars): %s", sprint_hex_inrow(response, resplen)); - saveFile(dg_table[EF_COM].filename, ".BIN", response, resplen); + saveFile(filepath, ".BIN", response, resplen); + + free(filepath); uint8_t filelist[50]; size_t filelistlen = 0; @@ -1041,7 +1096,7 @@ int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab } PrintAndLogEx(DEBUG, "Current file: %s", dg->filename); if (!dg->pace && !dg->eac) { - emrtd_dump_file(ks_enc, ks_mac, ssc, dg->fileid, dg->filename, BAC, use_14b); + emrtd_dump_file(ks_enc, ks_mac, ssc, dg->fileid, dg->filename, BAC, use_14b, path); } } DropField(); @@ -1864,6 +1919,7 @@ static int cmd_hf_emrtd_dump(const char *Cmd) { arg_str0("d", "dateofbirth", "", "date of birth in YYMMDD format"), arg_str0("e", "expiry", "", "expiry in YYMMDD format"), arg_str0("m", "mrz", "<[0-9A-Z<]>", "2nd line of MRZ, 44 chars"), + arg_str0(NULL, "path", "", "save dump to the given dirpath"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -1930,11 +1986,16 @@ static int cmd_hf_emrtd_dump(const char *Cmd) { } } + uint8_t path[FILENAME_MAX] = { 0x00 }; + if (CLIParamStrToBuf(arg_get_str(ctx, 5), path, sizeof(path), &slen) != 0 || slen == 0) { + path[0] = '.'; + } + CLIParserFree(ctx); if (error) { return PM3_ESOFT; } - return dumpHF_EMRTD((char *)docnum, (char *)dob, (char *)expiry, BAC); + return dumpHF_EMRTD((char *)docnum, (char *)dob, (char *)expiry, BAC, (const char *)path); } static int cmd_hf_emrtd_info(const char *Cmd) { diff --git a/client/src/cmdhfemrtd.h b/client/src/cmdhfemrtd.h index f7bd64945..bb32fb53d 100644 --- a/client/src/cmdhfemrtd.h +++ b/client/src/cmdhfemrtd.h @@ -24,7 +24,7 @@ typedef struct emrtd_dg_s { bool required; // some are required only if PACE bool fastdump; // fast to dump int (*parser)(uint8_t *data, size_t datalen); - int (*dumper)(uint8_t *data, size_t datalen); + int (*dumper)(uint8_t *data, size_t datalen, const char *path); } emrtd_dg_t; typedef struct emrtd_hashalg_s { @@ -37,7 +37,7 @@ typedef struct emrtd_hashalg_s { int CmdHFeMRTD(const char *Cmd); -int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_available); +int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_available, const char *path); int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_available); int infoHF_EMRTD_offline(const char *path); #endif From 037fd47673156a2ef780e1b347bdb612eb04b4e8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 30 Dec 2020 18:57:30 +0100 Subject: [PATCH 070/173] fix #1151 - improved feedback text --- client/src/fileutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/fileutils.c b/client/src/fileutils.c index f7ccf1516..4d607b9df 100644 --- a/client/src/fileutils.c +++ b/client/src/fileutils.c @@ -735,7 +735,7 @@ int createMfcKeyDump(const char *preferredName, uint8_t sectorsCnt, sector_t *e_ fflush(f); fclose(f); PrintAndLogEx(SUCCESS, "Found keys have been dumped to " _YELLOW_("%s"), fileName); - PrintAndLogEx(INFO, " OBS! --> 0xFFFFFFFFFFFF <-- has been inserted for unknown keys."); + PrintAndLogEx(INFO, "FYI! --> " _YELLOW_("0xFFFFFFFFFFFF") " <-- has been inserted for unknown keys where " _YELLOW_("res") " is " _YELLOW_("0")); free(fileName); return PM3_SUCCESS; } From 49f684c31adb42228da2c45f1edcb717d6e75562 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 30 Dec 2020 18:58:04 +0100 Subject: [PATCH 071/173] add noralsy/vigik entry --- client/resources/mad.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/resources/mad.json b/client/resources/mad.json index d5c413d73..c63190cda 100644 --- a/client/resources/mad.json +++ b/client/resources/mad.json @@ -6096,6 +6096,13 @@ "service_provider": "CDVI", "system_integrator": "CDVI" }, + { + "application": "(access control and security) VIGIK", + "company": "NORALSY", + "mad": "0x4980", + "service_provider": "NORALSY", + "system_integrator": "NORALSY" + }, { "application": "Card Administratin, cardholder adminstration, access control & security, company services, miscellaneous applications", "company": "Ministry of Defense", From cdbd4d7d1e2e8d259119278b4f3501709af32147 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 30 Dec 2020 19:16:37 +0100 Subject: [PATCH 072/173] hf mf mad - deals with user supplied keys in a different order now --- client/src/cmdhfmf.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 481a5ce14..8cf0f4e1a 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -4869,28 +4869,45 @@ static int CmdHF14AMfMAD(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, true); bool verbose = arg_get_lit(ctx, 1); uint8_t aid[2] = {0}; - int aidlen; + int aidlen = 0; CLIGetHexWithReturn(ctx, 2, aid, &aidlen); - uint8_t key[6] = {0}; - int keylen; - CLIGetHexWithReturn(ctx, 3, key, &keylen); + uint8_t userkey[6] = {0}; + int keylen = 0; + CLIGetHexWithReturn(ctx, 3, userkey, &keylen); bool keyB = arg_get_lit(ctx, 4); bool swapmad = arg_get_lit(ctx, 5); bool decodeholder = arg_get_lit(ctx, 6); CLIParserFree(ctx); - if (aidlen != 2 && !decodeholder && keylen > 0) { - PrintAndLogEx(WARNING, "Using default MAD keys instead"); - } - uint8_t sector0[16 * 4] = {0}; uint8_t sector10[16 * 4] = {0}; + + bool got_first = true; if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0)) { PrintAndLogEx(ERR, "error, read sector 0. card don't have MAD or don't have MAD on default keys"); + got_first = false; + } + + // User supplied key + if (got_first == false && keylen == 6) { + if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, userkey, sector0)) { + PrintAndLogEx(ERR, "error, read sector 0. card don't have MAD or don't the custom key is wrong"); + } else { + got_first = true; + } + } + + // Both default and user supplied key failed + if (got_first == false) { return PM3_ESOFT; } +// if (aidlen != 2 && !decodeholder) { +// PrintAndLogEx(WARNING, "Using default MAD keys instead"); + + + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("MIFARE App Directory Information") " ----------------"); PrintAndLogEx(INFO, "-----------------------------------------------------"); @@ -4921,7 +4938,7 @@ static int CmdHF14AMfMAD(const char *Cmd) { // user specified key if (keylen == 6) { - memcpy(akey, key, 6); + memcpy(akey, userkey, 6); } uint16_t aaid = 0x0004; From c3ea0c83ada42c0533b4060d81031f4980ff4ec3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 30 Dec 2020 22:05:28 +0100 Subject: [PATCH 073/173] hf mf mad - text --- client/src/cmdhfmf.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 8cf0f4e1a..e9b87add6 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -4884,16 +4884,20 @@ static int CmdHF14AMfMAD(const char *Cmd) { uint8_t sector10[16 * 4] = {0}; bool got_first = true; - if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0)) { - PrintAndLogEx(ERR, "error, read sector 0. card don't have MAD or don't have MAD on default keys"); + if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "error, read sector 0. card don't have MAD or don't have MAD on default keys"); got_first = false; + } else { + PrintAndLogEx(INFO, "Authentication ( " _GREEN_("OK") " )"); } // User supplied key if (got_first == false && keylen == 6) { - if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, userkey, sector0)) { - PrintAndLogEx(ERR, "error, read sector 0. card don't have MAD or don't the custom key is wrong"); + PrintAndLogEx(INFO, "Trying user specified key..."); + if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, userkey, sector0) != PM3_SUCCESS) { + PrintAndLogEx(ERR, "error, read sector 0. card don't have MAD or don't the custom key is wrong"); } else { + PrintAndLogEx(INFO, "Authentication ( " _GREEN_("OK") " )"); got_first = true; } } @@ -4903,11 +4907,6 @@ static int CmdHF14AMfMAD(const char *Cmd) { return PM3_ESOFT; } -// if (aidlen != 2 && !decodeholder) { -// PrintAndLogEx(WARNING, "Using default MAD keys instead"); - - - PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("MIFARE App Directory Information") " ----------------"); PrintAndLogEx(INFO, "-----------------------------------------------------"); From 6d62f3f53c47e9f79463e8ef8355874fd6ce7d4a Mon Sep 17 00:00:00 2001 From: ikarus Date: Wed, 30 Dec 2020 23:10:53 +0100 Subject: [PATCH 074/173] hf_mf_format.lua: fixed off by one and typo. --- client/luascripts/hf_mf_format.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/luascripts/hf_mf_format.lua b/client/luascripts/hf_mf_format.lua index 0bde3c2d1..7aed6b757 100644 --- a/client/luascripts/hf_mf_format.lua +++ b/client/luascripts/hf_mf_format.lua @@ -14,7 +14,7 @@ This script will generate 'hf mf wrbl' commands for each block to format a Mifar Alla datablocks gets 0x00 As default the script sets the keys A/B to 0xFFFFFFFFFFFF and the access bytes will become 0x78,0x77,0x88 -The GDB will become 0x00 +The GPB will become 0x00 The script will skip the manufactoring block 0. ]] @@ -169,7 +169,7 @@ local function main(args) GetCardInfo() -- Show info - print( string.format('Estimating number of blocks: %d', numBlocks)) + print( string.format('Estimating number of blocks: %d', numBlocks + 1)) print( string.format('Old key: %s', OldKey)) print( string.format('New key: %s', NewKey)) print( string.format('New Access: %s', Accessbytes)) From 027ed5e5589b1c9f577bb28f57953a8369e75ee4 Mon Sep 17 00:00:00 2001 From: Gabriele Gristina Date: Thu, 31 Dec 2020 00:33:42 +0100 Subject: [PATCH 075/173] Fixed build errors on osx --- client/src/cmdhf14a.c | 2 +- client/src/cmdhfemrtd.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 8a6ce45ef..1048be3f5 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -2219,7 +2219,7 @@ static int CmdHf14AFindapdu(const char *Cmd) { bool inc_p1 = true; bool skip_ins = false; - uint64_t all_sw[256][256] = {0}; + uint64_t all_sw[256][256] = { { 0 } }; uint64_t sw_occurences = 0; uint64_t t_start = msclock(); uint64_t t_last_reset = msclock(); diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 2ba45f5b7..afe5b6b6f 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1777,8 +1777,8 @@ int infoHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab } // Grab the hash list - uint8_t dg_hashes_sod[17][64] = { 0x00 }; - uint8_t dg_hashes_calc[17][64] = { 0x00 }; + uint8_t dg_hashes_sod[17][64] = { { 0 } }; + uint8_t dg_hashes_calc[17][64] = { { 0 } }; int hash_algo = 0; if (!emrtd_select_and_read(response, &resplen, dg_table[EF_SOD].fileid, ks_enc, ks_mac, ssc, BAC, use_14b)) { @@ -1856,8 +1856,8 @@ int infoHF_EMRTD_offline(const char *path) { free(data); // Grab the hash list - uint8_t dg_hashes_sod[17][64] = { 0x00 }; - uint8_t dg_hashes_calc[17][64] = { 0x00 }; + uint8_t dg_hashes_sod[17][64] = { { 0 } }; + uint8_t dg_hashes_calc[17][64] = { { 0 } }; int hash_algo = 0; strcpy(filepath, path); From a9f4f4f80477913d41bf4b44600270e48031d1b6 Mon Sep 17 00:00:00 2001 From: tcprst Date: Wed, 30 Dec 2020 22:42:46 -0500 Subject: [PATCH 076/173] hf 14a config - now use cliparser --- armsrc/iso14443a.c | 2 +- client/src/cmdhf14a.c | 249 +++++++++++++++------------------------ client/src/cmdhf14a.h | 2 +- doc/cliparser_todo.txt | 1 - doc/magic_cards_notes.md | 24 ++-- 5 files changed, 108 insertions(+), 170 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index db00f5494..4776e555a 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -142,7 +142,7 @@ void printHf14aConfig(void) { Dbprintf(" [b] BCC override........%i %s%s%s", hf14aconfig.forcebcc, (hf14aconfig.forcebcc == 0) ? "( " _GREEN_("No") " ) follow standard" : "", - (hf14aconfig.forcebcc == 1) ? "( " _RED_("Yes") " ) always do CL2" : "", + (hf14aconfig.forcebcc == 1) ? "( " _RED_("Yes") " ) force fix of bad BCC" : "", (hf14aconfig.forcebcc == 2) ? "( " _RED_("Yes") " ) always use card BCC" : "" ); Dbprintf(" [2] CL2 override........%i %s%s%s", diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 1048be3f5..02b3a817e 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -170,45 +170,6 @@ const char *getTagInfo(uint8_t uid) { static uint16_t frameLength = 0; uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256}; -static int usage_hf_14a_config(void) { - PrintAndLogEx(NORMAL, "Usage: hf 14a config [a 0|1|2] [b 0|1|2] [2 0|1|2] [3 0|1|2]"); - PrintAndLogEx(NORMAL, "\nOptions:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " a 0|1|2 ATQA<>anticollision: 0=follow standard 1=execute anticol 2=skip anticol"); - PrintAndLogEx(NORMAL, " b 0|1|2 BCC: 0=follow standard 1=use fixed BCC 2=use card BCC"); - PrintAndLogEx(NORMAL, " 2 0|1|2 SAK<>CL2: 0=follow standard 1=execute CL2 2=skip CL2"); - PrintAndLogEx(NORMAL, " 3 0|1|2 SAK<>CL3: 0=follow standard 1=execute CL3 2=skip CL3"); - PrintAndLogEx(NORMAL, " r 0|1|2 SAK<>ATS: 0=follow standard 1=execute RATS 2=skip RATS"); - PrintAndLogEx(NORMAL, "\nExamples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config ")" Print current configuration"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 1 ")" Force execution of anticollision"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 0 ")" Restore ATQA interpretation"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config b 1 ")" Force fix of bad BCC in anticollision"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config b 0 ")" Restore BCC check"); - PrintAndLogEx(NORMAL, "\nExamples to revive Gen2/DirectWrite magic cards failing at anticollision:"); - PrintAndLogEx(NORMAL, _CYAN_(" MFC 1k 4b UID")":"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 1 b 2 2 2 r 2")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 11223344440804006263646566676869")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 0 b 0 2 0 r 0")); - PrintAndLogEx(NORMAL, _CYAN_(" MFC 4k 4b UID")":"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 1 b 2 2 2 r 2")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 11223344441802006263646566676869")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 0 b 0 2 0 r 0")); - PrintAndLogEx(NORMAL, _CYAN_(" MFC 1k 7b UID")":"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 1 b 2 2 1 3 2 r 2")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566084400626364656667")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 0 b 0 2 0 3 0 r 0")); - PrintAndLogEx(NORMAL, _CYAN_(" MFC 4k 7b UID")":"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 1 b 2 2 1 3 2 r 2")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566184200626364656667")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 0 b 0 2 0 3 0 r 0")); - PrintAndLogEx(NORMAL, _CYAN_(" MFUL ")"/" _CYAN_(" MFUL EV1 ")"/" _CYAN_(" MFULC")":"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 1 b 2 2 1 3 2 r 2")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu setuid 04112233445566")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 0 b 0 2 0 3 0 r 0")); - return PM3_SUCCESS; -} - static int CmdHF14AList(const char *Cmd) { char args[128] = {0}; if (strlen(Cmd) == 0) { @@ -237,142 +198,120 @@ int hf14a_getconfig(hf14a_config *config) { return PM3_SUCCESS; } -int hf14a_setconfig(hf14a_config *config) { +int hf14a_setconfig(hf14a_config *config, bool verbose) { if (!session.pm3_present) return PM3_ENOTTY; clearCommandBuffer(); - if (config != NULL) + if (config != NULL) { SendCommandNG(CMD_HF_ISO14443A_SET_CONFIG, (uint8_t *)config, sizeof(hf14a_config)); - else + if (verbose) { + SendCommandNG(CMD_HF_ISO14443A_PRINT_CONFIG, NULL, 0); + } + } else { SendCommandNG(CMD_HF_ISO14443A_PRINT_CONFIG, NULL, 0); + } return PM3_SUCCESS; } +static int hf_14a_config_example(void) { + PrintAndLogEx(NORMAL, "\nExamples to revive Gen2/DirectWrite magic cards failing at anticollision:"); + PrintAndLogEx(NORMAL, _CYAN_(" MFC 1k 4b UID")":"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 1 --bcc 2 --cl2 2 --rats 2")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 11223344440804006263646566676869")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 0 --bcc 0 --cl2 0 --rats 0")); + PrintAndLogEx(NORMAL, _CYAN_(" MFC 4k 4b UID")":"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 1 --bcc 2 --cl2 2 --rats 2")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 11223344441802006263646566676869")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 0 --bcc 0 --cl2 0 --rats 0")); + PrintAndLogEx(NORMAL, _CYAN_(" MFC 1k 7b UID")":"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 1 --bcc 2 --cl2 1 --cl3 2 --rats 2")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566084400626364656667")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 0 --bcc 0 --cl2 0 --rats 0")); + PrintAndLogEx(NORMAL, _CYAN_(" MFC 4k 7b UID")":"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 1 --bcc 2 --cl2 1 --cl3 2 --rats 2")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566184200626364656667")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 0 --bcc 0 --cl2 0 --rats 0")); + PrintAndLogEx(NORMAL, _CYAN_(" MFUL ")"/" _CYAN_(" MFUL EV1 ")"/" _CYAN_(" MFULC")":"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 1 --bcc 2 --cl2 1 --cl3 2 r 2")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu setuid 04112233445566")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 0 --bcc 0 --cl2 0 --rats 0")); + return PM3_SUCCESS; +} static int CmdHf14AConfig(const char *Cmd) { - if (!session.pm3_present) return PM3_ENOTTY; - // if called with no params, just print the device config + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 14a config", + "Configure 14a settings (use with caution)", + "hf 14a config -> Print current configuration\n" + "hf 14a config --atqa 0 -> Follow standard\n" + "hf 14a config --atqa 1 -> Force execution of anticollision\n" + "hf 14a config --atqa 2 -> Skip anticollision\n" + "hf 14a config --bcc 0 -> Follow standard\n" + "hf 14a config --bcc 1 -> Force fix of bad BCC in anticollision\n" + "hf 14a config --bcc 2 -> Use card BCC\n" + "hf 14a config --cl2 0 -> Follow standard\n" + "hf 14a config --cl2 1 -> Execute CL2\n" + "hf 14a config --cl2 2 -> Skip CL2\n" + "hf 14a config --cl3 0 -> Follow standard\n" + "hf 14a config --cl3 1 -> Execute CL3\n" + "hf 14a config --cl3 2 -> Skip CL3\n" + "hf 14a config --rats 0 -> Follow standard\n" + "hf 14a config --rats 1 -> Execute RATS\n" + "hf 14a config --rats 2 -> Skip RATS"); + + void *argtable[] = { + arg_param_begin, + arg_int0(NULL, "atqa", "", "Configure ATQA<>anticollision behavior"), + arg_int0(NULL, "bcc", "", "Configure BCC behavior"), + arg_int0(NULL, "cl2", "", "Configure SAK<>CL2 behavior"), + arg_int0(NULL, "cl3", "", "Configure SAK<>CL3 behavior"), + arg_int0(NULL, "rats", "", "Configure RATS behavior"), + arg_lit0("v", "verbose", "verbose output, also prints examples for reviving Gen2 cards"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int atqa = arg_get_int_def(ctx, 1, -1); + int bcc = arg_get_int_def(ctx, 2, -1); + int cl2 = arg_get_int_def(ctx, 3, -1); + int cl3 = arg_get_int_def(ctx, 4, -1); + int rats = arg_get_int_def(ctx, 5, -1); + + int *config_options[5] = {&atqa, &bcc, &cl2, &cl3, &rats}; + + bool verbose = arg_get_lit(ctx, 6); + + CLIParserFree(ctx); + + // validations if (strlen(Cmd) == 0) { - return hf14a_setconfig(NULL); + return hf14a_setconfig(NULL, verbose); } - hf14a_config config = { - .forceanticol = -1, - .forcebcc = -1, - .forcecl2 = -1, - .forcecl3 = -1, - .forcerats = -1 - }; + if (verbose) { + hf_14a_config_example(); + } - bool errors = false; - uint8_t cmdp = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (param_getchar(Cmd, cmdp)) { - case 'h': - return usage_hf_14a_config(); - case 'a': - switch (param_getchar(Cmd, cmdp + 1)) { - case '0': - config.forceanticol = 0; - break; - case '1': - config.forceanticol = 1; - break; - case '2': - config.forceanticol = 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown value '%c'", param_getchar(Cmd, cmdp + 1)); - errors = 1; - break; - } - cmdp += 2; - break; - case 'b': - switch (param_getchar(Cmd, cmdp + 1)) { - case '0': - config.forcebcc = 0; - break; - case '1': - config.forcebcc = 1; - break; - case '2': - config.forcebcc = 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown value '%c'", param_getchar(Cmd, cmdp + 1)); - errors = 1; - break; - } - cmdp += 2; - break; - case '2': - switch (param_getchar(Cmd, cmdp + 1)) { - case '0': - config.forcecl2 = 0; - break; - case '1': - config.forcecl2 = 1; - break; - case '2': - config.forcecl2 = 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown value '%c'", param_getchar(Cmd, cmdp + 1)); - errors = 1; - break; - } - cmdp += 2; - break; - case '3': - switch (param_getchar(Cmd, cmdp + 1)) { - case '0': - config.forcecl3 = 0; - break; - case '1': - config.forcecl3 = 1; - break; - case '2': - config.forcecl3 = 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown value '%c'", param_getchar(Cmd, cmdp + 1)); - errors = 1; - break; - } - cmdp += 2; - break; - case 'r': - switch (param_getchar(Cmd, cmdp + 1)) { - case '0': - config.forcerats = 0; - break; - case '1': - config.forcerats = 1; - break; - case '2': - config.forcerats = 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown value '%c'", param_getchar(Cmd, cmdp + 1)); - errors = 1; - break; - } - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = 1; - break; + for (int i = 0; i < 5; ++i) { + if (*config_options[i] > -1) { + if (*config_options[i] > 2) { + PrintAndLogEx(ERR, "Argument must be 0, 1, or 2"); + return PM3_EINVARG; + } } } - // validations - if (errors) return usage_hf_14a_config(); + hf14a_config config = { + .forceanticol = atqa, + .forcebcc = bcc, + .forcecl2 = cl2, + .forcecl3 = cl3, + .forcerats = rats + }; - return hf14a_setconfig(&config); + return hf14a_setconfig(&config, verbose); } int Hf14443_4aGetCardData(iso14a_card_select_t *card) { diff --git a/client/src/cmdhf14a.h b/client/src/cmdhf14a.h index 925bf8bef..a1a2279a0 100644 --- a/client/src/cmdhf14a.h +++ b/client/src/cmdhf14a.h @@ -27,7 +27,7 @@ int CmdHF14ASniff(const char *Cmd); // used by hf topaz sniff int CmdHF14ASim(const char *Cmd); // used by hf mfu sim int hf14a_getconfig(hf14a_config *config); -int hf14a_setconfig(hf14a_config *config); +int hf14a_setconfig(hf14a_config *config, bool verbose); int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search); const char *getTagInfo(uint8_t uid); int Hf14443_4aGetCardData(iso14a_card_select_t *card); diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 0a5e5c77e..7f5643b2f 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -41,7 +41,6 @@ data print data samples data setdebugmode data tune -hf 14a config hf 14b sriwrite hf 15 dump hf 15 info diff --git a/doc/magic_cards_notes.md b/doc/magic_cards_notes.md index 9e4cdce12..08aaa0386 100644 --- a/doc/magic_cards_notes.md +++ b/doc/magic_cards_notes.md @@ -45,12 +45,12 @@ Here are some tips if the card doesn't react or gives error on a simple `hf 14a Let's force a 4b UID anticollision and see what happens: ``` -hf 14a config a 1 b 2 2 2 r 2 +hf 14a config --atqa 1 --bcc 2 --cl2 2 --rats 2 hf 14a reader ``` It it responds, we know it's a TypeA card. But maybe it's a 7b UID, so let's force a 7b UID anticollision: ``` -hf 14a config a 1 b 2 2 1 3 2 r 2 +hf 14a config --atqa 1 --bcc 2 --cl2 1 --cl3 2 --rats 2 hf 14a reader ``` At this stage, you know if it's a TypeA 4b or 7b card and you can check further on this page how to reconfigure different types of cards. @@ -58,7 +58,7 @@ At this stage, you know if it's a TypeA 4b or 7b card and you can check further To restore anticollision config of the Proxmark3: ``` -hf 14a config a 0 b 0 2 0 3 0 r 0 +hf 14a config --atqa 0 --bcc 0 --cl2 0 --cl3 0 --rats 0 ``` # MIFARE Classic @@ -335,26 +335,26 @@ hf mf wrbl 0 A FFFFFFFFFFFF 11223344440804006263646566676869 When "soft-bricked" (by writing invalid data in block0), these ones may help: ``` -hf 14a config h +hf 14a config -h ``` e.g. for 4b UID: ``` -hf 14a config a 1 b 2 2 2 r 2 +hf 14a config --atqa 1 --bcc 2 --cl2 2 --rats 2 hf mf wrbl 0 A FFFFFFFFFFFF 11223344440804006263646566676869 # for 1k hf mf wrbl 0 A FFFFFFFFFFFF 11223344441802006263646566676869 # for 4k -hf 14a config a 0 b 0 2 0 r 0 +hf 14a config --atqa 0 --bcc 0 --cl2 0 --rats 0 hf 14a reader ``` e.g. for 7b UID: ``` -hf 14a config a 1 b 2 2 1 3 2 r 2 +hf 14a config --atqa 1 --bcc 2 --cl2 1 --cl3 2 --rats 2 hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566084400626364656667 # for 1k hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566184200626364656667 # for 4k -hf 14a config a 0 b 0 2 0 3 0 r 0 +hf 14a config --atqa 0 --bcc 0 --cl2 0 --cl3 0 --rats 0 hf 14a reader ``` ## MIFARE Classic DirectWrite, FUID version aka 1-write @@ -537,7 +537,7 @@ script run hf_mfu_setuid -h When "soft-bricked" (by writing invalid data in block0), these ones may help: ``` -hf 14a config h +hf 14a config -h script run run hf_mf_magicrevive -u ``` @@ -599,14 +599,14 @@ hf 14a raw -c a2 02 44480000 When "soft-bricked" (by writing invalid data in block0), these ones may help: ``` -hf 14a config h +hf 14a config -h ``` E.g.: ``` -hf 14a config a 1 b 2 2 1 3 2 r 2 +hf 14a config --atqa 1 --bcc 2 --cl2 1 --cl3 2 --rats 2 hf mfu setuid 04112233445566 -hf 14a config a 0 b 0 2 0 3 0 r 0 +hf 14a config --atqa 0 --bcc 0 --cl2 0 --cl3 0 --rats 0 hf 14a reader ``` From b956d4c148e3c07014375ab36429b1c48d205fa2 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 31 Dec 2020 11:39:57 +0100 Subject: [PATCH 077/173] hf 14a config cliparser: use string values --- armsrc/iso14443a.c | 45 ++++++------- client/src/cmdhf14a.c | 146 ++++++++++++++++++++++++++++-------------- 2 files changed, 117 insertions(+), 74 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 4776e555a..759e5e646 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -133,35 +133,30 @@ static hf14a_config hf14aconfig = { 0, 0, 0, 0, 0 } ; void printHf14aConfig(void) { DbpString(_CYAN_("HF 14a config")); - Dbprintf(" [a] Anticol override....%i %s%s%s", - hf14aconfig.forceanticol, - (hf14aconfig.forceanticol == 0) ? "( " _GREEN_("No") " ) follow standard " : "", - (hf14aconfig.forceanticol == 1) ? "( " _RED_("Yes") " ) always do anticol" : "", - (hf14aconfig.forceanticol == 2) ? "( " _RED_("Yes") " ) always skip anticol" : "" + Dbprintf(" [a] Anticol override....%s%s%s", + (hf14aconfig.forceanticol == 0) ? _GREEN_("std") " : follow standard " : "", + (hf14aconfig.forceanticol == 1) ? _RED_("force") " : always do anticol" : "", + (hf14aconfig.forceanticol == 2) ? _RED_("skip") " : always skip anticol" : "" ); - Dbprintf(" [b] BCC override........%i %s%s%s", - hf14aconfig.forcebcc, - (hf14aconfig.forcebcc == 0) ? "( " _GREEN_("No") " ) follow standard" : "", - (hf14aconfig.forcebcc == 1) ? "( " _RED_("Yes") " ) force fix of bad BCC" : "", - (hf14aconfig.forcebcc == 2) ? "( " _RED_("Yes") " ) always use card BCC" : "" + Dbprintf(" [b] BCC override........%s%s%s", + (hf14aconfig.forcebcc == 0) ? _GREEN_("std") " : follow standard" : "", + (hf14aconfig.forcebcc == 1) ? _RED_("fix") " : fix bad BCC" : "", + (hf14aconfig.forcebcc == 2) ? _RED_("ignore") " : ignore bad BCC, always use card BCC" : "" ); - Dbprintf(" [2] CL2 override........%i %s%s%s", - hf14aconfig.forcecl2, - (hf14aconfig.forcecl2 == 0) ? "( " _GREEN_("No") " ) follow standard" : "", - (hf14aconfig.forcecl2 == 1) ? "( " _RED_("Yes") " ) always do CL2" : "", - (hf14aconfig.forcecl2 == 2) ? "( " _RED_("Yes") " ) always skip CL2" : "" + Dbprintf(" [2] CL2 override........%s%s%s", + (hf14aconfig.forcecl2 == 0) ? _GREEN_("std") " : follow standard" : "", + (hf14aconfig.forcecl2 == 1) ? _RED_("force") " : always do CL2" : "", + (hf14aconfig.forcecl2 == 2) ? _RED_("skip") " : always skip CL2" : "" ); - Dbprintf(" [3] CL3 override........%i %s%s%s", - hf14aconfig.forcecl3, - (hf14aconfig.forcecl3 == 0) ? "( " _GREEN_("No") " ) follow standard" : "", - (hf14aconfig.forcecl3 == 1) ? "( " _RED_("Yes") " ) always do CL3" : "", - (hf14aconfig.forcecl3 == 2) ? "( " _RED_("Yes") " ) always skip CL3" : "" + Dbprintf(" [3] CL3 override........%s%s%s", + (hf14aconfig.forcecl3 == 0) ? _GREEN_("std") " : follow standard" : "", + (hf14aconfig.forcecl3 == 1) ? _RED_("force") " : always do CL3" : "", + (hf14aconfig.forcecl3 == 2) ? _RED_("skip") " : always skip CL3" : "" ); - Dbprintf(" [r] RATS override.......%i %s%s%s", - hf14aconfig.forcerats, - (hf14aconfig.forcerats == 0) ? "( " _GREEN_("No") " ) follow standard " : "", - (hf14aconfig.forcerats == 1) ? "( " _RED_("Yes") " ) always do RATS" : "", - (hf14aconfig.forcerats == 2) ? "( " _RED_("Yes") " ) always skip RATS" : "" + Dbprintf(" [r] RATS override.......%s%s%s", + (hf14aconfig.forcerats == 0) ? _GREEN_("std") " : follow standard " : "", + (hf14aconfig.forcerats == 1) ? _RED_("force") " : always do RATS" : "", + (hf14aconfig.forcerats == 2) ? _RED_("skip") " : always skip RATS" : "" ); } diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 02b3a817e..373e81d49 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -217,25 +217,25 @@ int hf14a_setconfig(hf14a_config *config, bool verbose) { static int hf_14a_config_example(void) { PrintAndLogEx(NORMAL, "\nExamples to revive Gen2/DirectWrite magic cards failing at anticollision:"); PrintAndLogEx(NORMAL, _CYAN_(" MFC 1k 4b UID")":"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 1 --bcc 2 --cl2 2 --rats 2")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 skip --rats skip")); PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 11223344440804006263646566676869")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 0 --bcc 0 --cl2 0 --rats 0")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std")); PrintAndLogEx(NORMAL, _CYAN_(" MFC 4k 4b UID")":"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 1 --bcc 2 --cl2 2 --rats 2")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 skip --rats skip")); PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 11223344441802006263646566676869")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 0 --bcc 0 --cl2 0 --rats 0")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std")); PrintAndLogEx(NORMAL, _CYAN_(" MFC 1k 7b UID")":"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 1 --bcc 2 --cl2 1 --cl3 2 --rats 2")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip --rats skip")); PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566084400626364656667")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 0 --bcc 0 --cl2 0 --rats 0")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std")); PrintAndLogEx(NORMAL, _CYAN_(" MFC 4k 7b UID")":"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 1 --bcc 2 --cl2 1 --cl3 2 --rats 2")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa forcce --bcc ignore --cl2 force --cl3 skip --rats skip")); PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566184200626364656667")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 0 --bcc 0 --cl2 0 --rats 0")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std")); PrintAndLogEx(NORMAL, _CYAN_(" MFUL ")"/" _CYAN_(" MFUL EV1 ")"/" _CYAN_(" MFULC")":"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 1 --bcc 2 --cl2 1 --cl3 2 r 2")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip -rats skip")); PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu setuid 04112233445566")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa 0 --bcc 0 --cl2 0 --rats 0")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std")); return PM3_SUCCESS; } static int CmdHf14AConfig(const char *Cmd) { @@ -244,44 +244,101 @@ static int CmdHf14AConfig(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf 14a config", "Configure 14a settings (use with caution)", - "hf 14a config -> Print current configuration\n" - "hf 14a config --atqa 0 -> Follow standard\n" - "hf 14a config --atqa 1 -> Force execution of anticollision\n" - "hf 14a config --atqa 2 -> Skip anticollision\n" - "hf 14a config --bcc 0 -> Follow standard\n" - "hf 14a config --bcc 1 -> Force fix of bad BCC in anticollision\n" - "hf 14a config --bcc 2 -> Use card BCC\n" - "hf 14a config --cl2 0 -> Follow standard\n" - "hf 14a config --cl2 1 -> Execute CL2\n" - "hf 14a config --cl2 2 -> Skip CL2\n" - "hf 14a config --cl3 0 -> Follow standard\n" - "hf 14a config --cl3 1 -> Execute CL3\n" - "hf 14a config --cl3 2 -> Skip CL3\n" - "hf 14a config --rats 0 -> Follow standard\n" - "hf 14a config --rats 1 -> Execute RATS\n" - "hf 14a config --rats 2 -> Skip RATS"); + "hf 14a config -> Print current configuration\n" + "hf 14a config --std -> Reset default configuration (follow standard)\n" + "hf 14a config --atqa std -> Follow standard\n" + "hf 14a config --atqa force -> Force execution of anticollision\n" + "hf 14a config --atqa skip -> Skip anticollision\n" + "hf 14a config --bcc std -> Follow standard\n" + "hf 14a config --bcc fix -> Fix bad BCC in anticollision\n" + "hf 14a config --bcc ignore -> Ignore bad BCC and use it as such\n" + "hf 14a config --cl2 std -> Follow standard\n" + "hf 14a config --cl2 force -> Execute CL2\n" + "hf 14a config --cl2 skip -> Skip CL2\n" + "hf 14a config --cl3 std -> Follow standard\n" + "hf 14a config --cl3 force -> Execute CL3\n" + "hf 14a config --cl3 skip -> Skip CL3\n" + "hf 14a config --rats std -> Follow standard\n" + "hf 14a config --rats force -> Execute RATS\n" + "hf 14a config --rats skip -> Skip RATS"); void *argtable[] = { arg_param_begin, - arg_int0(NULL, "atqa", "", "Configure ATQA<>anticollision behavior"), - arg_int0(NULL, "bcc", "", "Configure BCC behavior"), - arg_int0(NULL, "cl2", "", "Configure SAK<>CL2 behavior"), - arg_int0(NULL, "cl3", "", "Configure SAK<>CL3 behavior"), - arg_int0(NULL, "rats", "", "Configure RATS behavior"), + arg_str0(NULL, "atqa", "", "Configure ATQA<>anticollision behavior"), + arg_str0(NULL, "bcc", "", "Configure BCC behavior"), + arg_str0(NULL, "cl2", "", "Configure SAK<>CL2 behavior"), + arg_str0(NULL, "cl3", "", "Configure SAK<>CL3 behavior"), + arg_str0(NULL, "rats", "", "Configure RATS behavior"), + arg_lit0(NULL, "std", "Reset default configuration: follow all standard"), arg_lit0("v", "verbose", "verbose output, also prints examples for reviving Gen2 cards"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); + bool defaults = arg_get_lit(ctx, 6); + int vlen = 0; + char value[10]; + int atqa = defaults ? 0 : -1; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)value, sizeof(value), &vlen); + if (vlen > 0) { + if (strcmp(value, "std") == 0) atqa = 0; + else if (strcmp(value, "force") == 0) atqa = 1; + else if (strcmp(value, "skip") == 0) atqa = 2; + else { + PrintAndLogEx(ERR, "atqa argument must be 'std', 'force', or 'skip'"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } + int bcc = defaults ? 0 : -1; + CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)value, sizeof(value), &vlen); + if (vlen > 0) { + if (strcmp(value, "std") == 0) bcc = 0; + else if (strcmp(value, "fix") == 0) bcc = 1; + else if (strcmp(value, "ignore") == 0) bcc = 2; + else { + PrintAndLogEx(ERR, "bcc argument must be 'std', 'fix', or 'ignore'"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } + int cl2 = defaults ? 0 : -1; + CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)value, sizeof(value), &vlen); + if (vlen > 0) { + if (strcmp(value, "std") == 0) cl2 = 0; + else if (strcmp(value, "force") == 0) cl2 = 1; + else if (strcmp(value, "skip") == 0) cl2 = 2; + else { + PrintAndLogEx(ERR, "cl2 argument must be 'std', 'force', or 'skip'"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } + int cl3 = defaults ? 0 : -1; + CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)value, sizeof(value), &vlen); + if (vlen > 0) { + if (strcmp(value, "std") == 0) cl3 = 0; + else if (strcmp(value, "force") == 0) cl3 = 1; + else if (strcmp(value, "skip") == 0) cl3 = 2; + else { + PrintAndLogEx(ERR, "cl3 argument must be 'std', 'force', or 'skip'"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } + int rats = defaults ? 0 : -1; + CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)value, sizeof(value), &vlen); + if (vlen > 0) { + if (strcmp(value, "std") == 0) rats = 0; + else if (strcmp(value, "force") == 0) rats = 1; + else if (strcmp(value, "skip") == 0) rats = 2; + else { + PrintAndLogEx(ERR, "rats argument must be 'std', 'force', or 'skip'"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + } - int atqa = arg_get_int_def(ctx, 1, -1); - int bcc = arg_get_int_def(ctx, 2, -1); - int cl2 = arg_get_int_def(ctx, 3, -1); - int cl3 = arg_get_int_def(ctx, 4, -1); - int rats = arg_get_int_def(ctx, 5, -1); - - int *config_options[5] = {&atqa, &bcc, &cl2, &cl3, &rats}; - - bool verbose = arg_get_lit(ctx, 6); + bool verbose = arg_get_lit(ctx, 7); CLIParserFree(ctx); @@ -294,15 +351,6 @@ static int CmdHf14AConfig(const char *Cmd) { hf_14a_config_example(); } - for (int i = 0; i < 5; ++i) { - if (*config_options[i] > -1) { - if (*config_options[i] > 2) { - PrintAndLogEx(ERR, "Argument must be 0, 1, or 2"); - return PM3_EINVARG; - } - } - } - hf14a_config config = { .forceanticol = atqa, .forcebcc = bcc, From 0b3931f1b057f9c641711883d0d099c078b574f3 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 31 Dec 2020 11:44:19 +0100 Subject: [PATCH 078/173] adapt doc --- doc/magic_cards_notes.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/magic_cards_notes.md b/doc/magic_cards_notes.md index 08aaa0386..d24a0b7c5 100644 --- a/doc/magic_cards_notes.md +++ b/doc/magic_cards_notes.md @@ -45,12 +45,12 @@ Here are some tips if the card doesn't react or gives error on a simple `hf 14a Let's force a 4b UID anticollision and see what happens: ``` -hf 14a config --atqa 1 --bcc 2 --cl2 2 --rats 2 +hf 14a config --atqa force --bcc ignore --cl2 skip --rats skip hf 14a reader ``` It it responds, we know it's a TypeA card. But maybe it's a 7b UID, so let's force a 7b UID anticollision: ``` -hf 14a config --atqa 1 --bcc 2 --cl2 1 --cl3 2 --rats 2 +hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip --rats skip hf 14a reader ``` At this stage, you know if it's a TypeA 4b or 7b card and you can check further on this page how to reconfigure different types of cards. @@ -58,7 +58,7 @@ At this stage, you know if it's a TypeA 4b or 7b card and you can check further To restore anticollision config of the Proxmark3: ``` -hf 14a config --atqa 0 --bcc 0 --cl2 0 --cl3 0 --rats 0 +hf 14a config --std ``` # MIFARE Classic @@ -341,20 +341,20 @@ hf 14a config -h e.g. for 4b UID: ``` -hf 14a config --atqa 1 --bcc 2 --cl2 2 --rats 2 +hf 14a config --atqa force --bcc ignore --cl2 skip --rats skip hf mf wrbl 0 A FFFFFFFFFFFF 11223344440804006263646566676869 # for 1k hf mf wrbl 0 A FFFFFFFFFFFF 11223344441802006263646566676869 # for 4k -hf 14a config --atqa 0 --bcc 0 --cl2 0 --rats 0 +hf 14a config --std hf 14a reader ``` e.g. for 7b UID: ``` -hf 14a config --atqa 1 --bcc 2 --cl2 1 --cl3 2 --rats 2 +hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip --rats skip hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566084400626364656667 # for 1k hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566184200626364656667 # for 4k -hf 14a config --atqa 0 --bcc 0 --cl2 0 --cl3 0 --rats 0 +hf 14a config --std hf 14a reader ``` ## MIFARE Classic DirectWrite, FUID version aka 1-write @@ -604,9 +604,9 @@ hf 14a config -h E.g.: ``` -hf 14a config --atqa 1 --bcc 2 --cl2 1 --cl3 2 --rats 2 +hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip --rats skip hf mfu setuid 04112233445566 -hf 14a config --atqa 0 --bcc 0 --cl2 0 --cl3 0 --rats 0 +hf 14a config --std hf 14a reader ``` From afc4d78d68f0ca3e51bd997cd18f0ceeb53949b9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 31 Dec 2020 13:51:38 +0100 Subject: [PATCH 079/173] hf mfu eload/restore/sim/cauth - now uses cliparser --- client/src/cmdhfmfu.c | 371 ++++++++++++++++++++---------------------- 1 file changed, 173 insertions(+), 198 deletions(-) diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 2a32e0a8d..8d3e85c36 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -42,73 +42,6 @@ static int CmdHelp(const char *Cmd); -static int usage_hf_mfu_restore(void) { - PrintAndLogEx(NORMAL, "Restore dumpfile onto card."); - PrintAndLogEx(NORMAL, "Usage: hf mfu restore [h] [l] [s] k n "); - PrintAndLogEx(NORMAL, " Options :"); - PrintAndLogEx(NORMAL, " k : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); - PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); - PrintAndLogEx(NORMAL, " s : (optional) enable special write UID " _BLUE_("-MAGIC TAG ONLY-")); - PrintAndLogEx(NORMAL, " e : (optional) enable special write version/signature " _BLUE_("-MAGIC NTAG 21* ONLY-")); - PrintAndLogEx(NORMAL, " r : (optional) use the password found in dumpfile to configure tag. requires " _YELLOW_("'e'") " parameter to work"); - PrintAndLogEx(NORMAL, " f : " _YELLOW_("filename w .bin") " to restore"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu restore s f myfile")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu restore k AABBCCDD s f myfile")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu restore k AABBCCDD s e r f myfile")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} - -static int usage_hf_mfu_eload(void) { - PrintAndLogEx(NORMAL, "It loads emul dump from the file " _YELLOW_("`filename.eml`")); - PrintAndLogEx(NORMAL, "Hint: See " _YELLOW_("`script run hf_mfu_dumptoemulator`") " to convert the .bin to the eml"); - PrintAndLogEx(NORMAL, "Usage: hf mfu eload u [numblocks]"); - PrintAndLogEx(NORMAL, " Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, " u : UL (required)"); - PrintAndLogEx(NORMAL, " [filename] : without `.eml` (required)"); - PrintAndLogEx(NORMAL, " numblocks : number of blocks to load from eml file (optional)"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu eload u filename")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu eload u filename 57")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} - -static int usage_hf_mfu_sim(void) { - PrintAndLogEx(NORMAL, "\nEmulating Ultralight tag from emulator memory\n"); - PrintAndLogEx(NORMAL, "\nBe sure to load the emulator memory first!\n"); - PrintAndLogEx(NORMAL, "Usage: hf mfu sim t 7 u [n ]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, " t 7 : 7 = NTAG or Ultralight sim (required)"); - PrintAndLogEx(NORMAL, " n : exit simulation after blocks have been read by reader. 0 = infinite (optional)"); - PrintAndLogEx(NORMAL, " u : 4 or 7 byte UID (optional)"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu sim t 7")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu sim t 7 u 1122344556677")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu sim t 7 u 1122344556677 n 5")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} - -static int usage_hf_mfu_ucauth(void) { - PrintAndLogEx(NORMAL, "Tests 3DES password on Mifare Ultralight-C tag."); - PrintAndLogEx(NORMAL, "If password is not specified, a set of known defaults will be tested."); - PrintAndLogEx(NORMAL, "Usage: hf mfu cauth [k] "); - PrintAndLogEx(NORMAL, " k - keep field on (only if a password is provided too)"); - PrintAndLogEx(NORMAL, " [password] - (32 hex symbols)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu cauth")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu cauth 000102030405060708090a0b0c0d0e0f")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} - static int usage_hf_mfu_ucsetpwd(void) { PrintAndLogEx(NORMAL, "Set 3DES password on Mifare Ultralight-C tag."); PrintAndLogEx(NORMAL, "Usage: hf mfu setpwd "); @@ -349,10 +282,10 @@ static int try_default_3des_keys(uint8_t **correct_key) { uint8_t *key = default_3des_keys[i]; if (ulc_authentication(key, true)) { *correct_key = key; - return 1; + return PM3_SUCCESS; } } - return 0; + return PM3_ESOFT; } static int ulev1_requestAuthentication(uint8_t *pwd, uint8_t *pack, uint16_t packLength) { @@ -615,7 +548,7 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces) { memset(typestr, 0x00, sizeof(typestr)); if (tagtype & UL) - snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight (MF0ICU1)s"), spaces, ""); + snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight (MF0ICU1)"), spaces, ""); else if (tagtype & UL_C) snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight C (MF0ULC)"), spaces, ""); else if (tagtype & UL_NANO_40) @@ -676,7 +609,7 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces) { snprintf(typestr + strlen(typestr), 4, " ("); snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), " %s ", (tagtype & MAGIC) ? _GREEN_("magic") : ""); - tagtype ^= MAGIC; + tagtype &= ~(MAGIC); snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", (tagtype & MAGIC_1A) ? _GREEN_("Gen 1a") : ""); snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", (tagtype & MAGIC_1B) ? _GREEN_("Gen 1b") : ""); @@ -688,11 +621,11 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces) { } static int ulc_print_3deskey(uint8_t *data) { - PrintAndLogEx(NORMAL, " deskey1 [44/0x2C]: %s [%s]", sprint_hex(data, 4), sprint_ascii(data, 4)); - PrintAndLogEx(NORMAL, " deskey1 [45/0x2D]: %s [%s]", sprint_hex(data + 4, 4), sprint_ascii(data + 4, 4)); - PrintAndLogEx(NORMAL, " deskey2 [46/0x2E]: %s [%s]", sprint_hex(data + 8, 4), sprint_ascii(data + 8, 4)); - PrintAndLogEx(NORMAL, " deskey2 [47/0x2F]: %s [%s]", sprint_hex(data + 12, 4), sprint_ascii(data + 12, 4)); - PrintAndLogEx(NORMAL, "\n 3des key: %s", sprint_hex(SwapEndian64(data, 16, 8), 16)); + PrintAndLogEx(INFO, " deskey1 [44/0x2C]: %s [%s]", sprint_hex(data, 4), sprint_ascii(data, 4)); + PrintAndLogEx(INFO, " deskey1 [45/0x2D]: %s [%s]", sprint_hex(data + 4, 4), sprint_ascii(data + 4, 4)); + PrintAndLogEx(INFO, " deskey2 [46/0x2E]: %s [%s]", sprint_hex(data + 8, 4), sprint_ascii(data + 8, 4)); + PrintAndLogEx(INFO, " deskey2 [47/0x2F]: %s [%s]", sprint_hex(data + 12, 4), sprint_ascii(data + 12, 4)); + PrintAndLogEx(INFO, "3des key: " _GREEN_("%s"), sprint_hex_inrow(SwapEndian64(data, 16, 8), 16)); return PM3_SUCCESS; } @@ -839,7 +772,7 @@ static int ulev1_print_counters(void) { len = ulev1_readCounter(i, counter, sizeof(counter)); if (len == 3) { PrintAndLogEx(INFO, " [%0d]: %s", i, sprint_hex(counter, 3)); - PrintAndLogEx(SUCCESS, " - %02X tearing (%s)" + PrintAndLogEx(SUCCESS, " - %02X tearing ( %s )" , tear[0] , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail") ); @@ -930,7 +863,7 @@ static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *sig if (is_valid == false || i == ARRAYLEN(nxp_mfu_public_keys)) { PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1"); PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len)); - PrintAndLogEx(SUCCESS, " Signature verification (" _RED_("fail") ")"); + PrintAndLogEx(SUCCESS, " Signature verification ( " _RED_("fail") " )"); return PM3_ESOFT; } @@ -938,7 +871,7 @@ static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *sig PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfu_public_keys[i].value); PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1"); PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len)); - PrintAndLogEx(SUCCESS, " Signature verification (" _GREEN_("successful") ")"); + PrintAndLogEx(SUCCESS, " Signature verification ( " _GREEN_("successful") " )"); return PM3_SUCCESS; } @@ -968,7 +901,7 @@ static int ntag_print_counter(void) { len = ulev1_readCounter(0x02, counter, sizeof(counter)); (void)len; PrintAndLogEx(INFO, " [02]: %s", sprint_hex(counter, 3)); - PrintAndLogEx(SUCCESS, " - %02X tearing (%s)" + PrintAndLogEx(SUCCESS, " - %02X tearing ( %s )" , tear[0] , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail") ); @@ -1038,6 +971,19 @@ static int ul_magic_test(void) { return 0; } +static char *GenerateFilename(const char *prefix, const char *suffix) { + iso14a_card_select_t card; + if (ul_select(&card) == false) { + PrintAndLogEx(WARNING, "No tag found."); + return NULL; + } + + char *fptr = calloc(sizeof(char) * (strlen(prefix) + strlen(suffix)) + sizeof(card.uid) * 2 + 1, sizeof(uint8_t)); + strcpy(fptr, prefix); + FillFileNameByUID(fptr, card.uid, suffix, card.uidlen); + return fptr; +} + uint32_t GetHF14AMfU_Type(void) { TagTypeUL_t tagtype = UNKNOWN; @@ -1218,7 +1164,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0("k", "key", "", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"), - arg_lit0("l", NULL, "swap entered key's endianness"), + arg_lit0("l", NULL, "swap entered key's endianness"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -1319,7 +1265,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { } // also try to diversify default keys.. look into CmdHF14AMfGenDiverseKeys - if (try_default_3des_keys(&key)) { + if (try_default_3des_keys(&key) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "Found default 3des key: "); uint8_t keySwap[16]; memcpy(keySwap, SwapEndian64(key, 16, 8), 16); @@ -1425,7 +1371,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { num_to_bytes(ul_ev1_pwdgenA(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found default password " _GREEN_("%s") " pack %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); goto out; } @@ -1437,7 +1383,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { num_to_bytes(ul_ev1_pwdgenB(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found default password " _GREEN_("%s") " pack %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); goto out; } @@ -1449,7 +1395,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { num_to_bytes(ul_ev1_pwdgenC(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found default password " _GREEN_("%s") " pack %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); goto out; } @@ -1461,7 +1407,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { num_to_bytes(ul_ev1_pwdgenD(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(SUCCESS, "Found a default password:" _GREEN_("%s") " Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found default password" _GREEN_("%s") " pack %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); goto out; } @@ -1473,7 +1419,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { key = default_pwd_pack[i]; len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(SUCCESS, "Found a default password: " _GREEN_("%s") " Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found default password " _GREEN_("%s") " pack %02X %02X", sprint_hex(key, 4), pack[0], pack[1]); break; } else { if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) { @@ -1515,7 +1461,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0("k", "key", "", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"), - arg_lit0("l", NULL, "swap entered key's endianness"), + arg_lit0("l", NULL, "swap entered key's endianness"), arg_int1("b", "block", "", "block number to write"), arg_str1("d", "data", "", "block data (4 or 16 hex bytes, 16 hex bytes will do a compatibility write)"), arg_param_end @@ -1645,7 +1591,7 @@ static int CmdHF14AMfURdBl(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0("k", "key", "", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"), - arg_lit0("l", NULL, "swap entered key's endianness"), + arg_lit0("l", NULL, "swap entered key's endianness"), arg_int1("b", "block", "", "block number to write"), arg_param_end }; @@ -1729,7 +1675,7 @@ static int CmdHF14AMfURdBl(const char *Cmd) { PrintAndLogEx(INFO, "-----------------------------"); PrintAndLogEx(INFO, "%02d/0x%02X | %s| %s\n", blockno, blockno, sprint_hex(d, 4), sprint_ascii(d, 4)); } else { - PrintAndLogEx(WARNING, "Failed reading block: (%02x)", isOK); + PrintAndLogEx(WARNING, "Failed reading block: ( %02x )", isOK); } } else { PrintAndLogEx(WARNING, "Command execute time-out"); @@ -1906,7 +1852,7 @@ static int CmdHF14AMfUDump(const char *Cmd) { arg_param_begin, arg_str0("f", "file", "", "specify a filename for dump file"), arg_str0("k", "key", "", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"), - arg_lit0("l", NULL, "swap entered key's endianness"), + arg_lit0("l", NULL, "swap entered key's endianness"), arg_int0("p", "page", "", "manually set start page number to start from"), arg_int0("q", "qty", "", "manually set number of pages to dump"), arg_param_end @@ -2154,82 +2100,58 @@ static void wait4response(uint8_t b) { // Restore dump file onto tag // static int CmdHF14AMfURestore(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfu restore", + "Restore dumpfile onto card.", + "hf mfu restore -f myfile -s -> user specified filename and special write\n" + "hf mfu restore -f myfile -k AABBCCDD -s -> user specified filename, special write and use key\n" + "hf mfu restore -f myfile -k AABBCCDD -ser -> user specified filename, special write, use key, ..." + ); - char tempStr[50] = {0}; + void *argtable[] = { + arg_param_begin, + arg_str1("f", "file", "", "specify a filename to restore"), + arg_str0("k", "key", "", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"), + arg_lit0("l", NULL, "swap entered key's endianness"), + arg_lit0("s", NULL, "enable special write UID -MAGIC TAG ONLY-"), + arg_lit0("e", NULL, "enable special write version/signature -MAGIC NTAG 21* ONLY-"), + arg_lit0("r", NULL, "use the password found in dumpfile to configure tag. requires " _YELLOW_("'-e'") " parameter to work"), + arg_lit0("v", "verbose", "verbose"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int fnlen = 0; char filename[FILE_PATH_SIZE] = {0}; - uint8_t authkey[16] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + + int ak_len = 0; + uint8_t authkey[16] = {0x00}; uint8_t *p_authkey = authkey; - uint8_t cmdp = 0, keylen = 0; + CLIGetHexWithReturn(ctx, 2, authkey, &ak_len); + + bool swap_endian = arg_get_lit(ctx, 3); + bool write_special = arg_get_lit(ctx, 4); + bool write_extra = arg_get_lit(ctx, 5); + bool read_key = arg_get_lit(ctx, 6); + bool verbose = arg_get_lit(ctx, 7); + CLIParserFree(ctx); + bool hasKey = false; - bool swapEndian = false; - bool errors = false; - bool write_special = false; - bool write_extra = false; - bool read_key = false; - bool verbose = false; - size_t filelen = 0; - - memset(authkey, 0x00, sizeof(authkey)); - - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_mfu_restore(); - case 'k': - keylen = param_getstr(Cmd, cmdp + 1, tempStr, sizeof(tempStr)); - if (keylen == 32 || keylen == 8) { //ul-c or ev1/ntag key length - errors = param_gethex(tempStr, 0, authkey, keylen); - keylen /= 2; - } else { - PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); - errors = true; - } - cmdp += 2; - hasKey = true; - break; - case 'l': - swapEndian = true; - cmdp++; - break; - case 'f': - filelen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); - - if (filelen > FILE_PATH_SIZE - 5) - filelen = FILE_PATH_SIZE - 5; - - if (filelen < 1) - sprintf(filename, "dumpdata.bin"); - - cmdp += 2; - break; - case 's': - cmdp++; - write_special = true; - break; - case 'e': - cmdp++; - write_extra = true; - break; - case 'r': - cmdp++; - read_key = true; - break; - case 'v': - cmdp++; - verbose = true; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter: " _RED_("'%c'"), param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - - //Validations - if (errors || cmdp == 0) return usage_hf_mfu_restore(); uint8_t *dump = NULL; size_t bytes_read = 0; + + if (fnlen == 0) { + char *fptr = GenerateFilename("hf-mfu-", "-dump.bin"); + if (fptr != NULL) { + strcpy(filename, fptr); + } else { + snprintf(filename, sizeof(filename), "dumpdata.bin"); + } + free(fptr); + } + if (loadFile_safe(filename, "", (void **)&dump, &bytes_read) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Could not find file " _YELLOW_("%s"), filename); return PM3_EIO; @@ -2263,19 +2185,19 @@ static int CmdHF14AMfURestore(const char *Cmd) { printMFUdumpEx(mem, pages, 0); // Swap endianness - if (swapEndian && hasKey) { - if (keylen == 16) - p_authkey = SwapEndian64(authkey, keylen, 8); + if (swap_endian && hasKey) { + if (ak_len == 16) + p_authkey = SwapEndian64(authkey, ak_len, 8); else - p_authkey = SwapEndian64(authkey, keylen, 4); + p_authkey = SwapEndian64(authkey, ak_len, 4); } uint8_t data[20] = {0}; uint8_t keytype = 0; // set key - only once if (hasKey) { - keytype = (keylen == 16) ? 1 : 2; - memcpy(data + 4, p_authkey, keylen); + keytype = (ak_len == 16) ? 1 : 2; + memcpy(data + 4, p_authkey, ak_len); } // write version, signature, pack @@ -2379,16 +2301,54 @@ static int CmdHF14AMfURestore(const char *Cmd) { // Load emulator with dump file // static int CmdHF14AMfUeLoad(const char *Cmd) { - char c = tolower(param_getchar(Cmd, 0)); - if (c == 'h' || c == 0x00) return usage_hf_mfu_eload(); + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfu eload", + "It loads emul dump from the file `filename.eml`", + "hf mfu eload -u -f myfile\n" + "hf mfu eload -u -f myfile -q 57 -> load 57 blocks from myfile" + ); + + void *argtable[] = { + arg_param_begin, + arg_str1("f", "file", "", "specify a filename w/o `.eml` to load"), + arg_lit1("u", NULL, "Ultralight Family type"), + arg_int0("q", "qty", "", "number of blocks to load from eml file"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + CLIParserFree(ctx); + + PrintAndLogEx(HINT, "Hint: See " _YELLOW_("`script run hf_mfu_dumptoemulator`") " to convert the .bin to .eml"); return CmdHF14AMfELoad(Cmd); } // // Simulate tag // static int CmdHF14AMfUSim(const char *Cmd) { - char c = tolower(param_getchar(Cmd, 0)); - if (c == 'h' || c == 0x00) return usage_hf_mfu_sim(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfu sim", + "Simulate MIFARE Ultralight family type based upon\n" + "ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n" + "from emulator memory. See `hf mfu eload` first", + "hf mfu sim -t 2 --uid 1122344556677 -> MIFARE Ultralight\n" + "hf mfu sim -t 7 --uid 1122344556677 -n 5 -> AMIIBO (NTAG 215), pack 0x8080" + ); + + void *argtable[] = { + arg_param_begin, + arg_int1("t", "type", "<1-10> ", "Simulation type to use"), + arg_str0("u", "uid", "", "4, 7 or 10 byte UID"), + arg_int0("n", "num", "", "Exit simulation after blocks have been read by reader. 0 = infinite"), + arg_lit0("v", "verbose", "verbose output"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + CLIParserFree(ctx); return CmdHF14ASim(Cmd); } @@ -2396,43 +2356,58 @@ static int CmdHF14AMfUSim(const char *Cmd) { // Ultralight C Methods //------------------------------------------------------------------------------- -// // Ultralight C Authentication // - static int CmdHF14AMfUCAuth(const char *Cmd) { - uint8_t cmdp = 0; - char c = tolower(param_getchar(Cmd, 0)); - if (c == 'h') { - return usage_hf_mfu_ucauth(); - } - bool keep_field_on = false; - if (c == 'k') { - keep_field_on = true; - cmdp++; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfu cauth", + "Tests 3DES password on Mifare Ultralight-C tag.\n" + "If password is not specified, a set of known defaults will be tested.", + "hf mfu cauth\n" + "hf mfu cauth --key 000102030405060708090a0b0c0d0e0f" + ); + + void *argtable[] = { + arg_param_begin, + arg_str0("k", "key", "", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"), + arg_lit0("l", NULL, "swap entered key's endianness"), + arg_lit0("k", NULL, "keep field on (only if a password is provided too)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int ak_len = 0; + uint8_t authenticationkey[16] = {0x00}; + uint8_t *authKeyPtr = authenticationkey; + CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len); + bool swap_endian = arg_get_lit(ctx, 2); + bool keep_field_on = arg_get_lit(ctx, 3); + CLIParserFree(ctx); + + if (ak_len != 16 && ak_len != 0) { + PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); + return PM3_EINVARG; } - uint8_t key_buf[16]; - uint8_t *key; - int succeeded; + // Swap endianness + if (swap_endian && ak_len) { + authKeyPtr = SwapEndian64(authenticationkey, 16, 8); + } - // If no hex key is specified, try all known ones - if (strlen(Cmd + cmdp) == 0) { - succeeded = try_default_3des_keys(&key); - // Else try user-supplied + bool isok = false; + + // If no hex key is specified, try default keys + if (ak_len == 0) { + isok = (try_default_3des_keys(&authKeyPtr) == PM3_SUCCESS); } else { - if (param_gethex(Cmd, cmdp, key_buf, 32)) { - PrintAndLogEx(WARNING, "Password must include 32 HEX symbols"); - return PM3_EINVARG; - } - succeeded = ulc_authentication(key_buf, ! keep_field_on); - key = key_buf; + // try user-supplied + isok = ulc_authentication(authKeyPtr, !keep_field_on); } - if (succeeded) - PrintAndLogEx(SUCCESS, "Authentication successful. 3des key: %s", sprint_hex(key, 16)); + if (isok) + PrintAndLogEx(SUCCESS, "Authentication success. 3des key: " _GREEN_("%s"), sprint_hex_inrow(authKeyPtr, 16)); else - PrintAndLogEx(WARNING, "Authentication failed"); + PrintAndLogEx(WARNING, "Authentication ( " _RED_("fail") " )"); return PM3_SUCCESS; } @@ -3484,7 +3459,7 @@ static int CmdHF14MfuNDEF(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0("k", "key", "replace default key for NDEF", NULL), - arg_lit0("l", "key", "(optional) swap entered key's endianness"), + arg_lit0("l", NULL, "swap entered key's endianness"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); From d08f0d7fe8aed5899cdec4e2f3baead6e749e11a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 1 Jan 2021 21:01:10 +0100 Subject: [PATCH 080/173] hf mfu setpwd/setuid/keygen - now uses cliparser --- client/src/cmdhfmfu.c | 199 +++++++++++++++++++++--------------------- 1 file changed, 100 insertions(+), 99 deletions(-) diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 8d3e85c36..5f0548968 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -42,41 +42,7 @@ static int CmdHelp(const char *Cmd); -static int usage_hf_mfu_ucsetpwd(void) { - PrintAndLogEx(NORMAL, "Set 3DES password on Mifare Ultralight-C tag."); - PrintAndLogEx(NORMAL, "Usage: hf mfu setpwd "); - PrintAndLogEx(NORMAL, " [password] - (32 hex symbols)"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu setpwd 000102030405060708090a0b0c0d0e0f")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} -static int usage_hf_mfu_ucsetuid(void) { - PrintAndLogEx(NORMAL, "Usage: hf mfu setuid "); - PrintAndLogEx(NORMAL, " [uid] - (14 hex symbols)"); - PrintAndLogEx(NORMAL, "\n"); - PrintAndLogEx(NORMAL, "This only works for " _BLUE_("Magic Ultralight") " tags."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu setuid 11223344556677")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} - -static int usage_hf_mfu_gendiverse(void) { - PrintAndLogEx(NORMAL, "Usage: hf mfu gen [h] [r] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, " r : read uid from tag"); - PrintAndLogEx(NORMAL, " : 4 byte UID (optional)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu gen r")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu gen 11223344")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} static int usage_hf_mfu_pwdgen(void) { PrintAndLogEx(NORMAL, "Usage: hf mfu pwdgen [h|t] [r] "); @@ -2137,7 +2103,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { bool verbose = arg_get_lit(ctx, 7); CLIParserFree(ctx); - bool hasKey = false; + bool has_key = false; uint8_t *dump = NULL; size_t bytes_read = 0; @@ -2185,7 +2151,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { printMFUdumpEx(mem, pages, 0); // Swap endianness - if (swap_endian && hasKey) { + if (swap_endian && has_key) { if (ak_len == 16) p_authkey = SwapEndian64(authkey, ak_len, 8); else @@ -2195,7 +2161,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { uint8_t data[20] = {0}; uint8_t keytype = 0; // set key - only once - if (hasKey) { + if (has_key) { keytype = (ak_len == 16) ? 1 : 2; memcpy(data + 4, p_authkey, ak_len); } @@ -2209,16 +2175,15 @@ static int CmdHF14AMfURestore(const char *Cmd) { #define MFU_NTAG_SPECIAL_VERSION 0xFA #define MFU_NTAG_SPECIAL_SIGNATURE 0xF2 // pwd - if (hasKey || read_key) { + if (has_key || read_key) { + memcpy(data, p_authkey, 4); if (read_key) { // try reading key from dump and use. memcpy(data, mem->data + (bytes_read - MFU_DUMP_PREFIX_LENGTH - 8), 4); - } else { - memcpy(data, p_authkey, 4); } - PrintAndLogEx(NORMAL, "special PWD block written 0x%X - %s\n", MFU_NTAG_SPECIAL_PWD, sprint_hex(data, 4)); + PrintAndLogEx(INFO, "special PWD block written 0x%X - %s\n", MFU_NTAG_SPECIAL_PWD, sprint_hex(data, 4)); clearCommandBuffer(); SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, MFU_NTAG_SPECIAL_PWD, keytype, 0, data, sizeof(data)); @@ -2234,7 +2199,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { memcpy(data, mem->data + (bytes_read - MFU_DUMP_PREFIX_LENGTH - 4), 2); data[2] = 0; data[3] = 0; - PrintAndLogEx(NORMAL, "special PACK block written 0x%X - %s\n", MFU_NTAG_SPECIAL_PACK, sprint_hex(data, 4)); + PrintAndLogEx(INFO, "special PACK block written 0x%X - %s\n", MFU_NTAG_SPECIAL_PACK, sprint_hex(data, 4)); clearCommandBuffer(); SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, MFU_NTAG_SPECIAL_PACK, keytype, 0, data, sizeof(data)); wait4response(MFU_NTAG_SPECIAL_PACK); @@ -2242,7 +2207,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { // Signature for (uint8_t s = MFU_NTAG_SPECIAL_SIGNATURE, i = 0; s < MFU_NTAG_SPECIAL_SIGNATURE + 8; s++, i += 4) { memcpy(data, mem->signature + i, 4); - PrintAndLogEx(NORMAL, "special SIG block written 0x%X - %s\n", s, sprint_hex(data, 4)); + PrintAndLogEx(INFO, "special SIG block written 0x%X - %s\n", s, sprint_hex(data, 4)); clearCommandBuffer(); SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, s, keytype, 0, data, sizeof(data)); wait4response(s); @@ -2251,7 +2216,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { // Version for (uint8_t s = MFU_NTAG_SPECIAL_VERSION, i = 0; s < MFU_NTAG_SPECIAL_VERSION + 2; s++, i += 4) { memcpy(data, mem->version + i, 4); - PrintAndLogEx(NORMAL, "special VERSION block written 0x%X - %s\n", s, sprint_hex(data, 4)); + PrintAndLogEx(INFO, "special VERSION block written 0x%X - %s\n", s, sprint_hex(data, 4)); clearCommandBuffer(); SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, s, keytype, 0, data, sizeof(data)); wait4response(s); @@ -2271,14 +2236,14 @@ static int CmdHF14AMfURestore(const char *Cmd) { wait4response(b); PrintAndLogEx(NORMAL, "." NOLF); } - PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(NORMAL, ""); // write special data last if (write_special) { PrintAndLogEx(INFO, "Restoring configuration blocks.\n"); - PrintAndLogEx(NORMAL, "authentication with keytype[%x] %s\n", (uint8_t)(keytype & 0xff), sprint_hex(p_authkey, 4)); + PrintAndLogEx(INFO, "authentication with keytype[%x] %s\n", (uint8_t)(keytype & 0xff), sprint_hex(p_authkey, 4)); // otp, uid, lock, cfg1, cfg0, dynlockbits uint8_t blocks[] = {3, 0, 1, 2, pages - 5, pages - 4, pages - 3}; @@ -2288,13 +2253,13 @@ static int CmdHF14AMfURestore(const char *Cmd) { clearCommandBuffer(); SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data)); wait4response(b); - PrintAndLogEx(NORMAL, "special block written %u - %s\n", b, sprint_hex(data, 4)); + PrintAndLogEx(INFO, "special block written %u - %s\n", b, sprint_hex(data, 4)); } } DropField(); free(dump); - PrintAndLogEx(INFO, "Finish restore"); + PrintAndLogEx(INFO, "Restore finished"); return PM3_SUCCESS; } // @@ -2317,10 +2282,6 @@ static int CmdHF14AMfUeLoad(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); - - int fnlen = 0; - char filename[FILE_PATH_SIZE] = {0}; - CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); CLIParserFree(ctx); PrintAndLogEx(HINT, "Hint: See " _YELLOW_("`script run hf_mfu_dumptoemulator`") " to convert the .bin to .eml"); @@ -2513,26 +2474,38 @@ static int CmdTestDES(const char * cmd) // Mifare Ultralight C - Set password // static int CmdHF14AMfUCSetPwd(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfu setpwd", + "Set the 3DES key on MIFARE Ultralight-C tag. ", + "hf mfu setpwd --key 000102030405060708090a0b0c0d0e0f" + ); - uint8_t pwd[16] = {0x00}; - char cmdp = tolower(param_getchar(Cmd, 0)); + void *argtable[] = { + arg_param_begin, + arg_str0("k", "key", "", "New key (16 bytes)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int k_len = 0; + uint8_t key[16] = {0x00}; + CLIGetHexWithReturn(ctx, 1, key, &k_len); + CLIParserFree(ctx); - if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_ucsetpwd(); - - if (param_gethex(Cmd, 0, pwd, 32)) { - PrintAndLogEx(WARNING, "Password must include 32 HEX symbols"); + if (k_len != 16) { + PrintAndLogEx(WARNING, "Key must be 16 hex bytes"); return PM3_EINVARG; } clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFAREUC_SETPWD, 0, 0, 0, pwd, 16); + SendCommandMIX(CMD_HF_MIFAREUC_SETPWD, 0, 0, 0, key, sizeof(key)); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { if ((resp.oldarg[0] & 0xff) == 1) { - PrintAndLogEx(INFO, "Ultralight-C new password: %s", sprint_hex(pwd, 16)); + PrintAndLogEx(INFO, "Ultralight-C new key: %s", sprint_hex(key, sizeof(key))); } else { - PrintAndLogEx(WARNING, "Failed writing at block %u", (uint8_t)(resp.oldarg[1] & 0xff)); + PrintAndLogEx(WARNING, "Failed writing at block %u", (uint8_t)(resp.oldarg[1] & 0xFF)); return PM3_ESOFT; } } else { @@ -2546,20 +2519,35 @@ static int CmdHF14AMfUCSetPwd(const char *Cmd) { // Magic UL / UL-C tags - Set UID // static int CmdHF14AMfUCSetUid(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfu setuid", + "Set uid on MIFARE Ultralight tag.\n" + "This only works for `magic Ultralight` tags.", + "hf mfu setuid --uid 11223344556677" + ); - PacketResponseNG resp; + void *argtable[] = { + arg_param_begin, + arg_str0("uk", "uid", "", "new uid (7 bytes)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int u_len = 0; uint8_t uid[7] = {0x00}; - char cmdp = tolower(param_getchar(Cmd, 0)); + CLIGetHexWithReturn(ctx, 1, uid, &u_len); + CLIParserFree(ctx); - if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_ucsetuid(); - - if (param_gethex(Cmd, 0, uid, 14)) { - PrintAndLogEx(WARNING, "UID must include 14 HEX symbols"); + if (u_len != 7) { + PrintAndLogEx(WARNING, "UID must be 7 hex bytes"); return PM3_EINVARG; } PrintAndLogEx(INFO, "Please ignore possible transient BCC warnings"); + // read block2. + PacketResponseNG resp; clearCommandBuffer(); SendCommandMIX(CMD_HF_MIFAREU_READBL, 2, 0, 0, NULL, 0); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { @@ -2632,12 +2620,28 @@ static int CmdHF14AMfUCSetUid(const char *Cmd) { } static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfu keygen", + "Set the 3DES key on MIFARE Ultralight-C tag. ", + "hf mfu keygen -r\n" + "hf mfu keygen --uid 11223344556677" + ); - uint8_t uid[4]; - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_gendiverse(); + void *argtable[] = { + arg_param_begin, + arg_str0("u", "uid", "", "4|7 hex byte UID"), + arg_lit0("r", NULL, "read UID from tag"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int ulen = 0; + uint8_t uid[7]; + CLIGetHexWithReturn(ctx, 1, uid, &ulen); + bool read_tag = arg_get_lit(ctx, 2); + CLIParserFree(ctx); - if (cmdp == 'r') { + if (read_tag) { // read uid from tag clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0); @@ -2656,17 +2660,14 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { PrintAndLogEx(WARNING, "iso14443a card select failed"); return PM3_ESOFT; } - /* - if (card.uidlen != 4) { - PrintAndLogEx(WARNING, "Wrong sized UID, expected 4bytes got %d", card.uidlen); - return PM3_ESOFT; - } - */ - memcpy(uid, card.uid, card.uidlen); - } else { - if (param_gethex(Cmd, 0, uid, 8)) return usage_hf_mfu_gendiverse(); - } + if (card.uidlen != 4 && card.uidlen != 7) { + PrintAndLogEx(WARNING, "Wrong sized UID, expected 4|7 bytes got %d", card.uidlen); + return PM3_ESOFT; + } + ulen = card.uidlen; + memcpy(uid, card.uid, card.uidlen); + } uint8_t iv[8] = { 0x00 }; uint8_t block = 0x01; @@ -2687,10 +2688,10 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { mix[6] = block ^ uid[2]; mix[7] = uid[3]; - mbedtls_des3_context ctx; - mbedtls_des3_set2key_enc(&ctx, masterkey); + mbedtls_des3_context ctx_des3; + mbedtls_des3_set2key_enc(&ctx_des3, masterkey); - mbedtls_des3_crypt_cbc(&ctx // des3_context + mbedtls_des3_crypt_cbc(&ctx_des3 // des3_context , MBEDTLS_DES_ENCRYPT // int mode , sizeof(mix) // length , iv // iv[8] @@ -2699,12 +2700,12 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { ); PrintAndLogEx(SUCCESS, "-- 3DES version"); - PrintAndLogEx(SUCCESS, "Masterkey :\t %s", sprint_hex(masterkey, sizeof(masterkey))); - PrintAndLogEx(SUCCESS, "UID :\t %s", sprint_hex(uid, sizeof(uid))); - PrintAndLogEx(SUCCESS, "block :\t %0d", block); - PrintAndLogEx(SUCCESS, "Mifare key :\t %s", sprint_hex(mifarekeyA, sizeof(mifarekeyA))); - PrintAndLogEx(SUCCESS, "Message :\t %s", sprint_hex(mix, sizeof(mix))); - PrintAndLogEx(SUCCESS, "Diversified key: %s", sprint_hex(divkey + 1, 6)); + PrintAndLogEx(SUCCESS, "Masterkey......... %s", sprint_hex(masterkey, sizeof(masterkey))); + PrintAndLogEx(SUCCESS, "UID............... %s", sprint_hex(uid, ulen)); + PrintAndLogEx(SUCCESS, "block............. %0d", block); + PrintAndLogEx(SUCCESS, "Mifare key........ %s", sprint_hex(mifarekeyA, sizeof(mifarekeyA))); + PrintAndLogEx(SUCCESS, "Message........... %s", sprint_hex(mix, sizeof(mix))); + PrintAndLogEx(SUCCESS, "Diversified key... %s", sprint_hex(divkey + 1, 6)); for (int i = 0; i < ARRAYLEN(mifarekeyA); ++i) { dkeyA[i] = (mifarekeyA[i] << 1) & 0xff; @@ -2724,9 +2725,9 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { memcpy(dmkey + 16, dkeyA, 8); memset(iv, 0x00, 8); - mbedtls_des3_set3key_enc(&ctx, dmkey); + mbedtls_des3_set3key_enc(&ctx_des3, dmkey); - mbedtls_des3_crypt_cbc(&ctx // des3_context + mbedtls_des3_crypt_cbc(&ctx_des3 // des3_context , MBEDTLS_DES_ENCRYPT // int mode , sizeof(newpwd) // length , iv // iv[8] @@ -2735,12 +2736,12 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { ); PrintAndLogEx(SUCCESS, "\n-- DES version"); - PrintAndLogEx(SUCCESS, "Mifare dkeyA :\t %s", sprint_hex(dkeyA, sizeof(dkeyA))); - PrintAndLogEx(SUCCESS, "Mifare dkeyB :\t %s", sprint_hex(dkeyB, sizeof(dkeyB))); - PrintAndLogEx(SUCCESS, "Mifare ABA :\t %s", sprint_hex(dmkey, sizeof(dmkey))); - PrintAndLogEx(SUCCESS, "Mifare Pwd :\t %s", sprint_hex(newpwd, sizeof(newpwd))); + PrintAndLogEx(SUCCESS, "MIFARE dkeyA...... %s", sprint_hex(dkeyA, sizeof(dkeyA))); + PrintAndLogEx(SUCCESS, "MIFARE dkeyB...... %s", sprint_hex(dkeyB, sizeof(dkeyB))); + PrintAndLogEx(SUCCESS, "MIFARE ABA........ %s", sprint_hex(dmkey, sizeof(dmkey))); + PrintAndLogEx(SUCCESS, "MIFARE PWD........ %s", sprint_hex(newpwd, sizeof(newpwd))); - mbedtls_des3_free(&ctx); + mbedtls_des3_free(&ctx_des3); mbedtls_aes_context ctx_aes; uint8_t aes_iv[16] = { 0x00 }; @@ -2752,8 +2753,8 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { mbedtls_aes_free(&ctx_aes); PrintAndLogEx(SUCCESS, "\n-- AES version"); - PrintAndLogEx(SUCCESS, "Mifare AES m :\t %s", sprint_hex(aes_masterkey, sizeof(aes_masterkey))); - PrintAndLogEx(SUCCESS, "Mifare Div :\t %s", sprint_hex(aes_output, sizeof(aes_output))); + PrintAndLogEx(SUCCESS, "MIFARE AES mk..... %s", sprint_hex(aes_masterkey, sizeof(aes_masterkey))); + PrintAndLogEx(SUCCESS, "MIFARE Div........ %s", sprint_hex(aes_output, sizeof(aes_output))); // next. from the diversify_key method. return PM3_SUCCESS; From baa7ca086b7b302b402ef6a82a19ee9c749d3e2b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 1 Jan 2021 21:02:22 +0100 Subject: [PATCH 081/173] hf mfu eview - view emulator memory. Defaults to download and show 0xFF blocks * 4 bytes since we dont know the MFU tag type --- client/src/cmdhfmfu.c | 70 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 11 deletions(-) diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 5f0548968..d37321b1f 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -3550,26 +3550,74 @@ static int CmdHF14MfuNDEF(const char *Cmd) { free(records); return status; } + +static int CmdHF14AMfuEView(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfu eview", + "It displays emulator memory", + "hf mfu eview" + ); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + + uint16_t blocks = 0xFF; + uint16_t bytes = blocks * 4; + + uint8_t *dump = calloc(bytes, sizeof(uint8_t)); + if (dump == NULL) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); + return PM3_EMALLOC; + } + + PrintAndLogEx(INFO, "downloading from emulator memory"); + if (!GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false)) { + PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); + free(dump); + return PM3_ETIMEOUT; + } + + 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 * 4), 4)); + } + PrintAndLogEx(INFO, "----+-------------+-------"); + PrintAndLogEx(NORMAL, ""); + free(dump); + return PM3_SUCCESS; +} + //------------------------------------ // Menu Stuff //------------------------------------ static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"info", CmdHF14AMfUInfo, IfPm3Iso14443a, "Tag information"}, - {"dump", CmdHF14AMfUDump, IfPm3Iso14443a, "Dump Ultralight / Ultralight-C / NTAG tag to binary file"}, - {"restore", CmdHF14AMfURestore, IfPm3Iso14443a, "Restore a dump onto a MFU MAGIC tag"}, - {"eload", CmdHF14AMfUeLoad, IfPm3Iso14443a, "load Ultralight .eml dump file into emulator memory"}, - {"rdbl", CmdHF14AMfURdBl, IfPm3Iso14443a, "Read block"}, - {"wrbl", CmdHF14AMfUWrBl, IfPm3Iso14443a, "Write block"}, - {"cauth", CmdHF14AMfUCAuth, IfPm3Iso14443a, "Authentication - Ultralight C"}, - {"setpwd", CmdHF14AMfUCSetPwd, IfPm3Iso14443a, "Set 3des password - Ultralight-C"}, - {"setuid", CmdHF14AMfUCSetUid, IfPm3Iso14443a, "Set UID - MAGIC tags only"}, - {"sim", CmdHF14AMfUSim, IfPm3Iso14443a, "Simulate Ultralight from emulator memory"}, - {"gen", CmdHF14AMfUGenDiverseKeys, AlwaysAvailable, "Generate 3des mifare diversified keys"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("recovery") " -----------------------"}, + {"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"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("operations") " -----------------------"}, + {"cauth", CmdHF14AMfUCAuth, IfPm3Iso14443a, "Authentication - Ultralight-C"}, + {"dump", CmdHF14AMfUDump, IfPm3Iso14443a, "Dump MIFARE Ultralight family tag to binary file"}, + {"info", CmdHF14AMfUInfo, IfPm3Iso14443a, "Tag information"}, {"ndef", CmdHF14MfuNDEF, IfPm3Iso14443a, "Prints NDEF records from card"}, + {"rdbl", CmdHF14AMfURdBl, IfPm3Iso14443a, "Read block"}, + {"restore", CmdHF14AMfURestore, IfPm3Iso14443a, "Restore a dump onto a MFU MAGIC tag"}, + {"wrbl", CmdHF14AMfUWrBl, IfPm3Iso14443a, "Write block"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"}, + {"eload", CmdHF14AMfUeLoad, IfPm3Iso14443a, "load Ultralight .eml dump file into emulator memory"}, + {"eview", CmdHF14AMfuEView, IfPm3Iso14443a, "View emulator memory"}, + {"sim", CmdHF14AMfUSim, IfPm3Iso14443a, "Simulate MIFARE Ultralight from emulator memory"}, + {"setpwd", CmdHF14AMfUCSetPwd, IfPm3Iso14443a, "Set 3DES key - Ultralight-C"}, + {"setuid", CmdHF14AMfUCSetUid, IfPm3Iso14443a, "Set UID - MAGIC tags only"}, {NULL, NULL, NULL, NULL} }; From db213522d68b41e575ab0f347badaa52e3a7adf8 Mon Sep 17 00:00:00 2001 From: Samy Kamkar Date: Fri, 1 Jan 2021 15:47:47 -0800 Subject: [PATCH 082/173] Reorder Lua libs/includes to compile on macOS Jansson libs/include dirs were taking preference over the included Lua files, causing system Lua files to interfere with expected includes --- client/Makefile | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/client/Makefile b/client/Makefile index 9cfc4fc4b..29cc37180 100644 --- a/client/Makefile +++ b/client/Makefile @@ -115,21 +115,6 @@ STATICLIBS += $(HARDNESTEDLIB) LDLIBS +=$(HARDNESTEDLIBLD) INCLUDES += $(HARDNESTEDLIBINC) -## Jansson -ifneq ($(SKIPJANSSONSYSTEM),1) - JANSSONINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags jansson 2>/dev/null) - JANSSONLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs jansson 2>/dev/null) - ifneq ($(JANSSONLDLIBS),) - JANSSONLIB = - JANSSONLIBLD = $(JANSSONLDLIBS) - JANSSONLIBINC = $(JANSSONINCLUDES) - JANSSON_FOUND = 1 - endif -endif -STATICLIBS += $(JANSSONLIB) -LDLIBS += $(JANSSONLIBLD) -INCLUDES += $(JANSSONLIBINC) - ## Lua ifneq ($(SKIPLUASYSTEM),1) LUAINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags lua5.2 2>/dev/null) @@ -145,6 +130,21 @@ STATICLIBS += $(LUALIB) LDLIBS += $(LUALIBLD) INCLUDES += $(LUALIBINC) +## Jansson +ifneq ($(SKIPJANSSONSYSTEM),1) + JANSSONINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags jansson 2>/dev/null) + JANSSONLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs jansson 2>/dev/null) + ifneq ($(JANSSONLDLIBS),) + JANSSONLIB = + JANSSONLIBLD = $(JANSSONLDLIBS) + JANSSONLIBINC = $(JANSSONINCLUDES) + JANSSON_FOUND = 1 + endif +endif +STATICLIBS += $(JANSSONLIB) +LDLIBS += $(JANSSONLIBLD) +INCLUDES += $(JANSSONLIBINC) + ## mbed TLS # system library cannot be used because it is compiled by default without CMAC support STATICLIBS += $(MBEDTLSLIB) From 72896b902e37b484139d57a149efcb2befd5a1c5 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 2 Jan 2021 13:10:42 +0100 Subject: [PATCH 083/173] comment --- client/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/client/Makefile b/client/Makefile index 29cc37180..05a0979ae 100644 --- a/client/Makefile +++ b/client/Makefile @@ -131,6 +131,7 @@ LDLIBS += $(LUALIBLD) INCLUDES += $(LUALIBINC) ## Jansson +# Jansson section needs to be after Lua to avoid interferences on macOS if a locally incompatible Lua was available, see PR 1155 ifneq ($(SKIPJANSSONSYSTEM),1) JANSSONINCLUDES = $(shell $(PKG_CONFIG_ENV) pkg-config --cflags jansson 2>/dev/null) JANSSONLDLIBS = $(shell $(PKG_CONFIG_ENV) pkg-config --libs jansson 2>/dev/null) From 4e1a9694a21810cd2b218be96784a94d589e5e3d Mon Sep 17 00:00:00 2001 From: Gator96100 Date: Sun, 3 Jan 2021 02:49:40 +0100 Subject: [PATCH 084/173] Updated precompiled links Also x86 is no longer supported --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 56af79cda..578dccf7f 100644 --- a/README.md +++ b/README.md @@ -82,16 +82,13 @@ If you are having troubles with these files, contact the package maintainer @gat Ref: For Proxmark3 RDV4 -- [Precompiled builds for RDV40 dedicated x86](https://drive.google.com/open?id=13zUs-aiQkYaSl5KWrBtuW5IWCoHJPsue) -- [Precompiled builds for RDV40 dedicated x64](https://drive.google.com/open?id=1SyPB8t5Vo8O0Lh7PjNm3Kv-mO4BNbxjX) +- [Precompiled builds for RDV40 dedicated x64](https://www.proxmarkbuilds.org/#rdv40-64/) For Proxmark3 RDV4 with blueshark addon -- [Precompiled builds for RDV40 dedicated with Bluetooth addon x86](https://drive.google.com/open?id=1TqWYctkRvkLshQ1ZRBHPLDzYHR-asuMO) -- [Precompiled builds for RDV40 dedicated with Bluetooth addon x64](https://drive.google.com/open?id=17ful7u2QyYmMQzQzc5fAf8nJvyoDJfSL) +- [Precompiled builds for RDV40 dedicated with Bluetooth addon x64](https://www.proxmarkbuilds.org/#rdv40_bt-64/) Generice Proxmark3 devices (non RDV4), for Proxmark3 Easy, RDV1, RDV2, RDV3, etc etc -- [Precompiled builds for RRG / Iceman repository x86](https://drive.google.com/open?id=1PI3Xr1mussPBPnYGu4ZjWzGPARK4N7JR) -- [Precompiled builds for RRG / Iceman repository x64](https://drive.google.com/open?id=1uX9RtYGinuFrpHybu4xq_BE3HrobI20e) +- [Precompiled builds for RRG / Iceman repository x64](https://www.proxmarkbuilds.org/#rrg_other-64/) ## Roadmap From 9ce99862e89d38af219583a044ed65bad7652a60 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 4 Jan 2021 00:36:34 +0100 Subject: [PATCH 085/173] make style --- client/src/cmdhfmfu.c | 36 ++++++++++++++++++------------------ doc/commands.md | 23 ++++++++++++----------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index d37321b1f..b29c7ab26 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -2072,7 +2072,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { "hf mfu restore -f myfile -s -> user specified filename and special write\n" "hf mfu restore -f myfile -k AABBCCDD -s -> user specified filename, special write and use key\n" "hf mfu restore -f myfile -k AABBCCDD -ser -> user specified filename, special write, use key, ..." - ); + ); void *argtable[] = { arg_param_begin, @@ -2114,7 +2114,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { strcpy(filename, fptr); } else { snprintf(filename, sizeof(filename), "dumpdata.bin"); - } + } free(fptr); } @@ -2272,7 +2272,7 @@ static int CmdHF14AMfUeLoad(const char *Cmd) { "It loads emul dump from the file `filename.eml`", "hf mfu eload -u -f myfile\n" "hf mfu eload -u -f myfile -q 57 -> load 57 blocks from myfile" - ); + ); void *argtable[] = { arg_param_begin, @@ -2298,7 +2298,7 @@ static int CmdHF14AMfUSim(const char *Cmd) { "from emulator memory. See `hf mfu eload` first", "hf mfu sim -t 2 --uid 1122344556677 -> MIFARE Ultralight\n" "hf mfu sim -t 7 --uid 1122344556677 -n 5 -> AMIIBO (NTAG 215), pack 0x8080" - ); + ); void *argtable[] = { arg_param_begin, @@ -2326,7 +2326,7 @@ static int CmdHF14AMfUCAuth(const char *Cmd) { "If password is not specified, a set of known defaults will be tested.", "hf mfu cauth\n" "hf mfu cauth --key 000102030405060708090a0b0c0d0e0f" - ); + ); void *argtable[] = { arg_param_begin, @@ -2336,7 +2336,7 @@ static int CmdHF14AMfUCAuth(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - + int ak_len = 0; uint8_t authenticationkey[16] = {0x00}; uint8_t *authKeyPtr = authenticationkey; @@ -2359,7 +2359,7 @@ static int CmdHF14AMfUCAuth(const char *Cmd) { // If no hex key is specified, try default keys if (ak_len == 0) { - isok = (try_default_3des_keys(&authKeyPtr) == PM3_SUCCESS); + isok = (try_default_3des_keys(&authKeyPtr) == PM3_SUCCESS); } else { // try user-supplied isok = ulc_authentication(authKeyPtr, !keep_field_on); @@ -2478,7 +2478,7 @@ static int CmdHF14AMfUCSetPwd(const char *Cmd) { CLIParserInit(&ctx, "hf mfu setpwd", "Set the 3DES key on MIFARE Ultralight-C tag. ", "hf mfu setpwd --key 000102030405060708090a0b0c0d0e0f" - ); + ); void *argtable[] = { arg_param_begin, @@ -2486,7 +2486,7 @@ static int CmdHF14AMfUCSetPwd(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - + int k_len = 0; uint8_t key[16] = {0x00}; CLIGetHexWithReturn(ctx, 1, key, &k_len); @@ -2519,13 +2519,13 @@ static int CmdHF14AMfUCSetPwd(const char *Cmd) { // Magic UL / UL-C tags - Set UID // static int CmdHF14AMfUCSetUid(const char *Cmd) { - + CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfu setuid", "Set uid on MIFARE Ultralight tag.\n" "This only works for `magic Ultralight` tags.", "hf mfu setuid --uid 11223344556677" - ); + ); void *argtable[] = { arg_param_begin, @@ -2533,7 +2533,7 @@ static int CmdHF14AMfUCSetUid(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - + int u_len = 0; uint8_t uid[7] = {0x00}; CLIGetHexWithReturn(ctx, 1, uid, &u_len); @@ -2625,7 +2625,7 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { "Set the 3DES key on MIFARE Ultralight-C tag. ", "hf mfu keygen -r\n" "hf mfu keygen --uid 11223344556677" - ); + ); void *argtable[] = { arg_param_begin, @@ -2634,7 +2634,7 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - + int ulen = 0; uint8_t uid[7]; CLIGetHexWithReturn(ctx, 1, uid, &ulen); @@ -3556,7 +3556,7 @@ static int CmdHF14AMfuEView(const char *Cmd) { CLIParserInit(&ctx, "hf mfu eview", "It displays emulator memory", "hf mfu eview" - ); + ); void *argtable[] = { arg_param_begin, @@ -3610,10 +3610,10 @@ static command_t CommandTable[] = { {"info", CmdHF14AMfUInfo, IfPm3Iso14443a, "Tag information"}, {"ndef", CmdHF14MfuNDEF, IfPm3Iso14443a, "Prints NDEF records from card"}, {"rdbl", CmdHF14AMfURdBl, IfPm3Iso14443a, "Read block"}, - {"restore", CmdHF14AMfURestore, IfPm3Iso14443a, "Restore a dump onto a MFU MAGIC tag"}, + {"restore", CmdHF14AMfURestore, IfPm3Iso14443a, "Restore a dump onto a MFU MAGIC tag"}, {"wrbl", CmdHF14AMfUWrBl, IfPm3Iso14443a, "Write block"}, - {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"}, - {"eload", CmdHF14AMfUeLoad, IfPm3Iso14443a, "load Ultralight .eml dump file into emulator memory"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"}, + {"eload", CmdHF14AMfUeLoad, IfPm3Iso14443a, "load Ultralight .eml dump file into emulator memory"}, {"eview", CmdHF14AMfuEView, IfPm3Iso14443a, "View emulator memory"}, {"sim", CmdHF14AMfUSim, IfPm3Iso14443a, "Simulate MIFARE Ultralight from emulator memory"}, {"setpwd", CmdHF14AMfUCSetPwd, IfPm3Iso14443a, "Set 3DES key - Ultralight-C"}, diff --git a/doc/commands.md b/doc/commands.md index f10e7a2bf..fa960f973 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -400,20 +400,21 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`hf mfu help `|Y |`This help` -|`hf mfu info `|N |`Tag information` -|`hf mfu dump `|N |`Dump Ultralight / Ultralight-C / NTAG tag to binary file` -|`hf mfu restore `|N |`Restore a dump onto a MFU MAGIC tag` -|`hf mfu eload `|N |`load Ultralight .eml dump file into emulator memory` -|`hf mfu rdbl `|N |`Read block` -|`hf mfu wrbl `|N |`Write block` -|`hf mfu cauth `|N |`Authentication - Ultralight C` -|`hf mfu setpwd `|N |`Set 3des password - Ultralight-C` -|`hf mfu setuid `|N |`Set UID - MAGIC tags only` -|`hf mfu sim `|N |`Simulate Ultralight from emulator memory` -|`hf mfu gen `|Y |`Generate 3des mifare diversified keys` +|`hf mfu keygen `|Y |`Generate 3DES MIFARE diversified keys` |`hf mfu pwdgen `|Y |`Generate pwd from known algos` |`hf mfu otptear `|N |`Tear-off test on OTP bits` +|`hf mfu cauth `|N |`Authentication - Ultralight-C` +|`hf mfu dump `|N |`Dump MIFARE Ultralight family tag to binary file` +|`hf mfu info `|N |`Tag information` |`hf mfu ndef `|N |`Prints NDEF records from card` +|`hf mfu rdbl `|N |`Read block` +|`hf mfu restore `|N |`Restore a dump onto a MFU MAGIC tag` +|`hf mfu wrbl `|N |`Write block` +|`hf mfu eload `|N |`load Ultralight .eml dump file into emulator memory` +|`hf mfu eview `|N |`View emulator memory` +|`hf mfu sim `|N |`Simulate MIFARE Ultralight from emulator memory` +|`hf mfu setpwd `|N |`Set 3DES key - Ultralight-C` +|`hf mfu setuid `|N |`Set UID - MAGIC tags only` ### hf mfdes From eaee80f3d7a2fafabe54c125e7f690f9185697e0 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 4 Jan 2021 00:54:34 +0100 Subject: [PATCH 086/173] update changelog --- CHANGELOG.md | 7 ++++++- client/src/ui.c | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f890c8d5..b00aef560 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,12 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] -- Added `ICE_STATE_DUMP_SIM` - standalone mode for dumping/simming one iClass tag (@iconicsec) + - Added support for debugging ARM with JTAG & VSCode (@Gator96100) + - Added MFUL "Gen1b" suport to `hf_mfu_setuid.lua` (@iceman1001) + - Added possibility to get bargraph in `lf tune` and `hf tune` (@iceman1001, @doegox) + - Added `hf emrtd` ePassport dumping and parsing (@aveao) + - Added `aidsearch` to `hf 14b info` (@iceman1001) + - Added `ICE_STATE_DUMP_SIM` - standalone mode for dumping/simming one iClass tag (@iconicsec) - Added `lf em 4x50 eview` - show uploaded EM4x50 data in emul memory (@tharexde) - Fix `data rawdemod` parsing for psk2 and user defined clock (@cyberpunk-re) - Added `hf iclass encode` - encode a wiegand binary to a encrypted credential (@iceman1001) diff --git a/client/src/ui.c b/client/src/ui.c index b7e63e7dd..327d266bf 100644 --- a/client/src/ui.c +++ b/client/src/ui.c @@ -22,6 +22,7 @@ #include #ifdef HAVE_READLINE +//Load readline after stdio.h #include #endif From ecd52347fa021f8167147c3c46b3951e6b4e8a41 Mon Sep 17 00:00:00 2001 From: tcprst Date: Sun, 3 Jan 2021 19:27:20 -0500 Subject: [PATCH 087/173] Add support for Apple Silicon (M1) --- CHANGELOG.md | 1 + Makefile.defs | 5 +++++ client/CMakeLists.txt | 16 +++++++++++++--- client/Makefile | 7 +++---- ...ac-OS-X-Homebrew-Installation-Instructions.md | 16 ++++++++++++++++ 5 files changed, 38 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b00aef560..e5050bb6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fixed Makefile to account for changes when running on Apple Silicon (@tcprst) - Added support for debugging ARM with JTAG & VSCode (@Gator96100) - Added MFUL "Gen1b" suport to `hf_mfu_setuid.lua` (@iceman1001) - Added possibility to get bargraph in `lf tune` and `hf tune` (@iceman1001, @doegox) diff --git a/Makefile.defs b/Makefile.defs index b86b477aa..23dab5b32 100644 --- a/Makefile.defs +++ b/Makefile.defs @@ -57,6 +57,11 @@ else RANLIB= ranlib endif +# For detection of Apple Silicon +ifeq ($(platform),Darwin) + BREW_PREFIX = $(shell brew --prefix) +endif + ifeq ($(DEBUG),1) DEFCXXFLAGS = -g -O0 -pipe DEFCFLAGS = -g -O0 -fstrict-aliasing -pipe diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index ec1a28e60..ddfd288b2 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -32,7 +32,7 @@ find_package(PkgConfig) if (NOT SKIPQT EQUAL 1) if(APPLE AND EXISTS /usr/local/opt/qt5) # Homebrew installs Qt5 (up to at least 5.11.0) in - # /usr/local/qt5. Ensure that it can be found by CMake + # /usr/local/opt/qt5. Ensure that it can be found by CMake # since it is not in the default /usr/local prefix. # Add it to PATHS so that it doesn't override the # CMAKE_PREFIX_PATH environment variable. @@ -40,6 +40,16 @@ if (NOT SKIPQT EQUAL 1) # e.g. find_package(Qt5Core ${QT_FIND_PACKAGE_OPTIONS}) list(APPEND QT_FIND_PACKAGE_OPTIONS PATHS /usr/local/opt/qt5) endif(APPLE AND EXISTS /usr/local/opt/qt5) + if(APPLE AND EXISTS /opt/homebrew/opt/qt5) + # Homebrew on Apple Silicon installs Qt5 in + # /opt/homebrew/opt/qt5. Ensure that it can be found by CMake + # since it is not in the default /usr/local prefix. + # Add it to PATHS so that it doesn't override the + # CMAKE_PREFIX_PATH environment variable. + # QT_FIND_PACKAGE_OPTIONS should be passed to find_package, + # e.g. find_package(Qt5Core ${QT_FIND_PACKAGE_OPTIONS}) + list(APPEND QT_FIND_PACKAGE_OPTIONS PATHS /opt/homebrew/opt/qt5) + endif(APPLE AND EXISTS /opt/homebrew/opt/qt5) set(QT_PACKAGELIST Qt5Core Qt5Widgets @@ -77,8 +87,8 @@ endif (EMBED_READLINE OR EMBED_BZIP2) if (NOT SKIPREADLINE EQUAL 1) if (APPLE) - find_path(READLINE_INCLUDE_DIRS readline/readline.h /usr/local/opt/readline/include /opt/local/include /opt/include /usr/local/include /usr/include NO_DEFAULT_PATH) - find_library(READLINE_LIBRARIES readline /usr/local/opt/readline/lib /opt/local/lib /opt/lib /usr/local/lib /usr/lib NO_DEFAULT_PATH) + find_path(READLINE_INCLUDE_DIRS readline/readline.h /usr/local/opt/readline/include /opt/local/include /opt/include /usr/local/include /usr/include /opt/homebrew/opt/readline/include NO_DEFAULT_PATH) + find_library(READLINE_LIBRARIES readline /usr/local/opt/readline/lib /opt/local/lib /opt/lib /usr/local/lib /usr/lib /opt/homebrew/opt/readline/lib NO_DEFAULT_PATH) endif (APPLE) if (EMBED_READLINE) ExternalProject_Add(ncurses diff --git a/client/Makefile b/client/Makefile index 05a0979ae..a756a2ede 100644 --- a/client/Makefile +++ b/client/Makefile @@ -17,8 +17,7 @@ vpath %.dic dictionaries OBJDIR = obj ifeq ($(platform),Darwin) - # cf brew info qt: qt not symlinked anymore - PKG_CONFIG_ENV := PKG_CONFIG_PATH=/usr/local/opt/qt/lib/pkgconfig + PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/opt/qt/lib/pkgconfig endif ################### @@ -279,8 +278,8 @@ CXXINCLUDES += $(QTINCLUDES) ## Readline ifneq ($(SKIPREADLINE),1) ifeq ($(platform),Darwin) - LDLIBS += -L/usr/local/opt/readline/lib - INCLUDES += -I/usr/local/opt/readline/include + LDLIBS += -L$(BREW_PREFIX)/opt/readline/lib + INCLUDES += -I$(BREW_PREFIX)/opt/readline/include endif LDLIBS += -lreadline READLINE_FOUND = 1 diff --git a/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md b/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md index 6e21f852b..dbd2b2636 100644 --- a/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md @@ -1,5 +1,21 @@ # Homebrew (Mac OS X), automatic installation +## Apple Silicon (M1) Notes + +Ensure Rosetta 2 is installed as it's currently needed to run `arm-none-eabi-gcc` as it's delivered as a precombiled x86_64 binary. + +If you see an error like: + +```sh +bad CPU type in executable +``` + +Then you are missing Rosetta 2 and need to install it: `/usr/sbin/softwareupdate --install-rosetta` + +Homebrew has changed their prefix to differentiate between native Apple Silicon and Intel compiled binaries. The Makefile attempts to account for this but please note that whichever terminal or application you're using must be running under Architecture "Apple" as seen by Activity Monitor as all child processes inherit the Rosetta 2 environment of their parent. You can check which architecture you're currently running under with a `uname -m` in your terminal. + +Visual Studio Code still runs under Rosetta 2 and if you're developing for proxmark3 on an Apple Silicon Mac you might want to consider running the Insiders build which has support for running natively on Apple Silicon. + ## Install Proxmark3 tools These instructions comes from @Chrisfu, where we got the proxmark3.rb scriptfile from. From 4daf4a8d538b9ee3dfe2fc8002d8472eb67433f3 Mon Sep 17 00:00:00 2001 From: Ave Date: Mon, 4 Jan 2021 00:32:59 +0000 Subject: [PATCH 088/173] Create ubuntu-build-and-test.yml --- .github/workflows/ubuntu-build-and-test.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/workflows/ubuntu-build-and-test.yml diff --git a/.github/workflows/ubuntu-build-and-test.yml b/.github/workflows/ubuntu-build-and-test.yml new file mode 100644 index 000000000..8967451c9 --- /dev/null +++ b/.github/workflows/ubuntu-build-and-test.yml @@ -0,0 +1,12 @@ +name: Ubuntu Build and Test + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: make all + run: make all From e3119abd98373dee8b0900f4e280a0b00a371e84 Mon Sep 17 00:00:00 2001 From: Ave Date: Mon, 4 Jan 2021 00:38:58 +0000 Subject: [PATCH 089/173] Install deps on ubuntu builder Stolen from https://gitlab.com/mirrorbuilds/ci-configs/-/blob/master/iceman-pm3/.gitlab-ci.yml by @linuxgemini --- .github/workflows/ubuntu-build-and-test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ubuntu-build-and-test.yml b/.github/workflows/ubuntu-build-and-test.yml index 8967451c9..adecebcb8 100644 --- a/.github/workflows/ubuntu-build-and-test.yml +++ b/.github/workflows/ubuntu-build-and-test.yml @@ -8,5 +8,7 @@ jobs: steps: - uses: actions/checkout@v2 + - name: Install dependencies + run: apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg liblua5.2-0 lua5.2 sed - name: make all run: make all From cc9b80915117827f4f84a44f55424d8e1689aa4f Mon Sep 17 00:00:00 2001 From: Ave Date: Mon, 4 Jan 2021 00:44:41 +0000 Subject: [PATCH 090/173] sudo --- .github/workflows/ubuntu-build-and-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ubuntu-build-and-test.yml b/.github/workflows/ubuntu-build-and-test.yml index adecebcb8..86e8dd0a8 100644 --- a/.github/workflows/ubuntu-build-and-test.yml +++ b/.github/workflows/ubuntu-build-and-test.yml @@ -9,6 +9,6 @@ jobs: steps: - uses: actions/checkout@v2 - name: Install dependencies - run: apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg liblua5.2-0 lua5.2 sed + run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg liblua5.2-0 lua5.2 sed - name: make all run: make all From 37791bbbf84232cab6dbfc9782f509a47546afb5 Mon Sep 17 00:00:00 2001 From: Ave Date: Mon, 4 Jan 2021 00:46:28 +0000 Subject: [PATCH 091/173] Update and upgrade before installing deps --- .github/workflows/ubuntu-build-and-test.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ubuntu-build-and-test.yml b/.github/workflows/ubuntu-build-and-test.yml index 86e8dd0a8..3ec11b05a 100644 --- a/.github/workflows/ubuntu-build-and-test.yml +++ b/.github/workflows/ubuntu-build-and-test.yml @@ -8,6 +8,10 @@ jobs: steps: - uses: actions/checkout@v2 + - name: Update apt repos + run: sudo apt-get update + - name: Update packages + run: sudo apt-get upgrade -yqq - name: Install dependencies run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg liblua5.2-0 lua5.2 sed - name: make all From 2d6119b5cd4c19ee6b239f38ac5ed5480435032a Mon Sep 17 00:00:00 2001 From: Ave Date: Mon, 4 Jan 2021 00:57:05 +0000 Subject: [PATCH 092/173] Add tests to ubuntu CI --- .github/workflows/ubuntu-build-and-test.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ubuntu-build-and-test.yml b/.github/workflows/ubuntu-build-and-test.yml index 3ec11b05a..8bc11dbbf 100644 --- a/.github/workflows/ubuntu-build-and-test.yml +++ b/.github/workflows/ubuntu-build-and-test.yml @@ -14,5 +14,7 @@ jobs: run: sudo apt-get upgrade -yqq - name: Install dependencies run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg liblua5.2-0 lua5.2 sed - - name: make all - run: make all + - name: Build + run: make clean && make V=1 + - name: Test + run: make check From fdb28dd95e287ab00b2381114ecc609f50b2b81d Mon Sep 17 00:00:00 2001 From: Ave Date: Mon, 4 Jan 2021 04:05:19 +0300 Subject: [PATCH 093/173] github actions: add macos action --- .github/workflows/macos-build-and-test.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/macos-build-and-test.yml diff --git a/.github/workflows/macos-build-and-test.yml b/.github/workflows/macos-build-and-test.yml new file mode 100644 index 000000000..dff98dd2d --- /dev/null +++ b/.github/workflows/macos-build-and-test.yml @@ -0,0 +1,22 @@ +name: MacOS Build and Test + +on: [push, pull_request] + +jobs: + build: + runs-on: macos-latest + + steps: + - uses: actions/checkout@v2 + - name: Update brew repos + run: brew update + - name: Update packages + run: brew upgrade + - name: Tap RfidResearchGroup/proxmark3 + run: brew tap RfidResearchGroup/proxmark3 + - name: Install dependencies + run: readline qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc + - name: Build + run: make clean && make V=1 + - name: Test + run: make check From 7db332a6de4bf2f4abe62b9dca7aebf187fe96c8 Mon Sep 17 00:00:00 2001 From: Ave Date: Mon, 4 Jan 2021 04:13:27 +0300 Subject: [PATCH 094/173] gh actions: Add ubuntu with make w/ btaddon and cmake --- .../{macos-build-and-test.yml => macos.yml} | 0 .github/workflows/ubuntu-cmake.yml | 20 +++++++++++++++++++ .github/workflows/ubuntu-make-btaddon.yml | 20 +++++++++++++++++++ ...ntu-build-and-test.yml => ubuntu-make.yml} | 4 ++-- 4 files changed, 42 insertions(+), 2 deletions(-) rename .github/workflows/{macos-build-and-test.yml => macos.yml} (100%) create mode 100644 .github/workflows/ubuntu-cmake.yml create mode 100644 .github/workflows/ubuntu-make-btaddon.yml rename .github/workflows/{ubuntu-build-and-test.yml => ubuntu-make.yml} (92%) diff --git a/.github/workflows/macos-build-and-test.yml b/.github/workflows/macos.yml similarity index 100% rename from .github/workflows/macos-build-and-test.yml rename to .github/workflows/macos.yml diff --git a/.github/workflows/ubuntu-cmake.yml b/.github/workflows/ubuntu-cmake.yml new file mode 100644 index 000000000..539ac252d --- /dev/null +++ b/.github/workflows/ubuntu-cmake.yml @@ -0,0 +1,20 @@ +name: Ubuntu (cmake) Build and Test + +on: [push, pull_request] + +jobs: + build-and-test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Update apt repos + run: sudo apt-get update + - name: Update packages + run: sudo apt-get upgrade -yqq + - name: Install dependencies + run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg liblua5.2-0 lua5.2 sed + - name: Build + run: mkdir -p client/build && ( cd client/build && cmake .. && make VERBOSE=1 ) + - name: Test + run: make client/check CHECKARGS="--clientbin ./client/build/proxmark3" diff --git a/.github/workflows/ubuntu-make-btaddon.yml b/.github/workflows/ubuntu-make-btaddon.yml new file mode 100644 index 000000000..e8de696a7 --- /dev/null +++ b/.github/workflows/ubuntu-make-btaddon.yml @@ -0,0 +1,20 @@ +name: Ubuntu (make with BTADDON) Build and Test + +on: [push, pull_request] + +jobs: + build-and-test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Update apt repos + run: sudo apt-get update + - name: Update packages + run: sudo apt-get upgrade -yqq + - name: Install dependencies + run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg liblua5.2-0 lua5.2 sed + - name: Build + run: make clean && make V=1 PLATFORM_EXTRAS=BTADDON + - name: Test + run: make check diff --git a/.github/workflows/ubuntu-build-and-test.yml b/.github/workflows/ubuntu-make.yml similarity index 92% rename from .github/workflows/ubuntu-build-and-test.yml rename to .github/workflows/ubuntu-make.yml index 8bc11dbbf..958c9c35d 100644 --- a/.github/workflows/ubuntu-build-and-test.yml +++ b/.github/workflows/ubuntu-make.yml @@ -1,9 +1,9 @@ -name: Ubuntu Build and Test +name: Ubuntu (make) Build and Test on: [push, pull_request] jobs: - build: + build-and-test: runs-on: ubuntu-latest steps: From 3dfc068a284e4f49a7aa528983e0f6ba3f097f89 Mon Sep 17 00:00:00 2001 From: Ave Date: Mon, 4 Jan 2021 04:15:54 +0300 Subject: [PATCH 095/173] github actions: macos bugfix --- .github/workflows/macos.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index dff98dd2d..ff72a0e3d 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -8,9 +8,11 @@ jobs: steps: - uses: actions/checkout@v2 + - name: Brew python bug workaround + run: brew link --overwrite python - name: Update brew repos run: brew update - - name: Update packages + - name: Upgrade packages run: brew upgrade - name: Tap RfidResearchGroup/proxmark3 run: brew tap RfidResearchGroup/proxmark3 From 96127e0da3447bd93a50288990857834aacf9327 Mon Sep 17 00:00:00 2001 From: Ave Date: Mon, 4 Jan 2021 04:17:58 +0300 Subject: [PATCH 096/173] github actions: don't upgrade packages --- .github/workflows/macos.yml | 4 +--- .github/workflows/ubuntu-cmake.yml | 2 -- .github/workflows/ubuntu-make-btaddon.yml | 2 -- .github/workflows/ubuntu-make.yml | 2 -- 4 files changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index ff72a0e3d..3eb0b8584 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -12,12 +12,10 @@ jobs: run: brew link --overwrite python - name: Update brew repos run: brew update - - name: Upgrade packages - run: brew upgrade - name: Tap RfidResearchGroup/proxmark3 run: brew tap RfidResearchGroup/proxmark3 - name: Install dependencies - run: readline qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc + run: brew install readline qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc - name: Build run: make clean && make V=1 - name: Test diff --git a/.github/workflows/ubuntu-cmake.yml b/.github/workflows/ubuntu-cmake.yml index 539ac252d..dd99487f1 100644 --- a/.github/workflows/ubuntu-cmake.yml +++ b/.github/workflows/ubuntu-cmake.yml @@ -10,8 +10,6 @@ jobs: - uses: actions/checkout@v2 - name: Update apt repos run: sudo apt-get update - - name: Update packages - run: sudo apt-get upgrade -yqq - name: Install dependencies run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg liblua5.2-0 lua5.2 sed - name: Build diff --git a/.github/workflows/ubuntu-make-btaddon.yml b/.github/workflows/ubuntu-make-btaddon.yml index e8de696a7..0e11f01c3 100644 --- a/.github/workflows/ubuntu-make-btaddon.yml +++ b/.github/workflows/ubuntu-make-btaddon.yml @@ -10,8 +10,6 @@ jobs: - uses: actions/checkout@v2 - name: Update apt repos run: sudo apt-get update - - name: Update packages - run: sudo apt-get upgrade -yqq - name: Install dependencies run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg liblua5.2-0 lua5.2 sed - name: Build diff --git a/.github/workflows/ubuntu-make.yml b/.github/workflows/ubuntu-make.yml index 958c9c35d..f4f7d0113 100644 --- a/.github/workflows/ubuntu-make.yml +++ b/.github/workflows/ubuntu-make.yml @@ -10,8 +10,6 @@ jobs: - uses: actions/checkout@v2 - name: Update apt repos run: sudo apt-get update - - name: Update packages - run: sudo apt-get upgrade -yqq - name: Install dependencies run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libbz2-dev libbluetooth-dev libpython3-dev python3 python3-dev libpython3-all-dev liblua5.2-dev liblua5.2-0-dbg liblua5.2-0 lua5.2 sed - name: Build From 4a6b2d4390a4666e5208c4a8da3ae37ea68315fa Mon Sep 17 00:00:00 2001 From: Ave Date: Mon, 4 Jan 2021 04:26:56 +0300 Subject: [PATCH 097/173] github actions: Introduce build variants for macos too --- .github/workflows/macos-cmake.yaml | 20 +++++++++++++++++++ .github/workflows/macos-make-btaddon.yml | 20 +++++++++++++++++++ .../workflows/{macos.yml => macos-make.yml} | 4 +--- 3 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/macos-cmake.yaml create mode 100644 .github/workflows/macos-make-btaddon.yml rename .github/workflows/{macos.yml => macos-make.yml} (81%) diff --git a/.github/workflows/macos-cmake.yaml b/.github/workflows/macos-cmake.yaml new file mode 100644 index 000000000..8c6a41f37 --- /dev/null +++ b/.github/workflows/macos-cmake.yaml @@ -0,0 +1,20 @@ +name: MacOS (cmake) Build and Test + +on: [push, pull_request] + +jobs: + build: + runs-on: macos-latest + + steps: + - uses: actions/checkout@v2 + - name: Update brew repos + run: brew update + - name: Tap RfidResearchGroup/proxmark3 + run: brew tap RfidResearchGroup/proxmark3 + - name: Install dependencies + run: brew install readline qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc + - name: Build + run: mkdir -p client/build && ( cd client/build && cmake .. && make VERBOSE=1 ) + - name: Test + run: make client/check CHECKARGS="--clientbin ./client/build/proxmark3" diff --git a/.github/workflows/macos-make-btaddon.yml b/.github/workflows/macos-make-btaddon.yml new file mode 100644 index 000000000..9d5b75ff7 --- /dev/null +++ b/.github/workflows/macos-make-btaddon.yml @@ -0,0 +1,20 @@ +name: MacOS (make with BTADDON) Build and Test + +on: [push, pull_request] + +jobs: + build: + runs-on: macos-latest + + steps: + - uses: actions/checkout@v2 + - name: Update brew repos + run: brew update + - name: Tap RfidResearchGroup/proxmark3 + run: brew tap RfidResearchGroup/proxmark3 + - name: Install dependencies + run: brew install readline qt5 RfidResearchGroup/proxmark3/arm-none-eabi-gcc + - name: Build + run: make clean && make V=1 PLATFORM_EXTRAS=BTADDON + - name: Test + run: make check diff --git a/.github/workflows/macos.yml b/.github/workflows/macos-make.yml similarity index 81% rename from .github/workflows/macos.yml rename to .github/workflows/macos-make.yml index 3eb0b8584..a612bcda2 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos-make.yml @@ -1,4 +1,4 @@ -name: MacOS Build and Test +name: MacOS (make) Build and Test on: [push, pull_request] @@ -8,8 +8,6 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Brew python bug workaround - run: brew link --overwrite python - name: Update brew repos run: brew update - name: Tap RfidResearchGroup/proxmark3 From 38332d2fcf04f019a4001ae483f8c5db52d67d08 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 4 Jan 2021 11:11:05 +0100 Subject: [PATCH 098/173] hf mfu otptear/pwdgen - now supports cliparser --- client/src/cmdhfmfu.c | 289 +++++++++++++++++++---------------------- doc/cliparser_todo.txt | 15 --- 2 files changed, 137 insertions(+), 167 deletions(-) diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index b29c7ab26..9c0534c75 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -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] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, " t : selftest"); - PrintAndLogEx(NORMAL, " r : read uid from tag"); - PrintAndLogEx(NORMAL, " : 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 i l s d t \n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " b : (optional) block to run the test - default block: 8 (not OTP for safety)"); - PrintAndLogEx(NORMAL, " i