fix iclass simulation

This commit is contained in:
iceman1001 2020-07-13 23:27:16 +02:00
commit 4b14f21c77

View file

@ -148,8 +148,6 @@ static void CodeIClassTagSOF(void) {
// turn off afterwards // turn off afterwards
void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) {
if (DBGLEVEL > 3) Dbprintf("[+] iClass_simulate Enter");
LEDsoff(); LEDsoff();
Iso15693InitTag(); Iso15693InitTag();
@ -176,7 +174,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
doIClassSimulation(ICLASS_SIM_MODE_CSN, NULL); doIClassSimulation(ICLASS_SIM_MODE_CSN, NULL);
} else if (simType == ICLASS_SIM_MODE_READER_ATTACK) { } else if (simType == ICLASS_SIM_MODE_READER_ATTACK) {
Dbprintf("[+] going into attack mode, %d CSNS sent", numberOfCSNS); Dbprintf("going into attack mode, %d CSNS sent", numberOfCSNS);
// In this mode, a number of csns are within datain. We'll simulate each one, one at a time // 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 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. // in order to obtain the keys, as in the "dismantling iclass"-paper.
@ -204,7 +202,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
// the collected data (mac_response) is doubled out since we are trying to collect both keys in the keyroll process. // the collected data (mac_response) is doubled out since we are trying to collect both keys in the keyroll process.
// Keyroll iceman 9 csns * 8 * 2 = 144 // Keyroll iceman 9 csns * 8 * 2 = 144
// keyroll CARL55 15csns * 8 * 2 = 15 * 8 * 2 = 240 // keyroll CARL55 15csns * 8 * 2 = 15 * 8 * 2 = 240
Dbprintf("[+] going into attack keyroll mode, %d CSNS sent", numberOfCSNS); Dbprintf("going into attack keyroll mode, %d CSNS sent", numberOfCSNS);
// In this mode, a number of csns are within datain. We'll simulate each one, one at a time // 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 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. // in order to obtain the keys, as in the "dismantling iclass"-paper.
@ -218,14 +216,14 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
memcpy(emulator, datain + (i * 8), 8); memcpy(emulator, datain + (i * 8), 8);
// keyroll 1 // keyroll 1
if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) { if (doIClassSimulation(ICLASS_SIM_MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) {
reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2); reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
// Button pressed // Button pressed
goto out; goto out;
} }
// keyroll 2 // keyroll 2
if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + (i + numberOfCSNS) * EPURSE_MAC_SIZE)) { if (doIClassSimulation(ICLASS_SIM_MODE_EXIT_AFTER_MAC, mac_responses + (i + numberOfCSNS) * EPURSE_MAC_SIZE)) {
reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2); reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
// Button pressed // Button pressed
goto out; goto out;
@ -237,7 +235,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
} else { } else {
// We may want a mode here where we hardcode the csns to use (from proxclone). // We may want a mode here where we hardcode the csns to use (from proxclone).
// That will speed things up a little, but not required just yet. // That will speed things up a little, but not required just yet.
DbpString("[-] the mode is not implemented, reserved for future use"); DbpString("the mode is not implemented, reserved for future use");
} }
out: out:
@ -471,28 +469,29 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
block = receivedCmd[1]; block = receivedCmd[1];
if (cmd == ICLASS_CMD_ACTALL && len == 1) { // 0x0A if (cmd == ICLASS_CMD_ACTALL && len == 1) { // 0x0A
// Reader in anticollission phase // Reader in anti collision phase
if (chip_state != HALTED) { if (chip_state != HALTED) {
modulated_response = resp_sof; modulated_response = resp_sof;
modulated_response_size = resp_sof_len; modulated_response_size = resp_sof_len;
chip_state = ACTIVATED; chip_state = ACTIVATED;
goto send;
} }
goto send;
} else if (cmd == ICLASS_CMD_READ_OR_IDENTIFY) { // 0x0C } else if (cmd == ICLASS_CMD_READ_OR_IDENTIFY && len == 1) { // 0x0C
if (len == 1) { // Reader asks for anti collision CSN
// Reader asks for anticollission CSN
if (chip_state == SELECTED || chip_state == ACTIVATED) { if (chip_state == SELECTED || chip_state == ACTIVATED) {
modulated_response = resp_anticoll; modulated_response = resp_anticoll;
modulated_response_size = resp_anticoll_len; //order = 2; modulated_response_size = resp_anticoll_len;
trace_data = anticoll_data; trace_data = anticoll_data;
trace_data_size = sizeof(anticoll_data); trace_data_size = sizeof(anticoll_data);
}
goto send;
} else if (cmd == ICLASS_CMD_READ_OR_IDENTIFY && len == 4) { // 0x0C
if (chip_state != SELECTED) {
goto send; goto send;
} }
}
if (len == 4) {
if (chip_state == SELECTED) {
// block0,1,2,5 is always readable. // block0,1,2,5 is always readable.
switch (block) { switch (block) {
case 0: { // csn (0c 00) case 0: { // csn (0c 00)
@ -546,25 +545,42 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
CodeIso15693AsTag(trace_data, trace_data_size); CodeIso15693AsTag(trace_data, trace_data_size);
memcpy(modulated_response, ts->buf, ts->max); memcpy(modulated_response, ts->buf, ts->max);
modulated_response_size = ts->max; modulated_response_size = ts->max;
}
goto send; goto send;
} }
break;
}
} // swith } // swith
} // selected
} // if 4 } else if (cmd == ICLASS_CMD_SELECT && len == 9) { // 0x81
} else if (cmd == ICLASS_CMD_SELECT) { // 0x81
// Reader selects anticollission CSN. // Reader selects anticollission CSN.
// Tag sends the corresponding real CSN // Tag sends the corresponding real CSN
if (chip_state == ACTIVATED || chip_state == SELECTED) {
if (!memcmp(receivedCmd + 1, anticoll_data, 8)) {
modulated_response = resp_csn; modulated_response = resp_csn;
modulated_response_size = resp_csn_len; //order = 3; modulated_response_size = resp_csn_len;
trace_data = csn_data; trace_data = csn_data;
trace_data_size = sizeof(csn_data); trace_data_size = sizeof(csn_data);
chip_state = SELECTED;
} else {
chip_state = IDLE;
}
} else if (chip_state == HALTED) {
// RESELECT with CSN
if (!memcmp(receivedCmd + 1, csn_data, 8)) {
modulated_response = resp_csn;
modulated_response_size = resp_csn_len;
trace_data = csn_data;
trace_data_size = sizeof(csn_data);
chip_state = SELECTED;
}
}
goto send; goto send;
} else if (cmd == ICLASS_CMD_READCHECK) { // 0x88 } else if (cmd == ICLASS_CMD_READCHECK) { // 0x88
// Read e-purse KD (88 02) KC (18 02) // Read e-purse KD (88 02) KC (18 02)
if (chip_state == SELECTED) { if (chip_state != SELECTED) {
goto send;
}
if ( ICLASS_DEBIT(cmd) ){ if ( ICLASS_DEBIT(cmd) ){
cipher_state = &cipher_state_KD[current_page]; cipher_state = &cipher_state_KD[current_page];
diversified_key = diversified_kd; diversified_key = diversified_kd;
@ -572,15 +588,20 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
cipher_state = &cipher_state_KC[current_page]; cipher_state = &cipher_state_KC[current_page];
diversified_key = diversified_kc; diversified_key = diversified_kc;
} }
modulated_response = resp_cc; modulated_response = resp_cc;
modulated_response_size = resp_cc_len; modulated_response_size = resp_cc_len;
trace_data = card_challenge_data; trace_data = card_challenge_data;
trace_data_size = sizeof(card_challenge_data); trace_data_size = sizeof(card_challenge_data);
goto send; goto send;
} else if (cmd == ICLASS_CMD_CHECK && len == 9) { // 0x05
// Reader random and reader MAC!!!
if (chip_state != SELECTED) {
goto send;
} }
} else if (cmd == ICLASS_CMD_CHECK) { // 0x05
// Reader random and reader MAC!!!
if (simulationMode == ICLASS_SIM_MODE_FULL) { if (simulationMode == ICLASS_SIM_MODE_FULL) {
// NR, from reader, is in receivedCmd +1 // NR, from reader, is in receivedCmd +1
opt_doTagMAC_2(*cipher_state, receivedCmd + 1, data_generic_trace, diversified_key); opt_doTagMAC_2(*cipher_state, receivedCmd + 1, data_generic_trace, diversified_key);
@ -598,17 +619,18 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
modulated_response_size = 0; modulated_response_size = 0;
trace_data = NULL; trace_data = NULL;
trace_data_size = 0; trace_data_size = 0;
chip_state = HALTED;
if (simulationMode == MODE_EXIT_AFTER_MAC) { if (simulationMode == ICLASS_SIM_MODE_EXIT_AFTER_MAC) {
if (DBGLEVEL == DBG_EXTENDED) { if (DBGLEVEL == DBG_EXTENDED) {
Dbprintf("[+] CSN: %02x %02x %02x %02x %02x %02x %02x %02x", csn[0], csn[1], csn[2], csn[3], csn[4], csn[5], csn[6], csn[7]); Dbprintf("CSN: %02x %02x %02x %02x %02x %02x %02x %02x", csn[0], csn[1], csn[2], csn[3], csn[4], csn[5], csn[6], csn[7]);
Dbprintf("[+] RDR: (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x", len, Dbprintf("RDR: (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x", len,
receivedCmd[0], receivedCmd[1], receivedCmd[2], receivedCmd[0], receivedCmd[1], receivedCmd[2],
receivedCmd[3], receivedCmd[4], receivedCmd[5], receivedCmd[3], receivedCmd[4], receivedCmd[5],
receivedCmd[6], receivedCmd[7], receivedCmd[8]); receivedCmd[6], receivedCmd[7], receivedCmd[8]);
} else { } else {
Dbprintf("[+] CSN: %02x .... %02x OK", csn[0], csn[7]); Dbprintf("CSN: %02x .... %02x OK", csn[0], csn[7]);
} }
if (reader_mac_buf != NULL) { if (reader_mac_buf != NULL) {
// save NR and MAC for sim 2,4 // save NR and MAC for sim 2,4
@ -616,22 +638,26 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
} }
exit_loop = true; exit_loop = true;
} }
} }
goto send; goto send;
} else if (cmd == ICLASS_CMD_HALT && options == 0 && len == 1) { } else if (cmd == ICLASS_CMD_HALT && options == 0 && len == 1) {
if (chip_state == SELECTED) { if (chip_state != SELECTED) {
goto send;
}
// Reader ends the session // Reader ends the session
modulated_response = resp_sof; modulated_response = resp_sof;
modulated_response_size = resp_sof_len; modulated_response_size = resp_sof_len;
chip_state = HALTED; chip_state = HALTED;
goto send; goto send;
}
} else if (simulationMode == ICLASS_SIM_MODE_FULL && cmd == ICLASS_CMD_READ4 && len == 4) { // 0x06 } else if (simulationMode == ICLASS_SIM_MODE_FULL && cmd == ICLASS_CMD_READ4 && len == 4) { // 0x06
if (chip_state == SELECTED) { if (chip_state != SELECTED) {
goto send;
}
//Read block //Read block
memcpy(data_generic_trace, emulator + (current_page * page_size) + (block * 8), 8 * 4); memcpy(data_generic_trace, emulator + (current_page * page_size) + (block * 8), 8 * 4);
AddCrc(data_generic_trace, 8 * 4); AddCrc(data_generic_trace, 8 * 4);
@ -641,13 +667,14 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
memcpy(modulated_response, ts->buf, ts->max); memcpy(modulated_response, ts->buf, ts->max);
modulated_response_size = ts->max; modulated_response_size = ts->max;
goto send; goto send;
}
} else if (simulationMode == ICLASS_SIM_MODE_FULL && cmd == ICLASS_CMD_UPDATE && (len == 12 || len == 14)) { } else if (simulationMode == ICLASS_SIM_MODE_FULL && cmd == ICLASS_CMD_UPDATE && (len == 12 || len == 14)) {
// We're expected to respond with the data+crc, exactly what's already in the receivedCmd // We're expected to respond with the data+crc, exactly what's already in the receivedCmd
// receivedCmd is now UPDATE 1b | ADDRESS 1b | DATA 8b | Signature 4b or CRC 2b // receivedCmd is now UPDATE 1b | ADDRESS 1b | DATA 8b | Signature 4b or CRC 2b
if (chip_state == SELECTED) { if (chip_state != SELECTED) {
goto send;
}
if (block == 2) { // update e-purse if (block == 2) { // update e-purse
memcpy(card_challenge_data, receivedCmd + 2, 8); memcpy(card_challenge_data, receivedCmd + 2, 8);
@ -666,7 +693,9 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
} }
} }
cipher_state_KD[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kd); cipher_state_KD[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kd);
if (simulationMode == ICLASS_SIM_MODE_FULL) {
memcpy(emulator + (current_page * page_size) + (8 * 3), diversified_kd, 8);
}
} else if (block == 4) { // update Kc } else if (block == 4) { // update Kc
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
if (personalization_mode) { if (personalization_mode) {
@ -676,10 +705,13 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
} }
} }
cipher_state_KC[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kc); cipher_state_KC[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kc);
if (simulationMode == ICLASS_SIM_MODE_FULL) {
memcpy(emulator + (current_page * page_size) + (8 * 4), diversified_kc, 8);
} }
} else if (simulationMode == ICLASS_SIM_MODE_FULL) {
// update emulator // update emulator memory
memcpy(emulator + (current_page * page_size) + (8 * block), receivedCmd + 2, 8); memcpy(emulator + (current_page * page_size) + (8 * block), receivedCmd + 2, 8);
}
memcpy(data_generic_trace, receivedCmd + 2, 8); memcpy(data_generic_trace, receivedCmd + 2, 8);
AddCrc(data_generic_trace, 8); AddCrc(data_generic_trace, 8);
@ -689,15 +721,16 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
memcpy(data_response, ts->buf, ts->max); memcpy(data_response, ts->buf, ts->max);
modulated_response = data_response; modulated_response = data_response;
modulated_response_size = ts->max; modulated_response_size = ts->max;
}
goto send; goto send;
} else if (receivedCmd[0] == ICLASS_CMD_PAGESEL && len == 4) { // 0x84 } else if (cmd == ICLASS_CMD_PAGESEL && len == 4) { // 0x84
// Pagesel, // Pagesel,
// - enables to select a page in the selected chip memory and return its configuration block // - enables to select a page in the selected chip memory and return its configuration block
// Chips with a single page will not answer to this command // Chips with a single page will not answer to this command
// Otherwise, we should answer 8bytes (conf block 1) + 2bytes CRC // Otherwise, we should answer 8bytes (conf block 1) + 2bytes CRC
if (chip_state == SELECTED) { if (chip_state != SELECTED) {
goto send;
}
if (simulationMode == ICLASS_SIM_MODE_FULL && max_page > 0) { if (simulationMode == ICLASS_SIM_MODE_FULL && max_page > 0) {
@ -720,15 +753,15 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
modulated_response = data_response; modulated_response = data_response;
modulated_response_size = ts->max; modulated_response_size = ts->max;
} }
} goto send;
// } else if(receivedCmd[0] == ICLASS_CMD_DETECT) { // 0x0F // } else if(cmd == ICLASS_CMD_DETECT) { // 0x0F
} else if (receivedCmd[0] == 0x26 && len == 5) { } else if (cmd == 0x26 && len == 5) {
// standard ISO15693 INVENTORY command. Ignore. // standard ISO15693 INVENTORY command. Ignore.
} else { } else {
// Never seen this command before // Never seen this command before
if (DBGLEVEL >= DBG_EXTENDED) if (DBGLEVEL >= DBG_EXTENDED)
print_result("[-] Unhandled command received ", receivedCmd, len); print_result("Unhandled command received ", receivedCmd, len);
} }
send: send:
@ -745,7 +778,7 @@ send:
LEDsoff(); LEDsoff();
if (button_pressed) if (button_pressed)
DbpString("[+] button pressed"); DbpString("button pressed");
return button_pressed; return button_pressed;
} }