mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 21:33:47 -07:00
CHG: 'hf mf fchk' - two strategys. depth first for sector 1, AB. and width first with all sectors.
first run strategy 1. then 2.
This commit is contained in:
parent
9665bd526a
commit
da57e74140
2 changed files with 155 additions and 144 deletions
|
@ -1079,7 +1079,6 @@ uint8_t chkKey( struct chk_t *c ) {
|
||||||
++i;
|
++i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = mifare_classic_authex(c->pcs, c->cuid, c->block, c->keyType, c->key, AUTH_FIRST, NULL, NULL);
|
res = mifare_classic_authex(c->pcs, c->cuid, c->block, c->keyType, c->key, AUTH_FIRST, NULL, NULL);
|
||||||
|
|
||||||
CHK_TIMEOUT();
|
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) {
|
void chkKey_scanA(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) {
|
||||||
|
uint8_t status;
|
||||||
// keep track of how many sectors on card.
|
for (uint8_t s = 0; s < *sectorcnt; s++) {
|
||||||
for (uint8_t s = 0; s < *sectorcnt; ++s) {
|
|
||||||
|
|
||||||
// skip already found A keys
|
// 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 );
|
if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan A (%d)", c->block);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void chkKey_scanB(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) {
|
void chkKey_scanB(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) {
|
||||||
|
uint8_t status;
|
||||||
// keep track of how many sectors on card.
|
for (uint8_t s = 0; s < *sectorcnt; s++) {
|
||||||
for (uint8_t s = 0; s < *sectorcnt; ++s) {
|
|
||||||
|
|
||||||
// skip already found B keys
|
// skip already found B keys
|
||||||
if ( !found[(s*2)+1] ) {
|
if ( found[(s*2)+1] )
|
||||||
|
continue;
|
||||||
|
|
||||||
c->block = FirstBlockOfSector( s );
|
c->block = FirstBlockOfSector( s );
|
||||||
uint8_t status = chkKey( c );
|
status = chkKey( c );
|
||||||
if ( status == 0 ) {
|
if ( status == 0 ) {
|
||||||
num_to_bytes(c->key, 6, k_sector[s].keyB);
|
num_to_bytes(c->key, 6, k_sector[s].keyB);
|
||||||
found[(s*2)+1] = 1;
|
found[(s*2)+1] = 1;
|
||||||
++*foundkeys;
|
++*foundkeys;
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan B (%d)", c->block);
|
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.
|
// 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) {
|
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.
|
// read Block B, if A is found.
|
||||||
for (uint8_t s = 0; s < *sectorcnt; ++s) {
|
for (uint8_t s = 0; s < *sectorcnt; ++s) {
|
||||||
c->block = (FirstBlockOfSector( s ) + NumBlocksPerSector( s ) - 1);
|
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 ){
|
if ( status == 0 ){
|
||||||
found[(s*2)+1] = 1;
|
found[(s*2)+1] = 1;
|
||||||
++*foundkeys;
|
++*foundkeys;
|
||||||
|
|
||||||
|
if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Loop B only (%d)", c->block);
|
||||||
|
|
||||||
// try quick find all B?
|
// try quick find all B?
|
||||||
// assume: keys comes in groups. Find one B, test against 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->key = bytes_to_num( k_sector[s].keyB, 6);
|
||||||
c->block = 1;
|
c->keyType = 1;
|
||||||
chkKey_scanB(c, k_sector, found, sectorcnt, foundkeys);
|
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 sectorcnt = arg0 & 0xFF; // 16;
|
||||||
uint8_t firstchunk = (arg0 >> 8) & 0xF;
|
uint8_t firstchunk = (arg0 >> 8) & 0xF;
|
||||||
uint8_t lastchunk = (arg0 >> 12) & 0xF;
|
uint8_t lastchunk = (arg0 >> 12) & 0xF;
|
||||||
|
uint8_t strategy = arg1 & 0xFF;
|
||||||
uint8_t keyCount = arg2 & 0xFF;
|
uint8_t keyCount = arg2 & 0xFF;
|
||||||
uint8_t status = 0;
|
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);
|
set_tracing(false);
|
||||||
|
|
||||||
memset(k_sector, 0x00, 480+10);
|
memset(k_sector, 0x00, 480+10);
|
||||||
memset(found, 0x00, 80);
|
memset(found, 0x00, sizeof(found));
|
||||||
foundkeys = 0;
|
foundkeys = 0;
|
||||||
|
|
||||||
iso14a_card_select_t card_info;
|
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.cuid = cuid;
|
||||||
chk_data.cl = cascade_levels;
|
chk_data.cl = cascade_levels;
|
||||||
chk_data.pcs = pcs;
|
chk_data.pcs = pcs;
|
||||||
|
|
||||||
chk_data.block = 0;
|
chk_data.block = 0;
|
||||||
|
|
||||||
// keychunk loop - depth first for sector0.
|
// keychunk loop - depth first for sector0.
|
||||||
for (uint8_t i = 0; i < keyCount; ++i) {
|
if ( strategy == 1 ) {
|
||||||
// Allow button press / usb cmd to interrupt device
|
for (uint8_t i = 0; i < keyCount; ++i) {
|
||||||
if (BUTTON_PRESS() && !usb_poll_validate_length()) break;
|
// Allow button press / usb cmd to interrupt device
|
||||||
|
if (BUTTON_PRESS() && !usb_poll_validate_length()) {
|
||||||
WDT_HIT();
|
goto OUT;
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
WDT_HIT();
|
||||||
|
|
||||||
// skip already found B keys
|
// new key
|
||||||
if( !found[1] ) {
|
chk_data.key = bytes_to_num(datain + i * 6, 6);
|
||||||
chk_data.keyType = 1;
|
// those scans messes with block.
|
||||||
status = chkKey( &chk_data);
|
chk_data.block = 0;
|
||||||
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) {
|
|
||||||
|
|
||||||
// assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector
|
// 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
|
// skip already found A keys
|
||||||
if( !found[(s*2)] ) {
|
if( !found[0] ) {
|
||||||
chk_data.keyType = 0;
|
chk_data.keyType = 0;
|
||||||
status = chkKey( &chk_data);
|
status = chkKey( &chk_data);
|
||||||
if ( status == 0 ) {
|
if ( status == 0 ) {
|
||||||
memcpy(k_sector[s].keyA, datain + i * 6, 6);
|
memcpy(k_sector[0].keyA, datain + i * 6, 6);
|
||||||
found[(s*2)] = 1;
|
found[0] = 1;
|
||||||
++foundkeys;
|
++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.
|
// read Block B, if A is found.
|
||||||
chkKey_loopBonly( &chk_data, k_sector, found, §orcnt, &foundkeys);
|
chkKey_loopBonly( &chk_data, k_sector, found, §orcnt, &foundkeys);
|
||||||
|
|
||||||
|
chk_data.block = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip already found B keys
|
// skip already found B keys
|
||||||
if( !found[(s*2)+1] ) {
|
if( !found[1] ) {
|
||||||
chk_data.keyType = 1;
|
chk_data.keyType = 1;
|
||||||
status = chkKey( &chk_data);
|
status = chkKey( &chk_data);
|
||||||
if ( status == 0 ) {
|
if ( status == 0 ) {
|
||||||
memcpy(k_sector[s].keyB, datain + i * 6, 6);
|
memcpy(k_sector[0].keyB, datain + i * 6, 6);
|
||||||
found[(s*2)+1] = 1;
|
found[1] = 1;
|
||||||
++foundkeys;
|
++foundkeys;
|
||||||
|
|
||||||
chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys);
|
chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // end loop sectors
|
} // end look - depth first
|
||||||
|
} // strategy 1
|
||||||
// is all keys found?
|
|
||||||
if ( foundkeys == allkeys )
|
if ( strategy == 2 ) {
|
||||||
break;
|
// Keychunk loop
|
||||||
} // end loop keys
|
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:
|
OUT:
|
||||||
LEDsoff();
|
LEDsoff();
|
||||||
|
|
||||||
|
|
|
@ -1323,54 +1323,57 @@ int CmdHF14AMfChk_fast(const char *Cmd) {
|
||||||
// time
|
// time
|
||||||
uint64_t t1 = msclock();
|
uint64_t t1 = msclock();
|
||||||
|
|
||||||
// main keychunk loop
|
// strategys. 1= deep first on sector 0 AB, 2= width first on all sectors
|
||||||
for (uint32_t i = 0; i < keycnt; i += chunksize) {
|
for (uint8_t strategy = 1; strategy < 3; strategy++) {
|
||||||
|
// main keychunk loop
|
||||||
uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i;
|
for (uint32_t i = 0; i < keycnt; i += chunksize) {
|
||||||
|
|
||||||
// last chunk?
|
uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i;
|
||||||
if ( size == keycnt - i)
|
|
||||||
lastChunk = true;
|
// last chunk?
|
||||||
|
if ( size == keycnt - i)
|
||||||
// send keychunk
|
lastChunk = true;
|
||||||
UsbCommand c = {CMD_MIFARE_CHKKEYS_FAST, { (SectorsCnt | (firstChunk << 8) | (lastChunk << 12) ), 0, size}};
|
|
||||||
|
// send keychunk
|
||||||
memcpy(c.d.asBytes, keyBlock + i * 6, 6 * size);
|
UsbCommand c = {CMD_MIFARE_CHKKEYS_FAST, { (SectorsCnt | (firstChunk << 8) | (lastChunk << 12) ), strategy, size}};
|
||||||
|
|
||||||
|
memcpy(c.d.asBytes, keyBlock + i * 6, 6 * size);
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
|
|
||||||
|
if ( firstChunk ) firstChunk = false;
|
||||||
|
|
||||||
if ( firstChunk ) firstChunk = false;
|
uint64_t t2 = msclock();
|
||||||
|
while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) {
|
||||||
uint64_t t2 = msclock();
|
timeout++;
|
||||||
while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) {
|
printf(".");
|
||||||
timeout++;
|
fflush(stdout);
|
||||||
printf(".");
|
// max timeout for one chunk of 85keys, 60*2sec = 120seconds
|
||||||
fflush(stdout);
|
// s70 with 40*2 keys to check, 80*85 = 6800 auth.
|
||||||
// max timeout for one chunk of 85keys, 60*2sec = 120seconds
|
// takes about 97s, still some margin before abort
|
||||||
// s70 with 40*2 keys to check, 80*85 = 6800 auth.
|
if (timeout > 60) {
|
||||||
// takes about 97s, still some margin before abort
|
PrintAndLog("\nNo response from Proxmark. Aborting...");
|
||||||
if (timeout > 60) {
|
return 1;
|
||||||
PrintAndLog("\nNo response from Proxmark. Aborting...");
|
}
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
uint8_t curr_keys = resp.arg[0];
|
||||||
uint8_t curr_keys = resp.arg[0];
|
foo = bytes_to_num(resp.d.asBytes+480, 8);
|
||||||
foo = bytes_to_num(resp.d.asBytes+480, 8);
|
bar = bytes_to_num(resp.d.asBytes+488, 2);
|
||||||
bar = bytes_to_num(resp.d.asBytes+488, 2);
|
|
||||||
|
|
||||||
// reset
|
// reset
|
||||||
timeout = 0;
|
timeout = 0;
|
||||||
|
|
||||||
t2 = msclock() - t2;
|
t2 = msclock() - t2;
|
||||||
PrintAndLog("\n[-] Chunk: %.1fs | found %u/%u keys (%u)", (float)(t2/1000.0), curr_keys, (SectorsCnt<<1), size);
|
PrintAndLog("\n[-] Chunk: %.1fs | found %u/%u keys (%u)", (float)(t2/1000.0), curr_keys, (SectorsCnt<<1), size);
|
||||||
|
|
||||||
// all keys?
|
// all keys?
|
||||||
if ( curr_keys == SectorsCnt*2 || lastChunk ) {
|
if ( curr_keys == SectorsCnt*2 || lastChunk ) {
|
||||||
memcpy(e_sector, resp.d.asBytes, SectorsCnt * sizeof(icesector_t) );
|
memcpy(e_sector, resp.d.asBytes, SectorsCnt * sizeof(icesector_t) );
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue