Skip to content

Commit 3840796

Browse files
authored
Merge pull request #3176 from Antiklesys/master
Added `hf iclass tagsim` command and `--live` `hf iclass lookup`
2 parents c221d86 + 7d8c9f3 commit 3840796

File tree

4 files changed

+887
-28
lines changed

4 files changed

+887
-28
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file.
33
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...
44

55
## [unreleased][unreleased]
6+
- Improved SIO parsing for `hf iclass view` based on Iceman's "Dismantling the SEOS Protocol" talk (@antiklesys)
7+
- Added live fc/cn update to `hf iclass tagsim` refreshing the csn with each update (@antiklesys)
8+
- Added `--live` option to `hf iclass lookup` command to perform a live recovery of the reader's key by simulating a tag and running the lookup command against both standard and elite dictionaries (@antiklesys)
9+
- Added `hf iclass tagsim` command to quickly simulate an iclass card based on facility code and card number(@antiklesys)
610
- Added `-f` parameter to `hf iclass sam` command to use the sam to parse a card dump (@antiklesys)
711
- Fixed WTX response behavior in `ExchangeRaw14A()` (@team-orangeBlue)
812
- Added `-t` / `--timeout` option for `hf 15 sim` (@recursivenomad)

armsrc/iclass.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,27 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
500500

501501
uint32_t reader_eof_time = 0;
502502
len = GetIso15693CommandFromReader(receivedCmd, MAX_FRAME_SIZE, &reader_eof_time);
503+
if (len == -2) {
504+
// USB data arrived while waiting for RF — drain all pending EML_MEMSET
505+
// commands inline (without FpgaDownloadAndGo) so live tag updates work.
506+
PacketCommandNG rx;
507+
while (data_available()) {
508+
if (receive_ng(&rx) != PM3_SUCCESS) break;
509+
if (rx.cmd == CMD_HF_ICLASS_EML_MEMSET) {
510+
struct p {
511+
uint16_t offset;
512+
uint16_t plen;
513+
uint8_t data[];
514+
} PACKED;
515+
struct p *payload = (struct p *) rx.data.asBytes;
516+
emlSet(payload->data, payload->offset, payload->plen);
517+
} else {
518+
exit_loop = true;
519+
break;
520+
}
521+
}
522+
continue;
523+
}
503524
if (len < 0) {
504525
button_pressed = true;
505526
exit_loop = true;
@@ -512,6 +533,45 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
512533
block = receivedCmd[1];
513534

514535
if (cmd == ICLASS_CMD_ACTALL && len == 1) { // 0x0A
536+
537+
// Check for a live tag-identity reload requested by the client.
538+
// The client writes a non-zero byte to emulator offset 32*8 = 256
539+
// (one byte past the 32-block tag data) then updates blocks 0, 3, 4, 6-9
540+
// in emulator memory. We pick it up at the start of each anti-collision
541+
// cycle so the reader sees the new identity from the very first SELECT.
542+
if ((simulationMode == ICLASS_SIM_MODE_FULL ||
543+
simulationMode == ICLASS_SIM_MODE_FULL_GLITCH ||
544+
simulationMode == ICLASS_SIM_MODE_FULL_GLITCH_KEY) &&
545+
emulator[32 * 8] != 0) {
546+
547+
emulator[32 * 8] = 0; // consume the flag
548+
549+
// Reload CSN (block 0) and rebuild anticollision/CSN responses
550+
memcpy(csn_data, emulator, 8);
551+
rotateCSN(csn_data, anticoll_data);
552+
AddCrc(anticoll_data, 8);
553+
AddCrc(csn_data, 8);
554+
555+
CodeIso15693AsTag(anticoll_data, sizeof(anticoll_data));
556+
memcpy(resp_anticoll, ts->buf, ts->max);
557+
resp_anticoll_len = ts->max;
558+
559+
CodeIso15693AsTag(csn_data, sizeof(csn_data));
560+
memcpy(resp_csn, ts->buf, ts->max);
561+
resp_csn_len = ts->max;
562+
563+
// Reload KD/KC (blocks 3 & 4) and recompute cipher states
564+
memcpy(diversified_kd, emulator + (8 * 3), 8);
565+
memcpy(diversified_kc, emulator + (8 * 4), 8);
566+
cipher_state_KD[0] = opt_doTagMAC_1(card_challenge_data, diversified_kd);
567+
cipher_state_KC[0] = opt_doTagMAC_1(card_challenge_data, diversified_kc);
568+
569+
// Reset per-transaction auth state
570+
kc_attempt = 0;
571+
using_kc = false;
572+
cipher_state = &cipher_state_KD[0];
573+
}
574+
515575
// Reader in anti collision phase
516576
modulated_response = resp_sof;
517577
modulated_response_size = resp_sof_len;

armsrc/iso15693.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,8 +1500,10 @@ int GetIso15693CommandFromReader(uint8_t *received, size_t max_len, uint32_t *eo
15001500
int samples = 0;
15011501
bool gotFrame = false;
15021502

1503-
// the decoder data structure
1504-
DecodeReader_t *dr = (DecodeReader_t *)BigBuf_calloc(sizeof(DecodeReader_t));
1503+
// the decoder data structure — use stack, not BigBuf, to avoid a per-call
1504+
// allocation leak when the function is restarted (e.g. on data_available exit)
1505+
DecodeReader_t dr_buf = {0};
1506+
DecodeReader_t *dr = &dr_buf;
15051507
DecodeReaderInit(dr, received, max_len, 0, NULL);
15061508

15071509
// wait for last transfer to complete
@@ -1569,6 +1571,11 @@ int GetIso15693CommandFromReader(uint8_t *received, size_t max_len, uint32_t *eo
15691571
break;
15701572
}
15711573

1574+
if (data_available()) {
1575+
dr->byteCount = -2;
1576+
break;
1577+
}
1578+
15721579
WDT_HIT();
15731580
}
15741581

0 commit comments

Comments
 (0)