X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/c2731f37bef482bde1a87d79566c0b3bde658c98..e1ad67eaf252b9cf0e0aef9f02c13ce74d6ae546:/client/cmdhfmf.c diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index ed362cd1..d15a4020 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -9,6 +9,7 @@ //----------------------------------------------------------------------------- #include "cmdhfmf.h" +#include "cmdhfmfhard.h" #include "nonce2key/nonce2key.h" static int CmdHelp(const char *Cmd); @@ -28,6 +29,7 @@ int CmdHF14AMifare(const char *Cmd) printf("Press button on the proxmark3 device to abort both proxmark3 and client.\n"); printf("-------------------------------------------------------------------------\n"); + time_t time1 = clock(); start: clearCommandBuffer(); @@ -60,7 +62,7 @@ start: case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).\n"); break; case -3 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator is not predictable).\n"); break; case -4 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown"); - PrintAndLog("generating polynomial with 16 effective bits only, but shows unexpected behaviour.\n"); break; + PrintAndLog("generating polynomial with 16 effective bits only, but shows unexpected behaviour.\n"); break; default: ; } break; @@ -85,6 +87,7 @@ start: PrintAndLog("Found valid key: %012"llx" \n", r_key); } + PrintAndLog("Time in darkside: %1.0f seconds", (float)(clock() - time1)/CLOCKS_PER_SEC); PrintAndLog(""); return 0; } @@ -661,8 +664,7 @@ int CmdHF14AMfNested(const char *Cmd) } } else { // ------------------------------------ multiple sectors working - clock_t time1; - time1 = clock(); + clock_t time1 = clock(); e_sector = calloc(SectorsCnt, sizeof(sector)); if (e_sector == NULL) return 1; @@ -732,7 +734,7 @@ int CmdHF14AMfNested(const char *Cmd) } } - printf("Time in nested: %1.3f (%1.3f sec per key)\n\n", ((float)clock() - time1)/CLOCKS_PER_SEC, ((float)clock() - time1)/iterations/CLOCKS_PER_SEC); + PrintAndLog("Time in nested: %1.3f (%1.3f sec per key)\n\n", ((float)clock() - time1)/CLOCKS_PER_SEC, ((float)clock() - time1)/iterations/CLOCKS_PER_SEC); PrintAndLog("-----------------------------------------------\nIterations count: %d\n\n", iterations); //print them @@ -791,6 +793,122 @@ int CmdHF14AMfNested(const char *Cmd) return 0; } +int CmdHF14AMfNestedHard(const char *Cmd) +{ + uint8_t blockNo = 0; + uint8_t keyType = 0; + uint8_t trgBlockNo = 0; + uint8_t trgKeyType = 0; + uint8_t key[6] = {0, 0, 0, 0, 0, 0}; + uint8_t trgkey[6] = {0, 0, 0, 0, 0, 0}; + + char ctmp; + ctmp = param_getchar(Cmd, 0); + + if (ctmp != 'R' && ctmp != 'r' && ctmp != 'T' && ctmp != 't' && strlen(Cmd) < 20) { + PrintAndLog("Usage:"); + PrintAndLog(" hf mf hardnested "); + PrintAndLog(" [known target key (12 hex symbols)] [w] [s]"); + PrintAndLog(" or hf mf hardnested r [known target key]"); + PrintAndLog(" "); + PrintAndLog("Options: "); + PrintAndLog(" w: Acquire nonces and write them to binary file nonces.bin"); + PrintAndLog(" s: Slower acquisition (required by some non standard cards)"); + PrintAndLog(" r: Read nonces.bin and start attack"); + PrintAndLog(" "); + PrintAndLog(" sample1: hf mf hardnested 0 A FFFFFFFFFFFF 4 A"); + PrintAndLog(" sample2: hf mf hardnested 0 A FFFFFFFFFFFF 4 A w"); + PrintAndLog(" sample3: hf mf hardnested 0 A FFFFFFFFFFFF 4 A w s"); + PrintAndLog(" sample4: hf mf hardnested r"); + PrintAndLog(" "); + PrintAndLog("Add the known target key to check if it is present in the remaining key space:"); + PrintAndLog(" sample5: hf mf hardnested 0 A A0A1A2A3A4A5 4 A FFFFFFFFFFFF"); + return 0; + } + + bool know_target_key = false; + bool nonce_file_read = false; + bool nonce_file_write = false; + bool slow = false; + int tests = 0; + + + if (ctmp == 'R' || ctmp == 'r') { + nonce_file_read = true; + if (!param_gethex(Cmd, 1, trgkey, 12)) { + know_target_key = true; + } + } else if (ctmp == 'T' || ctmp == 't') { + tests = param_get32ex(Cmd, 1, 100, 10); + } else { + blockNo = param_get8(Cmd, 0); + ctmp = param_getchar(Cmd, 1); + if (ctmp != 'a' && ctmp != 'A' && ctmp != 'b' && ctmp != 'B') { + PrintAndLog("Key type must be A or B"); + return 1; + } + if (ctmp != 'A' && ctmp != 'a') { + keyType = 1; + } + + if (param_gethex(Cmd, 2, key, 12)) { + PrintAndLog("Key must include 12 HEX symbols"); + return 1; + } + + trgBlockNo = param_get8(Cmd, 3); + ctmp = param_getchar(Cmd, 4); + if (ctmp != 'a' && ctmp != 'A' && ctmp != 'b' && ctmp != 'B') { + PrintAndLog("Target key type must be A or B"); + return 1; + } + if (ctmp != 'A' && ctmp != 'a') { + trgKeyType = 1; + } + + uint16_t i = 5; + + if (!param_gethex(Cmd, 5, trgkey, 12)) { + know_target_key = true; + i++; + } + + while ((ctmp = param_getchar(Cmd, i))) { + if (ctmp == 's' || ctmp == 'S') { + slow = true; + } else if (ctmp == 'w' || ctmp == 'W') { + nonce_file_write = true; + } else { + PrintAndLog("Possible options are w and/or s"); + return 1; + } + i++; + } + } + + PrintAndLog("--target block no:%3d, target key type:%c, known target key: 0x%02x%02x%02x%02x%02x%02x%s, file action: %s, Slow: %s, Tests: %d ", + trgBlockNo, + trgKeyType?'B':'A', + trgkey[0], trgkey[1], trgkey[2], trgkey[3], trgkey[4], trgkey[5], + know_target_key?"":" (not set)", + nonce_file_write?"write":nonce_file_read?"read":"none", + slow?"Yes":"No", + tests); + + int16_t isOK = mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType, know_target_key?trgkey:NULL, nonce_file_read, nonce_file_write, slow, tests); + + if (isOK) { + switch (isOK) { + case 1 : PrintAndLog("Error: No response from Proxmark.\n"); break; + case 2 : PrintAndLog("Button pressed. Aborted.\n"); break; + default : break; + } + return 2; + } + + return 0; +} + int CmdHF14AMfChk(const char *Cmd) { if (strlen(Cmd)<3) { @@ -874,6 +992,7 @@ int CmdHF14AMfChk(const char *Cmd) break; default: PrintAndLog("Key type must be A , B or ?"); + free(keyBlock); return 1; }; @@ -925,6 +1044,7 @@ int CmdHF14AMfChk(const char *Cmd) if (!p) { PrintAndLog("Cannot allocate memory for defKeys"); free(keyBlock); + free(f); return 2; } keyBlock = p; @@ -964,7 +1084,9 @@ int CmdHF14AMfChk(const char *Cmd) } } } - + // time + time_t time1 = clock(); + for ( int t = !keyType; t < 2; keyType==2?(t++):(t=2) ) { int b=blockNo; for (int i = 0; i < SectorsCnt; ++i) { @@ -986,6 +1108,8 @@ int CmdHF14AMfChk(const char *Cmd) b<127?(b+=4):(b+=16); } } + printf("Time in checkkeys: %1.3f (%1.3f sec per key)\n\n", ((float)clock() - time1)/CLOCKS_PER_SEC, ((float)clock() - time1)/keycnt/CLOCKS_PER_SEC); + if (transferToEml) { uint8_t block[16]; @@ -1081,15 +1205,21 @@ int CmdHF14AMf1kSim(const char *Cmd) if(flags & FLAG_INTERACTIVE) { - PrintAndLog("Press pm3-button to abort simulation"); - uint8_t data[40]; uint8_t key[6]; UsbCommand resp; + PrintAndLog("Press pm3-button or send another cmd to abort simulation"); + //while(! WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + //We're waiting only 1.5 s at a time, otherwise we get the + // annoying message about "Waiting for a response... " + //} while(!ukbhit() ){ - if ( WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { - if ( (resp.arg[0] & 0xffff) == CMD_SIMULATE_MIFARE_CARD ){ + if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) continue; + + if ( !(flags & FLAG_NR_AR_ATTACK) ) break; + if ( (resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD ) break; + memset(data, 0x00, sizeof(data)); memset(key, 0x00, sizeof(key)); int len = (resp.arg[1] > sizeof(data)) ? sizeof(data) : resp.arg[1]; @@ -1099,23 +1229,21 @@ int CmdHF14AMf1kSim(const char *Cmd) uint64_t corr_uid = 0; if ( memcmp(data, "\x00\x00\x00\x00", 4) == 0 ) { corr_uid = (data[3] << 24) | (data[2] << 16) | (data[1] << 8) | data[0]; - } - else { + tryMfk32(corr_uid, data, key); + } else { corr_uid |= (uint64_t)data[2] << 48; corr_uid |= (uint64_t)data[1] << 40; corr_uid |= (uint64_t)data[0] << 32; - corr_uid |= data[7] << 24; - corr_uid |= data[6] << 16; - corr_uid |= data[5] << 8; - corr_uid |= data[4]; + corr_uid |= (uint64_t)data[7] << 24; + corr_uid |= (uint64_t)data[6] << 16; + corr_uid |= (uint64_t)data[5] << 8; + corr_uid |= (uint64_t)data[4]; + tryMfk64(corr_uid, data, key); } - tryMfk32(corr_uid, data, key); - //tryMfk64(corr_uid, data, key); PrintAndLog("--"); } } - } - } + return 0; } @@ -1220,7 +1348,7 @@ int CmdHF14AMfELoad(const char *Cmd) if ( ctmp == 'h' || ctmp == 'H' || ctmp == 0x00) { PrintAndLog("It loads emul dump from the file `filename.eml`"); - PrintAndLog("Usage: hf mf eload [card memory] "); + PrintAndLog("Usage: hf mf eload [card memory] [numblocks]"); PrintAndLog(" [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K, u = UL"); PrintAndLog(""); PrintAndLog(" sample: hf mf eload filename"); @@ -1234,17 +1362,19 @@ int CmdHF14AMfELoad(const char *Cmd) case '\0': numBlocks = 16*4; break; case '2' : numBlocks = 32*4; break; case '4' : numBlocks = 256; break; - case 'U' : // fall through , NTAG 215 has 135blocks a 540 bytes. - case 'u' : numBlocks = 135; blockWidth = 8; break; + case 'U' : // fall through + case 'u' : numBlocks = 255; blockWidth = 8; break; default: { numBlocks = 16*4; nameParamNo = 0; } } + uint32_t numblk2 = param_get32ex(Cmd,2,0,10); + if (numblk2 > 0) numBlocks = numblk2; len = param_getstr(Cmd,nameParamNo,filename); - if (len > FILE_PATH_SIZE - 4) len = FILE_PATH_SIZE - 4; + if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; fnameptr += len; @@ -1341,7 +1471,7 @@ int CmdHF14AMfESave(const char *Cmd) len = param_getstr(Cmd,nameParamNo,filename); - if (len > FILE_PATH_SIZE - 4) len = FILE_PATH_SIZE - 4; + if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; // user supplied filename? if (len < 1) { @@ -1541,7 +1671,7 @@ int CmdHF14AMfCSetUID(const char *Cmd) int CmdHF14AMfCSetBlk(const char *Cmd) { - uint8_t memBlock[16] = {0x00}; + uint8_t block[16] = {0x00}; uint8_t blockNo = 0; uint8_t params = MAGIC_SINGLE; int res; @@ -1556,7 +1686,7 @@ int CmdHF14AMfCSetBlk(const char *Cmd) blockNo = param_get8(Cmd, 0); - if (param_gethex(Cmd, 1, memBlock, 32)) { + if (param_gethex(Cmd, 1, block, 32)) { PrintAndLog("block data must include 32 HEX symbols"); return 1; } @@ -1565,9 +1695,9 @@ int CmdHF14AMfCSetBlk(const char *Cmd) if (ctmp == 'w' || ctmp == 'W') params |= MAGIC_WIPE; - PrintAndLog("--block number:%2d data:%s", blockNo, sprint_hex(memBlock, 16)); + PrintAndLog("--block number:%2d data:%s", blockNo, sprint_hex(block, 16)); - res = mfCSetBlock(blockNo, memBlock, NULL, params); + res = mfCSetBlock(blockNo, block, NULL, params); if (res) { PrintAndLog("Can't write block. error=%d", res); return 1; @@ -1618,7 +1748,7 @@ int CmdHF14AMfCLoad(const char *Cmd) return 0; } else { len = strlen(Cmd); - if (len > FILE_PATH_SIZE - 4) len = FILE_PATH_SIZE - 4; + if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; memcpy(filename, Cmd, len); fnameptr += len; @@ -1702,7 +1832,7 @@ int CmdHF14AMfCGetBlk(const char *Cmd) { return 1; } - PrintAndLog("data:%s", sprint_hex(data, sizeof(data))); + PrintAndLog("data: %s", sprint_hex(data, sizeof(data))); return 0; } @@ -1788,7 +1918,7 @@ int CmdHF14AMfCSave(const char *Cmd) { return 0; } else { len = strlen(Cmd); - if (len > FILE_PATH_SIZE - 4) len = FILE_PATH_SIZE - 4; + if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; // get filename based on UID if (len < 1) { @@ -1907,7 +2037,10 @@ int CmdHF14AMfSniff(const char *Cmd){ uint16_t traceLen = resp.arg[1]; len = resp.arg[2]; - if (res == 0) return 0; // we are done + if (res == 0) { + free(buf); + return 0; // we are done + } if (res == 1) { // there is (more) data to be transferred if (pckNum == 0) { // first packet, (re)allocate necessary buffer @@ -1929,6 +2062,11 @@ int CmdHF14AMfSniff(const char *Cmd){ bufsize = traceLen; memset(buf, 0x00, traceLen); } + if (bufPtr == NULL) { + PrintAndLog("Cannot allocate memory for trace"); + free(buf); + return 2; + } memcpy(bufPtr, resp.d.asBytes, len); bufPtr += len; pckNum++; @@ -2005,47 +2143,46 @@ int CmdHf14MfDecryptBytes(const char *Cmd){ return tryDecryptWord( nt, ar_enc, at_enc, data, len); } -static command_t CommandTable[] = -{ - {"help", CmdHelp, 1, "This help"}, - {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, - {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"}, - {"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"}, - {"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"}, - {"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"}, - {"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"}, - {"chk", CmdHF14AMfChk, 0, "Test block keys"}, - {"mifare", CmdHF14AMifare, 0, "Read parity error messages."}, - {"nested", CmdHF14AMfNested, 0, "Test nested authentication"}, - {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"}, - {"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE card"}, - {"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory block"}, - {"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"}, - {"eset", CmdHF14AMfESet, 0, "Set simulator memory block"}, - {"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"}, - {"esave", CmdHF14AMfESave, 0, "Save to file emul dump"}, - {"ecfill", CmdHF14AMfECFill, 0, "Fill simulator memory with help of keys from simulator"}, - {"ekeyprn", CmdHF14AMfEKeyPrn, 0, "Print keys from simulator memory"}, - {"csetuid", CmdHF14AMfCSetUID, 0, "Set UID for magic Chinese card"}, - {"csetblk", CmdHF14AMfCSetBlk, 0, "Write block - Magic Chinese card"}, - {"cgetblk", CmdHF14AMfCGetBlk, 0, "Read block - Magic Chinese card"}, - {"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"}, - {"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"}, - {"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"}, - {"decrypt", CmdHf14MfDecryptBytes, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"}, - {NULL, NULL, 0, NULL} +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, + {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"}, + {"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"}, + {"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"}, + {"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"}, + {"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"}, + {"chk", CmdHF14AMfChk, 0, "Test block keys"}, + {"mifare", CmdHF14AMifare, 0, "Read parity error messages."}, + {"nested", CmdHF14AMfNested, 0, "Test nested authentication"}, + {"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"}, + {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"}, + {"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE card"}, + {"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory block"}, + {"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"}, + {"eset", CmdHF14AMfESet, 0, "Set simulator memory block"}, + {"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"}, + {"esave", CmdHF14AMfESave, 0, "Save to file emul dump"}, + {"ecfill", CmdHF14AMfECFill, 0, "Fill simulator memory with help of keys from simulator"}, + {"ekeyprn", CmdHF14AMfEKeyPrn, 0, "Print keys from simulator memory"}, + {"csetuid", CmdHF14AMfCSetUID, 0, "Set UID for magic Chinese card"}, + {"csetblk", CmdHF14AMfCSetBlk, 0, "Write block - Magic Chinese card"}, + {"cgetblk", CmdHF14AMfCGetBlk, 0, "Read block - Magic Chinese card"}, + {"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"}, + {"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"}, + {"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"}, + {"decrypt", CmdHf14MfDecryptBytes, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"}, + {NULL, NULL, 0, NULL} }; -int CmdHFMF(const char *Cmd) -{ +int CmdHFMF(const char *Cmd) { // flush - WaitForResponseTimeout(CMD_ACK,NULL,100); + clearCommandBuffer(); + //WaitForResponseTimeout(CMD_ACK,NULL,100); CmdsParse(CommandTable, Cmd); return 0; } -int CmdHelp(const char *Cmd) -{ +int CmdHelp(const char *Cmd) { CmdsHelp(CommandTable); return 0; }