mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 02:27:26 -07:00
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:
parent
9b2657294a
commit
d40a89b27b
1 changed files with 74 additions and 43 deletions
|
@ -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();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue