diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 6829fba36..2527f8c7d 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -1159,19 +1159,20 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain // In this mode, a number of csns are within datain. We'll simulate each one, one at a time // in order to collect MAC's from the reader. This can later be used in an offlne-attack // in order to obtain the keys, as in the "dismantling iclass"-paper. + #define EPURSE_MAC_SIZE 16 int i = 0; - for (; i < numberOfCSNS && i*8 + 8 < USB_CMD_DATA_SIZE; i++) { + for (; i < numberOfCSNS && i * EPURSE_MAC_SIZE + 8 < USB_CMD_DATA_SIZE; i++) { // The usb data is 512 bytes, fitting 65 8-byte CSNs in there. memcpy(emulator, datain + (i*8), 8); - if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses+i*8)) { + if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses+i * EPURSE_MAC_SIZE)) { // Button pressed - cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i*8); + cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i * EPURSE_MAC_SIZE); goto out; } } - cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i*8); + cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i * EPURSE_MAC_SIZE); } else if (simType == 3){ //This is 'full sim' mode, where we use the emulator storage for data. @@ -1192,26 +1193,26 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain // attack below is same as SIM 2, but we run the CSN twice to collected the mac for both keys. int i = 0; // The usb data is 512 bytes, fitting 65 8-byte CSNs in there. iceman fork uses 9 CSNS - for (; i < numberOfCSNS && i*8 + 8 < USB_CMD_DATA_SIZE; i++) { + for (; i < numberOfCSNS && i * EPURSE_MAC_SIZE + 8 < USB_CMD_DATA_SIZE; i++) { memcpy(emulator, datain + (i*8), 8); // keyroll 1 - if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i*8 )) { - cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * 8 * 2); + if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE )) { + cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2); // Button pressed goto out; } // keyroll 2 - if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + (i + numberOfCSNS) * 8 )) { - cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * 8 * 2); + if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + (i + numberOfCSNS) * EPURSE_MAC_SIZE )) { + cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * EPURSE_MAC_SIZE* 2); // Button pressed goto out; } } // double the amount of collected data. - cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * 8 * 2 ); + cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2 ); } else { // We may want a mode here where we hardcode the csns to use (from proxclone). @@ -1255,6 +1256,7 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { uint8_t diversified_key[8] = { 0 }; // e-Purse uint8_t card_challenge_data[8] = { 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; + //uint8_t card_challenge_data[8] = { 0 }; if (simulationMode == MODE_FULLSIM) { //The diversified key should be stored on block 3 //Get the diversified key from emulator memory @@ -1265,7 +1267,11 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { //Precalculate the cipher state, feeding it the CC cipher_state = opt_doTagMAC_1(card_challenge_data, diversified_key); } - + // set epurse of sim2,4 attack + if (reader_mac_buf != NULL) { + memcpy(reader_mac_buf, card_challenge_data, 8); + } + int exitLoop = 0; // Reader 0a // Tag 0f @@ -1320,50 +1326,26 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { // First card answer: SOF CodeIClassTagSOF(); memcpy(resp_sof, ToSend, ToSendMax); resp_sof_Len = ToSendMax; - // if ( MF_DBGLEVEL == MF_DBG_EXTENDED) { - // DbpString("SOF"); - // PrintToSendBuffer(); - // } // Anticollision CSN CodeIClassTagAnswer(anticoll_data, sizeof(anticoll_data)); memcpy(resp_anticoll, ToSend, ToSendMax); resp_anticoll_len = ToSendMax; - // if ( MF_DBGLEVEL == MF_DBG_EXTENDED) { - // DbpString("ANTI COLL CSN"); - // PrintToSendBuffer(); - // } // CSN CodeIClassTagAnswer(csn_data, sizeof(csn_data)); memcpy(resp_csn, ToSend, ToSendMax); resp_csn_len = ToSendMax; - // if ( MF_DBGLEVEL == MF_DBG_EXTENDED) { - // DbpString("CSN"); - // PrintToSendBuffer(); - // } // Configuration CodeIClassTagAnswer(conf_data, sizeof(conf_data)); memcpy(resp_conf, ToSend, ToSendMax); resp_conf_len = ToSendMax; - // if ( MF_DBGLEVEL == MF_DBG_EXTENDED) { - // DbpString("Configuration"); - // PrintToSendBuffer(); - // } // e-Purse CodeIClassTagAnswer(card_challenge_data, sizeof(card_challenge_data)); memcpy(resp_cc, ToSend, ToSendMax); resp_cc_len = ToSendMax; - // if ( MF_DBGLEVEL == MF_DBG_EXTENDED) { - // DbpString("e-Purse"); - // PrintToSendBuffer(); - // } // Application Issuer Area CodeIClassTagAnswer(aia_data, sizeof(aia_data)); memcpy(resp_aia, ToSend, ToSendMax); resp_aia_len = ToSendMax; - // if ( MF_DBGLEVEL == MF_DBG_EXTENDED) { - // DbpString("Application Issuer Data"); - // PrintToSendBuffer(); - // } //This is used for responding to READ-block commands or other data which is dynamically generated //First the 'trace'-data, not encoded for FPGA @@ -1435,6 +1417,10 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { modulated_response = resp_cc; modulated_response_size = resp_cc_len; trace_data = card_challenge_data; trace_data_size = sizeof(card_challenge_data); + // set epurse of sim2,4 attack + if (reader_mac_buf != NULL) { + memcpy(reader_mac_buf, card_challenge_data, 8); + } break; case 5:// Application Issuer Area (0c 05) modulated_response = resp_aia; modulated_response_size = resp_aia_len; @@ -1498,7 +1484,7 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { Dbprintf("[+] CSN: %02x .... %02x OK", csn[0], csn[7]); } if (reader_mac_buf != NULL) { - memcpy(reader_mac_buf, receivedCmd+1, 8); + memcpy(reader_mac_buf + 8, receivedCmd+1, 8); } exitLoop = true; } diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index e512983dc..407cbd1aa 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -238,8 +238,11 @@ int usage_hf_iclass_lookup(void) { PrintAndLog(" u CSN"); PrintAndLog(" p EPURSE"); PrintAndLog(" m macs"); + PrintAndLog(" r raw"); + PrintAndLog(" e elite"); PrintAndLog("Samples:"); PrintAndLog(" hf iclass lookup u 9655a400f8ff12e0 p f0ffffffffffffff m 0000000089cb984b f default_iclass_keys.dic"); + PrintAndLog(" hf iclass lookup u 9655a400f8ff12e0 p f0ffffffffffffff m 0000000089cb984b f default_iclass_keys.dic e"); return 0; } @@ -360,7 +363,7 @@ int CmdHFiClassSim(const char *Cmd) { PrintAndLog("[+] press keyboard to cancel"); UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType, NUM_CSNS}}; UsbCommand resp = {0}; - memcpy(c.d.asBytes, csns, 8*NUM_CSNS); + memcpy(c.d.asBytes, csns, 8 * NUM_CSNS); clearCommandBuffer(); SendCommand(&c); @@ -390,13 +393,16 @@ int CmdHFiClassSim(const char *Cmd) { return 2; } - memset(dump, 0, datalen);//<-- Need zeroes for the CC-field + memset(dump, 0, datalen);//<-- Need zeroes for the EPURSE - field (offical) + uint8_t i = 0; for (i = 0 ; i < NUM_CSNS ; i++) { //copy CSN memcpy(dump + i*24, csns + i*8, 8); - //8 zero bytes here then comes NR_MAC (eight bytes from the response) ( 8b csn + 8 empty== 16) - memcpy(dump + i*24 + 16, resp.d.asBytes + i*8, 8); + //copy epurse + memcpy(dump + i*24 + 8, resp.d.asBytes + i*16, 8); + // NR_MAC (eight bytes from the response) ( 8b csn + 8b epurse == 16) + memcpy(dump + i*24 + 16, resp.d.asBytes + i*16 + 8, 8); } /** Now, save to dumpfile **/ saveFile("iclass_mac_attack", "bin", dump, datalen); @@ -445,10 +451,12 @@ int CmdHFiClassSim(const char *Cmd) { //Need zeroes for the CC-field memset(dump, 0, datalen); for (uint8_t i = 0; i < NUM_CSNS ; i++) { - // Copy CSN + // copy CSN memcpy(dump + i*MAC_ITEM_SIZE, csns + i*8, 8); //CSN - //8 zero bytes here then comes NR_MAC (eight bytes from the response) ( 8b csn + 8 empty== 16) - memcpy(dump + i*MAC_ITEM_SIZE + 16, resp.d.asBytes + i*8, 8); + // copy EPURSE + memcpy(dump + i*MAC_ITEM_SIZE + 8, resp.d.asBytes + i * 16, 8); + // copy NR_MAC (eight bytes from the response) ( 8b csn + 8b epurse == 16) + memcpy(dump + i*MAC_ITEM_SIZE + 16, resp.d.asBytes + i * 16 + 8, 8); } saveFile("iclass_mac_attack_keyroll_A", "bin", dump, datalen); @@ -456,11 +464,13 @@ int CmdHFiClassSim(const char *Cmd) { memset(dump, 0, datalen); uint8_t resp_index = 0; for (uint8_t i = 0; i < NUM_CSNS; i++) { - resp_index = (i + NUM_CSNS) * 8; + resp_index = (i + NUM_CSNS) * 16; // Copy CSN memcpy(dump + i*MAC_ITEM_SIZE, csns + i*8, 8); - //8 zero bytes here then comes NR_MAC (eight bytes from the response) ( 8b csn + 8 empty== 16) - memcpy(dump + i*MAC_ITEM_SIZE + 16, resp.d.asBytes + resp_index, 8); + // copy EPURSE + memcpy(dump + i*MAC_ITEM_SIZE + 8, resp.d.asBytes + resp_index, 8); + // copy NR_MAC (eight bytes from the response) ( 8b csn + 8 epurse == 16) + memcpy(dump + i*MAC_ITEM_SIZE + 16, resp.d.asBytes + resp_index + 8, 8); resp_index++; } saveFile("iclass_mac_attack_keyroll_B", "bin", dump, datalen); @@ -800,9 +810,9 @@ static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool v if (CCNR != NULL) memcpy(CCNR, data+16, 8); - // if (isOK > 0) { - // if (verbose) PrintAndLog("CSN: %s",sprint_hex(CSN,8)); - // } + if (isOK > 0) { + PrintAndLog("CCNR: %s MISSING NCN",sprint_hex(CCNR, 8)); + } if (isOK <= 1){ PrintAndLog("(%d) Failed to obtain CC! Aborting...", isOK); @@ -1926,6 +1936,8 @@ int CmdHFiClassCheckKeys(const char *Cmd) { } PrintAndLog("[+] Generating diversified keys and MAC"); + PrintAndLog("[+] CSN | %s", sprint_hex( CSN, sizeof(CSN) )); + PrintAndLog("[+] CCNR | %s", sprint_hex( CCNR, sizeof(CCNR) )); res = GenerateMacFromKeyFile( CSN, CCNR, use_raw, use_elite, keyBlock, keycnt, pre ); if ( res > 0) { free(keyBlock); @@ -2039,6 +2051,7 @@ int CmdHFiClassLookUp(const char *Cmd) { uint8_t CSN[8]; uint8_t EPURSE[8]; uint8_t MACS[8]; + uint8_t CCNR[12]; uint8_t MAC_TAG[4] = {0x00,0x00,0x00,0x00}; // elite key, raw key, standard key @@ -2122,10 +2135,15 @@ int CmdHFiClassLookUp(const char *Cmd) { if (errors) return usage_hf_iclass_lookup(); - PrintAndLog("[+] CSN %s", sprint_hex( CSN, sizeof(CSN) )); - PrintAndLog("[+] Epurse %s", sprint_hex( EPURSE, sizeof(EPURSE) )); - PrintAndLog("[+] MACS %s", sprint_hex( MACS, sizeof(MACS) )); - PrintAndLog("[+] MAC_TAG %s", sprint_hex( MAC_TAG, sizeof(MAC_TAG) )); + // stupid copy.. CCNR is a combo of epurse and reader nonce + memcpy(CCNR, EPURSE, 8); + memcpy(CCNR+8, MACS, 4); + + PrintAndLog("[+] CSN | %s", sprint_hex( CSN, sizeof(CSN) )); + PrintAndLog("[+] Epurse | %s", sprint_hex( EPURSE, sizeof(EPURSE) )); + PrintAndLog("[+] MACS | %s", sprint_hex( MACS, sizeof(MACS) )); + PrintAndLog("[+] CCNR | %s", sprint_hex( CCNR, sizeof(CCNR) )); + PrintAndLog("[+] MAC_TAG | %s", sprint_hex( MAC_TAG, sizeof(MAC_TAG) )); int res = LoadDictionaryKeyFile( filename, &keyBlock, &keycnt); if ( res > 0) { @@ -2140,7 +2158,7 @@ int CmdHFiClassLookUp(const char *Cmd) { } PrintAndLog("[-] Generating diversified keys and MAC"); - res = GenerateFromKeyFile( CSN, EPURSE, use_raw, use_elite, keyBlock, keycnt, prekey ); + res = GenerateFromKeyFile( CSN, CCNR, use_raw, use_elite, keyBlock, keycnt, prekey ); if ( res > 0) { free(keyBlock); free(prekey); diff --git a/client/loclass/cipher.c b/client/loclass/cipher.c index 0790bfb51..862345cce 100644 --- a/client/loclass/cipher.c +++ b/client/loclass/cipher.c @@ -226,17 +226,17 @@ void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) uint8_t div_key[8]; //cc_nr=(uint8_t*)malloc(length+1); - memcpy(cc_nr,cc_nr_p,12); - memcpy(div_key,div_key_p,8); + memcpy(cc_nr, cc_nr_p, 12); + memcpy(div_key, div_key_p, 8); - reverse_arraybytes(cc_nr,12); - BitstreamIn bitstream = {cc_nr,12 * 8,0}; + reverse_arraybytes(cc_nr, 12); + BitstreamIn bitstream = {cc_nr, 12 * 8, 0}; uint8_t dest []= {0,0,0,0,0,0,0,0}; BitstreamOut out = { dest, sizeof(dest)*8, 0 }; MAC(div_key,bitstream, out); //The output MAC must also be reversed reverse_arraybytes(dest, sizeof(dest)); - memcpy(mac,dest,4); + memcpy(mac, dest, 4); //free(cc_nr); return; } diff --git a/client/loclass/elite_crack.c b/client/loclass/elite_crack.c index 40005ecfa..a8aa82521 100644 --- a/client/loclass/elite_crack.c +++ b/client/loclass/elite_crack.c @@ -271,9 +271,9 @@ int _readFromDump(uint8_t dump[], dumpdata* item, uint8_t i) { memcpy(item, dump+i*itemsize, itemsize); if (true) { - printvar("csn", item->csn,8); - printvar("cc_nr", item->cc_nr,12); - printvar("mac", item->mac,4); + printvar("csn", item->csn, sizeof(item->csn)); + printvar("cc_nr", item->cc_nr, sizeof(item->cc_nr)); + printvar("mac", item->mac, sizeof(item->mac)); } return 0; } @@ -355,6 +355,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) { prnlog("[+] Bruteforcing byte %d", bytes_to_recover[i]); while (!found && !(brute & endmask)) { + //Update the keytable with the brute-values for (i=0; i < numbytes_to_recover; i++) { keytable[bytes_to_recover[i]] &= 0xFF00; @@ -380,7 +381,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) { // success if (memcmp(calculated_MAC, item.mac, 4) == 0) { - //printf("\r\n"); + printf("\r\n"); for (i =0 ; i < numbytes_to_recover; i++) { prnlog("[=] %d: 0x%02x", bytes_to_recover[i], 0xFF & keytable[bytes_to_recover[i]]); } diff --git a/client/loclass/elite_crack.h b/client/loclass/elite_crack.h index 46791fb5d..5413d84d0 100644 --- a/client/loclass/elite_crack.h +++ b/client/loclass/elite_crack.h @@ -84,8 +84,7 @@ typedef struct { uint8_t csn[8]; uint8_t cc_nr[12]; uint8_t mac[4]; - -}dumpdata; +} dumpdata; /** * @brief Performs brute force attack against a dump-data item, containing csn, cc_nr and mac.