diff --git a/armsrc/sam_picopass.c b/armsrc/sam_picopass.c index 546c480fa..e5a75e971 100644 --- a/armsrc/sam_picopass.c +++ b/armsrc/sam_picopass.c @@ -44,7 +44,7 @@ * @param response_len Pointer to the variable where the length of the retreived data will be stored. * @return Status code indicating success or failure of the operation. */ -static int sam_send_request_iso15(const uint8_t *const request, const uint8_t request_len, uint8_t *response, uint8_t *response_len, const bool shallow_mod) { +static int sam_send_request_iso15(const uint8_t *const request, const uint8_t request_len, uint8_t *response, uint8_t *response_len, const bool shallow_mod, const bool break_on_nr_mac, const bool prevent_epurse_update) { int res = PM3_SUCCESS; if (g_dbglevel >= DBG_DEBUG) DbpString("start sam_send_request_iso14a"); @@ -98,39 +98,68 @@ static int sam_send_request_iso15(const uint8_t *const request, const uint8_t re nfc_tx_len = sam_copy_payload_sam2nfc(nfc_tx_buf, sam_rx_buf); - // should consider blocking update(2) commands and simulating answer - // example command: 87 02 C9 FD FF FF FF FF FF FF F4 BF 98 E2 - - bool is_cmd_update = (nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_UPDATE; - - if (g_dbglevel >= DBG_INFO) { - DbpString("ISO15 TAG REQUEST: "); - Dbhexdump(nfc_tx_len, nfc_tx_buf, false); - } - - int tries = 3; - nfc_rx_len = 0; - while (tries-- > 0) { - iclass_send_as_reader(nfc_tx_buf, nfc_tx_len, &start_time, &eof_time, shallow_mod); - uint16_t timeout = is_cmd_update ? ICLASS_READER_TIMEOUT_UPDATE : ICLASS_READER_TIMEOUT_ACTALL; - - res = GetIso15693AnswerFromTag(nfc_rx_buf, ISO7816_MAX_FRAME, timeout, &eof_time, false, true, &nfc_rx_len); - if (res == PM3_SUCCESS && nfc_rx_len > 0) { - break; + bool is_cmd_check = (nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_CHECK; + if(is_cmd_check && break_on_nr_mac){ + memcpy(response, nfc_tx_buf, nfc_tx_len); + *response_len = nfc_tx_len; + if (g_dbglevel >= DBG_INFO) { + DbpString("NR-MAC: "); + Dbhexdump((*response_len)-1, response+1, false); } - - start_time = eof_time + ((DELAY_ICLASS_VICC_TO_VCD_READER + DELAY_ISO15693_VCD_TO_VICC_READER + (8 * 8 * 8 * 16)) * 2); - } - - - if (res != PM3_SUCCESS ) { - res = PM3_ECARDEXCHANGE; + res = PM3_SUCCESS; goto out; } - if (g_dbglevel >= DBG_INFO) { - DbpString("ISO15 TAG RESPONSE: "); - Dbhexdump(nfc_rx_len, nfc_rx_buf, false); + bool is_cmd_update = (nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_UPDATE; + if(is_cmd_update && prevent_epurse_update && nfc_tx_buf[0] == 0x87 && nfc_tx_buf[1] == 0x02){ + // block update(2) command and fake the response to prevent update of epurse + + // NFC TX BUFFERS PREPARED BY SAM LOOKS LIKE: + // 87 02 #1(C9 FD FF FF) #2(FF FF FF FF) F4 BF 98 E2 + + // NFC RX BUFFERS EXPECTED BY SAM WOULD LOOK LIKE: + // #2(FF FF FF FF) #1(C9 FD FF FF) 3A 47 + + memcpy(nfc_rx_buf+0, nfc_tx_buf+6, 4); + memcpy(nfc_rx_buf+4, nfc_tx_buf+0, 4); + AddCrc(nfc_rx_buf, 8); + nfc_rx_len = 10; + + if (g_dbglevel >= DBG_INFO) { + DbpString("FAKE EPURSE UPDATE RESPONSE: "); + Dbhexdump(nfc_rx_len, nfc_rx_buf, false); + } + + } else { + if (g_dbglevel >= DBG_INFO) { + DbpString("ISO15 TAG REQUEST: "); + Dbhexdump(nfc_tx_len, nfc_tx_buf, false); + } + + int tries = 3; + nfc_rx_len = 0; + while (tries-- > 0) { + iclass_send_as_reader(nfc_tx_buf, nfc_tx_len, &start_time, &eof_time, shallow_mod); + uint16_t timeout = is_cmd_update ? ICLASS_READER_TIMEOUT_UPDATE : ICLASS_READER_TIMEOUT_ACTALL; + + res = GetIso15693AnswerFromTag(nfc_rx_buf, ISO7816_MAX_FRAME, timeout, &eof_time, false, true, &nfc_rx_len); + if (res == PM3_SUCCESS && nfc_rx_len > 0) { + break; + } + + start_time = eof_time + ((DELAY_ICLASS_VICC_TO_VCD_READER + DELAY_ISO15693_VCD_TO_VICC_READER + (8 * 8 * 8 * 16)) * 2); + } + + + if (res != PM3_SUCCESS ) { + res = PM3_ECARDEXCHANGE; + goto out; + } + + if (g_dbglevel >= DBG_INFO) { + DbpString("ISO15 TAG RESPONSE: "); + Dbhexdump(nfc_rx_len, nfc_rx_buf, false); + } } @@ -296,9 +325,11 @@ out: * @return Status code indicating success or failure of the operation. */ int sam_picopass_get_pacs(PacketCommandNG *c) { - bool disconnectAfter = c->oldarg[0] & 0x01; - bool skipDetect = c->oldarg[1] & 0x01; - bool shallow_mod = false; + const bool disconnectAfter = !!(c->oldarg[0] & BITMASK(0)); + const bool skipDetect = !!(c->oldarg[0] & BITMASK(1)); + const bool breakOnNrMac = !!(c->oldarg[0] & BITMASK(2)); + const bool preventEpurseUpdate = !!(c->oldarg[0] & BITMASK(3)); + const bool shallow_mod = !!(c->oldarg[0] & BITMASK(4)); uint8_t *cmd = c->data.asBytes; uint16_t cmd_len = (uint16_t) c->oldarg[2]; @@ -334,7 +365,7 @@ int sam_picopass_get_pacs(PacketCommandNG *c) { // step 3: SamCommand RequestPACS, relay NFC communication uint8_t sam_response[ISO7816_MAX_FRAME] = { 0x00 }; uint8_t sam_response_len = 0; - res = sam_send_request_iso15(cmd, cmd_len, sam_response, &sam_response_len, shallow_mod); + res = sam_send_request_iso15(cmd, cmd_len, sam_response, &sam_response_len, shallow_mod, breakOnNrMac, preventEpurseUpdate); if (res != PM3_SUCCESS) { goto err; } diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 68add842a..bcdbee5cb 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -5407,31 +5407,32 @@ static int CmdHFiClassSAM(const char *Cmd) { arg_lit0("k", "keep", "keep the field active after command executed"), arg_lit0("n", "nodetect", "skip selecting the card and sending card details to SAM"), arg_lit0("t", "tlv", "decode TLV"), + arg_lit0(NULL, "break-on-nr-mac", "stop tag interaction on nr-mac"), + arg_lit0("p", "prevent-epurse-update", "fake epurse update"), + arg_lit0(NULL, "shallow", "shallow mod"), arg_strx0("d", "data", "", "DER encoded command to send to SAM"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - bool verbose = false; - if (arg_get_lit(ctx, 1)) { - verbose = true; - } - bool disconnectAfter = true; - if (arg_get_lit(ctx, 2)) { - disconnectAfter = false; - } - bool skipDetect = false; - if (arg_get_lit(ctx, 3)) { - skipDetect = true; - } - bool decodeTLV = false; - if (arg_get_lit(ctx, 4)) { - decodeTLV = true; - } + bool verbose = arg_get_lit(ctx, 1); + bool disconnectAfter = !arg_get_lit(ctx, 2); + bool skipDetect = arg_get_lit(ctx, 3); + bool decodeTLV = arg_get_lit(ctx, 4); + bool breakOnNrMac = arg_get_lit(ctx, 5); + bool preventEpurseUpdate = arg_get_lit(ctx, 6); + bool shallow_mod = arg_get_lit(ctx, 7); + + uint64_t command_flags = 0; + if (disconnectAfter) command_flags |= BITMASK(0); + if (skipDetect) command_flags |= BITMASK(1); + if (breakOnNrMac) command_flags |= BITMASK(2); + if (preventEpurseUpdate) command_flags |= BITMASK(3); + if (shallow_mod) command_flags |= BITMASK(4); uint8_t data[PM3_CMD_DATA_SIZE] = {0}; int datalen = 0; - CLIGetHexBLessWithReturn(ctx, 5, data, &datalen, 0); + CLIGetHexBLessWithReturn(ctx, 8, data, &datalen, 0); CLIParserFree(ctx); @@ -5440,7 +5441,7 @@ static int CmdHFiClassSAM(const char *Cmd) { } clearCommandBuffer(); - SendCommandMIX(CMD_HF_SAM_PICOPASS, disconnectAfter, skipDetect, datalen, data, datalen); + SendCommandMIX(CMD_HF_SAM_PICOPASS, command_flags, 0, datalen, data, datalen); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_HF_SAM_PICOPASS, &resp, 4000) == false) { PrintAndLogEx(WARNING, "SAM timeout"); @@ -5498,7 +5499,12 @@ static int CmdHFiClassSAM(const char *Cmd) { const uint8_t *mediaType = oid + 2 + oid_length; const uint8_t mediaType_data = mediaType[2]; PrintAndLogEx(SUCCESS, "SIO Media Type: " _GREEN_("%s"), getSioMediaTypeInfo(mediaType_data)); - + } else if(breakOnNrMac && d[0] == 0x05) { + PrintAndLogEx(SUCCESS, "Nr-MAC: " _GREEN_("%s"), sprint_hex_inrow(d+1, 8)); + if(verbose){ + PrintAndLogEx(INFO, "Replay Nr-MAC to dump SIO:"); + PrintAndLogEx(SUCCESS, " hf iclass dump -k \"%s\" --nr", sprint_hex_inrow(d+1, 8)); + } } else { print_hex(d, resp.length); }