diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 7d39b3f29..3e1967b4e 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -17,7 +17,7 @@ #include #ifndef HARDNESTED_AUTHENTICATION_TIMEOUT -# define HARDNESTED_AUTHENTICATION_TIMEOUT 848 //848 // card times out 1ms after wrong authentication (according to NXP documentation) +# define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) #endif #ifndef HARDNESTED_PRE_AUTHENTICATION_LEADTIME # define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication @@ -1122,7 +1122,6 @@ uint8_t chkKey_readb(struct chk_t *c, uint8_t *keyb) { } void chkKey_scanA(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { - uint8_t status; for (uint8_t s = 0; s < *sectorcnt; s++) { // skip already found A keys @@ -1130,8 +1129,7 @@ void chkKey_scanA(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, ui continue; c->block = FirstBlockOfSector( s ); - status = chkKey( c ); - if ( status == 0 ) { + if ( chkKey( c ) == 0 ) { num_to_bytes(c->key, 6, k_sector[s].keyA); found[(s*2)] = 1; ++*foundkeys; @@ -1142,7 +1140,6 @@ void chkKey_scanA(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, ui } void chkKey_scanB(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { - uint8_t status; for (uint8_t s = 0; s < *sectorcnt; s++) { // skip already found B keys @@ -1150,8 +1147,7 @@ void chkKey_scanB(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, ui continue; c->block = FirstBlockOfSector( s ); - status = chkKey( c ); - if ( status == 0 ) { + if ( chkKey( c ) == 0 ) { num_to_bytes(c->key, 6, k_sector[s].keyB); found[(s*2)+1] = 1; ++*foundkeys; @@ -1167,7 +1163,12 @@ void chkKey_loopBonly(struct chk_t *c, struct sector_t *k_sector, uint8_t *found // read Block B, if A is found. for (uint8_t s = 0; s < *sectorcnt; ++s) { + + if ( found[(s*2)] && found[(s*2)+1] ) + continue; + c->block = (FirstBlockOfSector( s ) + NumBlocksPerSector( s ) - 1); + // A but not B if ( found[(s*2)] && !found[(s*2)+1] ){ c->key = bytes_to_num(k_sector[s].keyA, 6); @@ -1187,6 +1188,9 @@ void chkKey_loopBonly(struct chk_t *c, struct sector_t *k_sector, uint8_t *found } } } + + + // get Chunks of keys, to test authentication against card. // arg0 = antal sectorer // arg0 = first time @@ -1200,7 +1204,8 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da uint8_t firstchunk = (arg0 >> 8) & 0xF; uint8_t lastchunk = (arg0 >> 12) & 0xF; uint8_t strategy = arg1 & 0xFF; - uint8_t keyCount = arg2 & 0xFF; + uint8_t use_flashmem = (arg1 >> 8) & 0xFF; + uint16_t keyCount = arg2 & 0xFF; uint8_t status = 0; struct Crypto1State mpcs = {0, 0}; @@ -1217,33 +1222,57 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da static uint8_t found[80]; static uint8_t *uid; - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); +#ifdef WITH_FLASH + if ( use_flashmem ) { + BigBuf_free(); + uint16_t isok = 0; + uint8_t size[2] = {0x00, 0x00}; + isok = Flash_ReadData(DEFAULT_MF_KEYS_OFFSET, size, 2); + if ( isok != 2 ) + goto OUT; + + keyCount = size[1] << 8 | size[0]; + + if ( keyCount == 0 && keyCount == 0xFFFF) + goto OUT; + + datain = BigBuf_malloc( keyCount * 6); + if (datain == NULL ) + goto OUT; + + isok = Flash_ReadData(DEFAULT_MF_KEYS_OFFSET+2, datain, keyCount * 6); + if ( isok != keyCount * 6 ) + goto OUT; + + } +#endif if (uid == NULL || firstchunk) { uid = BigBuf_malloc(10); - if (uid == NULL ) { - if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys: uid malloc failed"); + if (uid == NULL ) goto OUT; - } } + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); LEDsoff(); LED_A_ON(); if ( firstchunk ) { - + clear_trace(); set_tracing(false); memset(k_sector, 0x00, 480+10); memset(found, 0x00, sizeof(found)); foundkeys = 0; - + iso14a_card_select_t card_info; if ( !iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (ALL)"); + if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys_fast: Can't select card (ALL)"); goto OUT; } + switch (card_info.uidlen) { case 4 : cascade_levels = 1; break; case 7 : cascade_levels = 2; break; @@ -1262,19 +1291,23 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da chk_data.block = 0; // keychunk loop - depth first one sector. - if ( strategy == 1 ) { + if ( strategy == 1 || use_flashmem) { uint8_t newfound = foundkeys; + uint16_t lastpos = 0; + uint16_t s_point = 0; // Sector main loop // keep track of how many sectors on card. for (uint8_t s = 0; s < sectorcnt; ++s) { - if ( found[(s*2)] && found[(s*2)+1] ) + if ( found[(s*2)] && found[(s*2)+1] ) continue; - for (uint8_t i = 0; i < keyCount; ++i) { - + 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() && !usb_poll_validate_length()) { goto OUT; @@ -1292,8 +1325,6 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da // new key chk_data.key = bytes_to_num(datain + i * 6, 6); - // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector - // skip already found A keys if( !found[(s*2)] ) { chk_data.keyType = 0; @@ -1303,12 +1334,26 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da found[(s*2)] = 1; ++foundkeys; - chkKey_scanA(&chk_data, k_sector, found, §orcnt, &foundkeys); + chkKey_scanA(&chk_data, k_sector, found, §orcnt, &foundkeys); // read Block B, if A is found. chkKey_loopBonly( &chk_data, k_sector, found, §orcnt, &foundkeys); + chk_data.keyType = 1; + chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); + + chk_data.keyType = 0; chk_data.block = FirstBlockOfSector( s ); + + if ( use_flashmem ) { + if ( lastpos != i && lastpos != 0) { + if ( i - lastpos < 0xF) { + s_point = i & 0xFFF0; + } + } else { + lastpos = i; + } + } } } @@ -1322,25 +1367,46 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da ++foundkeys; chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); + + if ( use_flashmem ) { + if ( lastpos != i && lastpos != 0) { + + if ( i - lastpos < 0xF) + s_point = i & 0xFFF0; + } else { + lastpos = i; + } + } } } - + + if ( found[(s*2)] && found[(s*2)+1] ) + break; + } // end keys test loop - depth first // assume1. if no keys found in first sector, get next keychunk from client - if ( newfound-foundkeys == 0 ) + if ( !use_flashmem && (newfound-foundkeys == 0) ) goto OUT; } // end loop - sector } // end strategy 1 + + if ( foundkeys == allkeys ) + goto OUT; - if ( strategy == 2 ) { + if ( strategy == 2 || use_flashmem ) { + // Keychunk loop - for (uint8_t i = 0; i < keyCount; i++) { - + for (uint16_t i = 0; i < keyCount; i++) { + // Allow button press / usb cmd to interrupt device if (BUTTON_PRESS() && !usb_poll_validate_length()) break; + // found all keys? + if ( foundkeys == allkeys ) + goto OUT; + WDT_HIT(); // new key @@ -1349,7 +1415,9 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da // Sector main loop // keep track of how many sectors on card. for (uint8_t s = 0; s < sectorcnt; ++s) { - + + if ( found[(s*2)] && found[(s*2)+1] ) continue; + // found all keys? if ( foundkeys == allkeys ) goto OUT; @@ -1387,8 +1455,6 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); } } - - } // end loop sectors } // end loop keys } // end loop strategy 2 @@ -1416,7 +1482,7 @@ OUT: set_tracing(false); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - BigBuf_free(); BigBuf_Clear_ext(false); + BigBuf_free(); BigBuf_Clear_ext(false); } else { // partial/none keys found cmd_send(CMD_ACK, foundkeys, 0, 0, 0, 0); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 1bfbf10eb..33e1c6f66 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -170,7 +170,7 @@ int usage_hf14_chk(void){ } int usage_hf14_chk_fast(void){ PrintAndLogEx(NORMAL, "This is a improved checkkeys method speedwise. It checks Mifare Classic tags sector keys against a dictionary file with keys"); - PrintAndLogEx(NORMAL, "Usage: hf mf fchk [h] [t|d] [] []"); + PrintAndLogEx(NORMAL, "Usage: hf mf fchk [h] [t|d|f] [] []"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " all sectors based on card memory, other values than below defaults to 1k"); @@ -179,12 +179,16 @@ int usage_hf14_chk_fast(void){ PrintAndLogEx(NORMAL, " 2 - 2K"); PrintAndLogEx(NORMAL, " 4 - 4K"); PrintAndLogEx(NORMAL, " d write keys to binary file"); - PrintAndLogEx(NORMAL, " t write keys to emulator memory\n"); + PrintAndLogEx(NORMAL, " t write keys to emulator memory"); + PrintAndLogEx(NORMAL, " m use dictionary from flashmemory\n"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf fchk 1 1234567890ab keys.dic -- target 1K using key 1234567890ab, using dictionary file"); PrintAndLogEx(NORMAL, " hf mf fchk 1 t -- target 1K, write to emulator memory"); PrintAndLogEx(NORMAL, " hf mf fchk 1 d -- target 1K, write to file"); +#ifdef WITH_FLASH + PrintAndLogEx(NORMAL, " hf mf fchk 1 m -- target 1K, use dictionary from flashmemory"); +#endif return 0; } int usage_hf14_keybrute(void){ @@ -1136,7 +1140,7 @@ int CmdHF14AMfNested(const char *Cmd) { } PrintAndLogEx(SUCCESS, "Testing known keys. Sector count=%d", SectorsCnt); - res = mfCheckKeys_fast( SectorsCnt, true, true, 1, MIFARE_DEFAULTKEYS_SIZE + 1, keyBlock, e_sector); + res = mfCheckKeys_fast( SectorsCnt, true, true, 1, MIFARE_DEFAULTKEYS_SIZE + 1, keyBlock, e_sector, false); uint64_t t2 = msclock() - t1; PrintAndLogEx(SUCCESS, "Time to check %d known keys: %.0f seconds\n", MIFARE_DEFAULTKEYS_SIZE, (float)t2/1000.0 ); @@ -1167,7 +1171,7 @@ int CmdHF14AMfNested(const char *Cmd) { e_sector[sectorNo].foundKey[trgKeyType] = 1; e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6); - res = mfCheckKeys_fast( SectorsCnt, true, true, 2, 1, keyBlock, e_sector); + res = mfCheckKeys_fast( SectorsCnt, true, true, 2, 1, keyBlock, e_sector, false); continue; default : PrintAndLogEx(WARNING, "unknown Error.\n"); @@ -1467,8 +1471,8 @@ void shuffle( uint8_t *array, uint16_t len) { int CmdHF14AMfChk_fast(const char *Cmd) { char ctmp = 0x00; - ctmp = param_getchar(Cmd, 0); - if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_hf14_chk_fast(); + ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_chk_fast(); FILE * f; char filename[FILE_PATH_SIZE]={0}; @@ -1481,6 +1485,7 @@ int CmdHF14AMfChk_fast(const char *Cmd) { int clen = 0; int transferToEml = 0, createDumpFile = 0; uint32_t keyitems = MIFARE_DEFAULTKEYS_SIZE; + bool use_flashmemory = false; sector_t *e_sector = NULL; @@ -1501,7 +1506,7 @@ int CmdHF14AMfChk_fast(const char *Cmd) { for (i = 1; param_getchar(Cmd, i); i++) { - ctmp = param_getchar(Cmd, i); + ctmp = tolower(param_getchar(Cmd, i)); clen = param_getlength(Cmd, i); if (clen == 12) { @@ -1523,8 +1528,11 @@ int CmdHF14AMfChk_fast(const char *Cmd) { PrintAndLogEx(NORMAL, "[%2d] key %s", keycnt, sprint_hex( (keyBlock + 6*keycnt), 6 ) ); keycnt++; } else if ( clen == 1) { - if (ctmp == 't' || ctmp == 'T') { transferToEml = 1; continue; } - if (ctmp == 'd' || ctmp == 'D') { createDumpFile = 1; continue; } + if (ctmp == 't' ) { transferToEml = 1; continue; } + if (ctmp == 'd' ) { createDumpFile = 1; continue; } +#ifdef WITH_FLASH + if (ctmp == 'm' ) { use_flashmemory = true; continue; } +#endif } else { // May be a dic file if ( param_getstr(Cmd, i, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) { @@ -1574,7 +1582,7 @@ int CmdHF14AMfChk_fast(const char *Cmd) { } } - if (keycnt == 0) { + if (keycnt == 0 && !use_flashmemory) { PrintAndLogEx(SUCCESS, "No key specified, trying default keys"); for (;keycnt < MIFARE_DEFAULTKEYS_SIZE; keycnt++) PrintAndLogEx(NORMAL, "[%2d] %02x%02x%02x%02x%02x%02x", keycnt, @@ -1594,37 +1602,45 @@ int CmdHF14AMfChk_fast(const char *Cmd) { // time uint64_t t1 = msclock(); - - // strategys. 1= deep first on sector 0 AB, 2= width first on all sectors - for (uint8_t strategy = 1; strategy < 3; strategy++) { - PrintAndLogEx(SUCCESS, "Running strategy %u", strategy); - // main keychunk loop - for (uint32_t i = 0; i < keycnt; i += chunksize) { - - if (ukbhit()) { - int gc = getchar(); (void)gc; - PrintAndLogEx(NORMAL, "\naborted via keyboard!\n"); - goto out; - } - - uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i; - - // last chunk? - if ( size == keycnt - i) - lastChunk = true; - - int res = mfCheckKeys_fast( sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector); - if ( firstChunk ) - firstChunk = false; - - // all keys, aborted - if ( res == 0 || res == 2 ) - goto out; - } // end chunks of keys - firstChunk = true; - lastChunk = false; - } // end strategy + if ( use_flashmemory ) { + mfCheckKeys_fast( sectorsCnt, true, true, 1, 0, keyBlock, e_sector, use_flashmemory); + } else { + + // strategys. 1= deep first on sector 0 AB, 2= width first on all sectors + for (uint8_t strategy = 1; strategy < 3; strategy++) { + PrintAndLogEx(SUCCESS, "Running strategy %u", strategy); + + + + // main keychunk loop + for (uint32_t i = 0; i < keycnt; i += chunksize) { + + if (ukbhit()) { + int gc = getchar(); (void)gc; + PrintAndLogEx(NORMAL, "\naborted via keyboard!\n"); + goto out; + } + + uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i; + + // last chunk? + if ( size == keycnt - i) + lastChunk = true; + + int res = mfCheckKeys_fast( sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector, false); + + if ( firstChunk ) + firstChunk = false; + + // all keys, aborted + if ( res == 0 || res == 2 ) + goto out; + } // end chunks of keys + firstChunk = true; + lastChunk = false; + } // end strategy + } out: t1 = msclock() - t1; PrintAndLogEx(SUCCESS, "Time in checkkeys (fast): %.1fs\n", (float)(t1/1000.0)); diff --git a/client/mifarehost.c b/client/mifarehost.c index fe2495938..2859fc207 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -138,13 +138,13 @@ int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keyc // 1 == // 2 == Time-out, aborting int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, uint8_t strategy, - uint32_t size, uint8_t *keyBlock, sector_t *e_sector) { + uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory) { uint64_t t2 = msclock(); uint32_t timeout = 0; // send keychunk - UsbCommand c = {CMD_MIFARE_CHKKEYS_FAST, { (sectorsCnt | (firstChunk << 8) | (lastChunk << 12) ), strategy, size}}; + UsbCommand c = {CMD_MIFARE_CHKKEYS_FAST, { (sectorsCnt | (firstChunk << 8) | (lastChunk << 12) ), ((use_flashmemory << 8) | strategy), size}}; memcpy(c.d.asBytes, keyBlock, 6 * size); clearCommandBuffer(); SendCommand(&c); diff --git a/client/mifarehost.h b/client/mifarehost.h index 65500ded8..8f0f3f3bf 100644 --- a/client/mifarehost.h +++ b/client/mifarehost.h @@ -73,7 +73,7 @@ extern int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key); extern int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys, bool calibrate); extern int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key); extern int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, - uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector); + uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory); extern int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey);