From da57e74140e0c52e639008c827c9de0c276bf78c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 11 Dec 2017 01:44:55 +0100 Subject: [PATCH] CHG: 'hf mf fchk' - two strategys. depth first for sector 1, AB. and width first with all sectors. first run strategy 1. then 2. --- armsrc/mifarecmd.c | 208 +++++++++++++++++++++++---------------------- client/cmdhfmf.c | 91 ++++++++++---------- 2 files changed, 155 insertions(+), 144 deletions(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index bd2be1a7f..7ce0b76a6 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1079,7 +1079,6 @@ uint8_t chkKey( struct chk_t *c ) { ++i; continue; } - res = mifare_classic_authex(c->pcs, c->cuid, c->block, c->keyType, c->key, AUTH_FIRST, NULL, NULL); CHK_TIMEOUT(); @@ -1118,44 +1117,41 @@ 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) { - - // keep track of how many sectors on card. - for (uint8_t s = 0; s < *sectorcnt; ++s) { + uint8_t status; + for (uint8_t s = 0; s < *sectorcnt; s++) { // skip already found A keys - if ( !found[(s*2)] ) { + if ( found[(s*2)] ) + continue; + + c->block = FirstBlockOfSector( s ); + status = chkKey( c ); + if ( status == 0 ) { + num_to_bytes(c->key, 6, k_sector[s].keyA); + found[(s*2)] = 1; + ++*foundkeys; - c->block = FirstBlockOfSector( s ); - - uint8_t status = chkKey( c ); - if ( status == 0 ) { - num_to_bytes(c->key, 6, k_sector[s].keyA); - found[(s*2)] = 1; - ++*foundkeys; - - if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan A (%d)", c->block); - } + if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan A (%d)", c->block); } } } void chkKey_scanB(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { - - // keep track of how many sectors on card. - for (uint8_t s = 0; s < *sectorcnt; ++s) { + uint8_t status; + for (uint8_t s = 0; s < *sectorcnt; s++) { // skip already found B keys - if ( !found[(s*2)+1] ) { + if ( found[(s*2)+1] ) + continue; - c->block = FirstBlockOfSector( s ); - uint8_t status = chkKey( c ); - if ( status == 0 ) { - num_to_bytes(c->key, 6, k_sector[s].keyB); - found[(s*2)+1] = 1; - ++*foundkeys; - - if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan B (%d)", c->block); - } + c->block = FirstBlockOfSector( s ); + status = chkKey( c ); + if ( status == 0 ) { + num_to_bytes(c->key, 6, k_sector[s].keyB); + found[(s*2)+1] = 1; + ++*foundkeys; + + if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan B (%d)", c->block); } } } @@ -1164,8 +1160,6 @@ void chkKey_scanA(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, ui // when A is found but not B, try to read B. void chkKey_loopBonly(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { - if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Loop B only (%d)", c->block); - // read Block B, if A is found. for (uint8_t s = 0; s < *sectorcnt; ++s) { c->block = (FirstBlockOfSector( s ) + NumBlocksPerSector( s ) - 1); @@ -1176,10 +1170,13 @@ void chkKey_loopBonly(struct chk_t *c, struct sector_t *k_sector, uint8_t *found if ( status == 0 ){ found[(s*2)+1] = 1; ++*foundkeys; + + if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Loop B only (%d)", c->block); + // try quick find all B? // assume: keys comes in groups. Find one B, test against all B. c->key = bytes_to_num( k_sector[s].keyB, 6); - c->block = 1; + c->keyType = 1; chkKey_scanB(c, k_sector, found, sectorcnt, foundkeys); } } @@ -1197,6 +1194,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da uint8_t sectorcnt = arg0 & 0xFF; // 16; uint8_t firstchunk = (arg0 >> 8) & 0xF; uint8_t lastchunk = (arg0 >> 12) & 0xF; + uint8_t strategy = arg1 & 0xFF; uint8_t keyCount = arg2 & 0xFF; uint8_t status = 0; @@ -1233,7 +1231,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da set_tracing(false); memset(k_sector, 0x00, 480+10); - memset(found, 0x00, 80); + memset(found, 0x00, sizeof(found)); foundkeys = 0; iso14a_card_select_t card_info; @@ -1256,103 +1254,113 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da chk_data.cuid = cuid; chk_data.cl = cascade_levels; chk_data.pcs = pcs; - chk_data.block = 0; // keychunk loop - depth first for sector0. - for (uint8_t i = 0; i < keyCount; ++i) { - // Allow button press / usb cmd to interrupt device - if (BUTTON_PRESS() && !usb_poll_validate_length()) break; - - WDT_HIT(); - - // 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[0] ) { - chk_data.keyType = 0; - status = chkKey( &chk_data); - if ( status == 0 ) { - memcpy(k_sector[0].keyA, datain + i * 6, 6); - found[0] = 1; - ++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); + if ( strategy == 1 ) { + for (uint8_t i = 0; i < keyCount; ++i) { + // Allow button press / usb cmd to interrupt device + if (BUTTON_PRESS() && !usb_poll_validate_length()) { + goto OUT; } - } + + WDT_HIT(); - // skip already found B keys - if( !found[1] ) { - chk_data.keyType = 1; - status = chkKey( &chk_data); - if ( status == 0 ) { - memcpy(k_sector[0].keyB, datain + i * 6, 6); - found[1] = 1; - ++foundkeys; - - chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); - } - } - } // end look - depth first - - // Keychunk loop - for (uint8_t i = 0; i < keyCount; ++i) { - - // Allow button press / usb cmd to interrupt device - if (BUTTON_PRESS() && !usb_poll_validate_length()) break; - - WDT_HIT(); - - // new key - chk_data.key = bytes_to_num(datain + i * 6, 6); - - // Sector main loop - // keep track of how many sectors on card. - for (uint8_t s = 0; s < sectorcnt; ++s) { - + // new key + chk_data.key = bytes_to_num(datain + i * 6, 6); + // those scans messes with block. + chk_data.block = 0; // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector - chk_data.block = FirstBlockOfSector( s ); - + // skip already found A keys - if( !found[(s*2)] ) { + if( !found[0] ) { chk_data.keyType = 0; status = chkKey( &chk_data); if ( status == 0 ) { - memcpy(k_sector[s].keyA, datain + i * 6, 6); - found[(s*2)] = 1; + memcpy(k_sector[0].keyA, datain + i * 6, 6); + found[0] = 1; ++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.block = 0; } } // skip already found B keys - if( !found[(s*2)+1] ) { + if( !found[1] ) { chk_data.keyType = 1; status = chkKey( &chk_data); if ( status == 0 ) { - memcpy(k_sector[s].keyB, datain + i * 6, 6); - found[(s*2)+1] = 1; + memcpy(k_sector[0].keyB, datain + i * 6, 6); + found[1] = 1; ++foundkeys; chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); } } - } // end loop sectors - - // is all keys found? - if ( foundkeys == allkeys ) - break; - } // end loop keys + } // end look - depth first + } // strategy 1 + + if ( strategy == 2 ) { + // Keychunk loop + for (uint8_t i = 0; i < keyCount; i++) { + + // Allow button press / usb cmd to interrupt device + if (BUTTON_PRESS() && !usb_poll_validate_length()) break; + + WDT_HIT(); + // new key + chk_data.key = bytes_to_num(datain + i * 6, 6); + + // Sector main loop + // keep track of how many sectors on card. + for (uint8_t s = 0; s < sectorcnt; ++s) { + + // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector + chk_data.block = FirstBlockOfSector( s ); + + // skip already found A keys + if( !found[(s*2)] ) { + chk_data.keyType = 0; + status = chkKey( &chk_data); + if ( status == 0 ) { + memcpy(k_sector[s].keyA, datain + i * 6, 6); + found[(s*2)] = 1; + ++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.block = FirstBlockOfSector( s ); + } + } + + // skip already found B keys + if( !found[(s*2)+1] ) { + chk_data.keyType = 1; + status = chkKey( &chk_data); + if ( status == 0 ) { + memcpy(k_sector[s].keyB, datain + i * 6, 6); + found[(s*2)+1] = 1; + ++foundkeys; + + chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); + } + } + } // end loop sectors + + // is all keys found? + if ( foundkeys == allkeys ) + break; + } // end loop keys + } // end loop strategy 2 OUT: LEDsoff(); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index d15cee45a..dcff829b6 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1323,54 +1323,57 @@ int CmdHF14AMfChk_fast(const char *Cmd) { // time uint64_t t1 = msclock(); - // main keychunk loop - for (uint32_t i = 0; i < keycnt; i += chunksize) { - - uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i; - - // last chunk? - if ( size == keycnt - i) - lastChunk = true; - - // send keychunk - UsbCommand c = {CMD_MIFARE_CHKKEYS_FAST, { (SectorsCnt | (firstChunk << 8) | (lastChunk << 12) ), 0, size}}; - - memcpy(c.d.asBytes, keyBlock + i * 6, 6 * size); + // strategys. 1= deep first on sector 0 AB, 2= width first on all sectors + for (uint8_t strategy = 1; strategy < 3; strategy++) { + // main keychunk loop + for (uint32_t i = 0; i < keycnt; i += chunksize) { + + uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i; + + // last chunk? + if ( size == keycnt - i) + lastChunk = true; + + // send keychunk + UsbCommand c = {CMD_MIFARE_CHKKEYS_FAST, { (SectorsCnt | (firstChunk << 8) | (lastChunk << 12) ), strategy, size}}; + + memcpy(c.d.asBytes, keyBlock + i * 6, 6 * size); - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + + if ( firstChunk ) firstChunk = false; - if ( firstChunk ) firstChunk = false; - - uint64_t t2 = msclock(); - while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - timeout++; - printf("."); - fflush(stdout); - // max timeout for one chunk of 85keys, 60*2sec = 120seconds - // s70 with 40*2 keys to check, 80*85 = 6800 auth. - // takes about 97s, still some margin before abort - if (timeout > 60) { - PrintAndLog("\nNo response from Proxmark. Aborting..."); - return 1; + uint64_t t2 = msclock(); + while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + timeout++; + printf("."); + fflush(stdout); + // max timeout for one chunk of 85keys, 60*2sec = 120seconds + // s70 with 40*2 keys to check, 80*85 = 6800 auth. + // takes about 97s, still some margin before abort + if (timeout > 60) { + PrintAndLog("\nNo response from Proxmark. Aborting..."); + return 1; + } } - } - - uint8_t curr_keys = resp.arg[0]; - foo = bytes_to_num(resp.d.asBytes+480, 8); - bar = bytes_to_num(resp.d.asBytes+488, 2); + + uint8_t curr_keys = resp.arg[0]; + foo = bytes_to_num(resp.d.asBytes+480, 8); + bar = bytes_to_num(resp.d.asBytes+488, 2); - // reset - timeout = 0; - - t2 = msclock() - t2; - PrintAndLog("\n[-] Chunk: %.1fs | found %u/%u keys (%u)", (float)(t2/1000.0), curr_keys, (SectorsCnt<<1), size); - - // all keys? - if ( curr_keys == SectorsCnt*2 || lastChunk ) { - memcpy(e_sector, resp.d.asBytes, SectorsCnt * sizeof(icesector_t) ); - break; + // reset + timeout = 0; + + t2 = msclock() - t2; + PrintAndLog("\n[-] Chunk: %.1fs | found %u/%u keys (%u)", (float)(t2/1000.0), curr_keys, (SectorsCnt<<1), size); + + // all keys? + if ( curr_keys == SectorsCnt*2 || lastChunk ) { + memcpy(e_sector, resp.d.asBytes, SectorsCnt * sizeof(icesector_t) ); + break; + } } }