diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 52f4e30a6..e5af92dd4 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -2663,7 +2663,12 @@ static void PacketReceived(PacketCommandNG *packet) { struct p *payload = (struct p *) packet->data.asBytes; */ - SimulateIClass(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes); + if (packet->length < sizeof(iclass_sim_t)) { + reply_ng(CMD_HF_ICLASS_SIMULATE, PM3_EINVARG, NULL, 0); + break; + } + iclass_sim_t *payload = (iclass_sim_t *)packet->data.asBytes; + iclass_simulate(payload->sim_type, payload->num_csns, payload->send_reply, true, payload->csns, NULL, NULL); break; } case CMD_HF_ICLASS_READER: { diff --git a/armsrc/iclass.c b/armsrc/iclass.c index ff93e2872..1679a8f49 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -138,8 +138,15 @@ static void CodeIClassTagSOF(void) { * @param datain */ // turn off afterwards -void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { - iclass_simulate(arg0, arg1, arg2, true, datain, NULL, NULL); + +static void reply_iclass_sim(uint16_t num_mac, const uint8_t *macs, uint16_t maclen) { + uint8_t respbuf[sizeof(iclass_sim_resp_t) + PM3_CMD_DATA_SIZE] = {0}; + iclass_sim_resp_t *response = (iclass_sim_resp_t *)respbuf; + response->num_mac = num_mac; + if (maclen && macs) { + memcpy(response->mac, macs, maclen); + } + reply_ng(CMD_HF_ICLASS_SIMULATE, PM3_SUCCESS, respbuf, sizeof(iclass_sim_resp_t) + maclen); } void iclass_simulate(uint8_t sim_type, uint8_t num_csns, bool send_reply, bool trace, uint8_t *datain, uint8_t *dataout, uint16_t *dataoutlen) { @@ -187,7 +194,7 @@ void iclass_simulate(uint8_t sim_type, uint8_t num_csns, bool send_reply, bool t // Button pressed if (send_reply) - reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i, 0, mac_responses, i * EPURSE_MAC_SIZE); + reply_iclass_sim(i, mac_responses, i * EPURSE_MAC_SIZE); goto out; } } @@ -195,7 +202,7 @@ void iclass_simulate(uint8_t sim_type, uint8_t num_csns, bool send_reply, bool t *dataoutlen = i * EPURSE_MAC_SIZE; if (send_reply) - reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i, 0, mac_responses, i * EPURSE_MAC_SIZE); + reply_iclass_sim(i, mac_responses, i * EPURSE_MAC_SIZE); } else if (sim_type == ICLASS_SIM_MODE_FULL || sim_type == ICLASS_SIM_MODE_FULL_GLITCH || sim_type == ICLASS_SIM_MODE_FULL_GLITCH_KEY || sim_type == ICLASS_SIM_MODE_FULL_LIVE) { @@ -210,7 +217,7 @@ void iclass_simulate(uint8_t sim_type, uint8_t num_csns, bool send_reply, bool t } if (send_reply) { - reply_mix(CMD_ACK, CMD_HF_ICLASS_SIMULATE, 0, 0, NULL, 0); + reply_iclass_sim(0, NULL, 0); } } else if (sim_type == ICLASS_SIM_MODE_READER_ATTACK_KEYROLL) { @@ -239,7 +246,7 @@ void iclass_simulate(uint8_t sim_type, uint8_t num_csns, bool send_reply, bool t *dataoutlen = i * EPURSE_MAC_SIZE * 2; if (send_reply) - reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2); + reply_iclass_sim(i * 2, mac_responses, i * EPURSE_MAC_SIZE * 2); // Button pressed goto out; @@ -252,7 +259,7 @@ void iclass_simulate(uint8_t sim_type, uint8_t num_csns, bool send_reply, bool t *dataoutlen = i * EPURSE_MAC_SIZE * 2; if (send_reply) - reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2); + reply_iclass_sim(i * 2, mac_responses, i * EPURSE_MAC_SIZE * 2); // Button pressed goto out; @@ -264,7 +271,7 @@ void iclass_simulate(uint8_t sim_type, uint8_t num_csns, bool send_reply, bool t // double the amount of collected data. if (send_reply) - reply_old(CMD_ACK, CMD_HF_ICLASS_SIMULATE, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2); + reply_iclass_sim(i * 2, mac_responses, i * EPURSE_MAC_SIZE * 2); } else { // We may want a mode here where we hardcode the csns to use (from proxclone). diff --git a/armsrc/iclass.h b/armsrc/iclass.h index 9b3851394..42899f5ff 100644 --- a/armsrc/iclass.h +++ b/armsrc/iclass.h @@ -58,7 +58,6 @@ void iClass_Restore(iclass_restore_req_t *msg); int do_iclass_simulation_nonsec(void); int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf); -void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void iclass_simulate(uint8_t sim_type, uint8_t num_csns, bool send_reply, bool trace, uint8_t *datain, uint8_t *dataout, uint16_t *dataoutlen); void iClass_Authentication_fast(iclass_chk_t *p); diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index d8c8482d2..9bd035e3a 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -1140,9 +1140,15 @@ static int CmdHFiClassSim(const char *Cmd) { PrintAndLogEx(INFO, "Press " _GREEN_("") " to abort"); PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ICLASS_SIMULATE, sim_type, NUM_CSNS, 1, csns, NUM_CSNS * PICOPASS_BLOCK_SIZE); + uint8_t sbuf[sizeof(iclass_sim_t) + (NUM_CSNS * PICOPASS_BLOCK_SIZE)] = {0}; + iclass_sim_t *spayload = (iclass_sim_t *)sbuf; + spayload->sim_type = sim_type; + spayload->num_csns = NUM_CSNS; + spayload->send_reply = 1; + memcpy(spayload->csns, csns, NUM_CSNS * PICOPASS_BLOCK_SIZE); + SendCommandNG(CMD_HF_ICLASS_SIMULATE, sbuf, sizeof(sbuf)); - while (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { + while (WaitForResponseTimeout(CMD_HF_ICLASS_SIMULATE, &resp, 2000) == false) { tries++; if (kbd_enter_pressed()) { PrintAndLogEx(WARNING, "\naborted via keyboard."); @@ -1153,7 +1159,8 @@ static int CmdHFiClassSim(const char *Cmd) { return PM3_ETIMEOUT; } } - uint8_t num_mac = resp.oldarg[1]; + const iclass_sim_resp_t *sresp = (const iclass_sim_resp_t *)resp.data.asBytes; + uint8_t num_mac = (resp.length >= sizeof(iclass_sim_resp_t)) ? sresp->num_mac : 0; bool success = (NUM_CSNS == num_mac); PrintAndLogEx((success) ? SUCCESS : WARNING, "[%c] %d out of %d MAC obtained [%s]", (success) ? '+' : '!', num_mac, NUM_CSNS, (success) ? "OK" : "FAIL"); @@ -1174,9 +1181,9 @@ static int CmdHFiClassSim(const char *Cmd) { //copy CSN memcpy(dump + (i * MAC_ITEM_SIZE), csns + i * 8, 8); //copy epurse - memcpy(dump + (i * MAC_ITEM_SIZE) + 8, resp.data.asBytes + i * 16, 8); + memcpy(dump + (i * MAC_ITEM_SIZE) + 8, sresp->mac + i * 16, 8); // NR_MAC (eight bytes from the response) ( 8b csn + 8b epurse == 16) - memcpy(dump + (i * MAC_ITEM_SIZE) + 16, resp.data.asBytes + i * 16 + 8, 8); + memcpy(dump + (i * MAC_ITEM_SIZE) + 16, sresp->mac + i * 16 + 8, 8); } /** Now, save to dumpfile **/ saveFile("iclass_mac_attack", ".bin", dump, datalen); @@ -1191,9 +1198,15 @@ static int CmdHFiClassSim(const char *Cmd) { PrintAndLogEx(INFO, "Press " _GREEN_("") " to abort"); PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ICLASS_SIMULATE, sim_type, NUM_CSNS, 1, csns, NUM_CSNS * PICOPASS_BLOCK_SIZE); + uint8_t sbuf[sizeof(iclass_sim_t) + (NUM_CSNS * PICOPASS_BLOCK_SIZE)] = {0}; + iclass_sim_t *spayload = (iclass_sim_t *)sbuf; + spayload->sim_type = sim_type; + spayload->num_csns = NUM_CSNS; + spayload->send_reply = 1; + memcpy(spayload->csns, csns, NUM_CSNS * PICOPASS_BLOCK_SIZE); + SendCommandNG(CMD_HF_ICLASS_SIMULATE, sbuf, sizeof(sbuf)); - while (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { + while (WaitForResponseTimeout(CMD_HF_ICLASS_SIMULATE, &resp, 2000) == false) { tries++; if (kbd_enter_pressed()) { PrintAndLogEx(WARNING, "\naborted via keyboard."); @@ -1204,7 +1217,8 @@ static int CmdHFiClassSim(const char *Cmd) { return PM3_ETIMEOUT; } } - uint8_t num_mac = resp.oldarg[1]; + const iclass_sim_resp_t *sresp = (const iclass_sim_resp_t *)resp.data.asBytes; + uint8_t num_mac = (resp.length >= sizeof(iclass_sim_resp_t)) ? sresp->num_mac : 0; bool success = ((NUM_CSNS * 2) == num_mac); PrintAndLogEx((success) ? SUCCESS : WARNING, "[%c] %d out of %d MAC obtained [%s]", (success) ? '+' : '!', num_mac, NUM_CSNS * 2, (success) ? "OK" : "FAIL"); @@ -1225,9 +1239,9 @@ static int CmdHFiClassSim(const char *Cmd) { // copy CSN memcpy(dump + (i * MAC_ITEM_SIZE), csns + i * 8, 8); //CSN // copy EPURSE - memcpy(dump + (i * MAC_ITEM_SIZE) + 8, resp.data.asBytes + i * 16, 8); + memcpy(dump + (i * MAC_ITEM_SIZE) + 8, sresp->mac + i * 16, 8); // copy NR_MAC (eight bytes from the response) ( 8b csn + 8b epurse == 16) - memcpy(dump + (i * MAC_ITEM_SIZE) + 16, resp.data.asBytes + i * 16 + 8, 8); + memcpy(dump + (i * MAC_ITEM_SIZE) + 16, sresp->mac + i * 16 + 8, 8); } saveFile("iclass_mac_attack_keyroll_A", ".bin", dump, datalen); @@ -1238,9 +1252,9 @@ static int CmdHFiClassSim(const char *Cmd) { // Copy CSN memcpy(dump + (i * MAC_ITEM_SIZE), csns + i * 8, 8); // copy EPURSE - memcpy(dump + (i * MAC_ITEM_SIZE) + 8, resp.data.asBytes + resp_index, 8); + memcpy(dump + (i * MAC_ITEM_SIZE) + 8, sresp->mac + resp_index, 8); // copy NR_MAC (eight bytes from the response) ( 8b csn + 8 epurse == 16) - memcpy(dump + (i * MAC_ITEM_SIZE) + 16, resp.data.asBytes + resp_index + 8, 8); + memcpy(dump + (i * MAC_ITEM_SIZE) + 16, sresp->mac + resp_index + 8, 8); resp_index++; } saveFile("iclass_mac_attack_keyroll_B", ".bin", dump, datalen); @@ -1260,7 +1274,13 @@ static int CmdHFiClassSim(const char *Cmd) { PrintAndLogEx(INFO, "Press " _GREEN_("`pm3 button`") " to abort"); uint8_t numberOfCSNs = 0; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ICLASS_SIMULATE, sim_type, numberOfCSNs, 0, csn, 8); + uint8_t sbuf[sizeof(iclass_sim_t) + 8] = {0}; + iclass_sim_t *spayload = (iclass_sim_t *)sbuf; + spayload->sim_type = sim_type; + spayload->num_csns = numberOfCSNs; + spayload->send_reply = 0; + memcpy(spayload->csns, csn, 8); + SendCommandNG(CMD_HF_ICLASS_SIMULATE, sbuf, sizeof(sbuf)); 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"); @@ -1609,7 +1629,13 @@ static int CmdHFiClassTagSim(const char *Cmd) { } clearCommandBuffer(); - SendCommandMIX(CMD_HF_ICLASS_SIMULATE, ICLASS_SIM_MODE_FULL_LIVE, 0, 1, csn, 8); + uint8_t sbuf[sizeof(iclass_sim_t) + 8] = {0}; + iclass_sim_t *spayload = (iclass_sim_t *)sbuf; + spayload->sim_type = ICLASS_SIM_MODE_FULL_LIVE; + spayload->num_csns = 0; + spayload->send_reply = 1; + memcpy(spayload->csns, csn, 8); + SendCommandNG(CMD_HF_ICLASS_SIMULATE, sbuf, sizeof(sbuf)); PacketResponseNG resp; bool running = true; @@ -7002,10 +7028,16 @@ static int CmdHFiClassLookUp(const char *Cmd) { // Device returns: epurse[8] + NR[4] + MAC_reader[4] PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ICLASS_SIMULATE, ICLASS_SIM_MODE_READER_ATTACK, 1, 1, csn, 8); + uint8_t sbuf[sizeof(iclass_sim_t) + 8] = {0}; + iclass_sim_t *spayload = (iclass_sim_t *)sbuf; + spayload->sim_type = ICLASS_SIM_MODE_READER_ATTACK; + spayload->num_csns = 1; + spayload->send_reply = 1; + memcpy(spayload->csns, csn, 8); + SendCommandNG(CMD_HF_ICLASS_SIMULATE, sbuf, sizeof(sbuf)); uint8_t tries = 0; - while (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { + while (WaitForResponseTimeout(CMD_HF_ICLASS_SIMULATE, &resp, 2000) == false) { tries++; if (kbd_enter_pressed()) { PrintAndLogEx(WARNING, "\naborted via keyboard."); @@ -7017,16 +7049,17 @@ static int CmdHFiClassLookUp(const char *Cmd) { } } - uint8_t num_mac = resp.oldarg[1]; + const iclass_sim_resp_t *sresp = (const iclass_sim_resp_t *)resp.data.asBytes; + uint8_t num_mac = (resp.length >= sizeof(iclass_sim_resp_t)) ? sresp->num_mac : 0; if (num_mac == 0) { PrintAndLogEx(WARNING, "No CHECK command captured from reader"); return PM3_ESOFT; } uint8_t cap_epurse[8], nr[4], mac_r[4]; - memcpy(cap_epurse, resp.data.asBytes, 8); - memcpy(nr, resp.data.asBytes + 8, 4); - memcpy(mac_r, resp.data.asBytes + 12, 4); + memcpy(cap_epurse, sresp->mac, 8); + memcpy(nr, sresp->mac + 8, 4); + memcpy(mac_r, sresp->mac + 12, 4); PrintAndLogEx(SUCCESS, "Captured CHECK:"); PrintAndLogEx(SUCCESS, " ePurse.... %s", sprint_hex(cap_epurse, 8)); diff --git a/include/iclass_cmd.h b/include/iclass_cmd.h index ebc868cc0..944368fc2 100644 --- a/include/iclass_cmd.h +++ b/include/iclass_cmd.h @@ -209,4 +209,22 @@ typedef struct { uint8_t data[PICOPASS_MAX_BYTES]; } PACKED iclass_tag_t; +// CMD_HF_ICLASS_SIMULATE payload. +// Replaces oldargs: arg0 = sim_type, arg1 = num_csns, arg2 = send_reply +typedef struct { + uint8_t sim_type; + uint8_t num_csns; + uint8_t send_reply; + uint8_t rfu; + uint8_t csns[]; +} PACKED iclass_sim_t; + +// Reply for the reader-attack sim modes. The old reply put the opcode itself +// into arg0 so the client could tell anonymous CMD_ACKs apart; NG carries the +// opcode in the frame, so only the mac count is left to send. +typedef struct { + uint16_t num_mac; + uint8_t mac[]; +} PACKED iclass_sim_resp_t; + #endif // _ICLASS_H_