mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
added hf 14b view
and modified dump command to be prepared to handle the different tags
This commit is contained in:
parent
45ea60c92b
commit
7b732e152e
2 changed files with 291 additions and 151 deletions
|
@ -42,6 +42,9 @@
|
||||||
// client side time out, waiting for device to ask tag a APDU to answer
|
// client side time out, waiting for device to ask tag a APDU to answer
|
||||||
#define APDU_TIMEOUT 2000
|
#define APDU_TIMEOUT 2000
|
||||||
|
|
||||||
|
// for static arrays
|
||||||
|
#define ST25TB_SR_BLOCK_SIZE 4
|
||||||
|
|
||||||
// iso14b apdu input frame length
|
// iso14b apdu input frame length
|
||||||
static uint16_t apdu_frame_length = 0;
|
static uint16_t apdu_frame_length = 0;
|
||||||
//static uint16_t ats_fsc[] = {16, 24, 32, 40, 48, 64, 96, 128, 256};
|
//static uint16_t ats_fsc[] = {16, 24, 32, 40, 48, 64, 96, 128, 256};
|
||||||
|
@ -415,10 +418,14 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_14b_UID(iso14b_card_select_t *card) {
|
static bool get_14b_UID(uint8_t *d, iso14b_type_t *found_type) {
|
||||||
|
|
||||||
if (card == NULL)
|
// sanity checks
|
||||||
|
if (d == NULL || found_type == NULL) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*found_type = ISO14B_NONE;
|
||||||
|
|
||||||
iso14b_raw_cmd_t packet = {
|
iso14b_raw_cmd_t packet = {
|
||||||
.flags = (ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT),
|
.flags = (ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT),
|
||||||
|
@ -429,11 +436,11 @@ static bool get_14b_UID(iso14b_card_select_t *card) {
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)&packet, sizeof(iso14b_raw_cmd_t));
|
SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)&packet, sizeof(iso14b_raw_cmd_t));
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
||||||
|
|
||||||
if (resp.oldarg[0] == 0) {
|
if (resp.oldarg[0] == 0) {
|
||||||
memcpy(card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t));
|
memcpy(d, resp.data.asBytes, sizeof(iso14b_card_select_t));
|
||||||
|
*found_type = ISO14B_SELECT_SR;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -445,7 +452,21 @@ static bool get_14b_UID(iso14b_card_select_t *card) {
|
||||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
||||||
|
|
||||||
if (resp.oldarg[0] == 0) {
|
if (resp.oldarg[0] == 0) {
|
||||||
memcpy(card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t));
|
memcpy(d, resp.data.asBytes, sizeof(iso14b_card_select_t));
|
||||||
|
*found_type = ISO14B_STANDARD;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test CT
|
||||||
|
packet.flags = (ISO14B_CONNECT | ISO14B_SELECT_CTS | ISO14B_DISCONNECT);
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)&packet, sizeof(iso14b_raw_cmd_t));
|
||||||
|
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
|
||||||
|
|
||||||
|
if (resp.oldarg[0] == 0) {
|
||||||
|
memcpy(d, resp.data.asBytes, sizeof(iso14b_cts_card_select_t));
|
||||||
|
*found_type = ISO14B_CT;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -726,7 +747,7 @@ static void print_ct_general_info(void *vcard) {
|
||||||
iso14b_cts_card_select_t card;
|
iso14b_cts_card_select_t card;
|
||||||
memcpy(&card, (iso14b_cts_card_select_t *)vcard, sizeof(iso14b_cts_card_select_t));
|
memcpy(&card, (iso14b_cts_card_select_t *)vcard, sizeof(iso14b_cts_card_select_t));
|
||||||
|
|
||||||
uint32_t uid32 = (card.uid[0] | card.uid[1] << 8 | card.uid[2] << 16 | card.uid[3] << 24);
|
uint32_t uid32 = MemLeToUint4byte(card.uid);
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(SUCCESS, "ASK C-Ticket");
|
PrintAndLogEx(SUCCESS, "ASK C-Ticket");
|
||||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s") " ( " _YELLOW_("%010u") " )", sprint_hex(card.uid, sizeof(card.uid)), uid32);
|
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s") " ( " _YELLOW_("%010u") " )", sprint_hex(card.uid, sizeof(card.uid)), uid32);
|
||||||
|
@ -735,6 +756,71 @@ static void print_ct_general_info(void *vcard) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void print_hdr(void) {
|
||||||
|
PrintAndLogEx(INFO, " block# | data |lck| ascii");
|
||||||
|
PrintAndLogEx(INFO, "---------+--------------+---+----------");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_footer(void) {
|
||||||
|
PrintAndLogEx(INFO, "---------+--------------+---+----------");
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
static void print_ct_blocks(uint8_t *data, size_t len) {
|
||||||
|
|
||||||
|
size_t blocks = len / ST25TB_SR_BLOCK_SIZE;
|
||||||
|
|
||||||
|
print_hdr();
|
||||||
|
|
||||||
|
for (int i = 0; i <= blocks; i++) {
|
||||||
|
PrintAndLogEx(INFO,
|
||||||
|
"%3d/0x%02X | %s | %s | %s",
|
||||||
|
i,
|
||||||
|
i,
|
||||||
|
sprint_hex(data + (i * 4), 4),
|
||||||
|
" ",
|
||||||
|
sprint_ascii(data + (i * 4), 4)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
print_footer();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void print_sr_blocks(uint8_t *data, size_t len) {
|
||||||
|
|
||||||
|
size_t blocks = len / ST25TB_SR_BLOCK_SIZE;
|
||||||
|
uint8_t chipid = get_st_chipid(data);
|
||||||
|
PrintAndLogEx(SUCCESS, _GREEN_("%s") " tag", get_st_chip_model(chipid));
|
||||||
|
|
||||||
|
PrintAndLogEx(DEBUG, "systemblock : %s", sprint_hex(data + (blocks * 4), 4));
|
||||||
|
PrintAndLogEx(DEBUG, " otp lock : %02x %02x", data[(blocks * 4)], data[(blocks * 4) + 1]);
|
||||||
|
|
||||||
|
print_hdr();
|
||||||
|
|
||||||
|
for (int i = 0; i <= blocks; i++) {
|
||||||
|
PrintAndLogEx(INFO,
|
||||||
|
"%3d/0x%02X | %s | %s | %s",
|
||||||
|
i,
|
||||||
|
i,
|
||||||
|
sprint_hex(data + (i * 4), 4),
|
||||||
|
get_st_lock_info(chipid, data + (blocks * 4), i),
|
||||||
|
sprint_ascii(data + (i * 4), 4)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO,
|
||||||
|
"%3d/0x%02X | %s | %s | %s",
|
||||||
|
0xFF,
|
||||||
|
0xFF,
|
||||||
|
sprint_hex(data + (0xFF * 4), 4),
|
||||||
|
get_st_lock_info(chipid, data + (blocks * 4), 0xFF),
|
||||||
|
sprint_ascii(data + (0xFF * 4), 4)
|
||||||
|
);
|
||||||
|
|
||||||
|
print_footer();
|
||||||
|
}
|
||||||
|
|
||||||
// iceman, calypso?
|
// iceman, calypso?
|
||||||
// 05 00 00 = find one tag in field
|
// 05 00 00 = find one tag in field
|
||||||
// 1d xx xx xx xx 00 08 01 00 = attrib xx=UID (resp 10 [f9 e0])
|
// 1d xx xx xx xx 00 08 01 00 = attrib xx=UID (resp 10 [f9 e0])
|
||||||
|
@ -1280,166 +1366,164 @@ static int CmdHF14BDump(const char *Cmd) {
|
||||||
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
iso14b_card_select_t card;
|
|
||||||
if (get_14b_UID(&card) == false) {
|
uint8_t select[sizeof(iso14b_card_select_t)] = {0};
|
||||||
|
iso14b_type_t select_cardtype = ISO14B_NONE;
|
||||||
|
if (get_14b_UID(select, &select_cardtype) == false) {
|
||||||
PrintAndLogEx(WARNING, "no tag found");
|
PrintAndLogEx(WARNING, "no tag found");
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (card.uidlen != 8) {
|
if (select_cardtype == ISO14B_CT) {
|
||||||
PrintAndLogEx(FAILED, "current dump command only work with SRI4K / SRI512 tags");
|
iso14b_cts_card_select_t ct_card;
|
||||||
return PM3_SUCCESS;
|
memcpy(&ct_card, (iso14b_cts_card_select_t *)&select, sizeof(iso14b_cts_card_select_t));
|
||||||
}
|
|
||||||
|
|
||||||
// detect cardsize
|
uint32_t uid32 = MemLeToUint4byte(ct_card.uid);
|
||||||
// 1 = 4096
|
PrintAndLogEx(SUCCESS, "UID: " _GREEN_("%s") " ( " _YELLOW_("%010u") " )", sprint_hex(ct_card.uid, 4), uid32);
|
||||||
// 2 = 512
|
|
||||||
uint8_t cardtype = get_st_cardsize(card.uid);
|
|
||||||
uint8_t blocks = 0;
|
|
||||||
uint16_t cardsize = 0;
|
|
||||||
|
|
||||||
switch (cardtype) {
|
// Have to figure out how large one of these are..
|
||||||
case 2:
|
PrintAndLogEx(FAILED, "Dumping CT tags is not implemented yet.");
|
||||||
cardsize = (512 / 8) + 4;
|
|
||||||
blocks = 0x0F;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
default:
|
|
||||||
cardsize = (4096 / 8) + 4;
|
|
||||||
blocks = 0x7F;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t chipid = get_st_chipid(card.uid);
|
// print_ct_blocks(data, cardsize);
|
||||||
PrintAndLogEx(SUCCESS, "found a " _GREEN_("%s") " tag", get_st_chip_model(chipid));
|
|
||||||
|
|
||||||
// detect blocksize from card :)
|
|
||||||
PrintAndLogEx(INFO, "reading tag memory from UID " _GREEN_("%s"), sprint_hex_inrow(SwapEndian64(card.uid, card.uidlen, 8), card.uidlen));
|
|
||||||
|
|
||||||
iso14b_raw_cmd_t *packet = (iso14b_raw_cmd_t *)calloc(1, sizeof(iso14b_raw_cmd_t) + 2);
|
|
||||||
if (packet == NULL) {
|
|
||||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
|
||||||
return PM3_EMALLOC;
|
|
||||||
}
|
|
||||||
packet->flags = (ISO14B_CONNECT | ISO14B_SELECT_SR);
|
|
||||||
packet->timeout = 0;
|
|
||||||
packet->rawlen = 0;
|
|
||||||
|
|
||||||
clearCommandBuffer();
|
|
||||||
SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)packet, sizeof(iso14b_raw_cmd_t));
|
|
||||||
PacketResponseNG resp;
|
|
||||||
|
|
||||||
// select
|
|
||||||
int status;
|
|
||||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) {
|
|
||||||
status = resp.oldarg[0];
|
|
||||||
if (status < 0) {
|
|
||||||
PrintAndLogEx(FAILED, "failed to select arg0[%" PRId64 "]", resp.oldarg[0]);
|
|
||||||
free(packet);
|
|
||||||
return switch_off_field_14b();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "." NOLF);
|
|
||||||
|
|
||||||
uint8_t data[cardsize];
|
|
||||||
memset(data, 0, sizeof(data));
|
|
||||||
uint16_t blocknum = 0;
|
|
||||||
|
|
||||||
for (int retry = 0; retry < 5; retry++) {
|
|
||||||
|
|
||||||
// set up the read command
|
|
||||||
packet->flags = (ISO14B_APPEND_CRC | ISO14B_RAW);
|
|
||||||
packet->rawlen = 2;
|
|
||||||
packet->raw[0] = ISO14443B_READ_BLK;
|
|
||||||
packet->raw[1] = blocknum & 0xFF;
|
|
||||||
|
|
||||||
clearCommandBuffer();
|
|
||||||
SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)packet, sizeof(iso14b_raw_cmd_t) + 2);
|
|
||||||
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) {
|
|
||||||
|
|
||||||
status = resp.oldarg[0];
|
|
||||||
if (status < 0) {
|
|
||||||
PrintAndLogEx(FAILED, "retrying one more time");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t len = (resp.oldarg[1] & 0xFFFF);
|
|
||||||
uint8_t *recv = resp.data.asBytes;
|
|
||||||
|
|
||||||
if (check_crc(CRC_14443_B, recv, len) == false) {
|
|
||||||
PrintAndLogEx(FAILED, "crc fail, retrying one more time");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// last read
|
|
||||||
if (blocknum == 0xFF) {
|
|
||||||
// we reserved space for this block after 0x0F and 0x7F, ie 0x10, 0x80
|
|
||||||
memcpy(data + (blocks * 4), recv, 4);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
memcpy(data + (blocknum * 4), recv, 4);
|
|
||||||
|
|
||||||
|
|
||||||
retry = 0;
|
|
||||||
blocknum++;
|
|
||||||
if (blocknum > blocks) {
|
|
||||||
// read config block
|
|
||||||
blocknum = 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "." NOLF);
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(packet);
|
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
|
|
||||||
if (blocknum != 0xFF) {
|
|
||||||
PrintAndLogEx(FAILED, "dump failed");
|
|
||||||
return switch_off_field_14b();
|
return switch_off_field_14b();
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(DEBUG, "systemblock : %s", sprint_hex(data + (blocks * 4), 4));
|
if (select_cardtype == ISO14B_CT) {
|
||||||
PrintAndLogEx(DEBUG, " otp lock : %02x %02x", data[(blocks * 4)], data[(blocks * 4) + 1]);
|
// Have to figure out how large one of these are..
|
||||||
|
PrintAndLogEx(FAILED, "Dumping Standard ISO14443-B tags is not implemented yet.");
|
||||||
|
// print_std_blocks(data, cardsize);
|
||||||
PrintAndLogEx(INFO, " block# | data |lck| ascii");
|
return switch_off_field_14b();
|
||||||
PrintAndLogEx(INFO, "---------+--------------+---+----------");
|
|
||||||
|
|
||||||
for (int i = 0; i <= blocks; i++) {
|
|
||||||
PrintAndLogEx(INFO,
|
|
||||||
"%3d/0x%02X | %s | %s | %s",
|
|
||||||
i,
|
|
||||||
i,
|
|
||||||
sprint_hex(data + (i * 4), 4),
|
|
||||||
get_st_lock_info(chipid, data + (blocks * 4), i),
|
|
||||||
sprint_ascii(data + (i * 4), 4)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(INFO,
|
|
||||||
"%3d/0x%02X | %s | %s | %s",
|
|
||||||
0xFF,
|
|
||||||
0xFF,
|
|
||||||
sprint_hex(data + (0xFF * 4), 4),
|
|
||||||
get_st_lock_info(chipid, data + (blocks * 4), 0xFF),
|
|
||||||
sprint_ascii(data + (0xFF * 4), 4)
|
|
||||||
);
|
|
||||||
PrintAndLogEx(INFO, "---------+--------------+---+----------");
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
|
||||||
|
|
||||||
// save to file
|
if (select_cardtype == ISO14B_SR) {
|
||||||
if (fnlen < 1) {
|
iso14b_card_select_t card;
|
||||||
PrintAndLogEx(INFO, "using UID as filename");
|
memcpy(&card, (iso14b_card_select_t *)&select, sizeof(iso14b_card_select_t));
|
||||||
char *fptr = filename + snprintf(filename, sizeof(filename), "hf-14b-");
|
|
||||||
FillFileNameByUID(fptr, SwapEndian64(card.uid, card.uidlen, 8), "-dump", card.uidlen);
|
// detect cardsize
|
||||||
|
// 1 = 4096
|
||||||
|
// 2 = 512
|
||||||
|
uint8_t cardtype = get_st_cardsize(card.uid);
|
||||||
|
uint8_t blocks = 0;
|
||||||
|
uint16_t cardsize = 0;
|
||||||
|
|
||||||
|
switch (cardtype) {
|
||||||
|
case 2:
|
||||||
|
cardsize = (512 / 8) + 4;
|
||||||
|
blocks = 0x0F;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
default:
|
||||||
|
cardsize = (4096 / 8) + 4;
|
||||||
|
blocks = 0x7F;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t chipid = get_st_chipid(card.uid);
|
||||||
|
PrintAndLogEx(SUCCESS, "found a " _GREEN_("%s") " tag", get_st_chip_model(chipid));
|
||||||
|
|
||||||
|
// detect blocksize from card :)
|
||||||
|
PrintAndLogEx(INFO, "reading tag memory from UID " _GREEN_("%s"), sprint_hex_inrow(SwapEndian64(card.uid, card.uidlen, 8), card.uidlen));
|
||||||
|
|
||||||
|
iso14b_raw_cmd_t *packet = (iso14b_raw_cmd_t *)calloc(1, sizeof(iso14b_raw_cmd_t) + 2);
|
||||||
|
if (packet == NULL) {
|
||||||
|
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||||
|
return PM3_EMALLOC;
|
||||||
|
}
|
||||||
|
packet->flags = (ISO14B_CONNECT | ISO14B_SELECT_SR);
|
||||||
|
packet->timeout = 0;
|
||||||
|
packet->rawlen = 0;
|
||||||
|
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)packet, sizeof(iso14b_raw_cmd_t));
|
||||||
|
PacketResponseNG resp;
|
||||||
|
|
||||||
|
// select SR tag
|
||||||
|
int status;
|
||||||
|
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) {
|
||||||
|
status = resp.oldarg[0];
|
||||||
|
if (status < 0) {
|
||||||
|
PrintAndLogEx(FAILED, "failed to select arg0[%" PRId64 "]", resp.oldarg[0]);
|
||||||
|
free(packet);
|
||||||
|
return switch_off_field_14b();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "." NOLF);
|
||||||
|
|
||||||
|
uint8_t data[cardsize];
|
||||||
|
memset(data, 0, sizeof(data));
|
||||||
|
uint16_t blocknum = 0;
|
||||||
|
|
||||||
|
for (int retry = 0; retry < 5; retry++) {
|
||||||
|
|
||||||
|
// set up the read command
|
||||||
|
packet->flags = (ISO14B_APPEND_CRC | ISO14B_RAW);
|
||||||
|
packet->rawlen = 2;
|
||||||
|
packet->raw[0] = ISO14443B_READ_BLK;
|
||||||
|
packet->raw[1] = blocknum & 0xFF;
|
||||||
|
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)packet, sizeof(iso14b_raw_cmd_t) + 2);
|
||||||
|
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) {
|
||||||
|
|
||||||
|
status = resp.oldarg[0];
|
||||||
|
if (status < 0) {
|
||||||
|
PrintAndLogEx(FAILED, "retrying one more time");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t len = (resp.oldarg[1] & 0xFFFF);
|
||||||
|
uint8_t *recv = resp.data.asBytes;
|
||||||
|
|
||||||
|
if (check_crc(CRC_14443_B, recv, len) == false) {
|
||||||
|
PrintAndLogEx(FAILED, "crc fail, retrying one more time");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// last read
|
||||||
|
if (blocknum == 0xFF) {
|
||||||
|
// we reserved space for this block after 0x0F and 0x7F, ie 0x10, 0x80
|
||||||
|
memcpy(data + (blocks * 4), recv, 4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memcpy(data + (blocknum * 4), recv, 4);
|
||||||
|
|
||||||
|
|
||||||
|
retry = 0;
|
||||||
|
blocknum++;
|
||||||
|
if (blocknum > blocks) {
|
||||||
|
// read config block
|
||||||
|
blocknum = 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(packet);
|
||||||
|
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
|
if (blocknum != 0xFF) {
|
||||||
|
PrintAndLogEx(FAILED, "dump failed");
|
||||||
|
return switch_off_field_14b();
|
||||||
|
}
|
||||||
|
|
||||||
|
print_sr_blocks(data, cardsize);
|
||||||
|
|
||||||
|
// save to file
|
||||||
|
if (fnlen < 1) {
|
||||||
|
PrintAndLogEx(INFO, "using UID as filename");
|
||||||
|
char *fptr = filename + snprintf(filename, sizeof(filename), "hf-14b-");
|
||||||
|
FillFileNameByUID(fptr, SwapEndian64(card.uid, card.uidlen, 8), "-dump", card.uidlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t datalen = (blocks + 1) * 4;
|
||||||
|
pm3_save_dump(filename, data, datalen, jsf14b, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t datalen = (blocks + 1) * 4;
|
|
||||||
pm3_save_dump(filename, data, datalen, jsf14b, 4);
|
|
||||||
return switch_off_field_14b();
|
return switch_off_field_14b();
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -2018,6 +2102,54 @@ out:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int CmdHF14BView(const char *Cmd) {
|
||||||
|
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "hf 14b view",
|
||||||
|
"Print a ISO14443-B dump file (bin/eml/json)",
|
||||||
|
"hf 14b view -f hf-14b-01020304-dump.bin"
|
||||||
|
);
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_str1("f", "file", "<fn>", "filename of dump"),
|
||||||
|
arg_lit0("v", "verbose", "verbose output"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
int fnlen = 0;
|
||||||
|
char filename[FILE_PATH_SIZE];
|
||||||
|
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||||
|
bool verbose = arg_get_lit(ctx, 2);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
// read dump file
|
||||||
|
uint8_t *dump = NULL;
|
||||||
|
size_t bytes_read = 0;
|
||||||
|
int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, (ST25TB_SR_BLOCK_SIZE * 0xFF));
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t block_cnt = bytes_read / ST25TB_SR_BLOCK_SIZE;
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
PrintAndLogEx(INFO, "File: " _YELLOW_("%s"), filename);
|
||||||
|
PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, block_cnt, block_cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// figure out a way to identify the different dump files.
|
||||||
|
// STD/SR/CT is difference
|
||||||
|
|
||||||
|
print_sr_blocks(dump, bytes_read);
|
||||||
|
//print_std_blocks(dump, bytes_read);
|
||||||
|
//print_ct_blocks(dump, bytes_read);
|
||||||
|
|
||||||
|
free(dump);
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"apdu", CmdHF14BAPDU, IfPm3Iso14443b, "Send ISO 14443-4 APDU to tag"},
|
{"apdu", CmdHF14BAPDU, IfPm3Iso14443b, "Send ISO 14443-4 APDU to tag"},
|
||||||
|
@ -2032,6 +2164,7 @@ static command_t CommandTable[] = {
|
||||||
{"sniff", CmdHF14BSniff, IfPm3Iso14443b, "Eavesdrop ISO-14443-B"},
|
{"sniff", CmdHF14BSniff, IfPm3Iso14443b, "Eavesdrop ISO-14443-B"},
|
||||||
{"rdbl", CmdHF14BSriRdBl, IfPm3Iso14443b, "Read SRI512/SRIX4x block"},
|
{"rdbl", CmdHF14BSriRdBl, IfPm3Iso14443b, "Read SRI512/SRIX4x block"},
|
||||||
{"sriwrite", CmdHF14BWriteSri, IfPm3Iso14443b, "Write data to a SRI512 or SRIX4K tag"},
|
{"sriwrite", CmdHF14BWriteSri, IfPm3Iso14443b, "Write data to a SRI512 or SRIX4K tag"},
|
||||||
|
{"view", CmdHF14BView, AlwaysAvailable, "Display content from tag dump file"},
|
||||||
// {"valid", srix4kValid, AlwaysAvailable, "srix4k checksum test"},
|
// {"valid", srix4kValid, AlwaysAvailable, "srix4k checksum test"},
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,6 +50,13 @@ typedef enum ISO14B_COMMAND {
|
||||||
ISO14B_SELECT_XRX = (1 << 12),
|
ISO14B_SELECT_XRX = (1 << 12),
|
||||||
} iso14b_command_t;
|
} iso14b_command_t;
|
||||||
|
|
||||||
|
typedef enum ISO14B_TYPE {
|
||||||
|
ISO14B_NONE = 0,
|
||||||
|
ISO14B_STANDARD = 1,
|
||||||
|
ISO14B_SR = 2,
|
||||||
|
ISO14B_CT = 4,
|
||||||
|
} iso14b_type_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t flags; // the ISO14B_COMMAND enum
|
uint16_t flags; // the ISO14B_COMMAND enum
|
||||||
uint32_t timeout;
|
uint32_t timeout;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue