mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 02:27:26 -07:00
hf iclass list - now tries to recovery key
This commit is contained in:
parent
9ade745f07
commit
508151ee3a
5 changed files with 141 additions and 72 deletions
|
@ -362,6 +362,46 @@ static int usage_hf_iclass_permutekey(void) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int cmp_uint32(const void *a, const void *b) {
|
||||
|
||||
const iclass_prekey_t *x = (const iclass_prekey_t *)a;
|
||||
const iclass_prekey_t *y = (const iclass_prekey_t *)b;
|
||||
|
||||
uint32_t mx = bytes_to_num((uint8_t *)x->mac, 4);
|
||||
uint32_t my = bytes_to_num((uint8_t *)y->mac, 4);
|
||||
|
||||
if (mx < my)
|
||||
return -1;
|
||||
else
|
||||
return mx > my;
|
||||
}
|
||||
|
||||
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));
|
||||
if (prekey == false) {
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
uint8_t ccnr[12];
|
||||
memcpy(ccnr, epurse, 8);
|
||||
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);
|
||||
|
||||
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);
|
||||
if (item != NULL) {
|
||||
memcpy(key, item->key, 8);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
None = 0,
|
||||
DES,
|
||||
|
@ -415,7 +455,7 @@ static uint8_t notset(uint8_t val, uint8_t mask) {
|
|||
return !(val & mask);
|
||||
}
|
||||
|
||||
static uint8_t get_pagemap(const picopass_hdr *hdr) {
|
||||
uint8_t get_pagemap(const picopass_hdr *hdr) {
|
||||
return (hdr->conf.fuses & (FUSE_CRYPT0 | FUSE_CRYPT1)) >> 3;
|
||||
}
|
||||
|
||||
|
@ -2926,9 +2966,7 @@ static int CmdHFiClassCheckKeys(const char *Cmd) {
|
|||
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
uint8_t fileNameLen = 0;
|
||||
iclass_premac_t *pre = NULL;
|
||||
|
||||
// time
|
||||
uint64_t t1 = msclock();
|
||||
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
|
@ -2973,7 +3011,7 @@ static int CmdHFiClassCheckKeys(const char *Cmd) {
|
|||
return res;
|
||||
}
|
||||
|
||||
pre = calloc(keycount, sizeof(iclass_premac_t));
|
||||
iclass_premac_t *pre = calloc(keycount, sizeof(iclass_premac_t));
|
||||
if (!pre) {
|
||||
free(keyBlock);
|
||||
return PM3_EMALLOC;
|
||||
|
@ -3116,20 +3154,6 @@ out:
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int cmp_uint32(const void *a, const void *b) {
|
||||
|
||||
const iclass_prekey_t *x = (const iclass_prekey_t *)a;
|
||||
const iclass_prekey_t *y = (const iclass_prekey_t *)b;
|
||||
|
||||
uint32_t mx = bytes_to_num((uint8_t *)x->mac, 4);
|
||||
uint32_t my = bytes_to_num((uint8_t *)y->mac, 4);
|
||||
|
||||
if (mx < my)
|
||||
return -1;
|
||||
else
|
||||
return mx > my;
|
||||
}
|
||||
|
||||
// this method tries to identify in which configuration mode a iCLASS / iCLASS SE reader is in.
|
||||
// Standard or Elite / HighSecurity mode. It uses a default key dictionary list in order to work.
|
||||
static int CmdHFiClassLookUp(const char *Cmd) {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "common.h"
|
||||
#include "fileutils.h"
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
typedef struct iclass_block {
|
||||
uint8_t d[8];
|
||||
|
@ -38,4 +39,7 @@ void GenerateMacFrom(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elite,
|
|||
void GenerateMacKeyFrom(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elite, uint8_t *keys, uint32_t keycnt, iclass_prekey_t *list);
|
||||
void PrintPreCalcMac(uint8_t *keys, uint32_t keycnt, iclass_premac_t *pre_list);
|
||||
void PrintPreCalc(iclass_prekey_t *list, uint32_t itemcnt);
|
||||
|
||||
uint8_t get_pagemap(const picopass_hdr *hdr);
|
||||
bool check_known_default(uint8_t *csn, uint8_t *epurse, uint8_t* rmac, uint8_t* tmac, uint8_t* key);
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "crc16.h"
|
||||
#include "crapto1/crapto1.h"
|
||||
#include "protocols.h"
|
||||
#include "cmdhficlass.h"
|
||||
|
||||
enum MifareAuthSeq {
|
||||
masNone,
|
||||
|
@ -326,59 +327,99 @@ void annotateIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
|||
applyIso14443a(exp, size, cmd, cmdsize);
|
||||
}
|
||||
|
||||
void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) {
|
||||
uint8_t c = cmd[0] & 0x0F;
|
||||
uint8_t parity = 0;
|
||||
for (uint8_t i = 0; i < 7; i++) {
|
||||
parity ^= (cmd[0] >> i) & 1;
|
||||
}
|
||||
void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool isResponse) {
|
||||
|
||||
switch (c) {
|
||||
case ICLASS_CMD_HALT:
|
||||
snprintf(exp, size, "HALT");
|
||||
break;
|
||||
case ICLASS_CMD_SELECT:
|
||||
snprintf(exp, size, "SELECT");
|
||||
break;
|
||||
case ICLASS_CMD_ACTALL:
|
||||
snprintf(exp, size, "ACTALL");
|
||||
break;
|
||||
case ICLASS_CMD_DETECT:
|
||||
snprintf(exp, size, "DETECT");
|
||||
break;
|
||||
case ICLASS_CMD_CHECK:
|
||||
snprintf(exp, size, "CHECK");
|
||||
break;
|
||||
case ICLASS_CMD_READ4:
|
||||
snprintf(exp, size, "READ4(%d)", cmd[1]);
|
||||
break;
|
||||
case ICLASS_CMD_READ_OR_IDENTIFY: {
|
||||
if (cmdsize > 1) {
|
||||
snprintf(exp, size, "READ(%d)", cmd[1]);
|
||||
} else {
|
||||
snprintf(exp, size, "IDENTIFY");
|
||||
}
|
||||
break;
|
||||
enum pico_state {PICO_NONE, PICO_SELECT, PICO_AUTH_EPURSE, PICO_AUTH_MACS };
|
||||
static enum pico_state curr_state = PICO_NONE;
|
||||
static uint8_t csn[8];
|
||||
static uint8_t epurse[8];
|
||||
static uint8_t rmac[4];
|
||||
static uint8_t tmac[4];
|
||||
|
||||
if ( isResponse == false ) {
|
||||
uint8_t c = cmd[0] & 0x0F;
|
||||
uint8_t parity = 0;
|
||||
for (uint8_t i = 0; i < 7; i++) {
|
||||
parity ^= (cmd[0] >> i) & 1;
|
||||
}
|
||||
case ICLASS_CMD_PAGESEL:
|
||||
snprintf(exp, size, "PAGESEL(%d)", cmd[1]);
|
||||
break;
|
||||
case ICLASS_CMD_UPDATE:
|
||||
snprintf(exp, size, "UPDATE(%d)", cmd[1]);
|
||||
break;
|
||||
case ICLASS_CMD_READCHECK:
|
||||
if (ICLASS_CREDIT(cmd[0])) {
|
||||
snprintf(exp, size, "READCHECK[Kc](%d)", cmd[1]);
|
||||
} else {
|
||||
snprintf(exp, size, "READCHECK[Kd](%d)", cmd[1]);
|
||||
|
||||
switch (c) {
|
||||
case ICLASS_CMD_HALT:
|
||||
snprintf(exp, size, "HALT");
|
||||
curr_state = PICO_NONE;
|
||||
break;
|
||||
case ICLASS_CMD_SELECT:
|
||||
snprintf(exp, size, "SELECT");
|
||||
curr_state = PICO_SELECT;
|
||||
break;
|
||||
case ICLASS_CMD_ACTALL:
|
||||
snprintf(exp, size, "ACTALL");
|
||||
curr_state = PICO_NONE;
|
||||
break;
|
||||
case ICLASS_CMD_DETECT:
|
||||
snprintf(exp, size, "DETECT");
|
||||
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);
|
||||
break;
|
||||
case ICLASS_CMD_READ4:
|
||||
snprintf(exp, size, "READ4(%d)", cmd[1]);
|
||||
break;
|
||||
case ICLASS_CMD_READ_OR_IDENTIFY: {
|
||||
|
||||
if (cmdsize > 1) {
|
||||
snprintf(exp, size, "READ(%d)", cmd[1]);
|
||||
} else {
|
||||
snprintf(exp, size, "IDENTIFY");
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ICLASS_CMD_ACT:
|
||||
snprintf(exp, size, "ACT");
|
||||
break;
|
||||
default:
|
||||
snprintf(exp, size, "?");
|
||||
break;
|
||||
case ICLASS_CMD_PAGESEL:
|
||||
snprintf(exp, size, "PAGESEL(%d)", cmd[1]);
|
||||
curr_state = PICO_NONE;
|
||||
break;
|
||||
case ICLASS_CMD_UPDATE:
|
||||
snprintf(exp, size, "UPDATE(%d)", cmd[1]);
|
||||
curr_state = PICO_NONE;
|
||||
break;
|
||||
case ICLASS_CMD_READCHECK:
|
||||
if (ICLASS_CREDIT(cmd[0])) {
|
||||
snprintf(exp, size, "READCHECK[Kc](%d)", cmd[1]);
|
||||
curr_state = PICO_AUTH_EPURSE;
|
||||
} else {
|
||||
snprintf(exp, size, "READCHECK[Kd](%d)", cmd[1]);
|
||||
curr_state = PICO_AUTH_EPURSE;
|
||||
}
|
||||
break;
|
||||
case ICLASS_CMD_ACT:
|
||||
snprintf(exp, size, "ACT");
|
||||
curr_state = PICO_NONE;
|
||||
break;
|
||||
default:
|
||||
snprintf(exp, size, "?");
|
||||
curr_state = PICO_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (curr_state == PICO_SELECT) {
|
||||
memcpy(csn, cmd, 8);
|
||||
curr_state = PICO_NONE;
|
||||
} 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(key, 8) );
|
||||
}
|
||||
curr_state = PICO_NONE;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ uint8_t iclass_CRC_check(bool isResponse, uint8_t *d, uint8_t n);
|
|||
|
||||
int applyIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
|
||||
|
||||
void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
|
||||
void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool isResponse);
|
||||
void annotateIso15693(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
|
||||
void annotateTopaz(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
|
||||
void annotateLegic(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize);
|
||||
|
|
|
@ -387,6 +387,9 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
case PROTO_HITAGS:
|
||||
annotateHitagS(explanation, sizeof(explanation), frame, data_len, hdr->isResponse);
|
||||
break;
|
||||
case ICLASS:
|
||||
annotateIclass(explanation, sizeof(explanation), frame, data_len, hdr->isResponse);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -397,9 +400,6 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
|||
case LEGIC:
|
||||
annotateLegic(explanation, sizeof(explanation), frame, data_len);
|
||||
break;
|
||||
case ICLASS:
|
||||
annotateIclass(explanation, sizeof(explanation), frame, data_len);
|
||||
break;
|
||||
case ISO_14443A:
|
||||
annotateIso14443a(explanation, sizeof(explanation), frame, data_len);
|
||||
break;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue