mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-03-17 10:33:09 +08:00
Merge branch 'master' into feature/iclass_dump_view_suppress_repeated_blocks
This commit is contained in:
commit
925589a214
5 changed files with 101 additions and 49 deletions
|
@ -3,7 +3,9 @@ All notable changes to this project will be documented in this file.
|
|||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Changed `hf iclass view` to suppress consecutive blocks with repeated contents (@nvx)
|
||||
- Changed `hf iclass view` and related to suppress consecutive blocks with repeated contents with a `-z` flag, or `prefs set output --dense` (@nvx)
|
||||
- Changed `hf iclass list` to display matched keys on the CHECK command rather than the card response, and made it check for elite keys too (@nvx)
|
||||
- Fixed `hf iclass info` and `hf iclass view` key access info looking at the wrong card config bit (@nvx)
|
||||
- Added `hf gallagher decode` command and fix Gallagher diversification for card master key (@nvx)
|
||||
- Added mmbit-002 (kibi-002, kb5004xk1) russian tag to `hf texkom read` command (@merlokk)
|
||||
- Added `hf sniff --smode` skip/group adc data to consume less memory. Now it can sniff very long signals (@merlokk)
|
||||
|
|
|
@ -10,3 +10,4 @@
|
|||
25293C2F
|
||||
#
|
||||
# Paxton HT2
|
||||
BDF5E846
|
||||
|
|
|
@ -88,7 +88,7 @@ static int cmp_uint32(const void *a, const void *b) {
|
|||
|
||||
bool check_known_default(uint8_t *csn, uint8_t *epurse, uint8_t *rmac, uint8_t *tmac, uint8_t *key) {
|
||||
|
||||
iclass_prekey_t *prekey = calloc(ICLASS_KEYS_MAX, sizeof(iclass_prekey_t));
|
||||
iclass_prekey_t *prekey = calloc(ICLASS_KEYS_MAX * 2, sizeof(iclass_prekey_t));
|
||||
if (prekey == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
@ -98,17 +98,20 @@ bool check_known_default(uint8_t *csn, uint8_t *epurse, uint8_t *rmac, uint8_t *
|
|||
memcpy(ccnr + 8, rmac, 4);
|
||||
|
||||
GenerateMacKeyFrom(csn, ccnr, false, false, (uint8_t *)iClass_Key_Table, ICLASS_KEYS_MAX, prekey);
|
||||
qsort(prekey, ICLASS_KEYS_MAX, sizeof(iclass_prekey_t), cmp_uint32);
|
||||
GenerateMacKeyFrom(csn, ccnr, false, true, (uint8_t *)iClass_Key_Table, ICLASS_KEYS_MAX, prekey + ICLASS_KEYS_MAX);
|
||||
qsort(prekey, ICLASS_KEYS_MAX * 2, sizeof(iclass_prekey_t), cmp_uint32);
|
||||
|
||||
iclass_prekey_t lookup;
|
||||
memcpy(lookup.mac, tmac, 4);
|
||||
|
||||
// binsearch
|
||||
iclass_prekey_t *item = (iclass_prekey_t *) bsearch(&lookup, prekey, ICLASS_KEYS_MAX, sizeof(iclass_prekey_t), cmp_uint32);
|
||||
iclass_prekey_t *item = (iclass_prekey_t *) bsearch(&lookup, prekey, ICLASS_KEYS_MAX * 2, sizeof(iclass_prekey_t), cmp_uint32);
|
||||
if (item != NULL) {
|
||||
memcpy(key, item->key, 8);
|
||||
free(prekey);
|
||||
return true;
|
||||
}
|
||||
free(prekey);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -589,8 +592,8 @@ static void mem_app_config(const picopass_hdr_t *hdr) {
|
|||
|
||||
PrintAndLogEx(INFO, "------------------------- " _CYAN_("KeyAccess") " ------------------------");
|
||||
PrintAndLogEx(INFO, " * Kd, Debit key, AA1 Kc, Credit key, AA2 *");
|
||||
uint8_t book = isset(mem, 0x20);
|
||||
if (book) {
|
||||
uint8_t keyAccess = isset(mem, 0x01);
|
||||
if (keyAccess) {
|
||||
PrintAndLogEx(INFO, " Read A....... debit");
|
||||
PrintAndLogEx(INFO, " Read B....... credit");
|
||||
PrintAndLogEx(INFO, " Write A...... debit");
|
||||
|
@ -2450,8 +2453,9 @@ static int CmdHFiClass_loclass(const char *Cmd) {
|
|||
}
|
||||
|
||||
static void detect_credential(uint8_t *data, bool *legacy, bool *se, bool *sr) {
|
||||
char* r1 = strstr((char*)data + (5 * 8), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF");
|
||||
char* r2 = strstr((char*)data + (11 * 8), "\x05\x00\x05\x00");
|
||||
bool r1 = !memcmp(data + (5 * 8), "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8);
|
||||
uint8_t pattern[] = {0x05, 0x00, 0x05, 0x00};
|
||||
bool r2 = byte_strstr(data + (11 * 8), 6 * 8, pattern, sizeof(pattern)) != -1;
|
||||
|
||||
*legacy = (r1) && (data[6 * 8] != 0x30);
|
||||
*se = (r2) && (data[6 * 8] == 0x30);
|
||||
|
@ -2465,40 +2469,31 @@ static void printIclassSIO(uint8_t *iclass_dump) {
|
|||
bool isLegacy, isSE, isSR;
|
||||
detect_credential(iclass_dump, &isLegacy, &isSE, &isSR);
|
||||
|
||||
uint8_t pattern[] = {0x05, 0x00, 0x05, 0x00};
|
||||
uint8_t *sio_start;
|
||||
if (isSE) {
|
||||
|
||||
int dlen = byte_strstr(iclass_dump + (6 * 8), 8*8, pattern, sizeof(pattern));
|
||||
if (dlen) {
|
||||
|
||||
dlen += sizeof(pattern);
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "---------------------------- " _CYAN_("SIO - RAW") " ----------------------------");
|
||||
print_hex_noascii_break(iclass_dump + (6*8), dlen, 32);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "------------------------- " _CYAN_("SIO - ASN1 TLV") " --------------------------");
|
||||
asn1_print(iclass_dump + (6 * 8), dlen, " ");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
sio_start = iclass_dump + (6 * 8);
|
||||
} else if (isSR) {
|
||||
sio_start = iclass_dump + (10 * 8);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isSR) {
|
||||
|
||||
int dlen = byte_strstr(iclass_dump + (10 * 8), 8*8, pattern, sizeof(pattern));
|
||||
|
||||
if (dlen) {
|
||||
dlen += sizeof(pattern);
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "---------------------------- " _CYAN_("SIO - RAW") " ----------------------------");
|
||||
print_hex_noascii_break(iclass_dump + (10*8), dlen, 32);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "------------------------- " _CYAN_("SIO - ASN1 TLV") " --------------------------");
|
||||
asn1_print(iclass_dump + (10 * 8), dlen, " ");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
uint8_t pattern[] = {0x05, 0x00, 0x05, 0x00};
|
||||
int dlen = byte_strstr(sio_start, 8 * 8, pattern, sizeof(pattern));
|
||||
if (dlen == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
dlen += sizeof(pattern);
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "---------------------------- " _CYAN_("SIO - RAW") " ----------------------------");
|
||||
print_hex_noascii_break(sio_start, dlen, 32);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "------------------------- " _CYAN_("SIO - ASN1 TLV") " --------------------------");
|
||||
asn1_print(sio_start, dlen, " ");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
}
|
||||
|
||||
void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize, bool dense_output) {
|
||||
|
@ -2543,8 +2538,10 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e
|
|||
*/
|
||||
uint8_t pagemap = get_pagemap(hdr);
|
||||
|
||||
bool isLegacy, isSE, isSR;
|
||||
detect_credential(iclass_dump, &isLegacy, &isSE, &isSR);
|
||||
bool isLegacy = false, isSE = false, isSR = false;
|
||||
if (filemaxblock >= 17) {
|
||||
detect_credential(iclass_dump, &isLegacy, &isSE, &isSR);
|
||||
}
|
||||
|
||||
int i = startblock;
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
@ -3567,8 +3564,6 @@ void GenerateMacKeyFrom(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elit
|
|||
|
||||
for (int i = 0; i < iclass_tc; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
|
||||
// print diversified keys
|
||||
|
|
|
@ -464,10 +464,17 @@ void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool
|
|||
curr_state = PICO_NONE;
|
||||
break;
|
||||
case ICLASS_CMD_CHECK:
|
||||
snprintf(exp, size, "CHECK");
|
||||
curr_state = PICO_AUTH_MACS;
|
||||
memcpy(rmac, cmd + 1, 4);
|
||||
memcpy(tmac, cmd + 5, 4);
|
||||
|
||||
uint8_t key[8];
|
||||
if (check_known_default(csn, epurse, rmac, tmac, key)) {
|
||||
snprintf(exp, size, "CHECK ( %s )", sprint_hex_inrow(key, 8));
|
||||
} else {
|
||||
snprintf(exp, size, "CHECK");
|
||||
}
|
||||
|
||||
break;
|
||||
case ICLASS_CMD_READ4:
|
||||
snprintf(exp, size, "READ4(%d)", cmd[1]);
|
||||
|
@ -516,11 +523,7 @@ void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool
|
|||
} else if (curr_state == PICO_AUTH_EPURSE) {
|
||||
memcpy(epurse, cmd, 8);
|
||||
} else if (curr_state == PICO_AUTH_MACS) {
|
||||
|
||||
uint8_t key[8];
|
||||
if (check_known_default(csn, epurse, rmac, tmac, key)) {
|
||||
snprintf(exp, size, "( " _GREEN_("%s") " )", sprint_hex_inrow(key, 8));
|
||||
}
|
||||
snprintf(exp, size, _GREEN_("CHECK SUCCESS"));
|
||||
curr_state = PICO_NONE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,6 +149,15 @@ typedef enum {
|
|||
NTAG413DNA,
|
||||
} nxp_cardtype_t;
|
||||
|
||||
typedef enum {
|
||||
DESFIRE_UNKNOWN_PROD = 0,
|
||||
DESFIRE_PHYSICAL,
|
||||
DESFIRE_LIGHT_PHYSICAL,
|
||||
DESFIRE_MICROCONTROLLER,
|
||||
DESFIRE_JAVACARD,
|
||||
DESFIRE_HCE,
|
||||
} nxp_producttype_t;
|
||||
|
||||
typedef struct dfname {
|
||||
uint8_t aid[3];
|
||||
uint8_t fid[2];
|
||||
|
@ -298,6 +307,43 @@ static nxp_cardtype_t getCardType(uint8_t major, uint8_t minor) {
|
|||
return DESFIRE_UNKNOWN;
|
||||
}
|
||||
|
||||
// ref: https://www.nxp.com/docs/en/application-note/AN12343.pdf p7
|
||||
static nxp_producttype_t getProductType(uint8_t *versionhw) {
|
||||
|
||||
uint8_t product = versionhw[2];
|
||||
|
||||
if (product == 0x01)
|
||||
return DESFIRE_PHYSICAL;
|
||||
if (product == 0x08)
|
||||
return DESFIRE_LIGHT_PHYSICAL;
|
||||
if (product == 0x81 || product == 0x83)
|
||||
return DESFIRE_MICROCONTROLLER;
|
||||
if (product == 0x91)
|
||||
return DESFIRE_JAVACARD;
|
||||
if (product == 0xA1)
|
||||
return DESFIRE_HCE;
|
||||
return DESFIRE_UNKNOWN_PROD;
|
||||
}
|
||||
|
||||
static const char* getProductTypeStr(uint8_t *versionhw) {
|
||||
|
||||
uint8_t product = versionhw[2];
|
||||
|
||||
if (product == 0x01)
|
||||
return "MIFARE DESFire native IC (physical card)";
|
||||
if (product == 0x08)
|
||||
return "MIFARE DESFire Light native IC (physical card)";
|
||||
if (product == 0x81 || product == 0x83)
|
||||
return "MIFARE DESFire implementation on microcontroller (physical card)";
|
||||
if (product == 0x91)
|
||||
return "MIFARE DESFire applet on Java card / secure element";
|
||||
if (product == 0xA1)
|
||||
return "MIFARE DESFire HCE (MIFARE 2GO)";
|
||||
return "UNKNOWN PROD";
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int mfdes_get_info(mfdes_info_res_t *info) {
|
||||
SendCommandNG(CMD_HF_DESFIRE_INFO, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
|
@ -627,6 +673,12 @@ static int CmdHF14ADesInfo(const char *Cmd) {
|
|||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(info.uid, info.uidlen));
|
||||
PrintAndLogEx(SUCCESS, " Batch number: " _GREEN_("%s"), sprint_hex(info.details + 7, 5));
|
||||
PrintAndLogEx(SUCCESS, " Production date: week " _GREEN_("%02x") " / " _GREEN_("20%02x"), info.details[12], info.details[13]);
|
||||
|
||||
nxp_producttype_t prodtype = getProductType(info.versionHW);
|
||||
if (prodtype != DESFIRE_UNKNOWN_PROD) {
|
||||
PrintAndLogEx(SUCCESS, " Product type: %s", getProductTypeStr(info.versionHW));
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--- " _CYAN_("Hardware Information"));
|
||||
PrintAndLogEx(INFO, " raw: %s", sprint_hex_inrow(info.versionHW, sizeof(info.versionHW)));
|
||||
|
@ -646,7 +698,6 @@ static int CmdHF14ADesInfo(const char *Cmd) {
|
|||
PrintAndLogEx(INFO, " Version: " _YELLOW_("%d.%d"), info.versionSW[3], info.versionSW[4]);
|
||||
PrintAndLogEx(INFO, " Storage size: %s", getCardSizeStr(info.versionSW[5]));
|
||||
PrintAndLogEx(INFO, " Protocol: %s", getProtocolStr(info.versionSW[6], false));
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--------------------------------- " _CYAN_("Card capabilities") " ---------------------------------");
|
||||
uint8_t major = info.versionSW[3];
|
||||
|
|
Loading…
Reference in a new issue