FIX: 'hf iclass sim 2'

FIX: 'hf iclass sim 4'
FIX: 'hf iclass loclass' - this fixes the bug where loclass assumes the epurse value is all zeros, while it now should save the epurse value during the simulation if it is updated/read.

I assume a empty valid epurse, while an all zero epurse is too much easy to detect as a anomaly.
This commit is contained in:
iceman1001 2018-02-04 00:52:29 +01:00
commit dc25f9212f
5 changed files with 69 additions and 65 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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]]);
}

View file

@ -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.