X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/a39af1cb9cab6298fcf01d7243e9f48db0f45f26..f98702bace48fde3ec1492d1c732e23cd2eb8613:/client/cmdhfmf.c diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 9284d14c..c38e276e 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -29,6 +29,7 @@ #include "hardnested/hardnested_bf_core.h" #include "cliparser/cliparser.h" #include "cmdhf14a.h" +#include "mifare/mifaredefault.h" #include "mifare/mifare4.h" #include "mifare/mad.h" #include "mifare/ndef.h" @@ -1053,7 +1054,7 @@ int CmdHF14AMfChk(const char *Cmd) PrintAndLog("Usage: hf mf chk |<*card memory> [t|d|s|ss] [] []"); PrintAndLog(" * - all sectors"); PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); - PrintAndLog("d - write keys to binary file\n"); + PrintAndLog("d - write keys to binary file (not used when supplied)"); PrintAndLog("t - write keys to emulator memory"); PrintAndLog("s - slow execute. timeout 1ms"); PrintAndLog("ss - very slow execute. timeout 5ms"); @@ -1065,27 +1066,27 @@ int CmdHF14AMfChk(const char *Cmd) return 0; } - FILE * f; - char filename[FILE_PATH_SIZE]={0}; - char buf[13]; - uint8_t *keyBlock = NULL, *p; - uint16_t stKeyBlock = 20; - - int i, res; - int keycnt = 0; - char ctmp = 0x00; - int clen = 0; - uint8_t blockNo = 0; - uint8_t SectorsCnt = 0; - uint8_t keyType = 0; - uint64_t key64 = 0; + FILE * f; + char filename[FILE_PATH_SIZE]={0}; + char buf[13]; + uint8_t *keyBlock = NULL, *p; + uint16_t stKeyBlock = 20; + int i, res; + int keycnt = 0; + char ctmp = 0x00; + int clen = 0; + uint8_t blockNo = 0; + uint8_t SectorsCnt = 0; + uint8_t keyType = 0; + uint64_t key64 = 0; // timeout in units. (ms * 106)/10 or us*0.0106 - uint8_t btimeout14a = MF_CHKKEYS_DEFTIMEOUT; // fast by default - bool param3InUse = false; - - bool transferToEml = 0; - bool createDumpFile = 0; - + uint8_t btimeout14a = MF_CHKKEYS_DEFTIMEOUT; // fast by default + bool param3InUse = false; + bool transferToEml = 0; + bool createDumpFile = 0; + bool singleBlock = false; // Flag to ID if a single or multi key check + uint8_t keyFoundCount = 0; // Counter to display the number of keys found/transfered to emulator + sector_t *e_sector = NULL; keyBlock = calloc(stKeyBlock, 6); @@ -1098,9 +1099,19 @@ int CmdHF14AMfChk(const char *Cmd) if (param_getchar(Cmd, 0)=='*') { SectorsCnt = ParamCardSizeSectors(param_getchar(Cmd + 1, 0)); - } - else + } else { blockNo = param_get8(Cmd, 0); + // Singe Key check, so Set Sector count to cover sectors (1 to sector that contains the block) + // 1 and 2 Cards : Sector = blockNo/4 + 1 + // Sectors 0 - 31 : 4 blocks per sector : Blocks 0 - 127 + // Sectors 32 - 39 : 16 blocks per sector : Blocks 128 - 255 (4K) + if (blockNo < 128) { + SectorsCnt = (blockNo / 4) + 1; + } else { + SectorsCnt = 32 + ((blockNo-128)/16) + 1; + } + singleBlock = true; // Set flag for single key check + } ctmp = param_getchar(Cmd, 1); clen = param_getlength(Cmd, 1); @@ -1121,13 +1132,19 @@ int CmdHF14AMfChk(const char *Cmd) return 1; }; } - + parseParamTDS(Cmd, 2, &transferToEml, &createDumpFile, &btimeout14a); + if (singleBlock & createDumpFile) { + PrintAndLog (" block key check () and write to dump file (d) combination is not supported "); + PrintAndLog (" please remove option d and try again"); + return 1; + } + param3InUse = transferToEml | createDumpFile | (btimeout14a != MF_CHKKEYS_DEFTIMEOUT); PrintAndLog("--chk keys. sectors:%2d, block no:%3d, key type:%c, eml:%c, dmp=%c checktimeout=%d us", - SectorsCnt, blockNo, keyType?'B':'A', transferToEml?'y':'n', createDumpFile?'y':'n', ((int)btimeout14a * 10000) / 106); + SectorsCnt, blockNo, keyType==0?'A':keyType==1?'B':'?', transferToEml?'y':'n', createDumpFile?'y':'n', ((int)btimeout14a * 10000) / 106); for (i = param3InUse; param_getchar(Cmd, 2 + i); i++) { if (!param_gethex(Cmd, 2 + i, keyBlock + 6 * keycnt, 12)) { @@ -1141,7 +1158,7 @@ int CmdHF14AMfChk(const char *Cmd) keyBlock = p; } PrintAndLog("chk key[%2d] %02x%02x%02x%02x%02x%02x", keycnt, - (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], + (keyBlock + 6*keycnt)[0], (keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], (keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6); keycnt++; } else { @@ -1152,8 +1169,8 @@ int CmdHF14AMfChk(const char *Cmd) return 2; } - if ( (f = fopen( filename , "r")) ) { - while( fgets(buf, sizeof(buf), f) ){ + if ((f = fopen( filename , "r"))) { + while (fgets(buf, sizeof(buf), f)) { if (strlen(buf) < 12 || buf[11] == '\n') continue; @@ -1161,14 +1178,20 @@ int CmdHF14AMfChk(const char *Cmd) if( buf[0]=='#' ) continue; //The line start with # is comment, skip - if (!isxdigit((unsigned char)buf[0])){ - PrintAndLog("File content error. '%s' must include 12 HEX symbols",buf); + bool content_error = false; + for (int i = 0; i < 12; i++) { + if (!isxdigit((unsigned char)buf[i])) { + content_error = true; + } + } + if (content_error) { + PrintAndLog("File content error. '%s' must include 12 HEX symbols", buf); continue; } buf[12] = 0; - if ( stKeyBlock - keycnt < 2) { + if (stKeyBlock - keycnt < 2) { p = realloc(keyBlock, 6*(stKeyBlock+=10)); if (!p) { PrintAndLog("Cannot allocate memory for defKeys"); @@ -1189,7 +1212,6 @@ int CmdHF14AMfChk(const char *Cmd) PrintAndLog("File: %s: not found or locked.", filename); free(keyBlock); return 1; - } } } @@ -1199,7 +1221,7 @@ int CmdHF14AMfChk(const char *Cmd) PrintAndLog("No key specified, trying default keys"); for (;keycnt < defaultKeysSize; keycnt++) PrintAndLog("chk default key[%2d] %02x%02x%02x%02x%02x%02x", keycnt, - (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], + (keyBlock + 6*keycnt)[0], (keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], (keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6); } @@ -1218,14 +1240,18 @@ int CmdHF14AMfChk(const char *Cmd) printf("\n"); bool foundAKey = false; - uint32_t max_keys = keycnt > USB_CMD_DATA_SIZE / 6 ? USB_CMD_DATA_SIZE / 6 : keycnt; - if (SectorsCnt) { + bool clearTraceLog = true; + uint32_t max_keys = keycnt > USB_CMD_DATA_SIZE / 6 ? USB_CMD_DATA_SIZE / 6 : keycnt; + + // !SingleKey, so all key check (if SectorsCnt > 0) + if (!singleBlock) { PrintAndLog("To cancel this operation press the button on the proxmark..."); printf("--"); for (uint32_t c = 0; c < keycnt; c += max_keys) { uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c; - res = mfCheckKeysSec(SectorsCnt, keyType, btimeout14a, true, size, &keyBlock[6 * c], e_sector); // timeout is (ms * 106)/10 or us*0.0106 + res = mfCheckKeysSec(SectorsCnt, keyType, btimeout14a, clearTraceLog, size, &keyBlock[6 * c], e_sector); // timeout is (ms * 106)/10 or us*0.0106 + clearTraceLog = false; if (res != 1) { if (!res) { @@ -1239,18 +1265,26 @@ int CmdHF14AMfChk(const char *Cmd) PrintAndLog("Command execute timeout"); } } - } else { + } else { int keyAB = keyType; do { - for (uint32_t c = 0; c < keycnt; c+=max_keys) { + for (uint32_t c = 0; c < keycnt; c += max_keys) { uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c; res = mfCheckKeys(blockNo, keyAB & 0x01, true, size, &keyBlock[6 * c], &key64); + clearTraceLog = false; if (res != 1) { - if (!res) { - PrintAndLog("Found valid key:[%d:%c]%012" PRIx64, blockNo, (keyAB & 0x01)?'B':'A', key64); + if (!res) { + // Use the common format below + // PrintAndLog("Found valid key:[%d:%c]%012" PRIx64, blockNo, (keyAB & 0x01)?'B':'A', key64); foundAKey = true; + + // Store the Single Key for display list + // For a single block check, SectorsCnt = Sector that contains the block + e_sector[SectorsCnt-1].foundKey[(keyAB & 0x01)] = true; // flag key found + e_sector[SectorsCnt-1].Key[(keyAB & 0x01)] = key64; // Save key data + } } else { PrintAndLog("Command execute timeout"); @@ -1261,17 +1295,25 @@ int CmdHF14AMfChk(const char *Cmd) // print result if (foundAKey) { - if (SectorsCnt) { - PrintAndLog(""); - PrintAndLog("|---|----------------|---|----------------|---|"); - PrintAndLog("|sec|key A |res|key B |res|"); - PrintAndLog("|---|----------------|---|----------------|---|"); - for (i = 0; i < SectorsCnt; i++) { - PrintAndLog("|%03d| %012" PRIx64 " | %d | %012" PRIx64 " | %d |", i, - e_sector[i].Key[0], e_sector[i].foundKey[0], e_sector[i].Key[1], e_sector[i].foundKey[1]); + PrintAndLog(""); + PrintAndLog("|---|----------------|----------------|"); + PrintAndLog("|sec|key A |key B |"); + PrintAndLog("|---|----------------|----------------|"); + for (i = 0; i < SectorsCnt; i++) { + // If a block key check, only print a line if a key was found. + if (!singleBlock || e_sector[i].foundKey[0] || e_sector[i].foundKey[1]) { + char keyAString[13] = " ? "; + char keyBString[13] = " ? "; + if (e_sector[i].foundKey[0]) { + sprintf(keyAString, "%012" PRIx64, e_sector[i].Key[0]); + } + if (e_sector[i].foundKey[1]) { + sprintf(keyBString, "%012" PRIx64, e_sector[i].Key[1]); + } + PrintAndLog("|%03d| %s | %s |", i, keyAString, keyBString); } - PrintAndLog("|---|----------------|---|----------------|---|"); } + PrintAndLog("|---|----------------|----------------|"); } else { PrintAndLog(""); PrintAndLog("No valid keys found."); @@ -1285,15 +1327,17 @@ int CmdHF14AMfChk(const char *Cmd) for (uint16_t t = 0; t < 2; t++) { if (e_sector[sectorNo].foundKey[t]) { num_to_bytes(e_sector[sectorNo].Key[t], 6, block + t * 10); + keyFoundCount++; // Key found count for information } } mfEmlSetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); } } - PrintAndLog("Found keys have been transferred to the emulator memory"); + // Updated to show the actual number of keys found/transfered. + PrintAndLog("%d keys(s) found have been transferred to the emulator memory",keyFoundCount); } - if (createDumpFile) { + if (createDumpFile && !singleBlock) { FILE *fkeys = fopen("dumpkeys.bin","wb"); if (fkeys == NULL) { PrintAndLog("Could not create file dumpkeys.bin"); @@ -1311,13 +1355,14 @@ int CmdHF14AMfChk(const char *Cmd) fclose(fkeys); PrintAndLog("Found keys have been dumped to file dumpkeys.bin. 0xffffffffffff has been inserted for unknown keys."); } - + free(e_sector); free(keyBlock); PrintAndLog(""); return 0; } + void readerAttack(nonces_t ar_resp[], bool setEmulatorMem, bool doStandardAttack) { #define ATTACK_KEY_COUNT 7 // keep same as define in iso14443a.c -> Mifare1ksim() // cannot be more than 7 or it will overrun c.d.asBytes(512) @@ -1515,8 +1560,11 @@ int CmdHF14AMfSim(const char *Cmd) { break; case 'u': case 'U': - param_gethex_ex(Cmd, cmdp+1, uid, &uidlen); - switch(uidlen) { + uidlen = 14; + if (param_gethex_ex(Cmd, cmdp+1, uid, &uidlen)) { + return usage_hf14_mfsim(); + } + switch (uidlen) { case 14: flags = FLAG_7B_UID_IN_DATA; break; case 8: flags = FLAG_4B_UID_IN_DATA; break; default: return usage_hf14_mfsim(); @@ -2725,9 +2773,9 @@ int CmdHF14AMfSniff(const char *Cmd){ //needs nt, ar, at, Data to decrypt int CmdDecryptTraceCmds(const char *Cmd){ uint8_t data[50]; - int len = 0; - param_gethex_ex(Cmd,3,data,&len); - return tryDecryptWord(param_get32ex(Cmd,0,0,16),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16),data,len/2); + int len = 100; + param_gethex_ex(Cmd, 3, data, &len); + return tryDecryptWord(param_get32ex(Cmd, 0, 0, 16), param_get32ex(Cmd, 1, 0, 16), param_get32ex(Cmd, 2, 0, 16), data, len/2); } int CmdHF14AMfAuth4(const char *cmd) {