mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 13:00:42 -07:00
sam_picopass: add nr-mac extraction and epurse update prevention modes
This commit is contained in:
parent
53b67d1969
commit
7b34f462cd
2 changed files with 90 additions and 53 deletions
|
@ -44,7 +44,7 @@
|
||||||
* @param response_len Pointer to the variable where the length of the retreived data will be stored.
|
* @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.
|
* @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;
|
int res = PM3_SUCCESS;
|
||||||
if (g_dbglevel >= DBG_DEBUG)
|
if (g_dbglevel >= DBG_DEBUG)
|
||||||
DbpString("start sam_send_request_iso14a");
|
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);
|
nfc_tx_len = sam_copy_payload_sam2nfc(nfc_tx_buf, sam_rx_buf);
|
||||||
|
|
||||||
// should consider blocking update(2) commands and simulating answer
|
bool is_cmd_check = (nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_CHECK;
|
||||||
// example command: 87 02 C9 FD FF FF FF FF FF FF F4 BF 98 E2
|
if(is_cmd_check && break_on_nr_mac){
|
||||||
|
memcpy(response, nfc_tx_buf, nfc_tx_len);
|
||||||
bool is_cmd_update = (nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_UPDATE;
|
*response_len = nfc_tx_len;
|
||||||
|
if (g_dbglevel >= DBG_INFO) {
|
||||||
if (g_dbglevel >= DBG_INFO) {
|
DbpString("NR-MAC: ");
|
||||||
DbpString("ISO15 TAG REQUEST: ");
|
Dbhexdump((*response_len)-1, response+1, false);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
res = PM3_SUCCESS;
|
||||||
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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_dbglevel >= DBG_INFO) {
|
bool is_cmd_update = (nfc_tx_buf[0] & 0x0F) == ICLASS_CMD_UPDATE;
|
||||||
DbpString("ISO15 TAG RESPONSE: ");
|
if(is_cmd_update && prevent_epurse_update && nfc_tx_buf[0] == 0x87 && nfc_tx_buf[1] == 0x02){
|
||||||
Dbhexdump(nfc_rx_len, nfc_rx_buf, false);
|
// 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.
|
* @return Status code indicating success or failure of the operation.
|
||||||
*/
|
*/
|
||||||
int sam_picopass_get_pacs(PacketCommandNG *c) {
|
int sam_picopass_get_pacs(PacketCommandNG *c) {
|
||||||
bool disconnectAfter = c->oldarg[0] & 0x01;
|
const bool disconnectAfter = !!(c->oldarg[0] & BITMASK(0));
|
||||||
bool skipDetect = c->oldarg[1] & 0x01;
|
const bool skipDetect = !!(c->oldarg[0] & BITMASK(1));
|
||||||
bool shallow_mod = false;
|
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;
|
uint8_t *cmd = c->data.asBytes;
|
||||||
uint16_t cmd_len = (uint16_t) c->oldarg[2];
|
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
|
// step 3: SamCommand RequestPACS, relay NFC communication
|
||||||
uint8_t sam_response[ISO7816_MAX_FRAME] = { 0x00 };
|
uint8_t sam_response[ISO7816_MAX_FRAME] = { 0x00 };
|
||||||
uint8_t sam_response_len = 0;
|
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) {
|
if (res != PM3_SUCCESS) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5407,31 +5407,32 @@ static int CmdHFiClassSAM(const char *Cmd) {
|
||||||
arg_lit0("k", "keep", "keep the field active after command executed"),
|
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("n", "nodetect", "skip selecting the card and sending card details to SAM"),
|
||||||
arg_lit0("t", "tlv", "decode TLV"),
|
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", "<hex>", "DER encoded command to send to SAM"),
|
arg_strx0("d", "data", "<hex>", "DER encoded command to send to SAM"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
bool verbose = false;
|
bool verbose = arg_get_lit(ctx, 1);
|
||||||
if (arg_get_lit(ctx, 1)) {
|
bool disconnectAfter = !arg_get_lit(ctx, 2);
|
||||||
verbose = true;
|
bool skipDetect = arg_get_lit(ctx, 3);
|
||||||
}
|
bool decodeTLV = arg_get_lit(ctx, 4);
|
||||||
bool disconnectAfter = true;
|
bool breakOnNrMac = arg_get_lit(ctx, 5);
|
||||||
if (arg_get_lit(ctx, 2)) {
|
bool preventEpurseUpdate = arg_get_lit(ctx, 6);
|
||||||
disconnectAfter = false;
|
bool shallow_mod = arg_get_lit(ctx, 7);
|
||||||
}
|
|
||||||
bool skipDetect = false;
|
uint64_t command_flags = 0;
|
||||||
if (arg_get_lit(ctx, 3)) {
|
if (disconnectAfter) command_flags |= BITMASK(0);
|
||||||
skipDetect = true;
|
if (skipDetect) command_flags |= BITMASK(1);
|
||||||
}
|
if (breakOnNrMac) command_flags |= BITMASK(2);
|
||||||
bool decodeTLV = false;
|
if (preventEpurseUpdate) command_flags |= BITMASK(3);
|
||||||
if (arg_get_lit(ctx, 4)) {
|
if (shallow_mod) command_flags |= BITMASK(4);
|
||||||
decodeTLV = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t data[PM3_CMD_DATA_SIZE] = {0};
|
uint8_t data[PM3_CMD_DATA_SIZE] = {0};
|
||||||
int datalen = 0;
|
int datalen = 0;
|
||||||
CLIGetHexBLessWithReturn(ctx, 5, data, &datalen, 0);
|
CLIGetHexBLessWithReturn(ctx, 8, data, &datalen, 0);
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
@ -5440,7 +5441,7 @@ static int CmdHFiClassSAM(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandMIX(CMD_HF_SAM_PICOPASS, disconnectAfter, skipDetect, datalen, data, datalen);
|
SendCommandMIX(CMD_HF_SAM_PICOPASS, command_flags, 0, datalen, data, datalen);
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
if (WaitForResponseTimeout(CMD_HF_SAM_PICOPASS, &resp, 4000) == false) {
|
if (WaitForResponseTimeout(CMD_HF_SAM_PICOPASS, &resp, 4000) == false) {
|
||||||
PrintAndLogEx(WARNING, "SAM timeout");
|
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 = oid + 2 + oid_length;
|
||||||
const uint8_t mediaType_data = mediaType[2];
|
const uint8_t mediaType_data = mediaType[2];
|
||||||
PrintAndLogEx(SUCCESS, "SIO Media Type: " _GREEN_("%s"), getSioMediaTypeInfo(mediaType_data));
|
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 {
|
} else {
|
||||||
print_hex(d, resp.length);
|
print_hex(d, resp.length);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue