X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/3906036e11b6cfba19c043ae29ac1dcb3ea88414..60faf34855193c1b01e8f67e9f914192c6fdff7e:/client/cmdhfmf.c diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 83f26302..d354952b 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -20,8 +20,18 @@ int CmdHF14AMifare(const char *Cmd) uint32_t nt = 0, nr = 0; uint64_t par_list = 0, ks_list = 0, r_key = 0; int16_t isOK = 0; - - UsbCommand c = {CMD_READER_MIFARE, {true, 0, 0}}; + int tmpchar; + uint8_t blockNo = 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"); @@ -29,26 +39,31 @@ int CmdHF14AMifare(const char *Cmd) printf("Press button on the proxmark3 device to abort both proxmark3 and client.\n"); printf("-------------------------------------------------------------------------\n"); + clock_t t1 = clock(); start: clearCommandBuffer(); SendCommand(&c); //flush queue - while (ukbhit()) getchar(); + while (ukbhit()) { + tmpchar = getchar(); + (void)tmpchar; + } // wait cycle while (true) { printf("."); fflush(stdout); if (ukbhit()) { - getchar(); + tmpchar = getchar(); + (void)tmpchar; printf("\naborted via keyboard!\n"); break; } 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); @@ -81,12 +96,12 @@ start: c.arg[0] = false; goto start; } else { - isOK = 0; - printf("------------------------------------------------------------------\n"); PrintAndLog("Found valid key: %012"llx" \n", r_key); } - PrintAndLog(""); + t1 = clock() - t1; + if ( t1 > 0 ) + PrintAndLog("Time in darkside: %.0f ticks - %4.2f sec\n", (float)t1, ((float)t1)/CLOCKS_PER_SEC); return 0; } @@ -305,8 +320,10 @@ int CmdHF14AMfDump(const char *Cmd) } // Read keys A from file + size_t bytes_read; for (sectorNo=0; sectorNo 0 ) + PrintAndLog("Time to check 6 known keys: %.0f ticks %4.2f sec", (float)t2, ((float)t2)/CLOCKS_PER_SEC); + // 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; } } } - 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("-----------------------------------------------\nIterations count: %d\n\n", iterations); - //print them - PrintAndLog("|---|----------------|---|----------------|---|"); - PrintAndLog("|sec|key A |res|key B |res|"); - PrintAndLog("|---|----------------|---|----------------|---|"); + // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? + PrintAndLog("trying to read key B..."); for (i = 0; i < SectorsCnt; i++) { - PrintAndLog("|%03d| %012"llx" | %d | %012"llx" | %d |", i, - e_sector[i].Key[0], e_sector[i].foundKey[0], e_sector[i].Key[1], e_sector[i].foundKey[1]); + // 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(); + SendCommand(&c); + + UsbCommand resp; + if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) continue; + + uint8_t isOK = resp.arg[0] & 0xff; + if (!isOK) continue; + + uint8_t *data = resp.d.asBytes; + 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].Key[1] = key64; + } + } } - PrintAndLog("|---|----------------|---|----------------|---|"); + + 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 ); // transfer them to the emulator if (transferToEml) { @@ -804,7 +839,7 @@ int CmdHF14AMfNestedHard(const char *Cmd) char ctmp; ctmp = param_getchar(Cmd, 0); - if (ctmp != 'R' && ctmp != 'r' && strlen(Cmd) < 20) { + 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]"); @@ -829,15 +864,17 @@ int CmdHF14AMfNestedHard(const char *Cmd) 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') { @@ -883,15 +920,16 @@ int CmdHF14AMfNestedHard(const char *Cmd) } } - 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 ", + 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"); + 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); + 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) { @@ -925,6 +963,8 @@ int CmdHF14AMfChk(const char *Cmd) uint8_t *keyBlock = NULL, *p; uint8_t stKeyBlock = 20; + sector *e_sector = NULL; + int i, res; int keycnt = 0; char ctmp = 0x00; @@ -933,14 +973,15 @@ int CmdHF14AMfChk(const char *Cmd) uint8_t keyType = 0; uint64_t key64 = 0; + uint8_t tempkey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + int transferToEml = 0; int createDumpFile = 0; 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 @@ -958,9 +999,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; @@ -971,9 +1011,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) { @@ -1007,7 +1047,7 @@ int CmdHF14AMfChk(const char *Cmd) } keyBlock = p; } - PrintAndLog("chk key[%2d] %02x%02x%02x%02x%02x%02x", keycnt, + PrintAndLog("check 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++; @@ -1040,14 +1080,14 @@ int CmdHF14AMfChk(const char *Cmd) if (!p) { PrintAndLog("Cannot allocate memory for defKeys"); free(keyBlock); - free(f); + fclose(f); return 2; } keyBlock = p; } 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 custom key[%2d] %012"llx, keycnt, bytes_to_num(keyBlock + 6*keycnt, 6)); keycnt++; memset(buf, 0, sizeof(buf)); } @@ -1064,80 +1104,144 @@ 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("check 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)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6); } // initialize storage for found keys - bool validKey[2][40]; - uint8_t foundKey[2][40][6]; - for (uint16_t t = 0; t < 2; t++) { - for (uint16_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) { - validKey[t][sectorNo] = false; - for (uint16_t i = 0; i < 6; i++) { - foundKey[t][sectorNo][i] = 0xff; - } - } + e_sector = calloc(SectorsCnt, sizeof(sector)); + if (e_sector == NULL) { + free(keyBlock); + return 1; } + + uint8_t trgKeyType = 0; - for ( int t = !keyType; t < 2; keyType==2?(t++):(t=2) ) { - int b=blockNo; + // time + clock_t t1 = clock(); + + // check keys. + for (trgKeyType = 0; trgKeyType < 2; ++trgKeyType) { + int b = blockNo; for (int i = 0; i < SectorsCnt; ++i) { - PrintAndLog("--sector:%2d, block:%3d, key type:%C, key count:%2d ", i, b, t?'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) { - uint32_t size = keycnt-c>max_keys?max_keys:keycnt-c; - res = mfCheckKeys(b, t, true, size, &keyBlock[6*c], &key64); - if (res != 1) { - if (!res) { - PrintAndLog("Found valid key:[%012"llx"]",key64); - num_to_bytes(key64, 6, foundKey[t][i]); - validKey[t][i] = true; - } - } else { - PrintAndLog("Command execute timeout"); + + // skip already found keys. + if (e_sector[i].foundKey[trgKeyType]) continue; + + 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) { + + uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c; + + res = mfCheckKeys(b, trgKeyType, true, size, &keyBlock[6*c], &key64); + if (!res) { + 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 { + e_sector[i].Key[trgKeyType] = 0xffffffffffff; + e_sector[i].foundKey[trgKeyType] = FALSE; } } - b<127?(b+=4):(b+=16); + b < 127 ? ( b +=4 ) : ( b += 16 ); } } + // 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(); + SendCommand(&c); - if (transferToEml) { - uint8_t block[16]; - for (uint16_t sectorNo = 0; sectorNo < SectorsCnt; sectorNo++) { - if (validKey[0][sectorNo] || validKey[1][sectorNo]) { - mfEmlGetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); - for (uint16_t t = 0; t < 2; t++) { - if (validKey[t][sectorNo]) { - memcpy(block + t*10, foundKey[t][sectorNo], 6); - } - } - mfEmlSetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); + UsbCommand resp; + if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) continue; + + uint8_t isOK = resp.arg[0] & 0xff; + if (!isOK) continue; + + uint8_t *data = resp.d.asBytes; + 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].Key[1] = key64; } } - PrintAndLog("Found keys have been transferred to the emulator memory"); } + + 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 ); + + if (transferToEml) { + uint8_t block[16] = {0x00}; + for (uint8_t i = 0; i < SectorsCnt; ++i ) { + mfEmlGetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); + if (e_sector[i].foundKey[0]) + num_to_bytes(e_sector[i].Key[0], 6, block); + if (e_sector[i].foundKey[1]) + num_to_bytes(e_sector[i].Key[1], 6, block+10); + mfEmlSetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); + } + PrintAndLog("Found keys have been transferred to the emulator memory"); + } + if (createDumpFile) { FILE *fkeys = fopen("dumpkeys.bin","wb"); if (fkeys == NULL) { PrintAndLog("Could not create file dumpkeys.bin"); free(keyBlock); + free(e_sector); return 1; } - for (uint16_t t = 0; t < 2; t++) { - fwrite(foundKey[t], 1, 6*SectorsCnt, fkeys); + PrintAndLog("Printing keys to binary file dumpkeys.bin..."); + + for( i=0; i sizeof(data)) ? sizeof(data) : resp.arg[1]; - - memcpy(data, resp.d.asBytes, len); - - 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]; - 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]; - tryMfk64(corr_uid, data, key); - } - PrintAndLog("--"); + memset(data, 0x00, sizeof(data)); + memset(key, 0x00, sizeof(key)); + int len = (resp.arg[1] > sizeof(data)) ? sizeof(data) : resp.arg[1]; + + memcpy(data, resp.d.asBytes, len); + + uint64_t corr_uid = 0; + + // this IF? what was I thinking of? + if ( memcmp(data, "\x00\x00\x00\x00", 4) == 0 ) { + corr_uid = ((uint64_t)(data[3] << 24)) | (data[2] << 16) | (data[1] << 8) | data[0]; + 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 |= (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); } - } - + PrintAndLog("--"); + } + } return 0; } @@ -1781,6 +1889,7 @@ int CmdHF14AMfCLoad(const char *Cmd) if (mfCSetBlock(blockNum, buf8, NULL, flags)) { PrintAndLog("Can't set magic card block: %d", blockNum); + fclose(f); return 3; } blockNum++; @@ -1968,6 +2077,7 @@ int CmdHF14AMfSniff(const char *Cmd){ bool wantSaveToEmlFile = 0; //var + int tmpchar; int res = 0; int len = 0; int blockLen = 0; @@ -2018,7 +2128,8 @@ int CmdHF14AMfSniff(const char *Cmd){ printf("."); fflush(stdout); if (ukbhit()) { - getchar(); + tmpchar = getchar(); + (void)tmpchar; printf("\naborted via keyboard!\n"); break; }