X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/b725f2ca21d11709b5e61595bd88ae260fee4c7f..1d5464397c4a6e0c251ba7ed80f4f797a9063cb0:/client/cmdhfmf.c diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index e10a88f3..d6cae59f 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -21,8 +21,17 @@ int CmdHF14AMifare(const char *Cmd) uint64_t par_list = 0, ks_list = 0, r_key = 0; int16_t isOK = 0; int tmpchar; + uint8_t blockNo = 0; - UsbCommand c = {CMD_READER_MIFARE, {true, 0, 0}}; + char cmdp = param_getchar(Cmd, 0); + if ( cmdp == 'H' || cmdp == 'h') { + PrintAndLog("Usage: hf mf mifare "); + PrintAndLog(" sample: hf mf mifare 0"); + return 0; + } + + blockNo = param_get8(Cmd, 0); + UsbCommand c = {CMD_READER_MIFARE, {true, blockNo, 0}}; // message printf("-------------------------------------------------------------------------\n"); @@ -54,13 +63,8 @@ start: } UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { isOK = resp.arg[0]; - uid = (uint32_t)bytes_to_num(resp.d.asBytes + 0, 4); - nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4); - par_list = bytes_to_num(resp.d.asBytes + 8, 8); - ks_list = bytes_to_num(resp.d.asBytes + 16, 8); - nr = bytes_to_num(resp.d.asBytes + 24, 4); printf("\n\n"); switch (isOK) { case -1 : PrintAndLog("Button pressed. Aborted.\n"); break; @@ -70,6 +74,11 @@ start: PrintAndLog("generating polynomial with 16 effective bits only, but shows unexpected behaviour.\n"); break; default: ; } + uid = (uint32_t)bytes_to_num(resp.d.asBytes + 0, 4); + nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4); + par_list = bytes_to_num(resp.d.asBytes + 8, 8); + ks_list = bytes_to_num(resp.d.asBytes + 16, 8); + nr = bytes_to_num(resp.d.asBytes + 24, 4); break; } } @@ -87,14 +96,12 @@ start: c.arg[0] = false; goto start; } else { - isOK = 0; - printf("------------------------------------------------------------------\n"); PrintAndLog("Found valid key: %012"llx" \n", r_key); } + t1 = clock() - t1; - if ( t1 > 0 ){ - PrintAndLog("Time in darkside: %.0f ticks - %4.2f sec\n (%u)", (float)t1, ((float)t1)/CLOCKS_PER_SEC, CLOCKS_PER_SEC); - } + if ( t1 > 0 ) + PrintAndLog("Time in darkside: %.0f ticks - %4.2f sec\n", (float)t1, ((float)t1)/CLOCKS_PER_SEC); return 0; } @@ -566,7 +573,7 @@ int CmdHF14AMfNested(const char *Cmd) uint8_t trgKeyType = 0; uint8_t SectorsCnt = 0; uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - uint8_t keyBlock[14*6]; + uint8_t keyBlock[6*6]; uint64_t key64 = 0; bool transferToEml = false; @@ -640,40 +647,35 @@ int CmdHF14AMfNested(const char *Cmd) transferToEml |= (ctmp == 'd' || ctmp == 'D'); if (cmdp == 'o') { - PrintAndLog("--target block no:%3d, target key type:%c ", trgBlockNo, trgKeyType?'B':'A'); int16_t isOK = mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, true); - if (isOK) { - switch (isOK) { - case -1 : PrintAndLog("Error: No response from Proxmark.\n"); break; - case -2 : PrintAndLog("Button pressed. Aborted.\n"); break; - case -3 : PrintAndLog("Tag isn't vulnerable to Nested Attack (random numbers are not predictable).\n"); break; - default : PrintAndLog("Unknown Error.\n"); - } - return 2; - } - key64 = bytes_to_num(keyBlock, 6); - if (key64) { - PrintAndLog("Found valid key:%012"llx, key64); - - // transfer key to the emulator - if (transferToEml) { - uint8_t sectortrailer; - if (trgBlockNo < 32*4) { // 4 block sector - sectortrailer = (trgBlockNo & 0x03) + 3; - } else { // 16 block sector - sectortrailer = (trgBlockNo & 0x0f) + 15; + switch (isOK) { + case -1 : PrintAndLog("Error: No response from Proxmark.\n"); break; + case -2 : PrintAndLog("Button pressed. Aborted.\n"); break; + case -3 : PrintAndLog("Tag isn't vulnerable to Nested Attack (random numbers are not predictable).\n"); break; + case -4 : PrintAndLog("No valid key found"); break; + case -5 : + key64 = bytes_to_num(keyBlock, 6); + + // transfer key to the emulator + if (transferToEml) { + uint8_t sectortrailer; + if (trgBlockNo < 32*4) { // 4 block sector + sectortrailer = (trgBlockNo & 0x03) + 3; + } else { // 16 block sector + sectortrailer = (trgBlockNo & 0x0f) + 15; + } + mfEmlGetMem(keyBlock, sectortrailer, 1); + + if (!trgKeyType) + num_to_bytes(key64, 6, keyBlock); + else + num_to_bytes(key64, 6, &keyBlock[10]); + mfEmlSetMem(keyBlock, sectortrailer, 1); } - mfEmlGetMem(keyBlock, sectortrailer, 1); - - if (!trgKeyType) - num_to_bytes(key64, 6, keyBlock); - else - num_to_bytes(key64, 6, &keyBlock[10]); - mfEmlSetMem(keyBlock, sectortrailer, 1); - } - } else { - PrintAndLog("No valid key found"); + return 0; + default : PrintAndLog("Unknown Error.\n"); } + return 2; } else { // ------------------------------------ multiple sectors working clock_t t1 = clock(); @@ -688,14 +690,6 @@ int CmdHF14AMfNested(const char *Cmd) num_to_bytes(0xa0a1a2a3a4a5, 6, (uint8_t*)(keyBlock + 3 * 6)); num_to_bytes(0xb0b1b2b3b4b5, 6, (uint8_t*)(keyBlock + 4 * 6)); num_to_bytes(0xaabbccddeeff, 6, (uint8_t*)(keyBlock + 5 * 6)); - num_to_bytes(0x4d3a99c351dd, 6, (uint8_t*)(keyBlock + 6 * 6)); - num_to_bytes(0x1a982c7e459a, 6, (uint8_t*)(keyBlock + 7 * 6)); - num_to_bytes(0xd3f7d3f7d3f7, 6, (uint8_t*)(keyBlock + 8 * 6)); - num_to_bytes(0x714c5c886e97, 6, (uint8_t*)(keyBlock + 9 * 6)); - num_to_bytes(0x587ee5f9350f, 6, (uint8_t*)(keyBlock + 10 * 6)); - num_to_bytes(0xa0478cc39091, 6, (uint8_t*)(keyBlock + 11 * 6)); - num_to_bytes(0x533cb6c723f6, 6, (uint8_t*)(keyBlock + 12 * 6)); - num_to_bytes(0x8fd0a4f256e9, 6, (uint8_t*)(keyBlock + 13 * 6)); PrintAndLog("Testing known keys. Sector count=%d", SectorsCnt); for (i = 0; i < SectorsCnt; i++) { @@ -710,50 +704,61 @@ int CmdHF14AMfNested(const char *Cmd) } } } + clock_t t2 = clock() - t1; + if ( t2 > 0 ) + PrintAndLog("Time to check 6 known keys: %.0f ticks %4.2f sec", (float)t2, ((float)t2)/CLOCKS_PER_SEC); + + PrintAndLog("enter nested..."); // nested sectors iterations = 0; - PrintAndLog("nested..."); + PrintAndLog("enter nested..."); bool calibrate = true; + for (i = 0; i < NESTED_SECTOR_RETRY; i++) { - for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) { - for (trgKeyType = 0; trgKeyType < 2; trgKeyType++) { + for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; ++sectorNo) { + for (trgKeyType = 0; trgKeyType < 2; ++trgKeyType) { + if (e_sector[sectorNo].foundKey[trgKeyType]) continue; - PrintAndLog("-----------------------------------------------"); - int16_t isOK = mfnested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate); - if(isOK) { - switch (isOK) { - case -1 : PrintAndLog("Error: No response from Proxmark.\n"); break; - case -2 : PrintAndLog("Button pressed. Aborted.\n"); break; - case -3 : PrintAndLog("Tag isn't vulnerable to Nested Attack (random numbers are not predictable).\n"); break; - default : PrintAndLog("Unknown Error.\n"); - } - free(e_sector); - return 2; - } else { - calibrate = false; - } - iterations++; - - key64 = bytes_to_num(keyBlock, 6); - if (key64) { - PrintAndLog("Found valid key:%012"llx, key64); - e_sector[sectorNo].foundKey[trgKeyType] = 1; - e_sector[sectorNo].Key[trgKeyType] = key64; + int16_t isOK = mfnested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate); + switch (isOK) { + case -1 : PrintAndLog("Error: No response from Proxmark.\n"); break; + case -2 : PrintAndLog("Button pressed. Aborted.\n"); break; + case -3 : PrintAndLog("Tag isn't vulnerable to Nested Attack (random numbers are not predictable).\n"); break; + case -4 : //key not found + calibrate = false; + iterations++; + continue; + case -5 : + calibrate = false; + iterations++; + e_sector[sectorNo].foundKey[trgKeyType] = 1; + e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6); + continue; + + default : PrintAndLog("Unknown Error.\n"); } + free(e_sector); + return 2; } } } + + t1 = clock() - t1; + if ( t1 > 0 ) + PrintAndLog("Time in nested: %.0f ticks %4.2f sec (%4.2f sec per key)\n", (float)t1, ((float)t1)/CLOCKS_PER_SEC, ((float)t1)/iterations/CLOCKS_PER_SEC); // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? - PrintAndLog("testing to read B..."); + PrintAndLog("trying to read key B..."); for (i = 0; i < SectorsCnt; i++) { // KEY A but not KEY B if ( e_sector[i].foundKey[0] && !e_sector[i].foundKey[1] ) { uint8_t sectrail = (FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); + PrintAndLog("Reading block %d", sectrail); + UsbCommand c = {CMD_MIFARE_READBL, {sectrail, 0, 0}}; num_to_bytes(e_sector[i].Key[0], 6, c.d.asBytes); // KEY A clearCommandBuffer(); @@ -769,15 +774,12 @@ int CmdHF14AMfNested(const char *Cmd) key64 = bytes_to_num(data+10, 6); if (key64) { PrintAndLog("Data:%s", sprint_hex(data+10, 6)); - e_sector[i].foundKey[1] = 1; + e_sector[i].foundKey[1] = TRUE; e_sector[i].Key[1] = key64; } } } - - t1 = clock() - t1; - if ( t1 > 0 ) - PrintAndLog("Time in nested: %.0f ticks %4.2f sec (%4.2f sec per key)\n", (float)t1, ((float)t1)/CLOCKS_PER_SEC, ((float)t1)/iterations/CLOCKS_PER_SEC); + //print them printKeyTable( SectorsCnt, e_sector ); @@ -982,8 +984,7 @@ int CmdHF14AMfChk(const char *Cmd) keyBlock = calloc(stKeyBlock, 6); if (keyBlock == NULL) return 1; - uint64_t defaultKeys[] = - { + uint64_t defaultKeys[] = { 0xffffffffffff, // Default key (first key used by program if no user defined key) 0x000000000000, // Blank key 0xa0a1a2a3a4a5, // NFCForum MAD key @@ -1001,9 +1002,8 @@ int CmdHF14AMfChk(const char *Cmd) int defaultKeysSize = sizeof(defaultKeys) / sizeof(uint64_t); for (int defaultKeyCounter = 0; defaultKeyCounter < defaultKeysSize; defaultKeyCounter++) - { num_to_bytes(defaultKeys[defaultKeyCounter], 6, (uint8_t*)(keyBlock + defaultKeyCounter * 6)); - } + if (param_getchar(Cmd, 0)=='*') { blockNo = 3; @@ -1014,9 +1014,9 @@ int CmdHF14AMfChk(const char *Cmd) case '4': SectorsCnt = 40; break; default: SectorsCnt = 16; } - } - else + } else { blockNo = param_get8(Cmd, 0); + } ctmp = param_getchar(Cmd, 1); switch (ctmp) { @@ -1050,7 +1050,7 @@ int CmdHF14AMfChk(const char *Cmd) } keyBlock = p; } - PrintAndLog("chk key[%2d] %02x%02x%02x%02x%02x%02x", keycnt, + PrintAndLog("key[%2d] %02x%02x%02x%02x%02x%02x", keycnt, (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++; @@ -1090,7 +1090,7 @@ int CmdHF14AMfChk(const char *Cmd) } memset(keyBlock + 6 * keycnt, 0, 6); num_to_bytes(strtoll(buf, NULL, 16), 6, keyBlock + 6*keycnt); - PrintAndLog("chk custom key[%2d] %012"llx, keycnt, bytes_to_num(keyBlock + 6*keycnt, 6)); + PrintAndLog("check key[%2d] %012"llx, keycnt, bytes_to_num(keyBlock + 6*keycnt, 6)); keycnt++; memset(buf, 0, sizeof(buf)); } @@ -1107,7 +1107,7 @@ int CmdHF14AMfChk(const char *Cmd) if (keycnt == 0) { PrintAndLog("No key specified, trying default keys"); for (;keycnt < defaultKeysSize; keycnt++) - PrintAndLog("chk default key[%2d] %02x%02x%02x%02x%02x%02x", keycnt, + PrintAndLog("key[%2d] %02x%02x%02x%02x%02x%02x", keycnt, (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); } @@ -1120,21 +1120,20 @@ int CmdHF14AMfChk(const char *Cmd) } uint8_t trgKeyType = 0; + uint32_t max_keys = keycnt > (USB_CMD_DATA_SIZE/6) ? (USB_CMD_DATA_SIZE/6) : keycnt; // time clock_t t1 = clock(); // check keys. for (trgKeyType = 0; trgKeyType < 2; ++trgKeyType) { + int b = blockNo; for (int i = 0; i < SectorsCnt; ++i) { // skip already found keys. if (e_sector[i].foundKey[trgKeyType]) continue; - PrintAndLog("--sector:%2d, block:%3d, key type:%C, key count:%2d ", i, b, trgKeyType ? 'B':'A', keycnt); - - uint32_t max_keys = keycnt > (USB_CMD_DATA_SIZE/6) ? (USB_CMD_DATA_SIZE/6) : keycnt; for (uint32_t c = 0; c < keycnt; c += max_keys) { @@ -1142,11 +1141,12 @@ int CmdHF14AMfChk(const char *Cmd) res = mfCheckKeys(b, trgKeyType, true, size, &keyBlock[6*c], &key64); if (!res) { - PrintAndLog("Found valid key:[%012"llx"]",key64); + //PrintAndLog("Sector:%3d Block:%3d, key type: %C -- Found key [%012"llx"]", i, b, trgKeyType ? 'B':'A', key64); + e_sector[i].Key[trgKeyType] = key64; e_sector[i].foundKey[trgKeyType] = TRUE; break; - } else { + } else { e_sector[i].Key[trgKeyType] = 0xffffffffffff; e_sector[i].foundKey[trgKeyType] = FALSE; } @@ -1154,14 +1154,21 @@ int CmdHF14AMfChk(const char *Cmd) b < 127 ? ( b +=4 ) : ( b += 16 ); } } + + t1 = clock() - t1; + if ( t1 > 0 ) + printf("Time in checkkeys: %.0f ticks %1.2f sec (%1.2f sec per key)\n\n", (float)t1, ((float)t1)/CLOCKS_PER_SEC, ((float)t1)/keycnt/CLOCKS_PER_SEC); + // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? PrintAndLog("testing to read B..."); for (i = 0; i < SectorsCnt; i++) { // KEY A but not KEY B if ( e_sector[i].foundKey[0] && !e_sector[i].foundKey[1] ) { - + uint8_t sectrail = (FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); + PrintAndLog("Reading block %d", sectrail); + UsbCommand c = {CMD_MIFARE_READBL, {sectrail, 0, 0}}; num_to_bytes(e_sector[i].Key[0], 6, c.d.asBytes); // KEY A clearCommandBuffer(); @@ -1182,10 +1189,7 @@ int CmdHF14AMfChk(const char *Cmd) } } } - - t1 = clock() - t1; - if ( t1 > 0 ) - printf("Time in checkkeys: %.0f ticks %1.2f sec (%1.2f sec per key)\n\n", (float)t1, ((float)t1)/CLOCKS_PER_SEC, ((float)t1)/keycnt/CLOCKS_PER_SEC); + //print them printKeyTable( SectorsCnt, e_sector );