Implemented hf iclass sim -t 7

Implemented an iclass sim function that prevents simulated card responses after updating block 3.
Block 3 gets updated with the XOR key as if it was in personalization mode.
This commit is contained in:
Antiklesys 2025-06-07 23:12:21 +08:00
parent d83196fb35
commit 80e1c7f0d4
4 changed files with 32 additions and 16 deletions

View file

@ -5,8 +5,10 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
## [unreleased][unreleased]
- Updated the ATR list (@iceman1001)
- Fixed fpga binary images to use fixed seed 2 (@n-hutton)
- Changed `hf iclass sim -t 6` - implemented simulation that glitches specific block responses (@antiklesys)
- Changed `hf iclass sim -t 7` - implemented simulation that glitches key block responses (@antiklesys)
- Changed `hf iclass sim -t 6` - implemented simulation that glitches sio block (@antiklesys)
- Changed `hf iclass legbrute` - implemented multithreading support (@antiklesys)
- Changed `hf iclass legrec` - added a --sl option for further speed increase by tweaking the communication delays (@antiklesys)
- Changed `hf iclass legrec` - added a --fast option for further speed increase and automated AA2 block selection (@antiklesys)
- Changed `hf iclass legrec` - additional code optimizations gaining a ~147% speed increase (@antiklesys)
- Changed `hf iclass tear` - readability improvements for erase phase (@antiklesys)

View file

@ -196,7 +196,7 @@ void iclass_simulate(uint8_t sim_type, uint8_t num_csns, bool send_reply, uint8_
if (send_reply)
reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i, 0, mac_responses, i * EPURSE_MAC_SIZE);
} else if (sim_type == ICLASS_SIM_MODE_FULL || sim_type == ICLASS_SIM_MODE_FULL_GLITCH) {
} else if (sim_type == ICLASS_SIM_MODE_FULL || sim_type == ICLASS_SIM_MODE_FULL_GLITCH || sim_type == ICLASS_SIM_MODE_FULL_GLITCH_KEY) {
//This is 'full sim' mode, where we use the emulator storage for data.
//ie: BigBuf_get_EM_addr should be previously filled with data from the "eload" command
@ -328,7 +328,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
// AIA
uint8_t aia_data[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00};
if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) {
if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) {
memcpy(conf_block, emulator + (8 * 1), 8); // blk 1
memcpy(card_challenge_data, emulator + (8 * 2), 8); // e-purse, blk 2
@ -367,7 +367,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
cipher_state_KD[0] = opt_doTagMAC_1(card_challenge_data, diversified_kd);
cipher_state_KC[0] = opt_doTagMAC_1(card_challenge_data, diversified_kc);
if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) {
if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) {
for (int i = 1; i < max_page; i++) {
@ -380,6 +380,8 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
}
}
bool glitch_key_read = false;
// Anti-collision process:
// Reader 0a
// Tag 0f
@ -600,7 +602,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
goto send;
}
} // switch
} else if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) {
} else if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) {
if (block == 3 || block == 4) { // Kd, Kc, always respond with 0xff bytes
modulated_response = resp_ff;
modulated_response_size = resp_ff_len;
@ -663,7 +665,12 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
goto send;
}
if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) {
if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) {
if(glitch_key_read){
goto send;
}
// NR, from reader, is in receivedCmd +1
opt_doTagMAC_2(*cipher_state, receivedCmd + 1, data_generic_trace, diversified_key);
@ -730,7 +737,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
chip_state = HALTED;
goto send;
} else if ((simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) && cmd == ICLASS_CMD_READ4 && len == 4) { // 0x06
} else if ((simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) && cmd == ICLASS_CMD_READ4 && len == 4) { // 0x06
if (chip_state != SELECTED) {
goto send;
@ -771,20 +778,24 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
resp_cc_len = ts->max;
cipher_state_KD[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kd);
cipher_state_KC[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kc);
if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) {
if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) {
memcpy(emulator + (current_page * page_size) + (8 * 2), card_challenge_data, 8);
}
} else if (block == 3) { // update Kd
for (int i = 0; i < 8; i++) {
if (personalization_mode) {
if (personalization_mode || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) {
diversified_kd[i] = receivedCmd[2 + i];
} else {
diversified_kd[i] ^= receivedCmd[2 + i];
}
}
cipher_state_KD[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kd);
if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) {
if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) {
memcpy(emulator + (current_page * page_size) + (8 * 3), diversified_kd, 8);
if(simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY){
glitch_key_read = true;
goto send;
}
}
} else if (block == 4) { // update Kc
for (int i = 0; i < 8; i++) {
@ -795,10 +806,10 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
}
}
cipher_state_KC[current_page] = opt_doTagMAC_1(card_challenge_data, diversified_kc);
if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) {
if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) {
memcpy(emulator + (current_page * page_size) + (8 * 4), diversified_kc, 8);
}
} else if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) {
} else if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) {
// update emulator memory
memcpy(emulator + (current_page * page_size) + (8 * block), receivedCmd + 2, 8);
}
@ -838,7 +849,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
goto send;
}
if ((simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) && max_page > 0) {
if ((simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) && max_page > 0) {
// if on 2k, always ignore 3msb, & 0x1F)
uint8_t page = receivedCmd[1] & 0x1F;

View file

@ -845,7 +845,8 @@ static int CmdHFiClassSim(const char *Cmd) {
"hf iclass sim -t 2 --> execute loclass attack online part\n"
"hf iclass sim -t 3 --> simulate full iCLASS 2k tag\n"
"hf iclass sim -t 4 --> Reader-attack, adapted for KeyRoll mode, gather reader responses to extract elite key\n"
"hf iclass sim -t 6 --> simulate full iCLASS 2k tag that doesn't respond to r/w requests to the last SIO block");
"hf iclass sim -t 6 --> simulate full iCLASS 2k tag that doesn't respond to r/w requests to the last SIO block\n"
"hf iclass sim -t 7 --> simulate full iCLASS 2k tag that doesn't XOR or respond to r/w requests on block 3");
void *argtable[] = {
arg_param_begin,
@ -876,7 +877,7 @@ static int CmdHFiClassSim(const char *Cmd) {
CLIParserFree(ctx);
if (sim_type > 4 && sim_type != 6) {
if (sim_type > 4 && sim_type != 6 && sim_type != 7) {
PrintAndLogEx(ERR, "Undefined simtype %d", sim_type);
return PM3_EINVARG;
}
@ -1030,6 +1031,7 @@ static int CmdHFiClassSim(const char *Cmd) {
case ICLASS_SIM_MODE_CSN_DEFAULT:
case ICLASS_SIM_MODE_FULL:
case ICLASS_SIM_MODE_FULL_GLITCH:
case ICLASS_SIM_MODE_FULL_GLITCH_KEY:
default: {
PrintAndLogEx(INFO, "Starting iCLASS simulation");
PrintAndLogEx(INFO, "Press " _GREEN_("`pm3 button`") " to abort");
@ -1037,7 +1039,7 @@ static int CmdHFiClassSim(const char *Cmd) {
clearCommandBuffer();
SendCommandMIX(CMD_HF_ICLASS_SIMULATE, sim_type, numberOfCSNs, 1, csn, 8);
if (sim_type == ICLASS_SIM_MODE_FULL || sim_type == ICLASS_SIM_MODE_FULL_GLITCH)
if (sim_type == ICLASS_SIM_MODE_FULL || sim_type == ICLASS_SIM_MODE_FULL_GLITCH || sim_type == ICLASS_SIM_MODE_FULL_GLITCH_KEY)
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf iclass esave -h") "` to save the emulator memory to file");
break;
}

View file

@ -49,6 +49,7 @@
#define ICLASS_SIM_MODE_READER_ATTACK_KEYROLL 4
#define ICLASS_SIM_MODE_EXIT_AFTER_MAC 5 // note: device internal only
#define ICLASS_SIM_MODE_FULL_GLITCH 6
#define ICLASS_SIM_MODE_FULL_GLITCH_KEY 7
// iCLASS auth request data structure