Merge pull request #2887 from Antiklesys/master

Implemented a hf iclass sim variation
This commit is contained in:
Iceman 2025-06-06 20:27:27 +02:00 committed by GitHub
commit 32e29d9340
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 35 additions and 22 deletions

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased] ## [unreleased][unreleased]
- Changed `hf iclass sim` - implemented a sim -t 3 variation that glitches specific block responses (@antiklesys)
- Changed `hf iclass legbrute` - implemented multithreading support (@antiklesys) - Changed `hf iclass legbrute` - implemented multithreading support (@antiklesys)
- Changed `hf iclass legrec` - added a --fast option for further speed increase and automated AA2 block selection (@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 legrec` - additional code optimizations gaining a ~147% speed increase (@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) if (send_reply)
reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i, 0, mac_responses, i * EPURSE_MAC_SIZE); reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i, 0, mac_responses, i * EPURSE_MAC_SIZE);
} else if (sim_type == ICLASS_SIM_MODE_FULL) { } else if (sim_type == ICLASS_SIM_MODE_FULL || sim_type == ICLASS_SIM_MODE_FULL_GLITCH) {
//This is 'full sim' mode, where we use the emulator storage for data. //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 //ie: BigBuf_get_EM_addr should be previously filled with data from the "eload" command
@ -205,19 +205,13 @@ void iclass_simulate(uint8_t sim_type, uint8_t num_csns, bool send_reply, uint8_
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
do_iclass_simulation_nonsec(); do_iclass_simulation_nonsec();
} else { } else {
do_iclass_simulation(ICLASS_SIM_MODE_FULL, NULL); do_iclass_simulation(sim_type, NULL);
} }
if (send_reply) { if (send_reply) {
reply_mix(CMD_ACK, CMD_HF_ICLASS_SIMULATE, 0, 0, NULL, 0); reply_mix(CMD_ACK, CMD_HF_ICLASS_SIMULATE, 0, 0, NULL, 0);
} }
} else if (sim_type == ICLASS_SIM_MODE_CONFIG_CARD) {
// config card
do_iclass_simulation(ICLASS_SIM_MODE_FULL, NULL);
// swap bin
} else if (sim_type == ICLASS_SIM_MODE_READER_ATTACK_KEYROLL) { } else if (sim_type == ICLASS_SIM_MODE_READER_ATTACK_KEYROLL) {
// This is the KEYROLL version of sim 2. // This is the KEYROLL version of sim 2.
@ -334,7 +328,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
// AIA // AIA
uint8_t aia_data[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00}; uint8_t aia_data[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00};
if (simulationMode == ICLASS_SIM_MODE_FULL) { if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) {
memcpy(conf_block, emulator + (8 * 1), 8); // blk 1 memcpy(conf_block, emulator + (8 * 1), 8); // blk 1
memcpy(card_challenge_data, emulator + (8 * 2), 8); // e-purse, blk 2 memcpy(card_challenge_data, emulator + (8 * 2), 8); // e-purse, blk 2
@ -373,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_KD[0] = opt_doTagMAC_1(card_challenge_data, diversified_kd);
cipher_state_KC[0] = opt_doTagMAC_1(card_challenge_data, diversified_kc); cipher_state_KC[0] = opt_doTagMAC_1(card_challenge_data, diversified_kc);
if (simulationMode == ICLASS_SIM_MODE_FULL) { if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) {
for (int i = 1; i < max_page; i++) { for (int i = 1; i < max_page; i++) {
@ -606,13 +600,21 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
goto send; goto send;
} }
} // switch } // switch
} else if (simulationMode == ICLASS_SIM_MODE_FULL) { } else if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) {
if (block == 3 || block == 4) { // Kd, Kc, always respond with 0xff bytes if (block == 3 || block == 4) { // Kd, Kc, always respond with 0xff bytes
modulated_response = resp_ff; modulated_response = resp_ff;
modulated_response_size = resp_ff_len; modulated_response_size = resp_ff_len;
trace_data = ff_data; trace_data = ff_data;
trace_data_size = sizeof(ff_data); trace_data_size = sizeof(ff_data);
} else { // use data from emulator memory } else { // use data from emulator memory
if (simulationMode == ICLASS_SIM_MODE_FULL_GLITCH){
uint8_t block_check[8] ={0};
memcpy(block_check, emulator + (current_page * page_size) + (31 * 8), 8);
if (block == block_check[7]){
goto send;
}
}
memcpy(data_generic_trace, emulator + (current_page * page_size) + (block * 8), 8); memcpy(data_generic_trace, emulator + (current_page * page_size) + (block * 8), 8);
AddCrc(data_generic_trace, 8); AddCrc(data_generic_trace, 8);
trace_data = data_generic_trace; trace_data = data_generic_trace;
@ -655,7 +657,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
goto send; goto send;
} }
if (simulationMode == ICLASS_SIM_MODE_FULL) { if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) {
// 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);
@ -722,7 +724,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
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 || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH)&& cmd == ICLASS_CMD_READ4 && len == 4) { // 0x06
if (chip_state != SELECTED) { if (chip_state != SELECTED) {
goto send; goto send;
@ -763,7 +765,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
resp_cc_len = ts->max; resp_cc_len = ts->max;
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);
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) { if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) {
memcpy(emulator + (current_page * page_size) + (8 * 2), card_challenge_data, 8); memcpy(emulator + (current_page * page_size) + (8 * 2), card_challenge_data, 8);
} }
} else if (block == 3) { // update Kd } else if (block == 3) { // update Kd
@ -775,7 +777,7 @@ int do_iclass_simulation(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) { if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) {
memcpy(emulator + (current_page * page_size) + (8 * 3), diversified_kd, 8); memcpy(emulator + (current_page * page_size) + (8 * 3), diversified_kd, 8);
} }
} else if (block == 4) { // update Kc } else if (block == 4) { // update Kc
@ -787,14 +789,22 @@ int do_iclass_simulation(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) { if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) {
memcpy(emulator + (current_page * page_size) + (8 * 4), diversified_kc, 8); memcpy(emulator + (current_page * page_size) + (8 * 4), diversified_kc, 8);
} }
} else if (simulationMode == ICLASS_SIM_MODE_FULL) { } else if (simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH) {
// update emulator memory // 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);
} }
if (simulationMode == ICLASS_SIM_MODE_FULL_GLITCH){
uint8_t block_check[8] ={0};
memcpy(block_check, emulator + (current_page * page_size) + (31 * 8), 8);
if (block == block_check[7]){
goto send;
}
}
memcpy(data_generic_trace, receivedCmd + 2, 8); memcpy(data_generic_trace, receivedCmd + 2, 8);
AddCrc(data_generic_trace, 8); AddCrc(data_generic_trace, 8);
trace_data = data_generic_trace; trace_data = data_generic_trace;
@ -814,7 +824,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
goto send; goto send;
} }
if (simulationMode == ICLASS_SIM_MODE_FULL && max_page > 0) { if ((simulationMode == ICLASS_SIM_MODE_FULL || simulationMode == ICLASS_SIM_MODE_FULL_GLITCH)&& max_page > 0) {
// if on 2k, always ignore 3msb, & 0x1F) // if on 2k, always ignore 3msb, & 0x1F)
uint8_t page = receivedCmd[1] & 0x1F; uint8_t page = receivedCmd[1] & 0x1F;

View file

@ -844,7 +844,8 @@ static int CmdHFiClassSim(const char *Cmd) {
"hf iclass sim -t 1 --> simulate with default CSN\n" "hf iclass sim -t 1 --> simulate with default CSN\n"
"hf iclass sim -t 2 --> execute loclass attack online part\n" "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 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"); "hf iclass sim -t 4 --> Reader-attack, adapted for KeyRoll mode, gather reader responses to extract elite key\n"
"hf iclass sim -t 6 --> same as -t 3, but doesn't respond to r/w for the block specified in last byte of blk 31");
void *argtable[] = { void *argtable[] = {
arg_param_begin, arg_param_begin,
@ -875,7 +876,7 @@ static int CmdHFiClassSim(const char *Cmd) {
CLIParserFree(ctx); CLIParserFree(ctx);
if (sim_type > 4) { if (sim_type > 4 && sim_type != 6) {
PrintAndLogEx(ERR, "Undefined simtype %d", sim_type); PrintAndLogEx(ERR, "Undefined simtype %d", sim_type);
return PM3_EINVARG; return PM3_EINVARG;
} }
@ -1028,6 +1029,7 @@ static int CmdHFiClassSim(const char *Cmd) {
case ICLASS_SIM_MODE_CSN: case ICLASS_SIM_MODE_CSN:
case ICLASS_SIM_MODE_CSN_DEFAULT: case ICLASS_SIM_MODE_CSN_DEFAULT:
case ICLASS_SIM_MODE_FULL: case ICLASS_SIM_MODE_FULL:
case ICLASS_SIM_MODE_FULL_GLITCH:
default: { default: {
PrintAndLogEx(INFO, "Starting iCLASS simulation"); PrintAndLogEx(INFO, "Starting iCLASS simulation");
PrintAndLogEx(INFO, "Press " _GREEN_("`pm3 button`") " to abort"); PrintAndLogEx(INFO, "Press " _GREEN_("`pm3 button`") " to abort");
@ -1035,7 +1037,7 @@ static int CmdHFiClassSim(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_ICLASS_SIMULATE, sim_type, numberOfCSNs, 1, csn, 8); SendCommandMIX(CMD_HF_ICLASS_SIMULATE, sim_type, numberOfCSNs, 1, csn, 8);
if (sim_type == ICLASS_SIM_MODE_FULL) if (sim_type == ICLASS_SIM_MODE_FULL || sim_type == ICLASS_SIM_MODE_FULL_GLITCH)
PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf iclass esave -h") "` to save the emulator memory to file"); PrintAndLogEx(HINT, "Hint: Try `" _YELLOW_("hf iclass esave -h") "` to save the emulator memory to file");
break; break;
} }

View file

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