From 254beefda2b3a466293edf9ae98bc1402f43a070 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 28 Aug 2019 00:03:27 +0200 Subject: [PATCH 01/16] Fix mingw utf8->cp850 support --- client/Makefile | 2 +- client/proxmark3.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/Makefile b/client/Makefile index d9e43d445..fc7fa520b 100644 --- a/client/Makefile +++ b/client/Makefile @@ -73,7 +73,7 @@ ifneq (,$(PM3_SHARE_PATH)) PM3CFLAGS += -DPM3_SHARE_PATH=\"$(PM3_SHARE_PATH)\" endif ifneq (,$(findstring MINGW,$(platform))) - PM3CFLAGS += -mno-ms-bitfields + PM3CFLAGS += -mno-ms-bitfields -fexec-charset=cp850 endif CXXFLAGS ?= -Wall -Werror -O3 PM3CXXFLAGS = $(CXXFLAGS) -I../include diff --git a/client/proxmark3.c b/client/proxmark3.c index 6555ac0f2..6a23f4804 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -31,7 +31,7 @@ static void showBanner(void) { PrintAndLogEx(NORMAL, "\n"); -#if defined(__linux__) || (__APPLE__) +#if defined(__linux__) || (__APPLE__) || (_WIN32) PrintAndLogEx(NORMAL, _BLUE_("██████╗ ███╗ ███╗ ████╗ ") " ...iceman fork"); PrintAndLogEx(NORMAL, _BLUE_("██╔══██╗████╗ ████║ ══█║") " ...dedicated to " _BLUE_("RDV40")); PrintAndLogEx(NORMAL, _BLUE_("██████╔╝██╔████╔██║ ████╔╝")); From cbca61f6ba3e0e301c07abed6cd405150a230661 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 28 Aug 2019 19:25:15 +0200 Subject: [PATCH 02/16] searchAndList: hide temptative repo path --- client/fileutils.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/client/fileutils.c b/client/fileutils.c index 500bb7ef8..31e0aeed5 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -759,13 +759,14 @@ int convertOldMfuDump(uint8_t **dump, size_t *dumplen) { return PM3_SUCCESS; } -static int filelist(const char *path, const char *ext, bool last) { +static int filelist(const char *path, const char *ext, bool last, bool tentative) { struct dirent **namelist; int n; n = scandir(path, &namelist, NULL, alphasort); if (n == -1) { - PrintAndLogEx(NORMAL, "%s── %s => NOT FOUND", last ? "└" : "├", path); + if (!tentative) + PrintAndLogEx(NORMAL, "%s── %s", last ? "└" : "├", path); return PM3_EFILE; } @@ -781,25 +782,29 @@ static int filelist(const char *path, const char *ext, bool last) { } int searchAndList(const char *pm3dir, const char *ext) { + // display in same order as searched by searchFile + // try pm3 dirs in current workdir (dev mode) if (get_my_executable_directory() != NULL) { char script_directory_path[strlen(get_my_executable_directory()) + strlen(pm3dir) + 1]; strcpy(script_directory_path, get_my_executable_directory()); strcat(script_directory_path, pm3dir); - filelist(script_directory_path, ext, false); + filelist(script_directory_path, ext, false, true); } + // try pm3 dirs in user .proxmark3 (user mode) char *userpath = getenv("HOME"); if (userpath != NULL) { char script_directory_path[strlen(userpath) + strlen(PM3_USER_DIRECTORY) + strlen(pm3dir) + 1]; strcpy(script_directory_path, userpath); strcat(script_directory_path, PM3_USER_DIRECTORY); strcat(script_directory_path, pm3dir); - filelist(script_directory_path, ext, false); + filelist(script_directory_path, ext, false, false); } + // try pm3 dirs in pm3 installation dir (install mode) { char script_directory_path[strlen(PM3_SHARE_PATH) + strlen(pm3dir) + 1]; strcpy(script_directory_path, PM3_SHARE_PATH); strcat(script_directory_path, pm3dir); - filelist(script_directory_path, ext, true); + filelist(script_directory_path, ext, true, false); } return PM3_SUCCESS; } From 94f6a402e8d457130d6654953527d490e48a4671 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 28 Aug 2019 21:12:18 +0200 Subject: [PATCH 03/16] chg. prep for eload.. --- include/pm3_cmd.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 035e85405..dc48bd110 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -229,6 +229,10 @@ typedef struct { uint8_t key[6]; } PACKED mf_readblock_t; +typedef struct { + uint8_t sectorcnt; + uint8_t keytype; +} PACKED mfc_eload_t; // For the bootloader #define CMD_DEVICE_INFO 0x0000 From f3ab9632f058618720f006e8095639ef2ecc89ef Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 28 Aug 2019 21:12:32 +0200 Subject: [PATCH 04/16] return values --- client/mifare/mifarehost.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index d22073d02..54de89046 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -209,7 +209,8 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, // initialize storage for found keys icesector_t *tmp = calloc(sectorsCnt, sizeof(icesector_t)); if (tmp == NULL) - return 1; + return PM3_EMALLOC; + memcpy(tmp, resp.data.asBytes, sectorsCnt * sizeof(icesector_t)); for (int i = 0; i < sectorsCnt; i++) { @@ -227,11 +228,11 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, free(tmp); if (curr_keys == sectorsCnt * 2) - return 0; + return PM3_SUCCESS; if (lastChunk) - return 1; + return PM3_ESOFT; } - return 1; + return PM3_ESOFT; } // PM3 imp of J-Run mf_key_brute (part 2) From ad3fe38b45fe808fdb9fa9c6d888da3975f32d51 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 28 Aug 2019 21:15:32 +0200 Subject: [PATCH 05/16] fix: loaddictionary_save, now with correct mem clear. --- client/fileutils.c | 68 +++++++++++++++++++++++++--------------------- client/fileutils.h | 7 +++++ 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/client/fileutils.c b/client/fileutils.c index 31e0aeed5..c3c9f5acc 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -283,9 +283,9 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s } case jsfIclass: { JsonSaveStr(root, "FileType", "iclass"); - uint8_t uid[8] = {0}; - memcpy(uid, data, 8); - JsonSaveBufAsHexCompact(root, "$.Card.UID", uid, sizeof(uid)); + uint8_t csn[8] = {0}; + memcpy(csn, data, 8); + JsonSaveBufAsHexCompact(root, "$.Card.CSN", csn, sizeof(csn)); for (size_t i = 0; i < (datalen / 8); i++) { char path[PATH_MAX_LENGTH] = {0}; @@ -316,13 +316,13 @@ int createMfcKeyDump(uint8_t sectorsCnt, sector_t *e_sector, char *fptr) { int i; if (fptr == NULL) { - return 1; + return PM3_EINVARG; } FILE *fkeys = fopen(fptr, "wb"); if (fkeys == NULL) { PrintAndLogEx(WARNING, "Could not create file " _YELLOW_("%s"), fptr); - return 1; + return PM3_EFILE; } PrintAndLogEx(SUCCESS, "Printing keys to binary file " _YELLOW_("%s")"...", fptr); @@ -338,14 +338,14 @@ int createMfcKeyDump(uint8_t sectorsCnt, sector_t *e_sector, char *fptr) { fclose(fkeys); PrintAndLogEx(SUCCESS, "Found keys have been dumped to " _YELLOW_("%s")" --> 0xffffffffffff has been inserted for unknown keys.", fptr); - return 0; + return PM3_SUCCESS; } int loadFile(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen) { if (data == NULL) return 1; char *fileName = filenamemcopy(preferredName, suffix); - if (fileName == NULL) return 1; + if (fileName == NULL) return PM3_EINVARG; int retval = PM3_SUCCESS; @@ -363,23 +363,24 @@ int loadFile(const char *preferredName, const char *suffix, void *data, size_t m if (fsize <= 0) { PrintAndLogEx(FAILED, "error, when getting filesize"); - retval = 1; + retval = PM3_EFILE; goto out; } uint8_t *dump = calloc(fsize, sizeof(uint8_t)); if (!dump) { PrintAndLogEx(FAILED, "error, cannot allocate memory"); - retval = 2; + retval = PM3_EMALLOC; goto out; } size_t bytes_read = fread(dump, 1, fsize, f); + fclose(f); if (bytes_read != fsize) { PrintAndLogEx(FAILED, "error, bytes read mismatch file size"); free(dump); - retval = 3; + retval = PM3_EFILE; goto out; } @@ -396,9 +397,7 @@ int loadFile(const char *preferredName, const char *suffix, void *data, size_t m *datalen = bytes_read; out: - fclose(f); free(fileName); - return retval; } @@ -432,7 +431,7 @@ int loadFileEML(const char *preferredName, void *data, size_t *datalen) { break; fclose(f); PrintAndLogEx(FAILED, "File reading error."); - retval = 2; + retval = PM3_EFILE; goto out; } @@ -471,13 +470,13 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ root = json_load_file(fileName, 0, &error); if (!root) { PrintAndLogEx(ERR, "ERROR: json " _YELLOW_("%s") " error on line %d: %s", fileName, error.line, error.text); - retval = 2; + retval = PM3_ESOFT; goto out; } if (!json_is_object(root)) { PrintAndLogEx(ERR, "ERROR: Invalid json " _YELLOW_("%s") " format. root must be an object.", fileName); - retval = 3; + retval = PM3_ESOFT; goto out; } @@ -493,7 +492,7 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ size_t sptr = 0; for (int i = 0; i < 256; i++) { if (sptr + 16 > maxdatalen) { - retval = 5; + retval = PM3_EMALLOC; goto out; } @@ -515,7 +514,7 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ size_t sptr = 0; for (int i = 0; i < 256; i++) { if (sptr + 4 > maxdatalen) { - retval = 5; + retval = PM3_EMALLOC; goto out; } @@ -537,7 +536,7 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ size_t sptr = 0; for (size_t i = 0; i < (maxdatalen / 4); i++) { if (sptr + 4 > maxdatalen) { - retval = 5; + retval = PM3_EMALLOC; goto out; } @@ -559,7 +558,7 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ size_t sptr = 0; for (size_t i = 0; i < (maxdatalen / 8); i++) { if (sptr + 8 > maxdatalen) { - retval = 5; + retval = PM3_EMALLOC; goto out; } @@ -651,10 +650,8 @@ out: int loadFileDICTIONARY_safe(const char *preferredName, void **pdata, uint8_t keylen, uint16_t *keycnt) { - int block_size = 512; - int allocation_size = block_size; - size_t counter = 0; int retval = PM3_SUCCESS; + char *path; if (searchFile(&path, DICTIONARIES_SUBDIR, preferredName, ".dic") != PM3_SUCCESS) return PM3_EFILE; @@ -667,14 +664,20 @@ int loadFileDICTIONARY_safe(const char *preferredName, void **pdata, uint8_t key keylen = 6; } + size_t mem_size; + size_t block_size = 10 * keylen; + // double up since its chars keylen <<= 1; char line[255]; // allocate some space for the dictionary - *pdata = calloc(keylen * allocation_size, sizeof(uint8_t)); - if (*pdata == NULL) return PM3_EFILE; + *pdata = calloc( block_size , sizeof(uint8_t)); + if (*pdata == NULL) + return PM3_EFILE; + + mem_size = block_size; FILE *f = fopen(path, "r"); if (!f) { @@ -684,15 +687,17 @@ int loadFileDICTIONARY_safe(const char *preferredName, void **pdata, uint8_t key // read file while (fgets(line, sizeof(line), f)) { + // check if we have enough space (if not allocate more) - if ((*keycnt) >= allocation_size) { - allocation_size += block_size; - *pdata = realloc(*pdata, keylen * allocation_size * sizeof(uint8_t)); + if ( (*keycnt * (keylen >> 1) ) >= mem_size ) { + + mem_size += block_size; + *pdata = realloc(*pdata, mem_size); + if (*pdata == NULL) { return PM3_EFILE; } else { - // zero the new memory (safety first) - memset(*pdata + allocation_size - block_size, 0, block_size); + memset(*pdata + (mem_size - block_size), 0, block_size); } } @@ -714,10 +719,11 @@ int loadFileDICTIONARY_safe(const char *preferredName, void **pdata, uint8_t key uint64_t key = strtoull(line, NULL, 16); - num_to_bytes(key, keylen >> 1, *pdata + counter); + num_to_bytes(key, keylen >> 1, *pdata + (*keycnt * (keylen >> 1)) ); + (*keycnt)++; + memset(line, 0, sizeof(line)); - counter += (keylen >> 1); } fclose(f); PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") "keys from dictionary file " _YELLOW_("%s"), *keycnt, path); diff --git a/client/fileutils.h b/client/fileutils.h index 113cac222..7bfc7c138 100644 --- a/client/fileutils.h +++ b/client/fileutils.h @@ -62,6 +62,13 @@ typedef enum { // jsfT55xx, } JSONFileType; +typedef enum { + BIN = 0, + EML, + JSON, + DICTIONARY, +} DumpFileType_t; + int fileExists(const char *filename); /** From 8d9751ebe42fc2912e86c01109e417e1ead5a09f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 28 Aug 2019 21:16:09 +0200 Subject: [PATCH 06/16] fix: uint cant be negative.. --- client/cmdlft55xx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 965a5db0b..46cc3e017 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -2129,9 +2129,11 @@ static int CmdT55xxChkPwds(const char *Cmd) { uint16_t keycount = 0; int res = loadFileDICTIONARY_safe(filename, (void**) &keyBlock, 4, &keycount); - if (res != PM3_SUCCESS || keycount <= 0 || keyBlock == NULL) { + if (res != PM3_SUCCESS || keycount == 0 || keyBlock == NULL) { PrintAndLogEx(WARNING, "No keys found in file"); - if (keyBlock != NULL) free(keyBlock); + if (keyBlock != NULL) + free(keyBlock); + return PM3_ESOFT; } From 117ebf0beb618732e797dd3752638bc9e5c1ed6b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 28 Aug 2019 21:21:27 +0200 Subject: [PATCH 07/16] chg: 'hf mf ecfill' - now uses NG format. chg: 'hf mf eload' - now uses NG format. chg: 'hf mf fchk m' - now uses ecfill trick, if fchk got all keys, it will dump the card directly. sample: hf mf fchk 1 m (must have dictionaries uploaded to device) if all keys are found, you can now run hf mf esave to get a complete dump. --- client/cmdhfmf.c | 160 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 119 insertions(+), 41 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 0b7727031..cc435cb07 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -751,12 +751,56 @@ static uint8_t NumBlocksPerSector(uint8_t sectorNo) { return 16; } } + static uint8_t GetSectorFromBlockNo(uint8_t blockNo) { if (blockNo < 128) return blockNo / 4; else return 32 + ((128 - blockNo) / 16); } + +static char GetFormatFromSector(uint8_t sectorNo) { + switch (sectorNo) { + case MIFARE_MINI_MAXSECTOR: + return '0'; + case MIFARE_1K_MAXSECTOR: + return '1'; + case MIFARE_2K_MAXSECTOR: + return '2'; + case MIFARE_4K_MAXSECTOR: + return '4'; + default : + return ' '; + } +} + +static int FastDumpWithEcFill(uint8_t numsectors){ + PacketResponseNG resp; + + mfc_eload_t payload; + payload.sectorcnt = numsectors; + payload.keytype = 0; + + // ecfill key A + clearCommandBuffer(); + SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload)); + + int res = WaitForResponseTimeout(CMD_HF_MIFARE_EML_LOAD, &resp, 2000); + if ( res != PM3_SUCCESS) { + } + + // ecfill key B + payload.keytype = 1; + + clearCommandBuffer(); + SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload)); + res = WaitForResponseTimeout(CMD_HF_MIFARE_EML_LOAD, &resp, 2000); + if ( res != PM3_SUCCESS) { + + } + return PM3_SUCCESS; +} + static int CmdHF14AMfDump(const char *Cmd) { uint64_t t1 = msclock(); @@ -1242,7 +1286,12 @@ static int CmdHF14AMfNested(const char *Cmd) { } PrintAndLogEx(SUCCESS, "Testing known keys. Sector count=%d", SectorsCnt); - mfCheckKeys_fast(SectorsCnt, true, true, 1, ARRAYLEN(g_mifare_default_keys) + 1, keyBlock, e_sector, false); + int res = mfCheckKeys_fast(SectorsCnt, true, true, 1, ARRAYLEN(g_mifare_default_keys) + 1, keyBlock, e_sector, false); + if ( res == PM3_SUCCESS ) { + // all keys found + PrintAndLogEx(SUCCESS, "Fast check found all keys"); + goto jumptoend; + } uint64_t t2 = msclock() - t1; PrintAndLogEx(SUCCESS, "Time to check %d known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0); @@ -1329,6 +1378,7 @@ static int CmdHF14AMfNested(const char *Cmd) { } } +jumptoend: //print them printKeyTable(SectorsCnt, e_sector); @@ -1612,56 +1662,69 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { bool legacy_mfchk = false; bool prng_type = false; bool verbose = false; + bool has_filename = false; + bool errors = false; // Parse the options given by the user - ctmp = tolower(param_getchar(Cmd, 0)); - while ((ctmp = param_getchar(Cmd, cmdp))) { + while ( (ctmp = param_getchar(Cmd, cmdp)) && !errors ) { switch (tolower(ctmp)) { case 'h': return usage_hf14_autopwn(); case 'f': if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { PrintAndLogEx(FAILED, "Filename too long"); + errors = true; + } else { + has_filename = true; } - cmdp ++; + cmdp += 2; break; case 'l': legacy_mfchk = true; + cmdp++; break; case 'v': verbose = true; + cmdp++; break; case '*': // Get the number of sectors sectors_cnt = NumOfSectors(param_getchar(Cmd, cmdp + 1)); block_cnt = NumOfBlocks(param_getchar(Cmd, cmdp + 1)); - cmdp ++; + cmdp += 2; break; case 'k': // Get the known block number if (param_getchar(Cmd, cmdp + 1) == 0x00) { - PrintAndLogEx(WARNING, "Sector number is missing"); - return PM3_EINVARG; + errors = true; + break; } + blockNo = param_get8(Cmd, cmdp + 1); + // Get the knonwn block type ctmp = tolower(param_getchar(Cmd, cmdp + 2)); if (ctmp != 'a' && ctmp != 'b') { PrintAndLogEx(WARNING, "Key type must be A or B"); - return PM3_EINVARG; + errors = true; + break; } + if (ctmp != 'a') { keyType = 1; } + // Get the known block key if (param_gethex(Cmd, cmdp + 3, key, 12)) { PrintAndLogEx(WARNING, "Key must include 12 HEX symbols"); + errors = true; return PM3_EINVARG; } know_target_key = true; cmdp += 3; case 's': slow = true; + cmdp++; break; case 'i': SetSIMDInstr(SIMD_AUTO); @@ -1695,7 +1758,10 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", ctmp); return usage_hf14_autopwn(); } - cmdp++; + } + + if ( errors ) { + return usage_hf14_autopwn(); } // Create the key storage stucture @@ -1732,6 +1798,8 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { if (know_target_key == false) PrintAndLogEx(WARNING, "No known key was supplied, key recovery might fail"); else { + + PrintAndLogEx(INFO, "Validating known key"); if (mfCheckKeys(FirstBlockOfSector(blockNo), keyType, true, 1, key, &key64) == PM3_SUCCESS) { PrintAndLogEx(INFO, "Using key for the nested / hardnested | sector:" _RED_("%3d") " key type: "_RED_("%c") " key: " _RED_("%s"), @@ -1741,7 +1809,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { ); // Store the key for the nested / hardnested attack (if supplied by the user) - e_sector[blockNo].Key[keyType] = bytes_to_num(key, 6); + e_sector[blockNo].Key[keyType] = key64; e_sector[blockNo].foundKey[keyType] = 3; } else { know_target_key = false; @@ -1752,6 +1820,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { ); PrintAndLogEx(WARNING, "Falling back to dictionary"); } + // Check if the user supplied key is used by other sectors for (int i = 0; i < sectors_cnt; i++) { for (int j = 0; j < 2; j++) { @@ -1759,7 +1828,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, key, &key64) == PM3_SUCCESS) { e_sector[i].Key[j] = bytes_to_num(key, 6); e_sector[i].foundKey[j] = 4; - PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"), + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [" _YELLOW_("%s") "]", i, j ? 'B' : 'A', sprint_hex(key, sizeof(key)) @@ -1784,16 +1853,21 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { } } + bool load_success = true; // Load the dictionary - if (strlen(filename) != 0) { + if (has_filename) { int res = loadFileDICTIONARY_safe(filename, (void**) &keyBlock, 6, &key_cnt); - if (res != PM3_SUCCESS || key_cnt <= 0 || keyBlock == NULL) { + if (res != PM3_SUCCESS || key_cnt == 0 || keyBlock == NULL) { PrintAndLogEx(FAILED, "An error occurred while loading the dictionary! (we will use the default keys now)"); - if (keyBlock != NULL) free(keyBlock); - goto useDefaultKeys; + if (keyBlock != NULL) + free(keyBlock); + + load_success = false; } - } else { -useDefaultKeys: + + } + + if ( has_filename == false || load_success == false ) { keyBlock = calloc(ARRAYLEN(g_mifare_default_keys), 6); if (keyBlock == NULL) { free(e_sector); @@ -1804,6 +1878,7 @@ useDefaultKeys: num_to_bytes(g_mifare_default_keys[cnt], 6, keyBlock + cnt * 6); } key_cnt = ARRAYLEN(g_mifare_default_keys); + PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") "keys from hardcoded default array", key_cnt); } // Use the dictionary to find sector keys on the card @@ -1830,8 +1905,10 @@ useDefaultKeys: printf("\n"); fflush(stdout); } else { + int chunksize = key_cnt > (PM3_CMD_DATA_SIZE / 6) ? (PM3_CMD_DATA_SIZE / 6) : key_cnt; bool firstChunk = true, lastChunk = false; + for (uint8_t strategy = 1; strategy < 3; strategy++) { PrintAndLogEx(INFO, "Running strategy %u", strategy); // main keychunk loop @@ -1852,7 +1929,7 @@ useDefaultKeys: if (firstChunk) firstChunk = false; // all keys, aborted - if (res == 0 || res == 2) { + if (res == PM3_SUCCESS) { i = key_cnt; strategy = 3; break; // Exit the loop @@ -1866,9 +1943,9 @@ useDefaultKeys: // Analyse the dictionary attack for (int i = 0; i < sectors_cnt; i++) { for (int j = 0; j < 2; j++) { - if (e_sector[i].foundKey[j] == 1) { + if (e_sector[i].foundKey[j] > 0) { num_to_bytes(e_sector[i].Key[j], 6, tmp_key); - PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"), + PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [" _YELLOW_("%s") "]", i, j ? 'B' : 'A', sprint_hex(tmp_key, sizeof(tmp_key)) @@ -1918,19 +1995,9 @@ useDefaultKeys: PrintAndLogEx(SUCCESS, "\nFound valid key: %012" PRIx64 "\n", key64); break; } - num_to_bytes(key64, 6, key); - // Check if the darkside key is valid - if (mfCheckKeys(FirstBlockOfSector(blockNo), keyType, true, 1, key, &key64) != PM3_SUCCESS) { - PrintAndLogEx(FAILED, "The key generated by the darkside attack is not valid!" - _RED_("%3d") " key type: "_RED_("%c") " key: " _RED_("%s"), - blockNo, - keyType ? 'B' : 'A', - sprint_hex(key, sizeof(key)) - ); - goto noValidKeyFound; - } + // Store the keys - e_sector[blockNo].Key[keyType] = bytes_to_num(key, 6); + e_sector[blockNo].Key[keyType] = key64; e_sector[blockNo].foundKey[keyType] = 2; } else { noValidKeyFound: @@ -1940,6 +2007,7 @@ noValidKeyFound: return PM3_ESOFT; } } + free(keyBlock); // Clear the needed variables num_to_bytes(0, 6, tmp_key); @@ -2139,13 +2207,8 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack mfEmlSetMem(block, FirstBlockOfSector(current_sector_i) + NumBlocksPerSector(current_sector_i) - 1, 1); } - // using ecfill trick, keys already in emulator mem, load data using Key A - clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFARE_EML_LOAD, sectors_cnt, 0, 0, NULL, 0); - - // using ecfill trick, keys already in emulator mem, load data using Key B - clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFARE_EML_LOAD, sectors_cnt, 1, 0, NULL, 0); + // use ecfill trick + FastDumpWithEcFill(sectors_cnt); bytes = block_cnt * MFBLOCK_SIZE; dump = calloc(bytes, sizeof(uint8_t)); @@ -2388,7 +2451,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { firstChunk = false; // all keys, aborted - if (res == 0 || res == 2) + if (res == PM3_SUCCESS || res == 2) goto out; } // end chunks of keys firstChunk = true; @@ -2416,6 +2479,13 @@ out: printKeyTable(sectorsCnt, e_sector); + if ( use_flashmemory && found_keys == (sectorsCnt << 1) ) { + PrintAndLogEx(SUCCESS, "Card dumped aswell. run " _YELLOW_("`%s %c`"), + "hf mf esave", + GetFormatFromSector(sectorsCnt) + ); + } + if (transferToEml) { // fast push mode conn.block_after_ACK = true; @@ -2434,6 +2504,10 @@ out: mfEmlSetMem(block, blockno, 1); } PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory"); + + if ( found_keys == (sectorsCnt << 1) ) { + FastDumpWithEcFill(sectorsCnt); + } } if (createDumpFile) { @@ -3411,8 +3485,12 @@ static int CmdHF14AMfECFill(const char *Cmd) { } PrintAndLogEx(NORMAL, "--params: numSectors: %d, keyType: %c\n", numSectors, (keyType == 0) ? 'A' : 'B'); + + mfc_eload_t payload; + payload.sectorcnt = numSectors; + payload.keytype = keyType; clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFARE_EML_LOAD, numSectors, keyType, 0, NULL, 0); + SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload)); return PM3_SUCCESS; } From 28d703d6df0f839b33992cab4c3e0233be81596a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 28 Aug 2019 21:21:52 +0200 Subject: [PATCH 08/16] chg: eload NG --- armsrc/appmain.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index b593c826b..13aa6bc84 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1134,7 +1134,8 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_HF_MIFARE_EML_LOAD: { - MifareECardLoad(packet->oldarg[0], packet->oldarg[1]); + mfc_eload_t *payload = (mfc_eload_t *) packet->data.asBytes; + MifareECardLoadExt(payload->sectorcnt, payload->keytype); break; } // Work with "magic Chinese" card From 501182ca06b6c58bbd9bf1565331bfe3ed0448d2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 28 Aug 2019 21:23:31 +0200 Subject: [PATCH 09/16] chg: ecload NG, fchk use ecfill trick --- armsrc/mifarecmd.c | 89 +++++++++++++++++++++++++++++----------------- armsrc/mifarecmd.h | 3 +- 2 files changed, 59 insertions(+), 33 deletions(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 63cf1128d..17570e680 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1342,8 +1342,6 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da for (uint16_t i = s_point; i < keyCount; ++i) { - //if ( i % 100 == 0) Dbprintf("ChkKeys_fast: sector %d | checking %d | %d found | s_point %d", s, i, foundkeys, s_point); - // Allow button press / usb cmd to interrupt device if (BUTTON_PRESS() && !data_available()) { goto OUT; @@ -1525,6 +1523,33 @@ OUT: FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); BigBuf_free(); BigBuf_Clear_ext(false); + + // special trick ecfill + if (use_flashmem && foundkeys == allkeys) { + + uint8_t block[16] = {0}; + for (int i = 0; i < sectorcnt; i++) { + + uint8_t blockno; + if (i < 32) { + blockno = (i * 4) ^ 0x3; + } else { + blockno = (32 * 4 + (i - 32) * 16) ^ 0xF; + } + // get ST + emlGetMem(block, blockno, 1); + + memcpy(block, k_sector[i].keyA, 6); + memcpy(block + 10, k_sector[i].keyB, 6); + + emlSetMem_xt(block, blockno, 1, sizeof(block)); + } + int oldbg = DBGLEVEL; + DBGLEVEL = DBG_NONE; + MifareECardLoad(sectorcnt, 0); + MifareECardLoad(sectorcnt, 1); + DBGLEVEL = oldbg; + } } else { // partial/none keys found reply_mix(CMD_ACK, foundkeys, 0, 0, 0, 0); @@ -1669,10 +1694,15 @@ void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) { // Load a card into the emulator memory // //----------------------------------------------------------------------------- -int MifareECardLoad(uint32_t arg0, uint32_t arg1) { +int MifareECardLoadExt(uint8_t numSectors, uint8_t keyType) { + int retval = MifareECardLoad(numSectors, keyType); + reply_ng(CMD_HF_MIFARE_EML_LOAD, retval, NULL, 0); + return retval; +} + +int MifareECardLoad(uint8_t numSectors, uint8_t keyType) { + uint32_t cuid = 0; - uint8_t numSectors = arg0; - uint8_t keyType = arg1; struct Crypto1State mpcs = {0, 0}; struct Crypto1State *pcs; pcs = &mpcs; @@ -1683,42 +1713,40 @@ int MifareECardLoad(uint32_t arg0, uint32_t arg1) { uint8_t uid[10] = {0x00}; LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); set_tracing(true); - bool isOK = true; + int retval; if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - isOK = false; - if (DBGLEVEL >= 1) Dbprintf("Can't select card"); + retval = PM3_ESOFT; + if (DBGLEVEL > DBG_ERROR) Dbprintf("Can't select card"); + goto out; } - for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) { + for (uint8_t sectorNo = 0; sectorNo < numSectors; sectorNo++) { uint64_t ui64Key = emlGetKey(sectorNo, keyType); if (sectorNo == 0) { - if (isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { - if (DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo); + if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { + if (DBGLEVEL > DBG_ERROR) Dbprintf("Sector[%2d]. Auth error", sectorNo); break; } } else { - if (isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) { - isOK = false; - if (DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth nested error", sectorNo); - break; + if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) { + retval = PM3_ESOFT; + if (DBGLEVEL > DBG_ERROR) Dbprintf("Sector[%2d]. Auth nested error", sectorNo); + goto out; } } - for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { - if (isOK && mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) { - isOK = false; - if (DBGLEVEL >= 1) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo); + for (uint8_t blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) { + if (mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) { + retval = PM3_ESOFT; + if (DBGLEVEL > DBG_ERROR) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo); break; } - if (isOK) { if (blockNo < NumBlocksPerSector(sectorNo) - 1) { emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1); } else { // sector trailer, keep the keys, set only the AC @@ -1729,22 +1757,19 @@ int MifareECardLoad(uint32_t arg0, uint32_t arg1) { } } - } - - if (mifare_classic_halt(pcs, cuid)) - if (DBGLEVEL >= 1) + if (mifare_classic_halt(pcs, cuid)) { + if (DBGLEVEL > DBG_ERROR) Dbprintf("Halt error"); + } - // ----------------------------- crypto1 destroy + if (DBGLEVEL >= DBG_INFO) DbpString("Emulator fill sectors finished"); + +out: crypto1_destroy(pcs); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); - - if (DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED"); - set_tracing(false); - return (isOK) ? PM3_SUCCESS : PM3_EUNDEF; + return retval; } diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index 445b04130..d563e37a8 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -31,7 +31,8 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da void MifareEMemClr(void); void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain); void MifareEMemGet(uint8_t blockno, uint8_t blockcnt); -int MifareECardLoad(uint32_t arg0, uint32_t arg1); +int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype); +int MifareECardLoadExt(uint8_t numSectors, uint8_t keyType); void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); From 03867018f1098deb12edcd96b7241f243cc7e084 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 28 Aug 2019 21:29:08 +0200 Subject: [PATCH 10/16] chg: iclass fixes. better timings, to get 280us vs 330us (default) time before card response. --- armsrc/iclass.c | 57 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/armsrc/iclass.c b/armsrc/iclass.c index c8504e5ed..b550158cc 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -55,7 +55,13 @@ #include "protocols.h" #include "ticks.h" -static int timeout = 4096; +static int g_wait = 300; +static int timeout = 2900; +static uint32_t time_rdr = 0; +static uint32_t time_delta = 0; +static uint32_t time_delta_wait = 0; +static uint32_t time_response = 0; + static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay); int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf); @@ -151,7 +157,7 @@ typedef struct { static tUartIc Uart; static void OnError(uint8_t reason) { - reply_old(CMD_ACK, 0, reason, 0, 0, 0); + reply_mix(CMD_ACK, 0, reason, 0, 0, 0); switch_off(); } @@ -160,10 +166,12 @@ static void uart_reset(void) { Uart.synced = false; Uart.frame = false; } + static void uart_init(uint8_t *data) { Uart.buf = data; uart_reset(); } + static void uart_bit(uint8_t bit) { static uint8_t buf = 0xff; static uint8_t n_buf; @@ -1427,7 +1435,6 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { uint32_t time_0 = GetCountSspClk(); uint32_t t2r_stime = 0, t2r_etime = 0; uint32_t r2t_stime, r2t_etime = 0; - LED_A_ON(); bool buttonPressed = false; @@ -1717,6 +1724,8 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int bool firstpart = true; uint8_t sendbyte; + time_rdr = 0; + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); AT91C_BASE_SSC->SSC_THR = 0x00; @@ -1755,6 +1764,8 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int } } + time_rdr = GetCountSspClk(); + if (samples) { if (wait) *samples = (c + *wait) << 3; @@ -1827,7 +1838,7 @@ void ReaderTransmitIClass(uint8_t *frame, int len) { // If a response is captured return TRUE // If it takes too long return FALSE //----------------------------------------------------------------------------- -static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed) { +static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, int *wait) { // buffer needs to be 512 bytes // maxLen is not used... @@ -1837,13 +1848,16 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, // Setup UART/DEMOD to receive DemodIcInit(receivedResponse); - if (elapsed) *elapsed = 0; - // Set FPGA mode to "reader listen mode", no modulation (listen // only, since we are receiving, not transmitting). FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN); - SpinDelayUs(320); //310 Tout= 330us (iso15603-2) (330/21.3) take consideration for clock increments. + time_delta = GetCountSspClk() - time_rdr; + + SpinDelayUs(g_wait); //310 Tout= 330us (iso15603-2) (330/21.3) take consideration for clock increments. + time_delta_wait = GetCountSspClk() - time_rdr - time_delta; + + uint32_t foo = GetCountSspClk(); // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; (void)b; @@ -1861,15 +1875,16 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, } // keep tx buffer in a defined state anyway. +/* if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = 0x00; - // To make use of exact timing of next command from reader!! - if (elapsed)(*elapsed)++; } - +*/ // Wait for byte be become available in rx holding register if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - if (c >= timeout) return false; + + if ( GetCountSspClk() - foo > timeout) return false; +// if (c >= timeout) return false; c++; @@ -1881,25 +1896,28 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, if (ManchesterDecoding_iclass(b & 0x0f)) { if (samples) *samples = c << 3; + + time_response = GetCountSspClk() - foo; return true; } } } + return false; } int ReaderReceiveIClass(uint8_t *receivedAnswer) { int samples = 0; - if (!GetIClassAnswer(receivedAnswer, 0, &samples, NULL)) - return false; + if (GetIClassAnswer(receivedAnswer, 0, &samples, NULL) == false) + return 0; rsamples += samples; LogTrace(receivedAnswer, Demod.len, rsamples, rsamples, NULL, false); if (samples == 0) - return false; + return 0; return Demod.len; } @@ -1924,7 +1942,7 @@ void setupIclassReader() { // Now give it time to spin up. // Signal field is on with the appropriate LED FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); - SpinDelay(300); + SpinDelay(500); StartCountSspClk(); @@ -1936,13 +1954,20 @@ bool sendCmdGetResponseWithRetries(uint8_t *command, size_t cmdsize, uint8_t *re ReaderTransmitIClass(command, cmdsize); + //iceman - if received size is bigger than expected, we smash the stack here // since its called with fixed sized arrays + + // update/write commadn takes 4ms to 15ms before responding + if ( command[0] == ICLASS_CMD_UPDATE ) + g_wait = 15000; + uint8_t got_n = ReaderReceiveIClass(resp); // 0xBB is the internal debug separator byte.. if (expected_size != got_n || (resp[0] == 0xBB || resp[7] == 0xBB || resp[2] == 0xBB)) { //try again + SpinDelayUs(400); continue; } @@ -2396,8 +2421,6 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) { if (isOK) goto out; - SpinDelayUs(400); //iClass (iso15693-2) should timeout after 330us. - // Auth Sequence MUST begin with reading e-purse. (block2) // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC) ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); From d2d58db98528ace9b5bddb912f5baa98b5fd5a31 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 28 Aug 2019 21:15:11 +0200 Subject: [PATCH 11/16] Move history and logfile to ~/.proxmark3 --- client/fileutils.c | 2 ++ client/proxmark3.c | 15 ++++++++--- client/proxmark3.h | 2 ++ client/ui.c | 65 ++++++++++++++++++++++++++++++++++++++++------ client/ui.h | 3 ++- 5 files changed, 74 insertions(+), 13 deletions(-) diff --git a/client/fileutils.c b/client/fileutils.c index c3c9f5acc..72771f900 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -896,6 +896,8 @@ out: } int searchFile(char **foundpath, const char *pm3dir, const char *searchname, const char *suffix) { + if (foundpath == NULL) + return PM3_EINVARG; char *filename = filenamemcopy(searchname, suffix); if (filename == NULL) return PM3_EMALLOC; int res = searchFinalFile(foundpath, pm3dir, filename); diff --git a/client/proxmark3.c b/client/proxmark3.c index 6a23f4804..913f3735f 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -102,8 +102,13 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) { PrintAndLogEx(ERR, "could not open " _YELLOW_("%s") "...", script_cmds_file); } - read_history(".history"); - + char *my_history_path = NULL; + if (searchHomeFilePath(&my_history_path, PROXHISTORY, true) != PM3_SUCCESS) { + PrintAndLogEx(ERR, "could not create $HOME/" PROXHISTORY ", no history will be recorded"); + my_history_path = NULL; + } else { + read_history(my_history_path); + } // loops every time enter is pressed... while (1) { bool printprompt = false; @@ -220,8 +225,10 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) { if (sf) fclose(sf); - write_history(".history"); - + if (my_history_path) { + write_history(my_history_path); + free(my_history_path); + } if (cmd) { free(cmd); cmd = NULL; diff --git a/client/proxmark3.h b/client/proxmark3.h index 6d245da10..3da261c31 100644 --- a/client/proxmark3.h +++ b/client/proxmark3.h @@ -18,6 +18,8 @@ #define PROXPROMPT_USB "[usb] pm3 --> " #define PROXPROMPT_FPC "[fpc] pm3 --> " #define PROXPROMPT_OFFLINE "[offline] pm3 --> " +#define PROXHISTORY "history.txt" +#define PROXLOG "log_%Y%m%d.txt" #ifdef __cplusplus extern "C" { diff --git a/client/ui.c b/client/ui.c index 9927fd6d6..86f32e2bd 100644 --- a/client/ui.c +++ b/client/ui.c @@ -24,6 +24,9 @@ #include #include #include "util.h" +#include "proxmark3.h" // PROXLOG +#include "fileutils.h" +#include "pm3_cmd.h" session_arg_t session; @@ -36,9 +39,45 @@ bool GridLocked = false; bool showDemod = true; pthread_mutex_t print_lock = PTHREAD_MUTEX_INITIALIZER; -static const char *logfilename = "proxmark3.log"; + static void fPrintAndLog(FILE *stream, const char *fmt, ...); +// needed by flasher, so let's put it here instead of fileutils.c +int searchHomeFilePath(char **foundpath, const char *filename, bool create_home) { + if (foundpath == NULL) + return PM3_EINVARG; + char *user_path = getenv("HOME"); + if (user_path == NULL) + return PM3_EFILE; + char *path = calloc(strlen(user_path) + strlen(PM3_USER_DIRECTORY) + 1, sizeof(char)); + if (path == NULL) + return PM3_EMALLOC; + strcpy(path, user_path); + strcat(path, PM3_USER_DIRECTORY); + +#ifdef _WIN32 + struct _stat st; + int result = _stat(path, &st); +#else + struct stat st; + int result = stat(path, &st); +#endif + if ((result != 0) && create_home) { + if (mkdir(path, 0700)) { + free(path); + return PM3_EFILE; + } + } + if (filename == NULL) { + *foundpath = path; + return PM3_SUCCESS; + } + path = realloc(path, (strlen(user_path) + strlen(PM3_USER_DIRECTORY) + strlen(filename) + 1) * sizeof(char)); + strcat(path, filename); + *foundpath = path; + return PM3_SUCCESS; +} + void PrintAndLogOptions(const char *str[][2], size_t size, size_t space) { char buff[2000] = "Options:\n"; char format[2000] = ""; @@ -166,10 +205,24 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) { pthread_mutex_lock(&print_lock); if (logging && !logfile) { - logfile = fopen(logfilename, "a"); - if (!logfile) { - fprintf(stderr, "Can't open logfile, logging disabled!\n"); + char *my_logfile_path = NULL; + char filename[40]; + struct tm *timenow; + time_t now = time(NULL); + timenow = gmtime(&now); + strftime(filename, sizeof(filename), PROXLOG, timenow); + if (searchHomeFilePath(&my_logfile_path, filename, true) != PM3_SUCCESS) { + fprintf(stderr, "Could not create $HOME/.proxmark3/%s, no log will be recorded\n", filename); + my_logfile_path = NULL; logging = 0; + } else { + logfile = fopen(my_logfile_path, "a"); + if (logfile == NULL) { + fprintf(stderr, "Can't open logfile %s, logging disabled!\n", my_logfile_path); + logging = 0; + } + printf("Session is logged into %s\n", my_logfile_path); + free(my_logfile_path); } } @@ -228,10 +281,6 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) { pthread_mutex_unlock(&print_lock); } -void SetLogFilename(char *fn) { - logfilename = fn; -} - void SetFlushAfterWrite(bool value) { flushAfterWrite = value; } diff --git a/client/ui.h b/client/ui.h index 648dce4c4..7e00ab52b 100644 --- a/client/ui.h +++ b/client/ui.h @@ -39,7 +39,6 @@ void ShowGraphWindow(void); void RepaintGraphWindow(void); void PrintAndLogOptions(const char *str[][2], size_t size, size_t space); void PrintAndLogEx(logLevel_t level, const char *fmt, ...); -void SetLogFilename(char *fn); void SetFlushAfterWrite(bool value); void memcpy_filter_ansi(void *dest, const void *src, size_t n, bool filter); @@ -49,6 +48,8 @@ extern uint32_t CursorCPos, CursorDPos; extern bool GridLocked; extern bool showDemod; +int searchHomeFilePath(char **foundpath, const char *filename, bool create_home); + extern pthread_mutex_t print_lock; void iceIIR_Butterworth(int *data, const size_t len); From 11c7db352349d4d88ded9b6446dcdd275018c4d2 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 28 Aug 2019 23:07:23 +0200 Subject: [PATCH 12/16] Get ~/.proxmark3 working on Mingw --- client/ui.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/client/ui.c b/client/ui.c index 86f32e2bd..e6edb4369 100644 --- a/client/ui.c +++ b/client/ui.c @@ -27,7 +27,10 @@ #include "proxmark3.h" // PROXLOG #include "fileutils.h" #include "pm3_cmd.h" - +#ifdef _WIN32 +# include // _mkdir +#endif +#include session_arg_t session; double CursorScaleFactor = 1; @@ -55,15 +58,16 @@ int searchHomeFilePath(char **foundpath, const char *filename, bool create_home) strcpy(path, user_path); strcat(path, PM3_USER_DIRECTORY); -#ifdef _WIN32 - struct _stat st; - int result = _stat(path, &st); -#else +// Mingw: _stat fails on mangled HOME path /pm3 => C:\ProxSpace\pm3, while stat works fine struct stat st; int result = stat(path, &st); -#endif if ((result != 0) && create_home) { + +#ifdef _WIN32 + if (_mkdir(path)) { +#else if (mkdir(path, 0700)) { +#endif free(path); return PM3_EFILE; } From 37243a47294c7e74e5f708e4de2368857c6e903a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 28 Aug 2019 23:09:59 +0200 Subject: [PATCH 13/16] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3db619fd..f7dc5d6a9 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] + - Chg history and logfile are now saved into $HOME/.proxmark3/ (@doegox) - Chg optimization of iclass mac calculations on deviceside (@pwpiwi) - Add 'hf mf autopwn' - Autopwn function for Mifare Classic, extract all keys and dump card memory (@matthiaskonrath) - Add Lua paths: look for scripts also in ~/.proxmark/lua{scripts,libs} and /usr/local/share/proxmark3/lua{scripts,libs} (@doegox) From aa77f7298c18c22dda15673d518093b6f0f0e55e Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 28 Aug 2019 23:28:28 +0200 Subject: [PATCH 14/16] Fix buffer allocation for showing compiler version --- client/cmdhw.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/client/cmdhw.c b/client/cmdhw.c index b6cb2bd87..68a5390c6 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -619,15 +619,18 @@ int CmdHW(const char *Cmd) { void pm3_version(bool verbose, bool oneliner) { - if (oneliner) { - char msg[70]; - memset(msg, 0x00, sizeof(msg)); - strcat(msg, "Client: RRG/Iceman compiled with "); +#define PM3CLIENTONELINER "Client: RRG/Iceman compiled with " #if defined(__clang__) - strcat(msg + strlen(msg), _YELLOW_("Clang/LLVM "__VERSION__)); +# define PM3CLIENTCOMPILER "Clang/LLVM " #elif defined(__GNUC__) || defined(__GNUG__) - strcat(msg + strlen(msg), _YELLOW_("GCC "__VERSION__)); +# define PM3CLIENTCOMPILER "GCC " #endif + + if (oneliner) { + char msg[sizeof(PM3CLIENTONELINER)+sizeof(PM3CLIENTCOMPILER)+sizeof(__VERSION__)]; + memset(msg, 0x00, sizeof(msg)); + strcat(msg, PM3CLIENTONELINER); + strcat(msg + strlen(msg), _YELLOW_(PM3CLIENTCOMPILER __VERSION__)); PrintAndLogEx(NORMAL, "%s", msg); return; } @@ -644,12 +647,7 @@ void pm3_version(bool verbose, bool oneliner) { PrintAndLogEx(NORMAL, "\n" _BLUE_(" [ Proxmark3 RFID instrument ]") "\n"); PrintAndLogEx(NORMAL, "\n [ CLIENT ]"); PrintAndLogEx(NORMAL, " client: RRG/Iceman"); // TODO version info? -#if defined(__clang__) - PrintAndLogEx(NORMAL, " compiled with Clang/LLVM "__VERSION__); -#elif defined(__GNUC__) || defined(__GNUG__) - PrintAndLogEx(NORMAL, " compiled with GCC "__VERSION__); -#endif - + PrintAndLogEx(NORMAL, " compiled with " PM3CLIENTCOMPILER __VERSION__); PrintAndLogEx(NORMAL, "\n [ PROXMARK RDV4 ]"); PrintAndLogEx(NORMAL, " external flash: %s", IfPm3Flash() ? _GREEN_("present") : _YELLOW_("absent")); PrintAndLogEx(NORMAL, " smartcard reader: %s", IfPm3Smartcard() ? _GREEN_("present") : _YELLOW_("absent")); From 430c53a7ac0985526188ea02798a2c69ffd8a23d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 28 Aug 2019 23:51:52 +0200 Subject: [PATCH 15/16] Fix buffer allocation again, just getting rid of it --- client/cmdhw.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/client/cmdhw.c b/client/cmdhw.c index 68a5390c6..1d65f5d1d 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -619,7 +619,6 @@ int CmdHW(const char *Cmd) { void pm3_version(bool verbose, bool oneliner) { -#define PM3CLIENTONELINER "Client: RRG/Iceman compiled with " #if defined(__clang__) # define PM3CLIENTCOMPILER "Clang/LLVM " #elif defined(__GNUC__) || defined(__GNUG__) @@ -627,11 +626,7 @@ void pm3_version(bool verbose, bool oneliner) { #endif if (oneliner) { - char msg[sizeof(PM3CLIENTONELINER)+sizeof(PM3CLIENTCOMPILER)+sizeof(__VERSION__)]; - memset(msg, 0x00, sizeof(msg)); - strcat(msg, PM3CLIENTONELINER); - strcat(msg + strlen(msg), _YELLOW_(PM3CLIENTCOMPILER __VERSION__)); - PrintAndLogEx(NORMAL, "%s", msg); + PrintAndLogEx(NORMAL, "Client: RRG/Iceman compiled with " _YELLOW_(PM3CLIENTCOMPILER __VERSION__)); return; } From 199c1b3c9bba1a5ba6833d252b8a9274b66e38e6 Mon Sep 17 00:00:00 2001 From: Oleg Moiseenko <807634+merlokk@users.noreply.github.com> Date: Thu, 29 Aug 2019 02:38:35 +0300 Subject: [PATCH 16/16] Appveyour (#369) appveyour fix --- appveyor.yml | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index a0c261b2b..a0a4b18a9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -76,10 +76,64 @@ clone_script: Write-Host "Update msys2 packages..." -NoNewLine $env:Path = "C:\ProxSpace\msys2\usr\bin;C:\ProxSpace\msys2\mingw32\bin;C:\ProxSpace\gcc-arm-none-eabi\bin;$env:Path" + + Function ExecUpdate($Name, $Cmd, $ErrorLine) { - C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null 1> msys1.txt 2>&1 + #--- begin Job + + $Job = Start-Job -Name "$Name" -ScriptBlock { + $env:Path = "C:\ProxSpace\msys\bin;$env:Path" + Set-Location $using:PWD - C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null 1> msys1.txt 2>&1 + $sb=[scriptblock]::Create("$using:Cmd") + #execute scriptblock + $Cond=&$sb + + return $Cond + } + + #--- end Job + + $JobTime=[System.Environment]::TickCount + while($true) { + Receive-Job -Job $Job -Keep -OutVariable Res 2>&1 6>&1 | Out-Null + + if ($Res -is "String" -and $Res -like "*$ErrorLine*"){ + Write-host "Exit by stop phrase" + break + } + + if ($Res -is [Object]){ + [bool]$needexit = $false + ForEach($line in $Res){ + if ($line -like "*$ErrorLine*"){ + Write-host "Exit by stop phrase [obj]" + $needexit = $true + break + } + } + if ($needexit) { + break + } + } + + if(Wait-Job $Job -Timeout 5){ + Write-host "Exit by end job" + break + } + + if ([System.Environment]::TickCount-$JobTime -gt 600000) { + Write-host "Exit by timeout" + break + } + } + + Remove-Job -Force $Job + } + + ExecUpdate "update1" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2" + + ExecUpdate "update2" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2" Write-Host "[ OK ]" -ForegroundColor Green install: