From 3e22d99b036ce2fe94d772a14f858b304c3dd9af Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 25 Sep 2019 10:24:34 +0200 Subject: [PATCH] hf mf darkside uses NG. checkbutton more seldom, shoulded interfere with syncing the prng so much --- armsrc/appmain.c | 8 +++++- armsrc/iso14443a.c | 55 +++++++++++++++++++++++++---------- client/mifare/mifarehost.c | 59 ++++++++++++++++++++++++++++---------- 3 files changed, 91 insertions(+), 31 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 7c483f2e1..b778fa785 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1032,7 +1032,13 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_HF_MIFARE_READER: { - ReaderMifare(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2]); + struct p { + uint8_t first_run; + uint8_t blockno; + uint8_t key_type; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + ReaderMifare(payload->first_run, payload->blockno, payload->key_type); break; } case CMD_HF_MIFARE_READBL: { diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 348317a8a..7b0db6499 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2791,6 +2791,8 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { static uint8_t par_low = 0; static uint8_t mf_nr_ar3 = 0; + int return_status = PM3_SUCCESS; + AddCrc14A(mf_auth, 2); if (first_try) { @@ -2807,6 +2809,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { } LED_C_ON(); + uint16_t checkbtn_cnt = 0; uint16_t i; for (i = 0; true; ++i) { @@ -2815,10 +2818,15 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { WDT_HIT(); // Test if the action was cancelled - if (BUTTON_PRESS()) { - isOK = -1; - break; + if (checkbtn_cnt == 2000) { + if (BUTTON_PRESS() || data_available()) { + isOK = -1; + return_status = PM3_EABORTED; + break; + } + checkbtn_cnt = 0; } + checkbtn_cnt++; // this part is from Piwi's faster nonce collecting part in Hardnested. if (!have_uid) { // need a full select cycle to get the uid first @@ -2876,8 +2884,15 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding - if (ReaderReceive(receivedAnswer, receivedAnswerPar)) + int resp_res = ReaderReceive(receivedAnswer, receivedAnswerPar); + if (resp_res == 4) received_nack = true; + else if (resp_res == 32) { + // did we get lucky and got our dummykey to be valid? + isOK = -6; + break; + } + // we didn't calibrate our clock yet, // iceman: has to be calibrated every time. @@ -3000,26 +3015,36 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Number of sent auth requests: %u", i); - uint8_t buf[32] = {0x00}; - memset(buf, 0x00, sizeof(buf)); - num_to_bytes(cuid, 4, buf); - num_to_bytes(nt, 4, buf + 4); - memcpy(buf + 8, par_list, 8); - memcpy(buf + 16, ks_list, 8); - memcpy(buf + 24, mf_nr_ar, 8); + struct { + int32_t isOK; + uint8_t cuid[4]; + uint8_t nt[4]; + uint8_t par_list[8]; + uint8_t ks_list[8]; + uint8_t nr[4]; + uint8_t ar[4]; + } PACKED payload; - reply_mix(CMD_ACK, isOK, 0, 0, buf, sizeof(buf)); + payload.isOK = isOK; + num_to_bytes(cuid, 4, payload.cuid); + num_to_bytes(nt, 4, payload.nt); + memcpy(payload.par_list, par_list, sizeof(payload.par_list)); + memcpy(payload.ks_list, ks_list, sizeof(payload.ks_list)); + memcpy(payload.nr, mf_nr_ar, sizeof(payload.nr)); + memcpy(payload.ar, mf_nr_ar + 4, sizeof(payload.ar)); + + reply_ng(CMD_HF_MIFARE_READER, return_status, (uint8_t*)&payload, sizeof(payload)); hf_field_off(); set_tracing(false); } /* -* Mifare Classic NACK-bug detection -* Thanks to @doegox for the feedback and new approaches. + * Mifare Classic NACK-bug detection + * Thanks to @doegox for the feedback and new approaches. */ void DetectNACKbug(void) { - uint8_t mf_auth[] = {0x60, 0x00, 0xF5, 0x7B}; + uint8_t mf_auth[] = {0x60, 0x00, 0xF5, 0x7B}; uint8_t mf_nr_ar[] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index e4cec00c0..ac8015d98 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -30,7 +30,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { uint32_t nt = 0, nr = 0, ar = 0; uint64_t par_list = 0, ks_list = 0; uint64_t *keylist = NULL, *last_keylist = NULL; - bool arg0 = true; + bool first_run = true; // message PrintAndLogEx(NORMAL, "--------------------------------------------------------------------------------\n"); @@ -40,7 +40,15 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { while (true) { clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFARE_READER, arg0, blockno, key_type, NULL, 0); + struct { + uint8_t first_run; + uint8_t blockno; + uint8_t key_type; + } PACKED payload; + payload.first_run = first_run; + payload.blockno = blockno; + payload.key_type = key_type; + SendCommandNG(CMD_HF_MIFARE_READER, (uint8_t*)&payload, sizeof(payload)); //flush queue while (kbd_enter_pressed()) { @@ -56,26 +64,47 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { } PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - int16_t isOK = resp.oldarg[0]; - if (isOK < 0) - return isOK; + if (WaitForResponseTimeout(CMD_HF_MIFARE_READER, &resp, 2000)) { + if (resp.status == PM3_EABORTED) { + return -1; + } - uid = (uint32_t)bytes_to_num(resp.data.asBytes + 0, 4); - nt = (uint32_t)bytes_to_num(resp.data.asBytes + 4, 4); - par_list = bytes_to_num(resp.data.asBytes + 8, 8); - ks_list = bytes_to_num(resp.data.asBytes + 16, 8); - nr = (uint32_t)bytes_to_num(resp.data.asBytes + 24, 4); - ar = (uint32_t)bytes_to_num(resp.data.asBytes + 28, 4); + struct p { + int32_t isOK; + uint8_t cuid[4]; + uint8_t nt[4]; + uint8_t par_list[8]; + uint8_t ks_list[8]; + uint8_t nr[4]; + uint8_t ar[4]; + } PACKED; + + struct p* package = (struct p*) resp.data.asBytes; + + if (package->isOK == -6) { + *key = 0101; + return 1; + } + + if (package->isOK < 0) + return package->isOK; + + + uid = (uint32_t)bytes_to_num(package->cuid, sizeof(package->cuid)); + nt = (uint32_t)bytes_to_num(package->nt, sizeof(package->nr)); + par_list = bytes_to_num(package->par_list, sizeof(package->par_list)); + ks_list = bytes_to_num(package->ks_list, sizeof(package->ks_list)); + nr = (uint32_t)bytes_to_num(package->nr, 4); + ar = (uint32_t)bytes_to_num(package->ar, 4); break; } } PrintAndLogEx(NORMAL, "\n"); - if (par_list == 0 && arg0 == true) { + if (par_list == 0 && first_run == true) { PrintAndLogEx(SUCCESS, "Parity is all zero. Most likely this card sends NACK on every authentication."); } - arg0 = false; + first_run = false; uint32_t keycount = nonce2key(uid, nt, nr, ar, par_list, ks_list, &keylist); @@ -124,7 +153,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { PrintAndLogEx(FAILED, "all candidate keys failed. Restarting darkside attack"); free(last_keylist); last_keylist = keylist; - arg0 = true; + first_run = true; } } free(last_keylist);