chg: 'hf iclass' - work in progress. running default_iclass_keys.dic against reader (pm3 as simulation)

This commit is contained in:
iceman1001 2018-01-02 11:17:31 +01:00
commit fe9416db23
3 changed files with 171 additions and 95 deletions

View file

@ -2095,10 +2095,9 @@ void iClass_Authentication(uint8_t *mac) {
cmd_send(CMD_ACK,isOK,0,0,0,0); cmd_send(CMD_ACK,isOK,0,0,0,0);
} }
typedef struct iclass_precalc { typedef struct iclass_premac {
//uint8_t key[8];
uint8_t mac[4]; uint8_t mac[4];
} iclass_precalc_t; } iclass_premac_t;
/* this function works on the following assumptions. /* this function works on the following assumptions.
* - one select first, to get CSN / CC (e-purse) * - one select first, to get CSN / CC (e-purse)
@ -2122,7 +2121,7 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
// select card / e-purse // select card / e-purse
uint8_t card_data[6 * 8] = {0}; uint8_t card_data[6 * 8] = {0};
iclass_precalc_t *keys = (iclass_precalc_t *)datain; iclass_premac_t *keys = (iclass_premac_t *)datain;
LED_A_ON(); LED_A_ON();

View file

@ -216,12 +216,13 @@ int usage_hf_iclass_loclass(void) {
} }
int usage_hf_iclass_chk(void) { int usage_hf_iclass_chk(void) {
PrintAndLog("Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag"); PrintAndLog("Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag");
PrintAndLog("Usage: hf iclass chk [h|e|r] <f (*.dic)>"); PrintAndLog("Usage: hf iclass chk [h|e|r] [f (*.dic)] [c <csn>] [p <epurse>] [m <macs>]");
PrintAndLog("Options:"); PrintAndLog("Options:");
PrintAndLog(" h Show this help"); PrintAndLog(" h Show this help");
PrintAndLog(" f <filename> Dictionary file with default iclass keys"); PrintAndLog(" f <filename> Dictionary file with default iclass keys");
PrintAndLog(" e target Elite / High security key scheme"); PrintAndLog(" c CSN");
PrintAndLog(" r interpret dictionary file as raw (diversified keys)"); PrintAndLog(" p EPURSE");
PrintAndLog(" m macs");
PrintAndLog("Samples:"); PrintAndLog("Samples:");
PrintAndLog(" hf iclass chk f default_iclass_keys.dic"); PrintAndLog(" hf iclass chk f default_iclass_keys.dic");
PrintAndLog(" hf iclass chk f default_iclass_keys.dic e"); PrintAndLog(" hf iclass chk f default_iclass_keys.dic e");
@ -1823,7 +1824,7 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
uint8_t fileNameLen = 0; uint8_t fileNameLen = 0;
uint8_t *keyBlock = NULL; uint8_t *keyBlock = NULL;
iclass_precalc_t *pre = NULL; iclass_premac_t *pre = NULL;
int keycnt = 0; int keycnt = 0;
// time // time
@ -1879,13 +1880,13 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
} }
// load keys into keyblock // load keys into keyblock
int res = ReadDictionaryKeyFile( filename, &keyBlock, &keycnt); int res = LoadDictionaryKeyFile( filename, &keyBlock, &keycnt);
if ( res > 0) { if ( res > 0) {
free(keyBlock); free(keyBlock);
return 1; return 1;
} }
pre = calloc(keycnt, sizeof(iclass_precalc_t)); pre = calloc(keycnt, sizeof(iclass_premac_t));
if ( !pre ) { if ( !pre ) {
free(keyBlock); free(keyBlock);
return 1; return 1;
@ -1984,50 +1985,49 @@ out:
PrintAndLog(""); PrintAndLog("");
return 0; return 0;
} }
static int cmp_uint32( const void *a, const void *b) { static int cmp_uint32( const void *a, const void *b) {
if (*(const uint32_t *)a < *(const uint32_t *)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; return -1;
else else
return *(const uint32_t *)a > *(const uint32_t *)b; return mx > my;
}
static inline uint32_t binsearch(uint32_t key, uint32_t v[], size_t n){
int low, high, mid;
low = 0;
high = n - 1;
while (low <= high) {
mid = (low+high)/2;
if (key < v[mid])
high = mid + 1;
else if (key > v[mid])
low = mid + 1;
else /* found match */
return mid;
}
return -1; /* no match */
} }
int ReaderEliteLookUp(const char *Cmd) { // binary search in struct iclass_prekey_t for mac
// static inline int32_t binsearch(uint32_t key, iclass_prekey_t* v, size_t n){
// int mid, low = 0, high = n - 1;
// uint32_t m;
// while (low <= high) {
// mid = (low+high)/2;
// m = bytes_to_num( v[mid].mac, 4);
// if (key < m)
// high = mid - 1;
// else if (key > m)
// low = mid + 1;
// else /* found match */
// return mid;
// }
// return -1; /* no match */
// }
// 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.
int CmdHFiClassLookUp(const char *Cmd) {
// SIM / sniff, uint8_t CSN[8];
// reader tries to authenticate AA1 -> uint8_t EPURSE[8];
// legacy key uint8_t MACS[8];
// uint8_t MAC_TAG[4] = {0x00,0x00,0x00,0x00};
// or
// elite key
// ladda nycklar.
// sortera nycklar, mac på mac qsort
// leta upp mac binsearch,
// om funnen, printa
// load keys into keyblock
uint8_t CSN[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t CCNR[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
/*
uint8_t key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t mac_legacy[4] = {0x00,0x00,0x00,0x00};
uint8_t mac_elite[4] = {0x00,0x00,0x00,0x00};
*/
// elite key, raw key, standard key // elite key, raw key, standard key
bool use_elite = false; bool use_elite = false;
bool use_raw = false; bool use_raw = false;
@ -2038,8 +2038,8 @@ int ReaderEliteLookUp(const char *Cmd) {
uint8_t fileNameLen = 0; uint8_t fileNameLen = 0;
uint8_t *keyBlock = NULL; uint8_t *keyBlock = NULL;
iclass_precalc_t *pre = NULL; iclass_prekey_t *prekey = NULL;
int keycnt = 0; int keycnt = 0, len = 0;
// time // time
uint64_t t1 = msclock(); uint64_t t1 = msclock();
@ -2058,6 +2058,36 @@ int ReaderEliteLookUp(const char *Cmd) {
} }
cmdp += 2; cmdp += 2;
break; break;
case 'u':
case 'U':
param_gethex_ex(Cmd, cmdp+1, CSN, &len);
if ( len>>1 != sizeof(CSN) ) {
PrintAndLog("Wrong CSN length, expected %d got [%d]", sizeof(CSN), len>>1);
errors = true;
}
cmdp += 2;
break;
case 'm':
case 'M':
param_gethex_ex(Cmd, cmdp+1, MACS, &len);
if ( len>>1 != sizeof(MACS) ) {
PrintAndLog("Wrong MACS length, expected %d got [%d] ", sizeof(MACS), len>>1);
errors = true;
} else {
memcpy(MAC_TAG, MACS+4, 4);
}
cmdp += 2;
break;
case 'p':
case 'P':
param_gethex_ex(Cmd, cmdp+1, EPURSE, &len);
if ( len>>1 != sizeof(EPURSE) ) {
PrintAndLog("Wrong EPURSE length, expected %d got [%d] ", sizeof(EPURSE), len>>1);
errors = true;
}
cmdp += 2;
break;
break;
case 'e': case 'e':
case 'E': case 'E':
use_elite = true; use_elite = true;
@ -2075,54 +2105,60 @@ int ReaderEliteLookUp(const char *Cmd) {
} }
} }
if (errors) return usage_hf_iclass_chk(); if (errors) return usage_hf_iclass_chk();
int res = ReadDictionaryKeyFile( filename, &keyBlock, &keycnt); PrintAndLog("CSN %s", sprint_hex( CSN, sizeof(CSN) ));
if ( res > 0) { PrintAndLog("Epurse %s", sprint_hex( EPURSE, sizeof(EPURSE) ));
free(keyBlock); PrintAndLog("MACS %s", sprint_hex( MACS, sizeof(MACS) ));
return 1; PrintAndLog("MAC_TAG %s", sprint_hex( MAC_TAG, sizeof(MAC_TAG) ));
}
pre = calloc(keycnt, sizeof(iclass_precalc_t));
if ( !pre ) {
free(keyBlock);
return 1;
}
PrintAndLog("[+] Generating diversified keys and MAC"); int res = LoadDictionaryKeyFile( filename, &keyBlock, &keycnt);
res = GenerateMacFromKeyFile( CSN, CCNR, use_raw, use_elite, keyBlock, keycnt, pre );
if ( res > 0) { if ( res > 0) {
free(keyBlock); free(keyBlock);
free(pre); return 1;
}
//iclass_prekey_t
prekey = calloc(keycnt, sizeof(iclass_prekey_t));
if ( !prekey ) {
free(keyBlock);
return 1;
}
PrintAndLog("[-] Generating diversified keys and MAC");
res = GenerateFromKeyFile( CSN, EPURSE, use_raw, use_elite, keyBlock, keycnt, prekey );
if ( res > 0) {
free(keyBlock);
free(prekey);
return 1; return 1;
} }
// qsort
// qsort( pre, sizeof(iclass_precalc_t), cmp_uint32);
// binsearch(mac_elite, pre, keycnt)
// memcpy(div_key, key, 8);
// doMAC(CCNR, div_key, mac_legacy);
PrintAndLog("[-] Sorting");
// if (use_raw) // sort mac list.
// memcpy(div_key, key, 8); qsort( prekey, keycnt, sizeof(iclass_prekey_t), cmp_uint32);
// else
// HFiClassCalcDivKey(CSN, key, div_key, use_elite); //PrintPreCalc(prekey, keycnt);
PrintAndLog("[-] Searching");
iclass_prekey_t *item;
iclass_prekey_t lookup;
memcpy(lookup.mac, MAC_TAG, 4);
// using find
item = (iclass_prekey_t*) bsearch(&lookup, prekey, keycnt, sizeof(iclass_prekey_t), cmp_uint32);
if( item != NULL ) {
PrintAndLog("\n[+] [debit] found key %s", sprint_hex(item->key, 8));
}
// doMAC(CCNR, div_key, pre_list[i].mac);
t1 = msclock() - t1; t1 = msclock() - t1;
PrintAndLog("\nTime in iclass : %.0f seconds\n", (float)t1/1000.0); PrintAndLog("\nTime in iclass : %.0f seconds\n", (float)t1/1000.0);
DropField(); DropField();
free(pre); free(prekey);
free(keyBlock); free(keyBlock);
PrintAndLog(""); PrintAndLog("");
return 0; return 0;
} }
int ReadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) { int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) {
char buf[17]; char buf[17];
FILE * f; FILE * f;
@ -2172,7 +2208,7 @@ int ReadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) {
} }
// precalc diversified keys and their MAC // precalc diversified keys and their MAC
int GenerateMacFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_elite, uint8_t* keys, int keycnt, iclass_precalc_t* pre_list ) { int GenerateMacFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_elite, uint8_t* keys, int keycnt, iclass_premac_t* list ) {
uint8_t key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
@ -2185,24 +2221,54 @@ int GenerateMacFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_
else else
HFiClassCalcDivKey(CSN, key, div_key, use_elite); HFiClassCalcDivKey(CSN, key, div_key, use_elite);
doMAC(CCNR, div_key, pre_list[i].mac); doMAC(CCNR, div_key, list[i].mac);
}
return 0;
}
int GenerateFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_elite, uint8_t* keys, int keycnt, iclass_prekey_t* list ) {
uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
for ( int i=0; i < keycnt; i++) {
memcpy(list[i].key, keys + 8 * i , 8);
// generate diversifed key
if (use_raw)
memcpy(div_key, list[i].key, 8);
else
HFiClassCalcDivKey(CSN, list[i].key, div_key, use_elite);
// generate MAC
doMAC(CCNR, div_key, list[i].mac);
} }
return 0; return 0;
} }
// print diversified keys // print diversified keys
void PrintPreCalcMac(uint8_t* keys, int keycnt, iclass_precalc_t* pre_list) { void PrintPreCalcMac(uint8_t* keys, int keycnt, iclass_premac_t* pre_list) {
uint8_t key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; iclass_prekey_t* b = calloc(keycnt, sizeof(iclass_prekey_t));
if ( !b )
return;
for ( int i=0; i < keycnt; i++) {
memcpy(b[i].key, keys + 8 * i , 8);
memcpy(b[i].mac, pre_list[i].mac, 4);
}
PrintPreCalc(b, keycnt);
free(b);
}
void PrintPreCalc(iclass_prekey_t* list, int itemcnt) {
PrintAndLog("-----+------------------+---------"); PrintAndLog("-----+------------------+---------");
PrintAndLog("#key | key | mac"); PrintAndLog("#key | key | mac");
PrintAndLog("-----+------------------+---------"); PrintAndLog("-----+------------------+---------");
for ( int i=0; i < keycnt; i++) { for ( int i=0; i < itemcnt; i++) {
memcpy(key, keys + 8 * i , 8);
if (i < 10 ) { if (i < 10 ) {
PrintAndLog("[%2d] | %016" PRIx64 " | %08" PRIx32, i, bytes_to_num(key, 8), bytes_to_num( pre_list[i].mac, 4) ); PrintAndLog("[%2d] | %016" PRIx64 " | %08" PRIx32, i, bytes_to_num(list[i].key, 8), bytes_to_num( list[i].mac, 4) );
} else if ( i == 10 ) { } else if ( i == 10 ) {
PrintAndLog("... skip printing the rest"); PrintAndLog("... skip printing the rest");
} }
@ -2228,6 +2294,8 @@ static command_t CommandTable[] = {
{"sim", CmdHFiClassSim, 0, "[options..] Simulate iClass tag"}, {"sim", CmdHFiClassSim, 0, "[options..] Simulate iClass tag"},
{"sniff", CmdHFiClassSniff, 0, " Eavesdrop iClass communication"}, {"sniff", CmdHFiClassSniff, 0, " Eavesdrop iClass communication"},
{"writeblk", CmdHFiClass_WriteBlock, 0, "[options..] Authenticate and Write iClass block"}, {"writeblk", CmdHFiClass_WriteBlock, 0, "[options..] Authenticate and Write iClass block"},
{"a", CmdHFiClassLookUp, 0, "[options..] A"},
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
}; };

View file

@ -42,9 +42,14 @@ typedef struct iclass_block {
uint8_t d[8]; uint8_t d[8];
} iclass_block_t; } iclass_block_t;
typedef struct iclass_precalc { typedef struct iclass_premac {
uint8_t mac[4]; uint8_t mac[4];
} iclass_precalc_t; } iclass_premac_t;
typedef struct iclass_prekey {
uint8_t mac[4];
uint8_t key[8];
} iclass_prekey_t;
int CmdHFiClass(const char *Cmd); int CmdHFiClass(const char *Cmd);
@ -69,9 +74,13 @@ extern int CmdHFiClassSim(const char *Cmd);
extern int CmdHFiClassWriteKeyFile(const char *Cmd); extern int CmdHFiClassWriteKeyFile(const char *Cmd);
extern int CmdHFiClass_WriteBlock(const char *Cmd); extern int CmdHFiClass_WriteBlock(const char *Cmd);
extern int CmdHF14AMfChk(const char *Cmd); extern int CmdHF14AMfChk(const char *Cmd);
void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize); void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize);
void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite); void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite);
int ReadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt);
int GenerateMacFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_elite, uint8_t* keys, int keycnt, iclass_precalc_t* pre_list ); int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt);
void PrintPreCalcMac(uint8_t* keys, int keycnt, iclass_precalc_t* pre_list); int GenerateMacFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_elite, uint8_t* keys, int keycnt, iclass_premac_t* list );
int GenerateFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_elite, uint8_t* keys, int keycnt, iclass_prekey_t* list );
void PrintPreCalcMac(uint8_t* keys, int keycnt, iclass_premac_t* pre_list);
void PrintPreCalc(iclass_prekey_t* list, int itemcnt);
#endif #endif