improve the ecfill function used in autopwn among others. Lessen failed auth/reads by skipping s 16,17 using key A for MFC EV1 cards

This commit is contained in:
iceman1001 2023-06-25 16:22:39 +02:00
commit d40a89b27b

View file

@ -2302,64 +2302,98 @@ int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype) {
int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
uint32_t cuid = 0;
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs;
pcs = &mpcs;
// variables
uint8_t dataoutbuf[16] = {0x00};
uint8_t dataoutbuf2[16] = {0x00};
uint8_t uid[10] = {0x00};
LED_A_ON();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace();
set_tracing(true);
// variables
bool have_uid = false;
uint8_t cascade_levels = 0;
uint32_t cuid = 0;
uint8_t uid[10] = {0x00};
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs;
pcs = &mpcs;
int retval = PM3_SUCCESS;
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
retval = PM3_ESOFT;
if (g_dbglevel > DBG_ERROR) Dbprintf("Can't select card");
goto out;
}
for (uint8_t s = 0; s < sectorcnt; s++) {
uint64_t ui64Key = emlGetKey(s, keytype);
for (uint8_t sectorNo = 0; sectorNo < sectorcnt; sectorNo++) {
uint64_t ui64Key = emlGetKey(sectorNo, keytype);
if (sectorNo == 0) {
if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keytype, ui64Key, AUTH_FIRST)) {
retval = PM3_EPARTIAL;
if (g_dbglevel > DBG_ERROR) Dbprintf("Sector[%2d]. Auth error", sectorNo);
// MFC 1K EV1 sector 16,17 don't use key A.
if ((sectorcnt == 18) && (keytype == 0) && s > 15) {
continue;
}
// use fast select
if (have_uid == false) { // need a full select cycle to get the uid first
iso14a_card_select_t card_info;
if (iso14443a_select_card(uid, &card_info, &cuid, true, 0, true) == 0) {
continue;
}
} else {
if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keytype, ui64Key, AUTH_NESTED)) {
retval = PM3_EPARTIAL;
if (g_dbglevel > DBG_ERROR) Dbprintf("Sector[%2d]. Auth nested error", sectorNo);
switch (card_info.uidlen) {
case 4 :
cascade_levels = 1;
break;
case 7 :
cascade_levels = 2;
break;
case 10:
cascade_levels = 3;
break;
default:
break;
}
have_uid = true;
} else { // no need for anticollision. We can directly select the card
if (iso14443a_fast_select_card(uid, cascade_levels) == 0) {
continue;
}
}
for (uint8_t blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
if (mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) {
retval = PM3_EPARTIAL;
if (g_dbglevel > DBG_ERROR) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo);
continue;
// Auth
if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(s), keytype, ui64Key, AUTH_FIRST)) {
retval = PM3_EPARTIAL;
if (g_dbglevel > DBG_ERROR) {
Dbprintf("Sector %2d - Auth error", s);
}
continue;
}
if (memcmp(dataoutbuf, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) == 0) {
continue;
}
#define MAX_RETRIES 2
if (blockNo < NumBlocksPerSector(sectorNo) - 1) {
emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1);
} else { // sector trailer, keep the keys, set only the AC
emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);
memcpy(dataoutbuf2 + 6, dataoutbuf + 6, 4);
emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);
uint8_t data[16] = {0x00};
for (uint8_t b = 0; b < NumBlocksPerSector(s); b++) {
memset(data, 0x00, sizeof(data));
for (uint8_t r = 0; r < MAX_RETRIES; r++) {
if (mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(s) + b, data)) {
retval |= PM3_EPARTIAL;
if (g_dbglevel > DBG_ERROR) {
Dbprintf("Error reading sector %2d block %2d", s, b);
}
continue;
}
// No need to copy empty
if (memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) == 0) {
continue;
}
if (b < NumBlocksPerSector(s) - 1) {
emlSetMem(data, FirstBlockOfSector(s) + b, 1);
} else {
// sector trailer, keep the keys, set only the AC
uint8_t st[16] = {0x00};
emlGetMem(st, FirstBlockOfSector(s) + b, 1);
memcpy(st + 6, data + 6, 4);
emlSetMem(st, FirstBlockOfSector(s) + b, 1);
}
}
}
}
@ -2367,9 +2401,6 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) {
int res = mifare_classic_halt(pcs, cuid);
(void)res;
if (g_dbglevel >= DBG_INFO) DbpString("Emulator fill sectors finished");
out:
crypto1_deinit(pcs);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();