diff --git a/.github/ISSUE_TEMPLATE/checklist-for-release.md b/.github/ISSUE_TEMPLATE/checklist-for-release.md index 193516862..4825270d5 100644 --- a/.github/ISSUE_TEMPLATE/checklist-for-release.md +++ b/.github/ISSUE_TEMPLATE/checklist-for-release.md @@ -51,7 +51,8 @@ make hitag2crack/clean && make hitag2crack && tools/pm3_tests.sh hitag2crack || - [ ] Fedora - [ ] OpenSuse Leap - [ ] OpenSuse Tumbleweed -- [ ] OSX +- [ ] OSX (MacPorts) +- [ ] OSX (Homebrew) - [ ] Android - [ ] Termux diff --git a/CHANGELOG.md b/CHANGELOG.md index 1421f9cbd..eebf307e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,18 @@ 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] + - Changed drastically Hitag S ARM code to remove state machines and ease way to build new commands (@doegox) + - Fixed Hitag S crypto mode with key or NrAr, fixed `lf hitag cc`, fixed pwd dump in hitagS dump with LKP (@doegox) + - Changed `trace list -h` - textual change (@iceman1001) + - Fixed `hf iclass config` - not get stuck when trying to make a keyroll config card (@iceman1001) + - Changed textual output for iclass (@iceman1001) + - Changed `hf iclass reader` to use NG (@iceman1001) + - Changed various notes to have ToC and top links (@iceman1001) + - Added option `lf gprox demod --raw` - now supports decoding of raw bytes (@iceman1001) + - Added option `hf mf gview --pwd` - now supports user supplied password (@iceman1001) + - Added option `--force` to `hf mfu rdb/wrbl` to force operation even if address is out of range (@doegox) + - Added documentation for detailed usage of the Ultimate Magic Card (@doegox) + - Changed HitagS trace record and parsing to deal with partial bytes and to check CRC8 (@doegox) - Added support for KS X 6924 (South Korea's T-money card) (@toucan12) - Fixed `hf 15 dump` - now correctly dumps 256 blocks w/o crashing the client (@iceman1001) - Changed `hf 14a sim -t 3` - anticollision for DESFire simulation now uses different RATS (@mosci) diff --git a/README.md b/README.md index 58b8a6f4a..5decd8b24 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ |[Notes on file formats used with Proxmark3](/doc/extensions_notes.md)|[Notes on MFU binary format](/doc/mfu_binary_format_notes.md)|[Notes on FPGA & ARM](/doc/fpga_arm_notes.md)| |[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode)|[Notes on Magic cards](/doc/magic_cards_notes.md)| |[Notes on Color usage](/doc/colors_notes.md)|[Makefile vs CMake](/doc/md/Development/Makefile-vs-CMake.md)|[Notes on Cloner guns](/doc/cloner_notes.md)| -|[Notes on cliparser usage](/doc/cliparser.md)|[Notes on clocks](/doc/clocks.md)|[Notes on DESFire usage](/doc/desfire.md)| +|[Notes on cliparser usage](/doc/cliparser.md)|[Notes on clocks](/doc/clocks.md)|[Notes on MIFARE DESFire](/doc/desfire.md)| # How to build? diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index 97c2ef5c4..126e6baf1 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -13,6 +13,7 @@ #include "string.h" #include "dbprint.h" #include "pm3_cmd.h" +#include "util.h" // nbytes extern uint32_t _stack_start[], __bss_end__[]; @@ -289,6 +290,13 @@ bool LogTrace_ISO15693(const uint8_t *bytes, uint16_t len, uint32_t ts_start, ui return LogTrace(bytes, len, ts_start, ts_end, parity, reader2tag); } +// specific LogTrace function for bitstreams: the partial byte size is stored in first parity byte. E.g. bitstream "1100 00100010" -> partial byte: 4 bits +bool RAMFUNC LogTraceBits(const uint8_t *btBytes, uint16_t bitLen, uint32_t timestamp_start, uint32_t timestamp_end, bool readerToTag) { + uint8_t parity[(nbytes(bitLen) - 1) / 8 + 1]; + memset(parity, 0x00, sizeof(parity)); + parity[0] = bitLen % 8; + return LogTrace(btBytes, nbytes(bitLen), timestamp_start, timestamp_end, parity, readerToTag); +} // Emulator memory uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length) { diff --git a/armsrc/BigBuf.h b/armsrc/BigBuf.h index 6bdf4e331..435aeb80d 100644 --- a/armsrc/BigBuf.h +++ b/armsrc/BigBuf.h @@ -45,6 +45,7 @@ void set_tracelen(uint32_t value); bool get_tracing(void); bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); +bool RAMFUNC LogTraceBits(const uint8_t *btBytes, uint16_t bitLen, uint32_t timestamp_start, uint32_t timestamp_end, bool readerToTag); bool LogTrace_ISO15693(const uint8_t *bytes, uint16_t len, uint32_t ts_start, uint32_t ts_end, uint8_t *parity, bool reader2tag); uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length); diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index 93c92f92a..a48d839db 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -564,7 +564,7 @@ failtag: err = 1; allKeysFound = false; // used in portable imlementation on microcontroller: it reports back the fail and open the - // standalone lock reply_old(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); + // standalone lock reply_ng(CMD_CJB_FSMSTATE_MENU, NULL, 0); break; } else if (key == -2) { err = 1; // Can't select card. diff --git a/armsrc/Standalone/lf_nexid.c b/armsrc/Standalone/lf_nexid.c index c921fb2bd..f255a79c9 100644 --- a/armsrc/Standalone/lf_nexid.c +++ b/armsrc/Standalone/lf_nexid.c @@ -109,7 +109,7 @@ static uint8_t nexwatch_checksum(uint8_t magic, uint32_t id, uint8_t parity) { static int nexwatch_scamble(NexWatchScramble_t action, uint32_t *id, uint32_t *scambled) { // 255 = Not used/Unknown other values are the bit offset in the ID/FC values - uint8_t hex_2_id [] = { + const uint8_t hex_2_id [] = { 31, 27, 23, 19, 15, 11, 7, 3, 30, 26, 22, 18, 14, 10, 6, 2, 29, 25, 21, 17, 13, 9, 5, 1, diff --git a/armsrc/Standalone/readme.md b/armsrc/Standalone/readme.md index dee415ffa..dacf5057c 100644 --- a/armsrc/Standalone/readme.md +++ b/armsrc/Standalone/readme.md @@ -1,4 +1,19 @@ # Standalone Modes + + + +# Table of Contents +- [Standalone Modes](#standalone-modes) +- [Table of Contents](#table-of-contents) + - [Implementing a standalone mode](#implementing-a-standalone-mode) + - [Naming your standalone mode](#naming-your-standalone-mode) + - [Update MAKEFILE.HAL](#update-makefilehal) + - [Update MAKEFILE.INC](#update-makefileinc) + - [Adding identification string of your mode](#adding-identification-string-of-your-mode) + - [Compiling your standalone mode](#compiling-your-standalone-mode) + - [Submitting your code](#submitting-your-code) + + This contains functionality for different StandAlone modes. The fullimage will be built given the correct compiler flags used. Build targets for these files are contained in `Makefile.inc` and `Makefile.hal` @@ -8,7 +23,9 @@ Have a look at the skeleton standalone mode, in the file `lf_skeleton.c`. As it is now, you can only have one standalone mode installed at the time unless you use the dankarmulti mode (see `dankarmulti.c` on how to use it). To avoid clashes between standalone modes, protect all your static variables with a specific namespace. See how it is done in the existing standalone modes. + ## Implementing a standalone mode +^[Top](#top) We suggest you keep your standalone code inside the `armsrc/Standalone` folder. And that you name your files according to your standalone mode name. @@ -42,6 +59,7 @@ void RunMod(void) { ```` ## Naming your standalone mode +^[Top](#top) We suggest that you follow these guidelines: - Use HF/LF to denote which frequency your mode is targeting. @@ -58,6 +76,7 @@ This leads to your next step, your DEFINE name needed in Makefile. ## Update MAKEFILE.HAL +^[Top](#top) Add your mode to the `Makefile.hal` help and modes list (alphabetically): ``` @@ -82,6 +101,8 @@ STANDALONE_MODES_REQ_BT := ``` ## Update MAKEFILE.INC +^[Top](#top) + Add your source code files like the following sample in the `Makefile.inc` ``` @@ -97,6 +118,8 @@ endif ``` ## Adding identification string of your mode +^[Top](#top) + Do please add a identification string in a function called `ModInfo` inside your source code file. This will enable an easy way to detect on client side which standalone mode has been installed on the device. @@ -107,6 +130,8 @@ void ModInfo(void) { ```` ## Compiling your standalone mode +^[Top](#top) + Once all this is done, you and others can now easily compile different standalone modes by just selecting one of the standalone modes (list in `Makefile.hal` or ) , e.g.: - rename Makefile.platform.sample -> Makefile.platform @@ -143,6 +168,7 @@ When compiling you will see a header showing what configurations your project co Make sure it says your standalone mode name. ## Submitting your code +^[Top](#top) Once you're ready to share your mode, please diff --git a/armsrc/appmain.c b/armsrc/appmain.c index c379951e6..da9c6b9f5 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -23,6 +23,7 @@ #include "printf.h" #include "legicrf.h" #include "BigBuf.h" +#include "iclass_cmd.h" #include "iso14443a.h" #include "iso14443b.h" #include "iso15693.h" @@ -1093,7 +1094,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_LF_HITAGS_TEST_TRACES: { // Tests every challenge within the given file - check_challenges((bool)packet->oldarg[0], packet->data.asBytes, true); + Hitag_check_challenges(packet->data.asBytes, packet->oldarg[0], true); break; } case CMD_LF_HITAGS_READ: { //Reader for only Hitag S tags, args = key or challenge @@ -1574,12 +1575,13 @@ static void PacketReceived(PacketCommandNG *packet) { MifareGen3Freez(); break; } - case CMD_HF_MIFARE_G3_RDBL: { + case CMD_HF_MIFARE_G4_RDBL: { struct p { uint8_t blockno; + uint8_t pwd[4]; } PACKED; struct p *payload = (struct p *) packet->data.asBytes; - MifareG3ReadBlk(payload->blockno); + MifareG4ReadBlk(payload->blockno, payload->pwd); break; } case CMD_HF_MIFARE_PERSONALIZE_UID: { @@ -1684,7 +1686,8 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_HF_ICLASS_READER: { - ReaderIClass(packet->oldarg[0]); + iclass_card_select_t *payload = (iclass_card_select_t *) packet->data.asBytes; + ReaderIClass(payload->flags); break; } case CMD_HF_ICLASS_EML_MEMSET: { diff --git a/armsrc/em4x50.c b/armsrc/em4x50.c index 53b96ae64..8c64baed7 100644 --- a/armsrc/em4x50.c +++ b/armsrc/em4x50.c @@ -682,8 +682,10 @@ void em4x50_login(uint32_t *password, bool ledcontrol) { int status = PM3_EFAILED; if (ledcontrol) LED_C_ON(); if (get_signalproperties() && find_em4x50_tag()) { - if (ledcontrol) LED_C_OFF(); - if (ledcontrol) LED_D_ON(); + if (ledcontrol) { + LED_C_OFF(); + LED_D_ON(); + } status = login(*password); } @@ -700,8 +702,10 @@ void em4x50_brute(em4x50_data_t *etd, bool ledcontrol) { uint32_t pwd = 0x0; if (ledcontrol) LED_C_ON(); if (get_signalproperties() && find_em4x50_tag()) { - if (ledcontrol) LED_C_OFF(); - if (ledcontrol) LED_D_ON(); + if (ledcontrol) { + LED_C_OFF(); + LED_D_ON(); + } bsuccess = brute(etd->password1, etd->password2, &pwd); } @@ -736,8 +740,10 @@ void em4x50_chk(uint8_t *filename, bool ledcontrol) { if (ledcontrol) LED_C_ON(); if (get_signalproperties() && find_em4x50_tag()) { - if (ledcontrol) LED_C_OFF(); - if (ledcontrol) LED_D_ON(); + if (ledcontrol) { + LED_C_OFF(); + LED_D_ON(); + } // try to login with current password for (int i = 0; i < pwd_count; i++) { @@ -859,8 +865,10 @@ void em4x50_read(em4x50_data_t *etd, bool ledcontrol) { if (ledcontrol) LED_C_ON(); if (get_signalproperties() && find_em4x50_tag()) { - if (ledcontrol) LED_C_OFF(); - if (ledcontrol) LED_D_ON(); + if (ledcontrol) { + LED_C_OFF(); + LED_D_ON(); + } bool blogin = true; @@ -888,8 +896,10 @@ void em4x50_info(em4x50_data_t *etd, bool ledcontrol) { if (ledcontrol) LED_C_ON(); if (get_signalproperties() && find_em4x50_tag()) { - if (ledcontrol) LED_C_OFF(); - if (ledcontrol) LED_D_ON(); + if (ledcontrol) { + LED_C_OFF(); + LED_D_ON(); + } bool blogin = true; // login with given password @@ -917,8 +927,10 @@ void em4x50_reader(bool ledcontrol) { if (ledcontrol) LED_C_ON(); if (get_signalproperties() && find_em4x50_tag()) { - if (ledcontrol) LED_C_OFF(); - if (ledcontrol) LED_D_ON(); + if (ledcontrol) { + LED_C_OFF(); + LED_D_ON(); + } standard_read(&now, words); } @@ -1032,8 +1044,10 @@ void em4x50_write(em4x50_data_t *etd, bool ledcontrol) { if (ledcontrol) LED_C_ON(); if (get_signalproperties() && find_em4x50_tag()) { - if (ledcontrol) LED_C_OFF(); - if (ledcontrol) LED_D_ON(); + if (ledcontrol) { + LED_C_OFF(); + LED_D_ON(); + } // if password is given try to login first status = PM3_SUCCESS; @@ -1089,8 +1103,10 @@ void em4x50_writepwd(em4x50_data_t *etd, bool ledcontrol) { if (ledcontrol) LED_C_ON(); if (get_signalproperties() && find_em4x50_tag()) { - if (ledcontrol) LED_C_OFF(); - if (ledcontrol) LED_D_ON(); + if (ledcontrol) { + LED_C_OFF(); + LED_D_ON(); + } // login and change password if (login(etd->password1) == PM3_SUCCESS) { diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 693a5f9d2..376971a97 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -314,8 +314,8 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_ break; } - // LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false); - // LogTrace(tx, nbytes(txlen), 0, 0, NULL, true); + // LogTraceBits(rx, rxlen, 0, 0, false); + // LogTraceBits(tx, txlen, 0, 0, true); if (tag.crypto_active) { hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen / 8, *txlen % 8); @@ -1100,7 +1100,7 @@ void SniffHitag2(bool ledcontrol) { if (rxlen == 0) continue; - LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false); + LogTraceBits(rx, rxlen, 0, 0, false); total_count += nbytes(rxlen); } else { // decode reader comms @@ -1108,7 +1108,7 @@ void SniffHitag2(bool ledcontrol) { total_count += rxlen; // Pack the response into a byte array - // LogTrace(rx, nbytes(rdr), 0, 0, NULL, true); + // LogTraceBits(rx, rdr, 0, 0, true); // total_count += nbytes(rdr); } if (ledcontrol) LED_A_INV(); @@ -1265,7 +1265,7 @@ void SniffHitag2(bool ledcontrol) { // Check if frame was captured if (rxlen) { frame_count++; - LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame); + LogTraceBits(rx, rxlen, response, 0, reader_frame); // Check if we recognize a valid authentication attempt if (nbytes(rxlen) == 8) { @@ -1369,10 +1369,12 @@ void SimulateHitag2(bool ledcontrol) { // use malloc initSampleBufferEx(&signal_size, true); - if (ledcontrol) LED_D_ON(); + if (ledcontrol) { + LED_D_ON(); + LED_A_OFF(); + } // lf_reset_counter(); - if (ledcontrol) LED_A_OFF(); WDT_HIT(); /* @@ -1495,7 +1497,7 @@ void SimulateHitag2(bool ledcontrol) { // Check if frame was captured if (rxlen > 4) { - LogTrace(rx, nbytes(rxlen), response, response, NULL, true); + LogTraceBits(rx, rxlen, response, response, true); // Process the incoming frame (rx) and prepare the outgoing frame (tx) hitag2_handle_reader_command(rx, rxlen, tx, &txlen); @@ -1514,7 +1516,7 @@ void SimulateHitag2(bool ledcontrol) { lf_manchester_send_bytes(tx, txlen, ledcontrol); // Store the frame in the trace - LogTrace(tx, nbytes(txlen), 0, 0, NULL, false); + LogTraceBits(tx, txlen, 0, 0, false); } // Reset the received frame and response timing info @@ -1844,7 +1846,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd, bool ledcontrol) { // and to be able to overwrite the first samples with the trace (since they currently // still use the same memory space) if (txlen > 0) { - LogTrace(tx, nbytes(txlen), command_start, command_start + command_duration, NULL, true); + LogTraceBits(tx, txlen, command_start, command_start + command_duration, true); } // Reset values for receiving frames @@ -1904,7 +1906,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd, bool ledcontrol) { // Check if frame was captured and store it if (rxlen > 0) { - LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false); + LogTraceBits(rx, rxlen, response_start, response_start + response_duration, false); // TODO when using cumulative time for command_start, pm3 doesn't reply anymore, e.g. on lf hitag reader --23 -k 4F4E4D494B52 // Use delta time? @@ -2167,7 +2169,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page, bool ledcontrol) // and to be able to overwrite the first samples with the trace (since they currently // still use the same memory space) if (txlen > 0) { - LogTrace(tx, nbytes(txlen), command_start, command_start + command_duration, NULL, true); + LogTraceBits(tx, txlen, command_start, command_start + command_duration, true); } // Reset values for receiving frames @@ -2225,7 +2227,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page, bool ledcontrol) // Check if frame was captured and store it if (rxlen > 0) { - LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false); + LogTraceBits(rx, rxlen, response_start, response_start + response_duration, false); command_start = 0; } } diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 5ff3d9589..3a047738f 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -25,12 +25,11 @@ #include "commonutil.h" #include "hitag2_crypto.h" #include "lfadc.h" +#include "crc.h" #define CRC_PRESET 0xFF #define CRC_POLYNOM 0x1D -static bool bQuiet; -static bool bSuccessful; static struct hitagS_tag tag; static uint8_t page_to_be_written = 0; static int block_data_left = 0; @@ -48,7 +47,6 @@ static int temp2 = 0; static int sof_bits; // number of start-of-frame bits static uint8_t pwdh0, pwdl0, pwdl1; // password bytes static uint32_t rnd = 0x74124485; // randomnumber -static bool end = false; //#define SENDBIT_TEST /* array index 3 2 1 0 // bytes in sim.bin file are 0 1 2 3 @@ -89,6 +87,7 @@ static bool end = false; #define HITAG_T_WAIT_1 200 /* T_wresp should be 199..206 */ #define HITAG_T_WAIT_2 90 /* T_wresp should be 199..206 */ #define HITAG_T_WAIT_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */ +#define HITAG_T_PROG_MAX 750 #define HITAG_T_TAG_ONE_HALF_PERIOD 10 #define HITAG_T_TAG_TWO_HALF_PERIOD 25 @@ -320,10 +319,13 @@ static int check_select(uint8_t *rx, uint32_t uid) { uint32_t ans = 0x0; for (int i = 0; i < 48; i++) resp[i] = (rx[i / 8] >> (7 - (i % 8))) & 0x1; + for (int i = 0; i < 32; i++) ans += resp[5 + i] << (31 - i); + // global var? temp_uid = ans; + if (ans == tag.uid) return 1; @@ -370,11 +372,13 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, //UID request with a selected response protocol mode if (g_dbglevel >= DBG_EXTENDED) Dbprintf("UID request: length: %i first byte: %02x", rxlen, rx[0]); + tag.pstate = HT_READY; tag.tstate = HT_NO_OP; if ((rx[0] & 0xf0) == 0x30) { if (g_dbglevel >= DBG_EXTENDED) Dbprintf("HT_STANDARD"); + tag.mode = HT_STANDARD; sof_bits = 1; m = AC2K; @@ -383,6 +387,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, tag.mode = HT_ADVANCED; if (g_dbglevel >= DBG_EXTENDED) Dbprintf("HT_ADVANCED"); + sof_bits = 3; m = AC2K; } @@ -390,36 +395,45 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, if ((rx[0] & 0xf0) == 0xd0) { if (g_dbglevel >= DBG_EXTENDED) Dbprintf("HT_FAST_ADVANCED"); + tag.mode = HT_FAST_ADVANCED; sof_bits = 3; m = AC4K; } //send uid as a response *txlen = 32; - for (int i = 0; i < 4; i++) - tx[i] = (tag.uid >> (24 - (i * 8))) & 0xff; + for (int i = 0; i < 4; i++) { + tx[i] = (tag.uid >> (24 - (i * 8))) & 0xFF; + } } break; case 45: { //select command from reader received if (g_dbglevel >= DBG_EXTENDED) DbpString("SELECT"); + if (check_select(rx, tag.uid) == 1) { if (g_dbglevel >= DBG_EXTENDED) DbpString("SELECT match"); + //if the right tag was selected *txlen = 32; hitagS_set_frame_modulation(); //send configuration - for (int i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) { tx[i] = tag.pages[1][i]; + } + tx[3] = 0xff; + if (tag.mode != HT_STANDARD) { *txlen = 40; crc = CRC_PRESET; - for (int i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) { calc_crc(&crc, tx[i], 8); + } + tx[4] = crc; } } @@ -435,18 +449,22 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, REV32((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0]) ); Dbprintf(",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}", - rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]); + rx[0], rx[1], rx[2], rx[3], + rx[4], rx[5], rx[6], rx[7] + ); hitagS_set_frame_modulation(); - for (int i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) { _hitag2_byte(&state); + } //send con2, pwdh0, pwdl0, pwdl1 encrypted as a response tx[0] = _hitag2_byte(&state) ^ tag.pages[1][2]; tx[1] = _hitag2_byte(&state) ^ tag.pwdh0; tx[2] = _hitag2_byte(&state) ^ tag.pwdl0; tx[3] = _hitag2_byte(&state) ^ tag.pwdl1; + if (tag.mode != HT_STANDARD) { //add crc8 *txlen = 40; @@ -492,6 +510,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, tx[0] = 0x40; page_to_be_written = 0; hitagS_set_frame_modulation(); + } else if (tag.tstate == HT_WRITING_BLOCK_DATA) { tag.pages[page_to_be_written][0] = rx[0]; tag.pages[page_to_be_written][1] = rx[1]; @@ -503,6 +522,7 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, hitagS_set_frame_modulation(); page_to_be_written++; block_data_left--; + if (block_data_left == 0) { tag.tstate = HT_NO_OP; page_to_be_written = 0; @@ -519,8 +539,10 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, tx[1] = tag.pages[page][1]; tx[2] = tag.pages[page][2]; tx[3] = tag.pages[page][3]; - if (tag.LKP && page == 1) - tx[3] = 0xff; + + if (tag.LKP && page == 1) { + tx[3] = 0xFF; + } hitagS_set_frame_modulation(); @@ -528,8 +550,9 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, //add crc8 *txlen = 40; crc = CRC_PRESET; - for (int i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) { calc_crc(&crc, tx[i], 8); + } tx[4] = crc; } @@ -555,8 +578,9 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, //add crc8 *txlen = 32 * 4 + 8; crc = CRC_PRESET; - for (int i = 0; i < 16; i++) + for (int i = 0; i < 16; i++) { calc_crc(&crc, tx[i], 8); + } tx[16] = crc; } @@ -602,253 +626,6 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, } } -/* - * to authenticate to a tag with the given key or challenge - */ -static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrAr, uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) { - uint8_t rx_air[HITAG_FRAME_LEN]; - int response_bit[200]; - unsigned char mask = 1; - unsigned char uid[32]; - unsigned char crc; - uint64_t state; - uint8_t auth_ks[4]; - uint8_t conf_pages[3]; - memcpy(rx_air, rx, nbytes(rxlen)); - *txlen = 0; - - if (tag.pstate == HT_READY && rxlen >= 67) { - //received uid - if (end == true) { - Dbprintf("authentication failed!"); - return -1; - } - int z = 0; - for (int i = 0; i < 10; i++) { - for (int j = 0; j < 8; j++) { - response_bit[z] = 0; - if ((rx[i] & ((mask << 7) >> j)) != 0) - response_bit[z] = 1; - z++; - } - } - uint16_t k = 0; - for (int i = 5; i < z; i += 2) { - uid[k] = response_bit[i]; - k++; - if (k > 31) - break; - } - uint8_t uid1 = (uid[0] << 7) - | (uid[1] << 6) - | (uid[2] << 5) - | (uid[3] << 4) - | (uid[4] << 3) - | (uid[5] << 2) - | (uid[6] << 1) - | uid[7]; - - uint8_t uid2 = (uid[8] << 7) - | (uid[9] << 6) - | (uid[10] << 5) - | (uid[11] << 4) - | (uid[12] << 3) - | (uid[13] << 2) - | (uid[14] << 1) - | uid[15]; - - uint8_t uid3 = (uid[16] << 7) - | (uid[17] << 6) - | (uid[18] << 5) - | (uid[19] << 4) - | (uid[20] << 3) - | (uid[21] << 2) - | (uid[22] << 1) - | uid[23]; - - uint8_t uid4 = (uid[24] << 7) - | (uid[25] << 6) - | (uid[26] << 5) - | (uid[27] << 4) - | (uid[28] << 3) - | (uid[29] << 2) - | (uid[30] << 1) - | uid[31]; - - if (g_dbglevel >= DBG_EXTENDED) - Dbprintf("UID: %02X %02X %02X %02X", uid1, uid2, uid3, uid4); - - tag.uid = (uid4 << 24 | uid3 << 16 | uid2 << 8 | uid1); - - //select uid - *txlen = 45; - crc = CRC_PRESET; - calc_crc(&crc, 0x00, 5); - calc_crc(&crc, uid1, 8); - calc_crc(&crc, uid2, 8); - calc_crc(&crc, uid3, 8); - calc_crc(&crc, uid4, 8); - - for (int i = 0; i < 100; i++) { - response_bit[i] = 0; - } - - for (int i = 0; i < 5; i++) { - response_bit[i] = 0; - } - { - int i = 5; - for (; i < 37; i++) { - response_bit[i] = uid[i - 5]; - } - - for (int j = 0; j < 8; j++) { - response_bit[i] = 0; - if ((crc & ((mask << 7) >> j)) != 0) - response_bit[i] = 1; - i++; - } - } - k = 0; - for (int i = 0; i < 6; i++) { - tx[i] = (response_bit[k] << 7) - | (response_bit[k + 1] << 6) - | (response_bit[k + 2] << 5) - | (response_bit[k + 3] << 4) - | (response_bit[k + 4] << 3) - | (response_bit[k + 5] << 2) - | (response_bit[k + 6] << 1) - | response_bit[k + 7]; - - k += 8; - } - - tag.pstate = HT_INIT; - } else if (tag.pstate == HT_INIT && rxlen == 44) { - // received configuration after select command - int z = 0; - for (int i = 0; i < 6; i++) { - for (int j = 0; j < 8; j++) { - response_bit[z] = 0; - if ((rx[i] & ((mask << 7) >> j)) != 0) - response_bit[z] = 1; - z++; - } - } - conf_pages[0] = ((response_bit[4] << 7) | (response_bit[5] << 6) - | (response_bit[6] << 5) | (response_bit[7] << 4) - | (response_bit[8] << 3) | (response_bit[9] << 2) - | (response_bit[10] << 1) | response_bit[11]); - //check which memorysize this tag has - if (response_bit[10] == 0 && response_bit[11] == 0) - tag.max_page = 32 / 32; - if (response_bit[10] == 0 && response_bit[11] == 1) - tag.max_page = 256 / 32; - if (response_bit[10] == 1 && response_bit[11] == 0) - tag.max_page = 2048 / 32; - conf_pages[1] = ((response_bit[12] << 7) | (response_bit[13] << 6) - | (response_bit[14] << 5) | (response_bit[15] << 4) - | (response_bit[16] << 3) | (response_bit[17] << 2) - | (response_bit[18] << 1) | response_bit[19]); - tag.auth = response_bit[12]; - tag.TTFC = response_bit[13]; - //tag.TTFDR in response_bit[14] and response_bit[15] - //tag.TTFM in response_bit[16] and response_bit[17] - tag.LCON = response_bit[18]; - tag.LKP = response_bit[19]; - conf_pages[2] = ((response_bit[20] << 7) | (response_bit[21] << 6) - | (response_bit[22] << 5) | (response_bit[23] << 4) - | (response_bit[24] << 3) | (response_bit[25] << 2) - | (response_bit[26] << 1) | response_bit[27]); - tag.LCK7 = response_bit[20]; - tag.LCK6 = response_bit[21]; - tag.LCK5 = response_bit[22]; - tag.LCK4 = response_bit[23]; - tag.LCK3 = response_bit[24]; - tag.LCK2 = response_bit[25]; - tag.LCK1 = response_bit[26]; - tag.LCK0 = response_bit[27]; - - if (g_dbglevel >= DBG_EXTENDED) - Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0], conf_pages[1], conf_pages[2]); - - if (tag.auth == 1) { - //if the tag is in authentication mode try the key or challenge - *txlen = 64; - if (end != true) { - if (htf == 02 || htf == 04) { //RHTS_KEY //WHTS_KEY - state = _hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd)); - - for (int i = 0; i < 4; i++) { - auth_ks[i] = _hitag2_byte(&state) ^ 0xff; - } - *txlen = 64; - tx[0] = rnd & 0xff; - tx[1] = (rnd >> 8) & 0xff; - tx[2] = (rnd >> 16) & 0xff; - tx[3] = (rnd >> 24) & 0xff; - - tx[4] = auth_ks[0]; - tx[5] = auth_ks[1]; - tx[6] = auth_ks[2]; - tx[7] = auth_ks[3]; - if (g_dbglevel >= DBG_EXTENDED) - Dbprintf("%02X %02X %02X %02X %02X %02X %02X %02X", tx[0], - tx[1], tx[2], tx[3], tx[4], tx[5], tx[6], tx[7]); - } else if (htf == 01 || htf == 03) { //RHTS_CHALLENGE //WHTS_CHALLENGE - for (int i = 0; i < 8; i++) - tx[i] = ((NrAr >> (56 - (i * 8))) & 0xff); - } - end = true; - tag.pstate = HT_AUTHENTICATE; - } else { - Dbprintf("authentication failed!"); - return -1; - } - } else if (tag.auth == 0) { - tag.pstate = HT_SELECTED; - } - - } else if (tag.pstate == HT_AUTHENTICATE && rxlen == 44) { - //encrypted con2,password received. - crc = CRC_PRESET; - calc_crc(&crc, 0x80, 1); - calc_crc(&crc, ((rx[0] & 0x0f) * 16 + ((rx[1] & 0xf0) / 16)), 8); - calc_crc(&crc, ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)), 8); - calc_crc(&crc, ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)), 8); - calc_crc(&crc, ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)), 8); - if (g_dbglevel >= DBG_EXTENDED) { - Dbprintf("UID:::%X", tag.uid); - Dbprintf("RND:::%X", rnd); - } - - //decrypt password - pwdh0 = 0; - pwdl0 = 0; - pwdl1 = 0; - if (htf == 02 || htf == 04) { //RHTS_KEY //WHTS_KEY - { - state = _hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd)); - for (int i = 0; i < 5; i++) - _hitag2_byte(&state); - - pwdh0 = ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)) ^ _hitag2_byte(&state); - pwdl0 = ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)) ^ _hitag2_byte(&state); - pwdl1 = ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)) ^ _hitag2_byte(&state); - } - - if (g_dbglevel >= DBG_EXTENDED) - Dbprintf("pwdh0 %02X pwdl0 %02X pwdl1 %02X", pwdh0, pwdl0, pwdl1); - - //Dbprintf("%X %02X", rnd, ((rx[4] & 0x0f) * 16) + ((rx[5] & 0xf0) / 16)); - //rnd += 1; - } - tag.pstate = HT_SELECTED; //tag is now ready for read/write commands - } - return 0; - -} - /* * Emulates a Hitag S Tag with the given data from the .hts file */ @@ -860,7 +637,6 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data, bool ledcontrol) { int response = 0, overflow = 0; uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; - bQuiet = false; uint8_t txbuf[HITAG_FRAME_LEN]; uint8_t *tx = txbuf; size_t txlen = 0; @@ -884,9 +660,11 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data, bool ledcontrol) { // read tag data into memory if (tag_mem_supplied) { - for (int i = 0; i < 16; i++) - for (int j = 0; j < 4; j++) + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 4; j++) { tag.pages[i][j] = 0x0; + } + } DbpString("Loading hitagS memory..."); memcpy((uint8_t *)tag.pages, data, 4 * 64); @@ -901,58 +679,87 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data, bool ledcontrol) { (((uint64_t)tag.pages[3][0]) << 16) | (((uint64_t)tag.pages[2][3]) << 8) | (((uint64_t)tag.pages[2][2])); + tag.pwdl0 = tag.pages[2][0]; tag.pwdl1 = tag.pages[2][1]; tag.pwdh0 = tag.pages[1][3]; //con0 tag.max_page = 64; - if ((tag.pages[1][0] & 0x2) == 0 && (tag.pages[1][0] & 0x1) == 1) + + if ((tag.pages[1][0] & 0x2) == 0 && (tag.pages[1][0] & 0x1) == 1) { tag.max_page = 8; - if ((tag.pages[1][0] & 0x2) == 0 && (tag.pages[1][0] & 0x1) == 0) + } + + if ((tag.pages[1][0] & 0x2) == 0 && (tag.pages[1][0] & 0x1) == 0) { tag.max_page = 0; + } + if (g_dbglevel >= DBG_EXTENDED) - for (int i = 0; i < tag.max_page; i++) + for (int i = 0; i < tag.max_page; i++) { Dbprintf("Page[%2d]: %02X %02X %02X %02X", i, - (tag.pages[i][3]) & 0xff, - (tag.pages[i][2]) & 0xff, - (tag.pages[i][1]) & 0xff, - tag.pages[i][0] & 0xff); + (tag.pages[i][3]) & 0xFF, + (tag.pages[i][2]) & 0xFF, + (tag.pages[i][1]) & 0xFF, + tag.pages[i][0] & 0xFF + ); + } //con1 tag.auth = 0; - if ((tag.pages[1][1] & 0x80) == 0x80) + if ((tag.pages[1][1] & 0x80) == 0x80) { tag.auth = 1; + } + tag.LCON = 0; - if ((tag.pages[1][1] & 0x2) == 0x02) + if ((tag.pages[1][1] & 0x2) == 0x02) { tag.LCON = 1; + } + tag.LKP = 0; - if ((tag.pages[1][1] & 0x1) == 0x01) + if ((tag.pages[1][1] & 0x1) == 0x01) { tag.LKP = 1; + } + //con2 //0=read write 1=read only tag.LCK7 = 0; - if ((tag.pages[1][2] & 0x80) == 0x80) + if ((tag.pages[1][2] & 0x80) == 0x80) { tag.LCK7 = 1; + } + tag.LCK6 = 0; - if ((tag.pages[1][2] & 0x40) == 0x040) + if ((tag.pages[1][2] & 0x40) == 0x040) { tag.LCK6 = 1; + } + tag.LCK5 = 0; - if ((tag.pages[1][2] & 0x20) == 0x20) + if ((tag.pages[1][2] & 0x20) == 0x20) { tag.LCK5 = 1; + } + tag.LCK4 = 0; - if ((tag.pages[1][2] & 0x10) == 0x10) + if ((tag.pages[1][2] & 0x10) == 0x10) { tag.LCK4 = 1; + } + tag.LCK3 = 0; - if ((tag.pages[1][2] & 0x8) == 0x08) + if ((tag.pages[1][2] & 0x8) == 0x08) { tag.LCK3 = 1; + } + tag.LCK2 = 0; - if ((tag.pages[1][2] & 0x4) == 0x04) + if ((tag.pages[1][2] & 0x4) == 0x04) { tag.LCK2 = 1; + } + tag.LCK1 = 0; - if ((tag.pages[1][2] & 0x2) == 0x02) + if ((tag.pages[1][2] & 0x2) == 0x02) { tag.LCK1 = 1; + } + tag.LCK0 = 0; - if ((tag.pages[1][2] & 0x1) == 0x01) + if ((tag.pages[1][2] & 0x1) == 0x01) { tag.LCK0 = 1; + } // Set up simulator mode, frequency divisor which will drive the FPGA @@ -1035,8 +842,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data, bool ledcontrol) { // Check if frame was captured if (rxlen > 0) { -// frame_count++; - LogTrace(rx, nbytes(rxlen), response, response, NULL, true); + LogTraceBits(rx, rxlen, response, response, true); // Disable timer 1 with external trigger to avoid triggers during our own modulation AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; @@ -1055,7 +861,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data, bool ledcontrol) { if (txlen > 0) { // Transmit the tag frame hitag_send_frame(tx, txlen, ledcontrol); - LogTrace(tx, nbytes(txlen), 0, 0, NULL, false); + LogTraceBits(tx, txlen, 0, 0, false); } // Enable and reset external trigger in timer for capturing future frames @@ -1084,37 +890,54 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data, bool ledcontrol) { DbpString("Sim Stopped"); } -static void hitagS_receive_frame(uint8_t *rx, size_t *rxlen, int *response, bool ledcontrol) { +static void hitagS_receive_frame(uint8_t *rx, size_t sizeofrx, size_t *rxlen, uint32_t *resptime, bool ledcontrol) { // Reset values for receiving frames - memset(rx, 0x00, HITAG_FRAME_LEN * sizeof(uint8_t)); + memset(rx, 0x00, sizeofrx); *rxlen = 0; int lastbit = 1; bool bSkip = true; - int tag_sof = 1; - *response = 0; + *resptime = 0; uint32_t errorCount = 0; + // clk overflow but I failed moving TC0 & TC1 to + // slower clock AT91C_TC_CLKS_TIMER_DIV3_CLOCK + // so tracking overflow manually... + uint32_t overcount = 0; + uint32_t prevcv = 0; + bool bStarted = false; // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { + while (AT91C_BASE_TC0->TC_CV + (overcount << 16) < (T0 * HITAG_T_PROG_MAX)) { + // detect and track counter overflows + + uint32_t tmpcv = AT91C_BASE_TC0->TC_CV; + if (tmpcv < prevcv) { + overcount++; + } + prevcv = tmpcv; + // Check if falling edge in tag modulation is detected if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { // Retrieve the new timing values - int ra = (AT91C_BASE_TC1->TC_RA / T0); - + uint32_t ra = (AT91C_BASE_TC1->TC_RA + (overcount << 16)) / T0; // Reset timer every frame, we have to capture the last edge for timing AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + prevcv = 0; + overcount = 0; if (ledcontrol) LED_B_ON(); // Capture tag frame (manchester decoding using only falling edges) - if (ra >= HITAG_T_EOF) { - if (*rxlen != 0) { - //DbpString("weird1?"); + + if (!bStarted) { + if (ra >= HITAG_T_EOF) { + bStarted = true; + // Capture the T0 periods that have passed since last communication or field drop (reset) + // We always receive a 'one' first, which has the falling edge after a half period |-_| + *resptime = ra - HITAG_T_TAG_HALF_PERIOD; + } else { + errorCount++; } - // Capture the T0 periods that have passed since last communication or field drop (reset) - // We always receive a 'one' first, which has the falling edge after a half period |-_| - *response = ra - HITAG_T_TAG_HALF_PERIOD; } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { // Manchester coding example |-_|_-|-_| (101) rx[(*rxlen) / 8] |= 0 << (7 - ((*rxlen) % 8)); @@ -1134,14 +957,9 @@ static void hitagS_receive_frame(uint8_t *rx, size_t *rxlen, int *response, bool bSkip = !bSkip; } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { // Manchester coding example |_-|_-| (00) or |-_|-_| (11) - if (tag_sof) { - // Ignore bits that are transmitted during SOF - tag_sof--; - } else { - // bit is same as last bit - rx[(*rxlen) / 8] |= lastbit << (7 - ((*rxlen) % 8)); - (*rxlen)++; - } + // bit is same as last bit + rx[(*rxlen) / 8] |= lastbit << (7 - ((*rxlen) % 8)); + (*rxlen)++; } else { // Ignore weird value, is to small to mean anything errorCount++; @@ -1153,80 +971,90 @@ static void hitagS_receive_frame(uint8_t *rx, size_t *rxlen, int *response, bool // We can break this loop if we received the last bit from a frame if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { - if ((*rxlen) > 0) + if ((*rxlen) > 0) { break; + } } } + // Dbprintf("RX0 %i:%02X.. err:%i resptime:%i", *rxlen, rx[0], errorCount, *resptime); } -/* - * Authenticates to the Tag with the given key or challenge. - * If the key was given the password will be decrypted. - * Reads every page of a hitag S transpoder. - */ -void ReadHitagS(hitag_function htf, hitag_data *htd, bool ledcontrol) { +static void sendReceiveHitagS(uint8_t *tx, size_t txlen, uint8_t *rx, size_t sizeofrx, size_t *prxbits, int t_wait, bool ledcontrol, bool ac_seq) { + LogTraceBits(tx, txlen, HITAG_T_WAIT_2, HITAG_T_WAIT_2, true); + + // Send and store the reader command + // Disable timer 1 with external trigger to avoid triggers during our own modulation + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + + // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, + // Since the clock counts since the last falling edge, a 'one' means that the + // falling edge occurred halfway the period. with respect to this falling edge, + // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. + // All timer values are in terms of T0 units + + while (AT91C_BASE_TC0->TC_CV < T0 * t_wait) {}; + + // Transmit the reader frame + hitag_reader_send_frame(tx, txlen, ledcontrol); + + // Enable and reset external trigger in timer for capturing future frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + + uint32_t resptime = 0; + size_t rxlen = 0; + hitagS_receive_frame(rx, sizeofrx, &rxlen, &resptime, ledcontrol); + int k = 0; + // Check if frame was captured and store it + if (rxlen > 0) { + uint8_t response_bit[sizeofrx * 8]; + for (int i = 0; i < rxlen; i++) { + response_bit[i] = (rx[i / 8] >> (7 - (i % 8))) & 1; + } + memset(rx, 0x00, sizeofrx); + if (ac_seq) { + // Tag Response is AC encoded + for (int i = 6; i < rxlen; i += 2) { + rx[k / 8] |= response_bit[i] << (7 - (k % 8)); + k++; + if (k >= 8 * sizeofrx) + break; + } + } else { + for (int i = 5; i < rxlen; i++) { // ignore first 5 bits: SOF (actually 1 or 6 depending on response protocol) + rx[k / 8] |= response_bit[i] << (7 - (k % 8)); + k++; + if (k >= 8 * sizeofrx) + break; + } + } + LogTraceBits(rx, k, resptime, resptime, false); + } + *prxbits = k; +} + +static size_t concatbits(uint8_t *dstbuf, size_t dstbufskip, uint8_t *srcbuf, size_t srcbufstart, size_t srcbuflen) { + // erase dstbuf bits that will be overriden + dstbuf[dstbufskip / 8] &= 0xFF - ((1 << (7 - (dstbufskip % 8) + 1)) - 1); + for (size_t i = (dstbufskip / 8) + 1; i <= (dstbufskip + srcbuflen) / 8; i++) { + dstbuf[i] = 0; + } + for (size_t i = 0; i < srcbuflen; i++) { + // equiv of dstbufbits[dstbufskip + i] = srcbufbits[srcbufstart + i] + dstbuf[(dstbufskip + i) / 8] |= ((srcbuf[(srcbufstart + i) / 8] >> (7 - ((srcbufstart + i) % 8))) & 1) << (7 - ((dstbufskip + i) % 8)); + } + return dstbufskip + srcbuflen; +} + +static int selectHitagS(hitag_function htf, hitag_data *htd, uint8_t *tx, size_t sizeoftx, uint8_t *rx, size_t sizeofrx, int t_wait, bool ledcontrol) { StopTicks(); - int i, j, z, k; -// int frame_count = 0; - int response = 0; - int response_bit[200]; - uint8_t rx[HITAG_FRAME_LEN]; - size_t rxlen = 0; - uint8_t txbuf[HITAG_FRAME_LEN]; - uint8_t *tx = txbuf; - size_t txlen = 0; - int lastbit = 1; - int t_wait = HITAG_T_WAIT_MAX; - bool bStop = false; - int pageNum = 0; - unsigned char mask = 1; - unsigned char crc; - unsigned char pageData[32]; - page_to_be_written = 0; - - //read given key/challenge - uint8_t NrAr_[8]; - uint64_t key = 0; - uint64_t NrAr = 0; - uint8_t key_[6]; - - tag.pstate = HT_READY; - tag.tstate = HT_NO_OP; - - switch (htf) { - case RHTSF_CHALLENGE: { - DbpString("Authenticating using nr,ar pair:"); - memcpy(NrAr_, htd->auth.NrAr, 8); - Dbhexdump(8, NrAr_, false); - NrAr = NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 | - ((uint64_t)NrAr_[2]) << 40 | ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56; - break; - } - case RHTSF_KEY: { - DbpString("Authenticating using key:"); - memcpy(key_, htd->crypto.key, 6); - Dbhexdump(6, key_, false); - key = key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40; - break; - } - default: { - Dbprintf("Error , unknown function: %d", htf); - return; - } - } - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - // Reset the return status - bSuccessful = false; // Clean up trace and prepare it for storing frames set_tracing(true); clear_trace(); - bQuiet = false; - if (ledcontrol) LED_D_ON(); // Set fpga in edge detect with reader field, we can modulate as reader now @@ -1269,370 +1097,337 @@ void ReadHitagS(hitag_function htf, hitag_data *htd, bool ledcontrol) { // synchronized startup procedure while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero - // Reset the received frame, frame count and timing info - t_wait = 200; - while (!bStop && !BUTTON_PRESS() && !data_available()) { + + //start authentication + size_t txlen = 0; + size_t rxlen = 0; + uint8_t cmd = 0x18; + txlen = concatbits(tx, txlen, &cmd, 8 - 5, 5); + sendReceiveHitagS(tx, txlen, rx, sizeofrx, &rxlen, t_wait, ledcontrol, true); + + if (rxlen != 32) { + Dbprintf("UID Request failed!"); + return -1; + } + + tag.uid = (rx[3] << 24 | rx[2] << 16 | rx[1] << 8 | rx[0]); + if (g_dbglevel >= DBG_EXTENDED) + Dbprintf("UID: %02X %02X %02X %02X", rx[0], rx[1], rx[2], rx[3]); + //select uid + txlen = 0; + cmd = 0x00; + txlen = concatbits(tx, txlen, &cmd, 8 - 5, 5); + txlen = concatbits(tx, txlen, rx, 0, 32); + uint8_t crc = CRC8Hitag1Bits(tx, txlen); + txlen = concatbits(tx, txlen, &crc, 0, 8); + + sendReceiveHitagS(tx, txlen, rx, sizeofrx, &rxlen, t_wait, ledcontrol, false); + + if (rxlen != 40) { + Dbprintf("Select UID failed! %i", rxlen); + return -1; + } + + uint8_t conf_pages[3]; + conf_pages[0] = rx[0]; + + //check which memorysize this tag has + if ((conf_pages[0] & 0x3) == 0x00) { + tag.max_page = 32 / 32; + } else if ((conf_pages[0] & 0x3) == 0x1) { + tag.max_page = 256 / 32; + } else if ((conf_pages[0] & 0x3) == 0x2) { + tag.max_page = 2048 / 32; + } + + conf_pages[1] = rx[1]; + tag.auth = (conf_pages[1] >> 7) & 0x1; + tag.TTFC = (conf_pages[1] >> 6) & 0x1; + tag.TTFDR = (conf_pages[1] >> 5) & 0x3; + tag.TTFM = (conf_pages[1] >> 3) & 0x3; + tag.LCON = (conf_pages[1] >> 1) & 0x1; + tag.LKP = (conf_pages[1] >> 0) & 0x1; + + conf_pages[2] = rx[2]; + + tag.LCK7 = (conf_pages[2] >> 7) & 0x1; + tag.LCK6 = (conf_pages[2] >> 6) & 0x1; + tag.LCK5 = (conf_pages[2] >> 5) & 0x1; + tag.LCK4 = (conf_pages[2] >> 4) & 0x1; + tag.LCK3 = (conf_pages[2] >> 3) & 0x1; + tag.LCK2 = (conf_pages[2] >> 2) & 0x1; + tag.LCK1 = (conf_pages[2] >> 1) & 0x1; + tag.LCK0 = (conf_pages[2] >> 0) & 0x1; + + if (g_dbglevel >= DBG_EXTENDED) + Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0], conf_pages[1], conf_pages[2]); + + if (tag.auth == 1) { + uint64_t key = 0; + //if the tag is in authentication mode try the key or challenge + if (htf == RHTSF_KEY || htf == WHTSF_KEY) { + if (g_dbglevel >= DBG_EXTENDED) { + DbpString("Authenticating using key:"); + Dbhexdump(6, htd->crypto.key, false); + } + key = ((uint64_t)htd->crypto.key[0]) << 0 | + ((uint64_t)htd->crypto.key[1]) << 8 | + ((uint64_t)htd->crypto.key[2]) << 16 | + ((uint64_t)htd->crypto.key[3]) << 24 | + ((uint64_t)htd->crypto.key[4]) << 32 | + ((uint64_t)htd->crypto.key[5]) << 40 + ; + uint64_t state = _hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd)); + uint8_t auth_ks[4]; + for (int i = 0; i < 4; i++) { + auth_ks[i] = _hitag2_byte(&state) ^ 0xff; + } + + txlen = 0; + uint8_t revrnd[4] = {rnd, rnd >> 8, rnd >> 16, rnd >> 24}; + txlen = concatbits(tx, txlen, revrnd, 0, 32); + txlen = concatbits(tx, txlen, auth_ks, 0, 32); + + if (g_dbglevel >= DBG_EXTENDED) + Dbprintf("%02X %02X %02X %02X %02X %02X %02X %02X", tx[0], + tx[1], tx[2], tx[3], tx[4], tx[5], tx[6], tx[7]); + + } else if (htf == RHTSF_CHALLENGE || htf == WHTSF_CHALLENGE) { + if (g_dbglevel >= DBG_EXTENDED) { + DbpString("Authenticating using nr,ar pair:"); + Dbhexdump(8, htd->auth.NrAr, false); + } + uint64_t NrAr = 0; + NrAr = ((uint64_t)htd->auth.NrAr[7]) << 0 | + ((uint64_t)htd->auth.NrAr[6]) << 8 | + ((uint64_t)htd->auth.NrAr[5]) << 16 | + ((uint64_t)htd->auth.NrAr[4]) << 24 | + ((uint64_t)htd->auth.NrAr[3]) << 32 | + ((uint64_t)htd->auth.NrAr[2]) << 40 | + ((uint64_t)htd->auth.NrAr[1]) << 48 | + ((uint64_t)htd->auth.NrAr[0]) << 56; + txlen = 64; + for (int i = 0; i < 8; i++) { + tx[i] = ((NrAr >> (56 - (i * 8))) & 0xFF); + } + } else { + Dbprintf("Error , unknown function: %d", htf); + return -1; + } + + sendReceiveHitagS(tx, txlen, rx, sizeofrx, &rxlen, t_wait, ledcontrol, false); + + if (rxlen != 40) { + Dbprintf("Authenticate failed! %i", rxlen); + return -1; + } + + //encrypted con2,password received. + if (g_dbglevel >= DBG_EXTENDED) { + Dbprintf("UID:::%X", tag.uid); + Dbprintf("RND:::%X", rnd); + } + + //decrypt password + pwdh0 = 0; + pwdl0 = 0; + pwdl1 = 0; + if (htf == RHTSF_KEY || htf == WHTSF_KEY) { + uint64_t state = _hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd)); + for (int i = 0; i < 4; i++) { + _hitag2_byte(&state); + } + uint8_t con2 = rx[0] ^ _hitag2_byte(&state); + pwdh0 = rx[1] ^ _hitag2_byte(&state); + pwdl0 = rx[2] ^ _hitag2_byte(&state); + pwdl1 = rx[3] ^ _hitag2_byte(&state); + + if (g_dbglevel >= DBG_EXTENDED) + Dbprintf("con2 %02X pwdh0 %02X pwdl0 %02X pwdl1 %02X", con2, pwdh0, pwdl0, pwdl1); + + //Dbprintf("%X %02X", rnd, ((rx[4] & 0x0f) * 16) + ((rx[5] & 0xf0) / 16)); + //rnd += 1; + } + } + return 0; +} + +/* + * Authenticates to the Tag with the given key or challenge. + * If the key was given the password will be decrypted. + * Reads every page of a hitag S transpoder. + */ +void ReadHitagS(hitag_function htf, hitag_data *htd, bool ledcontrol) { + + uint8_t rx[HITAG_FRAME_LEN]; + size_t rxlen = 0; + uint8_t tx[HITAG_FRAME_LEN]; + size_t txlen = 0; + int t_wait = HITAG_T_WAIT_MAX; + + + if (selectHitagS(htf, htd, tx, ARRAYLEN(tx), rx, ARRAYLEN(rx), t_wait, ledcontrol) == -1) { + set_tracing(false); + lf_finalize(ledcontrol); + reply_mix(CMD_ACK, 0, 0, 0, 0, 0); + return; + } + int pageNum = 0; + while (!BUTTON_PRESS() && !data_available()) { WDT_HIT(); - // Check if frame was captured and store it - if (rxlen > 0) { -// frame_count++; - LogTrace(rx, nbytes(rxlen), response, response, NULL, false); - } - - // By default reset the transmission buffer - tx = txbuf; + //send read request txlen = 0; + uint8_t cmd = 0x0c; + txlen = concatbits(tx, txlen, &cmd, 8 - 4, 4); + uint8_t addr = pageNum; + txlen = concatbits(tx, txlen, &addr, 0, 8); + uint8_t crc = CRC8Hitag1Bits(tx, txlen); + txlen = concatbits(tx, txlen, &crc, 0, 8); + + sendReceiveHitagS(tx, txlen, rx, ARRAYLEN(rx), &rxlen, t_wait, ledcontrol, false); if (rxlen == 0) { - //start authentication - txlen = 5; - memcpy(tx, "\xC0", nbytes(txlen)); - tag.pstate = HT_READY; - tag.tstate = HT_NO_OP; - } else if (tag.pstate != HT_SELECTED) { - if (hitagS_handle_tag_auth(htf, key, NrAr, rx, rxlen, tx, &txlen) == -1) - bStop = !false; + Dbprintf("Read page failed!"); + break; } - if (tag.pstate == HT_SELECTED && tag.tstate == HT_NO_OP && rxlen > 0) { - //send read request - tag.tstate = HT_READING_PAGE; - txlen = 20; - crc = CRC_PRESET; - tx[0] = 0xc0 + (pageNum / 16); - calc_crc(&crc, tx[0], 8); - calc_crc(&crc, 0x00 + ((pageNum % 16) * 16), 4); - tx[1] = 0x00 + ((pageNum % 16) * 16) + (crc / 16); - tx[2] = 0x00 + (crc % 16) * 16; - } else if (tag.pstate == HT_SELECTED - && tag.tstate == HT_READING_PAGE - && rxlen > 0) { - //save received data - 40 bits - z = 0; - for (i = 0; i < 5; i++) { - for (j = 0; j < 8; j++) { - response_bit[z] = 0; - if ((rx[i] & ((mask << 7) >> j)) != 0) - response_bit[z] = 1; - z++; - } - } - k = 0; - for (i = 4; i < 36; i++) { // ignore first 4 bits: SOF (actually 1 or 6 depending on response protocol) - pageData[k] = response_bit[i]; - k++; - } - for (i = 0; i < 4; i++) // set page bytes to 0 - tag.pages[pageNum][i] = 0x0; - for (i = 0; i < 4; i++) { // set page bytes from received bits - tag.pages[pageNum][i] += ((pageData[i * 8] << 7) - | (pageData[1 + (i * 8)] << 6) - | (pageData[2 + (i * 8)] << 5) - | (pageData[3 + (i * 8)] << 4) - | (pageData[4 + (i * 8)] << 3) - | (pageData[5 + (i * 8)] << 2) - | (pageData[6 + (i * 8)] << 1) - | pageData[7 + (i * 8)]); - } - if (tag.auth && tag.LKP && pageNum == 1) { - Dbprintf("Page[%2d]: %02X %02X %02X %02X", pageNum, pwdh0, - (tag.pages[pageNum][2]) & 0xff, - (tag.pages[pageNum][1]) & 0xff, - tag.pages[pageNum][0] & 0xff); + //save received data - 40 bits + for (int i = 0; i < 4 && i < rxlen; i++) { // set page bytes from received bits + tag.pages[pageNum][i] = rx[i]; + } + + if (tag.auth && tag.LKP && pageNum == 1) { + Dbprintf("Page[%2d]: %02X %02X %02X %02X", pageNum, pwdh0, + (tag.pages[pageNum][2]) & 0xff, + (tag.pages[pageNum][1]) & 0xff, + tag.pages[pageNum][0] & 0xff); + } else { + Dbprintf("Page[%2d]: %02X %02X %02X %02X", pageNum, + (tag.pages[pageNum][3]) & 0xff, + (tag.pages[pageNum][2]) & 0xff, + (tag.pages[pageNum][1]) & 0xff, + tag.pages[pageNum][0] & 0xff); + } + + pageNum++; + //display key and password if possible + if (pageNum == 2 && tag.auth == 1 && tag.LKP) { + if (htf == RHTSF_KEY) { + Dbprintf("Page[ 2]: %02X %02X %02X %02X", + htd->crypto.key[1], + htd->crypto.key[0], + pwdl1, + pwdl0 + ); + Dbprintf("Page[ 3]: %02X %02X %02X %02X", + htd->crypto.key[5], + htd->crypto.key[4], + htd->crypto.key[3], + htd->crypto.key[2] + ); } else { - Dbprintf("Page[%2d]: %02X %02X %02X %02X", pageNum, - (tag.pages[pageNum][3]) & 0xff, - (tag.pages[pageNum][2]) & 0xff, - (tag.pages[pageNum][1]) & 0xff, - tag.pages[pageNum][0] & 0xff); - } - - pageNum++; - //display key and password if possible - if (pageNum == 2 && tag.auth == 1 && tag.LKP) { - if (htf == RHTSF_KEY) { - Dbprintf("Page[ 2]: %02X %02X %02X %02X", - (uint8_t)(key >> 8) & 0xff, - (uint8_t) key & 0xff, - pwdl1, - pwdl0 - ); - Dbprintf("Page[ 3]: %02X %02X %02X %02X", - (uint8_t)(key >> 40) & 0xff, - (uint8_t)(key >> 32) & 0xff, - (uint8_t)(key >> 24) & 0xff, - (uint8_t)(key >> 16) & 0xff - ); - } else { - //if the authentication is done with a challenge the key and password are unknown - Dbprintf("Page[ 2]: __ __ __ __"); - Dbprintf("Page[ 3]: __ __ __ __"); - } - // since page 2+3 are not accessible when LKP == 1 and AUT == 1 fastforward to next readable page - pageNum = 4; - } - - txlen = 20; - crc = CRC_PRESET; - tx[0] = 0xc0 + (pageNum / 16); - calc_crc(&crc, tx[0], 8); - calc_crc(&crc, 0x00 + ((pageNum % 16) * 16), 4); - tx[1] = 0x00 + ((pageNum % 16) * 16) + (crc / 16); - tx[2] = 0x00 + (crc % 16) * 16; - if (pageNum >= tag.max_page) { - bStop = !false; + //if the authentication is done with a challenge the key and password are unknown + Dbprintf("Page[ 2]: __ __ __ __"); + Dbprintf("Page[ 3]: __ __ __ __"); } + // since page 2+3 are not accessible when LKP == 1 and AUT == 1 fastforward to next readable page + pageNum = 4; } - - // Send and store the reader command - // Disable timer 1 with external trigger to avoid triggers during our own modulation - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, - // Since the clock counts since the last falling edge, a 'one' means that the - // falling edge occurred halfway the period. with respect to this falling edge, - // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. - // All timer values are in terms of T0 units - - while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; - - // Transmit the reader frame - hitag_reader_send_frame(tx, txlen, ledcontrol); - - // Enable and reset external trigger in timer for capturing future frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - - // Add transmitted frame to total count - if (txlen > 0) { -// frame_count++; - LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true); + if (pageNum >= tag.max_page) { + break; } - - hitagS_receive_frame(rx, &rxlen, &response, ledcontrol); } - end = false; set_tracing(false); lf_finalize(ledcontrol); - reply_mix(CMD_ACK, bSuccessful, 0, 0, 0, 0); + + // TODO reply_mix(CMD_ACK, 1, 0, 0, 0, 0); and send dump as well, to be decoded in the client + reply_mix(CMD_ACK, 0, 0, 0, 0, 0); } /* * Authenticates to the Tag with the given Key or Challenge. * Writes the given 32Bit data into page_ */ -void WritePageHitagS(hitag_function htf, hitag_data *htd, int page, bool ledcontrol) { +void WritePageHitagS(hitag_function htf, hitag_data *htd, int pageNum, bool ledcontrol) { - StopTicks(); + bool bSuccessful = false; + //check for valid input + if (pageNum == 0) { + Dbprintf("Error, invalid page"); + reply_mix(CMD_ACK, bSuccessful, 0, 0, 0, 0); + return; + } -// int frame_count = 0; - int response = 0; uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; - uint8_t txbuf[HITAG_FRAME_LEN]; - uint8_t *tx = txbuf; + uint8_t tx[HITAG_FRAME_LEN]; size_t txlen = 0; - int lastbit; int t_wait = HITAG_T_WAIT_MAX; - bool bStop; - unsigned char crc; + + if (selectHitagS(htf, htd, tx, ARRAYLEN(tx), rx, ARRAYLEN(rx), t_wait, ledcontrol) == -1) { + goto write_end; + } + + //check if the given page exists + if (pageNum > tag.max_page) { + Dbprintf("page number too big for this tag"); + goto write_end; + } + + //send write page request + txlen = 0; + uint8_t cmd = 0x08; + txlen = concatbits(tx, txlen, &cmd, 8 - 4, 4); + uint8_t addr = pageNum; + txlen = concatbits(tx, txlen, &addr, 0, 8); + uint8_t crc = CRC8Hitag1Bits(tx, txlen); + txlen = concatbits(tx, txlen, &crc, 0, 8); + + sendReceiveHitagS(tx, txlen, rx, ARRAYLEN(rx), &rxlen, t_wait, ledcontrol, false); + + if ((rxlen != 2) || (rx[0] >> (8 - 2) != 0x1)) { + Dbprintf("no write access on page %d", pageNum); + goto write_end; + } + + //ACK received to write the page. send data uint8_t data[4] = {0, 0, 0, 0}; - - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - - bSuccessful = false; - - // Clean up trace and prepare it for storing frames - set_tracing(true); - clear_trace(); - - //read given key/challenge, the page and the data - uint8_t NrAr_[8]; - uint64_t key = 0; - uint64_t NrAr = 0; - uint8_t key_[6]; switch (htf) { - case WHTSF_CHALLENGE: { - memcpy(data, htd->auth.data, 4); - DbpString("Authenticating using nr,ar pair:"); - memcpy(NrAr_, htd->auth.NrAr, 8); - Dbhexdump(8, NrAr_, false); - NrAr = NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 | - ((uint64_t)NrAr_[2]) << 40 | ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56; + case WHTSF_CHALLENGE: + data[0] = htd->auth.data[3]; + data[1] = htd->auth.data[2]; + data[2] = htd->auth.data[1]; + data[3] = htd->auth.data[0]; break; - } - - case WHTSF_KEY: { - memcpy(data, htd->crypto.data, 4); - DbpString("Authenticating using key:"); - memcpy(key_, htd->crypto.key, 6); - Dbhexdump(6, key_, false); - key = key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40; + case WHTSF_KEY: + data[0] = htd->crypto.data[3]; + data[1] = htd->crypto.data[2]; + data[2] = htd->crypto.data[1]; + data[3] = htd->crypto.data[0]; break; - } - default: { - Dbprintf("Error , unknown function: %d", htf); + default: return; - } + } + txlen = 0; + txlen = concatbits(tx, txlen, data, 0, 32); + crc = CRC8Hitag1Bits(tx, txlen); + txlen = concatbits(tx, txlen, &crc, 0, 8); + + sendReceiveHitagS(tx, txlen, rx, ARRAYLEN(rx), &rxlen, t_wait, ledcontrol, false); + + if ((rxlen != 2) || (rx[0] >> (8 - 2) != 0x1)) { + Dbprintf("write on page %d failed", pageNum); + } else { + Dbprintf("write on page %d successful", pageNum); + bSuccessful = true; } - Dbprintf("Page: %d", page); - Dbprintf("DATA: %02X %02X %02X %02X", data[0], data[1], data[2], data[3]); - - tag.pstate = HT_READY; - tag.tstate = HT_NO_OP; - - if (ledcontrol) LED_D_ON(); - - // Configure output and enable pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - - // Set fpga in edge detect with reader field, we can modulate as reader now - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); //125kHz - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - - // Disable modulation at default, which means enable the field - LOW(GPIO_SSC_DOUT); - - // Enable Peripheral Clock for - // TIMER_CLOCK0, used to measure exact timing before answering - // TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); - - AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - - // Disable timer during configuration - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; - // external trigger rising edge, load RA on falling edge of TIOA. - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK - | AT91C_TC_ETRGEDG_FALLING - | AT91C_TC_ABETRG - | AT91C_TC_LDRA_FALLING; - - // Enable and reset counters - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - - while (AT91C_BASE_TC0->TC_CV > 0); - - // Reset the received frame, frame count and timing info - lastbit = 1; - bStop = false; - t_wait = 200; - - while (!bStop && !BUTTON_PRESS() && !data_available()) { - - WDT_HIT(); - - // Check if frame was captured and store it - if (rxlen > 0) { -// frame_count++; - LogTrace(rx, nbytes(rxlen), response, response, NULL, false); - } - - //check for valid input - if (page == 0) { - Dbprintf( - "usage: lf hitag writer [--03 | --04] [--nrar CHALLENGE | -k KEY] [-p page] -d [4 hex bytes]"); - bStop = !false; - } - - // By default reset the transmission buffer - tx = txbuf; - txlen = 0; - - if (rxlen == 0 && tag.tstate == HT_WRITING_PAGE_ACK) { - //no write access on this page - Dbprintf("no write access on page %d", page); - bStop = !false; - } else if (rxlen == 0 && tag.tstate != HT_WRITING_PAGE_DATA) { - //start the authentication - txlen = 5; - memcpy(tx, "\xc0", nbytes(txlen)); - tag.pstate = HT_READY; - tag.tstate = HT_NO_OP; - } else if (tag.pstate != HT_SELECTED) { - //try to authenticate with the given key or challenge - if (hitagS_handle_tag_auth(htf, key, NrAr, rx, rxlen, tx, &txlen) == -1) - bStop = !false; - } - if (tag.pstate == HT_SELECTED && tag.tstate == HT_NO_OP && rxlen > 0) { - //check if the given page exists - if (page > tag.max_page) { - Dbprintf("page number too big"); - bStop = !false; - } - //ask Tag for write permission - tag.tstate = HT_WRITING_PAGE_ACK; - txlen = 20; - crc = CRC_PRESET; - tx[0] = 0x90 + (page / 16); - calc_crc(&crc, tx[0], 8); - calc_crc(&crc, 0x00 + ((page % 16) * 16), 4); - tx[1] = 0x00 + ((page % 16) * 16) + (crc / 16); - tx[2] = 0x00 + (crc % 16) * 16; - } else if (tag.pstate == HT_SELECTED && tag.tstate == HT_WRITING_PAGE_ACK - && rxlen == 6 && rx[0] == 0xf4) { - //ACK received to write the page. send data - tag.tstate = HT_WRITING_PAGE_DATA; - txlen = 40; - crc = CRC_PRESET; - calc_crc(&crc, data[3], 8); - calc_crc(&crc, data[2], 8); - calc_crc(&crc, data[1], 8); - calc_crc(&crc, data[0], 8); - tx[0] = data[3]; - tx[1] = data[2]; - tx[2] = data[1]; - tx[3] = data[0]; - tx[4] = crc; - } else if (tag.pstate == HT_SELECTED && tag.tstate == HT_WRITING_PAGE_DATA - && rxlen == 6 && rx[0] == 0xf4) { - //received ACK - Dbprintf("Successful!"); - bStop = !false; - } - - // Send and store the reader command - // Disable timer 1 with external trigger to avoid triggers during our own modulation - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, - // Since the clock counts since the last falling edge, a 'one' means that the - // falling edge occurred halfway the period. with respect to this falling edge, - // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. - // All timer values are in terms of T0 units - - while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; - - // Transmit the reader frame - hitag_reader_send_frame(tx, txlen, ledcontrol); - - // Enable and reset external trigger in timer for capturing future frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - - // Add transmitted frame to total count - if (txlen > 0) { -// frame_count++; - LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true); - } - - hitagS_receive_frame(rx, &rxlen, &response, ledcontrol); - - } - end = false; +write_end: set_tracing(false); - lf_finalize(ledcontrol); - reply_mix(CMD_ACK, bSuccessful, 0, 0, 0, 0); } @@ -1643,231 +1438,48 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page, bool ledcont * is not received correctly due to Antenna problems. This function * detects these challenges. */ -void check_challenges(bool file_given, uint8_t *data, bool ledcontrol) { - int i, j, z, k; -// int frame_count = 0; - int response = 0; - uint8_t uid_byte[4]; - uint8_t rx[HITAG_FRAME_LEN]; - uint8_t unlocker[60][8]; - int u1 = 0; - size_t rxlen = 0; - uint8_t txbuf[HITAG_FRAME_LEN]; - int t_wait = HITAG_T_WAIT_MAX; - int lastbit, STATE = 0; - bool bStop; - int response_bit[200]; - unsigned char mask = 1; - unsigned char uid[32]; - unsigned char crc; - - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - // Reset the return status - bSuccessful = false; - - // Clean up trace and prepare it for storing frames - set_tracing(true); - clear_trace(); - - bQuiet = false; - - if (ledcontrol) LED_D_ON(); - - // Configure output and enable pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - - // Set fpga in edge detect with reader field, we can modulate as reader now - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); //125kHz - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - - // Disable modulation at default, which means enable the field - LOW(GPIO_SSC_DOUT); - - // Enable Peripheral Clock for - // TIMER_CLOCK0, used to measure exact timing before answering - // TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); - - AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - - // Disable timer during configuration - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; - - // TC1: Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, - // external trigger rising edge, load RA on falling edge of TIOA. - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK - | AT91C_TC_ETRGEDG_FALLING - | AT91C_TC_ABETRG - | AT91C_TC_LDRA_FALLING; - - // Enable and reset counters - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - - while (AT91C_BASE_TC0->TC_CV > 0) {}; - - // Reset the received frame, frame count and timing info - lastbit = 1; - bStop = false; - t_wait = 200; - - if (file_given) { - DbpString("Loading challenges..."); - memcpy((uint8_t *)unlocker, data, 60 * 8); +void Hitag_check_challenges(uint8_t *data, uint32_t datalen, bool ledcontrol) { + //check for valid input + if (datalen < 8) { + Dbprintf("Error, need chals"); + reply_mix(CMD_ACK, 0, 0, 0, 0, 0); + return; } + uint32_t dataoffset = 0; - while (file_given && !bStop && !BUTTON_PRESS()) { + uint8_t rx[HITAG_FRAME_LEN]; + uint8_t tx[HITAG_FRAME_LEN]; + int t_wait = HITAG_T_WAIT_MAX; + + while (!BUTTON_PRESS() && !data_available()) { // Watchdog hit WDT_HIT(); - // Check if frame was captured and store it - if (rxlen > 0) { -// frame_count++; - LogTrace(rx, nbytes(rxlen), response, response, NULL, false); + hitag_data htd; + memcpy(htd.auth.NrAr, data + dataoffset, 8); + + int res = selectHitagS(RHTSF_CHALLENGE, &htd, tx, ARRAYLEN(tx), rx, ARRAYLEN(rx), t_wait, ledcontrol); + Dbprintf("Challenge %s: %02X %02X %02X %02X %02X %02X %02X %02X", res == -1 ? "failed " : "success", + htd.auth.NrAr[0], htd.auth.NrAr[1], + htd.auth.NrAr[2], htd.auth.NrAr[3], + htd.auth.NrAr[4], htd.auth.NrAr[5], + htd.auth.NrAr[6], htd.auth.NrAr[7]); + if (res == -1) { + // Need to do a dummy UID select that will fail + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(2); + selectHitagS(RHTSF_CHALLENGE, &htd, tx, ARRAYLEN(tx), rx, ARRAYLEN(rx), t_wait, ledcontrol); } - - uint8_t *tx = txbuf; - size_t txlen = 0; - if (rxlen == 0) { - if (STATE == 2) - // challenge failed - Dbprintf("Challenge failed: %02X %02X %02X %02X %02X %02X %02X %02X", - unlocker[u1 - 1][0], unlocker[u1 - 1][1], - unlocker[u1 - 1][2], unlocker[u1 - 1][3], - unlocker[u1 - 1][4], unlocker[u1 - 1][5], - unlocker[u1 - 1][6], unlocker[u1 - 1][7]); - STATE = 0; - txlen = 5; - //start new authentication - memcpy(tx, "\xC0", nbytes(txlen)); - } else if (rxlen >= 67 && STATE == 0) { - //received uid - z = 0; - for (i = 0; i < 10; i++) { - for (j = 0; j < 8; j++) { - response_bit[z] = 0; - if ((rx[i] & ((mask << 7) >> j)) != 0) - response_bit[z] = 1; - z++; - } - } - k = 0; - for (i = 5; i < z; i += 2) { - uid[k] = response_bit[i]; - k++; - if (k > 31) - break; - } - uid_byte[0] = (uid[0] << 7) | (uid[1] << 6) | (uid[2] << 5) - | (uid[3] << 4) | (uid[4] << 3) | (uid[5] << 2) - | (uid[6] << 1) | uid[7]; - uid_byte[1] = (uid[8] << 7) | (uid[9] << 6) | (uid[10] << 5) - | (uid[11] << 4) | (uid[12] << 3) | (uid[13] << 2) - | (uid[14] << 1) | uid[15]; - uid_byte[2] = (uid[16] << 7) | (uid[17] << 6) | (uid[18] << 5) - | (uid[19] << 4) | (uid[20] << 3) | (uid[21] << 2) - | (uid[22] << 1) | uid[23]; - uid_byte[3] = (uid[24] << 7) | (uid[25] << 6) | (uid[26] << 5) - | (uid[27] << 4) | (uid[28] << 3) | (uid[29] << 2) - | (uid[30] << 1) | uid[31]; - //Dbhexdump(10, rx, rxlen); - STATE = 1; - txlen = 45; - crc = CRC_PRESET; - calc_crc(&crc, 0x00, 5); - calc_crc(&crc, uid_byte[0], 8); - calc_crc(&crc, uid_byte[1], 8); - calc_crc(&crc, uid_byte[2], 8); - calc_crc(&crc, uid_byte[3], 8); - for (i = 0; i < 100; i++) { - response_bit[i] = 0; - } - for (i = 0; i < 5; i++) { - response_bit[i] = 0; - } - for (i = 5; i < 37; i++) { - response_bit[i] = uid[i - 5]; - } - for (j = 0; j < 8; j++) { - response_bit[i] = 0; - if ((crc & ((mask << 7) >> j)) != 0) - response_bit[i] = 1; - i++; - } - k = 0; - for (i = 0; i < 6; i++) { - tx[i] = (response_bit[k] << 7) | (response_bit[k + 1] << 6) - | (response_bit[k + 2] << 5) - | (response_bit[k + 3] << 4) - | (response_bit[k + 4] << 3) - | (response_bit[k + 5] << 2) - | (response_bit[k + 6] << 1) | response_bit[k + 7]; - k += 8; - } - - } else if (STATE == 1 && rxlen == 44) { - //received configuration - STATE = 2; - z = 0; - for (i = 0; i < 6; i++) { - for (j = 0; j < 8; j++) { - response_bit[z] = 0; - if ((rx[i] & ((mask << 7) >> j)) != 0) - response_bit[z] = 1; - z++; - } - } - txlen = 64; - - if (u1 >= ARRAYLEN(unlocker)) - bStop = !false; - for (i = 0; i < 8; i++) - tx[i] = unlocker[u1][i]; - u1++; - - } else if (STATE == 2 && rxlen >= 44) { - Dbprintf("Challenge success: %02X%02X%02X%02X %02X%02X%02X%02X", - unlocker[u1 - 1][0], unlocker[u1 - 1][1], - unlocker[u1 - 1][2], unlocker[u1 - 1][3], - unlocker[u1 - 1][4], unlocker[u1 - 1][5], - unlocker[u1 - 1][6], unlocker[u1 - 1][7]); - STATE = 0; - } - - // Send and store the reader command - // Disable timer 1 with external trigger to avoid triggers during our own modulation - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, - // Since the clock counts since the last falling edge, a 'one' means that the - // falling edge occurred halfway the period. with respect to this falling edge, - // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. - // All timer values are in terms of T0 units - - while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; - - // Transmit the reader frame - hitag_reader_send_frame(tx, txlen, ledcontrol); - - // Enable and reset external trigger in timer for capturing future frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - - // Add transmitted frame to total count - if (txlen > 0) { -// frame_count++; - LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true); - } - - hitagS_receive_frame(rx, &rxlen, &response, ledcontrol); + dataoffset += 8; + if (dataoffset >= datalen - 8) + break; + // reset field + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + // min t_reset = 2ms + SpinDelay(2); } - set_tracing(false); lf_finalize(ledcontrol); - reply_mix(CMD_ACK, bSuccessful, 0, 0, 0, 0); + reply_mix(CMD_ACK, 1, 0, 0, 0, 0); + return; } diff --git a/armsrc/hitagS.h b/armsrc/hitagS.h index 62db442ef..4bda3c75b 100644 --- a/armsrc/hitagS.h +++ b/armsrc/hitagS.h @@ -19,6 +19,5 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data, bool ledcontrol); void ReadHitagS(hitag_function htf, hitag_data *htd, bool ledcontrol); void WritePageHitagS(hitag_function htf, hitag_data *htd, int page, bool ledcontrol); -void check_challenges(bool file_given, uint8_t *data, bool ledcontrol); - +void Hitag_check_challenges(uint8_t *data, uint32_t datalen, bool ledcontrol); #endif diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 9fe238e6a..b7090ad9d 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -34,6 +34,7 @@ #include "protocols.h" #include "ticks.h" #include "iso15693.h" +#include "iclass_cmd.h" /* iclass_card_select_t struct */ static uint8_t get_pagemap(const picopass_hdr_t *hdr) { return (hdr->conf.fuses & (FUSE_CRYPT0 | FUSE_CRYPT1)) >> 3; @@ -1402,13 +1403,8 @@ bool select_iclass_tag(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_t // turn off afterwards void ReaderIClass(uint8_t flags) { - picopass_hdr_t hdr = {0}; -// uint8_t last_csn[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - uint8_t resp[ICLASS_BUFFER_SIZE] = {0}; - memset(resp, 0xFF, sizeof(resp)); - -// bool flag_readonce = flags & FLAG_ICLASS_READER_ONLY_ONCE; // flag to read until one tag is found successfully - bool use_credit_key = flags & FLAG_ICLASS_READER_CREDITKEY; // flag to use credit key + // flag to use credit key + bool use_credit_key = ((flags & FLAG_ICLASS_READER_CREDITKEY) == FLAG_ICLASS_READER_CREDITKEY); if ((flags & FLAG_ICLASS_READER_INIT) == FLAG_ICLASS_READER_INIT) { Iso15693InitReader(); @@ -1418,13 +1414,14 @@ void ReaderIClass(uint8_t flags) { clear_trace(); } - uint8_t result_status = 0; + + uint8_t res = 0; uint32_t eof_time = 0; - bool status = select_iclass_tag_ex(&hdr, use_credit_key, &eof_time, &result_status); - if (status == false) { - reply_mix(CMD_ACK, 0xFF, 0, 0, NULL, 0); - switch_off(); - return; + picopass_hdr_t hdr = {0}; + + if (select_iclass_tag_ex(&hdr, use_credit_key, &eof_time, &res) == false) { + reply_ng(CMD_HF_ICLASS_READER, PM3_ERFTRANS, NULL, 0); + goto out; } // Page mapping for secure mode @@ -1443,30 +1440,14 @@ void ReaderIClass(uint8_t flags) { // Return to client, e 6 * 8 bytes of data. // with 0xFF:s in block 3 and 4. - LED_B_ON(); - reply_mix(CMD_ACK, result_status, 0, 0, (uint8_t *)&hdr, sizeof(hdr)); + iclass_card_select_resp_t payload = { + .status = res + }; + memcpy(&payload.header.hdr, &hdr, sizeof(picopass_hdr_t)); - //Send back to client, but don't bother if we already sent this - - // only useful if looping in arm (not try_once && not abort_after_read) - /* - if (memcmp(last_csn, card_data, 8) != 0) { - - reply_mix(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data)); - if (flag_readonce) { - LED_B_OFF(); - return; - } - LED_B_OFF(); - } - */ - -// if (userCancelled) { -// reply_mix(CMD_ACK, 0xFF, 0, 0, card_data, 0); -// switch_off(); -// } else { -// reply_mix(CMD_ACK, result_status, 0, 0, card_data, 0); -// } + reply_ng(CMD_HF_ICLASS_READER, PM3_SUCCESS, (uint8_t*)&payload, sizeof(iclass_card_select_resp_t)); +out: switch_off(); } diff --git a/armsrc/iclass.h b/armsrc/iclass.h index 958382256..c0cbe9b3b 100644 --- a/armsrc/iclass.h +++ b/armsrc/iclass.h @@ -13,7 +13,7 @@ #define __ICLASS_H #include "common.h" -#include "pm3_cmd.h" +#include "iclass_cmd.h" void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string); void ReaderIClass(uint8_t flags); diff --git a/armsrc/lfzx.c b/armsrc/lfzx.c index 364af4abc..b392eba0e 100644 --- a/armsrc/lfzx.c +++ b/armsrc/lfzx.c @@ -87,7 +87,6 @@ static void zx8211_setup_read(void) { sample_config *sc = getSamplingConfig(); LFSetupFPGAForADC(sc->divisor, true); - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD); // 50ms for the resonant antenna to settle. @@ -132,6 +131,26 @@ static void zx_send(uint8_t *cmd, uint8_t clen) { turn_read_lf_on(ZX_TEOF * 8); } +static void zx_get(bool ledcontrol) { + + while (BUTTON_PRESS() == false) { + + WDT_HIT(); + + if (ledcontrol && (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY)) { + LED_D_ON(); + } + + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + (void)sample; + + // Test point 8 (TP8) can be used to trigger oscilloscope + if (ledcontrol) LED_D_OFF(); + + } + } +} int zx8211_read(zx8211_data_t *zxd, bool ledcontrol) { zx8211_setup_read(); @@ -144,13 +163,18 @@ int zx8211_read(zx8211_data_t *zxd, bool ledcontrol) { // send GET_UID zx_send(NULL, 0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD); + + zx_get(ledcontrol); + //uint32_t cs = CRC8Hitag1(uint8_t *buff, size_t size); if (ledcontrol) LEDsoff(); StopTicks(); lf_finalize(ledcontrol); - //reply_ng(CMD_LF_ZX_READ, status, tag.data, sizeof(tag.data)); + + reply_ng(CMD_LF_ZX_READ, PM3_SUCCESS, NULL, 0); return PM3_SUCCESS; } diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 42eef11a0..38ba66548 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -2594,7 +2594,7 @@ OUT: BigBuf_free(); } -void MifareG3ReadBlk(uint8_t blockno) { +void MifareG4ReadBlk(uint8_t blockno, uint8_t *pwd) { iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); set_tracing(true); @@ -2613,6 +2613,9 @@ void MifareG3ReadBlk(uint8_t blockno) { iso14a_set_timeout(13560000 / 1000 / (8 * 16) * 1000); // 2 seconds timeout uint8_t cmd[] = { 0xCF, 0x00, 0x00, 0x00, 0x00, 0xCE, blockno, 0x00, 0x00}; + + memcpy(cmd + 1, pwd, 4); + AddCrc14A(cmd, sizeof(cmd) - 2); ReaderTransmit(cmd, sizeof(cmd), NULL); @@ -2624,7 +2627,7 @@ void MifareG3ReadBlk(uint8_t blockno) { LED_B_OFF(); OUT: - reply_ng(CMD_HF_MIFARE_G3_RDBL, retval, buf, 18); + reply_ng(CMD_HF_MIFARE_G4_RDBL, retval, buf, 18); // turns off OnSuccessMagic(); BigBuf_free(); diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index bacb8405e..49f1832e7 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -49,8 +49,8 @@ void MifareGen3UID(uint8_t uidlen, uint8_t *uid); // Gen 3 magic card set UID wi void MifareGen3Blk(uint8_t block_len, uint8_t *block); // Gen 3 magic card overwrite manufacturer block void MifareGen3Freez(void); // Gen 3 magic card lock further UID changes -// MFC GEN3 GTU -void MifareG3ReadBlk(uint8_t blockno); +// MFC GEN4 GTU +void MifareG4ReadBlk(uint8_t blockno, uint8_t *pwd); void MifareSetMod(uint8_t *datain); void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key); diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index 61c94694c..be3a5a000 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -1464,4 +1464,14 @@ B5ADEFCA46C4 BF3FE47637EC B290401B0CAD AD11006B0601 - +# +# Data from Mifare Classic Tool repo +# Armenian Metro +E4410EF8ED2D +6A68A7D83E11 +0D6057E8133B +D3F3B958B8A3 +3E120568A35C +2196FAD8115B +7C469FE86855 +CE99FBC8BD26 diff --git a/client/src/cmdanalyse.c b/client/src/cmdanalyse.c index c567b18c3..4d3352da8 100644 --- a/client/src/cmdanalyse.c +++ b/client/src/cmdanalyse.c @@ -1052,7 +1052,7 @@ static int CmdAnalyseFoo(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx0("r", "raw", "", "raw bytes (strx)"), + arg_str1("r", "raw", "", "raw bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 1188b5308..70bc65b44 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -2407,7 +2407,7 @@ static int Cmdbin2hex(const char *Cmd) { ); void *argtable[] = { arg_param_begin, - arg_strx0("d", "data", "", "binary string to convert"), + arg_str1("d", "data", "", "binary string to convert"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); diff --git a/client/src/cmdflashmem.c b/client/src/cmdflashmem.c index c7af3141f..c2e5591a6 100644 --- a/client/src/cmdflashmem.c +++ b/client/src/cmdflashmem.c @@ -167,7 +167,7 @@ static int CmdFlashMemLoad(const char *Cmd) { arg_lit0("m", "mifare,mfc", "upload 6 bytes keys (mifare key dictionary)"), arg_lit0("i", "iclass", "upload 8 bytes keys (iClass key dictionary)"), arg_lit0("t", "t55xx", "upload 4 bytes keys (password dictionary)"), - arg_strx0("f", "file", "", "file name"), + arg_str1("f", "file", "", "file name"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -327,7 +327,7 @@ static int CmdFlashMemDump(const char *Cmd) { arg_int0("o", "offset", "", "offset in memory"), arg_int0("l", "len", "", "length"), arg_lit0("v", "view", "view dump"), - arg_strx0("f", "file", "", "file name"), + arg_str0("f", "file", "", "save filename"), arg_int0("c", "cols", "", "column breaks (def 32)"), arg_param_end }; diff --git a/client/src/cmdflashmemspiffs.c b/client/src/cmdflashmemspiffs.c index 684165236..407f1e54c 100644 --- a/client/src/cmdflashmemspiffs.c +++ b/client/src/cmdflashmemspiffs.c @@ -196,7 +196,7 @@ static int CmdFlashMemSpiFFSRemove(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str1("f", "filename", "", "file to remove"), + arg_str1("f", "file", "", "file to remove"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index b55043ff9..d127010d5 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -743,13 +743,16 @@ int CmdHF14ASim(const char *Cmd) { keypress = kbd_enter_pressed(); } - if (keypress && (flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) { - // inform device to break the sim loop since client has exited - SendCommandNG(CMD_BREAK_LOOP, NULL, 0); - } + if (keypress) { + if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) { + // inform device to break the sim loop since client has exited + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + } - if (resp.status == PM3_EOPABORTED && ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK)) - showSectorTable(k_sector, k_sectorsCount); + if (resp.status == PM3_EOPABORTED && ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK)) { + showSectorTable(k_sector, k_sectorsCount); + } + } PrintAndLogEx(INFO, "Done"); return PM3_SUCCESS; @@ -2274,7 +2277,7 @@ static int CmdHf14AFindapdu(const char *Cmd) { arg_str0(NULL, "p2", "", "Start value of P2 (1 hex byte)"), arg_u64_0("r", "reset", "", "Minimum secondes before resetting the tag (to prevent timeout issues). Default is 5 minutes"), arg_u64_0("e", "error-limit", "", "Maximum times an status word other than 0x9000 or 0x6D00 is shown. Default is 512."), - arg_strx0("s", "skip-ins", "", "Do not test an instructions (can be specified multiple times)"), + arg_strx0("s", "skip-ins", "", "Do not test an instruction (can be specified multiple times)"), arg_lit0("l", "with-le", "Search for APDUs with Le=0 (case 2S) as well"), arg_lit0("v", "verbose", "Verbose output"), arg_param_end diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index bd085210d..04e0a1a52 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -221,7 +221,7 @@ static int CmdHF14BSim(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx0("u", "uid", "hex", "4byte UID/PUPI"), + arg_str1("u", "uid", "hex", "4byte UID/PUPI"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -288,7 +288,7 @@ static int CmdHF14BCmdRaw(const char *Cmd) { arg_lit0("r", NULL, "do not read response from card"), arg_int0("t", "timeout", "", "timeout in ms"), arg_lit0("v", "verbose", "verbose"), - arg_strx0("d", "data", "", "data, bytes to send"), + arg_str0("d", "data", "", "data, bytes to send"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -1276,7 +1276,7 @@ static int CmdHF14BDump(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx0("f", "file", "", "(optional) filename, if no UID will be used as filename"), + arg_str0("f", "file", "", "(optional) filename, if no UID will be used as filename"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -1822,7 +1822,7 @@ static int CmdHF14BAPDU(const char *Cmd) { " must be 4 bytes: "), arg_lit0("e", "extended", "make extended length apdu if `m` parameter included"), arg_int0("l", "le", "", "Le apdu parameter if `m` parameter included"), - arg_strx1("d", "data", "", " if `m` parameter included"), + arg_str1("d", "data", "", " if `m` parameter included"), arg_int0(NULL, "timeout", "", "timeout in ms"), arg_param_end }; diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 73652837b..16071df8b 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1450,7 +1450,7 @@ static int CmdHF15Raw(const char *Cmd) { arg_lit0("c", "crc", "calculate and append CRC"), arg_lit0("k", NULL, "keep signal field ON after receive"), arg_lit0("r", NULL, "do not read response"), - arg_strx1("d", "data", "", "raw bytes to send"), + arg_str1("d", "data", "", "raw bytes to send"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); diff --git a/client/src/cmdhfcryptorf.c b/client/src/cmdhfcryptorf.c index 5edaa4cdd..1f68b9bd4 100644 --- a/client/src/cmdhfcryptorf.c +++ b/client/src/cmdhfcryptorf.c @@ -423,7 +423,7 @@ static int CmdHFCryptoRFELoad(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str1("f", "file", "", "filename of dump"), + arg_str1("f", "file", "", "filename of dump"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 613c0a055..2afefff1d 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -201,7 +201,7 @@ static int emrtd_exchange_commands_noout(sAPDU_t apdu, bool activate_field, bool } static char emrtd_calculate_check_digit(char *data) { - int mrz_weight[] = {7, 3, 1}; + const int mrz_weight[] = {7, 3, 1}; int value, cd = 0; for (int i = 0; i < strlen(data); i++) { @@ -295,7 +295,7 @@ static void des3_decrypt_cbc(uint8_t *iv, uint8_t *key, uint8_t *input, int inpu } static int pad_block(uint8_t *input, int inputlen, uint8_t *output) { - uint8_t padding[8] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + const uint8_t padding[8] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; memcpy(output, input, inputlen); diff --git a/client/src/cmdhfepa.c b/client/src/cmdhfepa.c index acc89d4c4..9864cc55e 100644 --- a/client/src/cmdhfepa.c +++ b/client/src/cmdhfepa.c @@ -132,7 +132,7 @@ static int CmdHFEPAPACEReplay(const char *Cmd) { uint8_t apdu_lengths[5] = {msesa_len, gn_len, map_len, pka_len, ma_len}; // pointers to the arrays to be able to iterate - uint8_t *apdus[] = {msesa_apdu, gn_apdu, map_apdu, pka_apdu, ma_apdu}; + const uint8_t *apdus[] = {msesa_apdu, gn_apdu, map_apdu, pka_apdu, ma_apdu}; // Proxmark response PacketResponseNG resp; diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 02f14c893..d6a03f0ef 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -2122,7 +2122,7 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { arg_u64_0("n", NULL, "", "number of bits"), arg_lit0("r", NULL, "do not read response"), arg_lit0("s", NULL, "active signal field ON with select"), - arg_strx1(NULL, NULL, "", "raw bytes to send"), + arg_str1(NULL, NULL, "", "raw bytes to send"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 8c68833ab..b9945bf2e 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -32,10 +32,11 @@ #include "wiegand_formatutils.h" #include "cmdsmartcard.h" // smart select fct #include "proxendian.h" +#include "iclass_cmd.h" -#define NUM_CSNS 9 -#define ICLASS_KEYS_MAX 8 -#define ICLASS_AUTH_RETRY 10 +#define NUM_CSNS 9 +#define ICLASS_KEYS_MAX 8 +#define ICLASS_AUTH_RETRY 10 #define ICLASS_DECRYPTION_BIN "iclass_decryptionkey.bin" static void print_picopass_info(const picopass_hdr_t *hdr); @@ -165,7 +166,7 @@ static const char *card_types[] = { }; static uint8_t card_app2_limit[] = { - 0xff, + 0x1f, 0xff, 0xff, 0xff, @@ -278,7 +279,8 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke // calc diversified key for selected card HFiClassCalcDivKey(cc->csn, iClass_Key_Table[0], cc->key_d, false); } else { - PrintAndLogEx(INFO, "failed to read a card, will use default config card data"); + PrintAndLogEx(FAILED, "failed to read a card"); + PrintAndLogEx(INFO,"falling back to default config card"); } // generate dump file @@ -323,35 +325,47 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke return PM3_EMALLOC; } data = p; - memset(data, 0xFF, tot_bytes); } + memset(data + sizeof(picopass_hdr_t), 0xFF, tot_bytes - sizeof(picopass_hdr_t)); + + bool old = GetFlushAfterWrite(); + SetFlushAfterWrite(true); + // KEYROLL need to encrypt + PrintAndLogEx(INFO, "Setting up encryption... " NOLF); uint8_t ffs[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; if (Encrypt(ffs, ffs) == false) { PrintAndLogEx(WARNING, "failed to encrypt FF"); + } else { + PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )"); } // local key copy + PrintAndLogEx(INFO, "Encrypting local key... " NOLF); uint8_t lkey[8]; memcpy(lkey, key, sizeof(lkey)); - uint8_t enckey1[8]; if (Encrypt(lkey, enckey1) == false) { PrintAndLogEx(WARNING, "failed to encrypt key1"); + } else { + PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )"); } + PrintAndLogEx(INFO, "Copy data... " NOLF); memcpy(data, cc, sizeof(picopass_hdr_t)); memcpy(data + (6 * 8), o->data, sizeof(o->data)); // encrypted keyroll key 0D memcpy(data + (0xD * 8), enckey1, sizeof(enckey1)); // encrypted 0xFF - for (uint8_t i = 0xe; i < 0x14; i++) { + for (uint8_t i = 0xD; i < 0x14; i++) { memcpy(data + (i * 8), ffs, sizeof(ffs)); } + PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )"); // encrypted partial keyroll key 14 + PrintAndLogEx(INFO, "Setting encrypted partial key14... " NOLF); uint8_t foo[8] = {0x15}; memcpy(foo + 1, lkey, 7); uint8_t enckey2[8]; @@ -359,34 +373,43 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke PrintAndLogEx(WARNING, "failed to encrypt partial 1"); } memcpy(data + (0x14 * 8), enckey2, sizeof(enckey2)); + PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )"); + // encrypted partial keyroll key 15 + PrintAndLogEx(INFO, "Setting encrypted partial key15... " NOLF); memset(foo, 0xFF, sizeof(foo)); foo[0] = lkey[7]; if (Encrypt(foo, enckey2) == false) { PrintAndLogEx(WARNING, "failed to encrypt partial 2"); } memcpy(data + (0x15 * 8), enckey2, sizeof(enckey2)); + PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )"); // encrypted 0xFF + PrintAndLogEx(INFO, "Setting 0xFF's... " NOLF); for (uint8_t i = 0x16; i <= app1_limit; i++) { memcpy(data + (i * 8), ffs, sizeof(ffs)); - } + } + PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )"); // revert potential modified app1_limit cc->conf.app_limit = old_limit; + SetFlushAfterWrite(old); } else { memcpy(data, cc, sizeof(picopass_hdr_t)); memcpy(data + (6 * 8), o->data, sizeof(o->data)); } //Send to device + PrintAndLogEx(INFO, "Uploading to device... "); uint16_t bytes_sent = 0; iclass_upload_emul(data, tot_bytes, &bytes_sent); free(data); - PrintAndLogEx(SUCCESS, "sent %u bytes of data to device emulator memory", bytes_sent); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "sent " _YELLOW_("%u") " bytes of data to device emulator memory", bytes_sent); PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass eview") "` to view dump file"); PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass sim -t 3") "` to start simulating config card"); return PM3_SUCCESS; @@ -454,15 +477,21 @@ static void fuse_config(const picopass_hdr_t *hdr) { PrintAndLogEx(SUCCESS, " RA........... Read access enabled (non-secure mode)"); else PrintAndLogEx(INFO, " RA........... Read access not enabled"); + + if (notset(fuses, FUSE_FPROD0) && isset(fuses, FUSE_FPROD1)) { + PrintAndLogEx(INFO, " PROD0/1...... Default production fuses"); + } } -static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *app_areas, uint8_t *kb) { +static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *app_areas, uint8_t *kb, uint8_t *books, uint8_t *pages) { // How to determine chip type // mem-bit 7 = 16K // mem-bit 5 = Book // mem-bit 4 = 2K // chip-bit 4 = Multi App + *books = 1; + *pages = 1; uint8_t k16 = isset(mem_cfg, 0x80); //uint8_t k2 = isset(mem_cfg, 0x10); @@ -477,12 +506,16 @@ static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *app_areas, } else if (notset(chip_cfg, 0x10) && !k16 && !book) { *kb = 16; *app_areas = 16; + *pages = 8; } else if (isset(chip_cfg, 0x10) && k16 && book) { *kb = 32; *app_areas = 3; + *books = 2; } else if (notset(chip_cfg, 0x10) && !k16 && book) { *kb = 32; *app_areas = 17; + *pages = 8; + *books = 2; } else { *kb = 32; *app_areas = 2; @@ -506,8 +539,10 @@ static void mem_app_config(const picopass_hdr_t *hdr) { uint8_t chip = hdr->conf.chip_config; uint8_t kb = 2; uint8_t app_areas = 2; - - getMemConfig(mem, chip, &app_areas, &kb); + uint8_t books = 1; + uint8_t pages = 1; + + getMemConfig(mem, chip, &app_areas, &kb, &books, &pages); uint8_t type = get_mem_config(hdr); uint8_t app1_limit = hdr->conf.app_limit - 5; // minus header blocks @@ -522,9 +557,26 @@ static void mem_app_config(const picopass_hdr_t *hdr) { return; } - PrintAndLogEx(INFO, " %u KBits/%u App Areas ( " _YELLOW_("%u") " bytes )", kb, app_areas, (app2_limit + 1) * 8); - PrintAndLogEx(INFO, " AA1 blocks %u { 0x06 - 0x%02X (06 - %02d) }", app1_limit, app1_limit + 5, app1_limit + 5); - PrintAndLogEx(INFO, " AA2 blocks %u { 0x%02X - 0x%02X (%02d - %02d) }", app2_limit - app1_limit, app1_limit + 5 + 1, app2_limit, app1_limit + 5 + 1, app2_limit); + PrintAndLogEx(INFO, " %u KBits/%u App Areas ( " _YELLOW_("%u") " bytes )" + , kb + , app_areas + , ((app2_limit + 1) * 8) * books * pages); + + PrintAndLogEx(INFO, " %u books / %u pages" + , books + , pages + ); + PrintAndLogEx(INFO, " First book / first page configuration"); + PrintAndLogEx(INFO, " Config | 0 - 5 ( 0x00 - 0x05 ) - 6 blocks "); + PrintAndLogEx(INFO, " AA1 | 6 - %2d ( 0x06 - 0x%02X ) - %u blocks", app1_limit + 5, app1_limit + 5, app1_limit); + if (app1_limit + 5 < app2_limit ) { + PrintAndLogEx(INFO, " AA2 | %2d - %2d ( 0x%02X - 0x%02X ) - %u blocks", app1_limit + 5 + 1, app2_limit, app1_limit + 5 + 1, app2_limit, app2_limit - app1_limit); + } +/* +[=] 32 KBits/3 App Areas ( 2048 bytes ) +[=] AA1 blocks 250 { 0x06 - 0xFF (06 - 255) } +[=] AA2 blocks 5 { 0x100 - 0xFF (256 - 255) } +*/ PrintAndLogEx(INFO, "------------------------- " _CYAN_("KeyAccess") " ------------------------"); PrintAndLogEx(INFO, " * Kd, Debit key, AA1 Kc, Credit key, AA2 *"); @@ -557,8 +609,19 @@ void print_picopass_header(const picopass_hdr_t *hdr) { PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " uid", sprint_hex(hdr->csn, sizeof(hdr->csn))); PrintAndLogEx(SUCCESS, " Config: %s Card configuration", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf))); PrintAndLogEx(SUCCESS, "E-purse: %s Card challenge, CC", sprint_hex(hdr->epurse, sizeof(hdr->epurse))); - PrintAndLogEx(SUCCESS, " Kd: %s Debit key, hidden", sprint_hex(hdr->key_d, sizeof(hdr->key_d))); - PrintAndLogEx(SUCCESS, " Kc: %s Credit key, hidden", sprint_hex(hdr->key_c, sizeof(hdr->key_c))); + + if (memcmp(hdr->key_d, zeros, sizeof(zeros)) && memcmp(hdr->key_d, empty, sizeof(empty))) { + PrintAndLogEx(SUCCESS, " Kd: " _YELLOW_("%s") " debit key", sprint_hex(hdr->key_d, sizeof(hdr->key_d))); + } else { + PrintAndLogEx(SUCCESS, " Kd: %s debit key ( hidden )", sprint_hex(hdr->key_d, sizeof(hdr->key_d))); + } + + if (memcmp(hdr->key_c, zeros, sizeof(zeros)) && memcmp(hdr->key_c, empty, sizeof(empty))) { + PrintAndLogEx(SUCCESS, " Kc: " _YELLOW_("%s") " credit key", sprint_hex(hdr->key_c, sizeof(hdr->key_c))); + } else { + PrintAndLogEx(SUCCESS, " Kc: %s credit key ( hidden )", sprint_hex(hdr->key_c, sizeof(hdr->key_c))); + } + PrintAndLogEx(SUCCESS, " AIA: %s Application Issuer area", sprint_hex(hdr->app_issuer_area, sizeof(hdr->app_issuer_area))); } @@ -834,25 +897,28 @@ static int CmdHFiClassInfo(const char *Cmd) { int read_iclass_csn(bool loop, bool verbose) { - uint32_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE); + iclass_card_select_t payload = { + .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE) + }; + int res = PM3_SUCCESS; do { clearCommandBuffer(); - SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0); PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + SendCommandNG(CMD_HF_ICLASS_READER, (uint8_t*)&payload, sizeof(iclass_card_select_t)); - uint8_t status = resp.oldarg[0] & 0xff; + if (WaitForResponseTimeout(CMD_HF_ICLASS_READER, &resp, 2000)) { + iclass_card_select_resp_t *r = (iclass_card_select_resp_t*)resp.data.asBytes; if (loop) { - if (status == 0xFF) { + if (resp.status == PM3_ERFTRANS) { continue; } } else { - if (status == 0 || status == 0xFF) { - if (verbose) PrintAndLogEx(WARNING, "iCLASS / ISO15693 card select failed"); + if (r->status == FLAG_ICLASS_NULL || resp.status == PM3_ERFTRANS) { + if (verbose) PrintAndLogEx(WARNING, "iCLASS / Picopass card select failed ( %d )", r->status); res = PM3_EOPABORTED; break; } @@ -860,13 +926,17 @@ int read_iclass_csn(bool loop, bool verbose) { picopass_hdr_t *card = calloc(1, sizeof(picopass_hdr_t)); if (card) { - memcpy(card, (picopass_hdr_t *)resp.data.asBytes, sizeof(picopass_hdr_t)); - PrintAndLogEx(NORMAL, ""); + memcpy(card, &r->header.hdr, sizeof(picopass_hdr_t)); + if (loop == false) { + PrintAndLogEx(NORMAL, ""); + } PrintAndLogEx(SUCCESS, "iCLASS / Picopass CSN: " _GREEN_("%s"), sprint_hex(card->csn, sizeof(card->csn))); iclass_set_last_known_card(card); free(card); + res = PM3_SUCCESS; } else { PrintAndLogEx(FAILED, "failed to allocate memory"); + res = PM3_EMALLOC; } } } while (loop && kbd_enter_pressed() == false); @@ -1240,7 +1310,9 @@ static int CmdHFiClassDecrypt(const char *Cmd) { } else { mbedtls_des3_crypt_ecb(&ctx, enc_data, dec_data); } - PrintAndLogEx(SUCCESS, "Data: %s", sprint_hex(dec_data, sizeof(dec_data))); + + PrintAndLogEx(SUCCESS, "encrypted... %s", sprint_hex_inrow(enc_data, sizeof(enc_data))); + PrintAndLogEx(SUCCESS, "plain....... " _YELLOW_("%s"), sprint_hex_inrow(dec_data, sizeof(dec_data))); if (use_sc && use_decode6) DecodeBlock6(dec_data); @@ -1256,7 +1328,9 @@ static int CmdHFiClassDecrypt(const char *Cmd) { uint8_t applimit = hdr->conf.app_limit; uint8_t kb = 2; uint8_t app_areas = 2; - getMemConfig(mem, chip, &app_areas, &kb); + uint8_t books = 1; + uint8_t pages = 1; + getMemConfig(mem, chip, &app_areas, &kb, &books, &pages); BLOCK79ENCRYPTION aa1_encryption = (decrypted[(6 * 8) + 7] & 0x03); @@ -1455,39 +1529,45 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) { } } + + PrintAndLogEx(SUCCESS, "plain....... %s", sprint_hex_inrow(blk_data, sizeof(blk_data))); + if (use_sc) { Encrypt(blk_data, blk_data); } else { iclass_encrypt_block_data(blk_data, key); } - PrintAndLogEx(SUCCESS, "encrypted block %s", sprint_hex(blk_data, 8)); + + PrintAndLogEx(SUCCESS, "encrypted... " _YELLOW_("%s"), sprint_hex_inrow(blk_data, sizeof(blk_data))); return PM3_SUCCESS; } static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool verbose) { - uint8_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE); + iclass_card_select_t payload = { + .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE) + }; clearCommandBuffer(); PacketResponseNG resp; - SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0); - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { + SendCommandNG(CMD_HF_ICLASS_READER, (uint8_t*)&payload, sizeof(iclass_card_select_t)); + + if (WaitForResponseTimeout(CMD_HF_ICLASS_READER, &resp, 2000) == false) { PrintAndLogEx(WARNING, "command execute timeout"); return false; } - uint8_t isok = resp.oldarg[0] & 0xff; + iclass_card_select_resp_t *r = (iclass_card_select_resp_t*)resp.data.asBytes; + picopass_hdr_t *hdr = &r->header.hdr; // no tag found or button pressed - if ((isok == 0) || isok == 0xFF) { + if (r->status == FLAG_ICLASS_NULL || resp.status == PM3_ERFTRANS) { if (verbose) { - PrintAndLogEx(FAILED, "failed tag-select, aborting... (%d)", isok); + PrintAndLogEx(FAILED, "failed tag-select, aborting... (%d)", r->status); } return false; } - picopass_hdr_t *hdr = (picopass_hdr_t *)resp.data.asBytes; - if (CSN != NULL) memcpy(CSN, hdr->csn, 8); @@ -1614,34 +1694,41 @@ static int CmdHFiClassDump(const char *Cmd) { uint8_t app_limit1 = 0, app_limit2 = 0; - uint32_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE); - //get CSN and config - PacketResponseNG resp; uint8_t tag_data[0x100 * 8]; memset(tag_data, 0xFF, sizeof(tag_data)); + + iclass_card_select_t payload_rdr = { + .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE) + }; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + PacketResponseNG resp; + SendCommandNG(CMD_HF_ICLASS_READER, (uint8_t*)&payload_rdr, sizeof(iclass_card_select_t)); + + if (WaitForResponseTimeout(CMD_HF_ICLASS_READER, &resp, 2000) == false) { PrintAndLogEx(WARNING, "command execute timeout"); DropField(); return PM3_ESOFT; } DropField(); - uint8_t readStatus = resp.oldarg[0] & 0xff; - picopass_hdr_t *hdr = (picopass_hdr_t *)resp.data.asBytes; - - if (readStatus == 0) { + if (resp.status == PM3_ERFTRANS) { PrintAndLogEx(FAILED, "no tag found"); DropField(); return PM3_ESOFT; } + iclass_card_select_resp_t *r = (iclass_card_select_resp_t*)resp.data.asBytes; + if (r->status == FLAG_ICLASS_NULL) { + PrintAndLogEx(FAILED, "failed to read block 0,1,2"); + return PM3_ESOFT; + } + + picopass_hdr_t *hdr = &r->header.hdr; uint8_t pagemap = get_pagemap(hdr); - if (readStatus & (FLAG_ICLASS_CSN | FLAG_ICLASS_CONF | FLAG_ICLASS_CC)) { + if (r->status & (FLAG_ICLASS_CSN | FLAG_ICLASS_CONF | FLAG_ICLASS_CC)) { memcpy(tag_data, hdr, 24); @@ -1661,11 +1748,6 @@ static int CmdHFiClassDump(const char *Cmd) { app_limit1 = hdr->conf.app_limit; app_limit2 = card_app2_limit[type]; } - - } else { - PrintAndLogEx(FAILED, "failed to read block 0,1,2"); - DropField(); - return PM3_ESOFT; } if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { @@ -2470,11 +2552,10 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e ); */ uint8_t pagemap = get_pagemap(hdr); - - - int i = startblock; + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "-------------------------- " _CYAN_("Tag memory") " ---------------------------"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, " block# | data | ascii |lck| info"); PrintAndLogEx(INFO, "---------+-------------------------+----------+---+--------------"); @@ -2484,7 +2565,7 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e ); if (i != 1) - PrintAndLogEx(INFO, "...."); + PrintAndLogEx(INFO, " ......"); while (i <= endblock) { uint8_t *blk = iclass_dump + (i * 8); @@ -3956,88 +4037,101 @@ int CmdHFiClass(const char *Cmd) { int info_iclass(void) { - uint32_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE); - + iclass_card_select_t payload = { + .flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE) + }; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0); PacketResponseNG resp; + SendCommandNG(CMD_HF_ICLASS_READER, (uint8_t*)&payload, sizeof(iclass_card_select_t)); - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - - uint8_t readStatus = resp.oldarg[0] & 0xff; - - // no tag found or button pressed - if (readStatus == 0 || readStatus == 0xFF) { - DropField(); - return PM3_EOPABORTED; - } - - picopass_hdr_t *hdr = (picopass_hdr_t *)resp.data.asBytes; - picopass_ns_hdr_t *ns_hdr = (picopass_ns_hdr_t *)resp.data.asBytes; - - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--------------------- " _CYAN_("Tag Information") " ----------------------"); - - if (readStatus & FLAG_ICLASS_CSN) { - PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " uid", sprint_hex(hdr->csn, sizeof(hdr->csn))); - } - - if (readStatus & FLAG_ICLASS_CONF) { - PrintAndLogEx(SUCCESS, " Config: %s card configuration", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf))); - } - - // page mapping. If fuse0|1 == 0x01, card is in non-secure mode, with CSN, CONF, AIA as top 3 blocks. - // page9 in http://www.proxmark.org/files/Documents/13.56%20MHz%20-%20iClass/DS%20Picopass%202KS%20V1-0.pdf - uint8_t pagemap = get_pagemap(hdr); - if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { - PrintAndLogEx(SUCCESS, " AIA: %s application issuer area", sprint_hex(ns_hdr->app_issuer_area, sizeof(ns_hdr->app_issuer_area))); - } else { - - if (readStatus & FLAG_ICLASS_CC) { - PrintAndLogEx(SUCCESS, "E-purse: %s Card challenge, CC", sprint_hex(hdr->epurse, sizeof(hdr->epurse))); - } - - PrintAndLogEx(SUCCESS, " Kd: %s debit key, hidden", sprint_hex(hdr->key_d, sizeof(hdr->key_d))); - PrintAndLogEx(SUCCESS, " Kc: %s credit key, hidden", sprint_hex(hdr->key_c, sizeof(hdr->key_c))); - - if (readStatus & FLAG_ICLASS_AIA) { - PrintAndLogEx(SUCCESS, " AIA: %s application issuer area", sprint_hex(hdr->app_issuer_area, sizeof(hdr->app_issuer_area))); - } - } - - if (readStatus & FLAG_ICLASS_CONF) { - print_picopass_info(hdr); - } - - PrintAndLogEx(INFO, "------------------------ " _CYAN_("Fingerprint") " -----------------------"); - - uint8_t aia[8]; - if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { - memcpy(aia, ns_hdr->app_issuer_area, sizeof(aia)); - } else { - memcpy(aia, hdr->app_issuer_area, sizeof(aia)); - } - - // if CSN ends with FF12E0, it's inside HID CSN range. - bool isHidRange = (memcmp(hdr->csn + 5, "\xFF\x12\xE0", 3) == 0); - - bool legacy = (memcmp(aia, "\xff\xff\xff\xff\xff\xff\xff\xff", 8) == 0); - bool se_enabled = (memcmp(aia, "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0); - - if (isHidRange) { - PrintAndLogEx(SUCCESS, " CSN.......... " _YELLOW_("HID range")); - if (legacy) - PrintAndLogEx(SUCCESS, " Credential... " _GREEN_("iCLASS legacy")); - if (se_enabled) - PrintAndLogEx(SUCCESS, " Credential... " _GREEN_("iCLASS SE")); - } else { - PrintAndLogEx(SUCCESS, " CSN.......... " _YELLOW_("outside HID range")); - } - - uint8_t cardtype = get_mem_config(hdr); - PrintAndLogEx(SUCCESS, " Card type.... " _GREEN_("%s"), card_types[cardtype]); + if (WaitForResponseTimeout(CMD_HF_ICLASS_READER, &resp, 2000) == false) { + DropField(); + return PM3_ETIMEOUT; } DropField(); + + iclass_card_select_resp_t *r = (iclass_card_select_resp_t*)resp.data.asBytes; + + // no tag found or button pressed + if (r->status == FLAG_ICLASS_NULL || resp.status == PM3_ERFTRANS) { + return PM3_EOPABORTED; + } + + picopass_hdr_t *hdr = &r->header.hdr; + picopass_ns_hdr_t *ns_hdr = &r->header.ns_hdr; + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "--------------------- " _CYAN_("Tag Information") " ----------------------"); + + if ((r->status & FLAG_ICLASS_CSN) == FLAG_ICLASS_CSN) { + PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " uid", sprint_hex(hdr->csn, sizeof(hdr->csn))); + } + + if ((r->status & FLAG_ICLASS_CONF) == FLAG_ICLASS_CONF) { + PrintAndLogEx(SUCCESS, " Config: %s card configuration", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf))); + } + + // page mapping. If fuse0|1 == 0x01, card is in non-secure mode, with CSN, CONF, AIA as top 3 blocks. + // page9 in http://www.proxmark.org/files/Documents/13.56%20MHz%20-%20iClass/DS%20Picopass%202KS%20V1-0.pdf + uint8_t pagemap = get_pagemap(hdr); + if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { + PrintAndLogEx(SUCCESS, " AIA: %s application issuer area", sprint_hex(ns_hdr->app_issuer_area, sizeof(ns_hdr->app_issuer_area))); + } else { + + if ((r->status & FLAG_ICLASS_CC) == FLAG_ICLASS_CC) { + PrintAndLogEx(SUCCESS, "E-purse: %s Card challenge, CC", sprint_hex(hdr->epurse, sizeof(hdr->epurse))); + } + + if (memcmp(hdr->key_d, zeros, sizeof(zeros))) { + PrintAndLogEx(SUCCESS, " Kd: " _YELLOW_("%s") " debit key", sprint_hex(hdr->key_d, sizeof(hdr->key_d))); + } else { + PrintAndLogEx(SUCCESS, " Kd: %s debit key ( hidden )", sprint_hex(hdr->key_d, sizeof(hdr->key_d))); + } + + if (memcmp(hdr->key_c, zeros, sizeof(zeros))) { + PrintAndLogEx(SUCCESS, " Kc: " _YELLOW_("%s") " credit key", sprint_hex(hdr->key_c, sizeof(hdr->key_c))); + } else { + PrintAndLogEx(SUCCESS, " Kc: %s credit key ( hidden )", sprint_hex(hdr->key_c, sizeof(hdr->key_c))); + } + + + if ((r->status & FLAG_ICLASS_AIA) == FLAG_ICLASS_AIA) { + PrintAndLogEx(SUCCESS, " AIA: %s application issuer area", sprint_hex(hdr->app_issuer_area, sizeof(hdr->app_issuer_area))); + } + } + + if ((r->status & FLAG_ICLASS_CONF) == FLAG_ICLASS_CONF) { + print_picopass_info(hdr); + } + + PrintAndLogEx(INFO, "------------------------ " _CYAN_("Fingerprint") " -----------------------"); + + uint8_t aia[8]; + if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { + memcpy(aia, ns_hdr->app_issuer_area, sizeof(aia)); + } else { + memcpy(aia, hdr->app_issuer_area, sizeof(aia)); + } + + // if CSN ends with FF12E0, it's inside HID CSN range. + bool isHidRange = (memcmp(hdr->csn + 5, "\xFF\x12\xE0", 3) == 0); + + bool legacy = (memcmp(aia, "\xff\xff\xff\xff\xff\xff\xff\xff", 8) == 0); + bool se_enabled = (memcmp(aia, "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0); + + if (isHidRange) { + PrintAndLogEx(SUCCESS, " CSN.......... " _YELLOW_("HID range")); + if (legacy) + PrintAndLogEx(SUCCESS, " Credential... " _GREEN_("iCLASS legacy")); + if (se_enabled) + PrintAndLogEx(SUCCESS, " Credential... " _GREEN_("iCLASS SE")); + } else { + PrintAndLogEx(SUCCESS, " CSN.......... " _YELLOW_("outside HID range")); + } + + uint8_t cardtype = get_mem_config(hdr); + PrintAndLogEx(SUCCESS, " Card type.... " _GREEN_("%s"), card_types[cardtype]); + return PM3_SUCCESS; } diff --git a/client/src/cmdhficlass.h b/client/src/cmdhficlass.h index 73d34df0b..9474dde45 100644 --- a/client/src/cmdhficlass.h +++ b/client/src/cmdhficlass.h @@ -13,21 +13,7 @@ #include "common.h" #include "fileutils.h" -#include "pm3_cmd.h" - -typedef struct iclass_block { - uint8_t d[8]; -} iclass_block_t; - -typedef struct iclass_prekey { - uint8_t mac[4]; - uint8_t key[8]; -} iclass_prekey_t; - -typedef struct { - char desc[70]; - uint8_t data[16]; -} iclass_config_card_item_t; +#include "iclass_cmd.h" int CmdHFiClass(const char *Cmd); diff --git a/client/src/cmdhfjooki.c b/client/src/cmdhfjooki.c index a789fb762..0c89406ba 100644 --- a/client/src/cmdhfjooki.c +++ b/client/src/cmdhfjooki.c @@ -135,7 +135,7 @@ static int jooki_encode(uint8_t *iv, uint8_t tid, uint8_t fid, uint8_t *uid, uin return PM3_EINVARG; } - uint8_t d[JOOKI_PLAIN_LEN] = {iv[0], iv[1], iv[2], tid, fid, uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6]}; + const uint8_t d[JOOKI_PLAIN_LEN] = {iv[0], iv[1], iv[2], tid, fid, uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6]}; uint8_t enc[JOOKI_PLAIN_LEN] = {0}; for (uint8_t i = 0; i < JOOKI_PLAIN_LEN; i++) { diff --git a/client/src/cmdhfksx6924.c b/client/src/cmdhfksx6924.c index 05a838bb0..9014ca519 100644 --- a/client/src/cmdhfksx6924.c +++ b/client/src/cmdhfksx6924.c @@ -111,7 +111,7 @@ static int CmdHFKSX6924Info(const char *Cmd) { uint16_t sw = 0; int res = KSX6924Select(true, true, buf, sizeof(buf), &len, &sw); - if (res) { + if (res || (len == 0)) { if (keep == false) { DropField(); } @@ -134,6 +134,7 @@ static int CmdHFKSX6924Info(const char *Cmd) { // FCI Response is a BER-TLV, we are interested in tag 6F,B0 only. const uint8_t *p = buf; struct tlv fci_tag; + memset(&fci_tag, 0, sizeof(fci_tag)); while (len > 0) { memset(&fci_tag, 0, sizeof(fci_tag)); @@ -244,7 +245,7 @@ static int CmdHFKSX6924Initialize(const char *Cmd) { arg_param_begin, arg_lit0("k", "keep", "keep field ON for next command"), arg_lit0("a", "apdu", "show APDU reqests and responses"), - arg_strx1(NULL, NULL, "", NULL), + arg_str1(NULL, NULL, "", NULL), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -297,7 +298,7 @@ static int CmdHFKSX6924PRec(const char *Cmd) { arg_param_begin, arg_lit0("k", "keep", "keep field ON for next command"), arg_lit0("a", "apdu", "show APDU reqests and responses"), - arg_strx1(NULL, NULL, "", NULL), + arg_str1(NULL, NULL, "", NULL), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); diff --git a/client/src/cmdhflegic.c b/client/src/cmdhflegic.c index 4a95bd683..d96fa320f 100644 --- a/client/src/cmdhflegic.c +++ b/client/src/cmdhflegic.c @@ -762,7 +762,7 @@ static int CmdLegicDump(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "specify a filename for dump file"), + arg_str0("f", "file", "", "Dump filename"), arg_lit0(NULL, "de", "deobfuscate dump data (xor with MCC)"), arg_param_end }; @@ -859,7 +859,7 @@ static int CmdLegicRestore(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str1("f", "file", "", "specify a filename to restore"), + arg_str1("f", "file", "", "Filename to restore"), arg_lit0(NULL, "ob", "obfuscate dump data (xor with MCC)"), arg_param_end }; @@ -963,7 +963,7 @@ static int CmdLegicELoad(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str1("f", "file", "", "Specify a filename to restore"), + arg_str1("f", "file", "", "Filename to restore"), arg_int0("t", "type", "", "Tag type to simulate."), arg_lit0(NULL, "obfuscate", "Obfuscate dump data (xor with MCC)"), arg_param_end @@ -1032,7 +1032,7 @@ static int CmdLegicESave(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "Specify a filename to save"), + arg_str0("f", "file", "", "Filename to save"), arg_int0("t", "type", "", "Tag type"), arg_lit0(NULL, "deobfuscate", "De-obfuscate dump data (xor with MCC)"), arg_param_end diff --git a/client/src/cmdhflto.c b/client/src/cmdhflto.c index 727da2548..71eea185b 100644 --- a/client/src/cmdhflto.c +++ b/client/src/cmdhflto.c @@ -729,7 +729,7 @@ static int CmdHfLTRestore(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str1("f", "file", "", "specify a filename for dumpfile"), + arg_str1("f", "file", "", "specify a filename for dumpfile"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 63e5665f7..eb4097ee7 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -444,7 +444,7 @@ static int CmdHF14AMfRdBl(const char *Cmd) { CLIParserInit(&ctx, "hf mf rdbl", "Read MIFARE Classic block", "hf mf rdbl --blk 0 -k FFFFFFFFFFFF\n" - "hf mf rdbl -b 3 -v -> get block 3, decode sector trailer\n" + "hf mf rdbl --blk 3 -v -> get block 3, decode sector trailer\n" ); void *argtable[] = { arg_param_begin, @@ -6133,11 +6133,11 @@ static int CmdHF14AMfView(const char *Cmd) { return PM3_SUCCESS; } -static int CmdHF14AGen3View(const char *Cmd) { +static int CmdHF14AGen4View(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf gview", - "View `magic gen3 gtu` card memory", + "View `magic gen4 gtu` card memory", "hf mf gview\n" "hf mf gview --4k" ); @@ -6147,6 +6147,7 @@ static int CmdHF14AGen3View(const char *Cmd) { arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"), arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"), arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"), + arg_str0("p", "pwd", "", "password 4bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -6154,9 +6155,18 @@ static int CmdHF14AGen3View(const char *Cmd) { bool m1 = arg_get_lit(ctx, 2); bool m2 = arg_get_lit(ctx, 3); bool m4 = arg_get_lit(ctx, 4); + + int pwd_len = 0; + uint8_t pwd[4] = {0}; + CLIGetHexWithReturn(ctx, 5, pwd, &pwd_len); CLIParserFree(ctx); // validations + if (pwd_len != 4 && pwd_len != 0) { + PrintAndLogEx(FAILED, "Must specify 4 bytes, got " _YELLOW_("%u"), pwd_len); + return PM3_EINVARG; + } + if ((m0 + m1 + m2 + m4) > 1) { PrintAndLogEx(WARNING, "Only specify one MIFARE Type"); return PM3_EINVARG; @@ -6183,7 +6193,7 @@ static int CmdHF14AGen3View(const char *Cmd) { PrintAndLogEx(WARNING, "Please specify a MIFARE Type"); return PM3_EINVARG; } - PrintAndLogEx(SUCCESS, "View magic gen3 GTU MIFARE Classic " _GREEN_("%s"), s); + PrintAndLogEx(SUCCESS, "View magic gen4 GTU MIFARE Classic " _GREEN_("%s"), s); PrintAndLogEx(INFO, "." NOLF); // Select card to get UID/UIDLEN information @@ -6221,7 +6231,7 @@ static int CmdHF14AGen3View(const char *Cmd) { for (uint16_t i = 0; i < block_cnt; i++) { - if (mfG3GetBlock(i, dump + (i * MFBLOCK_SIZE)) != PM3_SUCCESS) { + if (mfG4GetBlock(pwd, i, dump + (i * MFBLOCK_SIZE)) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Can't get magic card block: %u", i); PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position"); free(dump); @@ -6290,8 +6300,8 @@ static command_t CommandTable[] = { {"gen3uid", CmdHf14AGen3UID, IfPm3Iso14443a, "Set UID without changing manufacturer block"}, {"gen3blk", CmdHf14AGen3Block, IfPm3Iso14443a, "Overwrite manufacturer block"}, {"gen3freeze", CmdHf14AGen3Freeze, IfPm3Iso14443a, "Perma lock UID changes. irreversible"}, - {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen3 GTU") " -----------------------"}, - {"gview", CmdHF14AGen3View, IfPm3Iso14443a, "View card"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("magic gen4 GTU") " --------------------------"}, + {"gview", CmdHF14AGen4View, IfPm3Iso14443a, "View card"}, // {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("i") " -----------------------"}, // {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"}, {NULL, NULL, NULL, NULL} diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 1e5297e15..428364608 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1056,7 +1056,7 @@ static int CmdHF14aDesChk(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx0(NULL, "aid", "", "Use specific AID (3 hex bytes, big endian)"), + arg_str0(NULL, "aid", "", "Use specific AID (3 hex bytes, big endian)"), arg_str0("k", "key", "", "Key for checking (HEX 16 bytes)"), arg_str0("d", "dict", "", "File with keys dictionary"), arg_lit0(NULL, "pattern1b", "Check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)"), @@ -1914,8 +1914,8 @@ static int CmdHF14ADesBruteApps(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx0("s", "start", "", "Starting App ID as hex bytes (3 bytes, big endian)"), - arg_strx0("e", "end", "", "Last App ID as hex bytes (3 bytes, big endian)"), + arg_str0("s", "start", "", "Starting App ID as hex bytes (3 bytes, big endian)"), + arg_str0("e", "end", "", "Last App ID as hex bytes (3 bytes, big endian)"), arg_int0("i", "step", "", "Increment step when bruteforcing"), arg_lit0("m", "mad", "Only bruteforce the MAD range"), arg_param_end diff --git a/client/src/cmdhfmfp.c b/client/src/cmdhfmfp.c index 89584260a..339d8fae4 100644 --- a/client/src/cmdhfmfp.c +++ b/client/src/cmdhfmfp.c @@ -456,7 +456,7 @@ static int CmdHFMFPWritePerso(const char *Cmd) { arg_param_begin, arg_lit0("v", "verbose", "show internal data."), arg_str1(NULL, "ki", "", " key number, 2 hex bytes"), - arg_strx0(NULL, "key", "", " key, 16 hex bytes"), + arg_str0(NULL, "key", "", " key, 16 hex bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -521,7 +521,7 @@ static int CmdHFMFPInitPerso(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_litn("v", "verbose", 0, 2, "show internal data."), - arg_strx0("k", "key", "", "key, 16 hex bytes"), + arg_str0("k", "key", "", "key, 16 hex bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 9cf622f6b..722f02f2b 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -1772,6 +1772,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { arg_lit0("l", NULL, "swap entered key's endianness"), arg_int1("b", "block", "", "block number to write"), arg_str1("d", "data", "", "block data (4 or 16 hex bytes, 16 hex bytes will do a compatibility write)"), + arg_lit0(NULL, "force", "force operation even if address is out of range"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -1786,6 +1787,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { int datalen = 0; uint8_t data[16] = {0x00}; CLIGetHexWithReturn(ctx, 4, data, &datalen); + bool force = arg_get_lit(ctx, 5); CLIParserFree(ctx); bool has_auth_key = false; @@ -1823,7 +1825,7 @@ static int CmdHF14AMfUWrBl(const char *Cmd) { break; } } - if (blockno > maxblockno) { + if ((blockno > maxblockno) && (!force)) { PrintAndLogEx(WARNING, "block number too large. Max block is %u/0x%02X \n", maxblockno, maxblockno); return PM3_EINVARG; } @@ -1901,6 +1903,7 @@ static int CmdHF14AMfURdBl(const char *Cmd) { arg_str0("k", "key", "", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"), arg_lit0("l", NULL, "swap entered key's endianness"), arg_int1("b", "block", "", "block number to read"), + arg_lit0(NULL, "force", "force operation even if address is out of range"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -1910,6 +1913,7 @@ static int CmdHF14AMfURdBl(const char *Cmd) { CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len); bool swap_endian = arg_get_lit(ctx, 2); int blockno = arg_get_int_def(ctx, 3, -1); + bool force = arg_get_lit(ctx, 4); CLIParserFree(ctx); bool has_auth_key = false; @@ -1942,7 +1946,7 @@ static int CmdHF14AMfURdBl(const char *Cmd) { break; } } - if (blockno > maxblockno) { + if ((blockno > maxblockno) && (!force)) { PrintAndLogEx(WARNING, "block number to large. Max block is %u/0x%02X \n", maxblockno, maxblockno); return PM3_EINVARG; } diff --git a/client/src/cmdhfwaveshare.c b/client/src/cmdhfwaveshare.c index e99830d49..01dc7d63c 100644 --- a/client/src/cmdhfwaveshare.c +++ b/client/src/cmdhfwaveshare.c @@ -179,7 +179,7 @@ static void dither_chan_inplace(int16_t *chan, uint16_t width, uint16_t height) int16_t newp = oldp > 127 ? 255 : 0; chan[X + Y * width] = newp; int16_t err = oldp - newp; - float m[] = {7, 3, 5, 1}; + const float m[] = {7, 3, 5, 1}; if (X < width - 1) { chan[X + 1 + Y * width] = chan[X + 1 + Y * width] + m[0] / 16 * err; } @@ -239,7 +239,7 @@ static void dither_rgb_inplace(int16_t *chanR, int16_t *chanG, int16_t *chanB, u int16_t errR = oldR - newR; int16_t errG = oldG - newG; int16_t errB = oldB - newB; - float m[] = {7, 3, 5, 1}; + const float m[] = {7, 3, 5, 1}; if (Y % 2) { if (XX > 0) { chanR[XX - 1 + Y * width] = (chanR[XX - 1 + Y * width] + m[0] / 16 * errR); @@ -593,7 +593,7 @@ static int start_drawing_1in54B(uint8_t model_nr, uint8_t *black, uint8_t *red) uint8_t step_4[2] = {0xcd, 0x04}; uint8_t step_6[2] = {0xcd, 0x06}; uint8_t rx[20] = {0}; - uint16_t actrxlen[20], i = 0, progress = 0; + uint16_t actrxlen[20], i, progress; if (model_nr == M1in54B) { step_5[2] = 100; @@ -616,6 +616,7 @@ static int start_drawing_1in54B(uint8_t model_nr, uint8_t *black, uint8_t *red) if (ret != PM3_SUCCESS) { return ret; } + PrintAndLogEx(DEBUG, "1.54_Step7: e-paper config2 (red)"); if (model_nr == M1in54B) { //1.54inch B Keychain for (i = 0; i < 50; i++) { @@ -635,12 +636,13 @@ static int start_drawing_1in54B(uint8_t model_nr, uint8_t *black, uint8_t *red) if (ret != PM3_SUCCESS) { return ret; } + PrintAndLogEx(DEBUG, "1.54_Step9"); return PM3_SUCCESS; } static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) { - uint8_t progress = 0; + uint8_t progress; uint8_t step0[2] = {0xcd, 0x0d}; uint8_t step1[3] = {0xcd, 0x00, 10}; // select e-paper type and reset e-paper // 4 :2.13inch e-Paper @@ -667,14 +669,12 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) { // uint8_t step13[2]={0xcd,0x0b}; // Judge whether the power supply is turned off successfully // uint8_t step14[2]={0xcd,0x0c}; // The end of the transmission uint8_t rx[20]; - uint16_t actrxlen[20], i = 0; - - + uint16_t actrxlen[20], i; clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) { PrintAndLogEx(ERR, "No tag found"); DropField(); return PM3_ETIMEOUT; @@ -711,40 +711,41 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) { return PM3_ESOFT; } PrintAndLogEx(DEBUG, "model_nr = %d", model_nr); - int ret; + PrintAndLogEx(DEBUG, "Step0"); - ret = transceive_blocking(step0, 2, rx, 20, actrxlen, true); //cd 0d + int ret = transceive_blocking(step0, 2, rx, 20, actrxlen, true); //cd 0d if (ret != PM3_SUCCESS) { return ret; } + PrintAndLogEx(DEBUG, "Step1: e-paper config"); - //step1[2] screen model - //step8[2] nr of bytes sent at once - //step13[2] nr of bytes sent for the second time + // step1[2] screen model + // step8[2] nr of bytes sent at once + // step13[2] nr of bytes sent for the second time // generally, step8 sends a black image, step13 sends a red image - if (model_nr == M2in13) { //2.13inch + if (model_nr == M2in13) { // 2.13inch step1[2] = EPD_2IN13V2; step8[2] = 16; step13[2] = 0; - } else if (model_nr == M2in9) { //2.9inch + } else if (model_nr == M2in9) { // 2.9inch step1[2] = EPD_2IN9; step8[2] = 16; step13[2] = 0; - } else if (model_nr == M4in2) { //4.2inch + } else if (model_nr == M4in2) { // 4.2inch step1[2] = EPD_4IN2; step8[2] = 100; step13[2] = 0; - } else if (model_nr == M7in5) { //7.5inch + } else if (model_nr == M7in5) { // 7.5inch step1[2] = EPD_7IN5V2; step8[2] = 120; step13[2] = 0; - } else if (model_nr == M2in7) { //2.7inch + } else if (model_nr == M2in7) { // 2.7inch step1[2] = EPD_2IN7; step8[2] = 121; // Send blank data for the first time, and send other data to 0xff without processing the bottom layer step13[2] = 121; - //Sending the second data is the real image data. If the previous 0xff is not sent, the last output image is abnormally black - } else if (model_nr == M2in13B) { //2.13inch B + // Sending the second data is the real image data. If the previous 0xff is not sent, the last output image is abnormally black + } else if (model_nr == M2in13B) { // 2.13inch B step1[2] = EPD_2IN13BC; step8[2] = 106; step13[2] = 106; @@ -755,31 +756,35 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) { } if (model_nr == M1in54B) { - ret = transceive_blocking(step1, 2, rx, 20, actrxlen, true); //cd 00 + ret = transceive_blocking(step1, 2, rx, 20, actrxlen, true); // cd 00 } else { ret = transceive_blocking(step1, 3, rx, 20, actrxlen, true); } if (ret != PM3_SUCCESS) { return ret; } + msleep(100); PrintAndLogEx(DEBUG, "Step2: e-paper normal mode type"); - ret = transceive_blocking(step2, 2, rx, 20, actrxlen, true); //cd 01 + ret = transceive_blocking(step2, 2, rx, 20, actrxlen, true); // cd 01 if (ret != PM3_SUCCESS) { return ret; } + msleep(100); PrintAndLogEx(DEBUG, "Step3: e-paper config1"); - ret = transceive_blocking(step3, 2, rx, 20, actrxlen, true); //cd 02 + ret = transceive_blocking(step3, 2, rx, 20, actrxlen, true); // cd 02 if (ret != PM3_SUCCESS) { return ret; } + msleep(200); PrintAndLogEx(DEBUG, "Step4: e-paper power on"); - ret = transceive_blocking(step4, 2, rx, 20, actrxlen, true); //cd 03 + ret = transceive_blocking(step4, 2, rx, 20, actrxlen, true); // cd 03 if (ret != PM3_SUCCESS) { return ret; } + if (model_nr == M1in54B) { // 1.54B Keychain handler PrintAndLogEx(DEBUG, "Start_Drawing_1in54B"); @@ -787,27 +792,27 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) { if (ret != PM3_SUCCESS) { return ret; } - //1.54B Data transfer is complete and wait for refresh + // 1.54B Data transfer is complete and wait for refresh } else { PrintAndLogEx(DEBUG, "Step5: e-paper config2"); - ret = transceive_blocking(step5, 2, rx, 20, actrxlen, true); //cd 05 + ret = transceive_blocking(step5, 2, rx, 20, actrxlen, true); // cd 05 if (ret != PM3_SUCCESS) { return ret; } msleep(100); PrintAndLogEx(DEBUG, "Step6: EDP load to main") ; - ret = transceive_blocking(step6, 2, rx, 20, actrxlen, true); //cd 06 + ret = transceive_blocking(step6, 2, rx, 20, actrxlen, true); // cd 06 if (ret != PM3_SUCCESS) { return ret; } msleep(100); PrintAndLogEx(DEBUG, "Step7: Data preparation"); - ret = transceive_blocking(step7, 2, rx, 20, actrxlen, true); //cd 07 + ret = transceive_blocking(step7, 2, rx, 20, actrxlen, true); // cd 07 if (ret != PM3_SUCCESS) { return ret; } PrintAndLogEx(DEBUG, "Step8: Start data transfer"); - if (model_nr == M2in13) { //2.13inch + if (model_nr == M2in13) { // 2.13inch for (i = 0; i < 250; i++) { read_black(i, step8, model_nr, black); ret = transceive_blocking(step8, 19, rx, 20, actrxlen, true); // cd 08 @@ -939,6 +944,7 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) { } else if (model_nr == M7in5HD) { msleep(1000); } + uint8_t fail_num = 0; while (1) { if (model_nr == M1in54B) { @@ -1006,7 +1012,7 @@ static int CmdHF14AWSLoadBmp(const char *Cmd) { arg_param_begin, arg_int1("m", NULL, "", modeldesc), arg_lit0("s", "save", "save dithered version in filename-[n].bmp, only for RGB BMP"), - arg_str1("f", "file", "", "filename[.bmp] to upload to tag"), + arg_str1("f", "file", "", "specify filename[.bmp] to upload to tag"), arg_param_end }; diff --git a/client/src/cmdlfdestron.c b/client/src/cmdlfdestron.c index 7c8cf2760..a510089aa 100644 --- a/client/src/cmdlfdestron.c +++ b/client/src/cmdlfdestron.c @@ -136,7 +136,7 @@ static int CmdDestronClone(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx1("u", "uid", "", "5 bytes max"), + arg_str1("u", "uid", "", "5 bytes max"), arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"), arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"), arg_param_end diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index 9427a5148..f70dc1de0 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -200,7 +200,7 @@ int CmdEM4x50ELoad(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str1("f", "filename", "", "dump filename (bin/eml/json)"), + arg_str1("f", "file", "", "dump filename (bin/eml/json)"), arg_param_end }; @@ -237,7 +237,7 @@ int CmdEM4x50ESave(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "save filename"), + arg_str0("f", "file", "", "specifiy filename"), arg_param_end }; @@ -441,7 +441,7 @@ int CmdEM4x50Chk(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "dictionary filename"), + arg_str0("f", "file", "", "specify dictionary filename"), arg_param_end }; @@ -749,7 +749,7 @@ int CmdEM4x50Dump(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "dump filename (bin/eml/json)"), + arg_str0("f", "file", "", "specify dump filename (bin/eml/json)"), arg_str0("p", "pwd", "", "password, 4 hex bytes, lsb"), arg_param_end }; @@ -1060,7 +1060,7 @@ int CmdEM4x50Restore(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0("u", "uid", "", "uid, 4 hex bytes, msb"), - arg_str0("f", "file", "", "dump filename (bin/eml/json)"), + arg_str0("f", "file", "", "specify dump filename (bin/eml/json)"), arg_str0("p", "pwd", "", "password, 4 hex bytes, lsb"), arg_param_end }; diff --git a/client/src/cmdlfguard.c b/client/src/cmdlfguard.c index df2f430a5..4a31e8f19 100644 --- a/client/src/cmdlfguard.c +++ b/client/src/cmdlfguard.c @@ -27,6 +27,64 @@ static int CmdHelp(const char *Cmd); +static int demod_guard_raw(uint8_t *raw, uint8_t rlen) { + + if (rlen != 12) { + return PM3_EINVARG; + } + + uint8_t bits[96] = {0x00}; + bytes_to_bytebits(raw, rlen, bits); + + // start after 6 bit preamble + size_t start_idx = 6; + uint8_t bits_no_spacer[90]; + memcpy(bits_no_spacer, bits + start_idx, 90); + + // remove the 18 (90/5=18) parity bits (down to 72 bits (96-6-18=72)) + size_t len = removeParity(bits_no_spacer, 0, 5, 3, 90); // source, startloc, paritylen, ptype, length_to_run + if (len != 72) { + PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII spacer removal did not produce 72 bits: %zu, start: %zu", len, start_idx); + return PM3_ESOFT; + } + + uint8_t plain[8] = {0x00}; + + // get key and then get all 8 bytes of payload decoded + uint8_t xorKey = (uint8_t)bytebits_to_byteLSBF(bits_no_spacer, 8); + for (size_t idx = 0; idx < 8; idx++) { + plain[idx] = ((uint8_t)bytebits_to_byteLSBF(bits_no_spacer + 8 + (idx * 8), 8)) ^ xorKey; + PrintAndLogEx(DEBUG, "DEBUG: gProxII byte %zu after xor: %02x", idx, plain[idx]); + } + + // plain contains 8 Bytes (64 bits) of decrypted raw tag data + uint8_t fmtlen = plain[0] >> 2; + uint32_t FC = 0; + uint32_t Card = 0; + + bool unknown = false; + switch (fmtlen) { + case 36: + FC = ((plain[3] & 0x7F) << 7) | (plain[4] >> 1); + Card = ((plain[4] & 1) << 19) | (plain[5] << 11) | (plain[6] << 3) | ((plain[7] & 0xE0) >> 5); + break; + case 26: + FC = ((plain[3] & 0x7F) << 1) | (plain[4] >> 7); + Card = ((plain[4] & 0x7F) << 9) | (plain[5] << 1) | (plain[6] >> 7); + break; + default : + unknown = true; + break; + } + + if (unknown) + PrintAndLogEx(SUCCESS, "G-Prox-II - Unknown len: " _GREEN_("%u") ", Raw: %s", fmtlen, sprint_hex_inrow(raw, rlen)); + else + PrintAndLogEx(SUCCESS, "G-Prox-II - len: " _GREEN_("%u")" FC: " _GREEN_("%u") " Card: " _GREEN_("%u") ", Raw: %s", fmtlen, FC, Card, sprint_hex_inrow(raw, rlen)); + + return PM3_SUCCESS; +} + // attempts to demodulate and identify a G_Prox_II verex/chubb card // WARNING: if it fails during some points it will destroy the g_DemodBuffer data // but will leave the g_GraphBuffer intact. @@ -59,7 +117,6 @@ int demodGuard(bool verbose) { } // got a good demod of 96 bits - uint8_t plain[8] = {0x00}; uint8_t xorKey = 0; size_t startIdx = preambleIndex + 6; //start after 6 bit preamble @@ -119,16 +176,32 @@ static int CmdGuardDemod(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf gproxii demod", "Try to find Guardall Prox-II preamble, if found decode / descramble data", - "lf gproxii demod" + "lf gproxii demod -> use graphbuffer to decode\n" + "lf gproxii demod --raw fb8ee718ee3b8cc785c11b92 ->" ); void *argtable[] = { arg_param_begin, + arg_str0("r", "raw", "", "raw bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); + + int raw_len = 0; + uint8_t raw[12] = {0}; + CLIGetHexWithReturn(ctx, 1, raw, &raw_len); + CLIParserFree(ctx); - return demodGuard(true); + + if (raw_len != 12 && raw_len != 0) { + PrintAndLogEx(FAILED, "Must specify 12 bytes, got " _YELLOW_("%u"), raw_len); + return PM3_EINVARG; + } + + if (raw_len == 0) + return demodGuard(true); + else + return demod_guard_raw(raw, raw_len); } static int CmdGuardReader(const char *Cmd) { diff --git a/client/src/cmdlfhid.c b/client/src/cmdlfhid.c index 984dc482d..103dd9f87 100644 --- a/client/src/cmdlfhid.c +++ b/client/src/cmdlfhid.c @@ -246,7 +246,7 @@ static int CmdHIDSim(const char *Cmd) { arg_u64_0(NULL, "cn", "", "card number"), arg_u64_0("i", NULL, "", "issue level"), arg_u64_0("o", "oem", "", "OEM code"), - arg_strx0("r", "raw", "", "raw bytes"), + arg_str0("r", "raw", "", "raw bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -330,7 +330,7 @@ static int CmdHIDClone(const char *Cmd) { arg_u64_0(NULL, "cn", "", "card number"), arg_int0("i", NULL, "", "issue level"), arg_int0("o", "oem", "", "OEM code"), - arg_strx0("r", "raw", "", "raw bytes"), + arg_str0("r", "raw", "", "raw bytes"), arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"), arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"), arg_str0(NULL, "bin", "", "Binary string i.e 0001001001"), diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index 02d84321a..74534b915 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -17,6 +17,7 @@ #include "fileutils.h" // savefile #include "protocols.h" // defines #include "cliparser.h" +#include "crc.h" static int CmdHelp(const char *Cmd); @@ -214,7 +215,7 @@ static int CmdLFHitagEload(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str1("f", "file", "", "filename of dump"), + arg_str1("f", "file", "", "Specfiy dump filename"), arg_lit0("1", NULL, "Card type Hitag1"), arg_lit0("2", NULL, "Card type Hitag2"), arg_lit0("s", NULL, "Card type HitagS"), @@ -575,8 +576,8 @@ static int CmdLFHitagReader(const char *Cmd) { return PM3_EINVARG; } - if (nalen != 0 && nalen != 6) { - PrintAndLogEx(WARNING, "Wrong NR/AR len expected 0 or 6, got %d", nalen); + if (nalen != 0 && nalen != 8) { + PrintAndLogEx(WARNING, "Wrong NR/AR len expected 0 or 8, got %d", nalen); return PM3_EINVARG; } @@ -628,7 +629,6 @@ static int CmdLFHitagReader(const char *Cmd) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); return PM3_ETIMEOUT; } - if (resp.oldarg[0] == false) { PrintAndLogEx(DEBUG, "DEBUG: Error - hitag failed"); return PM3_ESOFT; @@ -657,7 +657,7 @@ static int CmdLFHitagCheckChallenges(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "filename to load ( w/o ext )"), + arg_str1("f", "file", "", "filename to load ( w/o ext )"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -670,22 +670,18 @@ static int CmdLFHitagCheckChallenges(const char *Cmd) { clearCommandBuffer(); - if (fnlen > 0) { - uint8_t *data = NULL; - size_t datalen = 0; - int res = loadFile_safe(filename, ".cc", (void **)&data, &datalen); - if (res == PM3_SUCCESS) { - if (datalen == (8 * 60)) { - SendCommandOLD(CMD_LF_HITAGS_TEST_TRACES, 1, 0, 0, data, datalen); - } else { - PrintAndLogEx(ERR, "Error, file length mismatch. Expected %d, got %zu", 8 * 60, datalen); - } + uint8_t *data = NULL; + size_t datalen = 0; + int res = loadFile_safe(filename, ".cc", (void **)&data, &datalen); + if (res == PM3_SUCCESS) { + if (datalen % 8 == 0) { + SendCommandMIX(CMD_LF_HITAGS_TEST_TRACES, datalen, 0, 0, data, datalen); + } else { + PrintAndLogEx(ERR, "Error, file length mismatch. Expected multiple of 8, got %zu", datalen); } - if (data) { - free(data); - } - } else { - SendCommandMIX(CMD_LF_HITAGS_TEST_TRACES, 0, 0, 0, NULL, 0); + } + if (data) { + free(data); } return PM3_SUCCESS; @@ -831,7 +827,7 @@ static int CmdLFHitag2Dump(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "file name"), + arg_str0("f", "file", "", "specify file name"), arg_str0("k", "key", "", "key, 4 or 6 hex bytes"), arg_str0(NULL, "nrar", "", "nonce / answer reader, 8 hex bytes"), arg_param_end @@ -970,3 +966,8 @@ int CmdLFHitag(const char *Cmd) { int readHitagUid(void) { return (CmdLFHitagReader("--26") == PM3_SUCCESS); } + +uint8_t hitag1_CRC_check(uint8_t *d, uint32_t nbit) { + if (nbit < 9) return 2; + return (CRC8Hitag1Bits(d, nbit) == 0); +} diff --git a/client/src/cmdlfhitag.h b/client/src/cmdlfhitag.h index 817cb16f3..7f92285e8 100644 --- a/client/src/cmdlfhitag.h +++ b/client/src/cmdlfhitag.h @@ -19,4 +19,5 @@ int readHitagUid(void); void annotateHitag1(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_response); void annotateHitag2(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_response); void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool is_response); +uint8_t hitag1_CRC_check(uint8_t *d, uint32_t nbit); #endif diff --git a/client/src/cmdlfidteck.c b/client/src/cmdlfidteck.c index 81bf270ad..d9830c282 100644 --- a/client/src/cmdlfidteck.c +++ b/client/src/cmdlfidteck.c @@ -112,7 +112,7 @@ static int CmdIdteckClone(const char *Cmd) { ); void *argtable[] = { arg_param_begin, - arg_strx0("r", "raw", "", "raw bytes"), + arg_str1("r", "raw", "", "raw bytes"), arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"), arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"), arg_param_end @@ -178,7 +178,7 @@ static int CmdIdteckSim(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx0("r", "raw", "", "raw bytes"), + arg_str1("r", "raw", "", "raw bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); diff --git a/client/src/cmdlfindala.c b/client/src/cmdlfindala.c index e18f34301..3ffed0453 100644 --- a/client/src/cmdlfindala.c +++ b/client/src/cmdlfindala.c @@ -542,7 +542,7 @@ static int CmdIndalaSim(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx0("r", "raw", "", "raw bytes"), + arg_str0("r", "raw", "", "raw bytes"), arg_int0(NULL, "heden", "", "Cardnumber for Heden 2L format"), arg_param_end }; @@ -639,7 +639,7 @@ static int CmdIndalaClone(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx0("r", "raw", "", "raw bytes"), + arg_str0("r", "raw", "", "raw bytes"), arg_int0(NULL, "heden", "", "Card number for Heden 2L format"), arg_int0(NULL, "fc", "", "Facility code (26 bit H10301 format)"), arg_int0(NULL, "cn", "", "Card number (26 bit H10301 format)"), diff --git a/client/src/cmdlfkeri.c b/client/src/cmdlfkeri.c index e4c16fe2a..ec57d5bf8 100644 --- a/client/src/cmdlfkeri.c +++ b/client/src/cmdlfkeri.c @@ -29,11 +29,11 @@ typedef enum {Scramble = 0, Descramble = 1} KeriMSScramble_t; static int CmdKeriMSScramble(KeriMSScramble_t Action, uint32_t *FC, uint32_t *ID, uint32_t *CardID) { // 255 = Not used/Unknown other values are the bit offset in the ID/FC values - uint8_t CardToID [] = { 255, 255, 255, 255, 13, 12, 20, 5, 16, 6, 21, 17, 8, 255, 0, 7, + const uint8_t CardToID [] = { 255, 255, 255, 255, 13, 12, 20, 5, 16, 6, 21, 17, 8, 255, 0, 7, 10, 15, 255, 11, 4, 1, 255, 18, 255, 19, 2, 14, 3, 9, 255, 255 }; - uint8_t CardToFC [] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 255, + const uint8_t CardToFC [] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 255, 255, 255, 2, 255, 255, 255, 3, 255, 4, 255, 255, 255, 255, 255, 1, 255 }; diff --git a/client/src/cmdlfmotorola.c b/client/src/cmdlfmotorola.c index dd00cfca6..b4d8fa1d2 100644 --- a/client/src/cmdlfmotorola.c +++ b/client/src/cmdlfmotorola.c @@ -193,7 +193,7 @@ static int CmdMotorolaClone(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx1("r", "raw", "", "raw hex bytes. 8 bytes"), + arg_str1("r", "raw", "", "raw hex bytes. 8 bytes"), arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"), arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"), arg_param_end diff --git a/client/src/cmdlfnexwatch.c b/client/src/cmdlfnexwatch.c index 3bc05db7b..3b02b798e 100644 --- a/client/src/cmdlfnexwatch.c +++ b/client/src/cmdlfnexwatch.c @@ -72,7 +72,7 @@ static uint8_t nexwatch_checksum(uint8_t magic, uint32_t id, uint8_t parity) { static int nexwatch_scamble(NexWatchScramble_t action, uint32_t *id, uint32_t *scambled) { // 255 = Not used/Unknown other values are the bit offset in the ID/FC values - uint8_t hex_2_id [] = { + const uint8_t hex_2_id [] = { 31, 27, 23, 19, 15, 11, 7, 3, 30, 26, 22, 18, 14, 10, 6, 2, 29, 25, 21, 17, 13, 9, 5, 1, diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index e90ebed1b..029f595fb 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -1368,7 +1368,7 @@ static bool testQ5Modulation(uint8_t mode, uint8_t modread) { } static int convertQ5bitRate(uint8_t bitRateRead) { - uint8_t expected[] = {8, 16, 32, 40, 50, 64, 100, 128}; + const uint8_t expected[] = {8, 16, 32, 40, 50, 64, 100, 128}; for (int i = 0; i < 8; i++) if (expected[i] == bitRateRead) return i; @@ -1425,7 +1425,7 @@ static bool testQ5(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk) } static bool testBitRate(uint8_t readRate, uint8_t clk) { - uint8_t expected[] = {8, 16, 32, 40, 50, 64, 100, 128}; + const uint8_t expected[] = {8, 16, 32, 40, 50, 64, 100, 128}; if (expected[readRate] == clk) return true; diff --git a/client/src/cmdlfviking.c b/client/src/cmdlfviking.c index 72ae4df45..206e65c67 100644 --- a/client/src/cmdlfviking.c +++ b/client/src/cmdlfviking.c @@ -111,7 +111,7 @@ static int CmdVikingClone(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx0(NULL, "cn", "", "8 digit hex viking card number"), + arg_str1(NULL, "cn", "", "8 digit hex viking card number"), arg_lit0(NULL, "q5", "optional - specify writing to Q5/T5555 tag"), arg_lit0(NULL, "em", "optional - specify writing to EM4305/4469 tag"), arg_param_end @@ -185,7 +185,7 @@ static int CmdVikingSim(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx0(NULL, "cn", "", "8 digit hex viking card number"), + arg_str1(NULL, "cn", "", "8 digit hex viking card number"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); diff --git a/client/src/cmdlfvisa2000.c b/client/src/cmdlfvisa2000.c index 07bdcff30..2a829f2af 100644 --- a/client/src/cmdlfvisa2000.c +++ b/client/src/cmdlfvisa2000.c @@ -44,12 +44,11 @@ static uint8_t visa_chksum(uint32_t id) { static uint8_t visa_parity(uint32_t id) { // 4bit parity LUT - uint8_t par_lut[] = { - 0, 1, 1, 0 - , 1, 0, 0, 1 - , 1, 0, 0, 1 - , 0, 1, 1, 0 + const uint8_t par_lut[] = { + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0 }; + uint8_t par = 0; par |= par_lut[(id >> 28) & 0xF ] << 7; par |= par_lut[(id >> 24) & 0xF ] << 6; diff --git a/client/src/cmdlfzx8211.c b/client/src/cmdlfzx8211.c index c6c8d7337..893875e50 100644 --- a/client/src/cmdlfzx8211.c +++ b/client/src/cmdlfzx8211.c @@ -74,6 +74,17 @@ int demodzx(bool verbose) { } static int lf_Zx_read(void) { + + PacketResponseNG resp; + clearCommandBuffer(); + + SendCommandNG(CMD_LF_ZX_READ, NULL, 0); + + if (WaitForResponseTimeout(CMD_LF_ZX_READ, &resp, 1000) == false) { + PrintAndLogEx(ERR, "Error occurred, device did not respond during read operation."); + return PM3_ETIMEOUT; + } + return PM3_SUCCESS; } diff --git a/client/src/cmdnfc.c b/client/src/cmdnfc.c index ca0f31a15..3606eb5b4 100644 --- a/client/src/cmdnfc.c +++ b/client/src/cmdnfc.c @@ -70,7 +70,7 @@ static int CmdNfcDecode(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx0("d", "data", "", "NDEF data to decode"), + arg_str0("d", "data", "", "NDEF data to decode"), arg_str0("f", "file", "", "file to load"), arg_lit0("v", "verbose", "verbose mode"), arg_param_end diff --git a/client/src/cmdsmartcard.c b/client/src/cmdsmartcard.c index f0764bbf5..7384d5a15 100644 --- a/client/src/cmdsmartcard.c +++ b/client/src/cmdsmartcard.c @@ -499,7 +499,7 @@ static int CmdSmartUpgrade(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str1("f", "file", "", "firmware file name"), + arg_str1("f", "file", "", "Specify firmware file name"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index 1e49ca64c..068588d99 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -216,10 +216,11 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr case ISO_15693: crcStatus = iso15693_CRC_check(frame, data_len); break; - case PROTO_CRYPTORF: case PROTO_HITAG1: - case PROTO_HITAG2: case PROTO_HITAGS: + crcStatus = hitag1_CRC_check(frame, (data_len * 8) - ((8 - parityBytes[0]) % 8)); + case PROTO_CRYPTORF: + case PROTO_HITAG2: default: break; } @@ -240,7 +241,8 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr sprintf(line[0], ""); } } - + uint8_t partialbytebuff = 0; + uint8_t offset = 0; for (int j = 0; j < data_len && j / 18 < 18; j++) { uint8_t parityBits = parityBytes[j >> 3]; if (protocol != LEGIC @@ -270,6 +272,18 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr snprintf(line[j / 18] + ((j % 18) * 4), 120, "%02x! ", frame[j]); } + } else if (((protocol == PROTO_HITAG1) || (protocol == PROTO_HITAG2) || (protocol == PROTO_HITAGS)) && (parityBytes[0] > 0)) { + // handle partial bytes + uint8_t nbits = parityBytes[0]; + if (j == 0) { + partialbytebuff = frame[0] << nbits; + snprintf(line[0], 120, "%02x(%i) ", frame[0] >> (8 - nbits), nbits); + offset = 2; + } else { + uint8_t byte = partialbytebuff | (frame[j] >> (8 - nbits)); + partialbytebuff = frame[j] << nbits; + snprintf(line[j / 18] + ((j % 18) * 4) + offset, 120, "%02x ", byte); + } } else { snprintf(line[j / 18] + ((j % 18) * 4), 120, "%02x ", frame[j]); } @@ -278,11 +292,20 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr if (markCRCBytes) { //CRC-command - if (crcStatus == 0 || crcStatus == 1) { - char *pos1 = line[(data_len - 2) / 18] + (((data_len - 2) % 18) * 4) - 1; + if (((protocol == PROTO_HITAG1) || (protocol == PROTO_HITAGS)) && (data_len > 1)) { + // Note that UID REQUEST response has no CRC, but we don't know + // if the response we see is a UID + char *pos1 = line[(data_len - 1) / 18] + (((data_len - 1) % 18) * 4) + offset - 1; (*pos1) = '['; - char *pos2 = line[(data_len) / 18] + (((data_len) % 18) * 4) - 1; + char *pos2 = line[(data_len) / 18] + (((data_len) % 18) * 4) + offset - 2; sprintf(pos2, "%c", ']'); + } else { + if (crcStatus == 0 || crcStatus == 1) { + char *pos1 = line[(data_len - 2) / 18] + (((data_len - 2) % 18) * 4) - 1; + (*pos1) = '['; + char *pos2 = line[(data_len) / 18] + (((data_len) % 18) * 4) - 1; + sprintf(pos2, "%c", ']'); + } } } @@ -567,7 +590,7 @@ static int CmdTraceLoad(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx0("f", "file", "", "trace file to load"), + arg_str1("f", "file", "", "Specify trace file to load"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -606,7 +629,7 @@ static int CmdTraceSave(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx0("f", "file", "", "trace file to save"), + arg_str1("f", "file", "", "Specify trace file to save"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -654,7 +677,7 @@ int CmdTraceListAlias(const char *Cmd, const char *alias, const char *protocol) arg_lit0("u", NULL, "display times in microseconds instead of clock cycles"), arg_lit0("x", NULL, "show hexdump to convert to pcap(ng)\n" " or to import into Wireshark using encapsulation type \"ISO 14443\""), - arg_strx0(NULL, "dict", "", "use dictionary keys file"), + arg_str0(NULL, "dict", "", "use dictionary keys file"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -672,22 +695,22 @@ int CmdTraceList(const char *Cmd) { "Annotate trace buffer with selected protocol data\n" "You can load a trace from file (see `trace load -h`) or it be downloaded from device by default\n", "trace list -t raw -> just show raw data without annotations\n" - "trace list -t 14a -> interpret as " _YELLOW_("ISO14443-A") " communications\n" - "trace list -t thinfilm -> interpret as " _YELLOW_("Thinfilm") " communications\n" - "trace list -t topaz -> interpret as " _YELLOW_("Topaz") " communications\n" - "trace list -t mf -> interpret as " _YELLOW_("MIFARE Classic") " communications and decrypt crypto1 stream\n" - "trace list -t des -> interpret as " _YELLOW_("MIFARE DESFire") " communications\n" - "trace list -t 14b -> interpret as " _YELLOW_("ISO14443-B") " communications\n" - "trace list -t 7816 -> interpret as " _YELLOW_("ISO7816-4") " communications\n" - "trace list -t 15 -> interpret as " _YELLOW_("ISO15693") " communications\n" - "trace list -t iclass -> interpret as " _YELLOW_("iCLASS") " communications\n" - "trace list -t legic -> interpret as " _YELLOW_("LEGIC") " communications\n" - "trace list -t felica -> interpret as " _YELLOW_("ISO18092 / FeliCa") " communications\n" - "trace list -t hitag1 -> interpret as " _YELLOW_("Hitag1") " communications\n" - "trace list -t hitag2 -> interpret as " _YELLOW_("Hitag2") " communications\n" - "trace list -t hitags -> interpret as " _YELLOW_("HitagS") " communications\n" - "trace list -t lto -> interpret as " _YELLOW_("LTO-CM") " communications\n" - "trace list -t cryptorf -> interpret as " _YELLOW_("CryptoRF") " communitcations\n" + "trace list -t 14a -> interpret as " _YELLOW_("ISO14443-A") "\n" + "trace list -t thinfilm -> interpret as " _YELLOW_("Thinfilm") "\n" + "trace list -t topaz -> interpret as " _YELLOW_("Topaz") "\n" + "trace list -t mf -> interpret as " _YELLOW_("MIFARE Classic") " and decrypt crypto1 stream\n" + "trace list -t des -> interpret as " _YELLOW_("MIFARE DESFire") "\n" + "trace list -t 14b -> interpret as " _YELLOW_("ISO14443-B") "\n" + "trace list -t 7816 -> interpret as " _YELLOW_("ISO7816-4") "\n" + "trace list -t 15 -> interpret as " _YELLOW_("ISO15693") "\n" + "trace list -t iclass -> interpret as " _YELLOW_("iCLASS") "\n" + "trace list -t legic -> interpret as " _YELLOW_("LEGIC") "\n" + "trace list -t felica -> interpret as " _YELLOW_("ISO18092 / FeliCa") "\n" + "trace list -t hitag1 -> interpret as " _YELLOW_("Hitag1") "\n" + "trace list -t hitag2 -> interpret as " _YELLOW_("Hitag2") "\n" + "trace list -t hitags -> interpret as " _YELLOW_("HitagS") "\n" + "trace list -t lto -> interpret as " _YELLOW_("LTO-CM") "\n" + "trace list -t cryptorf -> interpret as " _YELLOW_("CryptoRF") "\n\n" "trace list -t mf --dict -> use dictionary keys file\n" "trace list -t 14a -f -> show frame delay times\n" "trace list -t 14a -1 -> use trace buffer " @@ -702,11 +725,11 @@ int CmdTraceList(const char *Cmd) { arg_lit0("u", NULL, "display times in microseconds instead of clock cycles"), arg_lit0("x", NULL, "show hexdump to convert to pcap(ng)\n" " or to import into Wireshark using encapsulation type \"ISO 14443\""), - arg_strx0("t", "type", NULL, "protocol to annotate the trace"), - arg_strx0(NULL, "dict", "", "use dictionary keys file"), + arg_str0("t", "type", NULL, "protocol to annotate the trace"), + arg_str0(NULL, "dict", "", "use dictionary keys file"), arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, false); + CLIExecWithReturn(ctx, Cmd, argtable, true); bool use_buffer = arg_get_lit(ctx, 1); bool show_wait_cycles = arg_get_lit(ctx, 2); @@ -752,6 +775,11 @@ int CmdTraceList(const char *Cmd) { else if (strcmp(type, "lto") == 0) protocol = LTO; else if (strcmp(type, "cryptorf") == 0) protocol = PROTO_CRYPTORF; else if (strcmp(type, "raw") == 0) protocol = -1; + else if (strcmp(type, "") == 0) protocol = -1; + else { + PrintAndLogEx(FAILED, "Unknown protocol \"%s\"", type); + return PM3_EINVARG; + } if (use_buffer == false) { download_trace(); diff --git a/client/src/cmdwiegand.c b/client/src/cmdwiegand.c index e29db6a7b..3873a500a 100644 --- a/client/src/cmdwiegand.c +++ b/client/src/cmdwiegand.c @@ -113,7 +113,7 @@ int CmdWiegandDecode(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx0("r", "raw", "", "raw hex to be decoded"), + arg_str0("r", "raw", "", "raw hex to be decoded"), arg_str0("b", "bin", "", "binary string to be decoded"), arg_param_end }; diff --git a/client/src/emv/cmdemv.c b/client/src/emv/cmdemv.c index 8cd66dfaf..45d534981 100644 --- a/client/src/emv/cmdemv.c +++ b/client/src/emv/cmdemv.c @@ -81,10 +81,10 @@ static int CmdEMVSelect(const char *Cmd) { arg_param_begin, arg_lit0("sS", "select", "activate field and select card"), arg_lit0("kK", "keep", "keep field for next command"), - arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_lit0("aA", "apdu", "show APDU requests and responses"), arg_lit0("tT", "tlv", "TLV decode results"), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), - arg_strx0(NULL, NULL, "", NULL), + arg_str1(NULL, NULL, "", "Applet AID"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -247,7 +247,7 @@ static int CmdEMVGPO(const char *Cmd) { arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), - arg_strx0(NULL, NULL, "", NULL), + arg_strx0(NULL, NULL, "", "PDOLdata/PDOL"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -354,7 +354,7 @@ static int CmdEMVReadRecord(const char *Cmd) { arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), - arg_strx1(NULL, NULL, "", NULL), + arg_strx1(NULL, NULL, "", "", NULL), + arg_strx1(NULL, NULL, "", "CDOLdata/CDOL"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -590,7 +590,7 @@ static int CmdEMVInternalAuthenticate(const char *Cmd) { arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), - arg_strx1(NULL, NULL, "", NULL), + arg_strx1(NULL, NULL, "", "DDOLdata/DDOL"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -1442,7 +1442,7 @@ static int CmdEMVScan(const char *Cmd) { arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."), arg_lit0("mM", "merge", "Merge output file with card's data. (warning: the file may be corrupted!)"), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), - arg_str1(NULL, NULL, "output.json", "JSON output file name"), + arg_str1(NULL, NULL, "", "JSON output filename"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); diff --git a/client/src/flash.c b/client/src/flash.c index 869cd1630..c0ef1d25b 100644 --- a/client/src/flash.c +++ b/client/src/flash.c @@ -411,11 +411,15 @@ static void flash_suggest_update_bootloader(void) { PrintAndLogEx(ERR, _RED_("It is recommended that you first" _YELLOW_(" update your bootloader") _RED_(" alone,"))); PrintAndLogEx(ERR, _RED_("reboot the Proxmark3 then only update the main firmware") "\n"); - PrintAndLogEx(ERR, "Follow these steps :"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(ERR, "------------- " _CYAN_("Follow these steps") " -------------------"); + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(ERR, " 1) ./pm3-flash-bootrom"); PrintAndLogEx(ERR, " 2) ./pm3-flash-all"); PrintAndLogEx(ERR, " 3) ./pm3"); - PrintAndLogEx(INFO, "--------------------------------------------------------"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "---------------------------------------------------"); + PrintAndLogEx(NORMAL, ""); gs_printed_msg = true; } diff --git a/client/src/ksx6924/ksx6924core.c b/client/src/ksx6924/ksx6924core.c index 631d94771..2b4040fa7 100644 --- a/client/src/ksx6924/ksx6924core.c +++ b/client/src/ksx6924/ksx6924core.c @@ -93,82 +93,82 @@ MAKE_ENUM_TYPE(uint8_t); // KSX6924LookupCardType MAKE_ENUM_CONST(CardType, uint8_t, - { 0x00, "Pre-paid" }, - { 0x10, "Post-pay" }, - { 0x20, "Mobile post-pay" }, -); +{ 0x00, "Pre-paid" }, +{ 0x10, "Post-pay" }, +{ 0x20, "Mobile post-pay" }, + ); // KSX6924LookupAlg MAKE_ENUM_CONST(Alg, uint8_t, - { 0x00, "SEED" }, - { 0x10, "3DES" }, -); +{ 0x00, "SEED" }, +{ 0x10, "3DES" }, + ); // KSX6924LookupTMoneyIDCenter MAKE_ENUM_CONST(TMoneyIDCenter, uint8_t, - { 0x00, "reserved" }, - { 0x01, "Korea Financial Telecommunications and Clearings Institute" }, - { 0x02, "A-Cash" }, - { 0x03, "Mybi" }, +{ 0x00, "reserved" }, +{ 0x01, "Korea Financial Telecommunications and Clearings Institute" }, +{ 0x02, "A-Cash" }, +{ 0x03, "Mybi" }, - { 0x05, "V-Cash" }, - { 0x06, "Mondex Korea" }, - { 0x07, "Korea Expressway Corporation" }, - { 0x08, "Korea Smart Card Corporation" }, - { 0x09, "KORAIL Networks" }, +{ 0x05, "V-Cash" }, +{ 0x06, "Mondex Korea" }, +{ 0x07, "Korea Expressway Corporation" }, +{ 0x08, "Korea Smart Card Corporation" }, +{ 0x09, "KORAIL Networks" }, - { 0x0b, "EB Card Corporation" }, - { 0x0c, "Seoul Bus Transport Association" }, - { 0x0d, "Cardnet" }, -); +{ 0x0b, "EB Card Corporation" }, +{ 0x0c, "Seoul Bus Transport Association" }, +{ 0x0d, "Cardnet" }, + ); // KSX6924LookupTMoneyUserCode MAKE_ENUM_CONST(TMoneyUserCode, uint8_t, - { 0x01, "Regular/normal" }, - { 0x02, "Child" }, +{ 0x01, "Regular/normal" }, +{ 0x02, "Child" }, - { 0x04, "Youth" }, +{ 0x04, "Youth" }, - { 0x06, "elderly" }, +{ 0x06, "elderly" }, - { 0x0f, "Test" }, - { 0xff, "Inactive" }, -); +{ 0x0f, "Test" }, +{ 0xff, "Inactive" }, + ); // KSX6924LookupTMoneyDisRate MAKE_ENUM_CONST(TMoneyDisRate, uint8_t, - { 0x00, "No discount" }, +{ 0x00, "No discount" }, - { 0x10, "Disabled, basic" }, - { 0x11, "Disabled, companion" }, +{ 0x10, "Disabled, basic" }, +{ 0x11, "Disabled, companion" }, - { 0x20, "Merit, basic" }, - { 0x21, "Merit, companion" }, -); +{ 0x20, "Merit, basic" }, +{ 0x21, "Merit, companion" }, + ); // KSX6924LookupTMoneyTCode MAKE_ENUM_CONST(TMoneyTCode, uint8_t, - { 0x00, "None" }, - { 0x01, "SK Telecom" }, - { 0x02, "Korea Telecom" }, - { 0x03, "LG Uplus" }, -); +{ 0x00, "None" }, +{ 0x01, "SK Telecom" }, +{ 0x02, "Korea Telecom" }, +{ 0x03, "LG Uplus" }, + ); // KSX6924LookupTMoneyCCode MAKE_ENUM_CONST(TMoneyCCode, uint8_t, - { 0x00, "None" }, - { 0x01, "KB Kookmin Bank" }, - { 0x02, "Nonghyup Bank" }, - { 0x03, "Lotte Card" }, - { 0x04, "BC Card" }, - { 0x05, "Samsung Card" }, - { 0x06, "Shinhan Bank" }, - { 0x07, "Citibank Korea" }, - { 0x08, "Korea Exchange Bank" }, - { 0x09, "Woori" }, - { 0x0a, "Hana SK Card" }, - { 0x0b, "Hyundai Capital Services" }, -); +{ 0x00, "None" }, +{ 0x01, "KB Kookmin Bank" }, +{ 0x02, "Nonghyup Bank" }, +{ 0x03, "Lotte Card" }, +{ 0x04, "BC Card" }, +{ 0x05, "Samsung Card" }, +{ 0x06, "Shinhan Bank" }, +{ 0x07, "Citibank Korea" }, +{ 0x08, "Korea Exchange Bank" }, +{ 0x09, "Woori" }, +{ 0x0a, "Hana SK Card" }, +{ 0x0b, "Hyundai Capital Services" }, + ); static const char *KSX6924_UNKNOWN = "Unknown"; @@ -226,7 +226,7 @@ static int64_t bcdToLong(const uint8_t *buf, size_t len) { /** * Converts a date from on-card format to ksx6924_date format. */ -static bool convert_internal_date( const _ksx6924_internal_date_t i, struct ksx6924_date *ret) { +static bool convert_internal_date(const _ksx6924_internal_date_t i, struct ksx6924_date *ret) { int64_t year = bcdToLong(i.year, 2); int16_t month = bcdToInteger(i.month[0]); @@ -276,7 +276,7 @@ bool KSX6924ParsePurseInfo(const uint8_t *purseInfo, size_t purseLen, struct ksx 0, // min_str_len 0, // spaces_between false // uppercase - ); + ); int64_t idtr = bcdToLong(internalPurseInfo->idtr, 5); if (idtr < 0) { @@ -294,8 +294,8 @@ bool KSX6924ParsePurseInfo(const uint8_t *purseInfo, size_t purseLen, struct ksx convert_internal_date(internalPurseInfo->issueDate, &(ret->issueDate)); convert_internal_date(internalPurseInfo->expiryDate, &(ret->expiryDate)); - ret->balMax = MemBeToUint4byte((uint8_t*)internalPurseInfo->balMax); - ret->mmax = MemBeToUint4byte((uint8_t*)internalPurseInfo->mmax); + ret->balMax = MemBeToUint4byte((uint8_t *)internalPurseInfo->balMax); + ret->mmax = MemBeToUint4byte((uint8_t *)internalPurseInfo->mmax); memcpy(&ret->rfu, &internalPurseInfo->rfu, 8); @@ -367,7 +367,7 @@ int KSX6924Select(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t ResultLen, sw, NULL - ); + ); } /** @@ -390,7 +390,7 @@ bool KSX6924TrySelect(void) { "Not a KS X 6924 card! APDU response: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff) - ); + ); } else { PrintAndLogEx(FAILED, "APDU exchange error. Card returns 0x0000."); } @@ -430,8 +430,8 @@ bool KSX6924GetBalance(uint32_t *result) { return false; } - *result = MemBeToUint4byte((uint8_t*)arr); - return true; + *result = MemBeToUint4byte((uint8_t *)arr); + return true; } @@ -448,7 +448,7 @@ bool KSX6924InitializeCard(uint8_t mpda1, uint8_t mpda2, uint8_t mpda3, uint8_t uint16_t sw = 0; size_t rlen = 0; - // ALGep + VKep + BALep + IDcenter + IDep + NTep + Sign1 + sw + // ALGep + VKep + BALep + IDcenter + IDep + NTep + Sign1 + sw uint8_t arr[1 + 1 + 4 + 1 + 8 + 4 + 4 + 2]; memset(arr, 0, sizeof(arr)); diff --git a/client/src/ksx6924/ksx6924core.h b/client/src/ksx6924/ksx6924core.h index 6e9bccc74..10ffbd217 100644 --- a/client/src/ksx6924/ksx6924core.h +++ b/client/src/ksx6924/ksx6924core.h @@ -90,8 +90,7 @@ bool KSX6924InitializeCard(uint8_t mpda1, uint8_t mpda2, uint8_t mpda3, uint8_t // Proprietary get record command. Function unknown. // result must be 10 bytes long. -bool KSX6924ProprietaryGetRecord( - uint8_t id, uint8_t *result, size_t resultLen); +bool KSX6924ProprietaryGetRecord(uint8_t id, uint8_t *result, size_t result_len); #endif /* __KSX6924CORE_H__ */ diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index d7c4b1600..78bb6ebee 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -267,10 +267,10 @@ static bool DesfireISOChannelValidCmd(uint8_t cmd) { } static void DesfireSecureChannelEncodeD40(DesfireContext_t *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { - uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1); + + uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, sizeof(uint8_t)); if (data == NULL) return; - size_t rlen = 0; memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -279,6 +279,8 @@ static void DesfireSecureChannelEncodeD40(DesfireContext_t *ctx, uint8_t cmd, ui if (srcdatalen < hdrlen) hdrlen = srcdatalen; + size_t rlen; + if (ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && srcdatalen <= hdrlen)) { if (srcdatalen == 0) { free(data); @@ -330,14 +332,15 @@ static void DesfireSecureChannelEncodeD40(DesfireContext_t *ctx, uint8_t cmd, ui *dstdatalen = rlen; ctx->commMode = DCMEncrypted; } + free(data); } static void DesfireSecureChannelEncodeEV1(DesfireContext_t *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { - uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1); + + uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, sizeof(uint8_t)); if (data == NULL) return; - size_t rlen = 0; memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -346,6 +349,8 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext_t *ctx, uint8_t cmd, ui if (srcdatalen < hdrlen) hdrlen = srcdatalen; + size_t rlen; + // we calc MAC anyway // if encypted channel and no data - we only calc MAC if (ctx->commMode == DCMPlain || ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && srcdatalen <= hdrlen)) { @@ -360,6 +365,7 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext_t *ctx, uint8_t cmd, ui memcpy(&dstdata[srcdatalen], cmac, DesfireGetMACLength(ctx)); *dstdatalen = srcdatalen + DesfireGetMACLength(ctx); } + } else if (ctx->commMode == DCMEncrypted || ctx->commMode == DCMEncryptedWithPadding) { uint8_t paddinglen = (ctx->commMode == DCMEncryptedWithPadding) ? 1 : 0; rlen = padded_data_length(srcdatalen + 4 + paddinglen - hdrlen, desfire_get_key_block_length(ctx->keyType)); @@ -395,10 +401,10 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext_t *ctx, uint8_t cmd, ui } static void DesfireSecureChannelEncodeEV2(DesfireContext_t *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { - uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1); + + uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, sizeof(uint8_t)); if (data == NULL) return; - size_t rlen = 0; memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -416,6 +422,7 @@ static void DesfireSecureChannelEncodeEV2(DesfireContext_t *ctx, uint8_t cmd, ui } else if (ctx->commMode == DCMEncrypted || ctx->commMode == DCMEncryptedWithPadding || ctx->commMode == DCMEncryptedPlain) { memcpy(dstdata, srcdata, hdrlen); + size_t rlen = 0; if (srcdatalen > hdrlen) { rlen = padded_data_length(srcdatalen + 1 - hdrlen, desfire_get_key_block_length(ctx->keyType)); memcpy(data, &srcdata[hdrlen], srcdatalen - hdrlen); @@ -437,10 +444,10 @@ static void DesfireSecureChannelEncodeEV2(DesfireContext_t *ctx, uint8_t cmd, ui } static void DesfireSecureChannelEncodeLRP(DesfireContext_t *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { - uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1); + + uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, sizeof(uint8_t)); if (data == NULL) return; - size_t rlen = 0; memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -458,6 +465,7 @@ static void DesfireSecureChannelEncodeLRP(DesfireContext_t *ctx, uint8_t cmd, ui } else if (ctx->commMode == DCMEncrypted || ctx->commMode == DCMEncryptedWithPadding || ctx->commMode == DCMEncryptedPlain) { memcpy(dstdata, srcdata, hdrlen); + size_t rlen = 0; if (srcdatalen > hdrlen) { rlen = padded_data_length(srcdatalen + 1 - hdrlen, desfire_get_key_block_length(ctx->keyType)); memcpy(data, &srcdata[hdrlen], srcdatalen - hdrlen); @@ -502,10 +510,10 @@ void DesfireSecureChannelEncode(DesfireContext_t *ctx, uint8_t cmd, uint8_t *src } static void DesfireSecureChannelDecodeD40(DesfireContext_t *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { - uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1); + + uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, sizeof(uint8_t)); if (data == NULL) return; - size_t rlen = 0; memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -515,7 +523,7 @@ static void DesfireSecureChannelDecodeD40(DesfireContext_t *ctx, uint8_t *srcdat size_t maclen = DesfireGetMACLength(ctx); if (srcdatalen > maclen && DesfireEV1D40ReceiveMAC(ctx, ctx->lastCommand)) { uint8_t mac[16] = {0}; - rlen = padded_data_length(srcdatalen - maclen, desfire_get_key_block_length(ctx->keyType)); + size_t rlen = padded_data_length(srcdatalen - maclen, desfire_get_key_block_length(ctx->keyType)); memcpy(data, srcdata, srcdatalen - maclen); DesfireCryptoEncDecEx(ctx, DCOSessionKeyMac, data, rlen, NULL, true, true, mac); @@ -562,7 +570,8 @@ static void DesfireSecureChannelDecodeD40(DesfireContext_t *ctx, uint8_t *srcdat } static void DesfireSecureChannelDecodeEV1(DesfireContext_t *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { - uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1); + + uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, sizeof(uint8_t)); if (data == NULL) return; @@ -736,13 +745,14 @@ static void DesfireSecureChannelDecodeLRP(DesfireContext_t *ctx, uint8_t *srcdat static void DesfireISODecode(DesfireContext_t *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; - uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1); - if (data == NULL) - return; if (srcdatalen < DesfireGetMACLength(ctx)) return; + uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, 1); + if (data == NULL) + return; + uint8_t maclen = DesfireGetMACLength(ctx); if (DesfireIsAuthenticated(ctx)) { memcpy(data, srcdata, srcdatalen - maclen); diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index 4d36098f3..4b5e4e5a1 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -1069,18 +1069,21 @@ int mfGen3Freeze(void) { } } -int mfG3GetBlock(uint8_t blockno, uint8_t *data) { +int mfG4GetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data) { struct p { uint8_t blockno; + uint8_t pwd[4]; } PACKED payload; payload.blockno = blockno; + memcpy(payload.pwd, pwd, sizeof(payload.pwd)); clearCommandBuffer(); - SendCommandNG(CMD_HF_MIFARE_G3_RDBL, (uint8_t *)&payload, sizeof(payload)); + SendCommandNG(CMD_HF_MIFARE_G4_RDBL, (uint8_t *)&payload, sizeof(payload)); PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_HF_MIFARE_G3_RDBL, &resp, 1500)) { - if (resp.status != PM3_SUCCESS) + if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_RDBL, &resp, 1500)) { + if (resp.status != PM3_SUCCESS) { return PM3_EUNDEF; + } memcpy(data, resp.data.asBytes, 16); } else { PrintAndLogEx(WARNING, "command execute timeout"); diff --git a/client/src/mifare/mifarehost.h b/client/src/mifare/mifarehost.h index 8f5f215fd..56cc5d841 100644 --- a/client/src/mifare/mifarehost.h +++ b/client/src/mifare/mifarehost.h @@ -85,7 +85,7 @@ int mfGen3UID(uint8_t *uid, uint8_t uidlen, uint8_t *oldUid); int mfGen3Block(uint8_t *block, int blockLen, uint8_t *newBlock); int mfGen3Freeze(void); -int mfG3GetBlock(uint8_t blockno, uint8_t *data); +int mfG4GetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data); int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len); diff --git a/client/src/proxmark3.c b/client/src/proxmark3.c index 99403eab2..286463845 100644 --- a/client/src/proxmark3.c +++ b/client/src/proxmark3.c @@ -38,7 +38,7 @@ #ifndef LIBPM3 #define BANNERMSG1 "" -#define BANNERMSG2 " [ :snowflake: Iceman :snowflake: ]" +#define BANNERMSG2 " [ Iceman :snowflake: ]" #define BANNERMSG3 "" typedef enum LogoMode { UTF8, ANSI, ASCII } LogoMode; diff --git a/client/src/ui.c b/client/src/ui.c index 8ee9c783e..250b1cb0e 100644 --- a/client/src/ui.c +++ b/client/src/ui.c @@ -47,7 +47,7 @@ double g_PlotGridX = 0, g_PlotGridY = 0, g_PlotGridXdefault = 64, g_PlotGridYdef uint32_t g_CursorCPos = 0, g_CursorDPos = 0, g_GraphStop = 0; uint32_t g_GraphStart = 0; // Starting point/offset for the left side of the graph double g_GraphPixelsPerPoint = 1.f; // How many visual pixels are between each sample point (x axis) -static bool flushAfterWrite = 0; +static bool flushAfterWrite = false; double g_GridOffset = 0; bool g_GridLocked = false; @@ -411,6 +411,10 @@ void SetFlushAfterWrite(bool value) { flushAfterWrite = value; } +bool GetFlushAfterWrite(void) { + return flushAfterWrite; +} + void memcpy_filter_rlmarkers(void *dest, const void *src, size_t n) { uint8_t *rdest = (uint8_t *)dest; uint8_t *rsrc = (uint8_t *)src; diff --git a/client/src/ui.h b/client/src/ui.h index 36f6fd22e..115234ee9 100644 --- a/client/src/ui.h +++ b/client/src/ui.h @@ -63,6 +63,7 @@ extern session_arg_t g_session; void PrintAndLogOptions(const char *str[][2], size_t size, size_t space); void PrintAndLogEx(logLevel_t level, const char *fmt, ...); void SetFlushAfterWrite(bool value); +bool GetFlushAfterWrite(void); void memcpy_filter_ansi(void *dest, const void *src, size_t n, bool filter); void memcpy_filter_rlmarkers(void *dest, const void *src, size_t n); void memcpy_filter_emoji(void *dest, const void *src, size_t n, emojiMode_t mode); diff --git a/client/src/wiegand_formats.c b/client/src/wiegand_formats.c index 75f9ea987..7f507d982 100644 --- a/client/src/wiegand_formats.c +++ b/client/src/wiegand_formats.c @@ -1414,7 +1414,7 @@ int HIDFindCardFormat(const char *format) { bool HIDPack(int format_idx, wiegand_card_t *card, wiegand_message_t *packed, bool preamble) { memset(packed, 0, sizeof(wiegand_message_t)); - if (format_idx < 0 || format_idx >= ARRAYLEN(FormatTable)) + if (format_idx < 0 || format_idx >= ARRAYLEN(FormatTable) - 1) return false; return FormatTable[format_idx].Pack(card, packed, preamble); diff --git a/common/cardhelper.c b/common/cardhelper.c index db62c49f6..e337010e6 100644 --- a/common/cardhelper.c +++ b/common/cardhelper.c @@ -53,7 +53,7 @@ static bool executeCrypto(uint8_t ins, uint8_t *src, uint8_t *dest) { int resp_len = 0; uint8_t dec[11] = {0}; - ExchangeAPDUSC(false, cmd, sizeof(cmd), false, true, dec, sizeof(dec), &resp_len); + ExchangeAPDUSC(false, cmd, sizeof(cmd), true, true, dec, sizeof(dec), &resp_len); if (resp_len == 10) { memcpy(dest, dec, 8); return true; diff --git a/common/crc.c b/common/crc.c index e7f169691..cb077182f 100644 --- a/common/crc.c +++ b/common/crc.c @@ -147,3 +147,25 @@ uint32_t CRC8Hitag1(uint8_t *buff, size_t size) { } return crc_finish(&crc); } + +uint32_t CRC8Hitag1Bits(uint8_t *buff, size_t bitsize) { + crc_t crc; + uint8_t data = 0; + uint8_t n = 0; + crc_init_ref(&crc, 8, 0x1d, 0xff, 0, false, false); + uint8_t i; + for (i = 0; i < bitsize; i++) { + data <<= 1; + data += (buff[i / 8] >> (7 - (i % 8))) & 1; + n += 1; + if (n == 8) { + crc_update2(&crc, data, n); + n = 0; + data = 0; + } + } + if (n > 0) { + crc_update2(&crc, data, n); + } + return crc_finish(&crc); +} diff --git a/common/crc.h b/common/crc.h index 1b1faca57..33e289ee8 100644 --- a/common/crc.h +++ b/common/crc.h @@ -78,5 +78,6 @@ uint32_t CRC8Cardx(uint8_t *buff, size_t size); // Calculate CRC-8/Hitag1, ZX8211 checksum uint32_t CRC8Hitag1(uint8_t *buff, size_t size); +uint32_t CRC8Hitag1Bits(uint8_t *buff, size_t bitsize); #endif /* __CRC_H */ diff --git a/common/lfdemod.c b/common/lfdemod.c index 16dc8a56b..976195747 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -424,8 +424,8 @@ static size_t findModStart(uint8_t *src, size_t size, uint8_t expWaveSize) { } static int getClosestClock(int testclk) { - uint16_t clocks[] = {8, 16, 32, 40, 50, 64, 100, 128, 256, 384}; - uint8_t limit[] = {1, 2, 4, 4, 5, 8, 8, 8, 8, 8}; + const uint16_t clocks[] = {8, 16, 32, 40, 50, 64, 100, 128, 256, 384}; + const uint8_t limit[] = {1, 2, 4, 4, 5, 8, 8, 8, 8, 8}; for (uint8_t i = 0; i < 10; i++) { if (testclk >= clocks[i] - limit[i] && testclk <= clocks[i] + limit[i]) @@ -434,12 +434,12 @@ static int getClosestClock(int testclk) { return 0; } -void getNextLow(uint8_t *samples, size_t size, int low, size_t *i) { +void getNextLow(const uint8_t *samples, size_t size, int low, size_t *i) { while ((samples[*i] > low) && (*i < size)) *i += 1; } -void getNextHigh(uint8_t *samples, size_t size, int high, size_t *i) { +void getNextHigh(const uint8_t *samples, size_t size, int high, size_t *i) { while ((samples[*i] < high) && (*i < size)) *i += 1; } diff --git a/common/lfdemod.h b/common/lfdemod.h index e8d516604..4b840efc0 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -35,8 +35,8 @@ signal_t *getSignalProperties(void); void computeSignalProperties(uint8_t *samples, uint32_t size); void removeSignalOffset(uint8_t *samples, uint32_t size); -void getNextLow(uint8_t *samples, size_t size, int low, size_t *i); -void getNextHigh(uint8_t *samples, size_t size, int high, size_t *i); +void getNextLow(const uint8_t *samples, size_t size, int low, size_t *i); +void getNextHigh(const uint8_t *samples, size_t size, int high, size_t *i); bool loadWaveCounters(uint8_t *samples, size_t size, int lowToLowWaveLen[], int highToLowWaveLen[], int *waveCnt, int *skip, int *minClk, int *high, int *low); size_t pskFindFirstPhaseShift(uint8_t *samples, size_t size, uint8_t *curPhase, size_t waveStart, uint16_t fc, uint16_t *fullWaveLen); diff --git a/common/mbedtls/ssl_tls.c b/common/mbedtls/ssl_tls.c index f5e56f9d7..6e68cf104 100644 --- a/common/mbedtls/ssl_tls.c +++ b/common/mbedtls/ssl_tls.c @@ -3086,7 +3086,7 @@ static void ssl_calc_finished_tls_sha384( #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wstringop-overflow" #endif - mbedtls_sha512_finish_ret( &sha512, padbuf ); + mbedtls_sha512_finish_ret(&sha512, padbuf); #if defined(__GNUC__) && __GNUC__ >= 11 #pragma GCC diagnostic pop #endif diff --git a/doc/T5577_Guide.md b/doc/T5577_Guide.md index 4d973cf00..26ca77434 100644 --- a/doc/T5577_Guide.md +++ b/doc/T5577_Guide.md @@ -1,10 +1,13 @@ # T5577 Introduction Guide + ### Based on RRG/Iceman Proxmark3 repo ### Ver.1 8 Sep 2019 ### Ver.2 7 March 2021 +# Table of Contents + | Contents | | ----------------------------------------------------------------------------------- | | [Part 1](#part-1) | @@ -21,8 +24,10 @@ | [The configuration Block – Block 3 Page 1](#the-configuration-block-block-3-page-1) | # Part 1 +^[Top](#top) ## Introduction +^[Top](#top) The T5577 is a generic LF (Low Frequency) RFID card that is used in the 125 Khz frequency space. It is a good card to use to learn about RFID and @@ -49,6 +54,7 @@ try these as we go. To do so, have a blank T5577 card that you can use for this purpose. ## T5577 Overview +^[Top](#top) The T5577 is a chip that can hold data and a configuration (Section 4.12). @@ -63,6 +69,7 @@ the chip how to behave. ## What data is on my T5577 +^[Top](#top) Let’s have a look and see what a card might look like in the proxmark3 software. Since we can change the configuration of how the T5577 will @@ -121,6 +128,7 @@ I will cover the meaning of this data as we go, but for now, lets keep it simple. ## Read and Write Blocks of Data +^[Top](#top) The basic function of using the proxmark3 with rfid cards is to read and write data. This reading and writing must be done in the correct way @@ -224,6 +232,7 @@ can see the card) ``` ### Exercise 1 +^[Top](#top) Using the read and write commands you have learnt see if you can make the lf t55 dump command show the following data for blocks 1-7 (Page 0). @@ -261,6 +270,7 @@ If you forget this data/password, you won't be able to read or write to the card. ## How do I use a password +^[Top](#top) This can be a little tricky for beginners. ***If you forget your password you will lose access to your card***. @@ -521,6 +531,7 @@ required, please do not proceed. Yes we can! We can see Block 0 is the correct config 00088040 # Part 2 – Configuration Blocks +^[Top](#top) One of the things a lot of people have trouble with or miss, is that the T5577 has two different and separate communications protocols, each with @@ -539,6 +550,7 @@ from Block 3 Page 1. If the command is not encoded correctly it will ignore the command and revert back to default read mode. ## The configuration Block – Block 0 Page 0 +^[Top](#top) For this configuration the settings chosen will be for the purpose of the card when used in production. E.G. If you want the card to act like @@ -685,6 +697,7 @@ password set (if not, review and get you card back to this state). (Max Block = 2). On the T5577 these will be Blocks 1 and 2. ## Exercise 2 +^[Top](#top) Using the skills form part 1, see if you can view the data in blocks 1 and 2. @@ -699,3 +712,6 @@ it, we can follow the password section and update the config from ***Important : Don’t forget to set a valid password in block 7 and remember it.*** ## The configuration Block – Block 3 Page 1 +^[Top](#top) + +_to be written_ \ No newline at end of file diff --git a/doc/cliparser.md b/doc/cliparser.md index a837a5afc..118a82c86 100644 --- a/doc/cliparser.md +++ b/doc/cliparser.md @@ -1,4 +1,34 @@ -# Cliparser +# Note on Cliparser + + + +# Table of Contents +- [Note on Cliparser](#note-on-cliparser) +- [Table of Contents](#table-of-contents) + - [cliparser setup and use](#cliparser-setup-and-use) + - [design comments](#design-comments) + - [common options](#common-options) + - [How to implement in source code](#how-to-implement-in-source-code) + - [setup the parser data structure](#setup-the-parser-data-structure) + - [define the context](#define-the-context) + - [define the options](#define-the-options) + - [Notes:](#notes) + - [bool option. true if supplied](#bool-option--true-if-supplied) + - [integer that is optional](#integer-that-is-optional) + - [integer that is required](#integer-that-is-required) + - [double that is optional](#double-that-is-optional) + - [double that is required](#double-that-is-required) + - [String option that is optional and only one instance can be provided](#string-option-that-is-optional-and-only-one-instance-can-be-provided) + - [String option that is required and only one instance can be provided](#string-option-that-is-required-and-only-one-instance-can-be-provided) + - [String option that is optional and can have up to 250 instances provided](#string-option-that-is-optional-and-can-have-up-to-250-instances-provided) + - [String option that is required/at least one instance and can have up to 250 instances](#string-option-that-is-requiredat-least-one-instance-and-can-have-up-to-250-instances) + - [unsigned integer optional](#unsigned-integer-optional) + - [unsigned integer required](#unsigned-integer-required) + - [show the menu](#show-the-menu) + - [clean up](#clean-up) + - [retrieving options](#retrieving-options) + + The old style with mixed custom commandline parsing of user parameters or options was messy and confusing. You can find all kinds in the Proxmark3 client. Samples @@ -36,11 +66,13 @@ This is the _new_ and _preferred_ way to implement _helptext_ and _cli parsing_ ## cliparser setup and use +^[Top](#top) The parser will format and color and layout as needed. It will also add the `-h --help` option automatic. ## design comments +^[Top](#top) * where possible all options should be lowercase. * extended options preceded with -- should be short @@ -52,6 +84,8 @@ It will also add the `-h --help` option automatic. ## common options +^[Top](#top) + -h --help : help --cn : card number --fn : facility number @@ -69,8 +103,11 @@ It will also add the `-h --help` option automatic. ## How to implement in source code +^[Top](#top) ### setup the parser data structure +^[Top](#top) + Header file to include #include "cliparser.h" @@ -81,6 +118,8 @@ In the command function, setup the context ### define the context +^[Top](#top) + `CLIParserInit (\, \, \);` use -> to separate example and example comment and \\n to separate examples. @@ -94,12 +133,13 @@ e.g. lf indala clone -r a0000000a0002021 -> this uses ..... "lf indala clone -l -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5"); ### define the options +^[Top](#top) void *argtable[] = { arg_param_begin, arg_lit0("l", "long", "optional - long UID 224 bits"), arg_int0("c", "heden", "", "Cardnumber for Heden 2L format"), - arg_strx0("r", "raw", "", "raw bytes"), + arg_str0("r", "raw", "", "raw bytes"), arg_lit0("q", "Q5", "optional - specify writing to Q5/T5555 tag"), arg_int0(NULL, "fc", "", "Facility Code (26 bit format)"), arg_int0(NULL, "cn", "", "Cardnumber (26 bit format)"), @@ -110,6 +150,8 @@ _All options has a parameter index, since `-h --help` is added automatic, it wi Hence all options you add will start at index 1 and upwards. It added in the define "arg_param_begin_ ### Notes: +^[Top](#top) + #### bool option. true if supplied `bool : arg_lit0 ("", "", <"description">)` @@ -150,17 +192,21 @@ Unsigned values, like u32 and u64 can be accomplished with ### show the menu +^[Top](#top) + `CLIExecWithReturn(\, \, \, \);` CLIExecWithReturn(ctx, Cmd, argtable, false); ### clean up +^[Top](#top) + Once you have extracted the options, cleanup the context. CLIParserFree(ctx); ### retrieving options - +^[Top](#top) The parser will format and color and layout as needed. It will also add the `-h --help` option automatic. diff --git a/doc/clocks.md b/doc/clocks.md index c1d046f06..161d680fb 100644 --- a/doc/clocks.md +++ b/doc/clocks.md @@ -1,22 +1,46 @@ + + +# Notes on device side clocks +The device side firmware uses a range of different clocks. Here is an attempt to document the clocks in use and for what they are used. + + +# Table of Contents +- [Notes on device side clocks](#notes-on-device-side-clocks) +- [Table of Contents](#table-of-contents) + - [Slow clock](#slow-clock) + - [Main Oscillator / MAINCK](#main-oscillator--mainck) + - [PLL clock](#pll-clock) + - [Master Clock MCK, Processor Clock PCK, USB clock UDPCK](#master-clock-mck-processor-clock-pck-usb-clock-udpck) + - [Peripheral clocks](#peripheral-clocks) + - [1 kHz RTC: TickCount functions](#1-khz-rtc-tickcount-functions) + - [Occasional PWM timer](#occasional-pwm-timer) + - [Occasional TC0+TC1 / CountUS functions](#occasional-tc0tc1--countus-functions) + - [Occasional TC0+TC1+TC2 SSP_CLK from FPGA / CountSspClk functions](#occasional-tc0tc1tc2-ssp_clk-from-fpga--countsspclk-functions) + - [Occasional TC0+TC1 / Ticks functions](#occasional-tc0tc1--ticks-functions) + ## Slow clock +^[Top](#top) ~32kHz internal RC clock Can be between 22 and 42 kHz ## Main Oscillator / MAINCK +^[Top](#top) cf `PMC_MOR` register 16 MHz, based on external Xtal ## PLL clock +^[Top](#top) cf `PMC_PLLR` register 96 MHz (MAINCK * 12 / 2) ## Master Clock MCK, Processor Clock PCK, USB clock UDPCK +^[Top](#top) cf `common_arm/clocks.c` @@ -33,6 +57,7 @@ USB need to be clocked at 48 MHz from the PLL, so PLL / 2 (cf `CKGR_PLLR`). ## Peripheral clocks +^[Top](#top) cf `bootrom.c`: @@ -43,6 +68,7 @@ cf `appmain.c` Activate PCK0 pin as clock output, based on PLL / 4 = 24 MHz, for the FPGA. ## 1 kHz RTC: TickCount functions +^[Top](#top) cf `armsrc/ticks.c` @@ -73,6 +99,7 @@ Current usages: * USB connection speed measure ## Occasional PWM timer +^[Top](#top) * `void SpinDelayUs(int us)` * `void SpinDelay(int ms)` based on SpinDelayUs @@ -84,6 +111,7 @@ Busy wait based on 46.875 kHz PWM Channel 0 * *Precision* variant: 0.7 us precision and maximum 43 ms ## Occasional TC0+TC1 / CountUS functions +^[Top](#top) cf `armsrc/ticks.c` @@ -100,6 +128,7 @@ Maximal value: 0x7fffffff = 2147 s Can't be used at the same time as CountSspClk or Ticks functions. ## Occasional TC0+TC1+TC2 SSP_CLK from FPGA / CountSspClk functions +^[Top](#top) cf `armsrc/ticks.c` @@ -121,6 +150,7 @@ Usage: Can't be used at the same time as CountUS or Ticks functions. ## Occasional TC0+TC1 / Ticks functions +^[Top](#top) cf `armsrc/ticks.c` diff --git a/doc/cloner_notes.md b/doc/cloner_notes.md index 78f7b360e..83de05039 100644 --- a/doc/cloner_notes.md +++ b/doc/cloner_notes.md @@ -1,8 +1,13 @@ # Notes on Cloner guns + This document is based mostly on information posted on http://www.proxmark.org/forum/viewtopic.php?pid=39903#p39903 + +# Table of Contents + - [Notes on Cloner guns](#notes-on-cloner-guns) +- [Table of Contents](#table-of-contents) - [Blue and black cloners](#blue-and-black-cloners) - [White cloner (pre 2015)](#white-cloner-pre-2015) - [White cloner (after 2016)](#white-cloner-after-2016) @@ -12,6 +17,7 @@ This document is based mostly on information posted on http://www.proxmark.org/f # Blue and black cloners +^[Top](#top) 3 variants: 1. EM cloner @@ -26,6 +32,7 @@ Standard password is normally: 51243648 **Be sure to purchase the EM/HID version** # White cloner (pre 2015) +^[Top](#top) Multifrequency Buttons light up BLUE @@ -38,6 +45,8 @@ Standard password 13,56mHz: individual per white cloner # White cloner (after 2016) +^[Top](#top) + Multifrequency Buttons light up WHITE Data scrambled (variable per individual cloner, possibly due to prevent legal issues) @@ -49,6 +58,8 @@ Standard password 13,56mHz: individual per white cloner # White cloner (after 2016 D Quality) +^[Top](#top) + Multifrequency (it says so but it doesn't) Only works for EM/HID card (125kHz) High frequency not working @@ -59,12 +70,16 @@ Standard password is normally (for T55xx): AA55BBBB # Restore page1 data +^[Top](#top) + ``` lf t55xx write -b 1 -d E0150A48 --pg1 If t55xx write -b 2 -d 2D782308 --pg1 ``` # Sniffing the comms +^[Top](#top) + The T55x7 protocol uses a pwm based protocol for writing to tags. In order to make decoding easier try the new command as seen below instead. It will try to extract the data written. ``` diff --git a/doc/colors_notes.md b/doc/colors_notes.md index 38a3e9ede..9d8704c87 100644 --- a/doc/colors_notes.md +++ b/doc/colors_notes.md @@ -1,10 +1,16 @@ +# Notes on Color usage -# Notes on Color usage. -## Table of Contents - * [style/color](#style_color) - * [Proxspace](#proxspace) - * [help texts](#help-texts) + +# Table of Contents +- [Notes on Color usage](#notes-on-color-usage) +- [Table of Contents](#table-of-contents) + - [style/color](#stylecolor) + - [Definition](#definition) + - [Styled header](#styled-header) + - [non styled header](#non-styled-header) + - [Proxspace](#proxspace) + - [Help texts](#help-texts) The client should autodetect color support when starting. @@ -16,10 +22,12 @@ We have gradually been introducing this color scheme into the client since we go ## style/color ^[Top](#top) + The following definition has be crystallized out from these experiments. Its not set in stone yet so take this document as a guideline for how to create unified system scheme. ### Definition ^[Top](#top) + - blue - system related headers, banner - white - normal - cyan - headers @@ -31,6 +39,7 @@ The following definition has be crystallized out from these experiments. Its no ### Styled header ^[Top](#top) + ``` PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------"); @@ -41,14 +50,17 @@ For the command help texts using _YELLOW_ for the example makes it very easy to ### non styled header ^[Top](#top) + Most commands doesn't use a header yet. We added it to make it standout (ie: yellow, green) of the informative tidbits in the output of a command. ## Proxspace ^[Top](#top) + Proxspace has support for colors. ## Help texts ^[Top](#top) + The help text uses a hard coded template deep inside the cliparser.c file. \ No newline at end of file diff --git a/doc/commands.json b/doc/commands.json index 7ac247c3e..8cd2d65d5 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -76,9 +76,9 @@ "offline": true, "options": [ "-h, --help this help", - "-r, --raw raw bytes (strx)" + "-r, --raw raw bytes" ], - "usage": "analyse foo [-h] [-r ]..." + "usage": "analyse foo [-h] -r " }, "analyse freq": { "command": "analyse freq", @@ -227,7 +227,7 @@ "-h, --help this help", "-d, --data binary string to convert" ], - "usage": "data bin2hex [-h] [-d ]..." + "usage": "data bin2hex [-h] -d " }, "data bitsamples": { "command": "data bitsamples", @@ -744,9 +744,10 @@ "-m, -m, --make make cdoldata from cdol (tag 8c and 8d) and parameters (by default uses default parameters)", "-a, -a, --apdu show apdu reqests and responses", "-t, -t, --tlv tlv decode results of selected applets", - "-w, -w, --wired send data via contact (iso7816) interface. contactless interface set by default." + "-w, -w, --wired send data via contact (iso7816) interface. contactless interface set by default.", + " cdoldata/cdol" ], - "usage": "emv genac [-hkcpmatw] [-d ] []..." + "usage": "emv genac [-hkcpmatw] [-d ] []..." }, "emv gpo": { "command": "emv gpo", @@ -764,9 +765,10 @@ "-m, -m, --make make pdoldata from pdol (tag 9f38) and parameters (by default uses default parameters)", "-a, -a, --apdu show apdu reqests and responses", "-t, -t, --tlv tlv decode results of selected applets", - "-w, -w, --wired send data via contact (iso7816) interface. contactless interface set by default." + "-w, -w, --wired send data via contact (iso7816) interface. contactless interface set by default.", + " pdoldata/pdol" ], - "usage": "emv gpo [-hkpmatw] []..." + "usage": "emv gpo [-hkpmatw] []..." }, "emv help": { "command": "emv help", @@ -808,9 +810,10 @@ "-m, -m, --make make ddoldata from ddol (tag 9f49) and parameters (by default uses default parameters)", "-a, -a, --apdu show apdu reqests and responses", "-t, -t, --tlv tlv decode results of selected applets", - "-w, -w, --wired send data via contact (iso7816) interface. contactless interface set by default." + "-w, -w, --wired send data via contact (iso7816) interface. contactless interface set by default.", + " ddoldata/ddol" ], - "usage": "emv intauth [-hkpmatw] []..." + "usage": "emv intauth [-hkpmatw] []..." }, "emv list": { "command": "emv list", @@ -831,7 +834,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "emv list [-h1fcrux] [--dict ]..." + "usage": "emv list [-h1fcrux] [--dict ]" }, "emv pse": { "command": "emv pse", @@ -866,9 +869,10 @@ "-k, -k, --keep keep field on for next command", "-a, -a, --apdu show apdu reqests and responses", "-t, -t, --tlv tlv decode results of selected applets", - "-w, -w, --wired send data via contact (iso7816) interface. contactless interface set by default." + "-w, -w, --wired send data via contact (iso7816) interface. contactless interface set by default.", + " []..." + "usage": "emv readrec [-hkatw] []..." }, "emv roca": { "command": "emv roca", @@ -907,9 +911,9 @@ "-g, -g, --acgpo visa. generate ac from gpo.", "-m, -m, --merge merge output file with card's data. (warning: the file may be corrupted!)", "-w, -w, --wired send data via contact (iso7816) interface. contactless interface set by default.", - "output.json json output file name" + " json output filename" ], - "usage": "emv scan [-hatejvcxgmw] by default: output.json" + "usage": "emv scan [-hatejvcxgmw] by default: " }, "emv search": { "command": "emv search", @@ -941,11 +945,12 @@ "-h, --help this help", "-s, -s, --select activate field and select card", "-k, -k, --keep keep field for next command", - "-a, -a, --apdu show apdu reqests and responses", + "-a, -a, --apdu show apdu requests and responses", "-t, -t, --tlv tlv decode results", - "-w, -w, --wired send data via contact (iso7816) interface. contactless interface set by default." + "-w, -w, --wired send data via contact (iso7816) interface. contactless interface set by default.", + " applet aid" ], - "usage": "emv select [-hskatw] []..." + "usage": "emv select [-hskatw] " }, "emv test": { "command": "emv test", @@ -1055,7 +1060,7 @@ "--p2 start value of p2 (1 hex byte)", "-r, --reset minimum secondes before resetting the tag (to prevent timeout issues). default is 5 minutes", "-e, --error-limit maximum times an status word other than 0x9000 or 0x6d00 is shown. default is 512.", - "-s, --skip-ins do not test an instructions (can be specified multiple times)", + "-s, --skip-ins do not test an instruction (can be specified multiple times)", "-l, --with-le search for apdus with le=0 (case 2s) as well", "-v, --verbose verbose output" ], @@ -1093,7 +1098,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "hf 14a list [-h1fcrux] [--dict ]..." + "usage": "hf 14a list [-h1fcrux] [--dict ]" }, "hf 14a info": { "command": "hf 14a info", @@ -1224,9 +1229,9 @@ "offline": false, "options": [ "-h, --help this help", - "-f, --file (optional) filename, if no uid will be used as filename" + "-f, --file (optional) filename, if no uid will be used as filename" ], - "usage": "hf 14b dump [-h] [-f ]..." + "usage": "hf 14b dump [-h] [-f ]" }, "hf 14b help": { "command": "hf 14b help", @@ -1251,7 +1256,7 @@ "-d, --data if `m` parameter included", "--timeout timeout in ms" ], - "usage": "hf 14b apdu [-hskte] [--decode] [-m ] [-l ] -d [-d ]... [--timeout ]" + "usage": "hf 14b apdu [-hskte] [--decode] [-m ] [-l ] -d [--timeout ]" }, "hf 14b info": { "command": "hf 14b info", @@ -1286,7 +1291,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "hf 14b list [-h1fcrux] [--dict ]..." + "usage": "hf 14b list [-h1fcrux] [--dict ]" }, "hf 14b ndefread": { "command": "hf 14b ndefread", @@ -1323,7 +1328,7 @@ "-v, --verbose verbose", "-d, --data data, bytes to send" ], - "usage": "hf 14b raw [-hkscrv] [--sr] [--cts] [-t ] [-d ]..." + "usage": "hf 14b raw [-hkscrv] [--sr] [--cts] [-t ] [-d ]" }, "hf 14b rdbl": { "command": "hf 14b rdbl", @@ -1363,7 +1368,7 @@ "-h, --help this help", "-u, --uid hex 4byte uid/pupi" ], - "usage": "hf 14b sim [-h] [-u hex]..." + "usage": "hf 14b sim [-h] -u hex" }, "hf 14b sniff": { "command": "hf 14b sniff", @@ -1473,7 +1478,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "hf 15 list [-h1fcrux] [--dict ]..." + "usage": "hf 15 list [-h1fcrux] [--dict ]" }, "hf 15 info": { "command": "hf 15 info", @@ -1510,7 +1515,7 @@ "-r do not read response", "-d, --data raw bytes to send" ], - "usage": "hf 15 raw [-h2ckr] -d [-d ]..." + "usage": "hf 15 raw [-h2ckr] -d " }, "hf 15 rdbl": { "command": "hf 15 rdbl", @@ -1898,7 +1903,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "hf emrtd list [-h1fcrux] [--dict ]..." + "usage": "hf emrtd list [-h1fcrux] [--dict ]" }, "hf epa preplay": { "command": "hf epa preplay", @@ -1974,7 +1979,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "hf felica list [-h1fcrux] [--dict ]..." + "usage": "hf felica list [-h1fcrux] [--dict ]" }, "hf felica info": { "command": "hf felica info", @@ -2031,7 +2036,7 @@ "-s active signal field on with select", " raw bytes to send" ], - "usage": "hf felica raw [-hackrs] [-n ] []..." + "usage": "hf felica raw [-hackrs] [-n ] " }, "hf felica rdbl": { "command": "hf felica rdbl", @@ -2260,7 +2265,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "hf fido list [-h1fcrux] [--dict ]..." + "usage": "hf fido list [-h1fcrux] [--dict ]" }, "hf fido info": { "command": "hf fido info", @@ -2391,7 +2396,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "hf list [-h1fcrux] [--dict ]..." + "usage": "hf list [-h1fcrux] [--dict ]" }, "hf iclass calcnewkey": { "command": "hf iclass calcnewkey", @@ -2610,7 +2615,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "hf iclass list [-h1fcrux] [--dict ]..." + "usage": "hf iclass list [-h1fcrux] [--dict ]" }, "hf iclass loclass": { "command": "hf iclass loclass", @@ -2931,7 +2936,7 @@ "-k, --keep keep field on for next command", "-a, --apdu show apdu reqests and responses" ], - "usage": "hf ksx6924 initialize [-hka] []..." + "usage": "hf ksx6924 initialize [-hka] " }, "hf ksx6924 prec": { "command": "hf ksx6924 prec", @@ -2945,7 +2950,7 @@ "-k, --keep keep field on for next command", "-a, --apdu show apdu reqests and responses" ], - "usage": "hf ksx6924 prec [-hka] []..." + "usage": "hf ksx6924 prec [-hka] " }, "hf ksx6924 select": { "command": "hf ksx6924 select", @@ -2987,7 +2992,7 @@ "offline": false, "options": [ "-h, --help this help", - "-f, --file specify a filename for dump file", + "-f, --file dump filename", "--de deobfuscate dump data (xor with mcc)" ], "usage": "hf legic dump [-h] [-f ] [--de]" @@ -3003,11 +3008,11 @@ "offline": true, "options": [ "-h, --help this help", - "-f, --file specify a filename to restore", + "-f, --file filename to restore", "-t, --type tag type to simulate.", "--obfuscate obfuscate dump data (xor with mcc)" ], - "usage": "hf legic eload [-h] -f [-t ] [--obfuscate]" + "usage": "hf legic eload [-h] -f [-t ] [--obfuscate]" }, "hf legic esave": { "command": "hf legic esave", @@ -3021,7 +3026,7 @@ "offline": true, "options": [ "-h, --help this help", - "-f, --file specify a filename to save", + "-f, --file filename to save", "-t, --type tag type", "--deobfuscate de-obfuscate dump data (xor with mcc)" ], @@ -3046,7 +3051,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "hf legic list [-h1fcrux] [--dict ]..." + "usage": "hf legic list [-h1fcrux] [--dict ]" }, "hf legic info": { "command": "hf legic info", @@ -3100,10 +3105,10 @@ "offline": false, "options": [ "-h, --help this help", - "-f, --file specify a filename to restore", + "-f, --file filename to restore", "--ob obfuscate dump data (xor with mcc)" ], - "usage": "hf legic restore [-h] -f [--ob]" + "usage": "hf legic restore [-h] -f [--ob]" }, "hf legic sim": { "command": "hf legic sim", @@ -3192,7 +3197,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "hf lto list [-h1fcrux] [--dict ]..." + "usage": "hf lto list [-h1fcrux] [--dict ]" }, "hf lto rdbl": { "command": "hf lto rdbl", @@ -3217,9 +3222,9 @@ "offline": false, "options": [ "-h, --help this help", - "-f, --file specify a filename for dumpfile" + "-f, --file specify a filename for dumpfile" ], - "usage": "hf lto restore [-h] -f " + "usage": "hf lto restore [-h] -f " }, "hf lto wrbl": { "command": "hf lto wrbl", @@ -3730,7 +3735,7 @@ }, "hf mf gview": { "command": "hf mf gview", - "description": "view `magic gen3 gtu` card memory", + "description": "view `magic gen4 gtu` card memory", "notes": [ "hf mf gview", "hf mf gview --4k" @@ -3741,9 +3746,10 @@ "--mini mifare classic mini / s20", "--1k mifare classic 1k / s50 (def)", "--2k mifare classic/plus 2k", - "--4k mifare classic 4k / s70" + "--4k mifare classic 4k / s70", + "-p, --pwd password 4bytes" ], - "usage": "hf mf gview [-h] [--mini] [--1k] [--2k] [--4k]" + "usage": "hf mf gview [-h] [--mini] [--1k] [--2k] [--4k] [-p ]" }, "hf mf hardnested": { "command": "hf mf hardnested", @@ -3802,7 +3808,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "hf mf list [-h1fcrux] [--dict ]..." + "usage": "hf mf list [-h1fcrux] [--dict ]" }, "hf mf mad": { "command": "hf mf mad", @@ -3916,7 +3922,7 @@ "description": "read mifare classic block", "notes": [ "hf mf rdbl --blk 0 -k ffffffffffff", - "hf mf rdbl -b 3 -v -> get block 3, decode sector trailer" + "hf mf rdbl --blk 3 -v -> get block 3, decode sector trailer" ], "offline": false, "options": [ @@ -4143,7 +4149,7 @@ "-i, --step increment step when bruteforcing", "-m, --mad only bruteforce the mad range" ], - "usage": "hf mfdes bruteaid [-hm] [-s ]... [-e ]... [-i ]" + "usage": "hf mfdes bruteaid [-hm] [-s ] [-e ] [-i ]" }, "hf mfdes changekey": { "command": "hf mfdes changekey", @@ -4242,7 +4248,7 @@ "-i, --kdfi kdf input (hex 1-31 bytes)", "-a, --apdu show apdu requests and responses" ], - "usage": "hf mfdes chk [-hva] [--aid ]... [-k ] [-d ] [--pattern1b] [--pattern2b] [--startp2b ] [-j ] [-f ] [-i ]" + "usage": "hf mfdes chk [-hva] [--aid ] [-k ] [-d ] [--pattern1b] [--pattern2b] [--startp2b ] [-j ] [-f ] [-i ]" }, "hf mfdes chkeysettings": { "command": "hf mfdes chkeysettings", @@ -4929,7 +4935,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "hf mfdes list [-h1fcrux] [--dict ]..." + "usage": "hf mfdes list [-h1fcrux] [--dict ]" }, "hf mfdes lsapp": { "command": "hf mfdes lsapp", @@ -5300,7 +5306,7 @@ "-v, --verbose show internal data.", "-k, --key key, 16 hex bytes" ], - "usage": "hf mfp initp [-hv] [-k ]..." + "usage": "hf mfp initp [-hv] [-k ]" }, "hf mfp mad": { "command": "hf mfp mad", @@ -5410,7 +5416,7 @@ "--ki key number, 2 hex bytes", "--key key, 16 hex bytes" ], - "usage": "hf mfp wrp [-hv] --ki [--key ]..." + "usage": "hf mfp wrp [-hv] --ki [--key ]" }, "hf mfu cauth": { "command": "hf mfu cauth", @@ -5577,9 +5583,10 @@ "-h, --help this help", "-k, --key key for authentication (ul-c 16 bytes, ev1/ntag 4 bytes)", "-l swap entered key's endianness", - "-b, --block block number to read" + "-b, --block block number to read", + "--force force operation even if address is out of range" ], - "usage": "hf mfu rdbl [-hl] [-k ] -b " + "usage": "hf mfu rdbl [-hl] [-k ] -b [--force]" }, "hf mfu restore": { "command": "hf mfu restore", @@ -5659,9 +5666,10 @@ "-k, --key key for authentication (ul-c 16 bytes, ev1/ntag 4 bytes)", "-l swap entered key's endianness", "-b, --block block number to write", - "-d, --data block data (4 or 16 hex bytes, 16 hex bytes will do a compatibility write)" + "-d, --data block data (4 or 16 hex bytes, 16 hex bytes will do a compatibility write)", + "--force force operation even if address is out of range" ], - "usage": "hf mfu wrbl [-hl] [-k ] -b -d " + "usage": "hf mfu wrbl [-hl] [-k ] -b -d [--force]" }, "hf plot": { "command": "hf plot", @@ -5708,7 +5716,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "hf seos list [-h1fcrux] [--dict ]..." + "usage": "hf seos list [-h1fcrux] [--dict ]" }, "hf sniff": { "command": "hf sniff", @@ -5756,7 +5764,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "hf st25ta list [-h1fcrux] [--dict ]..." + "usage": "hf st25ta list [-h1fcrux] [--dict ]" }, "hf st25ta ndefread": { "command": "hf st25ta ndefread", @@ -5852,7 +5860,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "hf thinfilm list [-h1fcrux] [--dict ]..." + "usage": "hf thinfilm list [-h1fcrux] [--dict ]" }, "hf thinfilm sim": { "command": "hf thinfilm sim", @@ -5887,7 +5895,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "hf topaz list [-h1fcrux] [--dict ]..." + "usage": "hf topaz list [-h1fcrux] [--dict ]" }, "hf topaz info": { "command": "hf topaz info", @@ -5988,9 +5996,9 @@ "-h, --help this help", "-m model number [0 - 7] of your tag", "-s, --save save dithered version in filename-[n].bmp, only for rgb bmp", - "-f, --file filename[.bmp] to upload to tag" + "-f, --file specify filename[.bmp] to upload to tag" ], - "usage": "hf waveshare loadbmp [-hs] -m -f " + "usage": "hf waveshare loadbmp [-hs] -m -f " }, "hints": { "command": "hints", @@ -6410,7 +6418,7 @@ "--q5 optional - specify writing to q5/t5555 tag", "--em optional - specify writing to em4305/4469 tag" ], - "usage": "lf destron clone [-h] -u [-u ]... [--q5] [--em]" + "usage": "lf destron clone [-h] -u [--q5] [--em]" }, "lf destron help": { "command": "lf destron help", @@ -6721,7 +6729,7 @@ "offline": false, "options": [ "-h, --help this help", - "-f, --file dictionary filename" + "-f, --file specify dictionary filename" ], "usage": "lf em 4x50 chk [-h] [-f ]" }, @@ -6737,7 +6745,7 @@ "offline": false, "options": [ "-h, --help this help", - "-f, --file dump filename (bin/eml/json)", + "-f, --file specify dump filename (bin/eml/json)", "-p, --pwd password, 4 hex bytes, lsb" ], "usage": "lf em 4x50 dump [-h] [-f ] [-p ]" @@ -6751,7 +6759,7 @@ "offline": false, "options": [ "-h, --help this help", - "-f, --filename dump filename (bin/eml/json)" + "-f, --file dump filename (bin/eml/json)" ], "usage": "lf em 4x50 eload [-h] -f " }, @@ -6765,7 +6773,7 @@ "offline": false, "options": [ "-h, --help this help", - "-f, --file save filename" + "-f, --file specifiy filename" ], "usage": "lf em 4x50 esave [-h] [-f ]" }, @@ -6866,7 +6874,7 @@ "options": [ "-h, --help this help", "-u, --uid uid, 4 hex bytes, msb", - "-f, --file dump filename (bin/eml/json)", + "-f, --file specify dump filename (bin/eml/json)", "-p, --pwd password, 4 hex bytes, lsb" ], "usage": "lf em 4x50 restore [-h] [-u ] [-f ] [-p ]" @@ -7189,13 +7197,15 @@ "command": "lf gproxii help", "description": "help this help demod demodulate a g prox ii tag from the graphbuffer --------------------------------------------------------------------------------------- lf gproxii demod available offline: yes try to find guardall prox-ii preamble, if found decode / descramble data", "notes": [ - "lf gproxii demod" + "lf gproxii demod -> use graphbuffer to decode", + "lf gproxii demod --raw fb8ee718ee3b8cc785c11b92 ->" ], "offline": true, "options": [ - "-h, --help this help" + "-h, --help this help", + "-r, --raw raw bytes" ], - "usage": "lf gproxii demod [-h]" + "usage": "lf gproxii demod [-h] [-r ]" }, "lf gproxii reader": { "command": "lf gproxii reader", @@ -7300,7 +7310,7 @@ "--em optional - specify writing to em4305/4469 tag", "--bin binary string i.e 0001001001" ], - "usage": "lf hid clone [-h] [-w ] [--fc ] [--cn ] [-i ] [-o ] [-r ]... [--q5] [--em] [--bin ]" + "usage": "lf hid clone [-h] [-w ] [--fc ] [--cn ] [-i ] [-o ] [-r ] [--q5] [--em] [--bin ]" }, "lf hid help": { "command": "lf hid help", @@ -7347,7 +7357,7 @@ "-o, --oem oem code", "-r, --raw raw bytes" ], - "usage": "lf hid sim [-h] [-w ] [--fc ] [--cn ] [-i ] [-o ] [-r ]..." + "usage": "lf hid sim [-h] [-w ] [--fc ] [--cn ] [-i ] [-o ] [-r ]" }, "lf hid watch": { "command": "lf hid watch", @@ -7372,7 +7382,7 @@ "-h, --help this help", "-f, --file filename to load ( w/o ext )" ], - "usage": "lf hitag cc [-h] [-f ]" + "usage": "lf hitag cc [-h] -f " }, "lf hitag dump": { "command": "lf hitag dump", @@ -7384,7 +7394,7 @@ "offline": false, "options": [ "-h, --help this help", - "-f, --file file name", + "-f, --file specify file name", "-k, --key key, 4 or 6 hex bytes", "--nrar nonce / answer reader, 8 hex bytes" ], @@ -7399,13 +7409,13 @@ "offline": true, "options": [ "-h, --help this help", - "-f, --file filename of dump", + "-f, --file specfiy dump filename", "-1 card type hitag1", "-2 card type hitag2", "-s card type hitags", "-m card type hitagm" ], - "usage": "lf hitag eload [-h12sm] -f " + "usage": "lf hitag eload [-h12sm] -f " }, "lf hitag info": { "command": "lf hitag info", @@ -7438,7 +7448,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "lf hitag list [-h1fcrux] [--dict ]..." + "usage": "lf hitag list [-h1fcrux] [--dict ]" }, "lf hitag reader": { "command": "lf hitag reader", @@ -7533,7 +7543,7 @@ "--q5 optional - specify writing to q5/t5555 tag", "--em optional - specify writing to em4305/4469 tag" ], - "usage": "lf idteck clone [-h] [-r ]... [--q5] [--em]" + "usage": "lf idteck clone [-h] -r [--q5] [--em]" }, "lf idteck help": { "command": "lf idteck help", @@ -7571,7 +7581,7 @@ "-h, --help this help", "-r, --raw raw bytes" ], - "usage": "lf idteck sim [-h] [-r ]..." + "usage": "lf idteck sim [-h] -r " }, "lf indala altdemod": { "command": "lf indala altdemod", @@ -7608,7 +7618,7 @@ "--em optional - specify writing to em4305/4469 tag", "--4041x optional - specify indala 4041x format, must use with fc and cn" ], - "usage": "lf indala clone [-h] [-r ]... [--heden ] [--fc ] [--cn ] [--q5] [--em] [--4041x]" + "usage": "lf indala clone [-h] [-r ] [--heden ] [--fc ] [--cn ] [--q5] [--em] [--4041x]" }, "lf indala help": { "command": "lf indala help", @@ -7658,7 +7668,7 @@ "-r, --raw raw bytes", "--heden cardnumber for heden 2l format" ], - "usage": "lf indala sim [-h] [-r ]... [--heden ]" + "usage": "lf indala sim [-h] [-r ] [--heden ]" }, "lf io clone": { "command": "lf io clone", @@ -7855,7 +7865,7 @@ "--q5 optional - specify writing to q5/t5555 tag", "--em optional - specify writing to em4305/4469 tag" ], - "usage": "lf motorola clone [-h] -r [-r ]... [--q5] [--em]" + "usage": "lf motorola clone [-h] -r [--q5] [--em]" }, "lf motorola help": { "command": "lf motorola help", @@ -9053,7 +9063,7 @@ "--q5 optional - specify writing to q5/t5555 tag", "--em optional - specify writing to em4305/4469 tag" ], - "usage": "lf viking clone [-h] [--cn ]... [--q5] [--em]" + "usage": "lf viking clone [-h] --cn [--q5] [--em]" }, "lf viking help": { "command": "lf viking help", @@ -9091,7 +9101,7 @@ "-h, --help this help", "--cn 8 digit hex viking card number" ], - "usage": "lf viking sim [-h] [--cn ]..." + "usage": "lf viking sim [-h] --cn " }, "lf visa2000 clone": { "command": "lf visa2000 clone", @@ -9187,10 +9197,10 @@ "-o, --offset offset in memory", "-l, --len length", "-v, --view view dump", - "-f, --file file name", + "-f, --file save filename", "-c, --cols column breaks (def 32)" ], - "usage": "mem dump [-hv] [-o ] [-l ] [-f ]... [-c ]" + "usage": "mem dump [-hv] [-o ] [-l ] [-f ] [-c ]" }, "mem help": { "command": "mem help", @@ -9238,9 +9248,9 @@ "-m, --mifare, --mfc upload 6 bytes keys (mifare key dictionary)", "-i, --iclass upload 8 bytes keys (iclass key dictionary)", "-t, --t55xx upload 4 bytes keys (password dictionary)", - "-f, --file file name" + "-f, --file file name" ], - "usage": "mem load [-hmit] [-o ] [-f ]..." + "usage": "mem load [-hmit] [-o ] -f " }, "mem spiffs check": { "command": "mem spiffs check", @@ -9317,7 +9327,7 @@ "offline": false, "options": [ "-h, --help this help", - "-f, --filename file to remove" + "-f, --file file to remove" ], "usage": "mem spiffs remove [-h] -f " }, @@ -9456,7 +9466,7 @@ "or to import into wireshark using encapsulation type \"iso 14443\"", "--dict use dictionary keys file" ], - "usage": "smart list [-h1fcrux] [--dict ]..." + "usage": "smart list [-h1fcrux] [--dict ]" }, "nfc barcode sim": { "command": "nfc barcode sim", @@ -9487,7 +9497,7 @@ "-f, --file file to load", "-v, --verbose verbose mode" ], - "usage": "nfc decode [-hv] [-d ]... [-f ]" + "usage": "nfc decode [-hv] [-d ] [-f ]" }, "nfc mf help": { "command": "nfc mf help", @@ -9978,31 +9988,32 @@ "offline": true, "options": [ "-h, --help this help", - "-f, --file firmware file name" + "-f, --file specify firmware file name" ], - "usage": "smart upgrade [-h] -f " + "usage": "smart upgrade [-h] -f " }, "trace help": { "command": "trace help", "description": "help this help list list protocol data in trace buffer load load trace from file save save trace buffer to file --------------------------------------------------------------------------------------- trace list available offline: yes annotate trace buffer with selected protocol data you can load a trace from file (see `trace load -h`) or it be downloaded from device by default", "notes": [ "trace list -t raw -> just show raw data without annotations", - "trace list -t 14a -> interpret as iso14443-a communications", - "trace list -t thinfilm -> interpret as thinfilm communications", - "trace list -t topaz -> interpret as topaz communications", - "trace list -t mf -> interpret as mifare classic communications and decrypt crypto1 stream", - "trace list -t des -> interpret as mifare desfire communications", - "trace list -t 14b -> interpret as iso14443-b communications", - "trace list -t 7816 -> interpret as iso7816-4 communications", - "trace list -t 15 -> interpret as iso15693 communications", - "trace list -t iclass -> interpret as iclass communications", - "trace list -t legic -> interpret as legic communications", - "trace list -t felica -> interpret as iso18092 / felica communications", - "trace list -t hitag1 -> interpret as hitag1 communications", - "trace list -t hitag2 -> interpret as hitag2 communications", - "trace list -t hitags -> interpret as hitags communications", - "trace list -t lto -> interpret as lto-cm communications", - "trace list -t cryptorf -> interpret as cryptorf communitcations", + "trace list -t 14a -> interpret as iso14443-a", + "trace list -t thinfilm -> interpret as thinfilm", + "trace list -t topaz -> interpret as topaz", + "trace list -t mf -> interpret as mifare classic and decrypt crypto1 stream", + "trace list -t des -> interpret as mifare desfire", + "trace list -t 14b -> interpret as iso14443-b", + "trace list -t 7816 -> interpret as iso7816-4", + "trace list -t 15 -> interpret as iso15693", + "trace list -t iclass -> interpret as iclass", + "trace list -t legic -> interpret as legic", + "trace list -t felica -> interpret as iso18092 / felica", + "trace list -t hitag1 -> interpret as hitag1", + "trace list -t hitag2 -> interpret as hitag2", + "trace list -t hitags -> interpret as hitags", + "trace list -t lto -> interpret as lto-cm", + "trace list -t cryptorf -> interpret as cryptorf", + "", "trace list -t mf --dict -> use dictionary keys file", "trace list -t 14a -f -> show frame delay times", "trace list -t 14a -1 -> use trace buffer" @@ -10018,9 +10029,9 @@ "-x show hexdump to convert to pcap(ng)", "or to import into wireshark using encapsulation type \"iso 14443\"", "-t, --type protocol to annotate the trace", - "--dict use dictionary keys file" + "--dict use dictionary keys file" ], - "usage": "trace list [-h1fcrux] [-t ]... [--dict ]..." + "usage": "trace list [-h1fcrux] [-t ] [--dict ]" }, "trace load": { "command": "trace load", @@ -10031,9 +10042,9 @@ "offline": true, "options": [ "-h, --help this help", - "-f, --file trace file to load" + "-f, --file specify trace file to load" ], - "usage": "trace load [-h] [-f ]..." + "usage": "trace load [-h] -f " }, "trace save": { "command": "trace save", @@ -10044,9 +10055,9 @@ "offline": true, "options": [ "-h, --help this help", - "-f, --file trace file to save" + "-f, --file specify trace file to save" ], - "usage": "trace save [-h] [-f ]..." + "usage": "trace save [-h] -f " }, "usart btfactory": { "command": "usart btfactory", @@ -10171,7 +10182,7 @@ "-r, --raw raw hex to be decoded", "-b, --bin binary string to be decoded" ], - "usage": "wiegand decode [-h] [-r ]... [-b ]" + "usage": "wiegand decode [-h] [-r ] [-b ]" }, "wiegand encode": { "command": "wiegand encode", diff --git a/doc/desfire.md b/doc/desfire.md index 6739d3322..50bddc9d5 100644 --- a/doc/desfire.md +++ b/doc/desfire.md @@ -1,6 +1,34 @@ -# DESFire card +# Notes on MIFARE DESFire + + +# Table of Contents + +- [Notes on MIFARE DESFire](#notes-on-mifare-desfire) +- [Table of Contents](#table-of-contents) + - [Documentation](#documentation) + - [Source code](#source-code) + - [Communication channel with a card](#communication-channel-with-a-card) + - [Card architecture](#card-architecture) + - [Card structure](#card-structure) + - [DESFire Light](#desfire-light) + - [How to](#how-to) + - [How to get card UID](#how-to-get-card-uid) + - [How to get/set default communication channel settings](#how-to-getset-default-communication-channel-settings) + - [How to guess default communication channel settings](#how-to-guess-default-communication-channel-settings) + - [How to try communication channel settings](#how-to-try-communication-channel-settings) + - [How to look at the application list on the card](#how-to-look-at-the-application-list-on-the-card) + - [How to look/dump files from the application file list](#how-to-lookdump-files-from-the-application-file-list) + - [How to change key](#how-to-change-key) + - [How to create the application](#how-to-create-the-application) + - [How to create files](#how-to-create-files) + - [How to delete files](#how-to-delete-files) + - [How to read/write files](#how-to-readwrite-files) + - [How to work with transaction mac](#how-to-work-with-transaction-mac) + - [How to switch DESFire Light to LRP mode](#how-to-switch-desfire-light-to-lrp-mode) + ## Documentation +^[Top](#top) [DESFire Light datasheet MF2DL(H)x0](https://www.nxp.com/docs/en/data-sheet/MF2DLHX0.pdf) @@ -21,6 +49,7 @@ [Symmetric key diversifications AN10922](https://www.nxp.com/docs/en/application-note/AN10922.pdf) ## Source code +^[Top](#top) [desfire_crypto from proxmark3](https://github.com/RfidResearchGroup/proxmark3/blob/master/armsrc/desfire_crypto.c) @@ -36,7 +65,8 @@ [LRP/ev2 nfc-ev2-crypto](https://github.com/icedevml/nfc-ev2-crypto) -## Communication channel with a card: +## Communication channel with a card +^[Top](#top) The card can work with a combination of: key type - command set - secure channel - communication mode @@ -75,6 +105,7 @@ The card can work with a combination of: key type - command set - secure channel **encrypted** - encrypted data in the request/response/both in the ev2 channel data signed with mac. ## Card architecture +^[Top](#top) The card has several applications on it and the applications have files and some other objects. @@ -84,7 +115,8 @@ Master application has many keys with different purposes, but commands show that Each application may have its own key type and set of keys. Each file can only have links to these keys in its access rights. -## Card structure: +## Card structure +^[Top](#top) - Application - Application number: 1 byte @@ -101,7 +133,8 @@ Each application may have its own key type and set of keys. Each file can only h - File communication mode: plain/maced/encrypted - File access right: there are 4 modes: read/write/read-write/change settings. And each mode access can be: key0..keyD, E - free access, F - deny access -## DESFire Light: +## DESFire Light +^[Top](#top) The card has one preinstalled master file (ISO ID 0x3f00) and one application (0xdf01) @@ -131,7 +164,9 @@ If it needs to have more space for FCI - just change the ID of one of the bigger ## How to + ### How to get card UID +^[Top](#top) The card can return UID in encrypted communication mode. Needs to authenticate with any key from the card. @@ -142,6 +177,7 @@ The card can return UID in encrypted communication mode. Needs to authenticate w `hf mfdes getuid -s ev2 -t aes -k 11223344556677889900112233445566` - via ev2 secure channel with specified aes key ### How to get/set default communication channel settings +^[Top](#top) All the commands use these settings by default if a more important setting is not specified in the command line. @@ -150,6 +186,7 @@ All the commands use these settings by default if a more important setting is no `hf mfdes default -n 1 -t aes` - set key number 1 and key type aes ### How to guess default communication channel settings +^[Top](#top) `hf mfdes detect` - simply detect key for master application (PICC level) @@ -162,12 +199,14 @@ All the commands use these settings by default if a more important setting is no `hf mfdes detect --aid 123456 -n 2` - detect key 2 from application with AID 123456 ### How to try communication channel settings +^[Top](#top) `hf mfdes auth -n 0 -t des -k 1122334455667788 --aid 123456` - try application 123456 master key `hf mfdes auth -n 0 -t aes --save` - try PICC AES master key and save the configuration to defaults if authentication succeeds ### How to look at the application list on the card +^[Top](#top) `hf mfdes lsapp --no-auth` - show applications list without authentication @@ -178,12 +217,14 @@ All the commands use these settings by default if a more important setting is no `hf mfdes getaids --no-auth` - this command can return a simple AID list if it is enabled in the card settings ### How to look/dump files from the application file list +^[Top](#top) `hf mfdes lsfiles --aid 123456 -t aes` - file list for application 123456 with aes key `hf mfdes dump --aid 123456` - shows files and their contents from application 123456 ### How to change key +^[Top](#top) Changing key algorithm can be done only in one case - change card master key. @@ -196,12 +237,14 @@ Key algorithm for application can be chosen only on its creation. `hf mfdes changekey --aid 123456 -t des -n 0 --newkeyno 1 --oldkey 5555555555555555 --newkey 1122334455667788` - change key 1 with authentication with key 0 (app master key) ### How to create the application +^[Top](#top) `hf mfdes createapp --aid 123456 --fid 2345 --dfname aid123456 --dstalgo aes` - create an application with ISO file ID, df name, and key algorithm AES `hf mfdes createapp --aid 123456` - create an application 123456 with DES key algorithm and without ISO file ID. in this case, iso file id can't be provided for application's files ### How to create files +^[Top](#top) `hf mfdes createfile --aid 123456 --fid 01 --isofid 0001 --size 000010` - create standard file with ISO ID and default access settings @@ -220,10 +263,12 @@ Create standard file with mac access mode and specified access settings. access `hf mfdes createmacfile --aid 123456 --fid 01 --rawrights 0FF0 --mackey 00112233445566778899aabbccddeeff --mackeyver 01` - create transaction mac file ### How to delete files +^[Top](#top) `hf mfdes deletefile --aid 123456 --fid 01` - delete file ### How to read/write files +^[Top](#top) *read:* @@ -270,6 +315,7 @@ For more detailed samples look at the next howto. `hf mfdes write --aid 123456 --fid 01 -d 01020304 --readerid 010203` write data to the file with CommitReaderID command before and CommitTransaction after write ### How to work with transaction mac +^[Top](#top) There are two types of transactions with mac: with and without the CommitReaderID command. The type can be chosen by `hf mfdes createmacfile` command. @@ -328,6 +374,7 @@ step 2. write something to a file with CommitReaderID command and provide the ke `hf mfdes write --aid 123456 --fid 01 -d 01020304 --readerid 010203 --trkey 00112233445566778899aabbccddeeff` ### How to switch DESFire Light to LRP mode +^[Top](#top) Remove failed authentication counters (if needs, but strongly recommended) diff --git a/doc/emv_notes.md b/doc/emv_notes.md index 2766e6761..60f85ebb8 100644 --- a/doc/emv_notes.md +++ b/doc/emv_notes.md @@ -1,7 +1,25 @@ # EMV commands -### EMV Implemented parts: +Notes on EMV works on Proxmark3 + +# Table of Contents +- [EMV commands](#emv-commands) +- [Table of Contents](#table-of-contents) + - [EMV Implemented parts](#emv-implemented-parts) + - [Working parts of qVSDC](#working-parts-of-qvsdc) + - [`not implemented` parts of EMV](#not-implemented-parts-of-emv) + - [Commands](#commands) + - [VISA(r) transactions](#visar-transactions) + - [Mastercard(r) transactions](#mastercardr-transactions) + - [all commands](#all-commands) + - [Useful links](#useful-links) + - [EMV kernels](#emv-kernels) + + + +### EMV Implemented parts +^[Top](#top) - Get ATR|ATS - Get AID by PSE (`emv pse`) @@ -22,7 +40,7 @@ - Check ARQC cryptogram (`not implemented`) - Issuer scripts processing (`not implemented`) -### Working parts of qVSDC: +### Working parts of qVSDC ^[Top](#top) - Get ATR|ATS @@ -58,7 +76,7 @@ command `emv exec` executes EMV transaction. it have parameters: ``` It works for VISA(r) and Mastercard(r) transactions. It may work with other EMV payment system's card (and it works in general cases that is described in EMV). -### VISA(r) transactions: +### VISA(r) transactions ^[Top](#top) MSD - Magnetic Stripe mode @@ -74,7 +92,7 @@ M/Chip - contact and contactless transaction Different cards have different modes on/of and different behavior in them. So needs to check card in all this modes. MSD - compatibility mode. Now it work always. But it less secure and in near future it will be slowly) disabled. -### all commands: +### all commands ^[Top](#top) ``` @@ -101,7 +119,7 @@ All main commands are parts of EMV specification. Commands than not described th `emv test` - test all crypto code from emv part of proxmark. -### Useful links: +### Useful links ^[Top](#top) EMV specifications diff --git a/doc/ext_flash_notes.md b/doc/ext_flash_notes.md index 76b4d9279..4b2452d2f 100644 --- a/doc/ext_flash_notes.md +++ b/doc/ext_flash_notes.md @@ -1,8 +1,21 @@ # External flash + External 256kbytes flash is a unique feature of the RDV4 edition. +# Table of Contents +- [External flash](#external-flash) +- [Table of Contents](#table-of-contents) + - [Addresses](#addresses) + - [Layout](#layout) + - [Page3 Layout](#page3-layout) + - [RSA signature](#rsa-signature) +- [backup first!](#backup-first) + + + ## Addresses +^[Top](#top) Flash memory is @@ -19,6 +32,7 @@ Therefore a flash address can be interpreted as such: ``` ## Layout +^[Top](#top) Page 0: * available for user data @@ -44,6 +58,7 @@ Page 3: * Updating keys dictionaries doesn't require to erase page 3. ## Page3 Layout +^[Top](#top) Page3 is used as follows by the Proxmark3 RDV4 firmware: @@ -69,6 +84,7 @@ Page3 is used as follows by the Proxmark3 RDV4 firmware: * offset should have been 0x3FF80 but historically it's one byte off and therefore the last byte of the flash is unused ## RSA signature +^[Top](#top) To ensure your Proxmark3 RDV4 is not a counterfeit product, its external flash contains a RSA signature of the flash unique ID. You can verify it with: `mem info` @@ -105,6 +121,8 @@ Here below is a sample output of a RDV4 device. ``` # backup first! +^[Top](#top) + To make a backup of the signature to file: `mem dump p f flash_signature_dump o 262015 l 128` diff --git a/doc/fpga_arm_notes.md b/doc/fpga_arm_notes.md index 37aa6a911..4271f5790 100644 --- a/doc/fpga_arm_notes.md +++ b/doc/fpga_arm_notes.md @@ -1,4 +1,25 @@ -# Notes on ARM & FPGA comms +# Notes on ARM & FPGA communications + + +# Table of Contents +- [Notes on ARM & FPGA communications](#notes-on-arm--fpga-communications) +- [Table of Contents](#table-of-contents) +- [INTERFACE FROM THE ARM TO THE FPGA](#interface-from-the-arm-to-the-fpga) + - [FPGA](#fpga) + - [FPGA modes](#fpga-modes) + - [ARM FPGA communications](#arm-fpga-communications) + - [ARM GPIO setup](#arm-gpio-setup) + - [FPGA Setup](#fpga-setup) +- [HARDWARE OVERVIEW](#hardware-overview) + - [ADC (ANALOG TO DIGITAL CONVERTER)](#adc-analog-to-digital-converter) + - [FIELD PROGRAMMABLE GATE ARRAY, FPGA](#field-programmable-gate-array-fpga) + - [MICROCONTROLLER](#microcontroller) + - [](#) + - [To behave like a READER](#to-behave-like-a-reader) + - [To behave like a TAG](#to-behave-like-a-tag) + - [To sniff traffic](#to-sniff-traffic) + - [FPGA purpose](#fpga-purpose) + https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/original_proxmark3/proxmark3.pdf @@ -34,6 +55,8 @@ LF analog path (MCP6294 opamp. This has a GBW of 10 MHz), all 'slow' signals. ## FPGA +^[Top](#top) + Since the SPARTAN II is a old outdated FPGA, thus is very limited resource there was a need to split LF and HF functionality into two separate FPGA images. Which are stored in ARM flash memory as bitstreams. We swap between these images by flashing fpga from ARM on the go. It takes about 1sec. Hence its usually a bad idea to program your device to continuously execute LF alt HF commands. @@ -50,19 +73,22 @@ In order to save space, these fpga images are LZ4 compressed and included in th This means we save some precious space on the ARM but its a bit more complex when flashing to fpga since it has to decompress on the fly. -### FPGA modes. +### FPGA modes +^[Top](#top) + - Major modes - Minor modes -## ARM FPGA communications. +## ARM FPGA communications +^[Top](#top) The ARM talks with FPGA over the Synchronous Serial Port (SSC) rx an tx. ARM, send a 16bit configuration with fits the select major mode. - ## ARM GPIO setup +^[Top](#top) ``` // First configure the GPIOs, and get ourselves a clock. @@ -100,6 +126,8 @@ ARM, send a 16bit configuration with fits the select major mode. ``` ## FPGA Setup +^[Top](#top) + // Set up DMA to receive samples from the FPGA. We will use the PDC, with // a single buffer as a circular buffer (so that we just chain back to @@ -107,13 +135,19 @@ ARM, send a 16bit configuration with fits the select major mode. # HARDWARE OVERVIEW +^[Top](#top) + ## ADC (ANALOG TO DIGITAL CONVERTER) +^[Top](#top) + The analogue signal that comes from the antenna circuit is fed into an 8-bit Analogue to Digital Converter (ADC). This delivers 8 output bits in parallel which represent the current voltage retrieved from the field. ## FIELD PROGRAMMABLE GATE ARRAY, FPGA +^[Top](#top) + The 8 output pins from the ADC are connected to 8 pins of the Field Programmable Gate Array (FPGA). An FPGA has a great advantage over a normal microcontroller in the sense that it emulates hardware. A hardware description can be compiled and flashed into an FPGA. @@ -141,6 +175,8 @@ FPGA generates an electromagnetic field on power hi and drops the amplitude for ## MICROCONTROLLER +^[Top](#top) + The microcontroller is responsible for the protocol management. It receives the digital encoded signals from the FPGA and decodes them. The decoded signals can just be copied to a buffer in the EEPROM memory. Additionally, an answer to the received message can be send by encoding a reply and @@ -185,13 +221,17 @@ Problems: ## -## To behave like a READER. +## To behave like a READER +^[Top](#top) + By driving all of the buffers LOW, it is possible to make the antenna look to the receive path like a parallel LC circuit; this provides a high-voltage output signal. This is typically what will be done when we are not actively transmitting a carrier (i.e., behaving as a reader). ## To behave like a TAG +^[Top](#top) + On the receive side, there are two possibilities, which are selected by RLY1. A mechanical relay is used, because the signal from the antenna is likely to be more positive or negative than the highest or lowest supply @@ -222,10 +262,13 @@ is the master) or its generic synchronous serial port (again, the ARM is the master). The ARM connects to the outside world over USB. ## To sniff traffic +^[Top](#top) ## FPGA purpose +^[Top](#top) + Digital signal processing. In short, apply low pass / hi pass filtering, peak detect, correlate signal meaning IQ pair collecting. diff --git a/doc/jooki_notes.md b/doc/jooki_notes.md index 5217ea3e8..aa950fdfa 100644 --- a/doc/jooki_notes.md +++ b/doc/jooki_notes.md @@ -1,15 +1,35 @@ # Jooki Figurine Notes + + +# Table of Contents +- [Jooki Figurine Notes](#jooki-figurine-notes) +- [Table of Contents](#table-of-contents) + - [Jooki proxmark commands](#jooki-proxmark-commands) + - [Decoding NDEF URL parameter](#decoding-ndef-url-parameter) + - [Encoding NDEF record](#encoding-ndef-record) + - [Simulation](#simulation) + - [Cloning to a NTAG213 tag](#cloning-to-a-ntag213-tag) + - [List of known figurine types](#list-of-known-figurine-types) + + + - NTAG213 (Should be tested if other NTAG2xx work) - A single NDEF record of type URL - Physical figurines are Fox, Dragon, Knight, Ghost, Whale, Generic Flat. Than there are variations of those figures with different colors. ## Jooki proxmark commands +^[Top](#top) + You can `encode`, `decode` a NDEF record, write with `clone` a record to a card or simulate with`sim`. ### Decoding NDEF URL parameter +^[Top](#top) + `hf jooki decode -d g+t07s57aX1bB6tk` ### Encoding NDEF record +^[Top](#top) + You can either use figurine abbreviation arguments: ``` --dragon @@ -49,6 +69,8 @@ Output: Use `-r` parameter to read UID directly from tag. ### Simulation +^[Top](#top) + To simulate the above figurine use the encoded URL parameter given in `encode` output and type following command into your proxmark: `hf jooki sim -b g+t07s57aX1bB6tk` @@ -56,6 +78,8 @@ To simulate the above figurine use the encoded URL parameter given in `encode` o If no parameter is given to the simulation command, last loaded dump is used. ### Cloning to a NTAG213 tag +^[Top](#top) + ``` hf jooki clone [-h] [-b ] [-d ] [-p ] @@ -81,6 +105,8 @@ or use the base64 encoded parameter to clone: Note: Jooki doesn't like more than one NDEF record, so make sure you just have one. Check with `hf mfu ndefread` ### List of known figurine types +^[Top](#top) + `Value`|`Figurine Type`| |------|---------------| **01** | Stones | diff --git a/doc/jtag_notes.md b/doc/jtag_notes.md index 1e6369767..eaea64b6e 100644 --- a/doc/jtag_notes.md +++ b/doc/jtag_notes.md @@ -1,8 +1,31 @@ +# Notes on JTAG + + Some notes on how to reflash a bricked Proxmark3 over JTAG. +# Table of Contents +- [Notes on JTAG](#notes-on-jtag) +- [Table of Contents](#table-of-contents) +- [Linux and OpenOCD](#linux-and-openocd) + - [Using RDV4 scripts](#using-rdv4-scripts) + - [RDV4 pinout](#rdv4-pinout) + - [JLink pinout](#jlink-pinout) + - [Raspberry Pi pinout](#raspberry-pi-pinout) +- [Where to find more information?](#where-to-find-more-information) + - [Third party notes on using a BusPirate](#third-party-notes-on-using-a-buspirate) + - [Third party notes on using a J-Link](#third-party-notes-on-using-a-j-link) + - [Third party notes on using a RaspBerry Pi](#third-party-notes-on-using-a-raspberry-pi) + - [Third party notes on using a J-Link on Windows](#third-party-notes-on-using-a-j-link-on-windows) + - [Stack Overflow write up article.](#stack-overflow-write-up-article) + - [Old original docs](#old-original-docs) + + + # Linux and OpenOCD +^[Top](#top) ## Using RDV4 scripts +^[Top](#top) The RDV4 repository contains helper scripts for JTAG flashing. @@ -22,12 +45,14 @@ In some rare situations, flashing the full image over JTAG may fail but the boot For advanced usages there are also `openocd_flash_dump.sh` for dumping the content of the Proxmark3 and `openocd_interactive.sh` for an OpenOCD console. ## RDV4 pinout +^[Top](#top) The RDV4 JTAG header is quite smaller compared to other Proxmark3 platforms. If you're using a J-Link, there is a [convenient adapter](https://github.com/RfidResearchGroup/proxmark3/wiki/Tools#jtag-adapter) made by Proxgrind. You can also make yours with some 1.27mm headers (look for `1.27mm header` on Aliexpress) or Pogo pins or buy an already made clip, e.g. search `dykb clamp` on Aliexpress and take a 1.27mm single-row 6P version. ## JLink pinout +^[Top](#top) J-Link [pinout](https://www.segger.com/interface-description.html): @@ -48,6 +73,7 @@ GND | 6 3.3 | 2 ## Raspberry Pi pinout +^[Top](#top) RPi [pinout](https://pinout.xyz/): @@ -61,9 +87,12 @@ GND | 6 3.3 | 1 # Where to find more information? +^[Top](#top) + There has been lots of articles and blogposts about recovering, debricking, JTAG your Proxmark3 and you find here below an assortiment of resources that will be of help. ## Third party notes on using a BusPirate +^[Top](#top) * https://github.com/Proxmark/proxmark3/wiki/Debricking-Proxmark3-with-buspirate * https://b4cktr4ck2.github.io/De-Brickify-Pm3-RDV2/ @@ -71,22 +100,29 @@ There has been lots of articles and blogposts about recovering, debricking, JTAG * https://joanbono.github.io/PoC/Flashing_Proxmark3.html ## Third party notes on using a J-Link +^[Top](#top) * http://wiki.yobi.be/wiki/Proxmark ## Third party notes on using a RaspBerry Pi +^[Top](#top) * http://www.lucasoldi.com/2017/01/17/unbrick-proxmark3-with-a-raspberry-pi-and-openocd/ * https://wiki.elvis.science/index.php?title=Proxmark3:_Debricking * https://github.com/synthetos/PiOCD/wiki/Using-a-Raspberry-Pi-as-a-JTAG-Dongle ## Third party notes on using a J-Link on Windows +^[Top](#top) * https://github.com/Proxmark/proxmark3/wiki/De-Bricking-Segger ## Stack Overflow write up article. +^[Top](#top) + https://stackoverflow.com/questions/48794076/error-halt-timed-out-wake-up-gdb/64291913#64291913 -## Old original doc, +## Old original docs +^[Top](#top) + Describes the SEGGER JLINK, JTAG process but be warned, this document is old. https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/original_proxmark3/Compiling%20Proxmark%20source%20and%20firmware%20upgrading%20v1.pdf \ No newline at end of file diff --git a/doc/loclass_notes.md b/doc/loclass_notes.md index 741a81023..43398f749 100644 --- a/doc/loclass_notes.md +++ b/doc/loclass_notes.md @@ -1,4 +1,11 @@ -# About LOCLASS attack +# Notes about the LOCLASS attack + + +# Table of Contents +- [Notes about the LOCLASS attack](#notes-about-the-loclass-attack) +- [Table of Contents](#table-of-contents) +- [Unit testing](#unit-testing) + This document is primarily intended for understanding `hf iclass loclass` and files used with it. @@ -15,6 +22,8 @@ If you don't have access to a iClass SE reader configured in Elite mode there is # Unit testing +^[Top](#top) + In order to verify that loclass is actually working, there is a "unit" test mode. run `hf iclass loclass --test`. diff --git a/doc/magic_cards_notes.md b/doc/magic_cards_notes.md index a295f01e0..5aaee0260 100644 --- a/doc/magic_cards_notes.md +++ b/doc/magic_cards_notes.md @@ -1,9 +1,14 @@ + + # Notes on Magic Cards, aka UID changeable This document is based mostly on information posted on http://www.proxmark.org/forum/viewtopic.php?pid=35372#p35372 Useful docs: * [AN10833 MIFARE Type Identification Procedure](https://www.nxp.com/docs/en/application-note/AN10833.pdf) + +# Table of Contents + - [ISO14443A](#iso14443a) * [Identifying broken ISO14443A magic](#identifying-broken-iso14443a-magic) - [MIFARE Classic](#mifare-classic) @@ -15,7 +20,6 @@ Useful docs: * [MIFARE Classic DirectWrite, UFUID version](#mifare-classic-directwrite-ufuid-version) * [MIFARE Classic, other versions](#mifare-classic-other-versions) * [MIFARE Classic Gen3 aka APDU](#mifare-classic-gen3-aka-apdu) - * [MIFARE Classic Gen3 aka GTU](#mifare-classic-gen3-aka-gtu) * [MIFARE Classic Super](#mifare-classic-super) - [MIFARE Ultralight](#mifare-ultralight) * [MIFARE Ultralight blocks 0..2](#mifare-ultralight-blocks-02) @@ -34,11 +38,14 @@ Useful docs: * [ISO14443B magic](#iso14443b-magic) - [ISO15693](#iso15693) * [ISO15693 magic](#iso15693-magic) +- [Multi](#multi) + * [Gen 4 GTU](#gen-4-gtu) # ISO14443A ## Identifying broken ISO14443A magic +^[Top](#top) When a magic card configuration is really messed up and the card is not labeled, it may be hard to find out which type of card it is. @@ -62,10 +69,12 @@ To restore anticollision config of the Proxmark3: hf 14a config --std ``` # MIFARE Classic +^[Top](#top) Referred as M1, S50 (1k), S70 (4k) ## MIFARE Classic block0 +^[Top](#top) UID 4b: (actually NUID as there are no more "unique" IDs on 4b) @@ -95,8 +104,10 @@ UID 7b: ``` ## MIFARE Classic Gen1A aka UID +^[Top](#top) ### Identify +^[Top](#top) ``` hf 14a info @@ -105,12 +116,14 @@ hf 14a info ``` ### Magic commands +^[Top](#top) * Wipe: `40(7)`, `41` (use 2000ms timeout) * Read: `40(7)`, `43`, `30xx`+crc * Write: `40(7)`, `43`, `A0xx`+crc, `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`+crc ### Characteristics +^[Top](#top) * UID: Only 4b versions * ATQA: @@ -125,48 +138,56 @@ hf 14a info * no card with ATS #### MIFARE Classic Gen1A flavour 1 +^[Top](#top) * SAK: play blindly the block0 SAK byte, beware! * PRNG: static 01200145 * Wipe: filled with 0xFF #### MIFARE Classic Gen1A flavour 2 +^[Top](#top) * SAK: play blindly the block0 SAK byte, beware! * PRNG: static 01200145 * Wipe: filled with 0x00 #### MIFARE Classic Gen1A flavour 3 +^[Top](#top) * SAK: 08 * PRNG: static 01200145 * Wipe: filled with 0xFF #### MIFARE Classic Gen1A flavour 4 +^[Top](#top) * SAK: 08 * PRNG: weak * Wipe: timeout, no wipe #### MIFARE Classic Gen1A flavour 5 +^[Top](#top) * SAK: 08 * PRNG: weak * Wipe: reply ok but no wipe performed #### MIFARE Classic Gen1A flavour 6 +^[Top](#top) * SAK: 08 or 88 if block0_SAK most significant bit is set * PRNG: weak * Wipe: timeout, no wipe #### MIFARE Classic Gen1A flavour 7 +^[Top](#top) * SAK: 08 or 88 if block0_SAK most significant bit is set * PRNG: weak * Wipe: filled with 0x00 ### Proxmark3 commands +^[Top](#top) ``` hf mf csetuid @@ -213,6 +234,7 @@ hf 14a raw -t 1000 41 ``` ### libnfc commands +^[Top](#top) ``` nfc-mfsetuid @@ -221,10 +243,12 @@ nfc-mfclassic W a u mydump ``` ## MIFARE Classic Gen1B +^[Top](#top) Similar to Gen1A, but supports directly read/write after command 40 ### Identify +^[Top](#top) ``` hf 14a info @@ -233,15 +257,18 @@ hf 14a info ``` ### Magic commands +^[Top](#top) * Read: `40(7)`, `30xx` * Write: `40(7)`, `A0xx`+crc, `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`+crc ## MIFARE Classic DirectWrite aka Gen2 aka CUID +^[Top](#top) (also referred as MCT compatible by some sellers) ### Identify +^[Top](#top) ``` hf 14a info @@ -254,12 +281,14 @@ Not all Gen2 cards can be identified with `hf 14a info`, only those replying to To identify the other ones, you've to try to write to block0 and see if it works... ### Magic commands +^[Top](#top) Android compatible * issue regular write to block0 ### Characteristics +^[Top](#top) * UID: 4b and 7b versions * ATQA: @@ -276,6 +305,7 @@ Android compatible * some reply with an ATS #### MIFARE Classic DirectWrite flavour 1 +^[Top](#top) * UID 4b * ATQA: play blindly the block0 ATQA bytes, beware! @@ -285,6 +315,7 @@ Android compatible * PRNG: weak #### MIFARE Classic DirectWrite flavour 2 +^[Top](#top) * UID 4b * ATQA: fixed @@ -294,6 +325,7 @@ Android compatible * PRNG: weak #### MIFARE Classic DirectWrite flavour 3 +^[Top](#top) * UID 4b * ATQA: play blindly the block0 ATQA bytes, beware! @@ -303,6 +335,7 @@ Android compatible * PRNG: weak #### MIFARE Classic DirectWrite flavour 4 +^[Top](#top) * UID 7b * ATQA: fixed @@ -312,6 +345,7 @@ Android compatible * PRNG: static 00000000 #### MIFARE Classic DirectWrite flavour 5 +^[Top](#top) * UID 4b * ATQA: fixed @@ -321,6 +355,7 @@ Android compatible * PRNG: weak #### MIFARE Classic DirectWrite flavour 6 +^[Top](#top) **TODO** need more info @@ -328,6 +363,7 @@ Android compatible * ATS: 0D780071028849A13020150608563D ### Proxmark3 commands +^[Top](#top) ``` hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 11223344440804006263646566676869 @@ -361,12 +397,14 @@ hf 14a config --std hf 14a reader ``` ## MIFARE Classic DirectWrite, FUID version aka 1-write +^[Top](#top) Same as MIFARE Classic DirectWrite, but block0 can be written only once. Initial UID is AA55C396 ### Identify +^[Top](#top) Only possible before personalization. @@ -377,14 +415,17 @@ hf 14a info ``` ## MIFARE Classic DirectWrite, UFUID version +^[Top](#top) Same as MIFARE Classic DirectWrite, but block0 can be locked with special command. ### Identify +^[Top](#top) **TODO** ### Proxmark3 commands +^[Top](#top) To lock definitively block0: ``` @@ -395,6 +436,7 @@ hf 14a raw -c 85000000000000000000000000000008 ``` ## MIFARE Classic, other versions +^[Top](#top) **TODO** @@ -402,8 +444,10 @@ hf 14a raw -c 85000000000000000000000000000008 * Some cards exhibit a specific SAK=28 ?? ## MIFARE Classic Gen3 aka APDU +^[Top](#top) ### Identify +^[Top](#top) ``` hf 14a info @@ -412,6 +456,7 @@ hf 14a info ``` ### Magic commands +^[Top](#top) Android compatible @@ -436,6 +481,7 @@ Writing to block 0 has some side-effects: * On 4-byte UID cards, BCC byte is automatically corrected. ### Characteristics +^[Top](#top) * UID: 4b and 7b versions * ATQA/SAK: fixed @@ -443,6 +489,7 @@ Writing to block 0 has some side-effects: * ATS: none ### Proxmark3 commands +^[Top](#top) ``` # change just UID: @@ -468,156 +515,9 @@ hf 14a raw -s -c -t 2000 90F0CCCC10 041219c3219316984200e32000000000 # lock (uid/block0?) forever: hf 14a raw -s -c 90FD111100 ``` ---------- -## MIFARE Classic Gen3 aka GTU - -### Identify - -Tag doesn't get identified by latest Proxmark3 client correct but instead mislabled as Gen2/CUID - -``` -hf 14a info -... -[+] Magic capabilities : Gen 2 / CUID -``` - - -### Magic commands - -Android compatible - unknown status - -* issue special APDUs - -``` -cla ins p1 p2 len - CF 00 00 00 00 32 - CF 00 00 00 00 35 - CF 00 00 00 00 34 - CF 00 00 00 00 68 - CF 00 00 00 00 69 <00> - CF 00 00 00 00 CE // Backdoor read card - CF 00 00 00 00 CD // Backdoor write card - CF 00 00 00 00 FE aabbccdd // set password to AABBCCDD - CF 00 00 00 00 F1 // fuse is set ??? - CF 00 00 00 00 F0 // fuse ??? -``` -Note: It doesn't seem to follow a APDU structure per default, - - -### Characteristics - -* UID: 4b, 7b and 10b versions -* ATQA/SAK: changeable -* BCC: -* ATS: changeable -* Card Type: changeable -* Shadow mode: GTU -* Backdoor password mode: - -#### Possible card types -Known Preset Change Available: -* MIFARE Mini -* MIFARE 1k S50 4 byte UID -* MIFARE 1k S50 7 byte UID -* MIFARE 1k S50 10 byte UID -* MIFARE 4k S70 4 byte UID -* MIFARE 4k S70 7 byte UID -* MIFARE 4k S70 10 byte UID -* Ultralight -* Ultralight-C -* Ultralight Ev1 -* NTAG - - - -### Proxmark3 commands - -``` -# view contents of tag memory: -hf mf gview -``` - -Equivalent: - - -change ATQA / SAK -================= -``` -hf 14a raw -s -c -t 1000 cf0000000035 -hf 14a raw -s -c -t 1000 cf0000000035440028 // ATQA 00 44 SAK 28 -``` - -change ATS -========== -It should be noted that when SAK=20,28, ATS must be turned on, otherwise the card will not be recognized! - -``` -hf 14a raw -s -c -t 1000 cf0000000034 -hf 14a raw -s -c -t 1000 cf000000003406067577810280 // ATS to 0606757781028002F0 -``` - * length 0, ATS is not sent - * when SAK is 20 or 28, ATS must be set, otherwise the card cannot be read - * the last two digits of ATS are CRC and cannot be counted as length - -set UID length (4, 7, 10) -========================= -``` -hf 14a raw -s -c -t 1000 cf0000000068 -hf 14a raw -s -c -t 1000 cf000000006801 // set UID length to 7 bytes -``` - * param=00: 4 bytes 01: 7 bytes 02: 10 bytes - -Set 14443A/B-UID -================ ---> missing instructions. - - - -Set Ultralight mode -=================== -``` -hf 14a raw -s -c -t 1000 cf0000000069<00> -``` - * 01: UL agreement opened - * 00: UL agreement closed - * in this mode, if SAK=00 ATQA=0044 (Pm3 sequence), it can become an Ultralight card - - -set shadow mode (GTU) -===================== - -This mode is divided into four states: off (pre-write), on (on restore), don’t care, and high-speed read and write. -If you use it, please enter the pre-write mode first. At this time, write the full card data. -After writing, set it to on. At this time, after writing the data, the first time you read the data just written, the next time you read It is the pre-written data. All modes support this operation. It should be noted that using any block to read and write in this mode may give wrong results. - -``` -hf 14a raw -s -c -t 1000 cf0000000032 -``` -Param | Description - 00 | Closed, shadow data can be written at this time - 01 | Open, start restore - 02 | Turn it off completely, as a normal card - 03 | High-speed read and write mode - -Any block read and write -======================== -Using the backdoor command can read and write any area without password, similar to UID card, it should be noted that this command must be used to modify UID. - -``` -hf 14a raw -s -c -t 1000 cf00000000CE // Backdoor read card -hf 14a raw -s -c -t 1000 cf00000000CD // Backdoor write card -``` - -set backdoor password -===================== -All backdoor operations are protected by passwords. If password is forgotten, the card will be scrapped -default password is 00000000 -``` -hf 14a raw -s -c -t 1000 cf00000000feaabbccdd // set password to AABBCCDD -``` - ## MIFARE Classic Super +^[Top](#top) It behaves like DirectWrite but records reader auth attempts. @@ -629,6 +529,7 @@ To do reader-only attack: at least two versions exist. * type 2: https://github.com/netscylla/super-card/blob/master/libnfc-1.7.1/utils/nfc-super.c for ?? ### Identify +^[Top](#top) Only type 1 at the moment: @@ -639,8 +540,10 @@ hf 14a info ``` # MIFARE Ultralight +^[Top](#top) ## MIFARE Ultralight blocks 0..2 +^[Top](#top) ``` SN0 SN1 SN2 BCC0 @@ -660,6 +563,7 @@ Anticol shortcut (CL1/3000) is supported for UL, ULC, NTAG except NTAG I2C ## MIFARE Ultralight Gen1A +^[Top](#top) ### Identify @@ -680,6 +584,7 @@ Only 7b versions **TODO** need more tests ### Proxmark3 commands +^[Top](#top) ``` script run hf_mfu_setuid -h @@ -693,8 +598,10 @@ script run hf_mf_magicrevive -u ``` ## MIFARE Ultralight DirectWrite +^[Top](#top) ### Identify +^[Top](#top) ``` hf 14a info @@ -705,10 +612,12 @@ hf 14a info It seems so far that all MFUL DW have an ATS. ### Magic commands +^[Top](#top) Issue three regular MFU write commands in a row to write first three blocks. ### Characteristics +^[Top](#top) * UID: Only 7b versions * ATQA: @@ -722,18 +631,21 @@ Issue three regular MFU write commands in a row to write first three blocks. * all cards reply with an ATS #### MIFARE Ultralight DirectWrite flavour 1 +^[Top](#top) * BCC: computed * ATS: 0A78008102DBA0C119402AB5 * Anticol shortcut (CL1/3000): fails #### MIFARE Ultralight DirectWrite flavour 2 +^[Top](#top) * BCC: play blindly the block0 BCC0 and block2 BCC1 bytes, beware! * ATS: 850000A00A000AB00000000000000000184D * Anticol shortcut (CL1/3000): succeeds ### Proxmark3 commands +^[Top](#top) ``` hf mfu setuid -h @@ -762,6 +674,7 @@ hf 14a reader ``` ### libnfc commands +^[Top](#top) ``` nfc-mfultralight -h @@ -769,14 +682,17 @@ nfc-mfultralight -h See `--uid` and `--full` ### Android +^[Top](#top) * MIFARE++ Ultralight ## MIFARE Ultralight EV1 DirectWrite +^[Top](#top) Similar to MFUL DirectWrite ### Identify +^[Top](#top) ``` hf 14a info @@ -785,6 +701,7 @@ hf 14a info ``` ### Characteristics +^[Top](#top) * UID: Only 7b versions * ATQA: @@ -797,24 +714,29 @@ hf 14a info * all cards reply with an ATS #### MIFARE Ultralight EV1 DirectWrite flavour 1 +^[Top](#top) * BCC: play blindly the block0 BCC0 and block2 BCC1 bytes, beware! * ATS: 850000A000000AC30004030101000B0341DF #### MIFARE Ultralight EV1 DirectWrite flavour 2 +^[Top](#top) * BCC: play blindly the block0 BCC0 and block2 BCC1 bytes, beware! * ATS: 850000A00A000AC30004030101000B0316D7 ## MIFARE Ultralight C Gen1A +^[Top](#top) Similar to MFUL Gen1A ## MIFARE Ultralight C DirectWrite +^[Top](#top) Similar to MFUL DirectWrite ### Identify +^[Top](#top) ``` hf 14a info @@ -823,6 +745,7 @@ hf 14a info ``` ### Characteristics +^[Top](#top) * UID: Only 7b versions * ATQA: @@ -835,18 +758,22 @@ hf 14a info * all cards reply with an ATS #### MIFARE Ultralight C DirectWrite flavour 1 +^[Top](#top) * BCC: computed * ATS: 0A78008102DBA0C119402AB5 * Anticol shortcut (CL1/3000): fails # NTAG +^[Top](#top) ## NTAG213 DirectWrite +^[Top](#top) Similar to MFUL DirectWrite ### Identify +^[Top](#top) ``` hf 14a info @@ -855,6 +782,7 @@ hf 14a info ``` ### Characteristics +^[Top](#top) * UID: Only 7b versions * ATQA: @@ -867,14 +795,17 @@ hf 14a info * all cards reply with an ATS #### NTAG213 DirectWrite flavour 1 +^[Top](#top) * BCC: play blindly the block0 BCC0 and block2 BCC1 bytes, beware! * ATS: 0A78008102DBA0C119402AB5 * Anticol shortcut (CL1/3000): succeeds ## NTAG21x +^[Top](#top) ### Identify +^[Top](#top) ``` hf 14a info @@ -883,6 +814,7 @@ hf 14a info ``` ### Characteristics +^[Top](#top) Emulates fully NTAG213, 213F, 215, 216, 216F @@ -891,12 +823,14 @@ Emulates partially UL EV1 48k/128k, NTAG210, NTAG212, NTAGI2C 1K/2K, NTAGI2C 1K Anticol shortcut (CL1/3000): fails ### Proxmark3 commands +^[Top](#top) ``` script run hf_mfu_magicwrite -h ``` # DESFire +^[Top](#top) ## "DESFire" APDU, 7b UID @@ -911,6 +845,7 @@ Android compatible * issue special APDUs ### Characteristics +^[Top](#top) * ATQA: 0344 * SAK: 20 @@ -919,6 +854,7 @@ Android compatible Only mimics DESFire anticollision (but wrong ATS), no further DESFire support ### Proxmark commands +^[Top](#top) UID 04112233445566 ``` @@ -930,6 +866,7 @@ hf 14a apdu -s 00ab00000704112233445566 ``` ### libnfc commands +^[Top](#top) ``` pn53x-tamashell @@ -937,14 +874,17 @@ pn53x-tamashell 420200ab00000704112233445566 ``` ## "DESFire" APDU, 4b UID +^[Top](#top) ### Magic commands +^[Top](#top) Android compatible * issue special APDUs ### Characteristics +^[Top](#top) * ATQA: 0008 ??? This is not DESFire, 0008/20 doesn't match anything * SAK: 20 @@ -953,6 +893,7 @@ Android compatible Only mimics DESFire anticollision (but wrong ATS), no further DESFire support ### Proxmark commands +^[Top](#top) UID 04112233445566 ``` @@ -966,12 +907,14 @@ hf 14a apdu -s 00ab00000411223344 It accepts longer UID but that doesn't affect BCC/ATQA/SAK ### pn53x-tamashell commands +^[Top](#top) ``` 4a0100 420200ab00000411223344 ``` ### Remarks +^[Top](#top) The same effect (with better ATQA!) can be obtained with a MFC Gen1A that uses SAK defined in block0: @@ -986,22 +929,27 @@ hf 14a info ``` # ISO14443B +^[Top](#top) ## ISO14443B magic +^[Top](#top) No such card is available. Some vendor allow to specify an ID (PUPI) when ordering a card. # ISO15693 +^[Top](#top) ## ISO15693 magic +^[Top](#top) ### Identify **TODO** ### Proxmark3 commands +^[Top](#top) Always set a UID starting with `E0`. @@ -1012,3 +960,418 @@ or (ignore errors): ``` script run hf_15_magic -u E004013344556677 ``` + + + +# Multi +^[Top](#top) + +## Gen 4 GTU +^[Top](#top) + +A.k.a ultimate magic card, most promenent feature is shadow mode (GTU) and optional password protected backdoor commands. + + +Can emulate MIFARE Classic, Ultralight/NTAG families, 14b UID & App Data + +- [Identify](#identify) +- [Magic commands](#magic-commands) +- [Characteristics](#characteristics) +- [Proxmark3 commands](#proxmark3-commands) +- [Change ATQA / SAK](#change-atqa--sak) +- [Change ATS](#change-ats) +- [Set UID length (4, 7, 10)](#set-uid-length-4-7-10) +- [Set 14443A UID](#set-14443a-uid) +- [Set 14443B UID and ATQB](#set-14443b-uid-and-atqb) +- [(De)Activate Ultralight mode](#deactivate-ultralight-mode) +- [Select Ultralight mode](#select-ultralight-mode) +- [Set shadow mode (GTU)](#set-shadow-mode-gtu) +- [Direct block read and write](#direct-block-read-and-write) +- [Change backdoor password](#change-backdoor-password) +- [Dump configuration](#dump-configuration) +- [Fast configuration](#fast-configuration) +- [Presets](#presets) +- [Version and Signature](#version-and-signature) + + +### Identify +^[Top](#top) ^^[Gen4](#g4top) + +👉 **TODO** Tag doesn't get identified correctly by latest Proxmark3 client (it might get mislabeled as MFC Gen2/CUID, Gen3/APDU or NTAG21x Modifiable, depending on configured UID/ATQA/SAK/ATS) + +One can identify manually such card if the password is still the default one, with the command to get the current configuration: +``` +hf 14a raw -s -c -t 1000 CF00000000C6 +``` +If the card is an Ultimate Magic Card, it returns 30 bytes. +### Magic commands +^[Top](#top) ^^[Gen4](#g4top) + +Special commands summary: + +``` +CF 32 <00-03> // Configure GTU shadow mode +CF 34 <1b length><0-16b ATS> // Configure ATS +CF 35 <2b ATQA><1b SAK> // Configure ATQA/SAK (swap ATQA bytes) +CF 68 <00-02> // Configure UID length +CF 69 <00-01> // (De)Activate Ultralight mode +CF 6A <00-03> // Select Ultralight mode +CF C6 // Dump configuration +CF CC // Factory test, returns 6666 +CF CD <1b block number><16b block data> // Backdoor write 16b block +CF CE <1b block number> // Backdoor read 16b block +CF F0 <30b configuration data> // Configure all params in one cmd +CF F1 <30b configuration data> // Configure all params in one cmd and fuse the configuration permanently +CF FE <4b new_password> // change password +``` +Default ``: `00000000` + +### Characteristics +^[Top](#top) ^^[Gen4](#g4top) + +* UID: 4b, 7b and 10b versions +* ATQA/SAK: changeable +* BCC: auto +* ATS: changeable, can be disabled +* Card Type: changeable +* Shadow mode: GTU +* Backdoor password mode + +### Proxmark3 commands +^[Top](#top) ^^[Gen4](#g4top) + +``` +# view contents of tag memory: +hf mf gview +``` +👉 **TODO** `hf mf gview` is currently missing Ultralight memory maps + +Equivalent: + +``` +hf 14a raw -s -c -t 1000 CF00000000CE00 +hf 14a raw -s -c -t 1000 CF00000000CE01 +hf 14a raw -s -c -t 1000 CF00000000CE02 +... +``` + +### Change ATQA / SAK +^[Top](#top) ^^[Gen4](#g4top) + +``` +hf 14a raw -s -c -t 1000 CF35<2b ATQA><1b SAK> +``` +* ⚠ ATQA bytes are swapped in the command +* ⚠ when SAK bit 6 is set (e.g. SAK=20 or 28), ATS must be turned on, otherwise the card may not be recognized by some readers! +* ⚠ never set SAK bit 3 (e.g. SAK=04), it indicates an extra cascade level is required (see `hf 14a config --cl2 skip` or `hf 14a config --cl3 skip` to recover a misconfigured card) + +Example: ATQA 0044 SAK 28, default pwd +``` +hf 14a raw -s -c -t 1000 CF0000000035440028 +``` +### Change ATS +^[Top](#top) ^^[Gen4](#g4top) + +``` +hf 14a raw -s -c -t 1000 CF34<1b length><0-16b ATS> +``` + * ``: ATS length byte, set to `00` to disable ATS + * ⚠ when SAK bit 6 is set (e.g. SAK=20 or 28), ATS must be turned on, otherwise the card may not be recognized by some readers! + * ATS CRC will be added automatically, don't configure it + * Max ATS length: 16 bytes (+CRC) + +Example: ATS to 0606757781028002F0, default pwd +``` +hf 14a raw -s -c -t 1000 CF000000003406067577810280 +``` + +### Set UID length (4, 7, 10) +^[Top](#top) ^^[Gen4](#g4top) + +``` +hf 14a raw -s -c -t 1000 CF68<1b param> +``` + * `` + * `00`: 4 bytes + * `01`: 7 bytes + * `02`: 10 bytes + +Example: set UID length to 7 bytes, default pwd +``` +hf 14a raw -s -c -t 1000 CF000000006801 +``` +### Set 14443A UID +^[Top](#top) ^^[Gen4](#g4top) + +UID is configured according to block0 with a backdoor write. + +Example: preparing first two blocks: +``` +hf 14a raw -s -c -t 1000 CF00000000CD00000102030405060708090A0B0C0D0E0F +hf 14a raw -s -c -t 1000 CF00000000CD01101112131415161718191A1B1C1D1E1F +hf 14a reader +``` +MFC mode, 4b UID +=> UID `00010203` + +MFC mode, 7b UID +=> UID `00010203040506` + +MFC mode, 10b UID +=> UID `00010203040506070809` + +Ultralight mode, 4b UID +=> UID `00010203` + +Ultralight mode, 7b UID +=> UID `00010210111213` +👉 the UID is composed of first two blocks as in regular Ultralights + +Ultralight mode, 10b UID +=> UID `00010203040506070809` +👉 the UID is composed only from block0 + +### Set 14443B UID and ATQB +^[Top](#top) ^^[Gen4](#g4top) + +UID and ATQB are configured according to block0 with a (14a) backdoor write. + +UID size is always 4 bytes. + +Example: +``` +hf 14a raw -s -c -t 1000 CF00000000CD00000102030405060708090A0B0C0D0E0F +hf 14b reader +``` +=> UID 00010203 +=> ATQB 0405060708090A + +### (De)Activate Ultralight mode +^[Top](#top) ^^[Gen4](#g4top) + +``` +hf 14a raw -s -c -t 1000 CF69<1b param> +``` + * `` + * `00`: MIFARE Classic mode + * `01`: MIFARE Ultralight/NTAG mode + +Example: activate Ultralight protocol, default pwd +``` +hf 14a raw -s -c -t 1000 CF000000006901 +``` + +In this mode, if SAK=`00` and ATQA=`0044`, it acts as an Ultralight card + +⚠ only the first four bytes of each block will be mapped in the Ultralight memory map (so the Ultralight block numbers follow backdoor R/W block numbers). + +### Select Ultralight mode +^[Top](#top) ^^[Gen4](#g4top) + +``` +hf 14a raw -s -c -t 1000 CF6A<1b param> +``` + + * `` + * `00`: UL EV1 + * `01`: NTAG + * `02`: UL-C + * `03`: UL + +⚠ it supposes Ultralight mode was activated (cf command `69`) + +Example: set Ultralight mode to Ultralight-C, default pwd +``` +hf 14a raw -s -c -t 1000 CF000000006A02 +``` +Now the card supports the 3DES UL-C authentication. +### Set shadow mode (GTU) +^[Top](#top) ^^[Gen4](#g4top) + +This mode is divided into four states: off (pre-write), on (on restore), don’t care, and high-speed read and write. +If you use it, please enter the pre-write mode first. At this time, write the full card data. +After writing, set it to on. At this time, after writing the data, the first time you read the data just written, the next time you read It is the pre-written data. All modes support this operation. It should be noted that using any block to read and write in this mode may give wrong results. + +``` +hf 14a raw -s -c -t 1000 CF32<1b param> +``` + * `` + * `00`: pre-write, shadow data can be written + * `01`: restore mode + * `02`: disabled + * `03`: disabled, high speed R/W mode for Ultralight? + +### Direct block read and write +^[Top](#top) ^^[Gen4](#g4top) + +Using the backdoor command, one can read and write any area without MFC password, similarly to MFC Gen1 card. It should be noted that this command must be used to modify UID. + +Backdoor read 16b block: +``` +hf 14a raw -s -c -t 1000 CFCE<1b block number> +``` +Backdoor write 16b block: +``` +hf 14a raw -s -c -t 1000 CFCD<1b block number><16b block data> +``` + +Read/Write operations work on 16 bytes, no matter the Ultralight mode. + +Note that only the first four bytes of each block will be mapped in the Ultralight memory map. + +Example: read block0, default pwd +``` +hf 14a raw -s -c -t 1000 CF00000000CE00 +``` +Example: write block0 with factory data, default pwd +``` +hf 14a raw -s -c -t 1000 CF00000000CD00112233441C000011778185BA18000000 +``` + +### Change backdoor password +^[Top](#top) ^^[Gen4](#g4top) + +All backdoor operations are protected by a password. If password is forgotten, the card can't be recovered. Default password is `00000000`. + +Change password: +``` +hf 14a raw -s -c -t 1000 CF FE <4b new_password> +``` +Example: change password from 00000000 to AABBCCDD +``` +hf 14a raw -s -c -t 1000 CF00000000FEAABBCCDD +``` +Example: change password from AABBCCDD back to 00000000 +``` +hf 14a raw -s -c -t 1000 CFAABBCCDDFE00000000 +``` + +### Dump configuration +^[Top](#top) ^^[Gen4](#g4top) + +``` +hf 14a raw -s -c -t 1000 CFC6 +``` +Default configuration: +``` +00000000000002000978009102DABC191010111213141516040008004F6B + ^^^^ ?? + ^^ cf cmd 6a: UL mode + ^^^^^^ cf cmd 35: ATQA/SAK + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cf cmd 34: ATS length & content + ^^ cf cmd 32: GTU mode + ^^^^^^^^ cf cmd fe: password + ^^ cf cmd 68: UID length +^^ cf cmd 69: Ultralight protocol +``` +### Fast configuration +^[Top](#top) ^^[Gen4](#g4top) + +``` +hf 14a raw -s -c -t 1000 CFF0<30b configuration data> +``` +cf **Dump configuration** for configuration data description. + +Example: Write factory configuration, using default password +``` +hf 14a raw -s -c -t 1000 CF00000000F000000000000002000978009102DABC191010111213141516040008004F6B +``` + +⚠ Variant with command `F1` instead of `F0` will set and fuse permanently the configuration. Backdoor R/W will still work. + +### Presets +^[Top](#top) ^^[Gen4](#g4top) + +Here are some presets available in the FuseTool (but with all ATS disabled) + +**MIFARE Mini S20 4-byte UID** +``` +hf 14a raw -s -c -t 1000 CF00000000F000000000000002000978009102DABC19101011121314151604000900 +``` + +**MIFARE Mini S20 7-byte UID** +``` +hf 14a raw -s -c -t 1000 CF00000000F000010000000002000978009102DABC19101011121314151644000900 +``` + +**MIFARE 1k S50 4-byte UID** (this is the factory setting) +``` +hf 14a raw -s -c -t 1000 CF00000000F000000000000002000978009102DABC19101011121314151604000800 +``` + +**MIFARE 1k S50 7-byte UID** +``` +hf 14a raw -s -c -t 1000 CF00000000F000010000000002000978009102DABC19101011121314151644000800 +``` + +**MIFARE 4k S70 4-byte UID** +``` +hf 14a raw -s -c -t 1000 CF00000000F000000000000002000978009102DABC19101011121314151602001800 +``` + +**MIFARE 4k S70 7 byte UID** +``` +hf 14a raw -s -c -t 1000 CF00000000F000010000000002000978009102DABC19101011121314151642001800 +``` + +**Ultralight** +``` +hf 14a raw -s -c -t 1000 CF00000000F001010000000003000978009102DABC19101011121314151644000003 +``` + +**Ultralight-C** +``` +hf 14a raw -s -c -t 1000 CF00000000F001010000000003000978009102DABC19101011121314151644000002 +``` + +**Ultralight EV1** +``` +hf 14a raw -s -c -t 1000 CF00000000F001010000000003000978009102DABC19101011121314151644000000 +``` + +**NTAG21x** +``` +hf 14a raw -s -c -t 1000 CF00000000F001010000000003000978009102DABC19101011121314151644000001 +``` + +### Version and Signature +^[Top](#top) ^^[Gen4](#g4top) + +Ultralight EV1 and NTAG Version info and Signature are stored respectively in blocks 250-251 and 242-249. + +Example for an Ultralight EV1 128b with the signature sample from tools/recover_pk.py +``` +hf 14a raw -s -c -t 1000 CF00000000F001010000000003000978009102DABC19101011121314151644000000 +hf mfu wrbl -b 0 -d 04C12865 +hf mfu wrbl -b 1 -d 5A373080 +hf mfu wrbl -b 242 -d CEA2EB0B --force +hf mfu wrbl -b 243 -d 3C95D084 --force +hf mfu wrbl -b 244 -d 4A95B824 --force +hf mfu wrbl -b 245 -d A7553703 --force +hf mfu wrbl -b 246 -d B3702378 --force +hf mfu wrbl -b 247 -d 033BF098 --force +hf mfu wrbl -b 248 -d 7899DB70 --force +hf mfu wrbl -b 249 -d 151A19E7 --force +hf mfu wrbl -b 250 -d 00040301 --force +hf mfu wrbl -b 251 -d 01000E03 --force +hf mfu info +``` + +Example for an NTAG216 with the signature sample from tools/recover_pk.py +``` +hf 14a raw -s -c -t 1000 CF00000000F001010000000003000978009102DABC19101011121314151644000001 +hf mfu wrbl -b 0 -d 04E10C61 +hf mfu wrbl -b 1 -d DA993C80 +hf mfu wrbl -b 242 -d 8B76052E --force +hf mfu wrbl -b 243 -d E42F5567 --force +hf mfu wrbl -b 244 -d BEB53238 --force +hf mfu wrbl -b 245 -d B3E3F995 --force +hf mfu wrbl -b 246 -d 0707C0DC --force +hf mfu wrbl -b 247 -d C956B5C5 --force +hf mfu wrbl -b 248 -d EFCFDB70 --force +hf mfu wrbl -b 249 -d 9B2D82B3 --force +hf mfu wrbl -b 250 -d 00040402 --force +hf mfu wrbl -b 251 -d 01001303 --force +hf mfu info +``` + diff --git a/doc/md/Development/Makefile-vs-CMake.md b/doc/md/Development/Makefile-vs-CMake.md index df696e5ec..d77734cfc 100644 --- a/doc/md/Development/Makefile-vs-CMake.md +++ b/doc/md/Development/Makefile-vs-CMake.md @@ -1,6 +1,21 @@ # Makefile vs CMake + + + +# Table of Contents +- [Makefile vs CMake](#makefile-vs-cmake) +- [Table of Contents](#table-of-contents) + - [Client](#client) + - [Tools](#tools) + - [ARM](#arm) + - [Features to be used via `Makefile.platform`](#features-to-be-used-via-makefileplatform) + - [Other features](#other-features) + - [Global](#global) + + ## Client +^[Top](#top) The client can be compiled both with the historical Makefile and with a newer CMakeLists.txt. At the moment both are maintained because they don't perfectly overlap yet. @@ -74,6 +89,7 @@ At the moment both are maintained because they don't perfectly overlap yet. | libpm3 with SWIG Lua+Python| **no** | *ongoing* | cf libpm3_experiments branch | ## Tools +^[Top](#top) `makefile` only at the moment @@ -82,10 +98,12 @@ At the moment both are maintained because they don't perfectly overlap yet. | Skip GPU-dependent code | `SKIPGPU=1` | to skip ht2crack5gpu tool when compiling the hitag2crack toolsuite | ## ARM +^[Top](#top) `makefile` only at the moment -### Features to be used via `Makefile.platform`: +### Features to be used via `Makefile.platform` +^[Top](#top) `SKIP_*`, `STANDALONE` @@ -97,7 +115,8 @@ At the moment both are maintained because they don't perfectly overlap yet. | Skip LF/HF techs in the firmware | `SKIP_`*`=1` | see `common_arm/Makefile.hal` for a list | | Standalone mode choice | `STANDALONE=` | see `doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md` for a list | -### Other features: +### Other features +^[Top](#top) | Feature | Makefile | Remarks | |-----|---|---| @@ -107,5 +126,6 @@ At the moment both are maintained because they don't perfectly overlap yet. | Tag firmware image | `FWTAG=` | for maintainers | ## Global +^[Top](#top) `makefile` only at the moment diff --git a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md index ef8e735c7..e9e17005b 100644 --- a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md @@ -1,4 +1,27 @@ + + +# Linux Installation Instructions + +# Table of Contents +- [Linux Installation Instructions](#linux-installation-instructions) +- [Table of Contents](#table-of-contents) +- [External resources](#external-resources) +- [Install the required dependencies](#install-the-required-dependencies) + - [On Debian / Ubuntu / Kali / ParrotOS / Raspbian](#on-debian--ubuntu--kali--parrotos--raspbian) + - [On ArchLinux](#on-archlinux) + - [On Fedora](#on-fedora) + - [On openSUSE](#on-opensuse) +- [Clone the RRG/Iceman repository](#clone-the-rrgiceman-repository) +- [Check ModemManager](#check-modemmanager) + - [⚠️ Very important ⚠️](#️-very-important-️) +- [Check connection](#check-connection) +- [Get permissions to use /dev/ttyACM0](#get-permissions-to-use-devttyacm0) +- [Compile and use the project](#compile-and-use-the-project) + + + # External resources +^[Top](#top) You might want to follow one of these external resources to get an overview, but please still read carefully this page as some instructions may have evolved. @@ -12,8 +35,10 @@ You might want to follow one of these external resources to get an overview, but # Install the required dependencies +^[Top](#top) ## On Debian / Ubuntu / Kali / ParrotOS / Raspbian +^[Top](#top) First what we want to do is get an update for the system. If you need to upgrade do this **before** the install. An upgrade was carried out prior to following these instructions. @@ -37,9 +62,10 @@ If you don't need support for Python3 scripts in the Proxmark3 client, you can s If you get some (non blocking) error at runtime such as _Gtk-Message: Failed to load module "canberra-gtk-module"_ you may have to install `libcanberra-gtk-module`. ## On ArchLinux +^[Top](#top) ```sh -sudo pacman -Sy git base-devel readline bzip2 arm-none-eabi-gcc arm-none-eabi-newlib qt5-base bluez python --needed +sudo pacman -Syu git base-devel readline bzip2 arm-none-eabi-gcc arm-none-eabi-newlib qt5-base bluez python --needed ``` If you don't need the native Bluetooth support in the client, you can skip the installation of `bluez`. @@ -49,6 +75,7 @@ If you don't need the graphical components of the Proxmark3 client (such as in ` If you don't need support for Python3 scripts in the Proxmark3 client, you can skip the installation of `python`. ## On Fedora +^[Top](#top) ```sh sudo dnf install git make gcc gcc-c++ arm-none-eabi-gcc-cs arm-none-eabi-newlib readline-devel bzip2-devel qt5-qtbase-devel bluez-libs-devel python3-devel libatomic @@ -61,6 +88,7 @@ If you don't need the graphical components of the Proxmark3 client (such as in ` If you don't need support for Python3 scripts in the Proxmark3 client, you can skip the installation of `python3-devel`. ## On openSUSE +^[Top](#top) ```sh sudo zypper install git patterns-devel-base-devel_basis gcc-c++ readline-devel libbz2-devel cross-arm-none-gcc9 cross-arm-none-newlib-devel python3-devel libqt5-qtbase-devel @@ -73,18 +101,23 @@ If you don't need the graphical components of the Proxmark3 client (such as in ` If you don't need support for Python3 scripts in the Proxmark3 client, you can skip the installation of `python3-devel`. # Clone the RRG/Iceman repository +^[Top](#top) ```sh git clone https://github.com/RfidResearchGroup/proxmark3.git ``` # Check ModemManager +^[Top](#top) ### ⚠️ Very important ⚠️ +^[Top](#top) + make sure ModemManager will not interfere, otherwise it could brick your Proxmark3! Read carefully [this page about ModemManager](ModemManager-Must-Be-Discarded.md) and follow its instructions. # Check connection +^[Top](#top) Check the proxmark is being picked up by your computer. Plug it in, then: @@ -100,6 +133,7 @@ cdc_acm 2-1.2:1.0: ttyACM0: USB ACM device And a new `/dev/ttyACM0` should have appeared. # Get permissions to use /dev/ttyACM0 +^[Top](#top) Add current user to the proper group to get permission to use `/dev/ttyACM0`. @@ -118,5 +152,6 @@ To test you have the proper read & write rights, plug the Proxmark3 and execute: It must return `ok`. Otherwise this means you've got a permission problem to fix. # Compile and use the project +^[Top](#top) Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). diff --git a/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md b/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md index bdd13df49..91a2fedc4 100644 --- a/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md @@ -1,6 +1,25 @@ -# Homebrew (Mac OS X), automatic installation + + + +# Mac OS X - Homebrew automatic installation + + +# Table of Contents +- [Mac OS X - Homebrew automatic installation](#mac-os-x---homebrew-automatic-installation) +- [Table of Contents](#table-of-contents) + - [Apple Silicon (M1) Notes](#apple-silicon-m1-notes) + - [Install Proxmark3 tools](#install-proxmark3-tools) + - [Upgrade HomeBrew tap formula](#upgrade-homebrew-tap-formula) + - [Flash the BOOTROM & FULLIMAGE](#flash-the-bootrom--fullimage) + - [Run the client](#run-the-client) + - [Next steps](#next-steps) +- [Homebrew (Mac OS X), developer installation](#homebrew-mac-os-x-developer-installation) + - [Compile and use the project](#compile-and-use-the-project) + + ## Apple Silicon (M1) Notes +^[Top](#top) Ensure Rosetta 2 is installed as it's currently needed to run `arm-none-eabi-gcc` as it's delivered as a precombiled x86_64 binary. @@ -12,11 +31,13 @@ bad CPU type in executable Then you are missing Rosetta 2 and need to install it: `/usr/sbin/softwareupdate --install-rosetta` -Homebrew has changed their prefix to differentiate between native Apple Silicon and Intel compiled binaries. The Makefile attempts to account for this but please note that whichever terminal or application you're using must be running under Architecture "Apple" as seen by Activity Monitor as all child processes inherit the Rosetta 2 environment of their parent. You can check which architecture you're currently running under with a `uname -m` in your terminal. +Homebrew has changed their prefix to differentiate between native Apple Silicon and Intel compiled binaries. The Makefile attempts to account for this but please note that +whichever terminal or application you're using must be running under Architecture "Apple" as seen by Activity Monitor as all child processes inherit the Rosetta 2 environment of their parent. You can check which architecture you're currently running under with a `uname -m` in your terminal. Visual Studio Code still runs under Rosetta 2 and if you're developing for proxmark3 on an Apple Silicon Mac you might want to consider running the Insiders build which has support for running natively on Apple Silicon. ## Install Proxmark3 tools +^[Top](#top) These instructions comes from \@Chrisfu, where we got the proxmark3.rb scriptfile from. For further questions about Mac & Homebrew, contact [\@Chrisfu on Twitter](https://github.com/chrisfu/) @@ -40,6 +61,7 @@ For further questions about Mac & Homebrew, contact [\@Chrisfu on Twitter](https For more info, go to https://github.com/RfidResearchGroup/homebrew-proxmark3 ## Upgrade HomeBrew tap formula +^[Top](#top) *This method is useful for those looking to run bleeding-edge versions of RRG/iceman's client. Keep this in mind when attempting to update your HomeBrew tap formula as this procedure could easily cause a build to break if an update is unstable on macOS.* @@ -54,6 +76,7 @@ brew upgrade --fetch-HEAD proxmark3 ``` ## Flash the BOOTROM & FULLIMAGE +^[Top](#top) With your Proxmark3 unplugged from your machine, press and hold the button on your Proxmark3 as you plug it into a USB port. You can release the button, two of the four LEDs should stay on. You're in bootloader mode, ready for the next step. In case the two LEDs don't stay on when you're releasing the button, you've an old bootloader, start over and keep the button pressed during the whole flashing procedure. @@ -73,6 +96,7 @@ proxmark3 /dev/tty.usbmodemiceman1 --flash --unlock-bootloader --image /usr/loca ## Run the client +^[Top](#top) ```sh pm3 @@ -85,6 +109,7 @@ proxmark3 /dev/tty.usbmodemiceman1 ``` ## Next steps +^[Top](#top) For the next steps, please read the following pages: @@ -96,6 +121,7 @@ For the next steps, please read the following pages: # Homebrew (Mac OS X), developer installation +^[Top](#top) These instructions will show how to setup the environment on OSX to the point where you'll be able to clone and compile the repo by yourself, as on Linux, Windows, etc. @@ -115,6 +141,7 @@ brew install astyle ## Compile and use the project +^[Top](#top) To use the compiled client, the only difference is that the Proxmark3 port is `/dev/tty.usbmodemiceman1`, so commands become: diff --git a/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md b/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md index 6fb66b6e0..94294296e 100644 --- a/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Mac-OS-X-MacPorts-Installation-Instructions.md @@ -1,8 +1,22 @@ -# MacPorts (Mac OS X) + + +# Mac OS X - MacPorts automatic installation

These insturctions won't work on Apple Silicon yet!

An arm64 native build of arm-none-eabi-gcc is still not available (as of 2021-11-26).
+# Table of Contents +- [Mac OS X - MacPorts automatic installation](#mac-os-x---macports-automatic-installation) +- [Table of Contents](#table-of-contents) + - [Main prerequisite](#main-prerequisite) + - [Installing latest releases](#installing-latest-releases) + - [Build from source](#build-from-source) + - [Compile and use the project](#compile-and-use-the-project) + + + + ## Main prerequisite +^[Top](#top) 1. Have MacPorts installed. Visit https://www.macports.org/ for more information. @@ -24,12 +38,14 @@ ``` ## Installing latest releases +^[Top](#top) Packaging for latest releases are available on MacPorts with the port name `proxmark3-iceman`, with a variant for PM3GENERIC firmwares available as `+pm3generic`. Installing is as simple as `sudo port install proxmark3-iceman` and if you want to install for PM3GENERIC, you can run `sudo port install proxmark3-iceman +pm3generic` instead. ## Build from source +^[Top](#top) These instructions will show how to setup the environment on OSX to the point where you'll be able to clone and compile the repo by yourself, as on Linux, Windows, etc. @@ -72,6 +88,7 @@ These instructions will show how to setup the environment on OSX to the point wh ## Compile and use the project +^[Top](#top) Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). diff --git a/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md b/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md index 7025da4d3..17bce5cbf 100644 --- a/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md +++ b/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md @@ -1,4 +1,24 @@ + + + +# Modem Manager must be discarded + + +# Table of Contents +- [Modem Manager must be discarded](#modem-manager-must-be-discarded) +- [Table of Contents](#table-of-contents) +- [If you're a Linux user](#if-youre-a-linux-user) +- [Solution 1: remove ModemManager](#solution-1-remove-modemmanager) +- [Solution 2: disable ModemManager](#solution-2-disable-modemmanager) +- [Solution 3: use filtering udev rules](#solution-3-use-filtering-udev-rules) +- [Solution 4: use global ttyACM filtering rule](#solution-4-use-global-ttyacm-filtering-rule) +- [Testing ModemManager filtering effectiveness](#testing-modemmanager-filtering-effectiveness) +- [I didn't read carefully this page and now my Proxmark3 is not responding](#i-didnt-read-carefully-this-page-and-now-my-proxmark3-is-not-responding) + - [Only the fullimage is damaged](#only-the-fullimage-is-damaged) + - [The bootloader is damaged](#the-bootloader-is-damaged) + # If you're a Linux user +^[Top](#top) ModemManager is a real threat that can lead to a bricked Proxmark3, read this very attentively. @@ -14,6 +34,7 @@ Yes it makes the flashing failing. And if it happens while you're flashing the b ModemManager is a threat for the Proxmark3, but also for many other embedded devices, such as some Arduino platforms. # Solution 1: remove ModemManager +^[Top](#top) If you don't need ModemManager, the safest is to remove it entirely. @@ -27,6 +48,7 @@ sudo pacman -R modemmanager ``` # Solution 2: disable ModemManager +^[Top](#top) ```sh sudo systemctl stop ModemManager @@ -34,6 +56,7 @@ sudo systemctl disable ModemManager ``` # Solution 3: use filtering udev rules +^[Top](#top) If you *really* need ModemManager, e.g. for your 4G device, you'll have to use some filtering rules to make sure it doesn't interfere with the Proxmark3. @@ -59,6 +82,7 @@ If it's using `filter-policy=strict`, either look at [solution 4](#solution-4-us In any case, it's very important that you test if the filtering is effective before attempting to flash your Proxmark3, see section [Testing ModemManager filtering effectiveness](#Testing-ModemManager-filtering-effectiveness). # Solution 4: use global ttyACM filtering rule +^[Top](#top) Edit the system ModemManager configuration: ```sh @@ -77,6 +101,7 @@ sudo service ModemManager restart It's very important that you test if the filtering is effective before attempting to flash your Proxmark3, see section [Testing ModemManager filtering effectiveness](#Testing-ModemManager-filtering-effectiveness). # Testing ModemManager filtering effectiveness +^[Top](#top) If you chose to keep ModemManager, test the filtering effectiveness before attempting to flash Proxmark3. @@ -107,12 +132,14 @@ sudo mmcli -G ERR ``` # I didn't read carefully this page and now my Proxmark3 is not responding +^[Top](#top) First of all, follow the instructions above to make sure ModemManager will not interfere with the Proxmark3 anymore. Now there are two possibilities: ## Only the fullimage is damaged +^[Top](#top) If the flashing of the fullimage failed, you can still force the Proxmark to start in bootloader mode by keeping the button pressed while you're plugging it in and while you're attempting to flash it again. @@ -126,7 +153,9 @@ In short: * release button * un/plug device + ## The bootloader is damaged +^[Top](#top) If attempting to flash via the button fails, this means your bootloader is corrupted. You'll have no other choice than flashing it via an external JTAG instrument. diff --git a/doc/md/Installation_Instructions/Troubleshooting.md b/doc/md/Installation_Instructions/Troubleshooting.md index 9f8e91dfd..141d62b41 100644 --- a/doc/md/Installation_Instructions/Troubleshooting.md +++ b/doc/md/Installation_Instructions/Troubleshooting.md @@ -1,6 +1,6 @@ -# Troubleshooting guide + -## First of all +# Troubleshooting guide Always use the latest repository commits from *master* branch. There are always many fixes done almost daily. @@ -43,8 +43,10 @@ Note that with the Bluetooth adapter, you *have to* use directly the client, and * [Bluetooth](/doc/bt_manual_v10.md) ## My Proxmark3 seems bricked +^[Top](#top) ### Maybe just a false alarm? +^[Top](#top) The flasher refused to flash your Proxmark3? Are there any messages in *red*? The most common reason is that the Proxmark3 RDV4 firmware recently got a new bootloader able to handle larger firmwares and... the image grew over 256k almost at the same time. So your old bootloader can't flash such new images. But it's easy, you just need to flash *first* the bootloader *only*, then the image. @@ -59,12 +61,14 @@ proxmark3 --flash --image armsrc/obj/fullimage.elf ``` ### Find out why it would be bricked +^[Top](#top) The most common reason of a flashing failure is the interference of ModemManager, read carefully [how to avoid ModemManager-related issues](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md) and fix your setup! Another possibility is if, when using the button for entering bootloader mode, the button was released during flashing (for old bootloaders) or the button was pressed again during flashing (for newer bootloaders). ### Determine if the bootloader was damaged or only the main OS image +^[Top](#top) Unplug, press the Proxmark3 button and keep it pressed when you plug it on USB. If the red LEDs show a "off/on/off/on" pattern, you're good, you manually entered into the bootloader mode. On new bootloaders, you can release the button. If the pattern disappears, you're on an older bootloader and you've to do it again and keep the button pressed during all the flashing operation. @@ -90,12 +94,14 @@ proxmark3 --flash --unlock-bootloader --image bootrom/obj/bootr ``` ### Ok, my bootloader is definitively dead, now what? +^[Top](#top) At this point, only reflashing via JTAG can revive your Proxmark3. See [details here](/doc/jtag_notes.md). ## Slow to boot or difficulties to enumerate the device over USB +^[Top](#top) You're using another Proxmark3 than a RDV4? The RDV4 firmware can run on other Proxmark3 as such but the booting procedure is a bit slower because of the absence of SIM and external flash. @@ -103,16 +109,19 @@ Make sure to configure properly your `Makefile.platform` to get a firmware bette See [details here](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md). ## Troubles with SIM card reader +^[Top](#top) (RDV4 only) Make sure you've the latest SIM firmware according to the [configuration documentation](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md#verify-sim-module-firmware-version). ## Troubles with t5577 commands or MFC/iClass/T55x7 dictionaries +^[Top](#top) (RDV4 only) Make sure you've set everything up according to the [configuration documentation](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md#first-things-on-your-rdv40). Instructions evolve over time so check if you're still up to date! ## File not found +^[Top](#top) If Proxmark3 has been installed with `make install` or packaged for your distro, the binaries should be in your path and you can call them directly: @@ -161,16 +170,20 @@ pm3 --> smart upgrade -f sim011.bin etc. ## Pixmap / pixbuf warnings +^[Top](#top) If you get warnings related to pixmap or pixbuf such as *Pixbuf theme: Cannot load pixmap file* or *Invalid borders specified for theme pixmap*, it's a problem of your Theme, try another one and the problem should vanish. See e.g. [#354](https://github.com/RfidResearchGroup/proxmark3/issues/354) (Yaru theme on Ubuntu) and [#386](https://github.com/RfidResearchGroup/proxmark3/issues/386) (Kali-X theme on Kali). ## Usb cable +^[Top](#top) It's needed to have a good USB cable to connect Proxmark3 to USB. If you have stability problems (Proxmark3 resets, firmware hangs, especially firmware hangs just after start, etc.) - check your cable with a USB tester (or try to change it). It needs to have a resistance smaller or equal to 0.3 Ohm. ## WSL +^[Top](#top) + When ```explorer.exe .``` doesn't work. Trying to access the dump files created in WSL, you will need to run ```explorer.exe .``` but sometimes this doesn't work. [As seen here](https://github.com/microsoft/WSL/issues/4027) they suggest checking the following registry value for *P9NP* @@ -178,11 +191,15 @@ Trying to access the dump files created in WSL, you will need to run ```explore [![screenshot of regedit](/doc/md/Installation_Instructions/wsl2_p9np.png)](/doc/md/Installation_Instructions/wsl2_p9np.png) ## Troubles with running the Proxmark3 client +^[Top](#top) + Some reports has stated that they needed to execute the Proxmark3 as root on their *nix system. Try running it with `sudo ./pm3` ## libQt5Core.so.5 not found +^[Top](#top) + On WSL1 / updated to Ubuntu 20.04, there is a slight chance you experience problems when compiling the repo with QT5. The following steps is needed to make the development environment happy again. ``` @@ -191,6 +208,8 @@ sudo strip --remove-section=.note.ABI-tag /usr/lib/x86_64-linux-gnu/libQt5Core.s ``` ## target attribute is not supported on this machine +^[Top](#top) + If you get the message ```error: target attribute is not supported on this machine [-Werror=attributes]``` when trying to compile, its because you have an older arm-none-eabi tool chain. @@ -224,6 +243,8 @@ ticks.h:26:1: error: target attribute is not supported on this machine [-Werror= ``` ## Qt Session management error +^[Top](#top) + If you get the message ``` diff --git a/doc/md/Installation_Instructions/VSCode-Installation-Instructions.md b/doc/md/Installation_Instructions/VSCode-Installation-Instructions.md index 079f301f6..482b52af1 100644 --- a/doc/md/Installation_Instructions/VSCode-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/VSCode-Installation-Instructions.md @@ -1,4 +1,19 @@ + + +# Visual Studio Code Installation Instructions + +# Table of Contents +- [Visual Studio Code Installation Instructions](#visual-studio-code-installation-instructions) +- [Table of Contents](#table-of-contents) +- [Visual Studio Code for debugging](#visual-studio-code-for-debugging) + - [Debian / Ubuntu / Kali / ParrotOS / Raspbian](#debian--ubuntu--kali--parrotos--raspbian) + - [Windows: WSL](#windows-wsl) + - [Windows: ProxSpace](#windows-proxspace) + + + # Visual Studio Code for debugging +^[Top](#top) Download and install [Visual Studio Code](https://code.visualstudio.com/) @@ -6,6 +21,7 @@ Download and install [J-Link Software and Documentation pack](https://www.segger ## Debian / Ubuntu / Kali / ParrotOS / Raspbian +^[Top](#top) Install dependencies @@ -27,6 +43,7 @@ now launch Visual Studio Code and open your project folder ## Windows: WSL +^[Top](#top) Enter WSL prompt (`wsl` or `start windows terminal`) @@ -52,6 +69,7 @@ code . ## Windows: ProxSpace +^[Top](#top) Download and install [Visual Studio Code](https://code.visualstudio.com/) diff --git a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md index 6430b2bc2..f46a41cb6 100644 --- a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md @@ -1,11 +1,30 @@ -# Installing on Windows -## Table of Contents +# Windows Installation instructions + + +## Table of Contents +- [Windows Installation instructions](#windows-installation-instructions) + - [Table of Contents](#table-of-contents) + - [Installing dev-environment with ProxSpace](#installing-dev-environment-with-proxspace) + - [Video Installation guide](#video-installation-guide) + - [Driver Installation ( Windows 7 )](#driver-installation--windows-7-) + - [Download ProxSpace repo](#download-proxspace-repo) + - [Launch ProxSpace](#launch-proxspace) + - [Clone the RRG/Iceman repository](#clone-the-rrgiceman-repository) + - [Compile and use the project](#compile-and-use-the-project) + - [Done!](#done) +- [Installing pre-compiled binaries with ProxSpace](#installing-pre-compiled-binaries-with-proxspace) +- [Installing dev-environment with WSL 1](#installing-dev-environment-with-wsl-1) + - [Stay away from WSL 2](#stay-away-from-wsl-2) + - [More about WSL](#more-about-wsl) + - [X Server Installation](#x-server-installation) + - [Windows Terminal Installation](#windows-terminal-installation) + - [Dependencies](#dependencies) + - [Clone the RRG/Iceman repository](#clone-the-rrgiceman-repository-1) + - [Compile and use the project](#compile-and-use-the-project-1) + - [Done!](#done-1) - * [Installing dev-environment with ProxSpace](#installing-dev-environment-with-proxspace) - * [Installing pre-compiled binaries with ProxSpace](#installing-pre-compiled-binaries-with-proxspace) - * [Installing dev-environment with WSL 1](#installing-dev-environment-with-wsl-1) There are two ways to install, build and use Proxmark3 on Windows: @@ -20,10 +39,13 @@ We have listed three ways to use these two setups (dev environment vs pre-compi ^[Top](#top) ## Video Installation guide +^[Top](#top) + _note: this video is out-of-date but still informative_ [![Windows Installation tutorial](https://raw.githubusercontent.com/Chrissy-Morgan/Proxmark3-RDV4-ParrotOS/master/screenshot-www.youtube.com-2019.03.17-20-44-33.png)](https://youtu.be/zzF0NCMJnYU "Windows Installation Tutorial") ## Driver Installation ( Windows 7 ) +^[Top](#top) _note: for Windows 7 you will this step. On a later Windows edition skip this._ @@ -31,6 +53,7 @@ Install required drivers for your Windows installation. You may need admin privi Step by step guides are online such as [RyscCorps](https://store.ryscc.com/blogs/news/how-to-install-a-proxmark3-driver-on-windows-10). ## Download ProxSpace repo +^[Top](#top) Download the Gator96100 ProxSpace package from https://github.com/Gator96100/ProxSpace/releases @@ -50,6 +73,7 @@ C:\My Documents\My Projects\proxspace If you're running Windows in a Virtualbox guest, make sure not to install ProxSpace on a vbox shared drive. (It's ok later to move the `/pm3` subfolder to a shared drive and edit the `*.bat`) ## Launch ProxSpace +^[Top](#top) Run `runme64.bat`. @@ -58,6 +82,7 @@ You'll get a Bash prompt and your home directory should become the ProxSpace `pm Please note you will need to use `/` in paths as you are using Bash. ## Clone the RRG/Iceman repository +^[Top](#top) ```sh cd @@ -72,10 +97,12 @@ pacman -S mingw-w64-x86_64-astyle ``` ## Compile and use the project +^[Top](#top) To use the compiled client, the only differences are that executables end with `.exe` (e.g. `proxmark3.exe`) and that the Proxmark3 port is one of your `comX` ports where "X" is the com port number assigned to proxmark3 under Windows, so commands like `proxmark3 /dev/ttyACMX` become `proxmark3.exe comX`. ## Done! +^[Top](#top) Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). @@ -96,9 +123,13 @@ It has excellent instructions to follow. WSL 1 requires to run on Windows 10 version 1709 or above. Previous windows versions didn't have support for COM ports. ### Stay away from WSL 2 +^[Top](#top) + *Microsoft introduced WSL 2 starting on Windows 10 version 2004 with Hyper-V powering its virtualization; As of 2020-08-13, WSL 2 does not support USB and Serial.* ### More about WSL +^[Top](#top) + Install WSL 1 with e.g. the standard Ubuntu. You can follow the guide on [Microsoft Docs](https://docs.microsoft.com/en-us/windows/wsl/install-win10) but be careful to follow WSL 1 specific instructions! When they recommend you to restart, you must restart. For WSL configuration, see [Manage and configure Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/wsl-config). @@ -106,6 +137,7 @@ For WSL configuration, see [Manage and configure Windows Subsystem for Linux](ht Make sure your WSL can launch Windows processes to get the `pm3` scripts working (cf `interop` in the WSL settings). ## X Server Installation +^[Top](#top) If you want to run the graphical components of the Proxmark3 client, you need to install a X Server such as in the list below, and launch it, e.g. by executing XLaunch. * [VcXsrv](https://sourceforge.net/projects/vcxsrv/) @@ -113,11 +145,14 @@ If you want to run the graphical components of the Proxmark3 client, you need to ## Windows Terminal Installation +^[Top](#top) + Microsoft has recently released a new terminal for their OS. It is much better experience than old `cmd.exe` so we strongly recommend installing it. It is also open sourced (see [github.com/microsoft/terminal](https://github.com/microsoft/terminal)). You can download and install from [GitHub](https://github.com/microsoft/terminal/releases/latest) or [Microsoft Store](https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701). ## Dependencies +^[Top](#top) Enter WSL prompt (`wsl` or Start Windows Terminal with `wt`) and from there, follow the [Linux Installation Instructions](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) for Ubuntu, summarized here below: @@ -140,12 +175,14 @@ If you don't need the graphical components of the Proxmark3 client, you can skip If you don't need support for Python3 scripts in the Proxmark3 client, you can skip the installation of `libpython3-dev`. ## Clone the RRG/Iceman repository +^[Top](#top) ```sh git clone https://github.com/RfidResearchGroup/proxmark3.git ``` ## Compile and use the project +^[Top](#top) To use the compiled client, the only difference is that the Proxmark3 port is translated from your `comX` port where **"X"** is the com port number assigned to proxmark3 under Windows, to a `/dev/ttySX`, so commands become: @@ -181,6 +218,7 @@ echo "export DISPLAY=:0" >> ~/.bashrc Note that it may take a quite long time for a freshly plugged Proxmark3 to be visible on a WSL /dev/ttySX port. ## Done! +^[Top](#top) Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md). diff --git a/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md b/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md index 9ac9472ea..f15d74f3d 100644 --- a/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md +++ b/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md @@ -1,6 +1,25 @@ + + # Compilation instructions +# Table of Contents +- [Compilation instructions](#compilation-instructions) +- [Table of Contents](#table-of-contents) + - [Tuning compilation parameters](#tuning-compilation-parameters) + - [Compile for Proxmark3 RDV4](#compile-for-proxmark3-rdv4) + - [Compile for generic Proxmark3 platforms](#compile-for-generic-proxmark3-platforms) + - [Get the latest commits](#get-the-latest-commits) + - [Clean and compile everything](#clean-and-compile-everything) + - [if you got an error](#if-you-got-an-error) + - [Install](#install) + - [Flash the BOOTROM & FULLIMAGE](#flash-the-bootrom--fullimage) + - [Run the client](#run-the-client) + - [Next steps](#next-steps) + + + ## Tuning compilation parameters +^[Top](#top) The client and the Proxmark3 firmware should always be in sync. Nevertheless, the firmware can be tuned depending on the Proxmark3 platform and options. @@ -10,13 +29,18 @@ Indeed, the RRG/Iceman fork can be used on other Proxmark3 hardware platforms as Via some definitions, you can adjust the firmware for a given platform, but also to add features like the support of the Blue Shark add-on or to select which standalone mode to embed. To learn how to adjust the firmware, please read [Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md). ### Compile for Proxmark3 RDV4 +^[Top](#top) + The repo defaults for compiling a firmware and client suitable for Proxmark3 RDV4. ### Compile for generic Proxmark3 platforms +^[Top](#top) + In order to build this repo for generic Proxmark3 platforms we urge you to read [Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md) ## Get the latest commits +^[Top](#top) ```sh cd proxmark3 @@ -24,12 +48,15 @@ git pull ``` ## Clean and compile everything +^[Top](#top) ```sh make clean && make -j ``` ### if you got an error +^[Top](#top) + Read the [troubleshooting guide](/doc/md/Installation_Instructions/Troubleshooting.md), For instance, on WSl-1 you usually get the `libQt5Core.so.5 not found` message @@ -37,6 +64,7 @@ For instance, on WSl-1 you usually get the `libQt5Core.so.5 not found` message ## Install +^[Top](#top) This is an optional step. If you do @@ -51,6 +79,7 @@ The commands given in the documentation assume you did the installation step. If e.g. calling `./pm3` or `client/proxmark3` instead of just `pm3` or `proxmark3`. ## Flash the BOOTROM & FULLIMAGE +^[Top](#top) In most cases, you can run the following script which try to auto-detect the port to use, on several OS: @@ -77,6 +106,7 @@ proxmark3 /dev/ttyACM0 --flash --unlock-bootloader --image /tmp/my-bootrom.elf - ``` ## Run the client +^[Top](#top) In most cases, you can run the script `pm3` which try to auto-detect the port to use, on several OS. ```sh @@ -98,6 +128,7 @@ client/proxmark3 /dev/ttyACM0 ``` ## Next steps +^[Top](#top) For the next steps, please read the following pages: diff --git a/doc/md/Use_of_Proxmark/1_Validation.md b/doc/md/Use_of_Proxmark/1_Validation.md index 7e75a12c3..01669c01b 100644 --- a/doc/md/Use_of_Proxmark/1_Validation.md +++ b/doc/md/Use_of_Proxmark/1_Validation.md @@ -1,4 +1,16 @@ -## 1. Validating proxmark client functionality + + +# 1. Validating Proxmark3 client functionality + +# Table of Contents +- [1. Validating Proxmark3 client functionality](#1-validating-proxmark3-client-functionality) +- [Table of Contents](#table-of-contents) + - [To get interactive help](#to-get-interactive-help) + - [First tests](#first-tests) + - [To quit the client](#to-quit-the-client) + - [Next steps](#next-steps) + + If all went well you should get some information about the firmware and memory usage as well as the prompt, something like this. @@ -55,10 +67,12 @@ This `[usb] pm3 --> ` is the Proxmark3 interactive prompt. ### To get interactive help +^[Top](#top) For basic help type `help`. Or for help on a set of sub commands type the command followed by `help`. For example `hf mf help`. ### First tests +^[Top](#top) These commands will return some info about your Proxmark software and hardware status. ``` @@ -70,12 +84,15 @@ These commands will return some info about your Proxmark software and hardware s You are now ready to use your newly flashed proxmark3 device. Many commands uses the `h` parameter to show a help text. ### To quit the client +^[Top](#top) + ``` [usb] pm3 --> quit ``` or simple press `CTRL-D`. ## Next steps +^[Top](#top) Some configuration steps are still needed. diff --git a/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md b/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md index 8ed9adf2b..175561062 100644 --- a/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md +++ b/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md @@ -1,4 +1,18 @@ + + +# 2. Configuration and Verification + +# Table of Contents +- [2. Configuration and Verification](#2-configuration-and-verification) +- [Table of Contents](#table-of-contents) + - [First things on your Proxmark3 RDV4](#first-things-on-your-proxmark3-rdv4) + - [Verify sim module firmware version](#verify-sim-module-firmware-version) + - [Next steps](#next-steps) + + + ### First things on your Proxmark3 RDV4 +^[Top](#top) You will need to run these commands to make sure your RDV4 is prepared ``` @@ -22,6 +36,7 @@ Set all t55xx settings to defaults (will set all 4 at once) ### Verify sim module firmware version +^[Top](#top) To make sure you got the latest sim module firmware. @@ -91,6 +106,7 @@ Run hw status command to verify that the upgrade went well. ``` ## Next steps +^[Top](#top) For the next steps, please read the following page: diff --git a/doc/md/Use_of_Proxmark/3_Commands-and-Features.md b/doc/md/Use_of_Proxmark/3_Commands-and-Features.md index 59be59127..373a24ab4 100644 --- a/doc/md/Use_of_Proxmark/3_Commands-and-Features.md +++ b/doc/md/Use_of_Proxmark/3_Commands-and-Features.md @@ -1,5 +1,15 @@ + + +# 3. Commands and Features + +# Table of Contents +- [3. Commands and Features](#3-commands-and-features) +- [Table of Contents](#table-of-contents) + - [To get interactive help](#to-get-interactive-help) + - [New Features in RDV4](#new-features-in-rdv4) + - [Useful commands](#useful-commands) + -# Commands and Features Please make sure you've gone through the following pages firstly: @@ -8,14 +18,17 @@ Please make sure you've gone through the following pages firstly: * [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md) ## To get interactive help +^[Top](#top) As seen before, for basic help type `help`. Or for help on a set of sub commands type the command followed by `help`. For example `hf mf help`. Many commands uses the `-h` / `--help` parameter to show a help text. ## New Features in RDV4 +^[Top](#top) Further details coming soon ## Useful commands +^[Top](#top) Here are some commands to start off with. diff --git a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md index 920974c51..150ad762a 100644 --- a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md +++ b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md @@ -1,4 +1,19 @@ -# Advanced compilation parameters + + +# 4. Advanced compilation parameters + +# Table of Contents +- [4. Advanced compilation parameters](#4-advanced-compilation-parameters) +- [Table of Contents](#table-of-contents) + - [Client](#client) + - [Firmware](#firmware) + - [PLATFORM](#platform) + - [PLATFORM_EXTRAS](#platform_extras) + - [STANDALONE](#standalone) + - [256kb versions](#256kb-versions) + - [Next step](#next-step) + + The client and the Proxmark3 firmware should always be in sync. Nevertheless, the firmware can be tuned depending on the Proxmark3 platform and options. @@ -7,7 +22,10 @@ Indeed, the RRG/Iceman fork can be used on other Proxmark3 hardware platforms as Via some definitions, you can adjust the firmware for a given platform, but also to add features like the support of the Blue Shark add-on or to select which standalone mode to embed. + + ## Client +^[Top](#top) The client doesn't depend on the capabilities of the Proxmark3 it's connected to. So you can use the same client for different Proxmark3 platforms, given that everything is running the same version. @@ -28,6 +46,7 @@ make SKIPBT=1 ## Firmware +^[Top](#top) By default, the firmware is of course tuned for the Proxmark3 RDV4 device, which has built-in support for 256kb onboard flash SPI memory, Sim module (smart card support), FPC connector. These features make it very different from all other Proxmark3 devices, there is non other like this one. @@ -38,6 +57,7 @@ If you need to tune things and save the configuration, create a file `Makefile.p For an up-to-date exhaustive list of options, you can run `make PLATFORM=`. ## PLATFORM +^[Top](#top) Here are the supported values you can assign to `PLATFORM` in `Makefile.platform`: @@ -58,6 +78,7 @@ Known issues: * Proxmark Pro: it has different fpga and unknown pin assignments. Unsupported. ## PLATFORM_EXTRAS +^[Top](#top) Here are the supported values you can assign to `PLATFORM_EXTRAS` in `Makefile.platform`: @@ -71,6 +92,7 @@ If you have installed a Blue Shark add-on on your RDV4, define `PLATFORM_EXTRAS= ## STANDALONE +^[Top](#top) The RRG/Iceman repository gives you to easily choose which standalone mode to embed in the firmware. @@ -109,6 +131,7 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo By default `STANDALONE=LF_SAMYRUN`. ## 256kb versions +^[Top](#top) If you own a Proxmark3 Easy with only 256kb, you can use a few definitions to help you getting a smaller firmware. @@ -154,5 +177,6 @@ Situation might change when the firmware is growing of course, requiring to skip Last note: if you skip a tech, be careful not to use a standalone mode which requires that same tech, else the firmware size reduction won't be much. ## Next step +^[Top](#top) See [Compilation instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md) diff --git a/doc/mfu_binary_format_notes.md b/doc/mfu_binary_format_notes.md index 85935160b..a368265e6 100644 --- a/doc/mfu_binary_format_notes.md +++ b/doc/mfu_binary_format_notes.md @@ -1,11 +1,20 @@ # Notes on MFU binary formats + + + +# Table of Contents +- [Notes on MFU binary formats](#notes-on-mfu-binary-formats) +- [Table of Contents](#table-of-contents) + - [New mfu format](#new-mfu-format) + - [Old mfu format](#old-mfu-format) + - [Plain mfu format](#plain-mfu-format) + - [future mfu format](#future-mfu-format) + - - new mfu format - - old mfu format - - plain mfu format - - future mfu format ## New mfu format +^[Top](#top) + The new mfu binary format was created to compensate for different manufactures tag functions. Like UL-Ev1 has three counter and tearing bytes, while NTAG only has one counter and tearing byte. PACK was removed from header, since its just normally part of the tag memory, unreadable, but when @@ -29,6 +38,8 @@ typedef struct { ``` ## Old mfu format +^[Top](#top) + The old binary format saved the extra data on tag in order for the Proxmark3 to able to simulate a real tag. ``` @@ -47,6 +58,8 @@ typedef struct { ``` ## Plain mfu format +^[Top](#top) + The first binary format for MFU was just a memory dump from the tag block 0 to end. No extra data was saved. ``` @@ -54,6 +67,8 @@ No extra data was saved. ``` ## future mfu format +^[Top](#top) + For developers of apps and other tools, like libnfc, we don't recommend using binary formats. We decided to adopt a JSON based format, which is much more flexible to changes of new tag functionality. diff --git a/doc/new_frame_format.md b/doc/new_frame_format.md index c5e7d542d..73c6faabb 100644 --- a/doc/new_frame_format.md +++ b/doc/new_frame_format.md @@ -1,11 +1,35 @@ # New frame format documentation + This document is primarily intended for developers only. A major change is the support of variable length frames between host and Proxmark3. This is a step especially important for usage over FPC/USART/BT. + +# Table of Contents +- [New frame format documentation](#new-frame-format-documentation) +- [Table of Contents](#table-of-contents) + - [Old format](#old-format) + - [New format](#new-format) + - [Transition](#transition) + - [New format API](#new-format-api) + - [On the client, for sending frames](#on-the-client-for-sending-frames) + - [On the Proxmark3, for receiving frames](#on-the-proxmark3-for-receiving-frames) + - [On the Proxmark3, for sending frames](#on-the-proxmark3-for-sending-frames) + - [On the client, for receiving frames](#on-the-client-for-receiving-frames) + - [API transition](#api-transition) + - [Bootrom](#bootrom) + - [On the Proxmark3, for receiving frames](#on-the-proxmark3-for-receiving-frames-1) + - [On the Proxmark3, for sending frames](#on-the-proxmark3-for-sending-frames-1) + - [On the client, for sending frames](#on-the-client-for-sending-frames-1) + - [On the client, for receiving frames](#on-the-client-for-receiving-frames-1) + - [New usart RX FIFO](#new-usart-rx-fifo) + - [Timings](#timings) + - [Reference frames](#reference-frames) + ## Old format +^[Top](#top) Previously, frames were, in both directions like this: @@ -21,6 +45,7 @@ So the frame size was fixed, 544 bytes, even for simple ACKs. When snooping the USB transfers, we can observe the host is sending 544b Bulk USB frames while the Proxmark3 is limited by its internal buffers and is sending 128b, 128b, 128b, 128b, 32b, so in total 5 packets. ## New format +^[Top](#top) Even if we make the payload part variable in the old format, we've still a minimum of 32 bytes per frame with fields arbitrarily large. So we designed a new format from scratch: @@ -74,10 +99,12 @@ Internal structures used to handle these packets are: But they are abstracted from the developer view with a new API. See below. ## Transition +^[Top](#top) Because it's a long transition to clean all the code from the old format and because we don't want to break stuffs when flashing the bootloader, the old frames are still supported together with the new frames. The old structure is now called `PacketCommandOLD` and `PacketResponseOLD` and it's also abstracted from the developer view with the new API. ## New format API +^[Top](#top) So the new API is a merge of the old and the new frame formats, to ensure a smooth transition. @@ -114,7 +141,8 @@ After the full transition, we might remove the fields `oldarg` and `ng`. } PacketResponseNG; -### On the client, for sending frames: +### On the client, for sending frames +^[Top](#top) (`client/comms.c`) @@ -132,7 +160,8 @@ Warning : it makes sense to move from `SendCommandOLD` to `SendCommandMIX` only Internally these functions prepare the new or old frames and call `uart_communication` which calls `uart_send`. -### On the Proxmark3, for receiving frames: +### On the Proxmark3, for receiving frames +^[Top](#top) (`armsrc/appmain.c`) @@ -143,7 +172,8 @@ Internally these functions prepare the new or old frames and call `uart_communic `PacketReceive` is the commands broker. Old handlers will still find their stuff in `PacketCommandNG.oldarg` field. -### On the Proxmark3, for sending frames: +### On the Proxmark3, for sending frames +^[Top](#top) (`common/cmd.c`) @@ -163,7 +193,8 @@ Example of a handler that supports both OLD/MIX and NG command styles and replie reply_mix(CMD_ACK, 0, 0, 0, packet->data.asBytes, packet->length); } -### On the client, for receiving frames: +### On the client, for receiving frames +^[Top](#top) (`client/comms.c`) @@ -174,6 +205,7 @@ Example of a handler that supports both OLD/MIX and NG command styles and replie Commands do `WaitForResponseTimeoutW` (or `dl_it`) which uses `getReply` to fetch responses. ## API transition +^[Top](#top) In short, to move from one format to the other, we need for each command: @@ -188,6 +220,7 @@ Meanwhile, a fast transition to MIX frames can be done with: * (pm3 TX) `reply_old` ⇒ `reply_mix` (but check the limited data size PM3_CMD_DATA_SIZE ⇒ PM3_CMD_DATA_SIZE_MIX) ## Bootrom +^[Top](#top) Bootrom code will still use the old frame format to remain compatible with other repos supporting the old format and because it would hardly gain anything from the new format: * almost all frames convey 512b of payload, so difference in overhead is negligible @@ -195,7 +228,8 @@ Bootrom code will still use the old frame format to remain compatible with other `SendCommandBL` is the same as `SendCommandOLD` with a different name to be sure not to migrate it. -### On the Proxmark3, for receiving frames: +### On the Proxmark3, for receiving frames +^[Top](#top) (`bootrom/bootrom.c`) @@ -204,7 +238,8 @@ Bootrom code will still use the old frame format to remain compatible with other also `usb_enable`, `usb_disable` (`common/usb_cdc.c`) -### On the Proxmark3, for sending frames: +### On the Proxmark3, for sending frames +^[Top](#top) (`bootrom/bootrom.c`) @@ -212,7 +247,8 @@ also `usb_enable`, `usb_disable` (`common/usb_cdc.c`) also `usb_enable`, `usb_disable` (`common/usb_cdc.c`) -### On the client, for sending frames: +### On the client, for sending frames +^[Top](#top) Therefore, the flasher client (`client/flasher.c` + `client/flash.c`) must still use these old frames. It uses a few commands in common with current client code: @@ -222,13 +258,15 @@ It uses a few commands in common with current client code: SendCommandOLD ⇒ CMD_DEVICE_INFO / CMD_START_FLASH / CMD_FINISH_WRITE / CMD_HARDWARE_RESET -### On the client, for receiving frames: +### On the client, for receiving frames +^[Top](#top) As usual, old frames are still supported WaitForResponseTimeout ⇒ PacketResponseNG ## New usart RX FIFO +^[Top](#top) USART code has been rewritten to cope with unknown size packets. * using USART full duplex with double DMA buffer on RX & TX @@ -264,6 +302,7 @@ USART code has been rewritten to cope with unknown size packets. * remember how many bytes we already copied to our FIFO ## Timings +^[Top](#top) Reference (before new format): @@ -416,7 +455,7 @@ Or if it's too complex to determine when we're sending the last command: ## Reference frames - +^[Top](#top) For helping debug... diff --git a/doc/path_notes.md b/doc/path_notes.md index 491f01cd0..8f0d20b88 100644 --- a/doc/path_notes.md +++ b/doc/path_notes.md @@ -1,4 +1,28 @@ -# Notes on paths. +# Notes on path + + +# Table of Contents +- [Notes on path](#notes-on-path) +- [Table of Contents](#table-of-contents) +- [Installed elements](#installed-elements) + - [Binaries](#binaries) + - [Firmwares](#firmwares) + - [Traces](#traces) + - [JTAG-related stuff](#jtag-related-stuff) + - [Proxmark3 client files: dictionaries](#proxmark3-client-files-dictionaries) + - [Proxmark3 client files: cmd scripts](#proxmark3-client-files-cmd-scripts) + - [Proxmark3 client files: Lua libraries and scripts](#proxmark3-client-files-lua-libraries-and-scripts) + - [Proxmark3 client files: various resources](#proxmark3-client-files-various-resources) + - [Documentation](#documentation) +- [User files](#user-files) + - [.history / log files](#history--log-files) + - [Proxmark3 client files and traces](#proxmark3-client-files-and-traces) +- [Searching files](#searching-files) + - [TL;DR](#tldr) + - [Gory details](#gory-details) +- [Scripts](#scripts) + - [Proxmark command script (.cmd)](#proxmark-command-script-cmd) + - [Shebangs (on *nix)](#shebangs-on-nix) With the recent (2019-09-01) changes and creation of `make install` command it is easy to get lost. @@ -6,8 +30,10 @@ With the recent (2019-09-01) changes and creation of `make install` command it If you install the Proxmark tools with `make install`, they will go under the prefix `/usr/local/` but if you install the tools from your distro, there are chances the path is `/usr` so you'll have to adapt the paths presented here. # Installed elements +^[Top](#top) ## Binaries +^[Top](#top) The main Proxmark3 executables / shellscripts will be copied to @@ -29,6 +55,7 @@ Some more executable / scripts will be copied to ## Firmwares +^[Top](#top) The recovery / firmware files will be copied to @@ -41,6 +68,7 @@ The recovery / firmware files will be copied to ## Traces +^[Top](#top) Proxmark3 client has a lot of sample trace files for many different low frequency tags. They will be copied to @@ -50,6 +78,7 @@ Proxmark3 client has a lot of sample trace files for many different low frequenc ## JTAG-related stuff +^[Top](#top) JTAG configurations and helper scripts for OpenOCD will be copied to @@ -57,6 +86,7 @@ JTAG configurations and helper scripts for OpenOCD will be copied to ## Proxmark3 client files: dictionaries +^[Top](#top) Dictionaries used by the client will be copied to @@ -76,6 +106,7 @@ if key isn't a hex number, the key is ignored. See [here](#proxmark3-client-files-and-traces) how to add your own dictionaries. ## Proxmark3 client files: cmd scripts +^[Top](#top) Cmd scripts used by the client will be copied to @@ -86,6 +117,7 @@ Cmd scripts used by the client will be copied to See [here](#proxmark3-client-files-and-traces) how to add your own cmd scripts. ## Proxmark3 client files: Lua libraries and scripts +^[Top](#top) Lua libraries and scripts used by the client will be copied to @@ -99,6 +131,7 @@ Lua libraries and scripts used by the client will be copied to See [here](#proxmark3-client-files-and-traces) how to add your own Lua scripts. ## Proxmark3 client files: various resources +^[Top](#top) Various resources used by the client will be copied to @@ -111,6 +144,7 @@ It comprises the needed files for commands like hardnested, fido, EMV, iClass. See [here](#proxmark3-client-files-and-traces) how to add your own resources. ## Documentation +^[Top](#top) Documentation will be copied to @@ -119,10 +153,12 @@ Documentation will be copied to ``` # User files +^[Top](#top) The client will make use of a personal directory `~/.proxmark3` (or more precisely `$HOME/.proxmark3`) ## .history / log files +^[Top](#top) We have now a rolling log file, created new per day. All these logfiles and the history file are now located at @@ -132,6 +168,7 @@ We have now a rolling log file, created new per day. All these logfiles and the ``` ## Proxmark3 client files and traces +^[Top](#top) If you wants to add scripts, dictionaries or other resources, you can use the same structure as the installed directory structure and add your own files there, e.g. @@ -148,10 +185,12 @@ If you add a file with the same name as the file provided with the Proxmark3 ins See also [Scripts](#scripts) on how to write your own scripts. # Searching files +^[Top](#top) With the directory structure explained above, the client applies some heuristics to find its files or the files you specified in command line. ## TL;DR +^[Top](#top) It adds the expected suffix if you didn't provide it yet, then it looks (by order of precedence): @@ -161,6 +200,7 @@ It adds the expected suffix if you didn't provide it yet, then it looks (by orde 4. in the installed directory structure, so it works when installed ## Gory details +^[Top](#top) The client is using _searchFile_ (in _client/fileutils.c_) when calling a Proxmark3 command with a filename or when the client needs to find its files. _searchFile_ takes as argument a relative path *pm3dir*, a file to search and possibly a *suffix*. @@ -177,11 +217,14 @@ When a user provides a filename (including possibly a path), _searchFile_ will s * Try to find the filename in the *pm3dir* relative to where the client binary is when in the installed configuration (*foo.dic* -> *$(path_to_dir_of_proxmark3_bin)/../share/proxmark3/dictionaries/foo.dic* which resolves to e.g. */usr/share/proxmark3/dictionaries/foo.dic* or */usr/local/share/proxmark3/dictionaries/foo.dic*), so when the client is executed from a repo workdir, filenames are searched in the expected location. # Scripts +^[Top](#top) You can provide your own lua or cmd scripts. Look at existing scripts for ideas how to create your own scripts. ### Proxmark command script (.cmd) +^[Top](#top) + For cmd scripts, the command line scripts, the client can run a text file containing Proxmark3 commands. A samplefile could be like this. @@ -210,6 +253,7 @@ You can skip the script file extension, it works equally well with. ### Shebangs (on *nix) +^[Top](#top) You can also use the magic of shebangs to make an executable script, e.g. taking the example above, we can write: diff --git a/doc/termux_notes.md b/doc/termux_notes.md index ae7207ddf..bbef0da20 100644 --- a/doc/termux_notes.md +++ b/doc/termux_notes.md @@ -1,5 +1,6 @@ - # Proxmark 3 on Android + + ## Table of Contents * [ Requirements ](#requirements) * [ Notes ](#notes) @@ -209,6 +210,7 @@ Alternatively, if you have made the client in the git repo: ^[Top](#top) #### BTADDON Missing in Firmware of PM3 +^[Top](#top) 1. Phone and pm3 are connected, blue led is on and *not* blinking 2. BTUART Tool TCP Server at Port 4321 @@ -231,4 +233,3 @@ Solution: Make sure you have installed a firmware with BTADDON compiled. See: https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md#platform_extras -ENJOY ! diff --git a/doc/trace_notes.md b/doc/trace_notes.md index 6f89cffbc..a13b209e6 100644 --- a/doc/trace_notes.md +++ b/doc/trace_notes.md @@ -1,10 +1,18 @@ - # Notes about the tracelog + -## Table of Contents - * [Command](#trace-command) - * [File format](#tracelog-format) - * [Wireshark dissector interoperability](#trace-and-wireshark) + +# Table of Contents +- [Notes about the tracelog](#notes-about-the-tracelog) +- [Table of Contents](#table-of-contents) + - [Trace command](#trace-command) + - [Timing](#timing) + - [Sources](#sources) + - [Data](#data) + - [CRC](#crc) + - [Annotation](#annotation) + - [Tracelog format](#tracelog-format) + - [Trace and Wireshark](#trace-and-wireshark) ## Trace command diff --git a/doc/uart_notes.md b/doc/uart_notes.md index 9e71c3dbf..5c8cb65b6 100644 --- a/doc/uart_notes.md +++ b/doc/uart_notes.md @@ -1,9 +1,29 @@ -# Various notes about UART and baudrates +# Notes about UART and baudrates + Proxmark3 RDV4 can interact with the client program running on a host via several means, let's go through each of them and study the notion of baudrate. +# Table of Contents +- [Notes about UART and baudrates](#notes-about-uart-and-baudrates) +- [Table of Contents](#table-of-contents) + - [USB-CDC ACM](#usb-cdc-acm) + - [Proxmark3 FPC USART](#proxmark3-fpc-usart) + - [Proxmark3 FPC USART + BT add-on (blue shark)](#proxmark3-fpc-usart--bt-add-on-blue-shark) + - [BT add-on AT configuration mode](#bt-add-on-at-configuration-mode) + - [BT add-on connected mode](#bt-add-on-connected-mode) + - [RFCOMM](#rfcomm) + - [BT add-on baudrate](#bt-add-on-baudrate) + - [BT on host side: internal BT](#bt-on-host-side-internal-bt) + - [BT on host side: HC-06 dongle](#bt-on-host-side-hc-06-dongle) + - [HC-06 dongle AT configuration mode](#hc-06-dongle-at-configuration-mode) + - [Proxmark3 FPC USART + FTDI](#proxmark3-fpc-usart--ftdi) + - [BT add-on + FTDI](#bt-add-on--ftdi) + - [HC-06 AT Commands](#hc-06-at-commands) + + ## USB-CDC ACM +^[Top](#top) USB CDC (Communications Device Class) ACM (Abstract Control Model) is a way to emulate serial ports over USB. On the host, it appears as a virtual serial port, e.g. `/dev/ttyACM0`. @@ -16,6 +36,7 @@ The real communication speed relates only to the USB link and is roughly about 7 In USB CDC ACM the host could "set" other baudrates and the USB CDC device would be informed of the changes (see `SET_LINE_CODING` and `GET_LINE_CODING`), which is potentially interesting if, behind, it has to configure a real UART, but we're not in this type of setup so baudrate notion on USB CDC (visible e.g. with `stty -F /dev/ttyACM0`) can simply be totally ignored. ## Proxmark3 FPC USART +^[Top](#top) Proxmark3 RDV4 has a FPC connector outputting on 2 pins a USART from the ARM: @@ -40,8 +61,10 @@ And for things to work fine, both sets have to match! Internally, the desired baudrate is converted to UART settings: a BRGR and a FP. The resulting baudrate will be close to but not always equal to the desired baudrate. Serial ports typically have some error tolerance in the actual baudrates. Theoretically < 2.5% on each side (so 5% in total), < 2% to be on the safe side. In the current firmware configuration, the Proxmark3 can provide any baudrate up to 2Mbauds with an error of max 2%, and selected baudrates up to 6Mbauds (tested with a FTDI C232HM DDHSL-0 cable). ## Proxmark3 FPC USART + BT add-on (blue shark) +^[Top](#top) ### BT add-on AT configuration mode +^[Top](#top) When the BT add-on is turned on but no actively connected to a host, it's in a configuration mode where it accepts "AT" commands and its blue LED is blinking at about 1Hz. @@ -54,18 +77,21 @@ Some specific commands are available when you add `BTADDON` to `PLATFORM_EXTRAS` Manual configuration is also possible with `usart txrx -d "AT+Px"` and `usart txrx -d "AT+BAUDx"`. ### BT add-on connected mode +^[Top](#top) When the BT add-on is paired with a host and the host establishes an active connection, the blue LED turns on steadily. The add-on acts as a bridge, between its UART and the BT communication channel, here a RFCOMM channel. ### RFCOMM +^[Top](#top) The Bluetooth RFCOMM protocol provides an emulation of serial ports over the L2CAP protocol ([ref](https://www.amd.e-technik.uni-rostock.de/ma/gol/lectures/wirlec/bluetooth_info/rfcomm.html)). As for USB-CDC, the real speed of the link is unrelated to serial baudrate notion. Literature mentions a maximal value of 360kbps for some implementations, but the HC-06 Bluetooth module within the BT add-on is limited as the vast majority of similar devices to 128kbps. ### BT add-on baudrate +^[Top](#top) Which baudrate will make sense? @@ -78,6 +104,7 @@ Using 115200 is safe and within the 128kbps limit. Using 230400 allows to maximize the BT channel capacity, but the gain is limited, about 10-15% faster than 115200. There is also a risk to take into account: you're delivering data too fast to the HC-06 than what it's capable to send over RFCOMM. So you're filling the internal buffer faster than it can be emptied. If you're doing it for too many data, you'll reach a point where data will be lost (once the internal buffer is full), which is observable with `hw status` for higher baudrates at the time of writing (`b17da830edadb8462e02a95a00b4a58302cce71b`). ### BT on host side: internal BT +^[Top](#top) On the other side of the BT link is the host. If it has built-in Bluetooth, the host can present a virtual serial port to the Proxmark3 client. E.g. on Linux, `rfcomm` allows to create such bindings of a BT device and a virtual port: `rfcomm bind rfcomm0 20:19:04:20:04:08` will create the virtual port `/dev/rfcomm0`. @@ -89,6 +116,7 @@ Note that the rfcomm implementation separates pairing from actual connection: * when the program closes, the link will be closed and the BT add-on blue LED will blink again, showing that the BT ad-on is in AT configuration mode. ### BT on host side: HC-06 dongle +^[Top](#top) On the other side of the BT link is the host. If it does not have a built-in Bluetooth, the host can use * a generic BT add-on, and we're back in the previous case @@ -111,12 +139,14 @@ The USB-UART speed is selected when a program opens the port. E.g. * the Python script meant to configure HC-06 dongle. The baudrate is given as option to `serial.Serial()` when opening `/dev/ttyUSB0`. ### HC-06 dongle AT configuration mode +^[Top](#top) When the BT add-on is turned off, the HC-06 dongle will not be connected and will fall back into its AT configuration mode (its LED is blinking). `tools/btaddon/hc06_factory.py` changes several times the USB-UART baudrate and parity till it matches the HC-06 dongle settings, then changes the baudrate and parity of the dongle to a default value. (`hc06_factory.py` does more but we're only interested in baudrate in this discussion) ## Proxmark3 FPC USART + FTDI +^[Top](#top) Just for completeness, let's mention the possibility to connect the Proxmark3 to the host via FPC and a USB-UART bridge such as a FTDI cable (or CP2102, ch341, PL2303...). It's not very interesting because USB-CDC is faster anyway. @@ -124,6 +154,7 @@ It's not very interesting because USB-CDC is faster anyway. In that case, Proxmark3 USART settings (configured e.g. via `usart config` while connected by USB-CDC) have to match FTDI cable settings, selected by the program opening the serial port (`/dev/ttyUSB0`). ## BT add-on + FTDI +^[Top](#top) Just for completeness, let's mention the possibility to connect the BT add-on to the host via FPC and a USB-UART bridge such as a FTDI cable (or CP2102, ch341, PL2303...). The only interest is for debug purposes, e.g. to reconfigure an add-on from the host rather than from the Proxmark3 itself. @@ -148,6 +179,7 @@ Turn BTpower switch ON, leave Battery switch OFF Use e.g. `tools/btaddon/hc06_factory.py` with `role = b'S'` ## HC-06 AT Commands +^[Top](#top) The HC-06 supports a subset of the AT commands and they are listed below. The commands are limited and vary in how to give parameters. A pure informative command like AT+VERSION just returns a string with current firmware the HC-06 has installed. diff --git a/include/hitag.h b/include/hitag.h index 168d3f439..6a42d976c 100644 --- a/include/hitag.h +++ b/include/hitag.h @@ -97,32 +97,32 @@ typedef enum SOF_TYPE { } stype; struct hitagS_tag { - PSTATE pstate; //protocol-state - TSATE tstate; //tag-state + PSTATE pstate; // protocol-state + TSATE tstate; // tag-state uint32_t uid; uint8_t pages[64][4]; uint64_t key; uint8_t pwdl0, pwdl1, pwdh0; - //con0 + // con0 int max_page; stype mode; - //con1 - bool auth; //0=Plain 1=Auth - bool TTFC; //Transponder Talks first coding. 0=Manchester 1=Biphase - int TTFDR; //data rate in TTF Mode - int TTFM; //the number of pages that are sent to the RWD - bool LCON; //0=con1/2 read write 1=con1 read only and con2 OTP - bool LKP; //0=page2/3 read write 1=page2/3 read only in Plain mode and no access in authenticate mode - //con2 - //0=read write 1=read only - bool LCK7; //page4/5 - bool LCK6; //page6/7 - bool LCK5; //page8-11 - bool LCK4; //page12-15 - bool LCK3; //page16-23 - bool LCK2; //page24-31 - bool LCK1; //page32-47 - bool LCK0; //page48-63 + // con1 + bool auth; // 0 = Plain 1 = Auth + bool TTFC; // Transponder Talks first coding. 0 = Manchester 1 = Biphase + int TTFDR; // data rate in TTF Mode + int TTFM; // the number of pages that are sent to the RWD + bool LCON; // 0 = con1/2 read write 1 =con1 read only and con2 OTP + bool LKP; // 0 = page2/3 read write 1 =page2/3 read only in Plain mode and no access in authenticate mode + // con2 + // 0 = read write 1 = read only + bool LCK7; // page4/5 + bool LCK6; // page6/7 + bool LCK5; // page8-11 + bool LCK4; // page12-15 + bool LCK3; // page16-23 + bool LCK2; // page24-31 + bool LCK1; // page32-47 + bool LCK0; // page48-63 }; #endif diff --git a/include/iclass_cmd.h b/include/iclass_cmd.h new file mode 100644 index 000000000..5bb4f9c92 --- /dev/null +++ b/include/iclass_cmd.h @@ -0,0 +1,159 @@ +//----------------------------------------------------------------------------- +// (c) 2021 Iceman +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// iCLASS type prototyping +//----------------------------------------------------------------------------- + +#ifndef _ICLASS_CMD_H_ +#define _ICLASS_CMD_H_ + +#include "common.h" + +//----------------------------------------------------------------------------- +// iCLASS / PICOPASS +//----------------------------------------------------------------------------- + + +// iCLASS reader flags +#define FLAG_ICLASS_READER_INIT 0x01 +#define FLAG_ICLASS_READER_CLEARTRACE 0x02 +//#define FLAG_ICLASS_READER_ONLY_ONCE 0x04 +#define FLAG_ICLASS_READER_CREDITKEY 0x08 +#define FLAG_ICLASS_READER_AIA 0x10 + +// iCLASS reader status flags +#define FLAG_ICLASS_NULL 0x00 +#define FLAG_ICLASS_CSN 0x01 +#define FLAG_ICLASS_CC 0x02 +#define FLAG_ICLASS_CONF 0x04 +#define FLAG_ICLASS_AIA 0x08 + +// iCLASS simulation modes +#define ICLASS_SIM_MODE_CSN 0 +#define ICLASS_SIM_MODE_CSN_DEFAULT 1 +#define ICLASS_SIM_MODE_READER_ATTACK 2 +#define ICLASS_SIM_MODE_FULL 3 +#define ICLASS_SIM_MODE_READER_ATTACK_KEYROLL 4 +#define ICLASS_SIM_MODE_EXIT_AFTER_MAC 5 // note: device internal only +#define ICLASS_SIM_MODE_CONFIG_CARD 6 + + +// iCLASS auth request data structure +// used with read block, dump, write block +typedef struct { + uint8_t key[8]; + bool use_raw; + bool use_elite; + bool use_credit_key; + bool use_replay; + bool send_reply; + bool do_auth; + uint8_t blockno; +} PACKED iclass_auth_req_t; + +// iCLASS read block response data structure +typedef struct { + bool isOK; + uint8_t div_key[8]; + uint8_t mac[4]; + uint8_t data[8]; +} PACKED iclass_readblock_resp_t; + +// iCLASS dump data structure +typedef struct { + iclass_auth_req_t req; + uint8_t start_block; + uint8_t end_block; +} PACKED iclass_dump_req_t; + +// iCLASS write block request data structure +typedef struct { + iclass_auth_req_t req; + uint8_t data[8]; +} PACKED iclass_writeblock_req_t; + +// iCLASS dump data structure +typedef struct { + uint8_t blockno; + uint8_t data[8]; +} PACKED iclass_restore_item_t; + +typedef struct { + iclass_auth_req_t req; + uint8_t item_cnt; + iclass_restore_item_t blocks[]; +} PACKED iclass_restore_req_t; + +typedef struct iclass_premac { + uint8_t mac[4]; +} PACKED iclass_premac_t; + +typedef struct { + bool use_credit_key; + uint8_t count; + iclass_premac_t items[]; +} PACKED iclass_chk_t; + +typedef struct iclass_block { + uint8_t d[8]; +} iclass_block_t; + +typedef struct iclass_prekey { + uint8_t mac[4]; + uint8_t key[8]; +} iclass_prekey_t; + +typedef struct { + char desc[70]; + uint8_t data[16]; +} iclass_config_card_item_t; + + +// iclass / picopass chip config structures and shared routines +typedef struct { + uint8_t app_limit; //[8] + uint8_t otp[2]; //[9-10] + uint8_t block_writelock;//[11] + uint8_t chip_config; //[12] + uint8_t mem_config; //[13] + uint8_t eas; //[14] + uint8_t fuses; //[15] +} PACKED picopass_conf_block_t; + +// iCLASS secure mode memory mapping +typedef struct { + uint8_t csn[8]; + picopass_conf_block_t conf; + uint8_t epurse[8]; + uint8_t key_d[8]; + uint8_t key_c[8]; + uint8_t app_issuer_area[8]; +} PACKED picopass_hdr_t; + +// iCLASS non-secure mode memory mapping +typedef struct { + uint8_t csn[8]; + picopass_conf_block_t conf; + uint8_t app_issuer_area[8]; +} PACKED picopass_ns_hdr_t; + +// reader flags +typedef struct { + uint8_t flags; +} PACKED iclass_card_select_t; + +// reader flags +typedef struct { + uint8_t status; + union { + picopass_hdr_t hdr; + picopass_ns_hdr_t ns_hdr; + } header; +} PACKED iclass_card_select_resp_t; + + +#endif // _ICLASS_H_ \ No newline at end of file diff --git a/include/legic.h b/include/legic.h index 574cb7fdf..17d2ebc26 100644 --- a/include/legic.h +++ b/include/legic.h @@ -24,4 +24,6 @@ typedef struct { uint16_t cardsize; } legic_card_select_t; +// iceman: todo : this should be packed + #endif // _LEGIC_H_ diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 88b7cb730..fe3a55862 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -291,92 +291,6 @@ typedef struct { } PACKED ecdsa_publickey_t; -// iCLASS auth request data structure -// used with read block, dump, write block -typedef struct { - uint8_t key[8]; - bool use_raw; - bool use_elite; - bool use_credit_key; - bool use_replay; - bool send_reply; - bool do_auth; - uint8_t blockno; -} PACKED iclass_auth_req_t; - -// iCLASS read block response data structure -typedef struct { - bool isOK; - uint8_t div_key[8]; - uint8_t mac[4]; - uint8_t data[8]; -} PACKED iclass_readblock_resp_t; - -// iCLASS dump data structure -typedef struct { - iclass_auth_req_t req; - uint8_t start_block; - uint8_t end_block; -} PACKED iclass_dump_req_t; - -// iCLASS write block request data structure -typedef struct { - iclass_auth_req_t req; - uint8_t data[8]; -} PACKED iclass_writeblock_req_t; - -// iCLASS dump data structure -typedef struct { - uint8_t blockno; - uint8_t data[8]; -} PACKED iclass_restore_item_t; - -typedef struct { - iclass_auth_req_t req; - uint8_t item_cnt; - iclass_restore_item_t blocks[]; -} PACKED iclass_restore_req_t; - -typedef struct iclass_premac { - uint8_t mac[4]; -} PACKED iclass_premac_t; - -typedef struct { - bool use_credit_key; - uint8_t count; - iclass_premac_t items[]; -} PACKED iclass_chk_t; - - -// iclass / picopass chip config structures and shared routines -typedef struct { - uint8_t app_limit; //[8] - uint8_t otp[2]; //[9-10] - uint8_t block_writelock;//[11] - uint8_t chip_config; //[12] - uint8_t mem_config; //[13] - uint8_t eas; //[14] - uint8_t fuses; //[15] -} PACKED picopass_conf_block_t; - -// iCLASS secure mode memory mapping -typedef struct { - uint8_t csn[8]; - picopass_conf_block_t conf; - uint8_t epurse[8]; - uint8_t key_d[8]; - uint8_t key_c[8]; - uint8_t app_issuer_area[8]; -} PACKED picopass_hdr_t; - -// iCLASS non-secure mode memory mapping -typedef struct { - uint8_t csn[8]; - picopass_conf_block_t conf; - uint8_t app_issuer_area[8]; -} PACKED picopass_ns_hdr_t; - - typedef struct { uint16_t delay_us; bool on; @@ -746,8 +660,8 @@ typedef struct { #define CMD_HF_MIFARE_GEN3BLK 0x0851 #define CMD_HF_MIFARE_GEN3FREEZ 0x0852 -// Gen 3 GTU magic cards -#define CMD_HF_MIFARE_G3_RDBL 0x0860 +// Gen 4 GTU magic cards +#define CMD_HF_MIFARE_G4_RDBL 0x0860 #define CMD_UNKNOWN 0xFFFF @@ -767,28 +681,6 @@ typedef struct { #define FLAG_CVE21_0430 0x2000 -// iCLASS reader flags -#define FLAG_ICLASS_READER_INIT 0x01 -#define FLAG_ICLASS_READER_CLEARTRACE 0x02 -#define FLAG_ICLASS_READER_ONLY_ONCE 0x04 -#define FLAG_ICLASS_READER_CREDITKEY 0x08 -#define FLAG_ICLASS_READER_AIA 0x10 - -// iCLASS reader status flags -#define FLAG_ICLASS_CSN 0x01 -#define FLAG_ICLASS_CC 0x02 -#define FLAG_ICLASS_CONF 0x04 -#define FLAG_ICLASS_AIA 0x08 - -// iCLASS simulation modes -#define ICLASS_SIM_MODE_CSN 0 -#define ICLASS_SIM_MODE_CSN_DEFAULT 1 -#define ICLASS_SIM_MODE_READER_ATTACK 2 -#define ICLASS_SIM_MODE_FULL 3 -#define ICLASS_SIM_MODE_READER_ATTACK_KEYROLL 4 -#define ICLASS_SIM_MODE_EXIT_AFTER_MAC 5 // note: device internal only -#define ICLASS_SIM_MODE_CONFIG_CARD 6 - #define MODE_SIM_CSN 0 #define MODE_EXIT_AFTER_MAC 1 #define MODE_FULLSIM 2 diff --git a/tools/deprecated-hid-flasher/flasher/usb_cmd.h b/tools/deprecated-hid-flasher/flasher/usb_cmd.h index 75136c1f4..90a76a1be 100644 --- a/tools/deprecated-hid-flasher/flasher/usb_cmd.h +++ b/tools/deprecated-hid-flasher/flasher/usb_cmd.h @@ -223,7 +223,7 @@ typedef struct { #define FLAG_NR_AR_ATTACK 0x20 //Iclass reader flags -#define FLAG_ICLASS_READER_ONLY_ONCE 0x01 +//#define FLAG_ICLASS_READER_ONLY_ONCE 0x01 #define FLAG_ICLASS_READER_CC 0x02 #define FLAG_ICLASS_READER_CSN 0x04 #define FLAG_ICLASS_READER_CONF 0x08 diff --git a/traces/lf_HitagS256_dump.trace b/traces/lf_HitagS256_dump.trace new file mode 100644 index 000000000..fe5f9f107 Binary files /dev/null and b/traces/lf_HitagS256_dump.trace differ