added hf 14b view and modified dump command to be prepared to handle the different tags

This commit is contained in:
iceman1001 2022-07-03 20:06:11 +02:00
commit 7b732e152e
2 changed files with 291 additions and 151 deletions

View file

@ -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,17 +1366,40 @@ 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));
uint32_t uid32 = MemLeToUint4byte(ct_card.uid);
PrintAndLogEx(SUCCESS, "UID: " _GREEN_("%s") " ( " _YELLOW_("%010u") " )", sprint_hex(ct_card.uid, 4), uid32);
// Have to figure out how large one of these are..
PrintAndLogEx(FAILED, "Dumping CT tags is not implemented yet.");
// print_ct_blocks(data, cardsize);
return switch_off_field_14b();
} }
if (select_cardtype == ISO14B_CT) {
// 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);
return switch_off_field_14b();
}
if (select_cardtype == ISO14B_SR) {
iso14b_card_select_t card;
memcpy(&card, (iso14b_card_select_t *)&select, sizeof(iso14b_card_select_t));
// detect cardsize // detect cardsize
// 1 = 4096 // 1 = 4096
// 2 = 512 // 2 = 512
@ -1329,7 +1438,7 @@ static int CmdHF14BDump(const char *Cmd) {
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));
PacketResponseNG resp; PacketResponseNG resp;
// select // select SR tag
int status; int status;
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) { if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) {
status = resp.oldarg[0]; status = resp.oldarg[0];
@ -1402,34 +1511,7 @@ static int CmdHF14BDump(const char *Cmd) {
return switch_off_field_14b(); return switch_off_field_14b();
} }
PrintAndLogEx(DEBUG, "systemblock : %s", sprint_hex(data + (blocks * 4), 4)); print_sr_blocks(data, cardsize);
PrintAndLogEx(DEBUG, " otp lock : %02x %02x", data[(blocks * 4)], data[(blocks * 4) + 1]);
PrintAndLogEx(INFO, " block# | data |lck| ascii");
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 // save to file
if (fnlen < 1) { if (fnlen < 1) {
@ -1440,6 +1522,8 @@ static int CmdHF14BDump(const char *Cmd) {
size_t datalen = (blocks + 1) * 4; size_t datalen = (blocks + 1) * 4;
pm3_save_dump(filename, data, datalen, jsf14b, 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}
}; };

View file

@ -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;