diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a1ce7f47..d20025afb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] - Added `-f` parameter to `hf iclass sam` command to use the sam to parse a card dump (@antiklesys) +- Fixed WTX response behavior in `ExchangeRaw14A()` (@team-orangeBlue) - Added `-t` / `--timeout` option for `hf 15 sim` (@recursivenomad) - Added `--aid` parameter to `hf seos` commands (@kormax) - Added `hf iclass blacktears` command to perform an automated tearoff of block 1 to set non-secure page mode(@antiklesys) diff --git a/armsrc/Standalone/hf_emvpng.c b/armsrc/Standalone/hf_emvpng.c index 21c5a593c..7de09f461 100644 --- a/armsrc/Standalone/hf_emvpng.c +++ b/armsrc/Standalone/hf_emvpng.c @@ -301,9 +301,14 @@ void RunMod(void) { if (iso14443a_select_card(NULL, &card_a_info, NULL, true, 0, false)) { DbpString(_YELLOW_("+") "Found ISO 14443 Type A!"); - + + chktoken = false; for (uint8_t i = 0; i < 4; i++) { - chktoken = false; + + if (i == 3 && chktoken) { + break; // Tag 57 was already found in GPO, no need to issue READ RECORD + } + LED_C_OFF(); LED_B_ON(); uint8_t apdulen = iso14_apdu(apdus[i], (uint16_t) apduslen[i], false, apdubuffer, sizeof(apdubuffer), NULL); @@ -331,13 +336,13 @@ void RunMod(void) { } - } else if (i == 3) { + } else if (i == 2 || i == 3) { - // find track 2 - if (apdubuffer[u] == 0x57 && apdubuffer[u + 1] == 0x13 && !chktoken) { + // find track 2 in GPO or READ RECORD + if (u + 20 < apdulen && apdubuffer[u] == 0x57 && apdubuffer[u + 1] == 0x13 && !chktoken) { chktoken = true; - memcpy(&token, &apdubuffer[u + 2], 19); + memcpy(token, &apdubuffer[u + 2], 19); break; } } diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 9ba2bcaf9..f64620108 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -286,7 +286,7 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_ // Received RWD authentication challenge and response case 64: { // Store the authentication attempt - if (auth_table_len < (AUTH_TABLE_LENGTH - 8)) { + if (auth_table_len + 8 <= AUTH_TABLE_LENGTH) { memcpy(auth_table + auth_table_len, rx, 8); auth_table_len += 8; } @@ -1371,7 +1371,7 @@ void SniffHitag2(bool ledcontrol) { // Check if we recognize a valid authentication attempt if (rxlen == 64) { // Store the authentication attempt - if (auth_table_len < (AUTH_TABLE_LENGTH - 8)) { + if (auth_table_len + 8 <= AUTH_TABLE_LENGTH) { memcpy(auth_table + auth_table_len, rx, 8); auth_table_len += 8; } diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 5f522aed1..76dc70ed1 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -4492,16 +4492,21 @@ void DetectNACKbug(void) { set_tracing(false); } -/* /// -Based upon the SimulateIso14443aTag, this aims to instead take an AID Value you've supplied, and return your selected response. -It can also continue after the AID has been selected, and respond to other request types. -This was forked from the original function to allow for more flexibility in the future, and to increase the processing speed of the original function. -/// */ +// Increased the buffer size to allow for more complex responses +#define DYNAMIC_RESPONSE_BUFFER2_SIZE ( 512 ) +#define DYNAMIC_MODULATION_BUFFER2_SIZE ( 1536 ) + +// EvilDaemond +// Based upon the SimulateIso14443aTag, this aims to instead take an AID Value you've supplied, and return your selected response. +// It can also continue after the AID has been selected, and respond to other request types. +// This was forked from the original function to allow for more flexibility in the future, and to increase the processing speed of the original function. +// void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid, uint8_t *ats, size_t ats_len, uint8_t *aid, size_t aid_len, uint8_t *selectaid_response, size_t selectaid_response_len, uint8_t *getdata_response, size_t getdata_response_len) { + tag_response_info_t *responses; uint32_t cuid = 0; uint8_t pages = 0; @@ -4514,14 +4519,19 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid, // Copy the AID, AID Response, and the GetData APDU response into our variables if ((aid == NULL) || (selectaid_response == NULL) || (getdata_response == NULL)) { reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINVARG, NULL, 0); + return; } // free eventually allocated BigBuf memory but keep Emulator Memory BigBuf_free_keep_EM(); - // Increased the buffer size to allow for more complex responses -#define DYNAMIC_RESPONSE_BUFFER2_SIZE 512 -#define DYNAMIC_MODULATION_BUFFER2_SIZE 1536 + // Response payloads must fit within the dynamic response buffer, + // accounting for 1-byte IBlock header + 1-byte optional CID (offset 0 or 1) + if (selectaid_response_len + 2 > DYNAMIC_RESPONSE_BUFFER2_SIZE || + getdata_response_len + 2 > DYNAMIC_RESPONSE_BUFFER2_SIZE) { + reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINVARG, NULL, 0); + return; + } uint8_t *dynamic_response_buffer2 = BigBuf_calloc(DYNAMIC_RESPONSE_BUFFER2_SIZE); if (dynamic_response_buffer2 == NULL) { diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index 2ccc12fb2..b5c751876 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -323,6 +323,10 @@ void MifareDES_Auth1(uint8_t *datain) { memcpy(keybytes, PICC_MASTER_KEY24, 24); } } else { + if (payload->keylen > sizeof(keybytes)) { + OnErrorNG(CMD_HF_DESFIRE_AUTH1, PM3_EINVARG); + return; + } memcpy(keybytes, payload->key, payload->keylen); } diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 44ef40c3a..dc3066bdd 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -1162,6 +1162,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav uint8_t *recv; PacketResponseNG resp; +resend: if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { recv = resp.data.asBytes; int iLen = resp.oldarg[0]; @@ -1184,7 +1185,23 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav } return PM3_ELENGTH; } - + if (recv[0] & 0xf0) { + uint8_t dbg_curr = DBG_NONE; + if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) { + return PM3_EFAILED; + } + if (dbg_curr >= DBG_DEBUG) { + PrintAndLogEx(WARNING, "Card requested WTX"); + } + // WARNING for users of this function: + // This NO_DISCONNECT flag will NOT save you. If you run your commands with LeaveSignalOn set to false, they will still fail if a card asks for WTX. + // Better keep the flag on and do a DropField(); at the end. + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | cmdc, 5, 0, recv, min); // 2b frame +1b "data" + 2b crc. Hardcode length to 5 and reply to response + goto resend; + } + // OBS + // This if check below breaks command flow if the card for whatever reason decides to request a WTX. + // Because WTX will do a |= 0xF0 to the framing, this check triggers and everything that was happening will stop. if (recv[0] != data[0]) { if (silentMode == false) { PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", recv[0], data[0]);