mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-02-15 03:34:22 +08:00
working progress..
This commit is contained in:
parent
4e6140570e
commit
61b8594cb4
2 changed files with 262 additions and 80 deletions
|
@ -28,15 +28,6 @@ static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = {
|
||||||
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }
|
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct iclass_block {
|
|
||||||
uint8_t d[8];
|
|
||||||
} iclass_block_t;
|
|
||||||
|
|
||||||
typedef struct iclass_precalc {
|
|
||||||
// uint8_t key[8];
|
|
||||||
uint8_t mac[4];
|
|
||||||
} iclass_precalc_t;
|
|
||||||
|
|
||||||
int usage_hf_iclass_sim(void) {
|
int usage_hf_iclass_sim(void) {
|
||||||
PrintAndLog("Usage: hf iclass sim <option> [CSN]");
|
PrintAndLog("Usage: hf iclass sim <option> [CSN]");
|
||||||
PrintAndLog(" options");
|
PrintAndLog(" options");
|
||||||
|
@ -392,7 +383,7 @@ int CmdHFiClassSim(const char *Cmd) {
|
||||||
free(dump);
|
free(dump);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4:{
|
case 4: {
|
||||||
PrintAndLog("Starting the sim 4 keyroll attack");
|
PrintAndLog("Starting the sim 4 keyroll attack");
|
||||||
UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType, NUM_CSNS}};
|
UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType, NUM_CSNS}};
|
||||||
UsbCommand resp = {0};
|
UsbCommand resp = {0};
|
||||||
|
@ -1816,9 +1807,6 @@ int CmdHFiClassManageKeys(const char *Cmd) {
|
||||||
|
|
||||||
int CmdHFiClassCheckKeys(const char *Cmd) {
|
int CmdHFiClassCheckKeys(const char *Cmd) {
|
||||||
|
|
||||||
//uint8_t mac[4] = {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 CSN[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
|
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 CCNR[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
|
||||||
|
|
||||||
|
@ -1826,17 +1814,17 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
|
||||||
bool use_elite = false;
|
bool use_elite = false;
|
||||||
bool use_raw = false;
|
bool use_raw = false;
|
||||||
bool found_debit = false;
|
bool found_debit = false;
|
||||||
bool found_credit = false;
|
//bool found_credit = false;
|
||||||
bool got_csn = false;
|
bool got_csn = false;
|
||||||
bool errors = false;
|
bool errors = false;
|
||||||
uint8_t cmdp = 0x00;
|
uint8_t cmdp = 0x00;
|
||||||
FILE * f;
|
|
||||||
char filename[FILE_PATH_SIZE] = {0};
|
char filename[FILE_PATH_SIZE] = {0};
|
||||||
uint8_t fileNameLen = 0;
|
uint8_t fileNameLen = 0;
|
||||||
char buf[17];
|
|
||||||
uint8_t *keyBlock = NULL, *p;
|
uint8_t *keyBlock = NULL;
|
||||||
iclass_precalc_t *pre = NULL;
|
iclass_precalc_t *pre = NULL;
|
||||||
int keyitems = 0, keycnt = 0;
|
int keycnt = 0;
|
||||||
|
|
||||||
// time
|
// time
|
||||||
uint64_t t1 = msclock();
|
uint64_t t1 = msclock();
|
||||||
|
@ -1872,45 +1860,10 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (errors) return usage_hf_iclass_chk();
|
if (errors) return usage_hf_iclass_chk();
|
||||||
|
|
||||||
if ( !(f = fopen( filename , "r")) ) {
|
|
||||||
PrintAndLog("File: %s: not found or locked.", filename);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while( fgets(buf, sizeof(buf), f) ){
|
|
||||||
if (strlen(buf) < 16 || buf[15] == '\n')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
while (fgetc(f) != '\n' && !feof(f)) ; //goto next line
|
// Get CSN / UID and CCNR
|
||||||
|
PrintAndLog("[+] Reading tag CSN");
|
||||||
if( buf[0]=='#' ) continue; //The line start with # is comment, skip
|
|
||||||
|
|
||||||
if (!isxdigit(buf[0])){
|
|
||||||
PrintAndLog("File content error. '%s' must include 16 HEX symbols",buf);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[16] = 0;
|
|
||||||
|
|
||||||
p = realloc(keyBlock, 8 * (keyitems += 64));
|
|
||||||
if (!p) {
|
|
||||||
PrintAndLog("Cannot allocate memory for default keys");
|
|
||||||
free(keyBlock);
|
|
||||||
fclose(f);
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
keyBlock = p;
|
|
||||||
|
|
||||||
memset(keyBlock + 8 * keycnt, 0, 8);
|
|
||||||
num_to_bytes(strtoull(buf, NULL, 16), 8, keyBlock + 8 * keycnt);
|
|
||||||
keycnt++;
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
PrintAndLog("[+] Loaded %2d keys from %s", keycnt, filename);
|
|
||||||
|
|
||||||
// // Get CSN / UID and CCNR
|
|
||||||
for (uint8_t i=0; i<10 && !got_csn; i++) {
|
for (uint8_t i=0; i<10 && !got_csn; i++) {
|
||||||
if (select_only(CSN, CCNR, false, false)) {
|
if (select_only(CSN, CCNR, false, false)) {
|
||||||
got_csn = true;
|
got_csn = true;
|
||||||
|
@ -1922,39 +1875,31 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
|
||||||
|
|
||||||
if ( !got_csn ) {
|
if ( !got_csn ) {
|
||||||
PrintAndLog("Can't select card, aborting...");
|
PrintAndLog("Can't select card, aborting...");
|
||||||
free(keyBlock);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load keys into keyblock
|
||||||
|
int res = ReadDictionaryKeyFile( filename, &keyBlock, &keycnt);
|
||||||
|
if ( res > 0) {
|
||||||
|
free(keyBlock);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
pre = calloc(keycnt, sizeof(iclass_precalc_t));
|
pre = calloc(keycnt, sizeof(iclass_precalc_t));
|
||||||
if ( !pre ) {
|
if ( !pre ) {
|
||||||
free(keyBlock);
|
free(keyBlock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// precalc diversified keys
|
PrintAndLog("[+] Generating diversified keys and MAC");
|
||||||
PrintAndLog("#key | key | mac");
|
res = GenerateMacFromKeyFile( CSN, CCNR, use_raw, use_elite, keyBlock, keycnt, pre );
|
||||||
PrintAndLog("-----+------------------+---------");
|
if ( res > 0) {
|
||||||
for ( int m=0; m < keycnt; m++) {
|
free(keyBlock);
|
||||||
|
free(pre);
|
||||||
memcpy(key, keyBlock + 8 * m , 8);
|
return 1;
|
||||||
|
|
||||||
if (use_raw)
|
|
||||||
memcpy(div_key, key, 8);
|
|
||||||
else
|
|
||||||
HFiClassCalcDivKey(CSN, key, div_key, use_elite);
|
|
||||||
|
|
||||||
doMAC(CCNR, div_key, pre[m].mac);
|
|
||||||
|
|
||||||
if (m < 10 ) {
|
|
||||||
PrintAndLog("[%2d] | %016" PRIx64 " | %08" PRIx32,
|
|
||||||
m,
|
|
||||||
bytes_to_num(key, 8),
|
|
||||||
bytes_to_num( pre[m].mac, 4) );
|
|
||||||
} else if ( m == 10 ) {
|
|
||||||
PrintAndLog("... skip printing the rest");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrintPreCalcMac(keyBlock, keycnt, pre);
|
||||||
|
|
||||||
// max 42 keys inside USB_COMMAND. 512/4 = 103 mac
|
// max 42 keys inside USB_COMMAND. 512/4 = 103 mac
|
||||||
uint32_t chunksize = keycnt > (USB_CMD_DATA_SIZE/4) ? (USB_CMD_DATA_SIZE/4) : keycnt;
|
uint32_t chunksize = keycnt > (USB_CMD_DATA_SIZE/4) ? (USB_CMD_DATA_SIZE/4) : keycnt;
|
||||||
|
@ -2021,7 +1966,7 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// both keys found.
|
// both keys found.
|
||||||
if ( found_debit && found_credit ) {
|
if ( found_debit ) {
|
||||||
PrintAndLog("[+] All keys found, exiting");
|
PrintAndLog("[+] All keys found, exiting");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2039,6 +1984,230 @@ out:
|
||||||
PrintAndLog("");
|
PrintAndLog("");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
static int cmp_uint32( const void *a, const void *b) {
|
||||||
|
if (*(const uint32_t *)a < *(const uint32_t *)b)
|
||||||
|
return -1;
|
||||||
|
else
|
||||||
|
return *(const uint32_t *)a > *(const uint32_t *)b;
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
|
||||||
|
// SIM / sniff,
|
||||||
|
// reader tries to authenticate AA1 ->
|
||||||
|
// legacy key
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
bool use_elite = false;
|
||||||
|
bool use_raw = false;
|
||||||
|
bool errors = false;
|
||||||
|
uint8_t cmdp = 0x00;
|
||||||
|
|
||||||
|
char filename[FILE_PATH_SIZE] = {0};
|
||||||
|
uint8_t fileNameLen = 0;
|
||||||
|
|
||||||
|
uint8_t *keyBlock = NULL;
|
||||||
|
iclass_precalc_t *pre = NULL;
|
||||||
|
int keycnt = 0;
|
||||||
|
|
||||||
|
// time
|
||||||
|
uint64_t t1 = msclock();
|
||||||
|
|
||||||
|
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||||
|
switch (param_getchar(Cmd, cmdp)) {
|
||||||
|
case 'h':
|
||||||
|
case 'H':
|
||||||
|
return usage_hf_iclass_chk();
|
||||||
|
case 'f':
|
||||||
|
case 'F':
|
||||||
|
fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
|
||||||
|
if (fileNameLen < 1) {
|
||||||
|
PrintAndLog("No filename found after f");
|
||||||
|
errors = true;
|
||||||
|
}
|
||||||
|
cmdp += 2;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
case 'E':
|
||||||
|
use_elite = true;
|
||||||
|
cmdp++;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
case 'R':
|
||||||
|
use_raw = true;
|
||||||
|
cmdp++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
|
||||||
|
errors = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errors) return usage_hf_iclass_chk();
|
||||||
|
|
||||||
|
int res = ReadDictionaryKeyFile( filename, &keyBlock, &keycnt);
|
||||||
|
if ( res > 0) {
|
||||||
|
free(keyBlock);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre = calloc(keycnt, sizeof(iclass_precalc_t));
|
||||||
|
if ( !pre ) {
|
||||||
|
free(keyBlock);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLog("[+] Generating diversified keys and MAC");
|
||||||
|
res = GenerateMacFromKeyFile( CSN, CCNR, use_raw, use_elite, keyBlock, keycnt, pre );
|
||||||
|
if ( res > 0) {
|
||||||
|
free(keyBlock);
|
||||||
|
free(pre);
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// if (use_raw)
|
||||||
|
// memcpy(div_key, key, 8);
|
||||||
|
// else
|
||||||
|
// HFiClassCalcDivKey(CSN, key, div_key, use_elite);
|
||||||
|
|
||||||
|
// doMAC(CCNR, div_key, pre_list[i].mac);
|
||||||
|
t1 = msclock() - t1;
|
||||||
|
|
||||||
|
PrintAndLog("\nTime in iclass : %.0f seconds\n", (float)t1/1000.0);
|
||||||
|
|
||||||
|
DropField();
|
||||||
|
free(pre);
|
||||||
|
free(keyBlock);
|
||||||
|
PrintAndLog("");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ReadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) {
|
||||||
|
|
||||||
|
char buf[17];
|
||||||
|
FILE * f;
|
||||||
|
uint8_t *p;
|
||||||
|
int keyitems = 0;
|
||||||
|
|
||||||
|
if ( !(f = fopen( filename , "r")) ) {
|
||||||
|
PrintAndLog("File: %s: not found or locked.", filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while( fgets(buf, sizeof(buf), f) ){
|
||||||
|
if (strlen(buf) < 16 || buf[15] == '\n')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//goto next line
|
||||||
|
while (fgetc(f) != '\n' && !feof(f)) {};
|
||||||
|
|
||||||
|
//The line start with # is comment, skip
|
||||||
|
if( buf[0]=='#' ) continue;
|
||||||
|
|
||||||
|
// doesn't this only test first char only?
|
||||||
|
if (!isxdigit(buf[0])){
|
||||||
|
PrintAndLog("File content error. '%s' must include 16 HEX symbols", buf);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// null terminator (skip the rest of the line)
|
||||||
|
buf[16] = 0;
|
||||||
|
|
||||||
|
p = realloc(*keys, 8 * (keyitems += 64));
|
||||||
|
if (!p) {
|
||||||
|
PrintAndLog("Cannot allocate memory for default keys");
|
||||||
|
fclose(f);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
*keys = p;
|
||||||
|
|
||||||
|
memset(*keys + 8 * (*keycnt), 0, 8);
|
||||||
|
num_to_bytes(strtoull(buf, NULL, 16), 8, *keys + 8 * (*keycnt));
|
||||||
|
(*keycnt)++;
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
PrintAndLog("%s Loaded %2d keys from %s", BLUE_MSG("[+]"), *keycnt, filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 ) {
|
||||||
|
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};
|
||||||
|
|
||||||
|
for ( int i=0; i < keycnt; i++) {
|
||||||
|
|
||||||
|
memcpy(key, keys + 8 * i , 8);
|
||||||
|
|
||||||
|
if (use_raw)
|
||||||
|
memcpy(div_key, key, 8);
|
||||||
|
else
|
||||||
|
HFiClassCalcDivKey(CSN, key, div_key, use_elite);
|
||||||
|
|
||||||
|
doMAC(CCNR, div_key, pre_list[i].mac);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// print diversified keys
|
||||||
|
void PrintPreCalcMac(uint8_t* keys, int keycnt, iclass_precalc_t* pre_list) {
|
||||||
|
|
||||||
|
uint8_t key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
|
||||||
|
PrintAndLog("-----+------------------+---------");
|
||||||
|
PrintAndLog("#key | key | mac");
|
||||||
|
PrintAndLog("-----+------------------+---------");
|
||||||
|
for ( int i=0; i < keycnt; i++) {
|
||||||
|
|
||||||
|
memcpy(key, keys + 8 * i , 8);
|
||||||
|
|
||||||
|
if (i < 10 ) {
|
||||||
|
PrintAndLog("[%2d] | %016" PRIx64 " | %08" PRIx32, i, bytes_to_num(key, 8), bytes_to_num( pre_list[i].mac, 4) );
|
||||||
|
} else if ( i == 10 ) {
|
||||||
|
PrintAndLog("... skip printing the rest");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static command_t CommandTable[] = {
|
static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, 1, "This help"},
|
{"help", CmdHelp, 1, "This help"},
|
||||||
|
|
|
@ -36,6 +36,16 @@
|
||||||
#include "protocols.h" // picopass structs,
|
#include "protocols.h" // picopass structs,
|
||||||
#include "usb_cdc.h" // for usb_poll_validate_length
|
#include "usb_cdc.h" // for usb_poll_validate_length
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct iclass_block {
|
||||||
|
uint8_t d[8];
|
||||||
|
} iclass_block_t;
|
||||||
|
|
||||||
|
typedef struct iclass_precalc {
|
||||||
|
uint8_t mac[4];
|
||||||
|
} iclass_precalc_t;
|
||||||
|
|
||||||
int CmdHFiClass(const char *Cmd);
|
int CmdHFiClass(const char *Cmd);
|
||||||
|
|
||||||
extern int CmdHFiClassCalcNewKey(const char *Cmd);
|
extern int CmdHFiClassCalcNewKey(const char *Cmd);
|
||||||
|
@ -61,4 +71,7 @@ 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 );
|
||||||
|
void PrintPreCalcMac(uint8_t* keys, int keycnt, iclass_precalc_t* pre_list);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue