diff --git a/CHANGELOG.md b/CHANGELOG.md index e9bb8d98f..de0373163 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,14 @@ 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... ## [unreleased][unreleased] + - Fix `hf 15 sim` - Added basic response to GET_SYSTEM_INFO and READBLOCK requests in order to fix iso15693 tag sim + - Added `mf mfu sim t 7 n ` - MFU emulation now supports automatic exit after blocks read. (@cyberpunk-re) + - Added T55xx Guide to assist in learning how to use the T55xx chip (@mwalker33) - Fix 'hf iclass wrbl' - dealing with tags in unsecured vs secured pagemode now is correct (@iceman1001) - Change many commands to cliparser (@iceman1001, @tcprst, @mwalker33,...) - ... + - Change `hf iclass chk/lookup/loclass` speedups (@iceman1001) + - Change - ongoing convertion to cliparser (@tcprst, @iceman1001) - Added compilation options for 256k Proxmark versions, see doc (@doegox) - Added support for 10b UID in `hf 14a sim` (@doegox) - Added `HF_TCPRST` standalone mode which read and emulate IKEA Rothult cards (@tcprst) diff --git a/Makefile b/Makefile index 89e5b4c98..b7e942f58 100644 --- a/Makefile +++ b/Makefile @@ -169,6 +169,7 @@ help: @echo "+ fpga_compress - Make tools/fpga_compress" @echo @echo "+ style - Apply some automated source code formatting rules" + @echo "+ cliparser - Generate cliparser TODO @echo "+ check - Run offline tests. Set CHECKARGS to pass arguments to the test script" @echo "+ .../check - Run offline tests against specific target. See above." @echo "+ miscchecks - Detect various encoding issues in source code" @@ -248,6 +249,14 @@ endif # easy printing of MAKE VARIABLES print-%: ; @echo $* = $($*) +cliparser: + # Get list of all commands + cat doc/commands.md | grep -e ^\|\` | cut -f 2 -d "\`" | grep -v 'help\|list\|mem spiffs\|quit\|exit' | awk '{$$1=$$1};1' > cliparser_all_commands.tmp + # Get list of cliparserized commands + grep -r CLIParserInit ./client/src/ | cut -f 2 -d "\"" | awk '{$$1=$$1};1' > cliparser_done.tmp + # Determine commands that still need cliparser conversion + grep -xvf cliparser_done.tmp cliparser_all_commands.tmp > ./doc/cliparser_todo.txt + style: # Make sure astyle is installed @which astyle >/dev/null || ( echo "Please install 'astyle' package first" ; exit 1 ) diff --git a/README.md b/README.md index e61260b54..bc7e88854 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ |[Donations](#Donations)|[Maintainers](/doc/md/Development/Maintainers.md)|[Command Cheat sheet](/doc/cheatsheet.md)| ||[Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md)|[More cheat sheets](https://github.com/RfidResearchGroup/proxmark3/wiki/More-cheat-sheets)| ||**[Troubleshooting](/doc/md/Installation_Instructions/Troubleshooting.md)**|[Complete client command set](/doc/commands.md)| -||**[JTAG](/doc/jtag_notes.md)**|| +||**[JTAG](/doc/jtag_notes.md)**|[T55xx Guide](/doc/T5577_Guide.md)| ## Notes / helpful documents diff --git a/armsrc/Standalone/hf_aveful.c b/armsrc/Standalone/hf_aveful.c index 97ef78745..c9464e3d1 100644 --- a/armsrc/Standalone/hf_aveful.c +++ b/armsrc/Standalone/hf_aveful.c @@ -243,7 +243,7 @@ void RunMod(void) { uint8_t flags = FLAG_7B_UID_IN_DATA; Dbprintf("Starting simulation, press pm3-button to stop and go back to search state."); - SimulateIso14443aTag(7, flags, card.uid); + SimulateIso14443aTag(7, flags, card.uid, 0); // Go back to search state if user presses pm3-button state = STATE_SEARCH; diff --git a/armsrc/Standalone/hf_young.c b/armsrc/Standalone/hf_young.c index 1673b8975..e7b69d550 100644 --- a/armsrc/Standalone/hf_young.c +++ b/armsrc/Standalone/hf_young.c @@ -244,22 +244,22 @@ void RunMod(void) { if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0) { DbpString("Mifare Classic 1k"); - SimulateIso14443aTag(1, flags, data); + SimulateIso14443aTag(1, flags, data, 0); } else if (uids[selected].sak == 0x18 && uids[selected].atqa[0] == 0x02 && uids[selected].atqa[1] == 0) { DbpString("Mifare Classic 4k (4b uid)"); - SimulateIso14443aTag(8, flags, data); + SimulateIso14443aTag(8, flags, data, 0); } else if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) { DbpString("Mifare Classic 4k (7b uid)"); - SimulateIso14443aTag(8, flags, data); + SimulateIso14443aTag(8, flags, data, 0); } else if (uids[selected].sak == 0x00 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) { DbpString("Mifare Ultralight"); - SimulateIso14443aTag(2, flags, data); + SimulateIso14443aTag(2, flags, data, 0); } else if (uids[selected].sak == 0x20 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0x03) { DbpString("Mifare DESFire"); - SimulateIso14443aTag(3, flags, data); + SimulateIso14443aTag(3, flags, data, 0); } else { Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation"); - SimulateIso14443aTag(1, flags, data); + SimulateIso14443aTag(1, flags, data, 0); } } else if (button_pressed == BUTTON_SINGLE_CLICK) { diff --git a/armsrc/Standalone/lf_hidbrute.c b/armsrc/Standalone/lf_hidbrute.c index f0d8cae86..c8d48bb0c 100644 --- a/armsrc/Standalone/lf_hidbrute.c +++ b/armsrc/Standalone/lf_hidbrute.c @@ -95,7 +95,7 @@ void RunMod(void) { WAIT_BUTTON_RELEASED(); - CopyHIDtoT55x7(0, high[selected], low[selected], 0); + CopyHIDtoT55x7(0, high[selected], low[selected], 0, false, false); Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]); LEDsoff(); diff --git a/armsrc/Standalone/lf_samyrun.c b/armsrc/Standalone/lf_samyrun.c index 9646dede3..497e0c03b 100644 --- a/armsrc/Standalone/lf_samyrun.c +++ b/armsrc/Standalone/lf_samyrun.c @@ -121,7 +121,7 @@ void RunMod(void) { Dbprintf("[=] cloning %x | %x%08x", selected, high[selected], low[selected]); // high2, high, low, no longFMT - CopyHIDtoT55x7(0, high[selected], low[selected], 0); + CopyHIDtoT55x7(0, high[selected], low[selected], 0, false, false); DbpString("[=] cloned done"); diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 69b628d7a..e0178a8d7 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -874,7 +874,7 @@ static void PacketReceived(PacketCommandNG *packet) { } case CMD_LF_HID_CLONE: { lf_hidsim_t *payload = (lf_hidsim_t *)packet->data.asBytes; - CopyHIDtoT55x7(payload->hi2, payload->hi, payload->lo, payload->longFMT); + CopyHIDtoT55x7(payload->hi2, payload->hi, payload->lo, payload->longFMT, payload->Q5, payload->EM); break; } case CMD_LF_IO_WATCH: { @@ -907,7 +907,13 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_LF_TI_WRITE: { - WriteTItag(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2]); + struct p { + uint32_t high; + uint32_t low; + uint16_t crc; + } PACKED; + struct p *payload = (struct p *)packet->data.asBytes; + WriteTItag(payload->high, payload->low, packet->crc); break; } case CMD_LF_SIMULATE: { @@ -1037,10 +1043,11 @@ static void PacketReceived(PacketCommandNG *packet) { case CMD_LF_VIKING_CLONE: { struct p { bool Q5; + bool EM; uint8_t blocks[8]; } PACKED; struct p *payload = (struct p *)packet->data.asBytes; - CopyVikingtoT55xx(payload->blocks, payload->Q5); + CopyVikingtoT55xx(payload->blocks, payload->Q5, payload->EM); break; } case CMD_LF_COTAG_READ: { @@ -1267,9 +1274,10 @@ static void PacketReceived(PacketCommandNG *packet) { uint8_t tagtype; uint8_t flags; uint8_t uid[10]; + uint8_t exitAfter; } PACKED; struct p *payload = (struct p *) packet->data.asBytes; - SimulateIso14443aTag(payload->tagtype, payload->flags, payload->uid); // ## Simulate iso14443a tag - pass tag type & UID + SimulateIso14443aTag(payload->tagtype, payload->flags, payload->uid, payload->exitAfter); // ## Simulate iso14443a tag - pass tag type & UID break; } case CMD_HF_ISO14443A_ANTIFUZZ: { diff --git a/armsrc/felica.c b/armsrc/felica.c index aafdae5d8..7aa524e62 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -620,7 +620,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { set_tracelen(numbts); set_tracelen(BigBuf_max_traceLen()); - Dbprintf("Felica sniffing done, tracelen: %i, use hf list felica for annotations", BigBuf_get_traceLen()); + Dbprintf("Felica sniffing done, tracelen: %i, use " _YELLOW_("`hf felica list`") " for annotations", BigBuf_get_traceLen()); reply_mix(CMD_ACK, 1, numbts, 0, 0, 0); LED_D_OFF(); } diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 86d8094b7..5cb5d71ae 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -1999,10 +1999,10 @@ void iClass_Restore(iclass_restore_req_t *msg) { // data + mac if (iclass_writeblock_ext(item.blockno, item.data, mac, use_mac)) { - Dbprintf("Write block [%02x] " _GREEN_("successful"), item.blockno); + Dbprintf("Write block [%3d/0x%02X] " _GREEN_("successful"), item.blockno, item.blockno); written++; } else { - Dbprintf("Write block [%02x] " _RED_("failed"), item.blockno); + Dbprintf("Write block [%3d/0x%02X] " _RED_("failed"), item.blockno, item.blockno); } } diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 806c63091..db00f5494 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -20,6 +20,7 @@ #include "ticks.h" #include "dbprint.h" #include "util.h" +#include "util.h" #include "parity.h" #include "mifareutil.h" #include "commonutil.h" @@ -1251,7 +1252,7 @@ bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_i // response to send, and send it. // 'hf 14a sim' //----------------------------------------------------------------------------- -void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) { +void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data, uint8_t exitAfterNReads) { #define ATTACK_KEY_COUNT 8 // keep same as define in cmdhfmf.c -> readerAttack() @@ -1327,6 +1328,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) { int happened = 0; int happened2 = 0; int cmdsRecvd = 0; + uint32_t numReads = 0; //Counts numer of times reader reads a block // compatible write block number uint8_t wrblock = 0; @@ -1338,7 +1340,10 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) { LED_A_ON(); // main loop - for (;;) { + //for (;;) { + bool finished = false; + bool button_pushed = BUTTON_PRESS(); + while (!button_pushed && !finished) { WDT_HIT(); tag_response_info_t *p_response = NULL; @@ -1467,6 +1472,12 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) { emlGetMemBt(emdata, start, 16); AddCrc14A(emdata, 16); EmSendCmd(emdata, sizeof(emdata)); + numReads++; // Increment number of times reader requested a block + + if (exitAfterNReads > 0 && numReads == exitAfterNReads) { + Dbprintf("[MFUEMUL_WORK] %d reads done, exiting", numReads); + finished = true; + } } // We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below p_response = NULL; @@ -1979,9 +1990,11 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) { for (;;) { WDT_HIT(); - if (check == 2000) { - if (BUTTON_PRESS()) + if (check == 1000) { + if (BUTTON_PRESS() || data_available()) { + Dbprintf("----------- " _GREEN_("BREAKING") " ----------"); return 1; + } check = 0; } ++check; diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 49317628b..325eed056 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -129,7 +129,7 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time); RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time); void RAMFUNC SniffIso14443a(uint8_t param); -void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data); +void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data, uint8_t numReads); bool SimulateIso14443aInit(int tagType, int flags, uint8_t *data, tag_response_info_t **responses, uint32_t *cuid, uint32_t counters[3], uint8_t tearings[3], uint8_t *pages); bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *len); void iso14443a_antifuzz(uint32_t flags); diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 5861b3d17..b6d1b7ed8 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -104,10 +104,12 @@ #define ISO15693_MAX_COMMAND_LENGTH 45 // allows write single block with the maximum block size of 256bits. Write multiple blocks not supported yet // 32 + 2 crc + 1 -#define ISO15_MAX_FRAME 35 -#define CMD_ID_RESP 5 -#define CMD_READ_RESP 13 -#define CMD_INV_RESP 12 +#define ISO15_MAX_FRAME 35 +#define CMD_ID_RESP 5 +#define CMD_READ_RESP 13 +#define CMD_INV_RESP 12 +#define CMD_SYSINFO_RESP 17 +#define CMD_READBLOCK_RESP 7 //#define Crc(data, len) Crc(CRC_15693, (data), (len)) #define CheckCrc15(data, len) check_crc(CRC_15693, (data), (len)) @@ -1679,27 +1681,7 @@ void SimTagIso15693(uint8_t *uid) { LED_C_ON(); - // Build INVENTORY command - uint8_t resp_inv[CMD_INV_RESP] = {0}; - resp_inv[0] = 0; // No error, no protocol format extension - resp_inv[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported - - // 64-bit UID - resp_inv[2] = uid[7]; - resp_inv[3] = uid[6]; - resp_inv[4] = uid[5]; - resp_inv[5] = uid[4]; - resp_inv[6] = uid[3]; - resp_inv[7] = uid[2]; - resp_inv[8] = uid[1]; - resp_inv[9] = uid[0]; - - // CRC - AddCrc15(resp_inv, 10); - CodeIso15693AsTag(resp_inv, CMD_INV_RESP); - - tosend_t *ts = get_tosend(); enum { NO_FIELD, IDLE, ACTIVATED, SELECTED, HALTED } chip_state = NO_FIELD; @@ -1745,11 +1727,96 @@ void SimTagIso15693(uint8_t *uid) { if ((cmd_len >= 5) && (cmd[0] & ISO15_REQ_INVENTORY) && (cmd[1] == ISO15_CMD_INVENTORY)) { bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH); uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM; + + // Build INVENTORY command + uint8_t resp_inv[CMD_INV_RESP] = {0}; + + resp_inv[0] = 0; // No error, no protocol format extension + resp_inv[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported + + // 64-bit UID + resp_inv[2] = uid[7]; + resp_inv[3] = uid[6]; + resp_inv[4] = uid[5]; + resp_inv[5] = uid[4]; + resp_inv[6] = uid[3]; + resp_inv[7] = uid[2]; + resp_inv[8] = uid[1]; + resp_inv[9] = uid[0]; + + // CRC + AddCrc15(resp_inv, 10); + CodeIso15693AsTag(resp_inv, CMD_INV_RESP); + + tosend_t *ts = get_tosend(); + TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, slow); LogTrace_ISO15693(resp_inv, CMD_INV_RESP, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false); chip_state = SELECTED; } + + // GET_SYSTEM_INFO + if ((cmd[1] == ISO15_CMD_SYSINFO)) { + bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH); + uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM; + + // Build GET_SYSTEM_INFO command + uint8_t resp_sysinfo[CMD_SYSINFO_RESP] = {0}; + + resp_sysinfo[0] = 0; // Response flags. + resp_sysinfo[1] = 0x0F; // Information flags (0x0F - DSFID, AFI, Mem size, IC) + + // 64-bit UID + resp_sysinfo[2] = uid[7]; + resp_sysinfo[3] = uid[6]; + resp_sysinfo[4] = uid[5]; + resp_sysinfo[5] = uid[4]; + resp_sysinfo[6] = uid[3]; + resp_sysinfo[7] = uid[2]; + resp_sysinfo[8] = uid[1]; + resp_sysinfo[9] = uid[0]; + + resp_sysinfo[10] = 0; // DSFID + resp_sysinfo[11] = 0; // AFI + + resp_sysinfo[12] = 0x1B; // Memory size. + resp_sysinfo[13] = 0x03; // Memory size. + resp_sysinfo[14] = 0x01; // IC reference. + + // CRC + AddCrc15(resp_sysinfo, 15); + CodeIso15693AsTag(resp_sysinfo, CMD_SYSINFO_RESP); + + tosend_t *ts = get_tosend(); + + TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, slow); + LogTrace_ISO15693(resp_sysinfo, CMD_SYSINFO_RESP, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false); + } + + // READ_BLOCK + if ((cmd[1] == ISO15_CMD_READ)) { + bool slow = !(cmd[0] & ISO15_REQ_DATARATE_HIGH); + uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM; + + // Build GET_SYSTEM_INFO command + uint8_t resp_readblock[CMD_READBLOCK_RESP] = {0}; + + resp_readblock[0] = 0; // Response flags. + resp_readblock[1] = 0; // Block data. + resp_readblock[2] = 0; // Block data. + resp_readblock[3] = 0; // Block data. + resp_readblock[4] = 0; // Block data. + + // CRC + AddCrc15(resp_readblock, 5); + CodeIso15693AsTag(resp_readblock, CMD_READBLOCK_RESP); + + tosend_t *ts = get_tosend(); + + TransmitTo15693Reader(ts->buf, ts->max, &response_time, 0, slow); + LogTrace_ISO15693(resp_readblock, CMD_READBLOCK_RESP, response_time * 32, (response_time * 32) + (ts->max * 32 * 64), NULL, false); + } } switch_off(); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index a6fbb7bba..32c9568d1 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -803,7 +803,7 @@ void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc) { AcquireTiType(); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - DbpString("Now use `lf ti read` to check"); + DbpString("Now use `lf ti reader` to check"); StopTicks(); } @@ -2190,10 +2190,8 @@ void T55xxWakeUp(uint32_t pwd, uint8_t flags) { reply_ng(CMD_LF_T55XX_WAKEUP, PM3_SUCCESS, NULL, 0); } - /*-------------- Cloning routines -----------*/ static void WriteT55xx(uint32_t *blockdata, uint8_t startblock, uint8_t numblocks) { - t55xx_write_block_t cmd; cmd.pwd = 0; cmd.flags = 0; @@ -2203,11 +2201,18 @@ static void WriteT55xx(uint32_t *blockdata, uint8_t startblock, uint8_t numblock cmd.blockno = i - 1; T55xxWriteBlock((uint8_t *)&cmd); } - } +/* disabled until verified. +static void WriteEM4x05(uint32_t *blockdata, uint8_t startblock, uint8_t numblocks) { + for (uint8_t i = numblocks + startblock; i > startblock; i--) { + EM4xWriteWord(i - 1, blockdata[i - 1], 0, false); + } +} +*/ + // Copy HID id to card and setup block 0 config -void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) { +void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, bool q5, bool em) { uint32_t data[] = {0, 0, 0, 0, 0, 0, 0}; uint8_t last_block = 0; @@ -2244,25 +2249,43 @@ void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) { data[0] = T55x7_BITRATE_RF_50 | T55x7_MODULATION_FSK2a | last_block << T55x7_MAXBLOCK_SHIFT; //TODO add selection of chip for Q5 or T55x7 - // data[0] = T5555_SET_BITRATE(50) | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | last_block << T5555_MAXBLOCK_SHIFT; + if (q5) { + data[0] = T5555_SET_BITRATE(50) | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | last_block << T5555_MAXBLOCK_SHIFT; + } else if (em) { + data[0] = (EM4x05_SET_BITRATE(50) | EM4x05_MODULATION_FSK2 | EM4x05_INVERT | EM4x05_SET_NUM_BLOCKS(last_block)); + } LED_D_ON(); - WriteT55xx(data, 0, last_block + 1); + if (em) { + Dbprintf("Clone HID Prox to EM4x05 is untested and disabled until verified"); + //WriteEM4x05(data, 0, last_block + 1); + } else { + WriteT55xx(data, 0, last_block + 1); + } LED_D_OFF(); + reply_ng(CMD_LF_HID_CLONE, PM3_SUCCESS, NULL, 0); } // clone viking tag to T55xx -void CopyVikingtoT55xx(uint8_t *blocks, uint8_t Q5) { +void CopyVikingtoT55xx(uint8_t *blocks, bool q5, bool em) { uint32_t data[] = {T55x7_BITRATE_RF_32 | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT), 0, 0}; - if (Q5) + if (q5) { data[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_MANCHESTER | 2 << T5555_MAXBLOCK_SHIFT; + } else if (em) { + data[0] = (EM4x05_SET_BITRATE(32) | EM4x05_MODULATION_MANCHESTER | EM4x05_SET_NUM_BLOCKS(2)); + } data[1] = bytes_to_num(blocks, 4); data[2] = bytes_to_num(blocks + 4, 4); // Program the data blocks for supplied ID and the block 0 config - WriteT55xx(data, 0, 3); + if (em) { + Dbprintf("Clone Viking to EM4x05 is untested and disabled until verified"); + //WriteEM4x05(data, 0, 3); + } else { + WriteT55xx(data, 0, 3); + } LED_D_OFF(); reply_ng(CMD_LF_VIKING_CLONE, PM3_SUCCESS, NULL, 0); } diff --git a/armsrc/lfops.h b/armsrc/lfops.h index 0ec050158..82db382d8 100644 --- a/armsrc/lfops.h +++ b/armsrc/lfops.h @@ -39,9 +39,8 @@ int lf_awid_watch(int findone, uint32_t *high, uint32_t *low); // Realtime demod int lf_em410x_watch(int findone, uint32_t *high, uint64_t *low); int lf_io_watch(int findone, uint32_t *high, uint32_t *low); -void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567 - -void CopyVikingtoT55xx(uint8_t *blocks, uint8_t Q5); +void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, bool q5, bool em); // Clone an HID card to T5557/T5567 +void CopyVikingtoT55xx(uint8_t *blocks, bool q5, bool em); int copy_em410x_to_t55xx(uint8_t card, uint8_t clock, uint32_t id_hi, uint32_t id_lo); diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index d31342ac0..7a42367dc 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -509,10 +509,21 @@ void doCotagAcquisition(void) { bool firsthigh = false, firstlow = false; uint16_t i = 0, noise_counter = 0; + uint16_t checker = 0; + while ((i < bufsize - 1) && (noise_counter < COTAG_T1 << 1)) { if (BUTTON_PRESS()) break; + + if (checker == 4000) { + if (data_available()) + break; + else + checker = 0; + } else { + ++checker; + } WDT_HIT(); @@ -567,12 +578,22 @@ uint16_t doCotagAcquisitionManchester(uint8_t *dest, uint16_t destlen) { bool firsthigh = false, firstlow = false; uint8_t curr = 0, prev = 0; uint16_t i = 0; - uint16_t period = 0; + uint16_t period = 0, checker = 0; while ((i < destlen) && BUTTON_PRESS() == false) { WDT_HIT(); + if (checker == 4000) { + if (data_available()) + break; + else + checker = 0; + } else { + ++checker; + } + + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 4eaf711b3..bba3132a7 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -535,8 +535,9 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 WDT_HIT(); - if (counter == 2000) { + if (counter == 1000) { if (data_available()) { + Dbprintf("----------- " _GREEN_("BREAKING") " ----------"); break; } counter = 0; diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 92888a0fa..b630bf5de 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -248,7 +248,8 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/cmdlfawid.c ${PM3_ROOT}/client/src/cmdlfcotag.c ${PM3_ROOT}/client/src/cmdlfdestron.c - ${PM3_ROOT}/client/src/cmdlfem4x.c + ${PM3_ROOT}/client/src/cmdlfem.c + ${PM3_ROOT}/client/src/cmdlfem410x.c ${PM3_ROOT}/client/src/cmdlfem4x05.c ${PM3_ROOT}/client/src/cmdlfem4x50.c ${PM3_ROOT}/client/src/cmdlffdxb.c diff --git a/client/Makefile b/client/Makefile index 2f0899bc8..d577b0d25 100644 --- a/client/Makefile +++ b/client/Makefile @@ -489,7 +489,8 @@ SRCS = aiddesfire.c \ cmdlfawid.c \ cmdlfcotag.c \ cmdlfdestron.c \ - cmdlfem4x.c \ + cmdlfem.c \ + cmdlfem410x.c \ cmdlfem4x05.c \ cmdlfem4x50.c \ cmdlffdxb.c \ diff --git a/client/dictionaries/iclass_default_keys.dic b/client/dictionaries/iclass_default_keys.dic index 22e1ee653..9f03720c9 100644 --- a/client/dictionaries/iclass_default_keys.dic +++ b/client/dictionaries/iclass_default_keys.dic @@ -10,3 +10,5 @@ AEA684A6DAB23278 # AA1 F0E1D2C3B4A59687 # Kd from PicoPass 2k documentation 5CBCF1DA45D5FB4F # PicoPass Default Exchange Key 31ad7ebd2f282168 # From HID multiclassSE reader +6EFD46EFCBB3C875 # From pastebin: https://pastebin.com/uHqpjiuU +E033CA419AEE43F9 # From pastebin: https://pastebin.com/uHqpjiuU \ No newline at end of file diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index b3bf93312..9f716608a 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -105,6 +105,11 @@ c934fe34d934 cccccccccccc dddddddddddd eeeeeeeeeeee +# +# elevator +# data from forum +FFFFFF545846 +# f1a97341a9fc 44ab09010845 # hotel system 85fed980ea5a # hotel system @@ -1275,4 +1280,7 @@ AABAFFCC7612 # gamefactory # ozdilek # -17D071403C20 \ No newline at end of file +17D071403C20 +# +534F4C415249 +534f4c303232 \ No newline at end of file diff --git a/client/dictionaries/t55xx_default_pwds.dic b/client/dictionaries/t55xx_default_pwds.dic index 6e7a69583..348c79e0d 100644 --- a/client/dictionaries/t55xx_default_pwds.dic +++ b/client/dictionaries/t55xx_default_pwds.dic @@ -3,7 +3,14 @@ 51243648 000D8787 19920427 -65857569 //chinese "handheld RFID writer" blue cloner from circa 2013 (also sold by xfpga.com) +# ZX-copy3 T55xx / EM4305 +# ref. http://www.proxmark.org/forum/viewtopic.php?pid=40662#p40662 +# default PROX +50524F58 +# blue gun EM4305 +F9DCEBA0 +# chinese "handheld RFID writer" blue cloner from circa 2013 (also sold by xfpga.com) +65857569 # ref. http://kazus.ru/forums/showpost.php?p=1045937&postcount=77 05D73B9F # ref. http://www.proxmark.org/forum/viewtopic.php?= @@ -24,10 +31,6 @@ A5B4C3D2 575F4F4B # 50520901 -# default PROX -50524F58 -# blue gun EM4305 -F9DCEBA0 # Default pwd, simple: 00000000 11111111 diff --git a/client/include/pm3.h b/client/include/pm3.h index cfdb69944..b9814ae48 100644 --- a/client/include/pm3.h +++ b/client/include/pm3.h @@ -4,8 +4,8 @@ typedef struct pm3_device pm3; pm3 *pm3_open(char *port); -int pm3_console(pm3* dev, char *cmd); -const char *pm3_name_get(pm3* dev); -void pm3_close(pm3* dev); +int pm3_console(pm3 *dev, char *cmd); +const char *pm3_name_get(pm3 *dev); +void pm3_close(pm3 *dev); pm3 *pm3_get_current_dev(void); #endif // LIBPM3_H diff --git a/client/luascripts/mfc_hammerlite.lua b/client/luascripts/mfc_hammerlite.lua new file mode 100644 index 000000000..c2f34f04c --- /dev/null +++ b/client/luascripts/mfc_hammerlite.lua @@ -0,0 +1,82 @@ +local getopt = require('getopt') +local lib14a = require('read14a') +local cmds = require('commands') +local ansicolors = require('ansicolors') + +copyright = 'Copyright 2020 A. Ozkal, released under GPLv2+.' +author = 'Ave' +version = 'v0.1.1' +desc = [[ +This script writes a bunch of random blocks to a Mifare Classic card + ]] +example = [[ + script run mfc_hammerlite -w 1000 -k FFFFFFFFFFFF +]] +usage = [[ + script run mfc_hammerlite [-h] [-w ] [-k ] +]] +arguments = [[ + -h : This help + -w : Amount of write rounds to be done to each block (optional, default: 100) + -k : A key for the sectors +]] + +local function help() + print(author) + print(version) + print(desc) + print(ansicolors.cyan..'Usage'..ansicolors.reset) + print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) +end + +function randhex(len) + result = "" + for i = 1,len,1 + do + -- 48-57 numbers, 65-70 a-f + hex = math.random(0, 15) + if hex >= 10 then + hex = hex + 7 + end + result = result..string.char(48 + hex) + end + return result +end + +--- +-- The main entry point +function main(args) + -- param defaults + loopcount = 100 + verifyevery = 10 + key = "FFFFFFFFFFFF" + + -- Read the parameters + for o, a in getopt.getopt(args, 'hw:k:') do + if o == 'h' then return help() end + if o == 'w' then loopcount = tonumber(a) end + if o == 'k' then key = a end + end + + starttime = os.time() + + for i = 1,loopcount,1 + do + for a = 1,63,1 + do + if ((a + 1) % 4 ~= 0) and a ~= 0 then -- :) + data = randhex(32) + -- core.console('hf mf rdbl '..a..' A FFFFFFFFFFFF') + core.console('hf mf wrbl '..a..' A '..key..' '..data) + end + end + end + + print("Hammering complete.") +end + +main(args) diff --git a/client/luascripts/ntag_hammertime.lua b/client/luascripts/ntag_hammertime.lua new file mode 100644 index 000000000..fc9168ae5 --- /dev/null +++ b/client/luascripts/ntag_hammertime.lua @@ -0,0 +1,189 @@ +local getopt = require('getopt') +local lib14a = require('read14a') +local cmds = require('commands') +local ansicolors = require('ansicolors') + +copyright = 'Copyright 2020 A. Ozkal, released under GPLv2+.' +author = 'Ave' +version = 'v2.1.3' +desc = [[ +This script writes a bunch of random blocks to a NTAG or MFUL card to test its actual write limits + ]] +example = [[ + script run ntag_hammertime -w 1000 -r 50 -z 50 -f 5 -s 4 -e 129 +]] +usage = [[ + script run ntag_hammertime [-h] [-w ] [-r ] [-z ] [-f ] [-s ] [-e ] +]] +arguments = [[ + -h : This help + -w : Amount of write rounds to be done to each block (optional, default: 100) + -r : Verify frequency (reads and checks written values every x rounds, optional, default: 10) + -z : Reselect frequency (reselects card once every x rounds, optional, default: 10) + -f : Maximum consequent fails (read/write) that will trigger a fail state (optional, default: 3) + -s : Block number for writes to be started to (optional, inclusive, decimal, default: 4) + -e : Block number for writes to be ended on (optional, inclusive, decimal, default: 129) +]] + +local function help() + print(author) + print(version) + print(desc) + print(ansicolors.cyan..'Usage'..ansicolors.reset) + print(usage) + print(ansicolors.cyan..'Arguments'..ansicolors.reset) + print(arguments) + print(ansicolors.cyan..'Example usage'..ansicolors.reset) + print(example) +end + +function randhex(len) + result = "" + for i = 1,len,1 + do + -- 48-57 numbers, 65-70 a-f + hex = math.random(0, 15) + if hex >= 10 then + hex = hex + 7 + end + result = result..string.char(48 + hex) + end + return result +end + +-- Used to send raw data to the firmware to subsequently forward the data to the card. +-- from mifareplus.lua +local function sendRaw(rawdata, crc, power) + -- print((": %s"):format(rawdata)) + + local flags = lib14a.ISO14A_COMMAND.ISO14A_RAW + if crc then + flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC + end + if power then + flags = flags + lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + end + + local command = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER, + arg1 = flags, -- Send raw + arg2 = string.len(rawdata) / 2, -- arg2 contains the length, which is half the length of the ASCII-string rawdata + data = rawdata + } + local ignore_response = false + local result, err = command:sendMIX(ignore_response) + if result then + --unpack the first 4 parts of the result as longs, and the last as an extremely long string to later be cut down based on arg1, the number of bytes returned + local count,cmd,arg1,arg2,arg3,data = bin.unpack('LLLLH512',result) + + returned_bytes = string.sub(data, 1, arg1 * 2) + if #returned_bytes > 0 then + -- print((": %s"):format(returned_bytes)) -- need to multiply by 2 because the hex digits are actually two bytes when they are strings + return returned_bytes + else + return nil + end + else + print("Error sending the card raw data.") + return nil + end +end + +local function selectCard(keepField, arg2, attemptCount) + for i = 1,attemptCount,1 + do + if lib14a.read(keepField, arg2) then + return true + end + end + return false +end + +--- +-- The main entry point +function main(args) + failcounter = 0 + + -- param defaults + loopcount = 100 + verifyevery = 10 + reselectevery = 10 + failmax = 3 + blockstart = 4 + blockend = 129 + + -- Read the parameters + for o, a in getopt.getopt(args, 'hw:r:z:f:s:e:') do + if o == 'h' then return help() end + if o == 'w' then loopcount = tonumber(a) end + if o == 'r' then verifyevery = tonumber(a) end + if o == 'z' then reselectevery = tonumber(a) end + if o == 'f' then failmax = tonumber(a) end + if o == 's' then blockstart = tonumber(a) end + if o == 'e' then blockend = tonumber(a) end + end + + starttime = os.time() + + if selectCard(true, false, 3) ~= true then + return print("Select failed.") + end + for i = 1,loopcount,1 + do + for block = blockstart,blockend,1 + do + data = randhex(8) + print(i..": Writing "..data.." to block "..block..".") + blockhex = string.format("%02x", block) + result = sendRaw("A2"..blockhex..data, true, true) + if result then -- if false/nil, that's a fail right there + print(ansicolors.green.."Got "..result.."."..ansicolors.reset) -- We want this to be 0A + failcounter = 0 + else + print(ansicolors.red.."Write FAILED."..ansicolors.reset) + failcounter = failcounter + 1 + goto continue + end + + if i % verifyevery == 0 then + result = sendRaw("30"..blockhex, true, true) + if result then -- if false, that's a fail right there + result = string.sub(result, 0, 8) + if result ~= data then + print(ansicolors.red.."Read IMPROPER, supposed to be "..data..", got "..result.."."..ansicolors.reset) + failcounter = failcounter + 1 + goto continue + else + print(ansicolors.green.."Read matches the write."..ansicolors.reset) + failcounter = 0 + end + else + print(ansicolors.red.."Read FAILED."..ansicolors.reset) + failcounter = failcounter + 1 + goto continue + end + end + ::continue:: + + if failcounter >= failmax then + -- close field + lib14a.read(false, false) + return print(ansicolors.red.."Test failed after "..(os.time() - starttime).." seconds, "..(i*(blockend-blockstart)).." writes and "..math.floor((i*(blockend-blockstart))/verifyevery).." reads."..ansicolors.reset) + end + end + + if i % reselectevery == 0 then + -- reselect + sendRaw("", false, false) + if selectCard(true, false, 3) ~= true then + return print("Reselect failed.") + end + print("Reselected card, current rate: "..(i*(blockend-blockstart))/(os.time() - starttime).." writes/s.") + end + end + + -- close field + lib14a.read(false, false) + print("Successfully completed test in "..(os.time() - starttime).." seconds, did "..(loopcount*(blockend-blockstart)).." writes and "..math.floor((loopcount*(blockend-blockstart))/verifyevery).." reads.") +end + +main(args) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 6f70ca2cc..d1855aaff 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -23,7 +23,7 @@ #include "comms.h" #include "lfdemod.h" // for demod code #include "loclass/cipherutils.h" // for decimating samples in getsamples -#include "cmdlfem4x.h" // askem410xdecode +#include "cmdlfem410x.h" // askem410xdecode #include "fileutils.h" // searchFile #include "mifare/ndef.h" #include "cliparser.h" @@ -1702,9 +1702,11 @@ int CmdTuneSamples(const char *Cmd) { if (package->peak_v > NON_VOLTAGE && package->peak_f > 0) PrintAndLogEx(SUCCESS, "LF optimal: %5.2f V - %6.2f kHz", (package->peak_v * ANTENNA_ERROR) / 1000.0, LF_DIV2FREQ(package->peak_f)); + // Empirical measures in mV const double vdd_rdv4 = 9000; - const double vdd_other = 5400; // Empirical measures in mV + const double vdd_other = 5400; double vdd = IfPm3Rdv4Fw() ? vdd_rdv4 : vdd_other; + if (package->peak_v > NON_VOLTAGE && package->peak_f > 0) { // Q measure with Q=f/delta_f @@ -1737,9 +1739,15 @@ int CmdTuneSamples(const char *Cmd) { // cross-check results if (lfq1 > 3) { double approx_vdd = (double)package->peak_v * 3.14 / 2 / lfq1; - if ((approx_vdd > (vdd_rdv4 + vdd_other) / 2) && (! IfPm3Rdv4Fw())) + // Got 8858 on a RDV4 with large antenna 134/14 + // Got 8761 on a non-RDV4 + const double approx_vdd_other_max = 8840; + + // 1% over threshold and supposedly non-RDV4 + if ((approx_vdd > approx_vdd_other_max * 1.01) && (! IfPm3Rdv4Fw())) PrintAndLogEx(WARNING, "Contradicting measures seem to indicate you're running a " _YELLOW_("PM3_OTHER firmware on a RDV4") ", please check your setup"); - if ((approx_vdd < (vdd_rdv4 + vdd_other) / 2) && (IfPm3Rdv4Fw())) + // 1% below threshold and supposedly RDV4 + if ((approx_vdd < approx_vdd_other_max * 0.99) && (IfPm3Rdv4Fw())) PrintAndLogEx(WARNING, "Contradicting measures seem to indicate you're running a " _YELLOW_("PM3_RDV4 firmware on a non-RDV4") ", please check your setup"); } } diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index c8d0a57eb..e5d5042f8 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -211,7 +211,7 @@ static int usage_hf_14a_config(void) { static int usage_hf_14a_sim(void) { PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"); - PrintAndLogEx(NORMAL, "Usage: hf 14a sim [h] t u [x] [e] [v]"); + PrintAndLogEx(NORMAL, "Usage: hf 14a sim [h] t u [n ] [x] [e] [v]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " t : 1 = MIFARE Classic 1k"); @@ -225,6 +225,7 @@ static int usage_hf_14a_sim(void) { PrintAndLogEx(NORMAL, " 9 = FM11RF005SH Shanghai Metro"); PrintAndLogEx(NORMAL, " 10 = JCOP 31/41 Rothult"); PrintAndLogEx(NORMAL, " u : 4, 7 or 10 byte UID"); + PrintAndLogEx(NORMAL, " n : (Optional) Exit simulation after blocks have been read by reader. 0 = infinite"); PrintAndLogEx(NORMAL, " x : (Optional) Performs the 'reader attack', nr/ar attack against a reader"); PrintAndLogEx(NORMAL, " e : (Optional) Fill simulator keys from found keys"); PrintAndLogEx(NORMAL, " v : (Optional) Verbose"); @@ -657,6 +658,7 @@ int CmdHF14ASim(const char *Cmd) { bool errors = false; sector_t *k_sector = NULL; uint8_t k_sectorsCount = 40; + uint8_t exitAfterNReads = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { @@ -693,6 +695,10 @@ int CmdHF14ASim(const char *Cmd) { } cmdp += 2; break; + case 'n': + exitAfterNReads = param_get8(Cmd, cmdp + 1); + cmdp += 2; + break; case 'v': verbose = true; cmdp++; @@ -722,10 +728,12 @@ int CmdHF14ASim(const char *Cmd) { uint8_t tagtype; uint8_t flags; uint8_t uid[10]; + uint8_t exitAfter; } PACKED payload; payload.tagtype = tagtype; payload.flags = flags; + payload.exitAfter = exitAfterNReads; memcpy(payload.uid, uid, uidlen); clearCommandBuffer(); diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 593eaaece..3eebbce74 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1725,7 +1725,7 @@ static int CmdHF15Write(const char *Cmd) { AddCrc15(req, reqlen); reqlen += 2; - PrintAndLogEx(INFO, "iso15693 writing to page %02d (0x%02X) | data ", pagenum, pagenum); + PrintAndLogEx(INFO, "iso15693 writing to page %02d (0x%02X) | data [ %s ] ", pagenum, pagenum, sprint_hex(req, reqlen)); PacketResponseNG resp; clearCommandBuffer(); diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 083e69b21..b051f58c0 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -49,7 +49,7 @@ static int usage_hf_felica_sim(void) { static int usage_hf_felica_sniff(void) { PrintAndLogEx(NORMAL, "\nInfo: It get data from the field and saves it into command buffer. "); - PrintAndLogEx(NORMAL, " Buffer accessible from command 'hf list felica'"); + PrintAndLogEx(NORMAL, " Buffer accessible from command 'hf felica list'"); PrintAndLogEx(NORMAL, "\nUsage: hf felica sniff [-h] [-s] [-t]"); PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -s samples to skip (decimal) max 9999"); diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 284317a47..cd6017c8a 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -51,182 +51,6 @@ static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; -static int usage_hf_iclass_sim(void) { - PrintAndLogEx(NORMAL, "Simulate a iCLASS legacy/standard tag\n"); - PrintAndLogEx(NORMAL, "Usage: hf iCLASS sim [h]