mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-01-01 05:07:03 +08:00
support loading of flipper zero .picopass files. Also adapted to naive detect if PACS w variable length encoded is present
This commit is contained in:
parent
4df28b88d3
commit
9c1644cd73
3 changed files with 107 additions and 26 deletions
|
@ -1321,36 +1321,101 @@ static int CmdHFiClassESetBlk(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static bool iclass_detect_new_pacs(uint8_t *d) {
|
||||
uint8_t n = 0;
|
||||
while (n++ < (PICOPASS_BLOCK_SIZE / 2)) {
|
||||
if (d[n] &&
|
||||
d[n + 1] == 0xA6) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// block 7 decoder for PACS
|
||||
static int iclass_decode_credentials_new_pacs(uint8_t *d) {
|
||||
|
||||
uint8_t offset = 0;
|
||||
while(d[offset] == 0 && (offset < PICOPASS_BLOCK_SIZE / 2)) {
|
||||
offset++;
|
||||
}
|
||||
|
||||
uint8_t pad = d[offset];
|
||||
|
||||
PrintAndLogEx(INFO, "%u , %u", offset, pad);
|
||||
|
||||
char *binstr = (char *)calloc((PICOPASS_BLOCK_SIZE * 8) + 1, sizeof(uint8_t));
|
||||
if (binstr == NULL) {
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
uint8_t n = PICOPASS_BLOCK_SIZE - offset - 2;
|
||||
byte_2_binstr(binstr, d + offset + 2, n);
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, "PACS......... " _GREEN_("%s"), sprint_hex_inrow(d + offset + 2, n));
|
||||
PrintAndLogEx(SUCCESS, "padded bin... " _GREEN_("%s") " ( %zu )", binstr, strlen(binstr));
|
||||
|
||||
binstr[strlen(binstr) - pad] = '\0';
|
||||
PrintAndLogEx(SUCCESS, "bin.......... " _GREEN_("%s") " ( %zu )", binstr, strlen(binstr));
|
||||
|
||||
size_t hexlen = 0;
|
||||
uint8_t hex[16] = {0};
|
||||
binstr_2_bytes(hex, &hexlen, binstr);
|
||||
PrintAndLogEx(SUCCESS, "hex.......... " _GREEN_("%s"), sprint_hex_inrow(hex, hexlen));
|
||||
|
||||
uint32_t top = 0, mid = 0, bot = 0;
|
||||
if (binstring_to_u96(&top, &mid, &bot, binstr) != strlen(binstr)) {
|
||||
PrintAndLogEx(ERR, "Binary string contains none <0|1> chars");
|
||||
free(binstr);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "Wiegand decode");
|
||||
wiegand_message_t packed = initialize_message_object(top, mid, bot, 0);
|
||||
HIDTryUnpack(&packed);
|
||||
}
|
||||
|
||||
static void iclass_decode_credentials(uint8_t *data) {
|
||||
picopass_hdr_t *hdr = (picopass_hdr_t *)data;
|
||||
if (memcmp(hdr->app_issuer_area, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", PICOPASS_BLOCK_SIZE)) {
|
||||
if (memcmp(hdr->app_issuer_area, empty, PICOPASS_BLOCK_SIZE)) {
|
||||
// Not a Legacy or SR card, nothing to do here.
|
||||
return;
|
||||
}
|
||||
|
||||
BLOCK79ENCRYPTION encryption = (data[(6 * 8) + 7] & 0x03);
|
||||
bool has_values = (memcmp(data + (8 * 7), empty, 8) != 0) && (memcmp(data + (8 * 7), zeros, 8) != 0);
|
||||
BLOCK79ENCRYPTION encryption = (data[(6 * PICOPASS_BLOCK_SIZE) + 7] & 0x03);
|
||||
|
||||
uint8_t *b7 = data + (PICOPASS_BLOCK_SIZE * 7);
|
||||
|
||||
bool has_new_pacs = iclass_detect_new_pacs(b7);
|
||||
bool has_values = (memcmp(b7, empty, PICOPASS_BLOCK_SIZE) != 0) && (memcmp(b7, zeros, PICOPASS_BLOCK_SIZE) != 0);
|
||||
if (has_values && encryption == None) {
|
||||
|
||||
//todo: remove preamble/sentinel
|
||||
uint32_t top = 0, mid = 0, bot = 0;
|
||||
|
||||
// todo: remove preamble/sentinel
|
||||
PrintAndLogEx(INFO, "Block 7 decoder");
|
||||
|
||||
char hexstr[16 + 1] = {0};
|
||||
hex_to_buffer((uint8_t *)hexstr, data + (8 * 7), 8, sizeof(hexstr) - 1, 0, 0, true);
|
||||
hexstring_to_u96(&top, &mid, &bot, hexstr);
|
||||
if (has_new_pacs) {
|
||||
iclass_decode_credentials_new_pacs(b7);
|
||||
} else {
|
||||
char hexstr[16 + 1] = {0};
|
||||
hex_to_buffer((uint8_t *)hexstr, b7, PICOPASS_BLOCK_SIZE, sizeof(hexstr) - 1, 0, 0, true);
|
||||
|
||||
char binstr[64 + 1];
|
||||
hextobinstring(binstr, hexstr);
|
||||
char *pbin = binstr;
|
||||
while (strlen(pbin) && *(++pbin) == '0');
|
||||
uint32_t top = 0, mid = 0, bot = 0;
|
||||
hexstring_to_u96(&top, &mid, &bot, hexstr);
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Binary..................... " _GREEN_("%s"), pbin);
|
||||
char binstr[64 + 1];
|
||||
hextobinstring(binstr, hexstr);
|
||||
char *pbin = binstr;
|
||||
while (strlen(pbin) && *(++pbin) == '0');
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Binary..................... " _GREEN_("%s"), pbin);
|
||||
|
||||
PrintAndLogEx(INFO, "Wiegand decode");
|
||||
wiegand_message_t packed = initialize_message_object(top, mid, bot, 0);
|
||||
HIDTryUnpack(&packed);
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "Wiegand decode");
|
||||
wiegand_message_t packed = initialize_message_object(top, mid, bot, 0);
|
||||
HIDTryUnpack(&packed);
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "No unencrypted legacy credential found");
|
||||
}
|
||||
|
|
|
@ -87,7 +87,9 @@ DumpFileType_t getfiletype(const char *filename) {
|
|||
} else if (str_endswith(s, "mct")) {
|
||||
o = MCT;
|
||||
} else if (str_endswith(s, "nfc")) {
|
||||
o = NFC;
|
||||
o = FLIPPER;
|
||||
} else if (str_endswith(s, "picopass")) {
|
||||
o = FLIPPER;
|
||||
} else {
|
||||
// mfd, trc, trace is binary
|
||||
o = BIN;
|
||||
|
@ -1020,7 +1022,7 @@ int loadFileNFC_safe(const char *preferredName, void *data, size_t maxdatalen, s
|
|||
int retval = PM3_SUCCESS;
|
||||
|
||||
char *path;
|
||||
int res = searchFile(&path, RESOURCES_SUBDIR, preferredName, ".nfc", false);
|
||||
int res = searchFile(&path, RESOURCES_SUBDIR, preferredName, "", false);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return PM3_EFILE;
|
||||
}
|
||||
|
@ -1221,14 +1223,18 @@ int loadFileNFC_safe(const char *preferredName, void *data, size_t maxdatalen, s
|
|||
uint8_t block[MFBLOCK_SIZE] = {0};
|
||||
param_gethex_to_eol(p, 0, block, MFBLOCK_SIZE, &n);
|
||||
memcpy(&udata.bytes[(blockno * MFBLOCK_SIZE)], block, MFBLOCK_SIZE);
|
||||
} else if (ft == NFC_DF_PICOPASS) {
|
||||
uint8_t block[PICOPASS_BLOCK_SIZE] = {0};
|
||||
param_gethex_to_eol(p, 0, block, PICOPASS_BLOCK_SIZE, &n);
|
||||
memcpy(&udata.bytes[(blockno * PICOPASS_BLOCK_SIZE)], block, PICOPASS_BLOCK_SIZE);
|
||||
}
|
||||
counter += MFBLOCK_SIZE;
|
||||
counter += PICOPASS_BLOCK_SIZE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// add header length
|
||||
if (ft == NFC_DF_MFC) {
|
||||
if (ft == NFC_DF_MFC || ft == NFC_DF_PICOPASS) {
|
||||
*datalen = counter;
|
||||
} else if (ft == NFC_DF_MFU) {
|
||||
*datalen += MFU_DUMP_PREFIX_LENGTH;
|
||||
|
@ -1382,6 +1388,7 @@ int loadFileJSONex(const char *preferredName, void *data, size_t maxdatalen, siz
|
|||
}
|
||||
|
||||
udata_t udata = (udata_t)data;
|
||||
|
||||
size_t len = 0;
|
||||
char blocks[PATH_MAX_LENGTH] = {0};
|
||||
|
||||
|
@ -2278,7 +2285,12 @@ nfc_df_e detect_nfc_dump_format(const char *preferredName, bool verbose) {
|
|||
if (str_startswith(line, "device type: iso14443-4a")) {
|
||||
retval = NFC_DF_14_4A;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (str_startswith(line, "filetype: flipper picopass device")) {
|
||||
retval = NFC_DF_PICOPASS;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
|
@ -2302,6 +2314,9 @@ nfc_df_e detect_nfc_dump_format(const char *preferredName, bool verbose) {
|
|||
case NFC_DF_14_4A:
|
||||
PrintAndLogEx(INFO, "detected ISO14443-4A based dump format. No data available");
|
||||
break;
|
||||
case NFC_DF_PICOPASS:
|
||||
PrintAndLogEx(INFO, "detected PICOPASS based dump format");
|
||||
break;
|
||||
case NFC_DF_UNKNOWN:
|
||||
PrintAndLogEx(WARNING, "failed to detected dump format");
|
||||
break;
|
||||
|
@ -2757,9 +2772,9 @@ int pm3_load_dump(const char *fn, void **pdump, size_t *dumplen, size_t maxdumpl
|
|||
res = loadFileMCT_safe(fn, pdump, dumplen);
|
||||
break;
|
||||
}
|
||||
case NFC: {
|
||||
case FLIPPER: {
|
||||
nfc_df_e foo = detect_nfc_dump_format(fn, true);
|
||||
if (foo == NFC_DF_MFC || foo == NFC_DF_MFU) {
|
||||
if (foo == NFC_DF_MFC || foo == NFC_DF_MFU || foo == NFC_DF_PICOPASS) {
|
||||
|
||||
if (foo == NFC_DF_MFC) {
|
||||
*pdump = calloc(maxdumplen, sizeof(uint8_t));
|
||||
|
|
|
@ -79,7 +79,7 @@ typedef enum {
|
|||
JSON,
|
||||
DICTIONARY,
|
||||
MCT,
|
||||
NFC,
|
||||
FLIPPER,
|
||||
} DumpFileType_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -96,7 +96,8 @@ typedef enum {
|
|||
NFC_DF_MFDES,
|
||||
NFC_DF_14_3A,
|
||||
NFC_DF_14_3B,
|
||||
NFC_DF_14_4A
|
||||
NFC_DF_14_4A,
|
||||
NFC_DF_PICOPASS,
|
||||
} nfc_df_e;
|
||||
|
||||
int fileExists(const char *filename);
|
||||
|
|
Loading…
Reference in a new issue