chg: 'hf iclass chk' - enabled credit/debit key selction

chg:  'hf iclass lookup'  - enabled credit/debit key selction
fix: first item in dictionary file now correct identified
chg: code cleanup
This commit is contained in:
Chris 2018-06-30 22:47:07 +02:00
parent 17d406be1c
commit 2b294912ee
2 changed files with 38 additions and 34 deletions

View file

@ -1853,9 +1853,9 @@ uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key) {
static uint8_t act_all[] = { ICLASS_CMD_ACTALL }; static uint8_t act_all[] = { ICLASS_CMD_ACTALL };
static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 }; static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 };
static uint8_t select[] = { ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static uint8_t select[] = { ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK_KD, 0x02 }; uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK_KD, 0x02 };
if (use_credit_key) if (use_credit_key)
readcheck_cc[0] = ICLASS_CMD_READCHECK_KC; readcheck_cc[0] = ICLASS_CMD_READCHECK_KC;
uint8_t resp[ICLASS_BUFFER_SIZE] = {0}; uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
@ -1891,12 +1891,13 @@ uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key) {
read_status = 1; read_status = 1;
// Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC) // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC)
// ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); // ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc));
// if (ReaderReceiveIClass(resp) == 8) { // if (ReaderReceiveIClass(resp) == 8) {
// //Save CC (e-purse) in response data // //Save CC (e-purse) in response data
// memcpy(card_data+8, resp, 8); // memcpy(card_data+8, resp, 8);
// read_status++; // read_status++;
// } // }
bool isOK = sendCmdGetResponseWithRetries(readcheck_cc, sizeof(readcheck_cc), resp, 8, 3); bool isOK = sendCmdGetResponseWithRetries(readcheck_cc, sizeof(readcheck_cc), resp, 8, 3);
if (!isOK) return read_status; if (!isOK) return read_status;
@ -2237,7 +2238,7 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
while ( read_status != 2) { while ( read_status != 2) {
if (BUTTON_PRESS() && !usb_poll_validate_length()) goto out; if (BUTTON_PRESS() && !usb_poll_validate_length()) goto out;
read_status = handshakeIclassTag_ext(card_data, use_credit_key); read_status = handshakeIclassTag_ext(card_data, use_credit_key);
if ( startup_limit-- == 0 ) { if ( startup_limit-- == 0 ) {
Dbprintf("[-] Handshake status | %d (fail 10)", read_status); Dbprintf("[-] Handshake status | %d (fail 10)", read_status);
@ -2262,7 +2263,7 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
check[7] = keys[i].mac[2]; check[7] = keys[i].mac[2];
check[8] = keys[i].mac[3]; check[8] = keys[i].mac[3];
// expect 4bytes, 2 retries times.. // expect 4bytes, 3 retries times..
isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 3); isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 3);
if ( isOK ) if ( isOK )
goto out; goto out;
@ -2272,8 +2273,6 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
// Auth Sequence MUST begin with reading e-purse. (block2) // Auth Sequence MUST begin with reading e-purse. (block2)
// Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC) // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC)
ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc));
// if (ReaderReceiveIClass(resp) == 8) {
// }
LED_B_OFF(); LED_B_OFF();
} }

View file

@ -225,6 +225,7 @@ int usage_hf_iclass_chk(void) {
PrintAndLogEx(NORMAL, " f <filename> Dictionary file with default iclass keys"); PrintAndLogEx(NORMAL, " f <filename> Dictionary file with default iclass keys");
PrintAndLogEx(NORMAL, " r raw"); PrintAndLogEx(NORMAL, " r raw");
PrintAndLogEx(NORMAL, " e elite"); PrintAndLogEx(NORMAL, " e elite");
PrintAndLogEx(NORMAL, " c credit key (if not use, default is debit)");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " hf iclass chk f default_iclass_keys.dic"); PrintAndLogEx(NORMAL, " hf iclass chk f default_iclass_keys.dic");
PrintAndLogEx(NORMAL, " hf iclass chk f default_iclass_keys.dic e"); PrintAndLogEx(NORMAL, " hf iclass chk f default_iclass_keys.dic e");
@ -1937,12 +1938,16 @@ int CmdHFiClassManageKeys(const char *Cmd) {
int CmdHFiClassCheckKeys(const char *Cmd) { int CmdHFiClassCheckKeys(const char *Cmd) {
// empty string
if (strlen(Cmd) == 0) return usage_hf_iclass_chk();
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};
// 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;
bool use_credit_key = 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;
@ -1955,21 +1960,15 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
uint8_t *keyBlock = NULL; uint8_t *keyBlock = NULL;
iclass_premac_t *pre = NULL; iclass_premac_t *pre = NULL;
int keycnt = 0; int keycnt = 0;
// if empty string
if (strlen(Cmd) == 0) errors = true;
// time // time
uint64_t t1 = msclock(); uint64_t t1 = msclock();
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (param_getchar(Cmd, cmdp)) { switch ( tolower(param_getchar(Cmd, cmdp))) {
case 'h': case 'h':
case 'H':
return usage_hf_iclass_chk(); return usage_hf_iclass_chk();
case 'f': case 'f':
case 'F':
fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
if (fileNameLen < 1) { if (fileNameLen < 1) {
PrintAndLogEx(WARNING, "no filename found after f"); PrintAndLogEx(WARNING, "no filename found after f");
@ -1978,12 +1977,14 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
cmdp += 2; cmdp += 2;
break; break;
case 'e': case 'e':
case 'E':
use_elite = true; use_elite = true;
cmdp++; cmdp++;
break; break;
case 'c':
use_credit_key = true;
cmdp++;
break;
case 'r': case 'r':
case 'R':
use_raw = true; use_raw = true;
cmdp++; cmdp++;
break; break;
@ -2048,7 +2049,7 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
if (ukbhit()) { if (ukbhit()) {
int gc = getchar(); (void)gc; int gc = getchar(); (void)gc;
PrintAndLogEx(NORMAL, "\n[!] aborted via keyboard!\n"); PrintAndLogEx(NORMAL, "\n[!] Aborted via keyboard!\n");
goto out; goto out;
} }
@ -2059,6 +2060,12 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
lastChunk = true; lastChunk = true;
UsbCommand c = {CMD_ICLASS_CHECK_KEYS, { (lastChunk << 8), keys, 0}}; UsbCommand c = {CMD_ICLASS_CHECK_KEYS, { (lastChunk << 8), keys, 0}};
// bit 16
// - 1 indicates credit key
// - 0 indicates debit key (default)
c.arg[0] |= (use_credit_key << 16);
memcpy(c.d.asBytes, pre + i, 4 * keys); memcpy(c.d.asBytes, pre + i, 4 * keys);
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
@ -2068,7 +2075,7 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
timeout++; timeout++;
printf("."); fflush(stdout); printf("."); fflush(stdout);
if (timeout > 120) { if (timeout > 120) {
PrintAndLogEx(WARNING, "\nno response from Proxmark. Aborting..."); PrintAndLogEx(WARNING, "\nNo response from Proxmark. Aborting...");
goto out; goto out;
} }
} }
@ -2081,17 +2088,23 @@ int CmdHFiClassCheckKeys(const char *Cmd) {
case 1: { case 1: {
found_debit = true; found_debit = true;
PrintAndLogEx(NORMAL, "\n[-] Chunk [%d/%d]: %.1fs [debit] found key %s (index %u)" PrintAndLogEx(NORMAL, "\n[-] Chunk [%d/%d]: %.1fs [%s] found key %s (index %u)"
, i , i
, keycnt , keycnt
, (float)(t2/1000.0) , (float)(t2/1000.0)
, (use_credit_key) ? "credit" : "debit"
, sprint_hex(keyBlock + (i+found)*8, 8) , sprint_hex(keyBlock + (i+found)*8, 8)
, found , found
); );
break; break;
} }
case 0: { case 0: {
PrintAndLogEx(NORMAL, "\n[-] Chunk [%d/%d] : %.1fs [debit]", i, keycnt, (float)(t2/1000.0)); PrintAndLogEx(NORMAL, "\n[-] Chunk [%d/%d] : %.1fs [%s]"
, i
, keycnt
, (float)(t2/1000.0)
, (use_credit_key) ? "credit" : "debit"
);
break; break;
} }
case 99: { case 99: {
@ -2161,12 +2174,10 @@ int CmdHFiClassLookUp(const char *Cmd) {
uint64_t t1 = msclock(); uint64_t t1 = msclock();
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (param_getchar(Cmd, cmdp)) { switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h': case 'h':
case 'H':
return usage_hf_iclass_lookup(); return usage_hf_iclass_lookup();
case 'f': case 'f':
case 'F':
fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
if (fileNameLen < 1) { if (fileNameLen < 1) {
PrintAndLogEx(WARNING, "No filename found after f"); PrintAndLogEx(WARNING, "No filename found after f");
@ -2175,7 +2186,6 @@ int CmdHFiClassLookUp(const char *Cmd) {
cmdp += 2; cmdp += 2;
break; break;
case 'u': case 'u':
case 'U':
param_gethex_ex(Cmd, cmdp+1, CSN, &len); param_gethex_ex(Cmd, cmdp+1, CSN, &len);
if ( len>>1 != sizeof(CSN) ) { if ( len>>1 != sizeof(CSN) ) {
PrintAndLogEx(WARNING, "Wrong CSN length, expected %d got [%d]", sizeof(CSN), len>>1); PrintAndLogEx(WARNING, "Wrong CSN length, expected %d got [%d]", sizeof(CSN), len>>1);
@ -2184,7 +2194,6 @@ int CmdHFiClassLookUp(const char *Cmd) {
cmdp += 2; cmdp += 2;
break; break;
case 'm': case 'm':
case 'M':
param_gethex_ex(Cmd, cmdp+1, MACS, &len); param_gethex_ex(Cmd, cmdp+1, MACS, &len);
if ( len>>1 != sizeof(MACS) ) { if ( len>>1 != sizeof(MACS) ) {
PrintAndLogEx(WARNING, "Wrong MACS length, expected %d got [%d] ", sizeof(MACS), len>>1); PrintAndLogEx(WARNING, "Wrong MACS length, expected %d got [%d] ", sizeof(MACS), len>>1);
@ -2195,7 +2204,6 @@ int CmdHFiClassLookUp(const char *Cmd) {
cmdp += 2; cmdp += 2;
break; break;
case 'p': case 'p':
case 'P':
param_gethex_ex(Cmd, cmdp+1, EPURSE, &len); param_gethex_ex(Cmd, cmdp+1, EPURSE, &len);
if ( len>>1 != sizeof(EPURSE) ) { if ( len>>1 != sizeof(EPURSE) ) {
PrintAndLogEx(WARNING, "Wrong EPURSE length, expected %d got [%d] ", sizeof(EPURSE), len>>1); PrintAndLogEx(WARNING, "Wrong EPURSE length, expected %d got [%d] ", sizeof(EPURSE), len>>1);
@ -2205,12 +2213,10 @@ int CmdHFiClassLookUp(const char *Cmd) {
break; break;
break; break;
case 'e': case 'e':
case 'E':
use_elite = true; use_elite = true;
cmdp++; cmdp++;
break; break;
case 'r': case 'r':
case 'R':
use_raw = true; use_raw = true;
cmdp++; cmdp++;
break; break;
@ -2265,11 +2271,10 @@ int CmdHFiClassLookUp(const char *Cmd) {
iclass_prekey_t lookup; iclass_prekey_t lookup;
memcpy(lookup.mac, MAC_TAG, 4); memcpy(lookup.mac, MAC_TAG, 4);
// using find // binsearch
item = (iclass_prekey_t*) bsearch(&lookup, prekey, keycnt, sizeof(iclass_prekey_t), cmp_uint32); item = (iclass_prekey_t*) bsearch(&lookup, prekey, keycnt, sizeof(iclass_prekey_t), cmp_uint32);
if( item != NULL ) { if( item != NULL )
PrintAndLogEx(SUCCESS, "\n[debit] found key %s", sprint_hex(item->key, 8)); PrintAndLogEx(SUCCESS, "\n[debit] found key %s", sprint_hex(item->key, 8));
}
t1 = msclock() - t1; t1 = msclock() - t1;
PrintAndLogEx(NORMAL, "\nTime in iclass : %.0f seconds\n", (float)t1/1000.0); PrintAndLogEx(NORMAL, "\nTime in iclass : %.0f seconds\n", (float)t1/1000.0);
@ -2325,7 +2330,7 @@ int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) {
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
} }
fclose(f); fclose(f);
PrintAndLogEx(NORMAL, _BLUE_([+]) " loaded " _GREEN_(%2d) " keys from %s", *keycnt, filename); PrintAndLogEx(NORMAL, _BLUE_([+]) "Loaded " _GREEN_(%2d) " keys from %s", *keycnt, filename);
return 0; return 0;
} }