From 547e4624223716dd635906ce4dd88e1c7a3e22b9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Mar 2021 12:55:28 +0100 Subject: [PATCH 01/67] spelling --- client/src/flash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/flash.c b/client/src/flash.c index 9693d8803..2f5f037c3 100644 --- a/client/src/flash.c +++ b/client/src/flash.c @@ -412,7 +412,7 @@ static void flash_suggest_update_bootloader(void) { PrintAndLogEx(ERR, _RED_("reboot the Proxmark3 then only update the main firmware") "\n"); PrintAndLogEx(ERR, "Follow these steps :"); PrintAndLogEx(ERR, " 1) ./pm3-flash-bootrom"); - PrintAndLogEx(ERR, " 2) ./pm3-flash-flash-all"); + PrintAndLogEx(ERR, " 2) ./pm3-flash-all"); PrintAndLogEx(ERR, " 3) ./pm3"); PrintAndLogEx(INFO, "--------------------------------------------------------"); g_printed_msg = true; From 6aa9b98afce27cf810b414bc2c309d93a64b40c6 Mon Sep 17 00:00:00 2001 From: mwalker33 <51802811+mwalker33@users.noreply.github.com> Date: Sat, 6 Mar 2021 17:36:42 +1100 Subject: [PATCH 02/67] Update cmdlft55xx.c T55xx detect - set default to try all downlink modes - ensured when trying all downlink modes it starts at fixed bit. --- client/src/cmdlft55xx.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 1c3993454..969eb46e1 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -997,10 +997,12 @@ static int CmdT55xxDetect(const char *Cmd) { downlink_mode = refLeading0; else if (r3) downlink_mode = ref1of4; - - if (ra) + else // This will set the default to user all d/l modes which will cover the ra flag as well. try_all_dl_modes = true; + // if (ra) + // try_all_dl_modes = true; + bool try_with_pwd = false; bool found = false; bool usewake = false; @@ -1026,9 +1028,9 @@ static int CmdT55xxDetect(const char *Cmd) { do { // do ... while to check without password then loop back if password supplied do { - if (try_all_dl_modes) { - for (uint8_t m = downlink_mode; m < 4; m++) { + // Loop from 1st d/l mode refFixedBit to the last d/l mode ref1of4 + for (uint8_t m = refFixedBit; m <= ref1of4; m++) { if (usewake) { // call wake if (try_with_pwd) From 17eefbcbb628ba4f5c5b61dae82f5dc9151578e7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 6 Mar 2021 17:13:05 +0100 Subject: [PATCH 03/67] maur --- client/dictionaries/mfc_default_keys.dic | 72 ++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index 15b70cddf..a0c8b9943 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -1296,3 +1296,75 @@ ff9a84635bd2 f1a1239a4487 # b882fd4a9f78 +CD7FFFF81C4A +AA0857C641A3 +C8AACD7CF3D1 +9FFDA233B496 +26B85DCA4321 +D4B2D140CB2D +A7395CCB42A0 +541C417E57C0 +D14E615E0545 +69D92108C8B5 +703265497350 +D75971531042 +10510049D725 +35C649004000 +5B0C7EC83645 +05F5EC05133C +521B517352C7 +94B6A644DFF6 +2CA4A4D68B8E +A7765C952DDF +E2F14D0A0E28 +DC018FC1D126 +4927C97F1D57 +046154274C11 +155332417E00 +6B13935CD550 +C151D998C669 +D973D917A4C7 +130662240200 +9386E2A48280 +52750A0E592A +541C417E57C0 +D14E615E0545 +075D1A4DD323 +32CA52054416 +460661C93045 +5429D67E1F57 +0C734F230E13 +1F0128447C00 +411053C05273 +42454C4C4147 +C428C4550A75 +730956C72BC2 +28D70900734C +4F75030AD12B +6307417353C1 +D65561530174 +D1F71E05AD9D +F7FA2F629BB1 +0E620691B9FE +43E69C28F08C +735175696421 +424C0FFBF657 +D01AFEEB890A +75CCB59C9BED +4B791BEA7BCC +51E97FFF51E9 +E7316853E731 +5C8FF9990DA2 +00460740D722 +35D152154017 +5D0762D13401 +0F35D5660653 +1170553E4304 +0C4233587119 +F678905568C3 +50240A68D1D8 +69D92108C8B5 +2E71D3BD262A +540D5E6355CC +D1417E431949 +4BF6DE347FB6 \ No newline at end of file From dff732840f9dfa0b05a30f16d80a625e478d73af Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 08:56:36 +0100 Subject: [PATCH 04/67] mem info - now accepts input id to facility easy testing. Signature offset also triggers erase before to enable easy updates --- armsrc/appmain.c | 4 +++ client/src/cmdflashmem.c | 64 +++++++++++++++++++++++++++++++--------- doc/ext_flash_notes.md | 9 +++--- 3 files changed, 59 insertions(+), 18 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 6a6058d3b..d9162dda8 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -2202,6 +2202,10 @@ static void PacketReceived(PacketCommandNG *packet) { Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); Flash_Erase4k(3, 0xB); + } else if (startidx == FLASH_MEM_SIGNATURE_OFFSET) { + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); + Flash_Erase4k(3, 0xF); } res = Flash_Write(startidx, data, len); diff --git a/client/src/cmdflashmem.c b/client/src/cmdflashmem.c index 23acad47d..2f807fa7f 100644 --- a/client/src/cmdflashmem.c +++ b/client/src/cmdflashmem.c @@ -39,7 +39,10 @@ static int CmdHelp(const char *Cmd); "9337F21C0C066FFB703D8BFCB5067F309E056772096642C2B1A8F50305D5EC33" \ "DB7FB5A3C8AC42EB635AE3C148C910750ABAA280CE82DC2F180F49F30A1393B5" +//------------------------------------------------------------------------------------- +// Sample private RSA Key // Following example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c) + // private key - Exponent D #define RSA_D "24BF6185468786FDD303083D25E64EFC" \ "66CA472BC44D253102F8B4A9D3BFA750" \ @@ -445,29 +448,39 @@ static int CmdFlashMemInfo(const char *Cmd) { CLIParserInit(&ctx, "mem info", "Collect signature and verify it from flash memory", "mem info" -// "mem info -s" +// "mem info -s -d 0102030405060708" ); void *argtable[] = { arg_param_begin, -// arg_lit0("s", NULL, "create a signature"), -// arg_lit0("w", NULL, "write signature to flash memory"), + arg_lit0("s", "sign", "create a signature"), + arg_str0("d", NULL, "", "flash memory id, 8 hex bytes"), +// arg_lit0("w", "write", "write signature to flash memory"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); bool shall_sign = false, shall_write = false; -// shall_sign = arg_get_lit(ctx, 1); -// shall_write = arg_get_lit(ctx, 2); + shall_sign = arg_get_lit(ctx, 1); + + int dlen = 0; + uint8_t id[8] = {0}; + int res = CLIParamHexToBuf(arg_get_str(ctx, 2), id, sizeof(id), &dlen); + +// shall_write = arg_get_lit(ctx, 3); CLIParserFree(ctx); - // validate signature data + if (dlen > 0 && dlen < sizeof(id) ) { + PrintAndLogEx(FAILED, "Error parsing flash memory id, expect 8, got %d", dlen); + return PM3_EINVARG; + } + + // validate devicesignature data rdv40_validation_t mem; - int res = rdv4_get_signature(&mem); + res = rdv4_get_signature(&mem); if (res != PM3_SUCCESS) { return res; } - res = rdv4_validate(&mem); // Flash ID hash (sha1) @@ -479,6 +492,11 @@ static int CmdFlashMemInfo(const char *Cmd) { PrintAndLogEx(INFO, "--- " _CYAN_("Flash memory Information") " ---------"); PrintAndLogEx(INFO, "ID................... %s", sprint_hex_inrow(mem.flashid, sizeof(mem.flashid))); PrintAndLogEx(INFO, "SHA1................. %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash))); + PrintAndLogEx( + (res == PM3_SUCCESS) ? SUCCESS : FAILED, + "Signature............ ( %s )", + (res == PM3_SUCCESS) ? _GREEN_("ok") : _RED_("fail") + ); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA signature") " ---------------"); for (int i = 0; i < (sizeof(mem.signature) / 32); i++) { @@ -520,13 +538,21 @@ static int CmdFlashMemInfo(const char *Cmd) { PrintAndLogEx(INFO, " %.64s", str_pk + 192); PrintAndLogEx(NORMAL, ""); - bool is_keyok = (mbedtls_rsa_check_pubkey(&rsa) == 0 || mbedtls_rsa_check_privkey(&rsa) == 0); + bool is_keyok = (mbedtls_rsa_check_pubkey(&rsa) == 0); PrintAndLogEx( (is_keyok) ? SUCCESS : FAILED, - "RSA key validation... ( %s )", + "RSA public key validation.... ( %s )", (is_keyok) ? _GREEN_("ok") : _RED_("fail") ); + is_keyok = (mbedtls_rsa_check_privkey(&rsa) == 0); + PrintAndLogEx( + (is_keyok) ? SUCCESS : FAILED, + "RSA private key validation... ( %s )", + (is_keyok) ? _GREEN_("ok") : _RED_("fail") + ); + + // to be verified uint8_t from_device[RRG_RSA_KEY_LEN]; memcpy(from_device, mem.signature, RRG_RSA_KEY_LEN); @@ -537,6 +563,13 @@ static int CmdFlashMemInfo(const char *Cmd) { // Signing (private key) if (shall_sign) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "--- " _CYAN_("Enter signing") " --------------------"); + + if (dlen == 8) { + mbedtls_sha1(id, sizeof(id), sha_hash); + } + PrintAndLogEx(INFO, "Signing %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash))); int is_signed = mbedtls_rsa_pkcs1_sign(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign); PrintAndLogEx( @@ -555,14 +588,17 @@ static int CmdFlashMemInfo(const char *Cmd) { } // Verify (public key) - int is_verified = mbedtls_rsa_pkcs1_verify(&rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device); + bool is_verified = (mbedtls_rsa_pkcs1_verify(&rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device) == 0); mbedtls_rsa_free(&rsa); PrintAndLogEx( - (is_verified == 0) ? SUCCESS : FAILED, - "RSA verification..... ( %s )", - (is_verified == 0) ? _GREEN_("ok") : _RED_("fail") + (is_verified) ? SUCCESS : FAILED, + "RSA verification..... ( %s )", + (is_verified) ? _GREEN_("ok") : _RED_("fail") ); + if (is_verified) { + PrintAndLogEx(SUCCESS, "Genuine Proxmark3 RDV4 signature detected"); + } PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; diff --git a/doc/ext_flash_notes.md b/doc/ext_flash_notes.md index 46059d9ca..f6e462421 100644 --- a/doc/ext_flash_notes.md +++ b/doc/ext_flash_notes.md @@ -39,8 +39,8 @@ Page 3: * used by Proxmark3 RDV4 specific functions: flash signature and keys dictionaries, see below for details * to dump it: `mem dump f page3_dump o 196608 l 65536` * to erase it: - * **Beware** it will erase your flash signature (see below) so better to back it up first as you won't be able to regenerate it by yourself! - * It's possible to erase completely page 3 by erase the entire flash memory with the voluntarily undocumented command `mem wipe i`. + * **Beware** it will erase your flash signature so better to back it up first as you won't be able to regenerate it by yourself! + * edit the source code to enable Page 3 as a valid input in the `mem wipe` command. * Updating keys dictionaries doesn't require to erase page 3. ## Page3 Layout @@ -64,7 +64,7 @@ Page3 is used as follows by the Proxmark3 RDV4 firmware: * length: 1 sector (actually only a few bytes are used to store `t55xx_config` structure) * **RSA SIGNATURE**, see below for details - * offset: page 3 sector 15 (0xF) offset 0xF7F @ 3*0x10000+15*0x1000+0xF7F=0x3FF7F + * offset: page 3 sector 15 (0xF) offset 0xF7F @ 3*0x10000+15*0x1000+0xF7F=0x3FF7F (decimal 262015) * length: 128 bytes * offset should have been 0x3FF80 but historically it's one byte off and therefore the last byte of the flash is unused @@ -91,5 +91,6 @@ You can verify it with: `mem info` [+] RSA Verification ok ``` -For a backup of the signature: `mem dump p f flash_signature_dump o 262015 l 128` +To make a backup of the signature to file: +`mem dump p f flash_signature_dump o 262015 l 128` From 14d62bf38046be7f3137bac3c7cfac19f378a09a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 08:58:16 +0100 Subject: [PATCH 05/67] some lf reader used this configblock, dont remember if it was discussed on forum or discord --- client/src/cmdlft55xx.h | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/cmdlft55xx.h b/client/src/cmdlft55xx.h index 83a35b848..1a31772eb 100644 --- a/client/src/cmdlft55xx.h +++ b/client/src/cmdlft55xx.h @@ -32,6 +32,7 @@ #define T55X7_NORALSY_CONFIG_BLOCK 0x00088C6A // ASK, compat mode, (NORALSY - KCP3000), data rate 32, 3 data blocks #define T55X7_PRESCO_CONFIG_BLOCK 0x00088088 // ASK, data rate 32, Manchester, 4 data blocks, STT #define T55X7_SECURAKEY_CONFIG_BLOCK 0x000C8060 // ASK, Manchester, data rate 40, 3 data blocks +#define T55X7_UNK_CONFIG_BLOCK 0x000880FA // ASK, Manchester, data rate 32, 7 data blocks STT, Inverse ... // FDXB requires data inversion and BiPhase 57 is simply BiPhase 50 inverted, so we can either do it using the modulation scheme or the inversion flag // we've done both below to prove that it works either way, and the modulation value for BiPhase 50 in the Atmel data sheet of binary "10001" (17) is a typo, From 346113b168b5c6cb45fd512c59890b7f9d2b935c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 10:18:50 +0100 Subject: [PATCH 06/67] text --- doc/ext_flash_notes.md | 45 ++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/doc/ext_flash_notes.md b/doc/ext_flash_notes.md index f6e462421..76b4d9279 100644 --- a/doc/ext_flash_notes.md +++ b/doc/ext_flash_notes.md @@ -73,24 +73,39 @@ Page3 is used as follows by the Proxmark3 RDV4 firmware: 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` + +Here below is a sample output of a RDV4 device. ``` -[usb] pm3 --> mem info - -[=] --- Flash memory Information --------- - -[=] ------------------------------------------------------------- -[=] ID | xx xx xx xx xx xx xx xx -[=] SHA1 | xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx -[=] RSA SIGNATURE | -[00] | xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx -[01] | xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx -[02] | xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx -[03] | xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx -[=] KEY length | 128 -[+] RSA key validation ok -[+] RSA Verification ok +[usb] pm3 --> mem info + +[=] --- Flash memory Information --------- +[=] ID................... 25AD99A782A867D5 +[=] SHA1................. 67C3B9BA2FA90AD4B283926B70017066C082C156 +[+] Signature............ ( ok ) + +[=] --- RDV4 RSA signature --------------- +[=] C7C7DF7FA3A2391A2B36E97D227C746ED8BB475E8766F54A13BAA9AAB29299BE +[=] 37546AACCC29157ABF8AFBF3A1CFB24275442D565F7E996C6B08090528ADE25E +[=] ED1498E3089C72C68348D83CBD13F1247327BDBC9D75B09ECE3E051E19FE19BB +[=] 98CB038757F2EDFD2DC5060D05C3296BC19A6F768290D555DFD50407E0E13A70 + +[=] --- RDV4 RSA Public key -------------- +[=] Len.................. 128 +[=] Exponent............. 010001 +[=] Public key modulus N +[=] E28D809BF323171D11D1ACA4C32A5B7E0A8974FD171E75AD120D60E9B76968FF +[=] 4B0A6364AE50583F9555B8EE1A725F279E949246DF0EFCE4C02B9F3ACDCC623F +[=] 9337F21C0C066FFB703D8BFCB5067F309E056772096642C2B1A8F50305D5EC33 +[=] DB7FB5A3C8AC42EB635AE3C148C910750ABAA280CE82DC2F180F49F30A1393B5 + +[+] RSA public key validation.... ( ok ) +[+] RSA private key validation... ( ok ) +[+] RSA verification..... ( ok ) +[+] Genuine Proxmark3 RDV4 signature detected ``` +# backup first! To make a backup of the signature to file: + `mem dump p f flash_signature_dump o 262015 l 128` From e4753011d8a33331d16e4cd0044578a5eb55d907 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 10:19:52 +0100 Subject: [PATCH 07/67] text --- client/src/cmdflashmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdflashmem.c b/client/src/cmdflashmem.c index 2f807fa7f..5bb3b8cd9 100644 --- a/client/src/cmdflashmem.c +++ b/client/src/cmdflashmem.c @@ -139,7 +139,7 @@ static int rdv4_sign_write(uint8_t *signature, uint8_t slen){ if (!resp.oldarg[0]) { PrintAndLogEx(FAILED, "Writing signature ( "_RED_("fail") ")"); } else { - PrintAndLogEx(SUCCESS, "Writing signature ( "_GREEN_("ok") " ) at offset %u", FLASH_MEM_SIGNATURE_OFFSET); + PrintAndLogEx(SUCCESS, "Writing signature at offset %u ( "_GREEN_("ok") " )", FLASH_MEM_SIGNATURE_OFFSET); return PM3_SUCCESS; } } From 70bcfb7ffe9d74cdaa0ec6ca345febdb95efe2f3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 10:44:21 +0100 Subject: [PATCH 08/67] textual, pushing a point --- client/src/cmdlft55xx.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 969eb46e1..bf688c76d 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -4193,8 +4193,12 @@ static int CmdT55xxSniff(const char *Cmd) { } static command_t CommandTable[] = { - {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("operations") " ---------------------"}, + {"-----------", CmdHelp, AlwaysAvailable, "---------------------------- " _CYAN_("notice") " -----------------------------"}, + {"", CmdHelp, AlwaysAvailable, "Remember to run `" _YELLOW_("lf t55xx detect") "` first whenever "}, + {"", CmdHelp, AlwaysAvailable, "a new card is placed on the Proxmark3 or the config block changed."}, + {"", CmdHelp, AlwaysAvailable, ""}, {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("operations") " ---------------------"}, {"clonehelp", CmdT55xxCloneHelp, IfPm3Lf, "Shows the available clone commands"}, {"config", CmdT55xxSetConfig, AlwaysAvailable, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"}, {"dangerraw", CmdT55xxDangerousRaw, IfPm3Lf, "Sends raw bitstream. Dangerous, do not use!!"}, From d5ea600289d440e783fb522795c67bae720db883 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 11:25:17 +0100 Subject: [PATCH 09/67] lf t55 dump - now uses cliparser --- client/src/cmdlft55xx.c | 153 +++++++++++++++++++++------------------- 1 file changed, 82 insertions(+), 71 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index bf688c76d..7578d3cfb 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -208,20 +208,7 @@ static int usage_t55xx_info(void) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } -static int usage_t55xx_dump(void) { - PrintAndLogEx(NORMAL, "Usage: lf t55xx dump [r ] [p [o]]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " p - OPTIONAL password 4bytes (8 hex symbols)"); - PrintAndLogEx(NORMAL, " o - OPTIONAL override, force pwd read despite danger to card"); - PrintAndLogEx(NORMAL, " f - override filename prefix (optional). Default is based on blk 0"); - print_usage_t55xx_downloadlink(T55XX_DLMODE_SINGLE, config.downlink_mode); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx dump")); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx dump p feedbeef o")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} + static int usage_t55xx_restore(void) { PrintAndLogEx(NORMAL, "Usage: lf t55xx restore f [p password]"); PrintAndLogEx(NORMAL, "Options:"); @@ -2198,48 +2185,66 @@ static int CmdT55xxInfo(const char *Cmd) { static int CmdT55xxDump(const char *Cmd) { - uint32_t password = 0; - uint8_t override = 0; - uint8_t downlink_mode = config.downlink_mode; + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf t55xx dump", + "This command dumps a T55xx card Page 0 block 0-7.\n" + "It will create three files (bin/eml/json)", + "lf t55xx dump\n" + "lf t55xx dump -p aabbccdd --override\n" + "lf t55xx dump -f my_lf_dump" + ); + + // 1 (help) + 3 (two user specified params) + (5 T55XX_DLMODE_SINGLE) + void *argtable[4 + 5] = { + arg_param_begin, + arg_str0("f", "filename", "", "filename (default is generated on blk 0"), + arg_lit0("o", "override", "override, force pwd read despite danger to card"), + arg_str0("p", "pwd", "", "password (4 hex bytes)"), + }; + uint8_t idx = 4; + arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_SINGLE, T55XX_DLMODE_SINGLE); + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, sizeof(filename), &fnlen); + + uint8_t override = arg_get_lit(ctx, 2) ? 1 : 0; + bool usepwd = false; - bool errors = false; - uint8_t cmdp = 0; - char preferredName[FILE_PATH_SIZE] = {0}; - bool success = true; - - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_t55xx_dump(); - case 'r': - downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10); - if (downlink_mode > 3) - downlink_mode = 0; - - cmdp += 2; - break; - case 'p': - password = param_get32ex(Cmd, cmdp + 1, 0, 16); - usepwd = true; - cmdp += 2; - break; - case 'o': - override = 1; - cmdp++; - break; - case 'f': - param_getstr(Cmd, cmdp + 1, preferredName, FILE_PATH_SIZE); - cmdp += 2; - if (strlen(preferredName) == 0) - errors = true; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } + uint32_t password = 0; + int res = arg_get_u32_hexstr_def_nlen(ctx, 3, 0, &password, 4, true); + if (res == 0 || res == 2) { + PrintAndLogEx(ERR, "Password should be 4 hex bytes"); + CLIParserFree(ctx); + return PM3_EINVARG; } - if (errors) return usage_t55xx_dump(); + if (res == 1) { + usepwd = true; + } + + bool r0 = arg_get_lit(ctx, 4); + bool r1 = arg_get_lit(ctx, 5); + bool r2 = arg_get_lit(ctx, 6); + bool r3 = arg_get_lit(ctx, 7); + CLIParserFree(ctx); + + if ((r0 + r1 + r2 + r3) > 1) { + PrintAndLogEx(FAILED, "Error multiple downlink encoding"); + return PM3_EINVARG; + } + + uint8_t downlink_mode = config.downlink_mode; + if (r0) + downlink_mode = refFixedBit; + else if (r1) + downlink_mode = refLongLeading; + else if (r2) + downlink_mode = refLeading0; + else if (r3) + downlink_mode = ref1of4; + + bool success = true; // Due to the few different T55xx cards and number of blocks supported // will save the dump file if ALL page 0 is OK @@ -2247,39 +2252,45 @@ static int CmdT55xxDump(const char *Cmd) { for (uint8_t i = 0; i < 8; ++i) { if (T55xxReadBlock(i, 0, usepwd, override, password, downlink_mode) != PM3_SUCCESS) success = false; - // idea for better user experience and display. + // only show override warning on the first block read - if (override == 1) override++; // flag not to show safty for 2nd and on. + if (override == 1) { + override++; + } } printT5xxHeader(1); for (uint8_t i = 0; i < 4; i++) if (T55xxReadBlock(i, 1, usepwd, override, password, downlink_mode) != PM3_SUCCESS) T55x7_SaveBlockData(8 + i, 0x00); + // all ok, save dump to file + if (success) { - if (success) { // all ok save dump to file - // saveFileEML will add .eml extension to filename - // saveFile (binary) passes in the .bin extension. - if (strcmp(preferredName, "") == 0) { // Set default filename, if not set by user - strcpy(preferredName, "lf-t55xx"); + // set default filename, if not set by user + if (strlen(filename) == 0) { + strcpy(filename, "lf-t55xx"); for (uint8_t i = 1; i <= 7; i++) { - if ((cardmem[i].blockdata != 0x00) && (cardmem[i].blockdata != 0xFFFFFFFF)) - snprintf(preferredName + strlen(preferredName), sizeof(preferredName) - strlen(preferredName), "-%08X", cardmem[i].blockdata); - else + if ((cardmem[i].blockdata != 0x00) && (cardmem[i].blockdata != 0xFFFFFFFF)) { + snprintf(filename + strlen(filename), sizeof(filename) - strlen(filename), "-%08X", cardmem[i].blockdata); + } else { break; + } } - strcat(preferredName, "-dump"); + strcat(filename, "-dump"); } // Swap endian so the files match the txt display uint32_t data[T55x7_BLOCK_COUNT]; - for (int i = 0; i < T55x7_BLOCK_COUNT; i++) + for (int i = 0; i < T55x7_BLOCK_COUNT; i++) { data[i] = BSWAP_32(cardmem[i].blockdata); + } - saveFileJSON(preferredName, jsfT55x7, (uint8_t *)data, T55x7_BLOCK_COUNT * sizeof(uint32_t), NULL); - saveFileEML(preferredName, (uint8_t *)data, T55x7_BLOCK_COUNT * sizeof(uint32_t), sizeof(uint32_t)); - saveFile(preferredName, ".bin", data, sizeof(data)); + // saveFileEML will add .eml extension to filename + // saveFile (binary) passes in the .bin extension. + saveFileJSON(filename, jsfT55x7, (uint8_t *)data, T55x7_BLOCK_COUNT * sizeof(uint32_t), NULL); + saveFileEML(filename, (uint8_t *)data, T55x7_BLOCK_COUNT * sizeof(uint32_t), sizeof(uint32_t)); + saveFile(filename, ".bin", data, sizeof(data)); } return PM3_SUCCESS; @@ -4194,8 +4205,8 @@ static int CmdT55xxSniff(const char *Cmd) { static command_t CommandTable[] = { {"-----------", CmdHelp, AlwaysAvailable, "---------------------------- " _CYAN_("notice") " -----------------------------"}, - {"", CmdHelp, AlwaysAvailable, "Remember to run `" _YELLOW_("lf t55xx detect") "` first whenever "}, - {"", CmdHelp, AlwaysAvailable, "a new card is placed on the Proxmark3 or the config block changed."}, + {"", CmdHelp, AlwaysAvailable, "Remember to run `" _YELLOW_("lf t55xx detect") "` first whenever a new card"}, + {"", CmdHelp, AlwaysAvailable, "is placed on the Proxmark3 or the config block changed."}, {"", CmdHelp, AlwaysAvailable, ""}, {"help", CmdHelp, AlwaysAvailable, "This help"}, {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("operations") " ---------------------"}, From 450c7fab5bb59d9ed71bafe3cd644a69e41de2d8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 11:42:23 +0100 Subject: [PATCH 10/67] lf t55xx restore - now uses cliparser --- client/src/cmdlft55xx.c | 222 ++++++++++++++++++++-------------------- 1 file changed, 110 insertions(+), 112 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 7578d3cfb..677b9417b 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -209,20 +209,6 @@ static int usage_t55xx_info(void) { return PM3_SUCCESS; } -static int usage_t55xx_restore(void) { - PrintAndLogEx(NORMAL, "Usage: lf t55xx restore f [p password]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " f - filename of the dump file (.bin/.eml)"); - PrintAndLogEx(NORMAL, " p - optional password if target card has password set"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, _YELLOW_(" Assumes lf t55 detect has been run first!")); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx restore f lf-t55xx-00148040-dump.bin")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} - static int usage_t55xx_clonehelp(void) { PrintAndLogEx(NORMAL, "For cloning specific techs on T55xx tags, see commands available in corresponding LF sub-menus, e.g.:"); PrintAndLogEx(NORMAL, _GREEN_("lf awid clone")); @@ -2197,7 +2183,7 @@ static int CmdT55xxDump(const char *Cmd) { // 1 (help) + 3 (two user specified params) + (5 T55XX_DLMODE_SINGLE) void *argtable[4 + 5] = { arg_param_begin, - arg_str0("f", "filename", "", "filename (default is generated on blk 0"), + arg_str0("f", "filename", "", "filename (default is generated on blk 0)"), arg_lit0("o", "override", "override, force pwd read despite danger to card"), arg_str0("p", "pwd", "", "password (4 hex bytes)"), }; @@ -2297,118 +2283,130 @@ static int CmdT55xxDump(const char *Cmd) { } static int CmdT55xxRestore(const char *Cmd) { - bool errors = false; - uint8_t cmdp = 0; - char preferredName[FILE_PATH_SIZE] = {0}; - char ext[FILE_PATH_SIZE] = {0}; - int success = PM3_ESOFT; - uint32_t password = 0x00; - bool usepwd = false; - uint32_t data[12] = {0}; - size_t datalen = 0; - uint8_t blockidx; - uint8_t downlink_mode; - char writeCmdOpt[100]; - char pwdOpt [11] = {0}; // p XXXXXXXX + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf t55xx restore", + "This command restores T55xx card page 0/1 n blocks", + "lf t55xx restore -f lf-t55xx-00148040-dump.bin" + ); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_t55xx_restore(); - case 'f': - param_getstr(Cmd, cmdp + 1, preferredName, FILE_PATH_SIZE); - if (strlen(preferredName) == 0) - errors = true; - cmdp += 2; - break; - case 'p': - password = param_get32ex(Cmd, cmdp + 1, 0, 16); - usepwd = true; - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } + void *argtable[] = { + arg_param_begin, + arg_str0("f", "filename", "", "filename of the dump file (bin|eml)"), + arg_str0("p", "pwd", "", "password if target card has password set (4 hex bytes)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, sizeof(filename), &fnlen); + + bool usepwd = false; + uint32_t password = 0; + int res = arg_get_u32_hexstr_def_nlen(ctx, 2, 0, &password, 4, true); + if (res == 0 || res == 2) { + PrintAndLogEx(ERR, "Password should be 4 hex bytes"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + if (res == 1) { + usepwd = true; + } + CLIParserFree(ctx); + + if (fnlen == 0) { + PrintAndLogEx(ERR, "Must specify a filename"); + return PM3_EINVARG; } - // File name expected to be .eml .bin or .json so sould be at least 4 - if (errors || (strlen(preferredName) == 0)) return usage_t55xx_restore(); + char ext[FILE_PATH_SIZE] = {0}; + uint32_t data[12] = {0}; + size_t datalen = 0; - // split file name into prefix and ext. - int fnLength; - - fnLength = strlen(preferredName); - - success = PM3_ESOFT; - if (fnLength > 4) { // Holds extension [.bin|.eml] - memcpy(ext, &preferredName[fnLength - 4], 4); + int retval = PM3_ESOFT; + if (fnlen > 4) { // Holds extension [.bin|.eml] + memcpy(ext, &filename[fnlen - 4], 4); ext[5] = 0x00; // check if valid file extension and attempt to load data - if (memcmp(ext, ".bin", 4) == 0) { - preferredName[fnLength - 4] = 0x00; - success = loadFile(preferredName, ".bin", data, sizeof(data), &datalen); + filename[fnlen - 4] = 0x00; + retval = loadFile(filename, ".bin", data, sizeof(data), &datalen); } else if (memcmp(ext, ".eml", 4) == 0) { - preferredName[fnLength - 4] = 0x00; + filename[fnlen - 4] = 0x00; datalen = 12; - success = loadFileEML(preferredName, (uint8_t *)data, &datalen); + retval = loadFileEML(filename, (uint8_t *)data, &datalen); - } else - PrintAndLogEx(WARNING, "\nWarning: invalid dump filename "_YELLOW_("%s")" to restore!\n", preferredName); - } - - if (success == PM3_SUCCESS) { // Got data, so write to cards - if (datalen == T55x7_BLOCK_COUNT * 4) { // 12 blocks * 4 bytes per block - if (usepwd) - snprintf(pwdOpt, sizeof(pwdOpt), "p %08X", password); - - // Restore endien for writing to card - for (blockidx = 0; blockidx < 12; blockidx++) - data[blockidx] = BSWAP_32(data[blockidx]); - - // Have data ready, lets write - // Order - // write blocks 1..7 page 0 - // write blocks 1..3 page 1 - // update downlink mode (if needed) and write b 0 - downlink_mode = 0; - if ((((data[11] >> 28) & 0xf) == 6) || (((data[11] >> 28) & 0xf) == 9)) - downlink_mode = (data[11] >> 10) & 3; - - // write out blocks 1-7 page 0 - for (blockidx = 1; blockidx <= 7; blockidx++) { - snprintf(writeCmdOpt, sizeof(writeCmdOpt), "b %d d %08X %s", blockidx, data[blockidx], pwdOpt); - - if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS) - PrintAndLogEx(WARNING, "Warning: error writing blk %d", blockidx); - } - - // if password was set on the "blank" update as we may have just changed it - if (usepwd) - snprintf(pwdOpt, sizeof(pwdOpt), "p %08X", data[7]); - - // write out blocks 1-3 page 1 - for (blockidx = 9; blockidx <= 11; blockidx++) { - snprintf(writeCmdOpt, sizeof(writeCmdOpt), "b %d 1 d %08X %s", blockidx - 8, data[blockidx], pwdOpt); - - if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS) - PrintAndLogEx(WARNING, "Warning: error writing blk %d", blockidx); - } - - // Update downlink mode for the page 0 config write. - config.downlink_mode = downlink_mode; - - // Write the page 0 config - snprintf(writeCmdOpt, sizeof(writeCmdOpt), "b 0 d %08X %s", data[0], pwdOpt); - if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS) - PrintAndLogEx(WARNING, "Warning: error writing blk 0"); + } else { + PrintAndLogEx(WARNING, "\nWarning: invalid dump filename "_YELLOW_("%s")" to restore!\n", filename); } } + if (retval != PM3_SUCCESS) { + return retval; + } + + if (datalen == T55x7_BLOCK_COUNT * 4) { + // 12 blocks * 4 bytes per block + + // this fct creats strings to call "lf t55 write" command. + // + // + uint8_t downlink_mode; + char writeCmdOpt[100]; + char pwdOpt [11] = {0}; // p XXXXXXXX + + if (usepwd) + snprintf(pwdOpt, sizeof(pwdOpt), "p %08X", password); + + uint8_t idx; + // Restore endien for writing to card + for (idx = 0; idx < 12; idx++) { + data[idx] = BSWAP_32(data[idx]); + } + + // Have data ready, lets write + // Order + // write blocks 1..7 page 0 + // write blocks 1..3 page 1 + // update downlink mode (if needed) and write b 0 + downlink_mode = 0; + if ((((data[11] >> 28) & 0xf) == 6) || (((data[11] >> 28) & 0xf) == 9)) + downlink_mode = (data[11] >> 10) & 3; + + // write out blocks 1-7 page 0 + for (idx = 1; idx <= 7; idx++) { + snprintf(writeCmdOpt, sizeof(writeCmdOpt), "b %d d %08X %s", idx, data[idx], pwdOpt); + + if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "Warning: error writing blk %d", idx); + } + } + + // if password was set on the "blank" update as we may have just changed it + if (usepwd) { + snprintf(pwdOpt, sizeof(pwdOpt), "p %08X", data[7]); + } + + // write out blocks 1-3 page 1 + for (idx = 9; idx <= 11; idx++) { + snprintf(writeCmdOpt, sizeof(writeCmdOpt), "b %d 1 d %08X %s", idx - 8, data[idx], pwdOpt); + + if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "Warning: error writing blk %d", idx); + } + } + + // Update downlink mode for the page 0 config write. + config.downlink_mode = downlink_mode; + + // Write the page 0 config + snprintf(writeCmdOpt, sizeof(writeCmdOpt), "b 0 d %08X %s", data[0], pwdOpt); + if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "Warning: error writing blk 0"); + } + } return PM3_SUCCESS; } /* From caf9e9cecc746a74afa966d1ef3b62cebb4cd8de Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 15:01:56 +0100 Subject: [PATCH 11/67] lf t55xx trace, info - now uses cliparser --- client/src/cmdlft55xx.c | 382 +++++++++++++++++++++------------------- 1 file changed, 204 insertions(+), 178 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 677b9417b..0637859a5 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -176,38 +176,6 @@ static int usage_t55xx_write(void) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } -static int usage_t55xx_trace(void) { - PrintAndLogEx(NORMAL, "Usage: lf t55xx trace [1] [r mode]"); - PrintAndLogEx(NORMAL, "Options:"); - print_usage_t55xx_downloadlink(T55XX_DLMODE_SINGLE, config.downlink_mode); - PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx trace")); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx trace 1")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} -static int usage_t55xx_info(void) { - PrintAndLogEx(NORMAL, "Usage: lf t55xx info [1] [r ] [c [q]]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " (default) - read data from tag."); - PrintAndLogEx(NORMAL, " p - OPTIONAL password 4bytes (8 hex symbols)"); - PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer instead of reading tag."); - PrintAndLogEx(NORMAL, " c - set configuration from a block0"); - PrintAndLogEx(NORMAL, " if set, use these data instead of reading tag."); - PrintAndLogEx(NORMAL, " q - if set, provided data are interpreted as Q5 config."); - print_usage_t55xx_downloadlink(T55XX_DLMODE_SINGLE, config.downlink_mode); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx info")); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx info 1")); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx info d 00083040")); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx info d 6001805A q")); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx info p 11223344")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} static int usage_t55xx_clonehelp(void) { PrintAndLogEx(NORMAL, "For cloning specific techs on T55xx tags, see commands available in corresponding LF sub-menus, e.g.:"); @@ -973,8 +941,6 @@ static int CmdT55xxDetect(const char *Cmd) { else // This will set the default to user all d/l modes which will cover the ra flag as well. try_all_dl_modes = true; - // if (ra) - // try_all_dl_modes = true; bool try_with_pwd = false; bool found = false; @@ -1713,36 +1679,46 @@ static int CmdT55xxDangerousRaw(const char *Cmd) { static int CmdT55xxReadTrace(const char *Cmd) { - bool frombuff = false; - uint8_t downlink_mode = config.downlink_mode; - uint8_t cmdp = 0; - bool errors = false; + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf t55xx trace", + "Show T55x7 configuration data (page 0/ blk 0) from reading the configuration block", + "lf t55xx trace\n" + "lf t55xx trace -1" + ); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_t55xx_trace(); - case 'r': - downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10); - if (downlink_mode > 3) - downlink_mode = 0; + // 1 (help) + 1 (one user specified params) + (5 T55XX_DLMODE_SINGLE) + void *argtable[2 + 5] = { + arg_param_begin, + arg_lit0("1", NULL, "extract using data from graphbuffer"), + }; + uint8_t idx = 2; + arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_SINGLE, config.downlink_mode); + CLIExecWithReturn(ctx, Cmd, argtable, true); - cmdp += 2; - break; - case '1': - frombuff = true; - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } + bool use_gb = arg_get_lit(ctx, 1); + + bool r0 = arg_get_lit(ctx, 2); + bool r1 = arg_get_lit(ctx, 3); + bool r2 = arg_get_lit(ctx, 4); + bool r3 = arg_get_lit(ctx, 5); + CLIParserFree(ctx); + + if ((r0 + r1 + r2 + r3) > 1) { + PrintAndLogEx(FAILED, "Error multiple downlink encoding"); + return PM3_EINVARG; } - if (errors) return usage_t55xx_trace(); + uint8_t downlink_mode = config.downlink_mode; + if (r0) + downlink_mode = refFixedBit; + else if (r1) + downlink_mode = refLongLeading; + else if (r2) + downlink_mode = refLeading0; + else if (r3) + downlink_mode = ref1of4; - if (!frombuff) { + if (use_gb == false) { // sanity check. if (SanityOfflineCheck(false) != PM3_SUCCESS) return PM3_ENODATA; @@ -1755,12 +1731,18 @@ static int CmdT55xxReadTrace(const char *Cmd) { } if (config.Q5) { - if (!DecodeT5555TraceBlock()) return PM3_ESOFT; + if (DecodeT5555TraceBlock() == false) { + return PM3_ESOFT; + } } else { - if (!DecodeT55xxBlock()) return PM3_ESOFT; + if (DecodeT55xxBlock() == false) { + return PM3_ESOFT; + } } - if (!DemodBufferLen) return PM3_ESOFT; + if (DemodBufferLen == 0){ + return PM3_ESOFT; + } RepaintGraphWindow(); uint8_t repeat = (config.offset > 5) ? 32 : 0; @@ -1865,22 +1847,21 @@ static int CmdT55xxReadTrace(const char *Cmd) { } void printT55x7Trace(t55x7_tracedata_t data, uint8_t repeat) { - PrintAndLogEx(NORMAL, "--- " _CYAN_("T55x7 Trace Information") " ----------------------------------"); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - PrintAndLogEx(NORMAL, " ACL Allocation class (ISO/IEC 15963-1) : 0x%02X (%d)", data.acl, data.acl); - PrintAndLogEx(NORMAL, " MFC Manufacturer ID (ISO/IEC 7816-6) : 0x%02X (%d) - %s", data.mfc, data.mfc, getTagInfo(data.mfc)); - PrintAndLogEx(NORMAL, " CID : 0x%02X (%d) - %s", data.cid, data.cid, GetModelStrFromCID(data.cid)); - PrintAndLogEx(NORMAL, " ICR IC Revision : %d", data.icr); - PrintAndLogEx(NORMAL, " Manufactured"); - PrintAndLogEx(NORMAL, " Year/Quarter : %d/%d", data.year, data.quarter); - PrintAndLogEx(NORMAL, " Lot ID : %d", data.lotid); - PrintAndLogEx(NORMAL, " Wafer number : %d", data.wafer); - PrintAndLogEx(NORMAL, " Die Number : %d", data.dw); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - PrintAndLogEx(NORMAL, " Raw Data - Page 1"); - PrintAndLogEx(NORMAL, " Block 1 : 0x%08X %s", data.bl1, sprint_bin(DemodBuffer + config.offset + repeat, 32)); - PrintAndLogEx(NORMAL, " Block 2 : 0x%08X %s", data.bl2, sprint_bin(DemodBuffer + config.offset + repeat + 32, 32)); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, "--- " _CYAN_("T55x7 Trace Information") " ----------------------------------"); + PrintAndLogEx(INFO, " ACL Allocation class (ISO/IEC 15963-1) : 0x%02X ( %d )", data.acl, data.acl); + PrintAndLogEx(INFO, " MFC Manufacturer ID (ISO/IEC 7816-6) : 0x%02X ( %d ) - %s", data.mfc, data.mfc, getTagInfo(data.mfc)); + PrintAndLogEx(INFO, " CID : 0x%02X ( %d ) - %s", data.cid, data.cid, GetModelStrFromCID(data.cid)); + PrintAndLogEx(INFO, " ICR IC Revision : %d", data.icr); + PrintAndLogEx(INFO, " Manufactured"); + PrintAndLogEx(INFO, " Year/Quarter... %d/%d", data.year, data.quarter); + PrintAndLogEx(INFO, " Lot ID......... %d", data.lotid); + PrintAndLogEx(INFO, " Wafer number... %d", data.wafer); + PrintAndLogEx(INFO, " Die Number..... %d", data.dw); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, " Raw Data - Page 1"); + PrintAndLogEx(INFO, " Block 1... %08X - %s", data.bl1, sprint_bin(DemodBuffer + config.offset + repeat, 32)); + PrintAndLogEx(INFO, " Block 2... %08X - %s", data.bl2, sprint_bin(DemodBuffer + config.offset + repeat + 32, 32)); + PrintAndLogEx(NORMAL, ""); /* Trace info. @@ -1912,16 +1893,15 @@ void printT55x7Trace(t55x7_tracedata_t data, uint8_t repeat) { } void printT5555Trace(t5555_tracedata_t data, uint8_t repeat) { - PrintAndLogEx(NORMAL, "--- " _CYAN_("Q5/T5555 Trace Information") " ---------------------------"); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - PrintAndLogEx(NORMAL, " ICR IC Revision : %d", data.icr); - PrintAndLogEx(NORMAL, " Lot : %c%d", data.lotidc, data.lotid); - PrintAndLogEx(NORMAL, " Wafer number : %d", data.wafer); - PrintAndLogEx(NORMAL, " Die Number : %d", data.dw); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - PrintAndLogEx(NORMAL, " Raw Data - Page 1"); - PrintAndLogEx(NORMAL, " Block 1 : 0x%08X %s", data.bl1, sprint_bin(DemodBuffer + config.offset + repeat, 32)); - PrintAndLogEx(NORMAL, " Block 2 : 0x%08X %s", data.bl2, sprint_bin(DemodBuffer + config.offset + repeat + 32, 32)); + PrintAndLogEx(INFO, "--- " _CYAN_("Q5/T5555 Trace Information") " ---------------------------"); + PrintAndLogEx(INFO, " ICR IC Revision.... %d", data.icr); + PrintAndLogEx(INFO, " Lot ID......... %c%d", data.lotidc, data.lotid); + PrintAndLogEx(INFO, " Wafer number... %d", data.wafer); + PrintAndLogEx(INFO, " Die Number..... %d", data.dw); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, " Raw Data - Page 1"); + PrintAndLogEx(INFO, " Block 1... %08X - %s", data.bl1, sprint_bin(DemodBuffer + config.offset + repeat, 32)); + PrintAndLogEx(INFO, " Block 2... %08X - %s", data.bl2, sprint_bin(DemodBuffer + config.offset + repeat + 32, 32)); /* ** Q5 ** @@ -2015,75 +1995,121 @@ static void printT5x7KnownBlock0(uint32_t b0) { break; } - if (strlen(s) > 0) - PrintAndLogEx(SUCCESS, "\nConfig block match : " _YELLOW_("%s"), s); + if (strlen(s) > 0) { + PrintAndLogEx(SUCCESS, "Config block match : " _YELLOW_("%s"), s); + } } static int CmdT55xxInfo(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf t55xx info", + "Show T55x7 configuration data (page 0/ blk 0) from reading the configuration block\n" + "from tag. Use `-c` to specify a config block data to be used instead of reading tag.", + "lf t55xx info\n" + "lf t55xx info -1\n" + "lf t55xx info -p 11223344\n" + "lf t55xx info -c 00083040\n" + "lf t55xx info -c 6001805A --q5" + ); + + // 1 (help) + 4 (four user specified params) + (5 T55XX_DLMODE_SINGLE) + void *argtable[5 + 5] = { + arg_param_begin, + arg_lit0("1", NULL, "extract using data from graphbuffer"), + arg_str0("p", "pwd", "", "password (4 hex bytes)"), + arg_str0("c", "blk0", "", "use these data instead (4 hex bytes)"), + arg_lit0(NULL, "q5", "interprete provided data as T5555/Q5 config"), + }; + uint8_t idx = 5; + arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_SINGLE, config.downlink_mode); + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool use_gb = arg_get_lit(ctx, 1); + + bool usepwd = false; + uint32_t password = 0; + int res = arg_get_u32_hexstr_def_nlen(ctx, 2, 0, &password, 4, true); + if (res == 0 || res == 2) { + PrintAndLogEx(ERR, "Password must be 4 hex bytes"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + if (res == 1) { + usepwd = true; + } + + bool gotdata = false; + uint32_t block0 = 0; + res = arg_get_u32_hexstr_def_nlen(ctx, 3, 0, &block0, 4, true); + if (res == 0 || res == 2) { + PrintAndLogEx(ERR, "block0 data must be 4 hex bytes"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + if (res == 1) { + gotdata = true; + } + + bool dataasq5 = arg_get_lit(ctx, 4); + + bool r0 = arg_get_lit(ctx, 5); + bool r1 = arg_get_lit(ctx, 6); + bool r2 = arg_get_lit(ctx, 7); + bool r3 = arg_get_lit(ctx, 8); + CLIParserFree(ctx); + + if (gotdata && use_gb) { + PrintAndLogEx(FAILED, "Must select one of user supplied data and use graphbuffer"); + return PM3_EINVARG; + } + + if (dataasq5 && gotdata == false) { + PrintAndLogEx(FAILED, "Must specify user supplied Q5 data"); + return PM3_EINVARG; + } + + if ((r0 + r1 + r2 + r3) > 1) { + PrintAndLogEx(FAILED, "Error multiple downlink encoding"); + return PM3_EINVARG; + } + + uint8_t downlink_mode = config.downlink_mode; + if (r0) + downlink_mode = refFixedBit; + else if (r1) + downlink_mode = refLongLeading; + else if (r2) + downlink_mode = refLeading0; + else if (r3) + downlink_mode = ref1of4; + + /* Page 0 Block 0 Configuration data. Normal mode Extended mode */ - bool frombuff = false, gotdata = false, dataasq5 = false, usepwd = false; - uint8_t cmdp = 0; - uint8_t downlink_mode = config.downlink_mode; - uint32_t block0 = 0, password = 0; - while (param_getchar(Cmd, cmdp) != 0x00) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_t55xx_info(); - case 'c': - block0 = param_get32ex(Cmd, cmdp + 1, 0, 16); - gotdata = true; - cmdp += 2; - break; - case 'p': - password = param_get32ex(Cmd, cmdp + 1, 0, 16); - usepwd = true; - cmdp += 2; - break; - case '1': - frombuff = true; - cmdp += 2; - break; - case 'q': - dataasq5 = true; - cmdp += 2; - break; - case 'r': - downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10); - if (downlink_mode > 3) - downlink_mode = 0; + if (use_gb == false && gotdata == false) { + // sanity check. + if (SanityOfflineCheck(false) != PM3_SUCCESS) { + return PM3_ENODATA; + } - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - return usage_t55xx_info(); + if (!AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, downlink_mode)) { + return PM3_ENODATA; } } - if (gotdata && frombuff) - return usage_t55xx_info(); - - if (dataasq5 && !gotdata) - return usage_t55xx_info(); - - if (!frombuff && !gotdata) { - // sanity check. - if (SanityOfflineCheck(false) != PM3_SUCCESS) return PM3_ENODATA; - - if (!AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password, downlink_mode)) - return PM3_ENODATA; - } - - if (!gotdata) { - if (!DecodeT55xxBlock()) return PM3_ESOFT; + if (gotdata == false) { + if (DecodeT55xxBlock() == false) { + return PM3_ESOFT; + } // too little space to start with - if (DemodBufferLen < 32 + config.offset) return PM3_ESOFT; + if (DemodBufferLen < 32 + config.offset) { + return PM3_ESOFT; + } //PrintAndLogEx(NORMAL, "Offset+32 ==%d\n DemodLen == %d", config.offset + 32, DemodBufferLen); block0 = PackBits(config.offset, 32, DemodBuffer); @@ -2102,19 +2128,18 @@ static int CmdT55xxInfo(const char *Cmd) { uint32_t datamod = (block0 >> (32 - 28)) & 0x07; uint32_t maxblk = (block0 >> (32 - 31)) & 0x07; uint32_t st = block0 & 0x01; - PrintAndLogEx(NORMAL, "--- " _CYAN_("Q5 Configuration & Information") " ------------"); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - PrintAndLogEx(NORMAL, " Header : 0x%03X%s", header, (header != 0x600) ? _RED_(" - Warning") : ""); - PrintAndLogEx(NORMAL, " Page select : %d", ps); - PrintAndLogEx(NORMAL, " Fast Write : %s", (fw) ? _GREEN_("Yes") : "No"); - PrintAndLogEx(NORMAL, " Data bit rate : %s", GetBitRateStr(dbr, 1)); - PrintAndLogEx(NORMAL, " AOR - Answer on Request : %s", (aor) ? _GREEN_("Yes") : "No"); - PrintAndLogEx(NORMAL, " Password mode : %s", (pwd) ? _GREEN_("Yes") : "No"); - PrintAndLogEx(NORMAL, " PSK clock frequency : %s", GetPskCfStr(pskcf, 1)); - PrintAndLogEx(NORMAL, " Inverse data : %s", (inv) ? _GREEN_("Yes") : "No"); - PrintAndLogEx(NORMAL, " Modulation : %s", GetQ5ModulationStr(datamod)); - PrintAndLogEx(NORMAL, " Max block : %d", maxblk); - PrintAndLogEx(NORMAL, " Sequence Terminator : %s", (st) ? _GREEN_("Yes") : "No"); + PrintAndLogEx(INFO, "--- " _CYAN_("Q5 Configuration & Information") " ------------"); + PrintAndLogEx(INFO, " Header : 0x%03X%s", header, (header != 0x600) ? _RED_(" - Warning") : ""); + PrintAndLogEx(INFO, " Page select : %d", ps); + PrintAndLogEx(INFO, " Fast Write : %s", (fw) ? _GREEN_("Yes") : "No"); + PrintAndLogEx(INFO, " Data bit rate : %s", GetBitRateStr(dbr, 1)); + PrintAndLogEx(INFO, " AOR - Answer on Request : %s", (aor) ? _GREEN_("Yes") : "No"); + PrintAndLogEx(INFO, " Password mode : %s", (pwd) ? _GREEN_("Yes") : "No"); + PrintAndLogEx(INFO, " PSK clock frequency : %s", GetPskCfStr(pskcf, 1)); + PrintAndLogEx(INFO, " Inverse data : %s", (inv) ? _GREEN_("Yes") : "No"); + PrintAndLogEx(INFO, " Modulation : %s", GetQ5ModulationStr(datamod)); + PrintAndLogEx(INFO, " Max block : %d", maxblk); + PrintAndLogEx(INFO, " Sequence Terminator : %s", (st) ? _GREEN_("Yes") : "No"); } else { uint32_t safer = (block0 >> (32 - 4)) & 0x0F; uint32_t extend = (block0 >> (32 - 15)) & 0x01; @@ -2137,35 +2162,36 @@ static int CmdT55xxInfo(const char *Cmd) { uint32_t inv = (block0 >> (32 - 31)) & 0x01; uint32_t por = (block0 >> (32 - 32)) & 0x01; - PrintAndLogEx(NORMAL, "--- " _CYAN_("T55x7 Configuration & Information") " ---------"); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - PrintAndLogEx(NORMAL, " Safer key : %s", GetSaferStr(safer)); - PrintAndLogEx(NORMAL, " reserved : %d", resv); - PrintAndLogEx(NORMAL, " Data bit rate : %s", GetBitRateStr(dbr, extend)); - PrintAndLogEx(NORMAL, " eXtended mode : %s", (extend) ? _YELLOW_("Yes - Warning") : "No"); - PrintAndLogEx(NORMAL, " Modulation : %s", GetModulationStr(datamod, extend)); - PrintAndLogEx(NORMAL, " PSK clock frequency : %s", GetPskCfStr(pskcf, 0)); - PrintAndLogEx(NORMAL, " AOR - Answer on Request : %s", (aor) ? _GREEN_("Yes") : "No"); - PrintAndLogEx(NORMAL, " OTP - One Time Pad : %s", (otp) ? ((extend) ? _YELLOW_("Yes - Warning") : _RED_("Yes - Warning")) : "No"); - PrintAndLogEx(NORMAL, " Max block : %d", maxblk); - PrintAndLogEx(NORMAL, " Password mode : %s", (pwd) ? _GREEN_("Yes") : "No"); - PrintAndLogEx(NORMAL, " Sequence %-12s : %s", (extend) ? "Start Marker" : "Terminator", (sst) ? _GREEN_("Yes") : "No"); - PrintAndLogEx(NORMAL, " Fast Write : %s", (fw) ? ((extend) ? _GREEN_("Yes") : _RED_("Yes - Warning")) : "No"); - PrintAndLogEx(NORMAL, " Inverse data : %s", (inv) ? ((extend) ? _GREEN_("Yes") : _RED_("Yes - Warning")) : "No"); - PrintAndLogEx(NORMAL, " POR-Delay : %s", (por) ? _GREEN_("Yes") : "No"); + PrintAndLogEx(INFO, "--- " _CYAN_("T55x7 Configuration & Information") " ---------"); + PrintAndLogEx(INFO, " Safer key : %s", GetSaferStr(safer)); + PrintAndLogEx(INFO, " reserved : %d", resv); + PrintAndLogEx(INFO, " Data bit rate : %s", GetBitRateStr(dbr, extend)); + PrintAndLogEx(INFO, " eXtended mode : %s", (extend) ? _YELLOW_("Yes - Warning") : "No"); + PrintAndLogEx(INFO, " Modulation : %s", GetModulationStr(datamod, extend)); + PrintAndLogEx(INFO, " PSK clock frequency : %s", GetPskCfStr(pskcf, 0)); + PrintAndLogEx(INFO, " AOR - Answer on Request : %s", (aor) ? _GREEN_("Yes") : "No"); + PrintAndLogEx(INFO, " OTP - One Time Pad : %s", (otp) ? ((extend) ? _YELLOW_("Yes - Warning") : _RED_("Yes - Warning")) : "No"); + PrintAndLogEx(INFO, " Max block : %d", maxblk); + PrintAndLogEx(INFO, " Password mode : %s", (pwd) ? _GREEN_("Yes") : "No"); + PrintAndLogEx(INFO, " Sequence %-12s : %s", (extend) ? "Start Marker" : "Terminator", (sst) ? _GREEN_("Yes") : "No"); + PrintAndLogEx(INFO, " Fast Write : %s", (fw) ? ((extend) ? _GREEN_("Yes") : _RED_("Yes - Warning")) : "No"); + PrintAndLogEx(INFO, " Inverse data : %s", (inv) ? ((extend) ? _GREEN_("Yes") : _RED_("Yes - Warning")) : "No"); + PrintAndLogEx(INFO, " POR-Delay : %s", (por) ? _GREEN_("Yes") : "No"); } - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - PrintAndLogEx(NORMAL, " Raw Data - Page 0, block 0"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, " Raw Data - Page 0, block 0"); if (gotdata) - PrintAndLogEx(NORMAL, " 0x" _GREEN_("%08X"), block0); + PrintAndLogEx(INFO, " " _GREEN_("%08X"), block0); else - PrintAndLogEx(NORMAL, " 0x" _GREEN_("%08X") " %s", block0, sprint_bin(DemodBuffer + config.offset, 32)); + PrintAndLogEx(INFO, " " _GREEN_("%08X") " - %s", block0, sprint_bin(DemodBuffer + config.offset, 32)); - if (((!gotdata) && (!config.Q5)) || (gotdata && (!dataasq5))) + if (((!gotdata) && (!config.Q5)) || (gotdata && (!dataasq5))) { + PrintAndLogEx(INFO, "--- " _CYAN_("Fingerprint") " ------------"); printT5x7KnownBlock0(block0); + } - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - + PrintAndLogEx(NORMAL, ""); + //PrintAndLogEx(INFO, "-------------------------------------------------------------"); return PM3_SUCCESS; } From 964aee329f2346c05e4f43bc029f12df20768c09 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 15:08:38 +0100 Subject: [PATCH 12/67] lf t55xx resetread - now uses cliparser --- client/src/cmdlft55xx.c | 74 ++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 0637859a5..30d60ff61 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -147,17 +147,7 @@ static int usage_t55xx_read(void) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } -static int usage_t55xx_resetread(void) { - PrintAndLogEx(NORMAL, "Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)"); - PrintAndLogEx(NORMAL, "Usage: lf t55xx resetread [r ]"); - PrintAndLogEx(NORMAL, "Options:"); - print_usage_t55xx_downloadlink(T55XX_DLMODE_SINGLE, config.downlink_mode); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx resetread")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} + static int usage_t55xx_write(void) { PrintAndLogEx(NORMAL, "Usage: lf t55xx write [r ] b d [p ] [1] [t] [v]"); PrintAndLogEx(NORMAL, "Options:"); @@ -2818,38 +2808,51 @@ static void t55x7_create_config_block(int tagtype) { static int CmdResetRead(const char *Cmd) { - uint8_t downlink_mode = config.downlink_mode; - uint8_t flags = 0; - uint8_t cmdp = 0; - bool errors = false; + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf t55xx resetread", + "Send Reset Cmd then `lf read` the stream to attempt\n" + "to identify the start of it (needs a demod and/or plot after)", + "lf t55xx resetread" + ); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_t55xx_resetread(); - case 'r': - downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10); - if (downlink_mode > 3) - downlink_mode = 0; + // 1 (help) + 0(one user specified params) + (5 T55XX_DLMODE_SINGLE) + void *argtable[0 + 5] = { + arg_param_begin, + arg_lit0("1", NULL, "extract using data from graphbuffer"), + }; + uint8_t idx = 1; + arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_SINGLE, config.downlink_mode); + CLIExecWithReturn(ctx, Cmd, argtable, true); - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } + bool r0 = arg_get_lit(ctx, 1); + bool r1 = arg_get_lit(ctx, 2); + bool r2 = arg_get_lit(ctx, 3); + bool r3 = arg_get_lit(ctx, 4); + CLIParserFree(ctx); + + if ((r0 + r1 + r2 + r3) > 1) { + PrintAndLogEx(FAILED, "Error multiple downlink encoding"); + return PM3_EINVARG; } - if (errors) return usage_t55xx_resetread(); + uint8_t downlink_mode = config.downlink_mode; + if (r0) + downlink_mode = refFixedBit; + else if (r1) + downlink_mode = refLongLeading; + else if (r2) + downlink_mode = refLeading0; + else if (r3) + downlink_mode = ref1of4; - flags = downlink_mode << 3; + uint8_t flags = downlink_mode << 3; + + PrintAndLogEx(INFO, "Sending reset command..."); PacketResponseNG resp; - clearCommandBuffer(); SendCommandNG(CMD_LF_T55XX_RESET_READ, &flags, sizeof(flags)); - if (!WaitForResponseTimeout(CMD_LF_T55XX_RESET_READ, &resp, 2500)) { + if (WaitForResponseTimeout(CMD_LF_T55XX_RESET_READ, &resp, 2500) == false) { PrintAndLogEx(WARNING, "command execution time out"); return PM3_ETIMEOUT; } @@ -2863,6 +2866,7 @@ static int CmdResetRead(const char *Cmd) { return PM3_EMALLOC; } + PrintAndLogEx(INFO, "Downloading samples..."); if (!GetFromDevice(BIG_BUF, got, gotsize, 0, NULL, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "command execution time out"); free(got); @@ -2871,6 +2875,8 @@ static int CmdResetRead(const char *Cmd) { setGraphBuf(got, gotsize); free(got); } + + PrintAndLogEx(INFO, "Done"); return PM3_SUCCESS; } From 0067a9b7fa61a4f1a6e2250a17eae21eb9296ece Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 18:55:48 +0100 Subject: [PATCH 13/67] for commands with many params --- client/deps/cliparser/argtable3.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/client/deps/cliparser/argtable3.c b/client/deps/cliparser/argtable3.c index 783bd303b..dfcccb81b 100644 --- a/client/deps/cliparser/argtable3.c +++ b/client/deps/cliparser/argtable3.c @@ -4639,11 +4639,13 @@ void arg_print_syntax(FILE *fp, void * *argtable, const char *suffix) { /* print GNU style [OPTION] string */ arg_print_gnuswitch(fp, table); + size_t len = 0; + /* print remaining options in abbreviated style */ for (tabindex = 0; table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { - char syntax[200] = ""; + char syntax[400] = ""; const char *shortopts, *longopts, *datatype; /* skip short options without arg values (they were printed by arg_print_gnu_switch) */ @@ -4681,6 +4683,12 @@ void arg_print_syntax(FILE *fp, void * *argtable, const char *suffix) { break; } } + + len += strlen(syntax); + if (len > 60) { + fprintf(fp, "\n "); + len = 0; + } } if (suffix) From 827c529aea08a654ac0ca20a0083fd2c356d982a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 18:56:37 +0100 Subject: [PATCH 14/67] lf t55 config - now uses cliparser... and texts --- client/src/cmdlft55xx.c | 348 +++++++++++++++++++++------------------- client/src/cmdlft55xx.h | 8 +- 2 files changed, 189 insertions(+), 167 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 30d60ff61..4f4e6ca27 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -50,7 +50,7 @@ t55xx_conf_block_t config = { .inverted = false, .offset = 0x00, .block0 = 0x00, - .block0Status = notSet, + .block0Status = NOTSET, .Q5 = false, .usepwd = false, .downlink_mode = refFixedBit @@ -106,27 +106,7 @@ static void arg_add_t55xx_downloadlink(void *at[], uint8_t *idx, uint8_t show, u *idx = n; } -static int usage_t55xx_config(void) { - PrintAndLogEx(NORMAL, "Usage: lf t55xx config [c ] [d ] [i [0/1]] [o ] [Q5 [0/1]] [ST [0/1]]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - This help"); - PrintAndLogEx(NORMAL, " c - set configuration from a block0"); - PrintAndLogEx(NORMAL, " b <8|16|32|40|50|64|100|128> - Set bitrate"); - PrintAndLogEx(NORMAL, " d - Set demodulation FSK / ASK / PSK / NRZ / Biphase / Biphase A"); - PrintAndLogEx(NORMAL, " i [0/1] - Set/reset data signal inversion"); - PrintAndLogEx(NORMAL, " o [offset] - Set offset, where data should start decode in bitstream"); - PrintAndLogEx(NORMAL, " Q5 [0/1] - Set/reset as Q5/T5555 chip instead of T55x7"); - PrintAndLogEx(NORMAL, " ST [0/1] - Set/reset Sequence Terminator on"); - PrintAndLogEx(NORMAL, ""); // layout is a little differnet, so seperate until a better fix - print_usage_t55xx_downloadlink(T55XX_DLMODE_SINGLE, config.downlink_mode); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx config d FSK") " - FSK demodulation"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx config d FSK i 1") " - FSK demodulation, inverse data"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx config d FSK i 1 o 3") " - FSK demodulation, inverse data, offset=3,start from position 3 to decode data"); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} + static int usage_t55xx_read(void) { PrintAndLogEx(NORMAL, "Usage: lf t55xx read [r ] b [p ] [o] "); PrintAndLogEx(NORMAL, "Options:"); @@ -489,141 +469,183 @@ void SetConfigWithBlock0Ex(uint32_t block0, uint8_t offset, bool Q5) { } static int CmdT55xxSetConfig(const char *Cmd) { - // No args - if (strlen(Cmd) == 0) return printConfiguration(config); + if (strlen(Cmd) == 0) { + PrintAndLogEx(INFO, "--- " _CYAN_("current t55xx config") " --------------------------"); + return printConfiguration(config); + } + + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf t55xx config", + "Set/Get T55XX configuration of the pm3 client. Like modulation, inverted, offset, rate etc.\n" + "Offset is start position to decode data.", + "lf t55xx config --FSK --> FSK demodulation\n" + "lf t55xx config --FSK -i --> FSK demodulation, inverse data\n" + "lf t55xx config --FSK -i -o 3 --> FSK demodulation, inverse data, offset 3\n" + ); + + // 1 (help) + 19 (user specified params) + (5 T55XX_DLMODE_SINGLE) + void *argtable[1 + 12 + 6 + 5] = { + arg_param_begin, + arg_lit0(NULL, "FSK", "set demodulation FSK"), + arg_lit0(NULL, "FSK1", "set demodulation FSK 1"), + arg_lit0(NULL, "FSK1A", "set demodulation FSK 1a (inv)"), + arg_lit0(NULL, "FSK2", "set demodulation FSK 2"), + arg_lit0(NULL, "FSK2A", "set demodulation FSK 2a (inv)"), + arg_lit0(NULL, "ASK", "set demodulation ASK"), + arg_lit0(NULL, "PSK1", "set demodulation PSK 1"), + arg_lit0(NULL, "PSK2", "set demodulation PSK 2"), + arg_lit0(NULL, "PSK3", "set demodulation PSK 3"), + arg_lit0(NULL, "NRZ", "set demodulation NRZ"), + arg_lit0(NULL, "BI", "set demodulation Biphase"), + arg_lit0(NULL, "BIA", "set demodulation Diphase (inverted biphase)"), + arg_lit0("i", "inv", "set/reset data signal inversion"), + arg_lit0(NULL, "q5", "set/reset as Q5/T5555 chip instead of T55x7"), + arg_lit0(NULL, "st", "set/reset Sequence Terminator on"), + arg_int0(NULL, "rate", "", "set bitrate <8|16|32|40|50|64|100|128>"), + arg_str0("c", "blk0", "", "set configuration from a block0 (4 hex bytes)"), + arg_int0("o", "offset", "", "set offset, where data should start decode in bitstream"), + }; + + uint8_t idx = 19; + arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_SINGLE, config.downlink_mode); + CLIExecWithReturn(ctx, Cmd, argtable, true); + + idx = 1; + bool mods[12]; + int verify_mods = 0; + while (idx - 1 < sizeof(mods)) { + mods[idx - 1] = arg_get_lit(ctx, idx); + verify_mods += mods[idx - 1]; + idx++; + } + + bool invert = arg_get_lit(ctx, idx++); + bool use_q5 = arg_get_lit(ctx, idx++); + bool use_st = arg_get_lit(ctx, idx++); + + int bitrate = arg_get_int_def(ctx, idx++, -1); - uint8_t offset = 0, bitRate = 0; - char modulation[6] = {0x00}; - uint8_t rates[9] = {8, 16, 32, 40, 50, 64, 100, 128, 0}; - uint8_t cmdp = 0; - uint8_t downlink_mode = 0; - bool errors = false; - uint32_t block0 = 0; bool gotconf = false; + uint32_t block0 = 0; + int res = arg_get_u32_hexstr_def_nlen(ctx, idx++, 0, &block0, 4, true); + if (res == 0 || res == 2) { + PrintAndLogEx(ERR, "block0 data must be 4 hex bytes"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + if (res == 1) { + gotconf = true; + } - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - char tmp = tolower(param_getchar(Cmd, cmdp)); - switch (tmp) { - case 'h': - return usage_t55xx_config(); - case 'b': - errors |= param_getdec(Cmd, cmdp + 1, &bitRate); - if (!errors) { - uint8_t i = 0; - for (; i < 9; i++) { - if (rates[i] == bitRate) { - config.bitrate = i; - config.block0 = ((config.block0 & ~(0x1c0000)) | (i << 18)); - break; - } - } - if (i == 9) errors = true; - } - cmdp += 2; - break; - case 'c': - block0 = param_get32ex(Cmd, cmdp + 1, 0, 16); - gotconf = true; - cmdp += 2; - break; - case 'd': - param_getstr(Cmd, cmdp + 1, modulation, sizeof(modulation)); - cmdp += 2; + int offset = arg_get_int_def(ctx, idx++, -1); - if (strcmp(modulation, "FSK") == 0) { - config.modulation = DEMOD_FSK; - } else if (strcmp(modulation, "FSK1") == 0) { - config.modulation = DEMOD_FSK1; - config.inverted = 1; - } else if (strcmp(modulation, "FSK1a") == 0) { - config.modulation = DEMOD_FSK1a; - config.inverted = 0; - } else if (strcmp(modulation, "FSK2") == 0) { - config.modulation = DEMOD_FSK2; - config.inverted = 0; - } else if (strcmp(modulation, "FSK2a") == 0) { - config.modulation = DEMOD_FSK2a; - config.inverted = 1; - } else if (strcmp(modulation, "ASK") == 0) { - config.modulation = DEMOD_ASK; - } else if (strcmp(modulation, "NRZ") == 0) { - config.modulation = DEMOD_NRZ; - } else if (strcmp(modulation, "PSK1") == 0) { - config.modulation = DEMOD_PSK1; - } else if (strcmp(modulation, "PSK2") == 0) { - config.modulation = DEMOD_PSK2; - } else if (strcmp(modulation, "PSK3") == 0) { - config.modulation = DEMOD_PSK3; - } else if (strcmp(modulation, "BIa") == 0) { - config.modulation = DEMOD_BIa; - config.inverted = 1; - } else if (strcmp(modulation, "BI") == 0) { - config.modulation = DEMOD_BI; - config.inverted = 0; - } else { - PrintAndLogEx(WARNING, "Unknown modulation '%s'", modulation); - errors = true; - } - config.block0 = ((config.block0 & ~(0x1f000)) | (config.modulation << 12)); - break; - case 'i': - if ((param_getchar(Cmd, cmdp + 1) == '0') || (param_getchar(Cmd, cmdp + 1) == '1')) { - config.inverted = param_getchar(Cmd, cmdp + 1) == '1'; - cmdp += 2; - } else { - config.inverted = true; - cmdp += 1; - } - break; - case 'o': - errors |= param_getdec(Cmd, cmdp + 1, &offset); - if (!errors) - config.offset = offset; - cmdp += 2; - break; - case 'q': - if ((param_getchar(Cmd, cmdp + 1) == '0') || (param_getchar(Cmd, cmdp + 1) == '1')) { - config.Q5 = param_getchar(Cmd, cmdp + 1) == '1'; - cmdp += 2; - } else { - config.Q5 = true; - cmdp += 1; - } - break; - case 's': - if ((param_getchar(Cmd, cmdp + 1) == '0') || (param_getchar(Cmd, cmdp + 1) == '1')) { - config.ST = param_getchar(Cmd, cmdp + 1) == '1'; - cmdp += 2; - } else { - config.ST = true; - cmdp += 1; - } - config.block0 = ((config.block0 & ~(0x8)) | (config.ST << 3)); - break; - case 'r': - errors = param_getdec(Cmd, cmdp + 1, &downlink_mode); - if (downlink_mode > 3) - downlink_mode = 0; - if (!errors) - config.downlink_mode = downlink_mode; - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; + bool r0 = arg_get_lit(ctx, idx++); + bool r1 = arg_get_lit(ctx, idx++); + bool r2 = arg_get_lit(ctx, idx++); + bool r3 = arg_get_lit(ctx, idx++); + CLIParserFree(ctx); + + // validate user specified downlink mode + if ((r0 + r1 + r2 + r3) > 1) { + PrintAndLogEx(FAILED, "Error multiple downlink encoding"); + return PM3_EINVARG; + } + + // validate user specified modulation FSK,FSK1,...BIA + if (verify_mods > 1) { + PrintAndLogEx(FAILED, "Error multiple demodulations, select one"); + return PM3_EINVARG; + } + + // validate user specified bitrate + uint8_t rates[9] = {8, 16, 32, 40, 50, 64, 100, 128, 0}; + if (bitrate != -1) { + uint8_t i = 0; + for (; i < ARRAYLEN(rates); i++) { + if (rates[i] == bitrate) { + config.bitrate = i; + config.block0 = ((config.block0 & ~(0x1c0000)) | (i << 18)); break; + } + } + if (i == 9){ + PrintAndLogEx(FAILED, "Error select a valid bitrate"); + return PM3_EINVARG; } } - //Validations - if (errors) return usage_t55xx_config(); + // validate user specified offset + if (offset > -1) { + config.offset = offset; + } - config.block0Status = userSet; + // validate user specific T5555 / Q5 + config.Q5 = use_q5; + + // validate user specific sequence terminator + config.ST = use_st; + if (use_st) { + config.block0 = ((config.block0 & ~(0x8)) | (config.ST << 3)); + } + + // validate user specific invert + config.inverted = invert; + + // validate user specific downlink mode + uint8_t downlink_mode = config.downlink_mode; + if (r0) + downlink_mode = refFixedBit; + else if (r1) + downlink_mode = refLongLeading; + else if (r2) + downlink_mode = refLeading0; + else if (r3) + downlink_mode = ref1of4; + + config.downlink_mode = downlink_mode; + + // validate user specific modulation + if (mods[0]){ + config.modulation = DEMOD_FSK; + } else if (mods[1]) { + config.modulation = DEMOD_FSK1; + config.inverted = 0; + } else if (mods[2]) { + config.modulation = DEMOD_FSK1a; + config.inverted = 1; + } else if (mods[3]) { + config.modulation = DEMOD_FSK2; + config.inverted = 0; + } else if (mods[4]) { + config.modulation = DEMOD_FSK2a; + config.inverted = 1; + } else if (mods[5]) { + config.modulation = DEMOD_ASK; + } else if (mods[6]) { + config.modulation = DEMOD_PSK1; + } else if (mods[7]) { + config.modulation = DEMOD_PSK2; + } else if (mods[8]) { + config.modulation = DEMOD_PSK3; + } else if (mods[9]) { + config.modulation = DEMOD_NRZ; + } else if (mods[10]) { + config.modulation = DEMOD_BI; + config.inverted = 0; + } else if (mods[11]) { + config.modulation = DEMOD_BIa; + config.inverted = 1; + } + + config.block0 = ((config.block0 & ~(0x1f000)) | (config.modulation << 12)); + + config.block0Status = USERSET; if (gotconf) { SetConfigWithBlock0Ex(block0, config.offset, config.Q5); } + PrintAndLogEx(INFO, "--- " _CYAN_("current t55xx config") " --------------------------"); return printConfiguration(config); } int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, uint8_t override, uint32_t password, uint8_t downlink_mode) { @@ -1201,7 +1223,7 @@ bool t55xxTryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32 config.pwd = pwd & 0xffffffff; } - config.block0Status = autoDetect; + config.block0Status = AUTODETECT; if (print_config) printConfiguration(config); @@ -1237,7 +1259,7 @@ bool t55xxTryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32 PrintAndLogEx(NORMAL, "--[%d]---------------", i + 1); } - config.block0Status = autoDetect; + config.block0Status = AUTODETECT; if (print_config) printConfiguration(tests[i]); } @@ -1514,17 +1536,17 @@ int CmdT55xxSpecial(const char *Cmd) { } int printConfiguration(t55xx_conf_block_t b) { - PrintAndLogEx(INFO, " Chip Type : " _GREEN_("%s"), (b.Q5) ? "Q5/T5555" : "T55x7"); - PrintAndLogEx(INFO, " Modulation : " _GREEN_("%s"), GetSelectedModulationStr(b.modulation)); - PrintAndLogEx(INFO, " Bit Rate : %s", GetBitRateStr(b.bitrate, (b.block0 & T55x7_X_MODE && (b.block0 >> 28 == 6 || b.block0 >> 28 == 9)))); - PrintAndLogEx(INFO, " Inverted : %s", (b.inverted) ? _GREEN_("Yes") : "No"); - PrintAndLogEx(INFO, " Offset : %d", b.offset); - PrintAndLogEx(INFO, " Seq. Term. : %s", (b.ST) ? _GREEN_("Yes") : "No"); - PrintAndLogEx(INFO, " Block0 : 0x%08X %s", b.block0, GetConfigBlock0Source(b.block0Status)); - PrintAndLogEx(INFO, " Downlink Mode : %s", GetDownlinkModeStr(b.downlink_mode)); - PrintAndLogEx(INFO, " Password Set : %s", (b.usepwd) ? _RED_("Yes") : _GREEN_("No")); + PrintAndLogEx(INFO, " Chip type......... " _GREEN_("%s"), (b.Q5) ? "Q5/T5555" : "T55x7"); + PrintAndLogEx(INFO, " Modulation........ " _GREEN_("%s"), GetSelectedModulationStr(b.modulation)); + PrintAndLogEx(INFO, " Bit rate.......... %s", GetBitRateStr(b.bitrate, (b.block0 & T55x7_X_MODE && (b.block0 >> 28 == 6 || b.block0 >> 28 == 9)))); + PrintAndLogEx(INFO, " Inverted.......... %s", (b.inverted) ? _GREEN_("Yes") : "No"); + PrintAndLogEx(INFO, " Offset............ %d", b.offset); + PrintAndLogEx(INFO, " Seq. terminator... %s", (b.ST) ? _GREEN_("Yes") : "No"); + PrintAndLogEx(INFO, " Block0............ %08X %s", b.block0, GetConfigBlock0Source(b.block0Status)); + PrintAndLogEx(INFO, " Downlink mode..... %s", GetDownlinkModeStr(b.downlink_mode)); + PrintAndLogEx(INFO, " Password set...... %s", (b.usepwd) ? _RED_("Yes") : _GREEN_("No")); if (b.usepwd) { - PrintAndLogEx(INFO, " Password : %08X", b.pwd); + PrintAndLogEx(INFO, " Password.......... %08X", b.pwd); } PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; @@ -2714,17 +2736,17 @@ char *GetConfigBlock0Source(uint8_t id) { char *retStr = buf; switch (id) { - case autoDetect: - snprintf(retStr, sizeof(buf), _YELLOW_("(Auto detect)")); + case AUTODETECT: + snprintf(retStr, sizeof(buf), _YELLOW_("(auto detect)")); break; - case userSet: - snprintf(retStr, sizeof(buf), _YELLOW_("(User set)")); + case USERSET: + snprintf(retStr, sizeof(buf), _YELLOW_("(user set)")); break; - case tagRead: - snprintf(retStr, sizeof(buf), _GREEN_("(Tag read)")); + case TAGREAD: + snprintf(retStr, sizeof(buf), _GREEN_("(tag read)")); break; default: - snprintf(retStr, sizeof(buf), _RED_("(Unknown)")); + snprintf(retStr, sizeof(buf), _RED_("(n/a)")); break; } return buf; @@ -4249,7 +4271,7 @@ static command_t CommandTable[] = { {"info", CmdT55xxInfo, AlwaysAvailable, "Show T55x7 configuration data (page 0/ blk 0)"}, {"p1detect", CmdT55xxDetectPage1, IfPm3Lf, "Try detecting if this is a t55xx tag by reading page 1"}, {"read", CmdT55xxReadBlock, IfPm3Lf, "Read T55xx block data"}, - {"resetread", CmdResetRead, IfPm3Lf, "Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)"}, + {"resetread", CmdResetRead, IfPm3Lf, "Send Reset Cmd then lf read the stream to attempt to identify the start of it"}, {"restore", CmdT55xxRestore, IfPm3Lf, "Restore T55xx card Page 0 / Page 1 blocks"}, {"trace", CmdT55xxReadTrace, AlwaysAvailable, "Show T55x7 traceability data (page 1/ blk 0-1)"}, {"wakeup", CmdT55xxWakeUp, IfPm3Lf, "Send AOR wakeup command"}, diff --git a/client/src/cmdlft55xx.h b/client/src/cmdlft55xx.h index 1a31772eb..d9061d039 100644 --- a/client/src/cmdlft55xx.h +++ b/client/src/cmdlft55xx.h @@ -127,10 +127,10 @@ typedef struct { uint8_t offset; uint32_t block0; enum { - notSet = 0x00, - autoDetect = 0x01, - userSet = 0x02, - tagRead = 0x03, + NOTSET = 0x00, + AUTODETECT = 0x01, + USERSET = 0x02, + TAGREAD = 0x03, } block0Status; enum { RF_8 = 0x00, From e9b8ed71a70154803b4de009b23fce5c771fccd5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 18:58:55 +0100 Subject: [PATCH 15/67] text --- doc/cliparser_todo.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 44f0bac7d..a7e55eba5 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -32,7 +32,6 @@ data print data samples data setdebugmode data tune -hf 14b sriwrite hf 15 dump hf 15 info hf 15 raw @@ -94,12 +93,6 @@ lf hitag sim lf hitag writer lf hitag dump lf hitag cc -lf t55xx config -lf t55xx dump -lf t55xx info lf t55xx read -lf t55xx resetread -lf t55xx restore -lf t55xx trace lf t55xx write script run From d93bcd40744dc0f5df437c6d850f9de5f0502487 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 19:04:14 +0100 Subject: [PATCH 16/67] text --- client/src/cmdlft55xx.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 4f4e6ca27..eae67d01e 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -151,10 +151,10 @@ static int usage_t55xx_clonehelp(void) { PrintAndLogEx(NORMAL, "For cloning specific techs on T55xx tags, see commands available in corresponding LF sub-menus, e.g.:"); PrintAndLogEx(NORMAL, _GREEN_("lf awid clone")); PrintAndLogEx(NORMAL, _GREEN_("lf destron clone")); - PrintAndLogEx(NORMAL, _GREEN_("lf em 410x_clone")); + PrintAndLogEx(NORMAL, _GREEN_("lf em 410x clone")); // todo: implement restore -// PrintAndLogEx(NORMAL, _GREEN_("lf em 4x05_write")); -// PrintAndLogEx(NORMAL, _GREEN_("lf em 4x50_write")); +// PrintAndLogEx(NORMAL, _GREEN_("lf em 4x05 write")); +// PrintAndLogEx(NORMAL, _GREEN_("lf em 4x50 write")); PrintAndLogEx(NORMAL, _GREEN_("lf fdxb clone")); PrintAndLogEx(NORMAL, _GREEN_("lf gallagher clone")); PrintAndLogEx(NORMAL, _GREEN_("lf gproxii clone")); @@ -163,9 +163,10 @@ static int usage_t55xx_clonehelp(void) { PrintAndLogEx(NORMAL, _GREEN_("lf io clone")); PrintAndLogEx(NORMAL, _GREEN_("lf jablotron clone")); PrintAndLogEx(NORMAL, _GREEN_("lf keri clone")); - PrintAndLogEx(NORMAL, _GREEN_("lf nedap clone")); - PrintAndLogEx(NORMAL, _GREEN_("lf noralsy clone")); PrintAndLogEx(NORMAL, _GREEN_("lf motorola clone")); + PrintAndLogEx(NORMAL, _GREEN_("lf nedap clone")); + PrintAndLogEx(NORMAL, _GREEN_("lf nexwatch clone")); + PrintAndLogEx(NORMAL, _GREEN_("lf noralsy clone")); PrintAndLogEx(NORMAL, _GREEN_("lf pac clone")); PrintAndLogEx(NORMAL, _GREEN_("lf paradox clone")); PrintAndLogEx(NORMAL, _GREEN_("lf presco clone")); From a3b42e27cf6b7cbe39d5cc98509e1ded8d58c635 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 20:24:13 +0100 Subject: [PATCH 17/67] lf t55xx read - now uses cliparser --- client/src/cmdlft55xx.c | 150 +++++++++++++++++++--------------------- 1 file changed, 70 insertions(+), 80 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index eae67d01e..fd0b4f893 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -66,6 +66,8 @@ void Set_t55xx_Config(t55xx_conf_block_t conf) { config = conf; } +static int CmdHelp(const char *Cmd); + static void print_usage_t55xx_downloadlink(uint8_t ShowAll, uint8_t dl_mode_default) { if (ShowAll == T55XX_DLMODE_ALL) PrintAndLogEx(NORMAL, " r - downlink encoding 0|1|2|3|4"); @@ -106,28 +108,6 @@ static void arg_add_t55xx_downloadlink(void *at[], uint8_t *idx, uint8_t show, u *idx = n; } - -static int usage_t55xx_read(void) { - PrintAndLogEx(NORMAL, "Usage: lf t55xx read [r ] b [p ] [o] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " b - block number to read. Between 0-7"); - PrintAndLogEx(NORMAL, " p - OPTIONAL password (8 hex characters)"); - PrintAndLogEx(NORMAL, " o - OPTIONAL override safety check"); - PrintAndLogEx(NORMAL, " 1 - OPTIONAL 0|1 read Page 1 instead of Page 0"); - print_usage_t55xx_downloadlink(T55XX_DLMODE_SINGLE, config.downlink_mode); - PrintAndLogEx(NORMAL, " " _RED_("**** WARNING ****")); - PrintAndLogEx(NORMAL, " Use of read with password on a tag not configured"); - PrintAndLogEx(NORMAL, " for a password can damage the tag"); - PrintAndLogEx(NORMAL, " " _RED_("*****************")); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx read b 0") " - read data from block 0"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx read b 0 p feedbeef") " - read data from block 0 password feedbeef"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx read b 0 p feedbeef o") " - read data from block 0 password feedbeef safety check"); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} - static int usage_t55xx_write(void) { PrintAndLogEx(NORMAL, "Usage: lf t55xx write [r ] b d [p ] [1] [t] [v]"); PrintAndLogEx(NORMAL, "Options:"); @@ -147,7 +127,8 @@ static int usage_t55xx_write(void) { return PM3_SUCCESS; } -static int usage_t55xx_clonehelp(void) { +static int CmdT55xxCloneHelp(const char *Cmd) { + (void)Cmd; // Cmd is not used so far PrintAndLogEx(NORMAL, "For cloning specific techs on T55xx tags, see commands available in corresponding LF sub-menus, e.g.:"); PrintAndLogEx(NORMAL, _GREEN_("lf awid clone")); PrintAndLogEx(NORMAL, _GREEN_("lf destron clone")); @@ -177,13 +158,6 @@ static int usage_t55xx_clonehelp(void) { return PM3_SUCCESS; } -static int CmdHelp(const char *Cmd); - -static int CmdT55xxCloneHelp(const char *Cmd) { - (void)Cmd; // Cmd is not used so far - return usage_t55xx_clonehelp(); -} - static void T55x7_SaveBlockData(uint8_t idx, uint32_t data) { if (idx < T55x7_BLOCK_COUNT) { cardmem[idx].valid = true; @@ -665,6 +639,7 @@ int T55xxReadBlockEx(uint8_t block, bool page1, bool usepwd, uint8_t override, u if (t55xxTryDetectModulationEx(downlink_mode, false, 0, password) == false) { PrintAndLogEx(WARNING, "Safety check: Could not detect if PWD bit is set in config block. Exits."); + PrintAndLogEx(HINT, "Consider using the override parameter to force read."); return PM3_EWRONGANSWER; } else { PrintAndLogEx(WARNING, "Safety check: PWD bit is NOT set in config block. Reading without password..."); @@ -689,51 +664,67 @@ int T55xxReadBlockEx(uint8_t block, bool page1, bool usepwd, uint8_t override, u } static int CmdT55xxReadBlock(const char *Cmd) { - uint8_t block = REGULAR_READ_MODE_BLOCK; - uint8_t override = 0; - uint8_t cmdp = 0; - uint8_t downlink_mode = config.downlink_mode; - uint32_t password = 0; //default to blank Block 7 + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf t55xx read", + "Read T55xx block data. This commands defaults to page 0.\n\n" + _RED_(" * * * WARNING * * *") "\n" + _CYAN_("Use of read with password on a tag not configured") "\n" + _CYAN_("for a password can damage the tag") "\n" + _RED_(" * * * * * * * * * *"), + "lf t55xx read -b 0 --> read data from block 0\n" + "lf t55xx read -b 0 --pwd 01020304 --> read data from block 0, pwd 01020304\n" + "lf t55xx read -b 0 --pwd 01020304 -o --> read data from block 0, pwd 01020304, override\n" + ); + + // 1 (help) + 4(four user specified params) + (5 T55XX_DLMODE_SINGLE) + void *argtable[5 + 5] = { + arg_param_begin, + arg_int1("b", "blk", "<0-7>", "block number to read"), + arg_str0("p", "pwd", "", "password (4 hex bytes)"), + arg_lit0("o", "override", "override safety check"), + arg_lit0(NULL, "pg1", "read page 1"), + }; + uint8_t idx = 5; + arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_SINGLE, config.downlink_mode); + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int block = arg_get_int_def(ctx, 1, REGULAR_READ_MODE_BLOCK); + bool usepwd = false; - bool page1 = false; - bool errors = false; - - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_t55xx_read(); - case 'b': - errors |= param_getdec(Cmd, cmdp + 1, &block); - cmdp += 2; - break; - case 'o': - override = 1; - cmdp++; - break; - case 'p': - password = param_get32ex(Cmd, cmdp + 1, 0, 16); - usepwd = true; - cmdp += 2; - break; - case '1': - page1 = true; - cmdp++; - break; - case 'r': - downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10); - if (downlink_mode > 3) - downlink_mode = 0; - - cmdp += 2; - break; - - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } + uint32_t password = 0; + int res = arg_get_u32_hexstr_def_nlen(ctx, 2, 0, &password, 4, true); + if (res == 0 || res == 2) { + PrintAndLogEx(ERR, "Password should be 4 hex bytes"); + CLIParserFree(ctx); + return PM3_EINVARG; } - if (errors || cmdp == 0) return usage_t55xx_read(); + if (res == 1) { + usepwd = true; + } + + uint8_t override = arg_get_lit(ctx, 3); + bool page1 = arg_get_lit(ctx, 4); + + bool r0 = arg_get_lit(ctx, 5); + bool r1 = arg_get_lit(ctx, 6); + bool r2 = arg_get_lit(ctx, 7); + bool r3 = arg_get_lit(ctx, 8); + CLIParserFree(ctx); + + if ((r0 + r1 + r2 + r3) > 1) { + PrintAndLogEx(FAILED, "Error multiple downlink encoding"); + return PM3_EINVARG; + } + + uint8_t downlink_mode = config.downlink_mode; + if (r0) + downlink_mode = refFixedBit; + else if (r1) + downlink_mode = refLongLeading; + else if (r2) + downlink_mode = refLeading0; + else if (r3) + downlink_mode = ref1of4; if (block > 7 && block != REGULAR_READ_MODE_BLOCK) { PrintAndLogEx(NORMAL, "Block must be between 0 and 7"); @@ -1316,17 +1307,16 @@ bool GetT55xxBlockData(uint32_t *blockdata) { void printT55xxBlock(uint8_t blockNum, bool page1) { - uint32_t blockData = 0; - uint8_t bytes[4] = {0}; - - if (GetT55xxBlockData(&blockData) == false) + uint32_t val = 0; + if (GetT55xxBlockData(&val) == false) return; - num_to_bytes(blockData, 4, bytes); + uint8_t bytes[4] = {0}; + num_to_bytes(val, 4, bytes); - T55x7_SaveBlockData((page1) ? blockNum + 8 : blockNum, blockData); + T55x7_SaveBlockData((page1) ? blockNum + 8 : blockNum, val); - PrintAndLogEx(SUCCESS, " %02d | %08X | %s | %s", blockNum, blockData, sprint_bin(DemodBuffer + config.offset, 32), sprint_ascii(bytes, 4)); + PrintAndLogEx(SUCCESS, " %02d | %08X | %s | %s", blockNum, val, sprint_bin(DemodBuffer + config.offset, 32), sprint_ascii(bytes, 4)); } static bool testModulation(uint8_t mode, uint8_t modread) { From 214fe8ce7492a16756ab010cdf84c0b91cca1db9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 20:38:51 +0100 Subject: [PATCH 18/67] updated text --- doc/T5577_Guide.md | 234 +++++++++++++++++++++++---------------------- 1 file changed, 120 insertions(+), 114 deletions(-) diff --git a/doc/T5577_Guide.md b/doc/T5577_Guide.md index cdffadd20..8e22aab86 100644 --- a/doc/T5577_Guide.md +++ b/doc/T5577_Guide.md @@ -1,8 +1,9 @@ # T5577 Introduction Guide -### Based on RRG proxmark3 fork. +### Based on RRG/Iceman Proxmark3 repo ### Ver.1 8 Sep 2019 +### Ver.2 7 March 2021 | Contents | | ----------------------------------------------------------------------------------- | @@ -79,14 +80,16 @@ examples shown, it will be assumed you have run the detect command. ``` You should see a results simular to the following: ``` - Chip Type : T55x7 - Modulation : ASK - Bit Rate : 2 - RF/32 - Inverted : No - Offset : 32 - Seq. Term. : Yes - Block0 : 0x000880E0 - Downlink Mode : default/fixed bit length + [=] Chip type......... T55x7 + [=] Modulation........ ASK + [=] Bit rate.......... 2 - RF/32 + [=] Inverted.......... No + [=] Offset............ 33 + [=] Seq. terminator... Yes + [=] Block0............ 000880E0 (auto detect) + [=] Downlink mode..... default/fixed bit length + [=] Password set...... No + ``` Now that the proxmark3 has detected a T55x7 chip, and found some information about it, we should be able to see all the data on the chip. @@ -140,7 +143,7 @@ can see the card) as, run a low frequency (lf) command for the T55xx chip (t55xx) and read block (b) number 1. ``` - [usb] pm3 --> lf t55xx read b 1 + [usb] pm3 --> lf t55xx read -b 1 ``` result: ``` @@ -164,7 +167,7 @@ can see the card) ``` 3) Now, lets check if the data was written. ``` - [usb] pm3 --> lf t55xx read b 1 + [usb] pm3 --> lf t55xx read -b 1 ``` result: ``` @@ -210,7 +213,7 @@ can see the card) ``` and check ``` - [usb] pm3 --> lf t55xx read b 1 + [usb] pm3 --> lf t55xx read -b 1 ``` result: ``` @@ -272,9 +275,10 @@ required, please do not proceed. ``` Result: ``` - [=] Begin wiping T55x7 tag + [=] Target T55x7 tag + [=] Default configuration block 000880E0 - [=] Default configation block 000880E0 + [=] Begin wiping... [=] Writing page 0 block: 00 data: 0x000880E0 [=] Writing page 0 block: 01 data: 0x00000000 [=] Writing page 0 block: 02 data: 0x00000000 @@ -291,14 +295,15 @@ required, please do not proceed. ``` result: ``` - Chip Type : T55x7 - Modulation : ASK - Bit Rate : 2 - RF/32 - Inverted : No - Offset : 32 - Seq. Term. : Yes - Block0 : 0x000880E0 - Downlink Mode : default/fixed bit length + [=] Chip type......... T55x7 + [=] Modulation........ ASK + [=] Bit rate.......... 2 - RF/32 + [=] Inverted.......... No + [=] Offset............ 33 + [=] Seq. terminator... Yes + [=] Block0............ 000880E0 (auto detect) + [=] Downlink mode..... default/fixed bit length + [=] Password set...... No ``` If block 0 does not hold the hex data **0x00088040 resolve this @@ -412,18 +417,20 @@ required, please do not proceed. Lets try again, but this time supply the password. We use the option p followed by the password. ``` - [usb] pm3 --> lf t55 detect p 12345678 + [usb] pm3 --> lf t55 detect -p 12345678 ``` result: ``` - Chip Type : T55x7 - Modulation : ASK - Bit Rate : 2 - RF/32 - Inverted : No - Offset : 32 - Seq. Term. : Yes - Block0 : 0x00088050 - Downlink Mode : default/fixed bit length + [=] Chip type......... T55x7 + [=] Modulation........ ASK + [=] Bit rate.......... 2 - RF/32 + [=] Inverted.......... No + [=] Offset............ 33 + [=] Seq. terminator... Yes + [=] Block0............ 00088050 (auto detect) + [=] Downlink mode..... default/fixed bit length + [=] Password set...... Yes + [=] Password.......... 00000000 ``` 7) Write a block of data with a password @@ -445,7 +452,7 @@ required, please do not proceed. The proxmark3 has a safety check\! ``` - [usb] pm3 --> lf t55xx read b 1 p 12345678 + [usb] pm3 --> lf t55xx read -b 1 -p 12345678 ``` result: ``` @@ -453,6 +460,7 @@ required, please do not proceed. [+] blk | hex data | binary | ascii [+] ----+----------+----------------------------------+------- [!] Safety check: Could not detect if PWD bit is set in config block. Exits. + [?] Consider using the override parameter to force read. ``` Note that the proxmark3 did not read the block, the safty kicked in @@ -460,7 +468,7 @@ required, please do not proceed. Lets try again with the ‘o’ option as we know the password is set. ``` - [usb] pm3 --> lf t55xx read b 1 p 12345678 o + [usb] pm3 --> lf t55xx read -b 1 -p 12345678 -o ``` result: ``` @@ -498,14 +506,15 @@ required, please do not proceed. ``` result: ``` - Chip Type : T55x7 - Modulation : ASK - Bit Rate : 2 - RF/32 - Inverted : No - Offset : 32 - Seq. Term. : Yes - Block0 : 0x00088040 - Downlink Mode : default/fixed bit length + [=] Chip type......... T55x7 + [=] Modulation........ ASK + [=] Bit rate.......... 2 - RF/32 + [=] Inverted.......... No + [=] Offset............ 33 + [=] Seq. terminator... Yes + [=] Block0............ 00088040 (auto detect) + [=] Downlink mode..... default/fixed bit length + [=] Password set...... No ``` Yes we can and we can see Block 0 is the correct config 00088040 @@ -571,14 +580,16 @@ password set (if not, review and get you card back to this state). 1) Lets turn you T5577 into an EM4100 with ID 1122334455 ``` - [usb] pm3 --> lf em 410x_write 1122334455 1 + [usb] pm3 --> lf em 410x clone --id 1122334455 ``` result: ``` - [+] Writing T55x7 tag with UID 0x1122334455 (clock rate: 64) - #db# Started writing T55x7 tag ... - #db# Clock rate: 64 - #db# Tag T55x7 written with 0xff8c65298c94a940 + [+] Preparing to clone EM4102 to T55x7 tag with ID 0F0368568B (RF/64) + [#] Clock rate: 64 + [#] Tag T55x7 written with 0xff83c03322a646e4 + + [+] Done + [?] Hint: try `lf em 410x reader` to verify ``` 2) Check this has work. @@ -586,42 +597,38 @@ password set (if not, review and get you card back to this state). [usb] pm3 --> lf search ``` result: - ``` - [=] NOTE: some demods output possible binary - [=] if it finds something that looks like a tag - [=] False Positives ARE possible - [=] - [=] Checking for known tags... - - [+] EM410x pattern found - - EM TAG ID : 1122334455 - - Possible de-scramble patterns - - Unique TAG ID : 8844CC22AA - HoneyWell IdentKey { - DEZ 8 : 03359829 - DEZ 10 : 0573785173 - DEZ 5.5 : 08755.17493 - DEZ 3.5A : 017.17493 - DEZ 3.5B : 034.17493 - DEZ 3.5C : 051.17493 - DEZ 14/IK2 : 00073588229205 - DEZ 15/IK3 : 000585269781162 - DEZ 20/ZK : 08080404121202021010 - } - Other : 17493_051_03359829 - Pattern Paxton : 289899093 [0x11478255] - Pattern 1 : 5931804 [0x5A831C] - Pattern Sebury : 17493 51 3359829 [0x4455 0x33 0x334455] - - [+] Valid EM410x ID found! - - - [+] Chipset detection : T55xx found - - [+] Try `lf t55xx` commands + ``` + [=] NOTE: some demods output possible binary + [=] if it finds something that looks like a tag + [=] False Positives ARE possible + [=] + [=] Checking for known tags... + [=] + [+] EM 410x ID 0F0368568B + [+] EM410x ( RF/64 ) + [=] -------- Possible de-scramble patterns --------- + [+] Unique TAG ID : F0C0166AD1 + [=] HoneyWell IdentKey + [+] DEZ 8 : 06837899 + [+] DEZ 10 : 0057169547 + [+] DEZ 5.5 : 00872.22155 + [+] DEZ 3.5A : 015.22155 + [+] DEZ 3.5B : 003.22155 + [+] DEZ 3.5C : 104.22155 + [+] DEZ 14/IK2 : 00064481678987 + [+] DEZ 15/IK3 : 001034014845649 + [+] DEZ 20/ZK : 15001200010606101301 + [=] + [+] Other : 22155_104_06837899 + [+] Pattern Paxton : 259822731 [0xF7C948B] + [+] Pattern 1 : 9750181 [0x94C6A5] + [+] Pattern Sebury : 22155 104 6837899 [0x568B 0x68 0x68568B] + [=] ------------------------------------------------ + + [+] Valid EM410x ID found! + + [+] Chipset detection: T55xx + [?] Hint: try `lf t55xx` commands ``` Looks good. @@ -631,44 +638,43 @@ password set (if not, review and get you card back to this state). ``` result: ``` - [usb] pm3 --> lf t55 detect - Chip Type : T55x7 - Modulation : ASK - Bit Rate : 5 - RF/64 - Inverted : No - Offset : 32 - Seq. Term. : Yes - Block0 : 0x00148040 - Downlink Mode : default/fixed bit length + [=] Chip type......... T55x7 + [=] Modulation........ ASK + [=] Bit rate.......... 5 - RF/64 + [=] Inverted.......... No + [=] Offset............ 33 + [=] Seq. terminator... Yes + [=] Block0............ 00148040 (auto detect) + [=] Downlink mode..... default/fixed bit length + [=] Password set...... No ``` ``` [usb] pm3 --> lf t55xx info ``` result: ``` - - -- T55x7 Configuration & Tag Information -------------------- - ------------------------------------------------------------- - Safer key : 0 - reserved : 0 - Data bit rate : 5 - RF/64 - eXtended mode : No - Modulation : 8 - Manchester - PSK clock frequency : 0 - RF/2 - AOR - Answer on Request : No - OTP - One Time Pad : No - Max block : 2 - Password mode : No - Sequence Terminator : No - Fast Write : No - Inverse data : No - POR-Delay : No - ------------------------------------------------------------- - Raw Data - Page 0 - Block 0 : 0x00148040 00000000000101001000000001000000 - - Config block match : EM unique, Paxton - ------------------------------------------------------------- + + [=] --- T55x7 Configuration & Information --------- + [=] Safer key : 0 + [=] reserved : 0 + [=] Data bit rate : 5 - RF/64 + [=] eXtended mode : No + [=] Modulation : 8 - Manchester + [=] PSK clock frequency : 0 - RF/2 + [=] AOR - Answer on Request : No + [=] OTP - One Time Pad : No + [=] Max block : 2 + [=] Password mode : No + [=] Sequence Terminator : No + [=] Fast Write : No + [=] Inverse data : No + [=] POR-Delay : No + [=] ------------------------------------------------------------- + [=] Raw Data - Page 0, block 0 + [=] 00148040 - 00000000000101001000000001000000 + [=] --- Fingerprint ------------ + [+] Config block match : EM unique, Paxton + ``` We can see that the info gave us more information and confirmed what we decoded by hand. But remember, the detect is still needed so the From 7377a45bd0667332620547aa821152a09c4e7328 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 22:00:33 +0100 Subject: [PATCH 19/67] lf t55xx write - now uses cliparser --- .../luascripts/tests/lf_t55xx_defaultask.lua | 4 +- .../luascripts/tests/lf_t55xx_defaultbi.lua | 4 +- .../luascripts/tests/lf_t55xx_defaultfsk.lua | 4 +- .../luascripts/tests/lf_t55xx_defaultpsk.lua | 4 +- .../luascripts/tests/lf_t55xx_writetest.lua | 12 +- client/src/cmdlft55xx.c | 182 ++++++++---------- doc/T5577_Guide.md | 12 +- doc/cloner_notes.md | 4 +- 8 files changed, 103 insertions(+), 123 deletions(-) diff --git a/client/luascripts/tests/lf_t55xx_defaultask.lua b/client/luascripts/tests/lf_t55xx_defaultask.lua index efb6ce8fe..9e81110b3 100644 --- a/client/luascripts/tests/lf_t55xx_defaultask.lua +++ b/client/luascripts/tests/lf_t55xx_defaultask.lua @@ -20,7 +20,7 @@ The outlined procedure is as following: -- manchester -- bit rate -"lf t55xx write b 0 d 00008040" +"lf t55xx write -b 0 -d 00008040" "lf t55xx detect" "lf t55xx info" @@ -118,7 +118,7 @@ local function test() elseif _ == 1 then local config = pcmd:format(config1, y, config2) - dbg(('lf t55xx write b 0 d %s'):format(config)) + dbg(('lf t55xx write -b 0 -d %s'):format(config)) local data = ('%s%s%s%s'):format(utils.SwapEndiannessStr(config, 32), password, block, flags) local wc = Command:newNG{cmd = cmds.CMD_LF_T55XX_WRITEBL, data = data} diff --git a/client/luascripts/tests/lf_t55xx_defaultbi.lua b/client/luascripts/tests/lf_t55xx_defaultbi.lua index 495faef02..2590dc38b 100644 --- a/client/luascripts/tests/lf_t55xx_defaultbi.lua +++ b/client/luascripts/tests/lf_t55xx_defaultbi.lua @@ -14,7 +14,7 @@ The outlined procedure is as following: --BIPHASE 00010040 -- -"lf t55xx write b 0 d 00010040" +"lf t55xx write -b 0 -d 00010040" "lf t55xx detect" "lf t55xx info" @@ -112,7 +112,7 @@ local function test() elseif _ == 1 then local config = pcmd:format(config1, y, config2) - dbg(('lf t55xx write b 0 d %s'):format(config)) + dbg(('lf t55xx write -b 0 -d %s'):format(config)) local data = ('%s%s%s%s'):format(utils.SwapEndiannessStr(config, 32), password, block, flags) diff --git a/client/luascripts/tests/lf_t55xx_defaultfsk.lua b/client/luascripts/tests/lf_t55xx_defaultfsk.lua index 2a5c272c4..9aa50f641 100644 --- a/client/luascripts/tests/lf_t55xx_defaultfsk.lua +++ b/client/luascripts/tests/lf_t55xx_defaultfsk.lua @@ -17,7 +17,7 @@ The outlined procedure is as following: -- FSK1 -- bit rate -"lf t55xx write b 0 d 00007040" +"lf t55xx write -b 0 -d 00007040" "lf t55xx detect" "lf t55xx info" @@ -114,7 +114,7 @@ local function test(modulation) elseif _ == 1 then local config = pcmd:format(config1, y, modulation, config2) - dbg(('lf t55xx write b 0 d %s'):format(config)) + dbg(('lf t55xx write -b 0 -d %s'):format(config)) local data = ('%s%s%s%s'):format(utils.SwapEndiannessStr(config, 32), password, block, flags) local wc = Command:newNG{cmd = cmds.CMD_LF_T55XX_WRITEBL, data = data} diff --git a/client/luascripts/tests/lf_t55xx_defaultpsk.lua b/client/luascripts/tests/lf_t55xx_defaultpsk.lua index 8b4f0447a..09a4063e8 100644 --- a/client/luascripts/tests/lf_t55xx_defaultpsk.lua +++ b/client/luascripts/tests/lf_t55xx_defaultpsk.lua @@ -11,7 +11,7 @@ desc = [[ This script will program a T55x7 TAG with the configuration: block 0x00 data 0x00088040 The outlined procedure is as following: -"lf t55xx write b 0 d 00088040" +"lf t55xx write -b 0 -d 00088040" "lf t55xx detect" "lf t55xx info" @@ -118,7 +118,7 @@ local function test(modulation) dbg('Writing to T55x7 TAG') local config = cmd:format(bitrate, modulation, clockrate) - dbg(('lf t55xx write b 0 d %s'):format(config)) + dbg(('lf t55xx write -b 0 -d %s'):format(config)) local data = ('%s%s%s%s'):format(utils.SwapEndiannessStr(config, 32), password, block, flags) diff --git a/client/luascripts/tests/lf_t55xx_writetest.lua b/client/luascripts/tests/lf_t55xx_writetest.lua index cfe46d565..48053db5d 100644 --- a/client/luascripts/tests/lf_t55xx_writetest.lua +++ b/client/luascripts/tests/lf_t55xx_writetest.lua @@ -17,10 +17,10 @@ It will then try to detect and read back those block data and compare if read da lf t55xx wipe lf t55xx detect -lf t55xx write b 1 d 00000000 -lf t55xx write b 2 d ffffffff -lf t55xx write b 3 d 80000000 -lf t55xx write b 4 d 00000001 +lf t55xx write -b 1 -d 00000000 +lf t55xx write -b 2 -d ffffffff +lf t55xx write -b 3 -d 80000000 +lf t55xx write -b 4 -d 00000001 Loop: @@ -278,7 +278,7 @@ local function WipeCard() core.console('rem [ERR:DETECT:WIPED] Failed to detect after wipe') return false else - local wipe_data_cmd = 'lf t55xx write b %s d %s' + local wipe_data_cmd = 'lf t55xx write -b %s -d %s' for _ = 1, #data_blocks_cmds do local val = data_blocks_cmds[_] local c = string.format(wipe_data_cmd, _, val) @@ -321,7 +321,7 @@ local function test(modulation) core.clearCommandBuffer() -- Write Config block - dbg(('lf t55xx write b 0 d %s'):format(p_config_cmd)) + dbg(('lf t55xx write -b 0 -d %s'):format(p_config_cmd)) local data = ('%s%s%s%s'):format(utils.SwapEndiannessStr(p_config_cmd, 32), password, block, flags) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index fd0b4f893..f3993adcc 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -68,19 +68,6 @@ void Set_t55xx_Config(t55xx_conf_block_t conf) { static int CmdHelp(const char *Cmd); -static void print_usage_t55xx_downloadlink(uint8_t ShowAll, uint8_t dl_mode_default) { - if (ShowAll == T55XX_DLMODE_ALL) - PrintAndLogEx(NORMAL, " r - downlink encoding 0|1|2|3|4"); - else - PrintAndLogEx(NORMAL, " r - downlink encoding 0|1|2|3"); - PrintAndLogEx(NORMAL, " 0 - fixed bit length%s", (dl_mode_default == 0) ? " (detected default)" : ""); // default will be whats in config struct - PrintAndLogEx(NORMAL, " 1 - long leading reference%s", (dl_mode_default == 1) ? " (detected default)" : ""); - PrintAndLogEx(NORMAL, " 2 - leading zero%s", (dl_mode_default == 2) ? " (detected default)" : ""); - PrintAndLogEx(NORMAL, " 3 - 1 of 4 coding reference%s", (dl_mode_default == 3) ? " (detected default)" : ""); - if (ShowAll == T55XX_DLMODE_ALL) - PrintAndLogEx(NORMAL, " 4 - Try all downlink modes%s", (dl_mode_default == 4) ? " (default)" : ""); -} - static void arg_add_t55xx_downloadlink(void *at[], uint8_t *idx, uint8_t show, uint8_t dl_mode_def) { char *r0 = (char *)calloc(56, sizeof(uint8_t)); @@ -108,25 +95,6 @@ static void arg_add_t55xx_downloadlink(void *at[], uint8_t *idx, uint8_t show, u *idx = n; } -static int usage_t55xx_write(void) { - PrintAndLogEx(NORMAL, "Usage: lf t55xx write [r ] b d [p ] [1] [t] [v]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " b - block number to write. Between 0-7"); - PrintAndLogEx(NORMAL, " d - 4 bytes of data to write (8 hex characters)"); - PrintAndLogEx(NORMAL, " p - OPTIONAL password 4bytes (8 hex characters)"); - PrintAndLogEx(NORMAL, " 1 - OPTIONAL write Page 1 instead of Page 0"); - PrintAndLogEx(NORMAL, " t - OPTIONAL test mode write - ****DANGER****"); - PrintAndLogEx(NORMAL, " v - OPTIONAL validate data afterwards"); - print_usage_t55xx_downloadlink(T55XX_DLMODE_SINGLE, config.downlink_mode); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx write b 3 d 11223344") " - write 11223344 to block 3"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx write b 3 d 11223344 p feedbeef") " - write 11223344 to block 3 password feedbeef"); - PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx write b 3 d 11223344 v") " - write 11223344 to block 3 and try to validate data"); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} - static int CmdT55xxCloneHelp(const char *Cmd) { (void)Cmd; // Cmd is not used so far PrintAndLogEx(NORMAL, "For cloning specific techs on T55xx tags, see commands available in corresponding LF sub-menus, e.g.:"); @@ -1544,74 +1512,86 @@ int printConfiguration(t55xx_conf_block_t b) { } static int CmdT55xxWriteBlock(const char *Cmd) { - uint8_t block = 0xFF; // default to invalid block - uint32_t data = 0; // default to blank Block - uint32_t password = 0; // default to blank Block 7 - bool usepwd = false; - bool page1 = false; - bool gotdata = false; - bool testMode = false; - bool errors = false; - bool validate = false; - uint8_t cmdp = 0; - uint32_t downlink_mode = config.downlink_mode; + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf t55xx write", + "Write T55xx block data", + "lf t55xx write -b 3 -d 11223344 --> write 11223344 to block 3\n" + "lf t55xx write -b 3 -d 11223344 --pwd 01020304 --> write 11223344 to block 3, pwd 01020304\n" + "lf t55xx write -b 3 -d 11223344 --pwd 01020304 --verify --> write 11223344 to block 3 and try validating write" + ); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_t55xx_write(); - case 'b': - errors |= param_getdec(Cmd, cmdp + 1, &block); - cmdp += 2; + // 1 (help) + 6 (six user specified params) + (5 T55XX_DLMODE_SINGLE) + void *argtable[7 + 5] = { + arg_param_begin, + arg_int1("b", "blk", "<0-7>", "block number to write"), + arg_str0("d", "data", "", "data to write (4 hex bytes)"), + arg_str0("p", "pwd", "", "password (4 hex bytes)"), + arg_lit0("t", "tm", "test mode write ( " _RED_("danger") " )"), + arg_lit0(NULL, "pg1", "write page 1"), + arg_lit0(NULL, "verify", "try validate data afterward"), + }; + uint8_t idx = 7; + arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_SINGLE, config.downlink_mode); + CLIExecWithReturn(ctx, Cmd, argtable, true); - if (block > 7) { - PrintAndLogEx(WARNING, "Block number must be between 0 and 7"); - errors = true; - } - break; - case 'd': - data = param_get32ex(Cmd, cmdp + 1, 0, 16); - gotdata = true; - cmdp += 2; - break; - case 'p': - password = param_get32ex(Cmd, cmdp + 1, 0, 16); - usepwd = true; - cmdp += 2; - break; - case 't': - testMode = true; - cmdp++; - break; - case '1': - page1 = true; - cmdp++; - break; - case 'r': - downlink_mode = param_get8ex(Cmd, cmdp + 1, 0, 10); - if (downlink_mode > 3) - downlink_mode = 0; + int block = arg_get_int_def(ctx, 1, REGULAR_READ_MODE_BLOCK); - cmdp += 2; - break; - case 'v': - validate = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } + uint32_t data = 0; // default to blank Block + int res = arg_get_u32_hexstr_def_nlen(ctx, 2, 0, &data, 4, true); + if (res == 0 || res == 2) { + PrintAndLogEx(ERR, "data must be 4 hex bytes"); + CLIParserFree(ctx); + return PM3_EINVARG; } - if (errors || !gotdata) return usage_t55xx_write(); - char pwdStr[16] = {0}; - snprintf(pwdStr, sizeof(pwdStr), "pwd: 0x%08X", password); + bool usepwd = false; + uint32_t password = 0; // default to blank Block 7 + res = arg_get_u32_hexstr_def_nlen(ctx, 3, 0, &password, 4, true); + if (res == 0 || res == 2) { + PrintAndLogEx(ERR, "Password should be 4 hex bytes"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + if (res == 1) { + usepwd = true; + } - PrintAndLogEx(INFO, "Writing page %d block: %02d data: 0x%08X %s", page1, block, data, (usepwd) ? pwdStr : ""); + bool testmode = arg_get_lit(ctx, 4); + bool page1 = arg_get_lit(ctx, 5); + bool validate = arg_get_lit(ctx, 6); - if (t55xxWrite(block, page1, usepwd, testMode, password, downlink_mode, data) != PM3_SUCCESS) { + bool r0 = arg_get_lit(ctx, 7); + bool r1 = arg_get_lit(ctx, 8); + bool r2 = arg_get_lit(ctx, 9); + bool r3 = arg_get_lit(ctx, 10); + CLIParserFree(ctx); + + if ((r0 + r1 + r2 + r3) > 1) { + PrintAndLogEx(FAILED, "Error multiple downlink encoding"); + return PM3_EINVARG; + } + + uint8_t downlink_mode = config.downlink_mode; + if (r0) + downlink_mode = refFixedBit; + else if (r1) + downlink_mode = refLongLeading; + else if (r2) + downlink_mode = refLeading0; + else if (r3) + downlink_mode = ref1of4; + + if (block > 7 && block != REGULAR_READ_MODE_BLOCK) { + PrintAndLogEx(NORMAL, "Block must be between 0 and 7"); + return PM3_ESOFT; + } + + char pwdstr[16] = {0}; + snprintf(pwdstr, sizeof(pwdstr), "pwd: 0x%08X", password); + + PrintAndLogEx(INFO, "Writing page %d block: %02d data: 0x%08X %s", page1, block, data, (usepwd) ? pwdstr : ""); + + if (t55xxWrite(block, page1, usepwd, testmode, password, downlink_mode, data) != PM3_SUCCESS) { PrintAndLogEx(ERR, "Write failed"); return PM3_ESOFT; } @@ -2387,7 +2367,7 @@ static int CmdT55xxRestore(const char *Cmd) { char pwdOpt [11] = {0}; // p XXXXXXXX if (usepwd) - snprintf(pwdOpt, sizeof(pwdOpt), "p %08X", password); + snprintf(pwdOpt, sizeof(pwdOpt), "-p %08X", password); uint8_t idx; // Restore endien for writing to card @@ -2406,7 +2386,7 @@ static int CmdT55xxRestore(const char *Cmd) { // write out blocks 1-7 page 0 for (idx = 1; idx <= 7; idx++) { - snprintf(writeCmdOpt, sizeof(writeCmdOpt), "b %d d %08X %s", idx, data[idx], pwdOpt); + snprintf(writeCmdOpt, sizeof(writeCmdOpt), "-b %d -d %08X %s", idx, data[idx], pwdOpt); if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Warning: error writing blk %d", idx); @@ -2415,12 +2395,12 @@ static int CmdT55xxRestore(const char *Cmd) { // if password was set on the "blank" update as we may have just changed it if (usepwd) { - snprintf(pwdOpt, sizeof(pwdOpt), "p %08X", data[7]); + snprintf(pwdOpt, sizeof(pwdOpt), "-p %08X", data[7]); } // write out blocks 1-3 page 1 for (idx = 9; idx <= 11; idx++) { - snprintf(writeCmdOpt, sizeof(writeCmdOpt), "b %d 1 d %08X %s", idx - 8, data[idx], pwdOpt); + snprintf(writeCmdOpt, sizeof(writeCmdOpt), "-b %d --pg1 -d %08X %s", idx - 8, data[idx], pwdOpt); if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Warning: error writing blk %d", idx); @@ -2431,7 +2411,7 @@ static int CmdT55xxRestore(const char *Cmd) { config.downlink_mode = downlink_mode; // Write the page 0 config - snprintf(writeCmdOpt, sizeof(writeCmdOpt), "b 0 d %08X %s", data[0], pwdOpt); + snprintf(writeCmdOpt, sizeof(writeCmdOpt), "-b 0 -d %08X %s", data[0], pwdOpt); if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Warning: error writing blk 0"); } @@ -2961,7 +2941,7 @@ static int CmdT55xxWipe(const char *Cmd) { // Creating cmd string for write block :) char writeData[36] = {0}; char *ptrData = writeData; - snprintf(ptrData, sizeof(writeData), "b 0 "); + snprintf(ptrData, sizeof(writeData), "-b 0 "); if (usepwd) { snprintf(ptrData + strlen(writeData), sizeof(writeData) - strlen(writeData), "p %08x ", password); @@ -2973,7 +2953,7 @@ static int CmdT55xxWipe(const char *Cmd) { for (uint8_t blk = 1; blk < 8; blk++) { - snprintf(ptrData, sizeof(writeData), "b %d d 0", blk); + snprintf(ptrData, sizeof(writeData), "-b %d -d 0", blk); if (CmdT55xxWriteBlock(ptrData) != PM3_SUCCESS) PrintAndLogEx(WARNING, "Warning: error writing blk %d", blk); @@ -2983,7 +2963,7 @@ static int CmdT55xxWipe(const char *Cmd) { // Check and rest t55xx downlink mode. if (config.downlink_mode != T55XX_DLMODE_FIXED) { // Detect found a different mode so card must support - snprintf(ptrData, sizeof(writeData), "b 3 1 d 00000000"); + snprintf(ptrData, sizeof(writeData), "-b 3 --pg1 -d 00000000"); if (CmdT55xxWriteBlock(ptrData) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Warning: failed writing block 3 page 1 (config)"); } diff --git a/doc/T5577_Guide.md b/doc/T5577_Guide.md index 8e22aab86..4bd8f30c6 100644 --- a/doc/T5577_Guide.md +++ b/doc/T5577_Guide.md @@ -159,7 +159,7 @@ can see the card) We use the d option to supply the data ‘12345678’ ``` - [usb] pm3 --> lf t55xx write b 1 d 12345678 + [usb] pm3 --> lf t55xx write -b 1 -d 12345678 ``` result: ``` @@ -205,7 +205,7 @@ can see the card) Lets try and write 89ABCDEF ``` - [usb] pm3 --> lf t55xx write b 1 d 89abcdef + [usb] pm3 --> lf t55xx write -b 1 -d 89abcdef ``` result: ``` @@ -314,7 +314,7 @@ required, please do not proceed. The password is saved in block 7 of page 0. ``` - [usb] pm3 --> lf t55xx write b 7 d 12345678 + [usb] pm3 --> lf t55xx write -b 7 -d 12345678 ``` result: ``` @@ -394,7 +394,7 @@ required, please do not proceed. If you have completed all steps and have the exact same results, we are ready to apply the new configuration. ``` - [usb] pm3 --> lf t55xx write b 0 d 00088050 + [usb] pm3 --> lf t55xx write -b 0 -d 00088050 ``` result: ``` @@ -435,7 +435,7 @@ required, please do not proceed. 7) Write a block of data with a password ``` - [usb] pm3 --> lf t55xx write b 1 d 1234abcd p 12345678 + [usb] pm3 --> lf t55xx write -b 1 -d 1234abcd -p 12345678 ``` result: ``` @@ -494,7 +494,7 @@ required, please do not proceed. In our examples we know what it should be : 00088040 ``` - [usb] pm3 --> lf t55xx write b 0 d 00088040 p 12345678 + [usb] pm3 --> lf t55xx write -b 0 -d 00088040 -p 12345678 ``` result: ``` diff --git a/doc/cloner_notes.md b/doc/cloner_notes.md index 71cada411..92de920ad 100644 --- a/doc/cloner_notes.md +++ b/doc/cloner_notes.md @@ -60,8 +60,8 @@ Standard password is normally (for T55xx): AA55BBBB # Restore page1 data ``` -lf t55xx write b 1 d E0150A48 1 -If t55xx write b 2 d 2D782308 1 +lf t55xx write -b 1 -d E0150A48 --pg1 +If t55xx write -b 2 -d 2D782308 --pg1 ``` # Sniffing the comms From e0b69871ac701eb987d4284eba811003e978c24f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 22:01:06 +0100 Subject: [PATCH 20/67] text --- doc/cliparser_todo.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index a7e55eba5..f3cc3500c 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -93,6 +93,4 @@ lf hitag sim lf hitag writer lf hitag dump lf hitag cc -lf t55xx read -lf t55xx write script run From fe25e70e6fbb6ba9c7eeb27b0882ee7853b15cd2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 22:24:37 +0100 Subject: [PATCH 21/67] string too small fix --- client/src/cmdlft55xx.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index f3993adcc..7e86e1c78 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -2363,11 +2363,11 @@ static int CmdT55xxRestore(const char *Cmd) { // // uint8_t downlink_mode; - char writeCmdOpt[100]; - char pwdOpt [11] = {0}; // p XXXXXXXX + char wcmd[100]; + char pwdopt [14] = {0}; // p XXXXXXXX if (usepwd) - snprintf(pwdOpt, sizeof(pwdOpt), "-p %08X", password); + snprintf(pwdopt, sizeof(pwdopt), "-p %08X", password); uint8_t idx; // Restore endien for writing to card @@ -2386,23 +2386,23 @@ static int CmdT55xxRestore(const char *Cmd) { // write out blocks 1-7 page 0 for (idx = 1; idx <= 7; idx++) { - snprintf(writeCmdOpt, sizeof(writeCmdOpt), "-b %d -d %08X %s", idx, data[idx], pwdOpt); + snprintf(wcmd, sizeof(wcmd), "-b %d -d %08X %s", idx, data[idx], pwdopt); - if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS) { + if (CmdT55xxWriteBlock(wcmd) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Warning: error writing blk %d", idx); } } // if password was set on the "blank" update as we may have just changed it if (usepwd) { - snprintf(pwdOpt, sizeof(pwdOpt), "-p %08X", data[7]); + snprintf(pwdopt, sizeof(pwdopt), "-p %08X", data[7]); } // write out blocks 1-3 page 1 for (idx = 9; idx <= 11; idx++) { - snprintf(writeCmdOpt, sizeof(writeCmdOpt), "-b %d --pg1 -d %08X %s", idx - 8, data[idx], pwdOpt); + snprintf(wcmd, sizeof(wcmd), "-b %d --pg1 -d %08X %s", idx - 8, data[idx], pwdopt); - if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS) { + if (CmdT55xxWriteBlock(wcmd) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Warning: error writing blk %d", idx); } } @@ -2411,8 +2411,8 @@ static int CmdT55xxRestore(const char *Cmd) { config.downlink_mode = downlink_mode; // Write the page 0 config - snprintf(writeCmdOpt, sizeof(writeCmdOpt), "-b 0 -d %08X %s", data[0], pwdOpt); - if (CmdT55xxWriteBlock(writeCmdOpt) != PM3_SUCCESS) { + snprintf(wcmd, sizeof(wcmd), "-b 0 -d %08X %s", data[0], pwdopt); + if (CmdT55xxWriteBlock(wcmd) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Warning: error writing blk 0"); } } From 55ccd18afd5437bf5a9affe1ca3dc661f55d62f9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Mar 2021 22:27:37 +0100 Subject: [PATCH 22/67] lf hitag cc - now uses cliparser --- client/src/cmdlfhitag.c | 87 +++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 52 deletions(-) diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index b98d83705..cb711a65c 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -113,19 +113,6 @@ static int usage_hitag_writer(void) { PrintAndLogEx(NORMAL, " 27 Write page, password mode. Default: 4D494B52 (\"MIKR\")"); return PM3_SUCCESS; } -static int usage_hitag_checkchallenges(void) { - PrintAndLogEx(NORMAL, "Check challenges, load a file with save hitag crypto challenges and test them all."); - PrintAndLogEx(NORMAL, "The file should be 8 * 60 bytes long, the file extension defaults to " _YELLOW_("`.cc`")); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf hitag cc [h] f "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " f Load data from BIN file"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf hitag cc f lf-hitag-challenges"); - return PM3_SUCCESS; -} static int CmdLFHitagList(const char *Cmd) { char args[128] = {0}; @@ -614,50 +601,46 @@ static int CmdLFHitagReader(const char *Cmd) { static int CmdLFHitagCheckChallenges(const char *Cmd) { - char filename[FILE_PATH_SIZE] = { 0x00 }; - size_t datalen = 0; - int res = 0; - bool file_given = false; - bool errors = false; - uint8_t cmdp = 0; - uint8_t *data = calloc(8 * 60, sizeof(uint8_t)); + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf hitag cc", + "Check challenges, load a file with saved hitag crypto challenges and test them all.\n" + "The file should be 8 * 60 bytes long, the file extension defaults to " _YELLOW_("`.cc`") " ", + "lf hitag cc -f my_hitag_challenges" + ); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - free(data); - return usage_hitag_checkchallenges(); - case 'f': - //file with all the challenges to try - param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); - res = loadFile(filename, ".cc", data, 8 * 60, &datalen); - if (res > 0) { - errors = true; - break; - } - file_given = true; - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + void *argtable[] = { + arg_param_begin, + arg_str0("f", "filename", "", "filename to load from"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); - //Validations - if (errors || strlen(Cmd) == 0) { - free(data); - return usage_hitag_checkchallenges(); - } + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + + CLIParserFree(ctx); clearCommandBuffer(); - if (file_given) - SendCommandOLD(CMD_LF_HITAGS_TEST_TRACES, 1, 0, 0, data, datalen); - else - SendCommandMIX(CMD_LF_HITAGS_TEST_TRACES, 0, 0, 0, NULL, 0); - free(data); + 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 %d", 8*60, datalen); + } + } + if (data) { + free(data); + } + } else { + SendCommandMIX(CMD_LF_HITAGS_TEST_TRACES, 0, 0, 0, NULL, 0); + } + return PM3_SUCCESS; } From e5c5629cf2761f1a582a84d66d4a0b59129b824e Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 7 Mar 2021 23:43:53 +0100 Subject: [PATCH 23/67] Some tunings of otptear: - make tearoff_delay_us and tearoff_enabled globals - use tearoff_hook and remove Dbprintf in critical tearoff timing - move initial write from MifareU_Otp_Tearoff to CmdHF14AMfuOtpTearoff and make it optional (old behavior was writing initial 00000000 when -d was not provided) - tearoff: compare with initial write, not with previous tearoff outcome - rephrase some messages - track all begin and end of erase and write phases, with quite complex logic to cover multiple cases (starting in middle of erased phase, starting with write 0, ...) and report them - check against initial write error - repeat same timing (up to 10x) in case of write/read errors then quit - typos --- armsrc/appmain.c | 4 +- armsrc/iclass.c | 2 +- armsrc/iso14443a.c | 2 +- armsrc/iso14443b.c | 2 +- armsrc/iso15693.c | 6 +- armsrc/lfops.c | 4 +- armsrc/mifarecmd.c | 21 ++---- client/src/cmdhfmfu.c | 169 +++++++++++++++++++++++++----------------- include/common.h | 4 + 9 files changed, 121 insertions(+), 93 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index d9162dda8..e9c34e2cc 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -73,8 +73,8 @@ extern uint32_t _stack_start, _stack_end; struct common_area common_area __attribute__((section(".commonarea"))); static int button_status = BUTTON_NO_CLICK; static bool allow_send_wtx = false; -static uint16_t tearoff_delay_us = 0; -static bool tearoff_enabled = false; +uint16_t tearoff_delay_us = 0; +bool tearoff_enabled = false; int tearoff_hook(void) { if (tearoff_enabled) { diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 4d5975324..e149254f7 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -1881,7 +1881,7 @@ void iClass_WriteBlock(uint8_t *msg) { iclass_send_as_reader(write, write_len, &start_time, &eof_time); - if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured + if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred res = false; switch_off(); if (payload->req.send_reply) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index cd07a4007..1509cc80c 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2972,7 +2972,7 @@ void ReaderIso14443a(PacketCommandNG *c) { } } - if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured + if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred FpgaDisableTracing(); reply_mix(CMD_ACK, 0, 0, 0, NULL, 0); } else { diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 09c5e775e..c747a0e27 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -2092,7 +2092,7 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) { uint32_t eof_time = 0; CodeAndTransmit14443bAsReader(cmd, len, &start_time, &eof_time); - if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured + if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred FpgaDisableTracing(); reply_mix(CMD_HF_ISO14443B_COMMAND, -2, 0, 0, NULL, 0); } else { diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index de7a409bd..66539c807 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -1477,7 +1477,7 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, bool speed_fast, uint8_t tosend_t *ts = get_tosend(); TransmitTo15693Tag(ts->buf, ts->max, &start_time); - if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured + if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred res = PM3_ETEAROFF; @@ -1598,7 +1598,7 @@ void ReaderIso15693(uint32_t parameter) { uint32_t eof_time; int recvlen = SendDataTag(cmd, sizeof(cmd), true, true, answer, ISO15693_MAX_RESPONSE_LENGTH, start_time, ISO15693_READER_TIMEOUT, &eof_time); - if (recvlen == PM3_ETEAROFF) { // tearoff occured + if (recvlen == PM3_ETEAROFF) { // tearoff occurred reply_mix(CMD_ACK, recvlen, 0, 0, NULL, 0); } else { @@ -1928,7 +1928,7 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint uint32_t start_time = 0; int recvlen = SendDataTag(data, datalen, true, speed, (recv ? recvbuf : NULL), sizeof(recvbuf), start_time, timeout, &eof_time); - if (recvlen == PM3_ETEAROFF) { // tearoff occured + if (recvlen == PM3_ETEAROFF) { // tearoff occurred reply_mix(CMD_ACK, recvlen, 0, 0, NULL, 0); } else { diff --git a/armsrc/lfops.c b/armsrc/lfops.c index b4daed774..9555e59c1 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -2639,7 +2639,7 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) { SendForward(len, false); - if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured + if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred StopTicks(); reply_ng(CMD_LF_EM4X_WRITEWORD, PM3_ETEAROFF, NULL, 0); } else { @@ -2681,7 +2681,7 @@ void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd) { SendForward(len, false); - if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured + if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred StopTicks(); reply_ng(CMD_LF_EM4X_PROTECTWORD, PM3_ETEAROFF, NULL, 0); } else { diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 2ea7aa1b8..bcb47aa24 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -2713,20 +2713,15 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain) { // // Tear-off attack against MFU. // - Moebius et al -void MifareU_Otp_Tearoff(uint8_t blno, uint32_t tearoff_time, uint8_t *datain) { +void MifareU_Otp_Tearoff(uint8_t blno, uint32_t tearoff_time, uint8_t *data_testwrite) { uint8_t blockNo = blno; - uint8_t data_fullwrite[4] = {0x00}; - uint8_t data_testwrite[4] = {0x00}; - memcpy(data_fullwrite, datain, 4); - memcpy(data_testwrite, datain + 4, 4); if (DBGLEVEL >= DBG_DEBUG) DbpString("Preparing OTP tear-off"); if (tearoff_time > 43000) tearoff_time = 43000; - - MifareUWriteBlockEx(blockNo, 0, data_fullwrite, false); - + tearoff_delay_us = tearoff_time; + tearoff_enabled = true; LEDsoff(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); @@ -2750,15 +2745,9 @@ void MifareU_Otp_Tearoff(uint8_t blno, uint32_t tearoff_time, uint8_t *datain) { return; }; // send - ReaderTransmit(cmd, sizeof(cmd), NULL); - - // Wait before cutting power. aka tear-off LED_D_ON(); - - SpinDelayUsPrecision(tearoff_time); - if (DBGLEVEL >= DBG_DEBUG) Dbprintf(_YELLOW_("OTP tear-off triggered!")); - switch_off(); - + ReaderTransmit(cmd, sizeof(cmd), NULL); + tearoff_hook(); reply_ng(CMD_HF_MFU_OTP_TEAROFF, PM3_SUCCESS, NULL, 0); } diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 4e4f5c6f4..9488378fd 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -3102,7 +3102,7 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) { "hf mfu otptear -b 3 -i 100 -s 1000\n" "hf mfu otptear -b 3 -i 1 -e 200\n" "hf mfu otptear -b 3 -i 100 -s 200 -e 2500 -d FFFFFFFF -t EEEEEEEE\n" - "hf mfu otptear -b 3 -i 100 -s 200 -e 2500 -d FFFFFFFF -t EEEEEEEE -m 00000000 -> quite when OTP is reset" + "hf mfu otptear -b 3 -i 100 -s 200 -e 2500 -d FFFFFFFF -t EEEEEEEE -m 00000000 -> quit when OTP is reset" ); void *argtable[] = { @@ -3112,7 +3112,7 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) { arg_u64_0("e", "end", "", "end time (def 3000 us)"), arg_u64_0("s", "start", "", "start time (def 0 us)"), arg_str0("d", "data", "", "initialise data before run (4 bytes)"), - arg_str0("t", "test", "", "test write data (4 bytes)"), + arg_str0("t", "test", "", "test write data (4 bytes, 00000000 by default)"), arg_str0("m", "match", "", "exit criteria, if block matches this value (4 bytes)"), arg_param_end }; @@ -3126,6 +3126,7 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) { int d_len = 0; uint8_t data[4] = {0x00}; CLIGetHexWithReturn(ctx, 5, data, &d_len); + bool use_data = (d_len > 0); int t_len = 0; uint8_t test[4] = {0x00}; @@ -3150,7 +3151,7 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) { return PM3_EINVARG; } if (start > (end - steps)) { - PrintAndLogEx(WARNING, "Start time larger then (end time + steps)"); + PrintAndLogEx(WARNING, "Start time larger than (end time + steps)"); return PM3_EINVARG; } @@ -3169,26 +3170,34 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) { return PM3_EINVARG; } - uint8_t teardata[8] = {0x00}; - memcpy(teardata, data, sizeof(data)); - memcpy(teardata + sizeof(data), test, sizeof(test)); + uint8_t teardata[4] = {0x00}; + memcpy(teardata, test, sizeof(test)); PrintAndLogEx(INFO, "----------------- " _CYAN_("MFU Tear off") " ---------------------"); PrintAndLogEx(INFO, "Starting Tear-off test"); PrintAndLogEx(INFO, "Target block no: %u", blockno); - PrintAndLogEx(INFO, "Target inital block data : %s", sprint_hex_inrow(teardata, 4)); - PrintAndLogEx(INFO, "Target write block data : %s", sprint_hex_inrow(teardata + 4, 4)); + if (use_data) { + PrintAndLogEx(INFO, "Target inital block data : %s", sprint_hex_inrow(data, 4)); + } + PrintAndLogEx(INFO, "Target write block data : %s", sprint_hex_inrow(teardata, 4)); + if (use_match) { + PrintAndLogEx(INFO, "Target match block data : %s", sprint_hex_inrow(match, 4)); + } PrintAndLogEx(INFO, "----------------------------------------------------"); uint8_t isOK; - bool got_pre = false, got_post = false, lock_on = false; + bool lock_on = false; uint8_t pre[4] = {0}; uint8_t post[4] = {0}; uint32_t current = start; - int phase_clear = -1; - int phase_newwr = -1; + int phase_begin_clear = -1; + int phase_end_clear = -1; + int phase_begin_newwr = -1; + int phase_end_newwr = -1; + bool skip_phase1 = false; uint8_t retries = 0; + uint8_t error_retries = 0; - while (current <= (end - steps)) { + while ((current <= (end - steps)) && (error_retries < 10)) { if (kbd_enter_pressed()) { PrintAndLogEx(INFO, "\naborted via keyboard!\n"); @@ -3198,10 +3207,27 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) { PrintAndLogEx(INFO, "Using tear-off delay " _GREEN_("%" PRIu32) " us", current); clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFAREU_READBL, blockno, 0, 0, NULL, 0); PacketResponseNG resp; - got_pre = false; + if (use_data) { + SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, blockno, 0, 0, data, d_len); + bool got_written = false; + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + isOK = resp.oldarg[0] & 0xff; + if (isOK) { + got_written = true; + } + } + if (! got_written) { + PrintAndLogEx(FAILED, "Failed to write block BEFORE"); + error_retries++; + continue; // try again + } + } + + SendCommandMIX(CMD_HF_MIFAREU_READBL, blockno, 0, 0, NULL, 0); + + bool got_pre = false; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { isOK = resp.oldarg[0] & 0xFF; if (isOK) { @@ -3209,9 +3235,13 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) { got_pre = true; } } - + if (! got_pre) { + PrintAndLogEx(FAILED, "Failed to read block BEFORE"); + error_retries++; + continue; // try again + } clearCommandBuffer(); - SendCommandMIX(CMD_HF_MFU_OTP_TEAROFF, blockno, current, 0, teardata, 8); + SendCommandMIX(CMD_HF_MFU_OTP_TEAROFF, blockno, current, 0, teardata, sizeof(teardata)); // we be getting ACK that we are silently ignoring here.. @@ -3222,10 +3252,11 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) { if (resp.status != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Tear off reporting failure to select tag"); + error_retries++; continue; } - got_post = false; + bool got_post = false; clearCommandBuffer(); SendCommandMIX(CMD_HF_MIFAREU_READBL, blockno, 0, 0, NULL, 0); if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { @@ -3235,55 +3266,53 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) { got_post = true; } } + if (! got_post) { + PrintAndLogEx(FAILED, "Failed to read block BEFORE"); + error_retries++; + continue; // try again + } + error_retries = 0; + char prestr[20] = {0}; + snprintf(prestr, sizeof(prestr), "%s", sprint_hex_inrow(pre, sizeof(pre))); + char poststr[20] = {0}; + snprintf(poststr, sizeof(poststr), "%s", sprint_hex_inrow(post, sizeof(post))); - if (got_pre && got_post) { - - char prestr[20] = {0}; - snprintf(prestr, sizeof(prestr), "%s", sprint_hex_inrow(pre, sizeof(pre))); - char poststr[20] = {0}; - snprintf(poststr, sizeof(poststr), "%s", sprint_hex_inrow(post, sizeof(post))); - - if (memcmp(pre, post, sizeof(pre)) == 0) { - - PrintAndLogEx(INFO, "Current %02d (0x%02X) %s" - , blockno - , blockno - , poststr - ); - } else { - - // skip first message, since its the reset write. - if (current == start) { - PrintAndLogEx(INFO, "Inital write"); - } else { - PrintAndLogEx(INFO, _CYAN_("Tear off occured") " : %02d (0x%02X) %s vs " _RED_("%s") - , blockno - , blockno - , prestr - , poststr - ); - - lock_on = true; - - if (phase_clear == -1) - phase_clear = current; - - // new write phase must be atleast 100us later.. - if (phase_clear > -1 && phase_newwr == -1 && current > (phase_clear + 100)) - phase_newwr = current; - } - } - - if (use_match && memcmp(pre, match, sizeof(pre)) == 0) { - PrintAndLogEx(SUCCESS, "Block matches!\n"); - break; - } + if (memcmp(pre, post, sizeof(pre)) == 0) { + PrintAndLogEx(INFO, "Current : %02d (0x%02X) %s" + , blockno + , blockno + , poststr + ); } else { - if (got_pre == false) - PrintAndLogEx(FAILED, "Failed to read block BEFORE"); - if (got_post == false) - PrintAndLogEx(FAILED, "Failed to read block AFTER"); + PrintAndLogEx(INFO, _CYAN_("Tear off occurred") " : %02d (0x%02X) %s => " _RED_("%s") + , blockno + , blockno + , prestr + , poststr + ); + + lock_on = true; + + if ((phase_begin_clear == -1) && (bitcount32(*(uint32_t*)pre) > bitcount32(*(uint32_t*)post))) + phase_begin_clear = current; + + if ((phase_begin_clear > -1) && (phase_end_clear == -1) && (bitcount32(*(uint32_t*)post) == 0)) + phase_end_clear = current; + + if ((current == start) && (phase_end_clear > -1)) + skip_phase1 = true; + // new write phase must be atleast 100us later.. + if (((bitcount32(*(uint32_t*)pre) == 0) || (phase_end_clear > -1)) && (phase_begin_newwr == -1) && (bitcount32(*(uint32_t*)post) != 0) && (skip_phase1 || (current > (phase_end_clear + 100)))) + phase_begin_newwr = current; + + if ((phase_begin_newwr > -1) && (phase_end_newwr == -1) && (memcmp(post, teardata, sizeof(teardata)) == 0)) + phase_end_newwr = current; + } + + if (use_match && memcmp(post, match, sizeof(post)) == 0) { + PrintAndLogEx(SUCCESS, "Block matches stop condition!\n"); + break; } /* TEMPORALLY DISABLED @@ -3314,11 +3343,17 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) { } PrintAndLogEx(INFO, "----------------------------------------------------"); - if (phase_clear > - 1) { - PrintAndLogEx(INFO, "New phase boundary around " _YELLOW_("%d") " us", phase_clear); + if ((phase_begin_clear > - 1) && (phase_begin_clear != start)) { + PrintAndLogEx(INFO, "Erase phase start boundary around " _YELLOW_("%5d") " us", phase_begin_clear); } - if (phase_newwr > - 1) { - PrintAndLogEx(INFO, "New phase boundary around " _YELLOW_("%d") " us", phase_newwr); + if ((phase_end_clear > - 1) && (phase_end_clear != start)){ + PrintAndLogEx(INFO, "Erase phase end boundary around " _YELLOW_("%5d") " us", phase_end_clear); + } + if (phase_begin_newwr > - 1) { + PrintAndLogEx(INFO, "Write phase start boundary around " _YELLOW_("%5d") " us", phase_begin_newwr); + } + if (phase_end_newwr > - 1) { + PrintAndLogEx(INFO, "Write phase end boundary around " _YELLOW_("%5d") " us", phase_end_newwr); } PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; diff --git a/include/common.h b/include/common.h index 3c6245e52..f0ba424c8 100644 --- a/include/common.h +++ b/include/common.h @@ -56,6 +56,10 @@ struct version_information { #define DBG_EXTENDED 4 // errors + info + debug + breaking debug messages extern int DBGLEVEL; +// tear-off +extern uint16_t tearoff_delay_us; +extern bool tearoff_enabled; + // reader voltage field detector #define MF_MINFIELDV 4000 From f2a0f3e272f6893cabf9e260b7251f7e39e78daa Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 7 Mar 2021 23:48:48 +0100 Subject: [PATCH 24/67] replace static countones & bitcount by utils in client --- client/src/cmdhficlass.c | 10 +--------- client/src/cmdlffdxb.c | 12 +----------- client/src/cmdlfnedap.c | 12 +----------- 3 files changed, 3 insertions(+), 31 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 2fda649b8..7225a443b 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -103,14 +103,6 @@ static inline uint32_t leadingzeros(uint64_t a) { #else return 0; #endif -} -static inline uint32_t countones(uint64_t a) { -#if defined __GNUC__ - return __builtin_popcountll(a); -#else - return 0; -#endif - } const char *card_types[] = { @@ -2034,7 +2026,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { uint64_t a = bytes_to_num(data, 8); bool starts = (leadingzeros(a) < 12); - bool ones = (countones(a) > 16 && countones(a) < 48); + bool ones = (bitcount64(a) > 16 && bitcount64(a) < 48); if (starts && ones) { PrintAndLogEx(INFO, "data looks encrypted, False Positives " _YELLOW_("ARE") " possible"); diff --git a/client/src/cmdlffdxb.c b/client/src/cmdlffdxb.c index fdead8ea9..4287db630 100644 --- a/client/src/cmdlffdxb.c +++ b/client/src/cmdlffdxb.c @@ -118,16 +118,6 @@ static void verify_values(uint64_t *animalid, uint32_t *countryid, uint32_t *ext } } -static inline uint32_t bitcount(uint32_t a) { -#if defined __GNUC__ - return __builtin_popcountl(a); -#else - a = a - ((a >> 1) & 0x55555555); - a = (a & 0x33333333) + ((a >> 2) & 0x33333333); - return (((a + (a >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24; -#endif -} - // FDX-B ISO11784/85 demod (aka animal tag) BIPHASE, inverted, rf/32, with preamble of 00000000001 (128bits) // 8 databits + 1 parity (1) // CIITT 16 chksum @@ -594,7 +584,7 @@ int demodFDXB(bool verbose) { uint8_t bt_par = (extended & 0x100) >> 8; uint8_t bt_temperature = extended & 0xff; - uint8_t bt_calc_parity = (bitcount(bt_temperature) & 0x1) ? 0 : 1; + uint8_t bt_calc_parity = (bitcount32(bt_temperature) & 0x1) ? 0 : 1; uint8_t is_bt_temperature = (bt_calc_parity == bt_par) && !(extended & 0xe00) ; if (is_bt_temperature) { diff --git a/client/src/cmdlfnedap.c b/client/src/cmdlfnedap.c index 20cb5eec5..829a5b106 100644 --- a/client/src/cmdlfnedap.c +++ b/client/src/cmdlfnedap.c @@ -37,20 +37,10 @@ const uint8_t translateTable[10] = {8, 2, 1, 12, 4, 5, 10, 13, 0, 9}; const uint8_t invTranslateTable[16] = {8, 2, 1, 0xff, 4, 5, 0xff, 0xff, 0, 9, 6, 0xff, 3, 7, 0xff, 0xff}; const uint8_t preamble[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}; // zero inside -static inline uint32_t bitcount(uint32_t a) { -#if defined __GNUC__ - return __builtin_popcountl(a); -#else - a = a - ((a >> 1) & 0x55555555); - a = (a & 0x33333333) + ((a >> 2) & 0x33333333); - return (((a + (a >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24; -#endif -} - static uint8_t isEven_64_63(const uint8_t *data) { // 8 uint32_t tmp[2]; memcpy(tmp, data, 8); - return (bitcount(tmp[0]) + (bitcount(tmp[1] & 0xfeffffff))) & 1; + return (bitcount32(tmp[0]) + (bitcount32(tmp[1] & 0xfeffffff))) & 1; } //NEDAP demod - ASK/Biphase (or Diphase), RF/64 with preamble of 1111111110 (always a 128 bit data stream) From fd656541dd68ccf4c6edf978f3ae3930f47b98d0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 8 Mar 2021 00:28:38 +0100 Subject: [PATCH 25/67] fix lf t55xx wipe - calling write with correct params --- client/src/cmdlft55xx.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 7e86e1c78..11f397ca1 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -2939,35 +2939,36 @@ static int CmdT55xxWipe(const char *Cmd) { PrintAndLogEx(INFO, "Begin wiping..."); // Creating cmd string for write block :) - char writeData[36] = {0}; - char *ptrData = writeData; - snprintf(ptrData, sizeof(writeData), "-b 0 "); + char wcmd[36] = {0}; + char *pwcmd = wcmd; + + snprintf(pwcmd, sizeof(wcmd), "-b 0 "); if (usepwd) { - snprintf(ptrData + strlen(writeData), sizeof(writeData) - strlen(writeData), "p %08x ", password); + snprintf(pwcmd + strlen(wcmd), sizeof(wcmd) - strlen(wcmd), "-p %08x ", password); } - snprintf(ptrData + strlen(writeData), sizeof(writeData) - strlen(writeData), "d %08X", block0); + snprintf(pwcmd + strlen(wcmd), sizeof(wcmd) - strlen(wcmd), "-d %08X", block0); - if (CmdT55xxWriteBlock(ptrData) != PM3_SUCCESS) + if (CmdT55xxWriteBlock(pwcmd) != PM3_SUCCESS) PrintAndLogEx(WARNING, "Warning: error writing blk 0"); for (uint8_t blk = 1; blk < 8; blk++) { - snprintf(ptrData, sizeof(writeData), "-b %d -d 0", blk); + snprintf(pwcmd, sizeof(wcmd), "-b %d -d 00000000", blk); - if (CmdT55xxWriteBlock(ptrData) != PM3_SUCCESS) + if (CmdT55xxWriteBlock(pwcmd) != PM3_SUCCESS) PrintAndLogEx(WARNING, "Warning: error writing blk %d", blk); - memset(writeData, 0x00, sizeof(writeData)); + memset(wcmd, 0x00, sizeof(wcmd)); } // Check and rest t55xx downlink mode. if (config.downlink_mode != T55XX_DLMODE_FIXED) { // Detect found a different mode so card must support - snprintf(ptrData, sizeof(writeData), "-b 3 --pg1 -d 00000000"); - if (CmdT55xxWriteBlock(ptrData) != PM3_SUCCESS) { + snprintf(pwcmd, sizeof(wcmd), "-b 3 --pg1 -d 00000000"); + if (CmdT55xxWriteBlock(pwcmd) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Warning: failed writing block 3 page 1 (config)"); } - memset(writeData, 0x00, sizeof(writeData)); + memset(wcmd, 0x00, sizeof(wcmd)); } return PM3_SUCCESS; } From 07422419946649779492357ea45a3bc37722cb33 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 8 Mar 2021 00:47:11 +0100 Subject: [PATCH 26/67] fix lf t55 config - bitrate and macros (thanks @mwalker33) --- client/src/cmdlft55xx.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 11f397ca1..5c298e85b 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -447,7 +447,7 @@ static int CmdT55xxSetConfig(const char *Cmd) { arg_lit0(NULL, "st", "set/reset Sequence Terminator on"), arg_int0(NULL, "rate", "", "set bitrate <8|16|32|40|50|64|100|128>"), arg_str0("c", "blk0", "", "set configuration from a block0 (4 hex bytes)"), - arg_int0("o", "offset", "", "set offset, where data should start decode in bitstream"), + arg_int0("o", "offset", "<0-255>", "set offset, where data should start decode in bitstream "), }; uint8_t idx = 19; @@ -467,7 +467,8 @@ static int CmdT55xxSetConfig(const char *Cmd) { bool use_q5 = arg_get_lit(ctx, idx++); bool use_st = arg_get_lit(ctx, idx++); - int bitrate = arg_get_int_def(ctx, idx++, -1); + int bitrate = arg_get_int_def(ctx, idx, -1); + idx++; bool gotconf = false; uint32_t block0 = 0; @@ -481,7 +482,8 @@ static int CmdT55xxSetConfig(const char *Cmd) { gotconf = true; } - int offset = arg_get_int_def(ctx, idx++, -1); + int offset = arg_get_int_def(ctx, idx, -1); + idx++; bool r0 = arg_get_lit(ctx, idx++); bool r1 = arg_get_lit(ctx, idx++); @@ -519,7 +521,7 @@ static int CmdT55xxSetConfig(const char *Cmd) { } // validate user specified offset - if (offset > -1) { + if (offset > -1 && offset < 0x100) { config.offset = offset; } @@ -2941,7 +2943,7 @@ static int CmdT55xxWipe(const char *Cmd) { // Creating cmd string for write block :) char wcmd[36] = {0}; char *pwcmd = wcmd; - + snprintf(pwcmd, sizeof(wcmd), "-b 0 "); if (usepwd) { From 0a3c05c02c43b91e33aaaa8efce04a57103b1c7c Mon Sep 17 00:00:00 2001 From: mwalker33 <51802811+mwalker33@users.noreply.github.com> Date: Mon, 8 Mar 2021 13:40:06 +1100 Subject: [PATCH 27/67] Update cmdlft55xx.c fix toggle of ST INV and Q5/T55 fix lf t55xx brute for all downlink modes fix lf t55xx chk -f fix lf t55xx chk for all downlink modes --- client/src/cmdlft55xx.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 5c298e85b..3dc3c3f40 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -526,16 +526,18 @@ static int CmdT55xxSetConfig(const char *Cmd) { } // validate user specific T5555 / Q5 - config.Q5 = use_q5; + config.Q5 = use_q5 ^ config.Q5; // validate user specific sequence terminator - config.ST = use_st; - if (use_st) { + if (use_st) { + config.ST ^= use_st; config.block0 = ((config.block0 & ~(0x8)) | (config.ST << 3)); } // validate user specific invert - config.inverted = invert; + // In theory this should also be set in the config block 0; butit requries the extend mode config, which will change other things. + // as such, leave in user config for decoding the data until a full fix can be added. + config.inverted = invert ^ config.inverted ; // validate user specific downlink mode uint8_t downlink_mode = config.downlink_mode; @@ -3052,7 +3054,7 @@ static int CmdT55xxChkPwds(const char *Cmd) { } uint8_t downlink_mode = config.downlink_mode; - if (r0) + if (r0 || ra) // ra should start downlink mode ad fixed bit to loop through all modes correctly downlink_mode = refFixedBit; else if (r1) downlink_mode = refLongLeading; @@ -3062,7 +3064,9 @@ static int CmdT55xxChkPwds(const char *Cmd) { downlink_mode = ref1of4; bool use_pwd_file = false; - if (strlen(filename) == 0) { + if (strlen(filename) != 0) + use_pwd_file = true; + else if (strlen(filename) == 0) { snprintf(filename, sizeof(filename), "t55xx_default_pwds"); use_pwd_file = true; } @@ -3181,18 +3185,14 @@ static int CmdT55xxChkPwds(const char *Cmd) { PrintAndLogEx(INFO, "testing %08"PRIX32, curr_password); for (dl_mode = downlink_mode; dl_mode <= 3; dl_mode++) { - - if (!AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, curr_password, dl_mode)) { - continue; + if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, curr_password, dl_mode)) { + found = t55xxTryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0, curr_password); + if (found) { + PrintAndLogEx(SUCCESS, "found valid password: [ " _GREEN_("%08"PRIX32) " ]", curr_password); + break; + } } - - found = t55xxTryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0, curr_password); - if (found) { - PrintAndLogEx(SUCCESS, "found valid password: [ " _GREEN_("%08"PRIX32) " ]", curr_password); - break; - } - - if (ra == false) // Exit loop if not trying all downlink modes + if (!ra) // Exit loop if not trying all downlink modes break; } } @@ -3258,7 +3258,7 @@ static int CmdT55xxBruteForce(const char *Cmd) { } uint8_t downlink_mode = config.downlink_mode; - if (r0) + if (r0 || ra) // if try all (ra) then start at fixed bit for correct try all downlink_mode = refFixedBit; else if (r1) downlink_mode = refLongLeading; @@ -3266,6 +3266,8 @@ static int CmdT55xxBruteForce(const char *Cmd) { downlink_mode = refLeading0; else if (r3) downlink_mode = ref1of4; + else // no downlink mode so try default fixedbit only (as most likly) + downlink_mode = refFixedBit; uint32_t curr = 0; uint8_t found = 0; // > 0 if found xx1 xx downlink needed, 1 found From b01c269c70e48e55998434df558a75d3317c11b5 Mon Sep 17 00:00:00 2001 From: mwalker33 <51802811+mwalker33@users.noreply.github.com> Date: Mon, 8 Mar 2021 19:25:14 +1100 Subject: [PATCH 28/67] Update cmdlft55xx.c Code clean and tweak --- client/src/cmdlft55xx.c | 45 ++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 3dc3c3f40..ae2beddd9 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -463,6 +463,8 @@ static int CmdT55xxSetConfig(const char *Cmd) { idx++; } + // Not these flags are used to Toggle the values. + // If not flag then dont set or reset, leave as is since the call may just be be setting a different value. bool invert = arg_get_lit(ctx, idx++); bool use_q5 = arg_get_lit(ctx, idx++); bool use_st = arg_get_lit(ctx, idx++); @@ -525,10 +527,11 @@ static int CmdT55xxSetConfig(const char *Cmd) { config.offset = offset; } - // validate user specific T5555 / Q5 - config.Q5 = use_q5 ^ config.Q5; + // validate user specific T5555 / Q5 - use the flag to toggle between T5577 and Q5 + config.Q5 ^= use_q5; // validate user specific sequence terminator + // if use_st flag was supplied, then toggle and update the config block0; if not supplied skip the config block0 update. if (use_st) { config.ST ^= use_st; config.block0 = ((config.block0 & ~(0x8)) | (config.ST << 3)); @@ -537,7 +540,8 @@ static int CmdT55xxSetConfig(const char *Cmd) { // validate user specific invert // In theory this should also be set in the config block 0; butit requries the extend mode config, which will change other things. // as such, leave in user config for decoding the data until a full fix can be added. - config.inverted = invert ^ config.inverted ; + // use the flag to toggle if invert is on or off. + config.inverted ^= invert; // validate user specific downlink mode uint8_t downlink_mode = config.downlink_mode; @@ -3053,22 +3057,21 @@ static int CmdT55xxChkPwds(const char *Cmd) { return PM3_EINVARG; } - uint8_t downlink_mode = config.downlink_mode; - if (r0 || ra) // ra should start downlink mode ad fixed bit to loop through all modes correctly - downlink_mode = refFixedBit; - else if (r1) + uint8_t downlink_mode = refFixedBit; // Password checks should always start with default/fixed bit unluess requested by user for specific mode + // if (r0 || ra) // ra should start downlink mode ad fixed bit to loop through all modes correctly + // downlink_mode = refFixedBit; + // else + if (r1) downlink_mode = refLongLeading; else if (r2) downlink_mode = refLeading0; else if (r3) downlink_mode = ref1of4; - bool use_pwd_file = false; - if (strlen(filename) != 0) - use_pwd_file = true; - else if (strlen(filename) == 0) { + bool use_pwd_file = true; // Assume we are going to use a file, unless turned off later. + + if (strlen(filename) == 0) { snprintf(filename, sizeof(filename), "t55xx_default_pwds"); - use_pwd_file = true; } PrintAndLogEx(INFO, "press " _GREEN_("'enter'") " to cancel the command"); @@ -3089,6 +3092,7 @@ static int CmdT55xxChkPwds(const char *Cmd) { uint8_t flags = downlink_mode << 3; if (from_flash) { + use_pwd_file = false; // turn of local password file since we are checking from flash. clearCommandBuffer(); SendCommandNG(CMD_LF_T55XX_CHK_PWDS, &flags, sizeof(flags)); PacketResponseNG resp; @@ -3185,6 +3189,9 @@ static int CmdT55xxChkPwds(const char *Cmd) { PrintAndLogEx(INFO, "testing %08"PRIX32, curr_password); for (dl_mode = downlink_mode; dl_mode <= 3; dl_mode++) { + // If aquire fails, then we still need to check if we are only trying a single downlink mode. + // If we continue on fail, it will skip that test and try the next downlink mode; thus slowing down the check + // when on a single downlink mode is wanted. if (AcquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, curr_password, dl_mode)) { found = t55xxTryDetectModulationEx(dl_mode, T55XX_PrintConfig, 0, curr_password); if (found) { @@ -3192,7 +3199,7 @@ static int CmdT55xxChkPwds(const char *Cmd) { break; } } - if (!ra) // Exit loop if not trying all downlink modes + if (ra == false) // Exit loop if not trying all downlink modes break; } } @@ -3257,17 +3264,17 @@ static int CmdT55xxBruteForce(const char *Cmd) { return PM3_EINVARG; } - uint8_t downlink_mode = config.downlink_mode; - if (r0 || ra) // if try all (ra) then start at fixed bit for correct try all - downlink_mode = refFixedBit; - else if (r1) + uint8_t downlink_mode = refFixedBit; // if no downlink mode suppliled use fixed bit/default as the is the most common + // Since we dont know the password the config.downlink mode is of little value. +// if (r0 || ra) // if try all (ra) then start at fixed bit for correct try all +// downlink_mode = refFixedBit; +// else + if (r1) downlink_mode = refLongLeading; else if (r2) downlink_mode = refLeading0; else if (r3) downlink_mode = ref1of4; - else // no downlink mode so try default fixedbit only (as most likly) - downlink_mode = refFixedBit; uint32_t curr = 0; uint8_t found = 0; // > 0 if found xx1 xx downlink needed, 1 found From 59379247e66b16191f485cd189dc8b1a6b1d378a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 8 Mar 2021 11:31:40 +0100 Subject: [PATCH 29/67] adapt text to t55xx --- client/src/cmdlfnedap.c | 28 ++++++++++++++-------------- doc/cheatsheet.md | 4 ++-- doc/cloner_notes.md | 4 ++-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/client/src/cmdlfnedap.c b/client/src/cmdlfnedap.c index 829a5b106..e45d35c3d 100644 --- a/client/src/cmdlfnedap.c +++ b/client/src/cmdlfnedap.c @@ -242,25 +242,25 @@ static int CmdLFNedapDemod(const char *Cmd) { configuration -lf t55xx wr b 0 d 00170082 +lf t55xx wr -b 0 -d 00170082 1) uid 049033 -lf t55 wr b 1 d FF8B4168 -lf t55 wr b 2 d C90B5359 -lf t55 wr b 3 d 19A40087 -lf t55 wr b 4 d 120115CF +lf t55xx wr -b 1 -d FF8B4168 +lf t55xx wr -b 2 -d C90B5359 +lf t55xx wr -b 3 -d 19A40087 +lf t55xx wr -b 4 -d 120115CF 2) uid 001630 -lf t55 wr b 1 d FF8B6B20 -lf t55 wr b 2 d F19B84A3 -lf t55 wr b 3 d 18058007 -lf t55 wr b 4 d 1200857C +lf t55xx wr -b 1 -d FF8B6B20 +lf t55xx wr -b 2 -d F19B84A3 +lf t55xx wr -b 3 -d 18058007 +lf t55xx wr -b 4 -d 1200857C 3) uid 39feff -lf t55xx wr b 1 d ffbfa73e -lf t55xx wr b 2 d 4c0003ff -lf t55xx wr b 3 d ffbfa73e -lf t55xx wr b 4 d 4c0003ff +lf t55xx wr -b 1 -d ffbfa73e +lf t55xx wr -b 2 -d 4c0003ff +lf t55xx wr -b 3 -d ffbfa73e +lf t55xx wr -b 4 -d 4c0003ff */ @@ -459,7 +459,7 @@ static int CmdLFNedapClone(const char *Cmd) { if (res == PM3_SUCCESS) { PrintAndLogEx(INFO, "The block 0 was changed (eXtended) which can be hard to detect."); - PrintAndLogEx(INFO, "Configure it manually " _YELLOW_("`lf t55xx config b 64 d BI i 1 o 32`")); + PrintAndLogEx(INFO, "Configure it manually " _YELLOW_("`lf t55xx config -b 64 --BI -i -o 32`")); } else { PrintAndLogEx(NORMAL, ""); } diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index 1358c8f3d..4ff857d9c 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -561,7 +561,7 @@ EM is ASK HID Prox is FSK Indala is PSK -pm3 --> lf t55xx config FSK +pm3 --> lf t55xx config --FSK ``` Set timings to default @@ -579,7 +579,7 @@ Write to T55xx block b : block number to write. Between 0-7 d : 4 bytes of data to write (8 hex characters) -pm3 --> lf t55xx wr b 0 d 00081040 +pm3 --> lf t55xx wr -b 0 -d 00081040 ``` Wipe a T55xx tag and set defaults diff --git a/doc/cloner_notes.md b/doc/cloner_notes.md index 92de920ad..77edc244b 100644 --- a/doc/cloner_notes.md +++ b/doc/cloner_notes.md @@ -69,12 +69,12 @@ The T55x7 protocol uses a pwm based protocol for writing to tags. In order to m ``` -- after threshold limit 20 is triggered, skip 10000 samples before collecting samples. -lf config s 10000 t 20 +lf config -s 10000 -t 20 lf t55xx sniff -- if you have a save trace from before, try data load -f xxxxxxx.pm3 -lf t55xx sniff 1 +lf t55xx sniff -1 ``` It uses the existing `lf sniff` command to collect the data, so setting that first as per normal sniffing is recommended. Once you have a sniff, you can "re-sniff" from the stored sniffed data and try different settings, if you think the data is not clean. From 02aabf90d3ae98568baa87d34e39b764c63c0e2b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 8 Mar 2021 17:39:21 +0100 Subject: [PATCH 30/67] mem spi mount/unmount/test/check/tree/info/remove/rename/wwipe - now uses cliparser. remove/rename uses NG --- armsrc/appmain.c | 42 ++-- client/src/cmdflashmemspiffs.c | 380 +++++++++++++++++++-------------- 2 files changed, 242 insertions(+), 180 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index e9c34e2cc..22190ef1a 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -2097,29 +2097,39 @@ static void PacketReceived(PacketCommandNG *packet) { } case CMD_SPIFFS_REMOVE: { LED_B_ON(); - uint8_t filename[32]; - uint8_t *pfilename = packet->data.asBytes; - memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN); - if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Filename received for spiffs REMOVE : %s", filename); - rdv40_spiffs_remove((char *) filename, RDV40_SPIFFS_SAFETY_SAFE); + + struct p { + uint8_t len; + uint8_t fn[32]; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + + if (DBGLEVEL >= DBG_DEBUG) { + Dbprintf("Filename received for spiffs REMOVE : %s", payload->fn); + } + + rdv40_spiffs_remove((char *)payload->fn, RDV40_SPIFFS_SAFETY_SAFE); + reply_ng(CMD_SPIFFS_REMOVE, PM3_SUCCESS, NULL, 0); LED_B_OFF(); break; } case CMD_SPIFFS_RENAME: { LED_B_ON(); - uint8_t src[32]; - uint8_t dest[32]; - uint8_t *pfilename = packet->data.asBytes; - char *token; - token = strtok((char *)pfilename, ","); - strncpy((char *)src, token, sizeof(src) - 1); - token = strtok(NULL, ","); - strncpy((char *)dest, token, sizeof(dest) - 1); + struct p { + uint8_t slen; + uint8_t src[32]; + uint8_t dlen; + uint8_t dest[32]; + } PACKED; + + struct p *payload = (struct p *) packet->data.asBytes; + if (DBGLEVEL >= DBG_DEBUG) { - Dbprintf("Filename received as source for spiffs RENAME : %s", src); - Dbprintf("Filename received as destination for spiffs RENAME : %s", dest); + Dbprintf("Filename received as source for spiffs RENAME : %s", payload->src); + Dbprintf("Filename received as destination for spiffs RENAME : %s", payload->dest); } - rdv40_spiffs_rename((char *) src, (char *)dest, RDV40_SPIFFS_SAFETY_SAFE); + rdv40_spiffs_rename((char *)payload->src, (char *)payload->dest, RDV40_SPIFFS_SAFETY_SAFE); + reply_ng(CMD_SPIFFS_RENAME, PM3_SUCCESS, NULL, 0); LED_B_OFF(); break; } diff --git a/client/src/cmdflashmemspiffs.c b/client/src/cmdflashmemspiffs.c index 11c4db2d7..f0877ab0d 100644 --- a/client/src/cmdflashmemspiffs.c +++ b/client/src/cmdflashmemspiffs.c @@ -8,34 +8,15 @@ // Proxmark3 RDV40 Flash memory commands //----------------------------------------------------------------------------- #include "cmdflashmemspiffs.h" - #include - -#include "cmdparser.h" // command_t +#include "cmdparser.h" // command_t #include "pmflash.h" #include "fileutils.h" //saveFile -#include "comms.h" //getfromdevice +#include "comms.h" //getfromdevice +#include "cliparser.h" static int CmdHelp(const char *Cmd); -static int usage_flashmemspiffs_remove(void) { - PrintAndLogEx(NORMAL, "Remove a file from spiffs filesystem\n"); - PrintAndLogEx(NORMAL, "Usage: mem spiffs remove "); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs remove lasttag.bin")); - return PM3_SUCCESS; -} - -static int usage_flashmemspiffs_rename(void) { - PrintAndLogEx(NORMAL, "Rename/move a file in spiffs filesystem\n"); - PrintAndLogEx(NORMAL, "Usage: mem spiffs rename "); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs rename lasttag.bin oldtag.bin")); - return PM3_SUCCESS; -} - static int usage_flashmemspiffs_copy(void) { PrintAndLogEx(NORMAL, "Copy a file to another (destructively) in spiffs filesystem\n"); PrintAndLogEx(NORMAL, "Usage: mem spiffs copy "); @@ -82,121 +63,260 @@ static int usage_flashmemspiffs_wipe(void) { PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs wipe")); return PM3_SUCCESS; } + + +int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) { + + int ret_val = PM3_SUCCESS; + + // We want to mount before multiple operation so the lazy writes/append will not + // trigger a mount + umount each loop iteration (lazy ops device side) + SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0); + + // Send to device + uint32_t bytes_sent = 0; + uint32_t bytes_remaining = datalen; + uint32_t append = 0; + + // fast push mode + conn.block_after_ACK = true; + + while (bytes_remaining > 0) { + uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); + + clearCommandBuffer(); + + char fdata[32 + bytes_in_packet]; + memset(fdata, 0, sizeof(fdata)); + memcpy(fdata, destfn, 32); + memcpy(fdata + 32, data + bytes_sent, bytes_in_packet); + + if (bytes_sent > 0) + append = 1; + + SendCommandOLD(CMD_SPIFFS_WRITE, append, bytes_in_packet, 0, fdata, 32 + bytes_in_packet); + + bytes_remaining -= bytes_in_packet; + bytes_sent += bytes_in_packet; + + PacketResponseNG resp; + + uint8_t retry = 3; + while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + retry--; + if (retry == 0) { + ret_val = PM3_ETIMEOUT; + goto out; + } + } + + uint8_t isok = resp.oldarg[0] & 0xFF; + if (!isok) { + PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent); + ret_val = PM3_EFLASH; + break; + } + } + +out: + clearCommandBuffer(); + + // turn off fast push mode + conn.block_after_ACK = false; + + // We want to unmount after these to set things back to normal but more than this + // unmouting ensure that SPIFFS CACHES are all flushed so our file is actually written on memory + SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0); + + return ret_val; +} + static int CmdFlashMemSpiFFSMount(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs mount", + "Mount the SPIFFS file system if not already mounted", + "mem spiffs mount"); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); clearCommandBuffer(); SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0); return PM3_SUCCESS; } static int CmdFlashMemSpiFFSUnmount(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs unmount", + "Un-mount the SPIFFS file system", + "mem spiffs unmount"); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); clearCommandBuffer(); SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0); return PM3_SUCCESS; } static int CmdFlashMemSpiFFSTest(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs test", + "Test SPIFFS Operations, require wiping pages 0 and 1", + "mem spiffs test"); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); clearCommandBuffer(); SendCommandNG(CMD_SPIFFS_TEST, NULL, 0); return PM3_SUCCESS; } static int CmdFlashMemSpiFFSCheck(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs check", + "Check/try to defrag faulty/fragmented SPIFFS file system", + "mem spiffs check"); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); clearCommandBuffer(); SendCommandNG(CMD_SPIFFS_CHECK, NULL, 0); return PM3_SUCCESS; } static int CmdFlashMemSpiFFSTree(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs tree", + "Print the Flash memory file system tree", + "mem spiffs tree"); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); clearCommandBuffer(); SendCommandNG(CMD_SPIFFS_PRINT_TREE, NULL, 0); return PM3_SUCCESS; } static int CmdFlashMemSpiFFSInfo(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs info", + "Print file system info and usage statistics", + "mem spiffs info"); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); clearCommandBuffer(); SendCommandNG(CMD_SPIFFS_PRINT_FSINFO, NULL, 0); return PM3_SUCCESS; } static int CmdFlashMemSpiFFSRemove(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs remove", + "Remove a file from SPIFFS filesystem", + "mem spiffs remove -f lasttag.bin" + ); - int len = strlen(Cmd); - if (len < 1) { - return usage_flashmemspiffs_remove(); - } - - char ctmp = tolower(param_getchar(Cmd, 0)); - if (len == 1 && ctmp == 'h') { - return usage_flashmemspiffs_remove(); - } + void *argtable[] = { + arg_param_begin, + arg_str1("f", "filename", "", "file to remove"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + int fnlen = 0; char filename[32] = {0}; - bool errors = false; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, 32, &fnlen); + CLIParserFree(ctx); - if (param_getstr(Cmd, 0, filename, 32) >= 32) { - PrintAndLogEx(FAILED, "Filename too long"); - errors = true; - } + PrintAndLogEx(DEBUG, "Removing `" _YELLOW_("%s") "`", filename); + struct { + uint8_t len; + uint8_t fn[32]; + } PACKED payload; + payload.len = fnlen; + memcpy(payload.fn, filename, fnlen); - // check null filename ? - if (errors) { - usage_flashmemspiffs_remove(); - return PM3_EINVARG; - } + PacketResponseNG resp; + clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_REMOVE, (uint8_t *)&payload, sizeof(payload)); + WaitForResponse(CMD_SPIFFS_REMOVE, &resp); + if (resp.status == PM3_SUCCESS) + PrintAndLogEx(INFO, "Done!"); - SendCommandMIX(CMD_SPIFFS_REMOVE, 0, 0, 0, (uint8_t *)filename, 32); return PM3_SUCCESS; } static int CmdFlashMemSpiFFSRename(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs rename", + "Rename/move a file from SPIFFS filesystem.", + "mem spiffs rename -s aaa.bin -d bbb.bin" + ); - int len = strlen(Cmd); - if (len < 1) { - return usage_flashmemspiffs_rename(); - } + void *argtable[] = { + arg_param_begin, + arg_str1("s", "src", "", "source file name"), + arg_str1("d", "dest", "", "destination file name"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); - char ctmp = tolower(param_getchar(Cmd, 0)); - if (len == 1 && ctmp == 'h') { - return usage_flashmemspiffs_rename(); - } + int slen = 0; + char src[32] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, 32, &slen); - char srcfilename[32] = {0}; - char destfilename[32] = {0}; - bool errors = false; + int dlen = 0; + char dest[32] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, 32, &dlen); + CLIParserFree(ctx); - if (param_getstr(Cmd, 0, srcfilename, 32) >= 32) { - PrintAndLogEx(FAILED, "Source Filename too long"); - errors = true; - } - if (srcfilename[0] == '\0') { - PrintAndLogEx(FAILED, "Source Filename missing or invalid"); - errors = true; - } + PrintAndLogEx(DEBUG, "Rename from `" _YELLOW_("%s") "` -> `" _YELLOW_("%s") "`", src, dest); - if (param_getstr(Cmd, 1, destfilename, 32) >= 32) { - PrintAndLogEx(FAILED, "Source Filename too long"); - errors = true; - } - if (destfilename[0] == '\0') { - PrintAndLogEx(FAILED, "Source Filename missing or invalid"); - errors = true; - } + struct { + uint8_t slen; + uint8_t src[32]; + uint8_t dlen; + uint8_t dest[32]; + } PACKED payload; + payload.slen = slen; + payload.dlen = dlen; - // check null filename ? - if (errors) { - usage_flashmemspiffs_rename(); - return PM3_EINVARG; - } + memcpy(payload.src, src, slen); + memcpy(payload.dest, dest, dlen); - char data[65]; - sprintf(data, "%s,%s", srcfilename, destfilename); - SendCommandMIX(CMD_SPIFFS_RENAME, 0, 0, 0, (uint8_t *)data, 65); + PacketResponseNG resp; + clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_RENAME, (uint8_t *)&payload, sizeof(payload)); + WaitForResponse(CMD_SPIFFS_RENAME, &resp); + if (resp.status == PM3_SUCCESS) + PrintAndLogEx(INFO, "Done!"); + + PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify"); return PM3_SUCCESS; } @@ -353,73 +473,6 @@ static int CmdFlashMemSpiFFSDump(const char *Cmd) { return PM3_SUCCESS; } -int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) { - - int ret_val = PM3_SUCCESS; - - // We want to mount before multiple operation so the lazy writes/append will not - // trigger a mount + umount each loop iteration (lazy ops device side) - SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0); - - // Send to device - uint32_t bytes_sent = 0; - uint32_t bytes_remaining = datalen; - uint32_t append = 0; - - // fast push mode - conn.block_after_ACK = true; - - while (bytes_remaining > 0) { - uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); - - clearCommandBuffer(); - - char fdata[32 + bytes_in_packet]; - memset(fdata, 0, sizeof(fdata)); - memcpy(fdata, destfn, 32); - memcpy(fdata + 32, data + bytes_sent, bytes_in_packet); - - if (bytes_sent > 0) - append = 1; - - SendCommandOLD(CMD_SPIFFS_WRITE, append, bytes_in_packet, 0, fdata, 32 + bytes_in_packet); - - bytes_remaining -= bytes_in_packet; - bytes_sent += bytes_in_packet; - - PacketResponseNG resp; - - uint8_t retry = 3; - while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - retry--; - if (retry == 0) { - ret_val = PM3_ETIMEOUT; - goto out; - } - } - - uint8_t isok = resp.oldarg[0] & 0xFF; - if (!isok) { - PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent); - ret_val = PM3_EFLASH; - break; - } - } - -out: - clearCommandBuffer(); - - // turn off fast push mode - conn.block_after_ACK = false; - - // We want to unmount after these to set things back to normal but more than this - // unmouting ensure that SPIFFS CACHES are all flushed so our file is actually written on memory - SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0); - - return ret_val; -} - static int CmdFlashMemSpiFFSWipe(const char *Cmd) { char ctmp = tolower(param_getchar(Cmd, 0)); @@ -433,7 +486,7 @@ static int CmdFlashMemSpiFFSWipe(const char *Cmd) { SendCommandNG(CMD_SPIFFS_WIPE, NULL, 0); WaitForResponse(CMD_SPIFFS_WIPE, &resp); PrintAndLogEx(INFO, "Done!"); - PrintAndLogEx(HINT, "Try use '" _YELLOW_("mem spiffs tree") "' to verify."); + PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify"); return PM3_SUCCESS; } @@ -495,20 +548,19 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) { } static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"copy", CmdFlashMemSpiFFSCopy, IfPm3Flash, "Copy a file to another (destructively) in SPIFFS FileSystem in FlashMEM (spiffs)"}, - {"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented Filesystem"}, - {"dump", CmdFlashMemSpiFFSDump, IfPm3Flash, "Dump a file from SPIFFS FileSystem in FlashMEM (spiffs)"}, - {"info", CmdFlashMemSpiFFSInfo, IfPm3Flash, "Print filesystem info and usage statistics (spiffs)"}, - {"load", CmdFlashMemSpiFFSLoad, IfPm3Flash, "Upload file into SPIFFS Filesystem (spiffs)"}, - {"mount", CmdFlashMemSpiFFSMount, IfPm3Flash, "Mount the SPIFFS Filesystem if not already mounted (spiffs)"}, - {"remove", CmdFlashMemSpiFFSRemove, IfPm3Flash, "Remove a file from SPIFFS FileSystem in FlashMEM (spiffs)"}, - {"rename", CmdFlashMemSpiFFSRename, IfPm3Flash, "Rename/move a file in SPIFFS FileSystem in FlashMEM (spiffs)"}, - {"test", CmdFlashMemSpiFFSTest, IfPm3Flash, "Test SPIFFS Operations (require wiping pages 0 and 1)"}, - {"tree", CmdFlashMemSpiFFSTree, IfPm3Flash, "Print the Flash Memory FileSystem Tree (spiffs)"}, - {"unmount", CmdFlashMemSpiFFSUnmount, IfPm3Flash, "Un-mount the SPIFFS Filesystem if not already mounted (spiffs)"}, - {"wipe", CmdFlashMemSpiFFSWipe, IfPm3Flash, "Wipe all files from SPIFFS FileSystem." _RED_("* dangerous *") }, + {"copy", CmdFlashMemSpiFFSCopy, IfPm3Flash, "Copy a file to another (destructively) in SPIFFS file system"}, + {"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented file system"}, + {"dump", CmdFlashMemSpiFFSDump, IfPm3Flash, "Dump a file from SPIFFS file system"}, + {"info", CmdFlashMemSpiFFSInfo, IfPm3Flash, "Print file system info and usage statistics"}, + {"load", CmdFlashMemSpiFFSLoad, IfPm3Flash, "Upload file into SPIFFS file system"}, + {"mount", CmdFlashMemSpiFFSMount, IfPm3Flash, "Mount the SPIFFS file system if not already mounted"}, + {"remove", CmdFlashMemSpiFFSRemove, IfPm3Flash, "Remove a file from SPIFFS file system"}, + {"rename", CmdFlashMemSpiFFSRename, IfPm3Flash, "Rename/move a file in SPIFFS file system"}, + {"test", CmdFlashMemSpiFFSTest, IfPm3Flash, "Test SPIFFS Operations"}, + {"tree", CmdFlashMemSpiFFSTree, IfPm3Flash, "Print the Flash memory file system tree"}, + {"unmount", CmdFlashMemSpiFFSUnmount, IfPm3Flash, "Un-mount the SPIFFS file system"}, + {"wipe", CmdFlashMemSpiFFSWipe, IfPm3Flash, "Wipe all files from SPIFFS file system. * " _RED_("dangerous") " *" }, {NULL, NULL, NULL, NULL} }; From 1e14ddbcf025ef00e1f7411ccd5e81740d261c90 Mon Sep 17 00:00:00 2001 From: mwalker33 <51802811+mwalker33@users.noreply.github.com> Date: Tue, 9 Mar 2021 11:51:57 +1100 Subject: [PATCH 31/67] Update T5577_Guide.md --- doc/T5577_Guide.md | 141 +++++++++++++++++++++++---------------------- 1 file changed, 71 insertions(+), 70 deletions(-) diff --git a/doc/T5577_Guide.md b/doc/T5577_Guide.md index 4bd8f30c6..6cc0a96b9 100644 --- a/doc/T5577_Guide.md +++ b/doc/T5577_Guide.md @@ -24,17 +24,17 @@ ## Introduction -The T5577 is a generic LF (Low Frequency) RFID card the is used in the +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 learn how to use the proxmark3. -It is highly recommend that when learning about RFID that learning how +It is highly recommended that when learning about RFID that learning how to read the data sheets be near the top of the list. It can be very hard as the data sheet will hold the information you need, but you don’t yet know what it means. As such, I will attempt to point to sections of the data sheet and would highly advise that you look at the data sheet as you go. Overtime the data sheet may change, as a result things may not -always be reference correctly. +always be referenced correctly. As at writing this guide, the data sheet can be found at : @@ -64,9 +64,9 @@ the chip how to behave. ## What data is on my T5577 -Let’s have a look and see what a card might look in the proxmark3 +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 -output data, the proxmark3 software need to work out how to interpreted +output data, the proxmark3 software needs to work out how to interpret the data it receives, we do this with the following command. It should be noted that the T5577 has many clones. As such the default @@ -102,20 +102,20 @@ Your results should look similar to the following: [+] blk | hex data | binary | ascii [+] ----+----------+----------------------------------+------- [+] 00 | 000880E0 | 00000000000010001000000011100000 | .... -[+] 01 | FFFFFFFF | 11111111111111111111111111111111 | .... -[+] 02 | FFFFFFFF | 11111111111111111111111111111111 | .... -[+] 03 | FFFFFFFF | 11111111111111111111111111111111 | .... -[+] 04 | FFFFFFFF | 11111111111111111111111111111111 | .... -[+] 05 | FFFFFFFF | 11111111111111111111111111111111 | .... -[+] 06 | FFFFFFFF | 11111111111111111111111111111111 | .... -[+] 07 | FFFFFFFF | 11111111111111111111111111111111 | .... +[+] 01 | 00000000 | 00000000000000000000000000000000 | .... +[+] 02 | 00000000 | 00000000000000000000000000000000 | .... +[+] 03 | 00000000 | 00000000000000000000000000000000 | .... +[+] 04 | 00000000 | 00000000000000000000000000000000 | .... +[+] 05 | 00000000 | 00000000000000000000000000000000 | .... +[+] 06 | 00000000 | 00000000000000000000000000000000 | .... +[+] 07 | 00000000 | 00000000000000000000000000000000 | .... [+] Reading Page 1: [+] blk | hex data | binary | ascii [+] ----+----------+----------------------------------+------- [+] 00 | 000880E0 | 00000000000010001000000011100000 | .... -[+] 01 | E0150A48 | 11100000000101010000101001001000 | ...H -[+] 02 | 2D782308 | 00101101011110000010001100001000 | -x#. -[+] 03 | FFFFFFFF | 11111111111111111111111111111111 | .... +[+] 01 | 00000000 | 00000000000000000000000000000000 | .... +[+] 02 | 00000000 | 00000000000000000000000000000000 | .... +[+] 03 | 00000000 | 00000000000000000000000000000000 | .... ``` I will cover the meaning of this data as we go, but for now, lets keep it simple. @@ -126,7 +126,7 @@ 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 needed for the chip (and its configuration). Lucky for us, the developers have done a great job and gave us commands. What we need to -know is that with the T5577 data is read/written one complete block at a +know is that with the T5577, data is read/written one complete block at a time. Each block holds 32 bits of data (hence the binary output shown) Since we know that the card has data and configuration blocks, lets say @@ -150,14 +150,14 @@ can see the card) [+] Reading Page 0: [+] blk | hex data | binary | ascii [+] ----+----------+----------------------------------+------- - [+] 01 | FFFFFFFF | 11111111111111111111111111111111 | .... + [+] 01 | 00000000 | 00000000000000000000000000000000 | .... ``` - Note: Depending on the history of your card your data may vary, but + Note: Depending on the history of your card, your data may vary, but should match the dump data. 2) Write some new data into block 1 on the card. - We use the d option to supply the data ‘12345678’ + We use the -d option to supply the data ‘12345678’ ``` [usb] pm3 --> lf t55xx write -b 1 -d 12345678 ``` @@ -177,8 +177,8 @@ can see the card) [+] 01 | 12345678 | 00010010001101000101011001111000 | .4Vx ``` 4) The data is written in Hexadecimal. A single hex digit holds 4 bits - of data. So to store 32 bits in a block we need to supply 8 hex - digits (8 \* 4 = 32). If you are familiar with hex and binary do a + of data. So to store 32 bits in a block, we need to supply 8 hex + digits (8 \* 4 = 32). If you are not familiar with hex and binary do a little bit of home work to learn. The following is a quick start. | Hex | Binary | Decimal | @@ -238,31 +238,34 @@ result: [+] ----+----------+----------------------------------+------- [+] 00 | 000880E0 | 00000000000010001000000011100000 | .... [+] 01 | 89ABCDEF | 10001001101010111100110111101111 | .... -[+] 02 | FFFFFFFF | 11111111111111111111111111111111 | .... -[+] 03 | FFFFFFFF | 11111111111111111111111111111111 | .... -[+] 04 | FFFFFFFF | 11111111111111111111111111111111 | .... -[+] 05 | FFFFFFFF | 11111111111111111111111111111111 | .... -[+] 06 | FFFFFFFF | 11111111111111111111111111111111 | .... -[+] 07 | FFFFFFFF | 11111111111111111111111111111111 | .... +[+] 02 | 00000000 | 00000000000000000000000000000000 | .... +[+] 03 | 00000000 | 00000000000000000000000000000000 | .... +[+] 04 | 00000000 | 00000000000000000000000000000000 | .... +[+] 05 | 00000000 | 00000000000000000000000000000000 | .... +[+] 06 | 00000000 | 00000000000000000000000000000000 | .... +[+] 07 | 00000000 | 00000000000000000000000000000000 | .... [+] Reading Page 1: [+] blk | hex data | binary | ascii [+] ----+----------+----------------------------------+------- [+] 00 | 000880E0 | 00000000000010001000000011100000 | .... -[+] 01 | E0150A48 | 11100000000101010000101001001000 | ...H -[+] 02 | 2D782308 | 00101101011110000010001100001000 | -x#. -[+] 03 | FFFFFFFF | 11111111111111111111111111111111 | .... +[+] 01 | 00000000 | 00000000000000000000000000000000 | .... +[+] 02 | 00000000 | 00000000000000000000000000000000 | .... +[+] 03 | 00000000 | 00000000000000000000000000000000 | .... ``` -Practice reading and writing to blocks 1 to 7 until you are happy you +Practice reading and writing to blocks 1 to 6 until you are happy you can do it and get the results you wanted (i.e. the data you want stored -is written to the block you want it stored in). +is written to the block you want it stored in). I recommend staying +away from block 7 as this is where the password is stored, if uesed. +If you forget this data/password, you wont be able to read or write +to the card. ## How do I use a password This can be a little tricky for beginners. ***If you forget your password you will lose access to your card***. -To tell the T5577 to use a password we have to change the data in the +To tell the T5577 to use a password, we have to change the data in the configuration block (0). To help learn this and make it as simple as I can, please read and follow exactly. If your results DON’T match 100% as required, please do not proceed. @@ -331,20 +334,20 @@ required, please do not proceed. [+] blk | hex data | binary | ascii [+] ----+----------+----------------------------------+------- [+] 00 | 000880E0 | 00000000000010001000000011100000 | .... - [+] 01 | FFFFFFFF | 11111111111111111111111111111111 | .... - [+] 02 | FFFFFFFF | 11111111111111111111111111111111 | .... - [+] 03 | FFFFFFFF | 11111111111111111111111111111111 | .... - [+] 04 | FFFFFFFF | 11111111111111111111111111111111 | .... - [+] 05 | FFFFFFFF | 11111111111111111111111111111111 | .... - [+] 06 | FFFFFFFF | 11111111111111111111111111111111 | .... + [+] 01 | 00000000 | 00000000000000000000000000000000 | .... + [+] 02 | 00000000 | 00000000000000000000000000000000 | .... + [+] 03 | 00000000 | 00000000000000000000000000000000 | .... + [+] 04 | 00000000 | 00000000000000000000000000000000 | .... + [+] 05 | 00000000 | 00000000000000000000000000000000 | .... + [+] 06 | 00000000 | 00000000000000000000000000000000 | .... [+] 07 | 12345678 | 00010010001101000101011001111000 | .4Vx [+] Reading Page 1: [+] blk | hex data | binary | ascii [+] ----+----------+----------------------------------+------- [+] 00 | 000880E0 | 00000000000010001000000011100000 | .... - [+] 01 | E0150A48 | 11100000000101010000101001001000 | ...H - [+] 02 | 2D782308 | 00101101011110000010001100001000 | -x#. - [+] 03 | FFFFFFFF | 11111111111111111111111111111111 | .... + [+] 01 | 00000000 | 00000000000000000000000000000000 | .... + [+] 02 | 00000000 | 00000000000000000000000000000000 | .... + [+] 03 | 00000000 | 00000000000000000000000000000000 | .... ``` ***Important : If block 0 and block 7 don’t match exactly, do not continue.*** @@ -358,7 +361,7 @@ required, please do not proceed. ![](./t55xx_block0.png) We will cover other things in the configuration later. But the key - note here is we ONLY want to change bit 28 and nothing else. + note here, is we ONLY want to change bit 28 and nothing else. Current Block 0 : ***00088040*** New Block 0 : ***00088050*** @@ -366,7 +369,7 @@ required, please do not proceed. To understand what happened to get from 00088040 to 00088050 we need to look at the binary data. - While this can be confusing it is important to understand this as we + While this can be confusing, it is important to understand this as we do more advanced things. Bit Location (28) @@ -380,7 +383,7 @@ required, please do not proceed. - See how in the above we change the bit in location 28 from a 0 to 1 + See how in the above we changed the bit in location 28 from a 0 to 1 0 = No Password, 1 = Use Password Note how we did NOT change any other part of the configuration, only bit 28. @@ -415,22 +418,22 @@ required, please do not proceed. card. Lets try again, but this time supply the password. We use the option - p followed by the password. + -p followed by the password. ``` [usb] pm3 --> lf t55 detect -p 12345678 ``` result: ``` - [=] Chip type......... T55x7 - [=] Modulation........ ASK - [=] Bit rate.......... 2 - RF/32 - [=] Inverted.......... No - [=] Offset............ 33 - [=] Seq. terminator... Yes - [=] Block0............ 00088050 (auto detect) + [=] Chip type......... T55x7 + [=] Modulation........ ASK + [=] Bit rate.......... 2 - RF/32 + [=] Inverted.......... No + [=] Offset............ 33 + [=] Seq. terminator... Yes + [=] Block0............ 00088050 (auto detect) [=] Downlink mode..... default/fixed bit length [=] Password set...... Yes - [=] Password.......... 00000000 + [=] Password.......... 12345678 ``` 7) Write a block of data with a password @@ -460,13 +463,12 @@ required, please do not proceed. [+] blk | hex data | binary | ascii [+] ----+----------+----------------------------------+------- [!] Safety check: Could not detect if PWD bit is set in config block. Exits. - [?] Consider using the override parameter to force read. ``` Note that the proxmark3 did not read the block, the safty kicked in - and wants us to confirm by supply the override option ‘o’. + and wants us to confirm by supply the override option ‘-o’. - Lets try again with the ‘o’ option as we know the password is set. + Lets try again with the ‘-o’ option as we know the password is set. ``` [usb] pm3 --> lf t55xx read -b 1 -p 12345678 -o ``` @@ -487,7 +489,7 @@ required, please do not proceed. this from above. Remember if we don’t know the config and write this config to the - card, it will over write all other settings. This can recoved the + card, it will overwrite all other settings. This can recover the card, but will lose any settings you may want. So it’s a good idea to read the config, and set bit 28 to 0, rather than just overwrite the config and change the way the card works. @@ -516,7 +518,7 @@ required, please do not proceed. [=] Downlink mode..... default/fixed bit length [=] Password set...... No ``` - Yes we can and we can see Block 0 is the correct config 00088040 + Yes we can! We can see Block 0 is the correct config 00088040 # Part 2 – Configuration Blocks @@ -532,7 +534,7 @@ from Block 0 in Page 0. It will use this in both default read mode (where is sends out the blocks from 1 to x on power up), as well as when it responds to commands. -In the Read To Card, the T5577 will encode the data using the settings +In the Reader To Card, the T5577 will encode the data using the settings from Block 3 Page 1. If the command is not encoded correctly it will ignore the command and revert back to default read mode. @@ -542,10 +544,10 @@ 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 an EM4100, then we need to choose the settings that work like the EM4100; same goes for others like HID. I am not going to cover these -here, rather use an example. Others have collect these and posted on the -forum. +here, rather use an example. Others have collected these and posted on the +forum or can be found by searching the web. -To get started lets look back at the tech sheet. +To get started lets look back at the data sheet. ![](./t55xx_clock0_cfg.png) @@ -584,12 +586,11 @@ password set (if not, review and get you card back to this state). ``` result: ``` - [+] Preparing to clone EM4102 to T55x7 tag with ID 0F0368568B (RF/64) - [#] Clock rate: 64 - [#] Tag T55x7 written with 0xff83c03322a646e4 - - [+] Done - [?] Hint: try `lf em 410x reader` to verify + [+] Preparing to clone EM4102 to T55x7 tag with ID 1122334455 (RF/64) + [#] Clock rate: 64 + [#] Tag T55x7 written with 0xff8c65298c94a940 + + [+] Done ``` 2) Check this has work. @@ -632,7 +633,7 @@ password set (if not, review and get you card back to this state). ``` Looks good. -3) Now lest see what the T5577 detect and info shows +3) Now lets see what the T5577 detect and info shows ``` [usb] pm3 --> lf t55 detect ``` From a8f74b54ea608048a7eba25db5abb5cabf47cb31 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 9 Mar 2021 12:32:59 +0100 Subject: [PATCH 32/67] typos --- doc/T5577_Guide.md | 6 +++--- doc/jtag_notes.md | 2 +- doc/path_notes.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/T5577_Guide.md b/doc/T5577_Guide.md index 6cc0a96b9..61d926b22 100644 --- a/doc/T5577_Guide.md +++ b/doc/T5577_Guide.md @@ -78,7 +78,7 @@ examples shown, it will be assumed you have run the detect command. ``` [usb] pm3 --> lf t55xx detect ``` -You should see a results simular to the following: +You should see a results similar to the following: ``` [=] Chip type......... T55x7 [=] Modulation........ ASK @@ -256,7 +256,7 @@ result: Practice reading and writing to blocks 1 to 6 until you are happy you can do it and get the results you wanted (i.e. the data you want stored is written to the block you want it stored in). I recommend staying -away from block 7 as this is where the password is stored, if uesed. +away from block 7 as this is where the password is stored, if used. If you forget this data/password, you wont be able to read or write to the card. @@ -465,7 +465,7 @@ required, please do not proceed. [!] Safety check: Could not detect if PWD bit is set in config block. Exits. ``` - Note that the proxmark3 did not read the block, the safty kicked in + Note that the proxmark3 did not read the block, the safety kicked in and wants us to confirm by supply the override option ‘-o’. Lets try again with the ‘-o’ option as we know the password is set. diff --git a/doc/jtag_notes.md b/doc/jtag_notes.md index 9029958e6..1e6369767 100644 --- a/doc/jtag_notes.md +++ b/doc/jtag_notes.md @@ -61,7 +61,7 @@ GND | 6 3.3 | 1 # Where to find more information? -There has been lots of articles and blogposts about recoving, debricking, JTAG your Proxmark3 and you find here below a sortiment of resources that will be of help. +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 diff --git a/doc/path_notes.md b/doc/path_notes.md index 76c3f7a1a..491f01cd0 100644 --- a/doc/path_notes.md +++ b/doc/path_notes.md @@ -65,7 +65,7 @@ Dictionaries used by the client will be copied to ``` Here you find the default dictionaries used for commands like `hf mf chk`, `hf mf fchk`, `lf t55xx chk` -A dictionary file is a text based file with one key per line in hexdecimal form. +A dictionary file is a text based file with one key per line in hexadecimal form. The length of the key is decided by the Proxmark3 client for the different commands. All chars afterwards on line is ignored. if key isn't a hex number, the key is ignored. From ad2b0879fce67e83632f82716184c66c60f8f4eb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 14:38:31 +0100 Subject: [PATCH 33/67] added: mem spiffs view - to view a file on SPIFFS\n mem spiffs dump - now uses cliparser and NG --- armsrc/Standalone/hf_legic.c | 2 +- armsrc/Standalone/lf_icehid.c | 2 +- armsrc/Standalone/lf_tharexde.c | 10 +- armsrc/appmain.c | 68 ++-- client/luascripts/mem_spiffs_readpwd.lua | 2 +- client/src/cmdflashmemspiffs.c | 429 +++++++++++------------ client/src/cmdflashmemspiffs.h | 2 +- client/src/cmdlfem4x50.c | 2 +- client/src/comms.c | 3 + client/src/mifare/mifarehost.c | 2 +- include/pm3_cmd.h | 11 + 11 files changed, 263 insertions(+), 270 deletions(-) diff --git a/armsrc/Standalone/hf_legic.c b/armsrc/Standalone/hf_legic.c index 6ebe6eff6..0b4d0e2ae 100644 --- a/armsrc/Standalone/hf_legic.c +++ b/armsrc/Standalone/hf_legic.c @@ -39,7 +39,7 @@ * * To delete a dump file from flash: * - * 1. mem spiffs remove hf-legic-XXYYZZWW-dump.bin + * 1. mem spiffs remove -f hf-legic-XXYYZZWW-dump.bin * */ diff --git a/armsrc/Standalone/lf_icehid.c b/armsrc/Standalone/lf_icehid.c index d125b0c03..9164e182e 100644 --- a/armsrc/Standalone/lf_icehid.c +++ b/armsrc/Standalone/lf_icehid.c @@ -48,7 +48,7 @@ * * To delete the log file from flash: * - * 1. mem spiffs remove lf_hidcollect.log + * 1. mem spiffs remove -f lf_hidcollect.log */ #define LF_HIDCOLLECT_LOGFILE "lf_hidcollect.log" diff --git a/armsrc/Standalone/lf_tharexde.c b/armsrc/Standalone/lf_tharexde.c index 2a7a686fb..713e27d84 100644 --- a/armsrc/Standalone/lf_tharexde.c +++ b/armsrc/Standalone/lf_tharexde.c @@ -42,7 +42,7 @@ * - LED D: unmounting/sync'ing flash (normally < 100ms) * * To upload input file (eml format) to flash: - * - mem spiffs load f o lf_em4x50_simulate.eml + * - mem spiffs upload -s -d lf_em4x50_simulate.eml * * To retrieve password file from flash: * - mem spiffs dump o lf_em4x50_passwords.log f @@ -54,13 +54,13 @@ * the lab connected to PM3 client before taking it into the field. * * To delete the input file from flash: - * - mem spiffs remove lf_em4x50_simulate.eml + * - mem spiffs remove -f lf_em4x50_simulate.eml * * To delete the log file from flash: - * - mem spiffs remove lf_em4x50_passwords.log + * - mem spiffs remove -f lf_em4x50_passwords.log * * To delete the log file from flash: - * - mem spiffs remove lf_em4x50_collect.log + * - mem spiffs remove -f lf_em4x50_collect.log */ #define STATE_SIM 0 @@ -77,7 +77,7 @@ static void LoadDataInstructions(const char *inputfile) { Dbprintf("To load datafile to flash and display it:"); Dbprintf("1. edit input file %s", inputfile); Dbprintf("2. start proxmark3 client"); - Dbprintf("3. mem spiffs load f o %s", inputfile); + Dbprintf("3. mem spiffs upload -f o %s", inputfile); Dbprintf("4. start standalone mode"); } diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 22190ef1a..77af73cb2 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -2078,7 +2078,7 @@ static void PacketReceived(PacketCommandNG *packet) { Dbprintf("transfer to client failed :: | bytes between %d - %d (%d) | result: %d", i, i + len, len, result); } // Trigger a finish downloading signal with an ACK frame - reply_mix(CMD_ACK, 1, 0, 0, 0, 0); + reply_ng(CMD_SPIFFS_DOWNLOAD, PM3_SUCCESS, NULL, 0); LED_B_OFF(); break; } @@ -2087,11 +2087,17 @@ static void PacketReceived(PacketCommandNG *packet) { uint8_t filename[32]; uint8_t *pfilename = packet->data.asBytes; memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN); - if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Filename received for spiffs STAT : %s", filename); + if (DBGLEVEL >= DBG_DEBUG) { + Dbprintf("Filename received for spiffs STAT : %s", filename); + } + int changed = rdv40_spiffs_lazy_mount(); uint32_t size = size_in_spiffs((char *)filename); - if (changed) rdv40_spiffs_lazy_unmount(); - reply_mix(CMD_ACK, size, 0, 0, 0, 0); + if (changed) { + rdv40_spiffs_lazy_unmount(); + } + + reply_ng(CMD_SPIFFS_STAT, PM3_SUCCESS, (uint8_t *)&size, sizeof(uint32_t)); LED_B_OFF(); break; } @@ -2121,12 +2127,12 @@ static void PacketReceived(PacketCommandNG *packet) { uint8_t dlen; uint8_t dest[32]; } PACKED; - struct p *payload = (struct p *) packet->data.asBytes; if (DBGLEVEL >= DBG_DEBUG) { - Dbprintf("Filename received as source for spiffs RENAME : %s", payload->src); - Dbprintf("Filename received as destination for spiffs RENAME : %s", payload->dest); + Dbprintf("SPIFFS RENAME"); + Dbprintf("Source........ %s", payload->src); + Dbprintf("Destination... %s", payload->dest); } rdv40_spiffs_rename((char *)payload->src, (char *)payload->dest, RDV40_SPIFFS_SAFETY_SAFE); reply_ng(CMD_SPIFFS_RENAME, PM3_SUCCESS, NULL, 0); @@ -2135,40 +2141,40 @@ static void PacketReceived(PacketCommandNG *packet) { } case CMD_SPIFFS_COPY: { LED_B_ON(); - uint8_t src[32]; - uint8_t dest[32]; - uint8_t *pfilename = packet->data.asBytes; - char *token; - token = strtok((char *)pfilename, ","); - strncpy((char *)src, token, sizeof(src) - 1); - token = strtok(NULL, ","); - strncpy((char *)dest, token, sizeof(dest) - 1); + struct p { + uint8_t slen; + uint8_t src[32]; + uint8_t dlen; + uint8_t dest[32]; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + if (DBGLEVEL >= DBG_DEBUG) { - Dbprintf("Filename received as source for spiffs COPY : %s", src); - Dbprintf("Filename received as destination for spiffs COPY : %s", dest); + Dbprintf("SPIFFS COPY"); + Dbprintf("Source........ %s", payload->src); + Dbprintf("Destination... %s", payload->dest); } - rdv40_spiffs_copy((char *) src, (char *)dest, RDV40_SPIFFS_SAFETY_SAFE); + rdv40_spiffs_copy((char *)payload->src, (char *)payload->dest, RDV40_SPIFFS_SAFETY_SAFE); + reply_ng(CMD_SPIFFS_COPY, PM3_SUCCESS, NULL, 0); LED_B_OFF(); break; } case CMD_SPIFFS_WRITE: { LED_B_ON(); - uint8_t filename[32]; - uint32_t append = packet->oldarg[0]; - uint32_t size = packet->oldarg[1]; - uint8_t *data = packet->data.asBytes; - uint8_t *pfilename = packet->data.asBytes; - memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN); - data += SPIFFS_OBJ_NAME_LEN; - if (DBGLEVEL >= DBG_DEBUG) Dbprintf("> Filename received for spiffs WRITE : %s with APPEND SET TO : %d", filename, append); + flashmem_write_t *payload = (flashmem_write_t *)packet->data.asBytes; - if (!append) { - rdv40_spiffs_write((char *) filename, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE); - } else { - rdv40_spiffs_append((char *) filename, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE); + if (DBGLEVEL >= DBG_DEBUG) { + Dbprintf("SPIFFS WRITE, dest `%s` with APPEND set to: %c", payload->fn, payload->append ? 'Y' : 'N'); } - reply_mix(CMD_ACK, 1, 0, 0, 0, 0); + + if (payload->append) { + rdv40_spiffs_append((char *) payload->fn, payload->data, payload->bytes_in_packet, RDV40_SPIFFS_SAFETY_SAFE); + } else { + rdv40_spiffs_write((char *) payload->fn, payload->data, payload->bytes_in_packet, RDV40_SPIFFS_SAFETY_SAFE); + } + + reply_ng(CMD_SPIFFS_WRITE, PM3_SUCCESS, NULL, 0); LED_B_OFF(); break; } diff --git a/client/luascripts/mem_spiffs_readpwd.lua b/client/luascripts/mem_spiffs_readpwd.lua index b4995e406..ef529440c 100644 --- a/client/luascripts/mem_spiffs_readpwd.lua +++ b/client/luascripts/mem_spiffs_readpwd.lua @@ -76,7 +76,7 @@ local function main(args) if removeflag then print('Deleting file '..filename.. ' from SPIFFS if exists') - core.console("mem spiffs remove " ..filename) + core.console("mem spiffs remove -f " ..filename) return end diff --git a/client/src/cmdflashmemspiffs.c b/client/src/cmdflashmemspiffs.c index f0877ab0d..1a372bb60 100644 --- a/client/src/cmdflashmemspiffs.c +++ b/client/src/cmdflashmemspiffs.c @@ -17,55 +17,7 @@ static int CmdHelp(const char *Cmd); -static int usage_flashmemspiffs_copy(void) { - PrintAndLogEx(NORMAL, "Copy a file to another (destructively) in spiffs filesystem\n"); - PrintAndLogEx(NORMAL, "Usage: mem spiffs copy "); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs copy lasttag.bin lasttag_cpy.bin")); - return PM3_SUCCESS; -} - -static int usage_flashmemspiffs_dump(void) { - PrintAndLogEx(NORMAL, "Dumps flash memory on device into a file or in console"); - PrintAndLogEx(NORMAL, "Size is handled by first sending a STAT command against file existence\n"); - PrintAndLogEx(NORMAL, "Usage: mem spiffs dump o [f [e]] [p]"); - PrintAndLogEx(NORMAL, " o - filename in SPIFFS"); - PrintAndLogEx(NORMAL, " f - file name to save to "); - PrintAndLogEx(NORMAL, " p - print dump in console"); - PrintAndLogEx(NORMAL, " e - also save in EML format (good for tags save and dictonnary files)"); - PrintAndLogEx(NORMAL, " You must specify at lease option f or option p, both if you wish"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs dump o lasttag.bin f lasttag e")); - PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs dump o lasttag.bin p")); - return PM3_SUCCESS; -} - -static int usage_flashmemspiffs_load(void) { - PrintAndLogEx(NORMAL, "Uploads binary-wise file into device filesystem"); - PrintAndLogEx(NORMAL, "Warning: mem area to be written must have been wiped first"); - PrintAndLogEx(NORMAL, "(this is already taken care when loading dictionaries)\n"); - PrintAndLogEx(NORMAL, "Usage: mem spiffs load o f "); - PrintAndLogEx(NORMAL, " o - destination filename"); - PrintAndLogEx(NORMAL, " f - local filename"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs load f myfile o myapp.conf")); - return PM3_SUCCESS; -} - -static int usage_flashmemspiffs_wipe(void) { - PrintAndLogEx(NORMAL, "wipes all files on the device filesystem " _RED_("* Warning *")); - PrintAndLogEx(NORMAL, "Usage: mem spiffs wipe [h]"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" mem spiffs wipe")); - return PM3_SUCCESS; -} - - -int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) { +int flashmem_spiffs_load(char *destfn, uint8_t *data, size_t datalen) { int ret_val = PM3_SUCCESS; @@ -76,33 +28,35 @@ int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) { // Send to device uint32_t bytes_sent = 0; uint32_t bytes_remaining = datalen; - uint32_t append = 0; // fast push mode conn.block_after_ACK = true; while (bytes_remaining > 0) { + uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); + flashmem_write_t *payload = calloc(1, sizeof(flashmem_write_t) + bytes_in_packet); + + payload->append = (bytes_sent > 0); + payload->fnlen = strlen(destfn); + memcpy(payload->fn, destfn, strlen(destfn)); + + payload->bytes_in_packet = bytes_in_packet; + memset(payload->data, 0, bytes_in_packet); + memcpy(payload->data, data + bytes_sent, bytes_in_packet); + + PacketResponseNG resp; clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_WRITE, (uint8_t *)payload, sizeof(flashmem_write_t) + bytes_in_packet); - char fdata[32 + bytes_in_packet]; - memset(fdata, 0, sizeof(fdata)); - memcpy(fdata, destfn, 32); - memcpy(fdata + 32, data + bytes_sent, bytes_in_packet); - - if (bytes_sent > 0) - append = 1; - - SendCommandOLD(CMD_SPIFFS_WRITE, append, bytes_in_packet, 0, fdata, 32 + bytes_in_packet); + free(payload); bytes_remaining -= bytes_in_packet; bytes_sent += bytes_in_packet; - PacketResponseNG resp; - uint8_t retry = 3; - while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + while (WaitForResponseTimeout(CMD_SPIFFS_WRITE, &resp, 2000) == false) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); retry--; if (retry == 0) { @@ -110,13 +64,6 @@ int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) { goto out; } } - - uint8_t isok = resp.oldarg[0] & 0xFF; - if (!isok) { - PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent); - ret_val = PM3_EFLASH; - break; - } } out: @@ -128,7 +75,6 @@ out: // We want to unmount after these to set things back to normal but more than this // unmouting ensure that SPIFFS CACHES are all flushed so our file is actually written on memory SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0); - return ret_val; } @@ -321,246 +267,273 @@ static int CmdFlashMemSpiFFSRename(const char *Cmd) { } static int CmdFlashMemSpiFFSCopy(const char *Cmd) { - int len = strlen(Cmd); - if (len < 1) { - return usage_flashmemspiffs_copy(); - } - char ctmp = tolower(param_getchar(Cmd, 0)); - if (len == 1 && ctmp == 'h') { - return usage_flashmemspiffs_copy(); - } + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs copy", + "Copy a file to another (destructively) in SPIFFS file system", + "mem spiffs copy -s aaa.bin -d aaa_cpy.bin" + ); + void *argtable[] = { + arg_param_begin, + arg_str1("s", "src", "", "source file name"), + arg_str1("d", "dest", "", "destination file name"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); - char srcfilename[32] = {0}; - char destfilename[32] = {0}; - bool errors = false; + int slen = 0; + char src[32] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, 32, &slen); - if (param_getstr(Cmd, 0, srcfilename, 32) >= 32) { - PrintAndLogEx(FAILED, "Source Filename too long"); - errors = true; - } - if (srcfilename[0] == '\0') { - PrintAndLogEx(FAILED, "Source Filename missing or invalid"); - errors = true; - } + int dlen = 0; + char dest[32] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, 32, &dlen); + CLIParserFree(ctx); - if (param_getstr(Cmd, 1, destfilename, 32) >= 32) { - PrintAndLogEx(FAILED, "Source Filename too long"); - errors = true; - } - if (destfilename[0] == '\0') { - PrintAndLogEx(FAILED, "Source Filename missing or invalid"); - errors = true; - } + struct { + uint8_t slen; + uint8_t src[32]; + uint8_t dlen; + uint8_t dest[32]; + } PACKED payload; + payload.slen = slen; + payload.dlen = dlen; - // check null filename ? - if (errors) { - usage_flashmemspiffs_copy(); - return PM3_EINVARG; - } + memcpy(payload.src, src, slen); + memcpy(payload.dest, dest, dlen); - char data[65]; - sprintf(data, "%s,%s", srcfilename, destfilename); - SendCommandMIX(CMD_SPIFFS_COPY, 0, 0, 0, (uint8_t *)data, 65); + PacketResponseNG resp; + clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_COPY, (uint8_t *)&payload, sizeof(payload)); + WaitForResponse(CMD_SPIFFS_COPY, &resp); + if (resp.status == PM3_SUCCESS) + PrintAndLogEx(INFO, "Done!"); + + PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify"); return PM3_SUCCESS; } static int CmdFlashMemSpiFFSDump(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs dump", + "Dumps device SPIFFS file to a local file\n" + "Size is handled by first sending a STAT command against file to verify existence", + "mem spiffs dump -s tag.bin --> download binary file from device\n" + "mem spiffs dump -s tag.bin -d aaa -e --> download tag.bin, save as aaa.eml format" + ); - char filename[FILE_PATH_SIZE] = {0}; - uint8_t cmdp = 0; - bool errors = false; - bool print = false; - uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE; - char destfilename[32] = {0}; - bool eml = false; + void *argtable[] = { + arg_param_begin, + arg_str1("s", "src", "", "SPIFFS file to save"), + arg_str0("d", "dest", "", "file name to save to "), + arg_lit0("e", "eml", "also save in EML format"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_flashmemspiffs_dump(); - /*case 'l': - len = param_get32ex(Cmd, cmdp + 1, FLASH_MEM_MAX_SIZE, 10); - cmdp += 2; - break;*/ - case 'o': - param_getstr(Cmd, cmdp + 1, destfilename, 32); - cmdp += 2; - break; - case 'p': - print = true; - cmdp += 1; - break; - case 'e': - eml = true; - cmdp += 1; - break; - case 'f': - // File handling - if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { - PrintAndLogEx(FAILED, "Filename too long"); - errors = true; - break; - } - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + int slen = 0; + char src[32] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, 32, &slen); - if ((filename[0] == '\0') && (!print)) { - PrintAndLogEx(FAILED, "No print asked and local dump filename missing or invalid"); - errors = true; - } + int dlen = 0; + char dest[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, FILE_PATH_SIZE, &dlen); - if (destfilename[0] == '\0') { - PrintAndLogEx(FAILED, "SPIFFS filename missing or invalid"); - errors = true; - } - - // Validations - if (errors || cmdp == 0) { - usage_flashmemspiffs_dump(); - return PM3_EINVARG; - } + bool eml = arg_get_lit(ctx, 3); + CLIParserFree(ctx); // get size from spiffs itself ! - SendCommandMIX(CMD_SPIFFS_STAT, 0, 0, 0, (uint8_t *)destfilename, 32); + clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_STAT, (uint8_t *)src, slen); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_SPIFFS_STAT, &resp, 2000) == false) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); return PM3_ETIMEOUT; } - len = resp.oldarg[0]; - + uint32_t len = resp.data.asDwords[0]; uint8_t *dump = calloc(len, sizeof(uint8_t)); if (!dump) { PrintAndLogEx(ERR, "error, cannot allocate memory "); return PM3_EMALLOC; } - PrintAndLogEx(INFO, "downloading "_YELLOW_("%u") " bytes from spiffs (flashmem)", len); - if (!GetFromDevice(SPIFFS, dump, len, start_index, (uint8_t *)destfilename, 32, NULL, -1, true)) { - PrintAndLogEx(FAILED, "ERROR; downloading from spiffs(flashmemory)"); + // download from device + uint32_t start_index = 0; + PrintAndLogEx(INFO, "downloading "_YELLOW_("%u") " bytes from `" _YELLOW_("%s") "` (spiffs)", len, src); + if (!GetFromDevice(SPIFFS, dump, len, start_index, (uint8_t *)src, slen, NULL, -1, true)) { + PrintAndLogEx(FAILED, "error, downloading from spiffs"); free(dump); return PM3_EFLASH; } - if (print) { - print_hex_break(dump, len, 32); + // save to file + char fn[FILE_PATH_SIZE] = {0}; + if (dlen == 0) { + strncpy(fn, src, slen); + } else { + strncpy(fn, dest, dlen); } - if (filename[0] != '\0') { - saveFile(filename, ".bin", dump, len); - if (eml) { - uint8_t eml_len = 16; + saveFile(fn, ".bin", dump, len); + if (eml) { + uint8_t eml_len = 16; + if (strstr(fn, "class") != NULL) + eml_len = 8; + else if (strstr(fn, "mfu") != NULL) + eml_len = 4; - if (strstr(filename, "class") != NULL) - eml_len = 8; - else if (strstr(filename, "mfu") != NULL) - eml_len = 4; - - saveFileEML(filename, dump, len, eml_len); - } + saveFileEML(fn, dump, len, eml_len); } - free(dump); return PM3_SUCCESS; } static int CmdFlashMemSpiFFSWipe(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs wipe", + _RED_("* * * Warning * * *") " \n" + _CYAN_("This command wipes all files on the device SPIFFS file system"), + "mem spiffs wipe"); - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') { - return usage_flashmemspiffs_wipe(); - } + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); - PrintAndLogEx(INFO, "Wiping all files from SPIFFS FileSystem"); + PrintAndLogEx(INFO, "Wiping all files from SPIFFS file system"); PacketResponseNG resp; clearCommandBuffer(); SendCommandNG(CMD_SPIFFS_WIPE, NULL, 0); WaitForResponse(CMD_SPIFFS_WIPE, &resp); - PrintAndLogEx(INFO, "Done!"); + if (resp.status == PM3_SUCCESS) + PrintAndLogEx(INFO, "Done!"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify"); return PM3_SUCCESS; } -static int CmdFlashMemSpiFFSLoad(const char *Cmd) { +static int CmdFlashMemSpiFFSUpload(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs upload", + "Uploads binary-wise file into device file system\n" + "Warning: mem area to be written must have been wiped first.\n" + "This is already taken care when loading dictionaries.\n" + "File names can only be 32 bytes long on device SPIFFS", + "mem spiffs upload -s local.bin -d dest.bin" + ); - char filename[FILE_PATH_SIZE] = {0}; - uint8_t destfilename[32] = {0}; - bool errors = false; - uint8_t cmdp = 0; + void *argtable[] = { + arg_param_begin, + arg_str1("s", "src", "", "source file name"), + arg_str1("d", "dest", "", "destination file name"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_flashmemspiffs_load(); - case 'f': - if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { - PrintAndLogEx(FAILED, "Filename too long"); - errors = true; - } - cmdp += 2; - break; - case 'o': - param_getstr(Cmd, cmdp + 1, (char *)destfilename, 32); - if (strlen((char *)destfilename) == 0) { - PrintAndLogEx(FAILED, "Destination Filename missing or invalid"); - errors = true; - } - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + int slen = 0; + char src[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, FILE_PATH_SIZE, &slen); - // Validations - if (errors || cmdp == 0) - return usage_flashmemspiffs_load(); + int dlen = 0; + char dest[32] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)dest, 32, &dlen); + CLIParserFree(ctx); + + PrintAndLogEx(DEBUG, "Upload `" _YELLOW_("%s") "` -> `" _YELLOW_("%s") "`", src, dest); size_t datalen = 0; uint8_t *data = NULL; - int res = loadFile_safe(filename, "", (void **)&data, &datalen); - // int res = loadFileEML( filename, data, &datalen); + int res = loadFile_safe(src, "", (void **)&data, &datalen); if (res != PM3_SUCCESS) { free(data); return PM3_EFILE; } - res = flashmem_spiffs_load(destfilename, data, datalen); - + res = flashmem_spiffs_load(dest, data, datalen); free(data); if (res == PM3_SUCCESS) - PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") " bytes to file "_GREEN_("%s"), datalen, destfilename); + PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") " bytes to file "_GREEN_("%s"), datalen, dest); + PrintAndLogEx(HINT, "Try `" _YELLOW_("mem spiffs tree") "` to verify"); return res; } +static int CmdFlashMemSpiFFSView(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "mem spiffs view", + "View a file on flash memory on devicer in console", + "mem spiffs view -f tag.bin" + ); + + void *argtable[] = { + arg_param_begin, + arg_str1("f", "file", "", "SPIFFS file to view"), + arg_int0("c", "cols", "", "column breaks (def 32)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int slen = 0; + char src[32] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)src, 32, &slen); + + int breaks = arg_get_int_def(ctx, 2, 32); + CLIParserFree(ctx); + + // get size from spiffs itself ! + clearCommandBuffer(); + SendCommandNG(CMD_SPIFFS_STAT, (uint8_t *)src, slen); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_SPIFFS_STAT, &resp, 2000) == false) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + return PM3_ETIMEOUT; + } + + uint32_t len = resp.data.asDwords[0]; + uint8_t *dump = calloc(len, sizeof(uint8_t)); + if (!dump) { + PrintAndLogEx(ERR, "error, cannot allocate memory "); + return PM3_EMALLOC; + } + + uint32_t start_index = 0; + PrintAndLogEx(INFO, "downloading "_YELLOW_("%u") " bytes from `" _YELLOW_("%s") "` (spiffs)", len, src); + + if (!GetFromDevice(SPIFFS, dump, len, start_index, (uint8_t *)src, slen, NULL, -1, true)) { + PrintAndLogEx(FAILED, "error, downloading from spiffs"); + free(dump); + return PM3_EFLASH; + } + + PrintAndLogEx(NORMAL, ""); + print_hex_break(dump, len, breaks); + PrintAndLogEx(NORMAL, ""); + free(dump); + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"copy", CmdFlashMemSpiFFSCopy, IfPm3Flash, "Copy a file to another (destructively) in SPIFFS file system"}, {"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented file system"}, {"dump", CmdFlashMemSpiFFSDump, IfPm3Flash, "Dump a file from SPIFFS file system"}, {"info", CmdFlashMemSpiFFSInfo, IfPm3Flash, "Print file system info and usage statistics"}, - {"load", CmdFlashMemSpiFFSLoad, IfPm3Flash, "Upload file into SPIFFS file system"}, {"mount", CmdFlashMemSpiFFSMount, IfPm3Flash, "Mount the SPIFFS file system if not already mounted"}, {"remove", CmdFlashMemSpiFFSRemove, IfPm3Flash, "Remove a file from SPIFFS file system"}, {"rename", CmdFlashMemSpiFFSRename, IfPm3Flash, "Rename/move a file in SPIFFS file system"}, {"test", CmdFlashMemSpiFFSTest, IfPm3Flash, "Test SPIFFS Operations"}, {"tree", CmdFlashMemSpiFFSTree, IfPm3Flash, "Print the Flash memory file system tree"}, {"unmount", CmdFlashMemSpiFFSUnmount, IfPm3Flash, "Un-mount the SPIFFS file system"}, - {"wipe", CmdFlashMemSpiFFSWipe, IfPm3Flash, "Wipe all files from SPIFFS file system. * " _RED_("dangerous") " *" }, + {"upload", CmdFlashMemSpiFFSUpload, IfPm3Flash, "Upload file into SPIFFS file system"}, + {"view", CmdFlashMemSpiFFSView, IfPm3Flash, "View file on SPIFFS file system"}, + {"wipe", CmdFlashMemSpiFFSWipe, IfPm3Flash, "Wipe all files from SPIFFS file system * " _RED_("dangerous") " *" }, {NULL, NULL, NULL, NULL} }; diff --git a/client/src/cmdflashmemspiffs.h b/client/src/cmdflashmemspiffs.h index 9324a541b..385d78401 100644 --- a/client/src/cmdflashmemspiffs.h +++ b/client/src/cmdflashmemspiffs.h @@ -14,6 +14,6 @@ #include "common.h" int CmdFlashMemSpiFFS(const char *Cmd); -int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen); +int flashmem_spiffs_load(char *destfn, uint8_t *data, size_t datalen); #endif diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index ea60c84b9..fc4f75e5b 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -471,7 +471,7 @@ int CmdEM4x50Chk(const char *Cmd) { // upload to flash. datalen = MIN(bytes_remaining, keyblock); - res = flashmem_spiffs_load(destfn, keys, datalen); + res = flashmem_spiffs_load((char*)destfn, keys, datalen); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, "SPIFFS upload failed"); return res; diff --git a/client/src/comms.c b/client/src/comms.c index 57a03afe7..26c68d889 100644 --- a/client/src/comms.c +++ b/client/src/comms.c @@ -839,6 +839,9 @@ static bool dl_it(uint8_t *dest, uint32_t bytes, PacketResponseNG *response, siz if (response->cmd == CMD_ACK) return true; + // Spiffs download is converted to NG, + if (response->cmd == CMD_SPIFFS_DOWNLOAD) + return true; // sample_buf is a array pointer, located in data.c // arg0 = offset in transfer. Startindex of this chunk diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index c6e02013e..4a34421ba 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -695,7 +695,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl mem[4] = (chunk & 0xFF); // upload to flash. - res = flashmem_spiffs_load(destfn, mem, 5 + (chunk * 6)); + res = flashmem_spiffs_load((char*)destfn, mem, 5 + (chunk * 6)); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, "\nSPIFFS upload failed"); free(mem); diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 6b7f5df07..a2193a85b 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -384,6 +384,15 @@ typedef struct { bool off; } PACKED tearoff_params_t; +// when writing to SPIFFS +typedef struct { + bool append : 1; + uint16_t bytes_in_packet : 15; + uint8_t fnlen; + uint8_t fn[32]; + uint8_t data[]; +} PACKED flashmem_write_t; + // For the bootloader #define CMD_DEVICE_INFO 0x0000 //#define CMD_SETUP_WRITE 0x0001 @@ -565,6 +574,8 @@ typedef struct { #define CMD_LF_HITAGS_READ 0x0373 #define CMD_LF_HITAGS_WRITE 0x0375 +#define CMD_LF_HITAG_ELOAD 0x0376 + #define CMD_HF_ISO14443A_ANTIFUZZ 0x0380 #define CMD_HF_ISO14443B_SIMULATE 0x0381 #define CMD_HF_ISO14443B_SNIFF 0x0382 From af6289c99a12cdd97ef7eee9040f4c1ad7fbb6a9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 14:38:53 +0100 Subject: [PATCH 34/67] text --- client/src/util.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/src/util.c b/client/src/util.c index 53825f28b..6519fec36 100644 --- a/client/src/util.c +++ b/client/src/util.c @@ -186,7 +186,7 @@ void print_hex_break(const uint8_t *data, const size_t len, uint8_t breaks) { if (data == NULL || len == 0) return; int rownum = 0; - PrintAndLogEx(NORMAL, "[%02d] | " NOLF, rownum); + PrintAndLogEx(INFO, "%02d | " NOLF, rownum); for (size_t i = 0; i < len; ++i) { PrintAndLogEx(NORMAL, "%02X " NOLF, data[i]); @@ -194,7 +194,8 @@ void print_hex_break(const uint8_t *data, const size_t len, uint8_t breaks) { // check if a line break is needed if (breaks > 0 && !((i + 1) % breaks) && (i + 1 < len)) { ++rownum; - PrintAndLogEx(NORMAL, "\n[%02d] | " NOLF, rownum); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "%02d | " NOLF, rownum); } } PrintAndLogEx(NORMAL, ""); From 8c16c4d95d78db80c87fd10ab55c4c697d522b77 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 14:58:08 +0100 Subject: [PATCH 35/67] text --- armsrc/Standalone/hf_14asniff.c | 8 ++++---- armsrc/Standalone/hf_iceclass.c | 8 ++++---- armsrc/Standalone/hf_legic.c | 2 +- armsrc/Standalone/lf_icehid.c | 4 ++-- armsrc/Standalone/lf_tharexde.c | 8 ++++---- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/armsrc/Standalone/hf_14asniff.c b/armsrc/Standalone/hf_14asniff.c index c52928825..0a6b48b48 100644 --- a/armsrc/Standalone/hf_14asniff.c +++ b/armsrc/Standalone/hf_14asniff.c @@ -71,13 +71,13 @@ static void DownloadTraceInstructions(void) { Dbprintf(""); Dbprintf("To get the trace from flash and display it:"); - Dbprintf("1. mem spiffs dump o "HF_14ASNIFF_LOGFILE" f trace.trc"); - Dbprintf("2. trace load trace.trc"); - Dbprintf("3. trace list 14a 1"); + Dbprintf("1. mem spiffs dump -s "HF_14ASNIFF_LOGFILE" -d trace.trc"); + Dbprintf("2. trace load -f trace.trc"); + Dbprintf("3. trace list -t 14a -1"); } void ModInfo(void) { - DbpString("hf_14asniff: standalone 'hf 14a sniff', storing in flashmem"); + DbpString(" ISO14443a sniff, storing in flashmem"); DownloadTraceInstructions(); } diff --git a/armsrc/Standalone/hf_iceclass.c b/armsrc/Standalone/hf_iceclass.c index 27e1bf5ab..bbebcab6e 100644 --- a/armsrc/Standalone/hf_iceclass.c +++ b/armsrc/Standalone/hf_iceclass.c @@ -130,27 +130,27 @@ static void download_instructions(uint8_t t) { switch (t) { case ICE_STATE_FULLSIM: { DbpString("The emulator memory was saved to SPIFFS"); - DbpString("1. " _YELLOW_("mem spiffs dump o " HF_ICLASS_FULLSIM_MOD_BIN " f " HF_ICLASS_FULLSIM_MOD" e")); + DbpString("1. " _YELLOW_("mem spiffs dump -s " HF_ICLASS_FULLSIM_MOD_BIN " -d " HF_ICLASS_FULLSIM_MOD" -e")); DbpString("2. " _YELLOW_("hf iclass view -f " HF_ICLASS_FULLSIM_MOD_BIN)); break; } case ICE_STATE_ATTACK: { DbpString("The collected data was saved to SPIFFS. The file names below may differ"); DbpString("1. " _YELLOW_("mem spiffs tree")); - DbpString("2. " _YELLOW_("mem spiffs dump o " HF_ICLASS_ATTACK_BIN " f " HF_ICLASS_ATTACK_BIN)); + DbpString("2. " _YELLOW_("mem spiffs dump -s " HF_ICLASS_ATTACK_BIN " -d " HF_ICLASS_ATTACK_BIN)); DbpString("3. " _YELLOW_("hf iclass loclass -f " HF_ICLASS_ATTACK_BIN)); break; } case ICE_STATE_READER: { DbpString("The found tags was saved to SPIFFS"); DbpString("1. " _YELLOW_("mem spiffs tree")); - DbpString("2. " _YELLOW_("mem spiffs dump h")); + DbpString("2. " _YELLOW_("mem spiffs dump -h")); break; } case ICE_STATE_DUMP_SIM: { DbpString("The found tag will be dumped to " HF_ICALSSS_READSIM_TEMP_BIN); DbpString("1. " _YELLOW_("mem spiffs tree")); - DbpString("2. " _YELLOW_("mem spiffs dump h")); + DbpString("2. " _YELLOW_("mem spiffs dump -h")); break; } } diff --git a/armsrc/Standalone/hf_legic.c b/armsrc/Standalone/hf_legic.c index 0b4d0e2ae..40174ce87 100644 --- a/armsrc/Standalone/hf_legic.c +++ b/armsrc/Standalone/hf_legic.c @@ -50,7 +50,7 @@ static void DownloadLogInstructions(void) { Dbprintf("[=] " _YELLOW_("-") " mem spiffs tree"); Dbprintf(""); Dbprintf("[=] To save a dump file from flash to client:"); - Dbprintf("[=] " _YELLOW_("-") " mem spiffs dump o hf-legic-UID-dump.bin f hf-legic-UID-dump.bin"); + Dbprintf("[=] " _YELLOW_("-") " mem spiffs dump -s hf-legic-UID-dump.bin -d hf-legic-UID-dump.bin"); } #endif diff --git a/armsrc/Standalone/lf_icehid.c b/armsrc/Standalone/lf_icehid.c index 9164e182e..0b1e6cbfe 100644 --- a/armsrc/Standalone/lf_icehid.c +++ b/armsrc/Standalone/lf_icehid.c @@ -36,7 +36,7 @@ * * To retrieve log file from flash: * - * 1. mem spiffs dump o lf_hidcollect.log f lf_hidcollect.log + * 1. mem spiffs dump -s lf_hidcollect.log -d lf_hidcollect.log * Copies log file from flash to your client. * * 2. exit the Proxmark3 client @@ -57,7 +57,7 @@ static void DownloadLogInstructions(void) { Dbprintf(""); Dbprintf("[=] To get the logfile from flash and display it:"); - Dbprintf("[=] " _YELLOW_("1.") " mem spiffs dump o "LF_HIDCOLLECT_LOGFILE" f "LF_HIDCOLLECT_LOGFILE); + Dbprintf("[=] " _YELLOW_("1.") " mem spiffs dump -s "LF_HIDCOLLECT_LOGFILE" -d "LF_HIDCOLLECT_LOGFILE); Dbprintf("[=] " _YELLOW_("2.") " exit proxmark3 client"); Dbprintf("[=] " _YELLOW_("3.") " cat "LF_HIDCOLLECT_LOGFILE); } diff --git a/armsrc/Standalone/lf_tharexde.c b/armsrc/Standalone/lf_tharexde.c index 713e27d84..f06cd9b07 100644 --- a/armsrc/Standalone/lf_tharexde.c +++ b/armsrc/Standalone/lf_tharexde.c @@ -45,10 +45,10 @@ * - mem spiffs upload -s -d lf_em4x50_simulate.eml * * To retrieve password file from flash: - * - mem spiffs dump o lf_em4x50_passwords.log f + * - mem spiffs dump -s lf_em4x50_passwords.log * * To retrieve log file from flash: - * - mem spiffs dump o lf_em4x50_collect.log f + * - mem spiffs dump -s lf_em4x50_collect.log * * This module emits debug strings during normal operation -- so try it out in * the lab connected to PM3 client before taking it into the field. @@ -77,14 +77,14 @@ static void LoadDataInstructions(const char *inputfile) { Dbprintf("To load datafile to flash and display it:"); Dbprintf("1. edit input file %s", inputfile); Dbprintf("2. start proxmark3 client"); - Dbprintf("3. mem spiffs upload -f o %s", inputfile); + Dbprintf("3. mem spiffs upload -s -d %s", inputfile); Dbprintf("4. start standalone mode"); } static void DownloadLogInstructions(const char *logfile) { Dbprintf(""); Dbprintf("To get the logfile from flash and display it:"); - Dbprintf("1. mem spiffs dump o %s f ", logfile); + Dbprintf("1. mem spiffs dump -s %s", logfile); Dbprintf("2. exit proxmark3 client"); Dbprintf("3. cat "); } From fc81b41b90a4302fdcf6976d40a9db82bdeaf225 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 15:00:58 +0100 Subject: [PATCH 36/67] text --- doc/new_frame_format.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/new_frame_format.md b/doc/new_frame_format.md index 6075fb2c9..102ef9c18 100644 --- a/doc/new_frame_format.md +++ b/doc/new_frame_format.md @@ -373,9 +373,9 @@ It was needed to tune pm3 RX usart `maxtry` : time client/proxmark3 -p /dev/ttyUSB0 -b 115200 -c "lf read" 6.28s - time client/proxmark3 -p /dev/ttyACM0 -c "mem dump f foo_usb" + time client/proxmark3 -p /dev/ttyACM0 -c "mem dump -f foo_usb" 1.48s - time client/proxmark3 -p /dev/ttyUSB0 -b 115200 -c "mem dump f foo_fpc" + time client/proxmark3 -p /dev/ttyUSB0 -b 115200 -c "mem dump -f foo_fpc" 25.34s From 60df5c8a673c6c1c2ae493e25eed9355c6e6efd9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 15:01:30 +0100 Subject: [PATCH 37/67] text --- doc/cliparser_todo.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index f3cc3500c..91aa977be 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -89,8 +89,6 @@ lf em 4x05 lf em 4x50 lf em 4x70 lf hitag reader -lf hitag sim lf hitag writer lf hitag dump -lf hitag cc script run From ba79bb7b06e16a1ac8130956d7948f9e7d4981fb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 16:09:36 +0100 Subject: [PATCH 38/67] fix some missing command when printing helps/markdown --- client/src/cmdflashmem.c | 16 ++++++++-------- client/src/cmdflashmemspiffs.c | 2 +- client/src/cmdlfem.c | 8 ++++---- client/src/cmdmain.c | 4 ++-- client/src/preferences.c | 4 ++-- doc/cliparser_todo.txt | 2 +- doc/commands.md | 2 +- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/client/src/cmdflashmem.c b/client/src/cmdflashmem.c index 5bb3b8cd9..475272a20 100644 --- a/client/src/cmdflashmem.c +++ b/client/src/cmdflashmem.c @@ -146,7 +146,7 @@ static int rdv4_sign_write(uint8_t *signature, uint8_t slen){ return PM3_EFAILED; } -static int CmdFlashmemSpiBaudrate(const char *Cmd) { +static int CmdFlashmemSpiBaud(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "mem baudrate", @@ -605,13 +605,13 @@ static int CmdFlashMemInfo(const char *Cmd) { } static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"baudrate", CmdFlashmemSpiBaudrate, IfPm3Flash, "Set Flash memory Spi baudrate"}, - {"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "High level SPI FileSystem Flash manipulation"}, - {"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information"}, - {"load", CmdFlashMemLoad, IfPm3Flash, "Load data into flash memory"}, - {"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory"}, - {"wipe", CmdFlashMemWipe, IfPm3Flash, "Wipe data from flash memory"}, + {"spiffs", CmdFlashMemSpiFFS, IfPm3Flash, "{ SPI File system }"}, + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"baudrate", CmdFlashmemSpiBaud, IfPm3Flash, "Set Flash memory Spi baudrate"}, + {"dump", CmdFlashMemDump, IfPm3Flash, "Dump data from flash memory"}, + {"info", CmdFlashMemInfo, IfPm3Flash, "Flash memory information"}, + {"load", CmdFlashMemLoad, IfPm3Flash, "Load data to flash memory"}, + {"wipe", CmdFlashMemWipe, IfPm3Flash, "Wipe data from flash memory"}, {NULL, NULL, NULL, NULL} }; diff --git a/client/src/cmdflashmemspiffs.c b/client/src/cmdflashmemspiffs.c index 1a372bb60..6da30392e 100644 --- a/client/src/cmdflashmemspiffs.c +++ b/client/src/cmdflashmemspiffs.c @@ -520,7 +520,7 @@ static int CmdFlashMemSpiFFSView(const char *Cmd) { } static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"help", CmdHelp, AlwaysAvailable, "This help"}, {"copy", CmdFlashMemSpiFFSCopy, IfPm3Flash, "Copy a file to another (destructively) in SPIFFS file system"}, {"check", CmdFlashMemSpiFFSCheck, IfPm3Flash, "Check/try to defrag faulty/fragmented file system"}, {"dump", CmdFlashMemSpiFFSDump, IfPm3Flash, "Dump a file from SPIFFS file system"}, diff --git a/client/src/cmdlfem.c b/client/src/cmdlfem.c index 7ad0da3dc..378bf6729 100644 --- a/client/src/cmdlfem.c +++ b/client/src/cmdlfem.c @@ -24,10 +24,10 @@ static int CmdHelp(const char *Cmd); static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"410x", CmdLFEM410X, AlwaysAvailable, "EM 4102 commands..."}, - {"4x05", CmdLFEM4X05, AlwaysAvailable, "EM 4205 / 4305 / 4369 / 4469 commands..."}, - {"4x50", CmdLFEM4X50, AlwaysAvailable, "EM 4350 / 4450 commands..."}, - {"4x70", CmdLFEM4X70, AlwaysAvailable, "EM 4070 / 4170 commands..."}, + {"410x", CmdLFEM410X, AlwaysAvailable, "{ EM 4102 commands... }"}, + {"4x05", CmdLFEM4X05, AlwaysAvailable, "{ EM 4205 / 4305 / 4369 / 4469 commands... }"}, + {"4x50", CmdLFEM4X50, AlwaysAvailable, "{ EM 4350 / 4450 commands... }"}, + {"4x70", CmdLFEM4X70, AlwaysAvailable, "{ EM 4070 / 4170 commands... }"}, {NULL, NULL, NULL, NULL} }; diff --git a/client/src/cmdmain.c b/client/src/cmdmain.c index fe4fa0b84..7e0c823a4 100644 --- a/client/src/cmdmain.c +++ b/client/src/cmdmain.c @@ -298,10 +298,10 @@ static command_t CommandTable[] = { {"--------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("General") " -----------------------"}, {"auto", CmdAuto, IfPm3Present, "Automated detection process for unknown tags"}, {"clear", CmdClear, AlwaysAvailable, "Clear screen"}, - {"help", CmdHelp, AlwaysAvailable, "This help. Use " _YELLOW_("' help'") " for details of a particular command."}, + {"help", CmdHelp, AlwaysAvailable, "Use " _YELLOW_("' help'") " for details of a particular command."}, {"hints", CmdHints, AlwaysAvailable, "Turn hints on / off"}, {"msleep", CmdMsleep, AlwaysAvailable, "Add a pause in milliseconds"}, - {"pref", CmdPref, AlwaysAvailable, "Edit preferences"}, + {"pref", CmdPref, AlwaysAvailable, "{ Edit preferences... }"}, {"rem", CmdRem, AlwaysAvailable, "Add a text line in log file"}, {"quit", CmdQuit, AlwaysAvailable, ""}, {"exit", CmdQuit, AlwaysAvailable, "Exit program"}, diff --git a/client/src/preferences.c b/client/src/preferences.c index d961d2c6f..db08fbd37 100644 --- a/client/src/preferences.c +++ b/client/src/preferences.c @@ -1043,8 +1043,8 @@ static int CmdPrefSave (const char *Cmd) { */ static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"get", CmdPrefGet, AlwaysAvailable, "Get a preference"}, - {"set", CmdPrefSet, AlwaysAvailable, "Set a preference"}, + {"get", CmdPrefGet, AlwaysAvailable, "{ Get a preference }"}, + {"set", CmdPrefSet, AlwaysAvailable, "{ Set a preference }"}, {"show", CmdPrefShow, AlwaysAvailable, "Show all preferences"}, {NULL, NULL, NULL, NULL} }; diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 91aa977be..6ebcfd7b3 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -91,4 +91,4 @@ lf em 4x70 lf hitag reader lf hitag writer lf hitag dump -script run +mem spiffs diff --git a/doc/commands.md b/doc/commands.md index 1c9938d16..1c655b144 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -905,7 +905,7 @@ Check column "offline" for their availability. |`lf t55xx info `|Y |`Show T55x7 configuration data (page 0/ blk 0)` |`lf t55xx p1detect `|N |`Try detecting if this is a t55xx tag by reading page 1` |`lf t55xx read `|N |`Read T55xx block data` -|`lf t55xx resetread `|N |`Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)` +|`lf t55xx resetread `|N |`Send Reset Cmd then lf read the stream to attempt to identify the start of it` |`lf t55xx restore `|N |`Restore T55xx card Page 0 / Page 1 blocks` |`lf t55xx trace `|Y |`Show T55x7 traceability data (page 1/ blk 0-1)` |`lf t55xx wakeup `|N |`Send AOR wakeup command` From bcb83e01a9ea3cf4a1751e1e9a839fb6218a96c8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 16:16:50 +0100 Subject: [PATCH 39/67] text --- client/src/cmdscript.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdscript.c b/client/src/cmdscript.c index 4f3aad7d9..7c44c8978 100644 --- a/client/src/cmdscript.c +++ b/client/src/cmdscript.c @@ -429,9 +429,9 @@ static int CmdScriptRun(const char *Cmd) { } static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "Usage info"}, + {"help", CmdHelp, AlwaysAvailable, "This help"}, {"list", CmdScriptList, AlwaysAvailable, "List available scripts"}, - {"run", CmdScriptRun, AlwaysAvailable, " -- execute a script"}, + {"run", CmdScriptRun, AlwaysAvailable, " - execute a script"}, {NULL, NULL, NULL, NULL} }; From 94f99acafdac1b9caf5c8508b767bbb8494ba1d4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 16:17:33 +0100 Subject: [PATCH 40/67] one more selfttest --- tools/recover_pk.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/recover_pk.py b/tools/recover_pk.py index 0f01337a7..b242ff4cc 100755 --- a/tools/recover_pk.py +++ b/tools/recover_pk.py @@ -102,7 +102,8 @@ def selftests(): 'pk': "040E98E117AAA36457F43173DC920A8757267F44CE4EC5ADD3C54075571AEBBF7B942A9774A1D94AD02572427E5AE0A2DD36591B1FB34FCF3D"}, {'name': "DESFire EV2", 'samples': ["042A41CAE45380", "B2769F8DDB575AEA2A680ADCA8FFED4FAB81A1E9908E2B82FE0FABB697BBD9B23835C416970E75768F12902ACA491349E94E6589EAF4F508", - "045640CAE45380", "D34B53A8C2C100D700DEA1C4C0D0DE4409F3A418CD8D57C4F41F146E42AD9A55F014199ABBF5CA259C7799DB0AE20D5E77D4950AC7E95D33"], + "045640CAE45380", "D34B53A8C2C100D700DEA1C4C0D0DE4409F3A418CD8D57C4F41F146E42AD9A55F014199ABBF5CA259C7799DB0AE20D5E77D4950AC7E95D33", + "040D259A965B80","B158073A7100C88C3726F4299FA58311FC3CB18744686DE3F234928AD74578F5CAD7FCEC1DCB962ECC7CC000B8557B37F45B76DC6573A58F"], 'pk': "04B304DC4C615F5326FE9383DDEC9AA892DF3A57FA7FFB3276192BC0EAA252ED45A865E3B093A3D0DCE5BE29E92F1392CE7DE321E3E5C52B3A"}, {'name': "DESFire EV3", 'samples': ["04448BD2DB6B80", "5CBB5632795C8F15263FEFB095B51C7B541AFD914A1AE44EF6FB8AF605EDF13DBFEE6C3A2DB372245E671DFE0D42CB1F0D0B8FE67A89D2F6", @@ -146,6 +147,7 @@ def selftests(): for c in curvenames: for h in [None, "md5", "sha1", "sha256", "sha512"]: recovered |= recover_multiple(t['samples'][::2], t['samples'][1::2], c, alghash=h) + if (len(recovered) == 1): pk = recovered.pop() pk = binascii.hexlify(pk).decode('utf8') From aa2ee21fd649c55a87402d8a0aa11028893ce65e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 17:03:15 +0100 Subject: [PATCH 41/67] text --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 224e822af..8b4aebc8f 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ |[Donations](#Donations)|[Maintainers](/doc/md/Development/Maintainers.md)|[Command Cheat sheet](/doc/cheatsheet.md)| ||[Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md)|[More cheat sheets](https://github.com/RfidResearchGroup/proxmark3/wiki/More-cheat-sheets)| ||**[Troubleshooting](/doc/md/Installation_Instructions/Troubleshooting.md)**|[Complete client command set](/doc/commands.md)| -||**[JTAG](/doc/jtag_notes.md)**|[T55xx Guide](/doc/T5577_Guide.md)| +||**[JTAG](/doc/jtag_notes.md)**|[T5577 Introduction Guide](/doc/T5577_Guide.md)| ## Notes / helpful documents From a807c504c150b38b4990c186ec598b5eb2b9f0bd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 21:08:24 +0100 Subject: [PATCH 42/67] added ascii to the output --- client/src/util.c | 52 +++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/client/src/util.c b/client/src/util.c index 6519fec36..978cb4b45 100644 --- a/client/src/util.c +++ b/client/src/util.c @@ -183,46 +183,54 @@ void print_hex(const uint8_t *data, const size_t len) { } void print_hex_break(const uint8_t *data, const size_t len, uint8_t breaks) { - if (data == NULL || len == 0) return; + if (data == NULL || len == 0 || breaks == 0) return; - int rownum = 0; - PrintAndLogEx(INFO, "%02d | " NOLF, rownum); - for (size_t i = 0; i < len; ++i) { - - PrintAndLogEx(NORMAL, "%02X " NOLF, data[i]); - - // check if a line break is needed - if (breaks > 0 && !((i + 1) % breaks) && (i + 1 < len)) { - ++rownum; - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "%02d | " NOLF, rownum); + uint16_t rownum = 0; + int i; + for (i = 0; i < len; i += breaks, rownum++) { + if (len - i < breaks) { // incomplete block, will be treated out of the loop + break; } + PrintAndLogEx(INFO, "%02u | %s", rownum, sprint_hex_ascii(data + i, breaks)); + } + + // the last odd bytes + uint8_t mod = len % breaks; + + if (mod) { + char buf[UTIL_BUFFER_SIZE_SPRINT + 3]; + memset(buf, 0, sizeof(buf)); + hex_to_buffer((uint8_t *)buf, data + i, mod, (sizeof(buf) - 1), 0, 1, true); + + // add the spaces... + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%*s", ((breaks - mod) * 3), " "); + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "| %s", sprint_ascii(data + i, mod)); + PrintAndLogEx(INFO, "%02u | %s", rownum, buf); } - PrintAndLogEx(NORMAL, ""); } -void print_buffer(const uint8_t *data, const size_t len, int level) { +static void print_buffer_ex(const uint8_t *data, const size_t len, int level, uint8_t breaks) { if (len < 1) return; char buf[UTIL_BUFFER_SIZE_SPRINT + 3]; int i; - for (i = 0; i < len; i += 16) { - if (len - i < 16) { // incomplete block, will be treated out of the loop + for (i = 0; i < len; i += breaks) { + if (len - i < breaks) { // incomplete block, will be treated out of the loop break; } // (16 * 3) + (16) + + 1 memset(buf, 0, sizeof(buf)); sprintf(buf, "%*s%02x: ", (level * 4), " ", i); - hex_to_buffer((uint8_t *)(buf + strlen(buf)), data + i, 16, (sizeof(buf) - strlen(buf) - 1), 0, 1, true); - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "| %s", sprint_ascii(data + i, 16)); + hex_to_buffer((uint8_t *)(buf + strlen(buf)), data + i, breaks, (sizeof(buf) - strlen(buf) - 1), 0, 1, true); + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "| %s", sprint_ascii(data + i, breaks)); PrintAndLogEx(INFO, "%s", buf); } // the last odd bytes - uint8_t mod = len % 16; + uint8_t mod = len % breaks; if (mod) { memset(buf, 0, sizeof(buf)); @@ -230,13 +238,17 @@ void print_buffer(const uint8_t *data, const size_t len, int level) { hex_to_buffer((uint8_t *)(buf + strlen(buf)), data + i, mod, (sizeof(buf) - strlen(buf) - 1), 0, 1, true); // add the spaces... - snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%*s", ((16 - mod) * 3), " "); + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%*s", ((breaks - mod) * 3), " "); snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "| %s", sprint_ascii(data + i, mod)); PrintAndLogEx(INFO, "%s", buf); } } +void print_buffer(const uint8_t *data, const size_t len, int level) { + print_buffer_ex(data, len, level, 16); +} + void print_blocks(uint32_t *data, size_t len) { PrintAndLogEx(SUCCESS, "Blk | Data "); PrintAndLogEx(SUCCESS, "----+------------"); From 8dddb0b3bcb835dd2c2964a27703ae6cd9d6869f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 21:16:51 +0100 Subject: [PATCH 43/67] mem dump - optional columns --- client/src/cmdflashmem.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/src/cmdflashmem.c b/client/src/cmdflashmem.c index 475272a20..34f60bd51 100644 --- a/client/src/cmdflashmem.c +++ b/client/src/cmdflashmem.c @@ -355,6 +355,7 @@ static int CmdFlashMemDump(const char *Cmd) { arg_int0("l", "len", "", "length"), arg_lit0("v", "view", "view dump"), arg_strx0("f", "file", "", "file name"), + arg_int0("c", "cols", "", "column breaks (def 32)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -365,6 +366,7 @@ static int CmdFlashMemDump(const char *Cmd) { int fnlen = 0; char filename[FILE_PATH_SIZE] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + int breaks = arg_get_int_def(ctx, 5, 32); CLIParserFree(ctx); uint8_t *dump = calloc(len, sizeof(uint8_t)); @@ -382,7 +384,7 @@ static int CmdFlashMemDump(const char *Cmd) { if (view) { PrintAndLogEx(INFO, "---- " _CYAN_("data") " ---------------"); - print_hex_break(dump, len, 32); + print_hex_break(dump, len, breaks); } if (filename[0] != '\0') { From 5fa62126f5c230b99d2ae258b593b9fd5a215bd6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 21:17:47 +0100 Subject: [PATCH 44/67] updated commands --- doc/commands.md | 154 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 143 insertions(+), 11 deletions(-) diff --git a/doc/commands.md b/doc/commands.md index 1c655b144..862ae353f 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -12,10 +12,9 @@ Check column "offline" for their availability. |------- |------- |----------- |`auto `|N |`Automated detection process for unknown tags` |`clear `|Y |`Clear screen` -|`help `|Y |`This help. Use ' help' for details of a particular command.` +|`help `|Y |`Use ' help' for details of a particular command.` |`hints `|Y |`Turn hints on / off` |`msleep `|Y |`Add a pause in milliseconds` -|`pref `|Y |`Edit preferences` |`rem `|Y |`Add a text line in log file` |`quit `|Y |`` |`exit `|Y |`Exit program` @@ -606,10 +605,80 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`lf em help `|Y |`This help` -|`lf em 410x `|Y |`EM 4102 commands...` -|`lf em 4x05 `|Y |`EM 4205 / 4305 / 4369 / 4469 commands...` -|`lf em 4x50 `|Y |`EM 4350 / 4450 commands...` -|`lf em 4x70 `|Y |`EM 4070 / 4170 commands...` + + +### lf em 410x + + { EM 4102 commands... } + +|command |offline |description +|------- |------- |----------- +|`lf em 410x help `|Y |`This help` +|`lf em 410x demod `|Y |`demodulate a EM410x tag from the GraphBuffer` +|`lf em 410x reader `|N |`attempt to read and extract tag data` +|`lf em 410x sim `|N |`simulate EM410x tag` +|`lf em 410x brute `|N |`reader bruteforce attack by simulating EM410x tags` +|`lf em 410x watch `|N |`watches for EM410x 125/134 kHz tags (option 'h' for 134)` +|`lf em 410x spoof `|N |`watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)` +|`lf em 410x clone `|N |`write EM410x UID to T55x7 or Q5/T5555 tag` + + +### lf em 4x05 + + { EM 4205 / 4305 / 4369 / 4469 commands... } + +|command |offline |description +|------- |------- |----------- +|`lf em 4x05 help `|Y |`This help` +|`lf em 4x05 brute `|N |`Bruteforce password` +|`lf em 4x05 chk `|N |`Check passwords from dictionary` +|`lf em 4x05 demod `|Y |`demodulate a EM4x05/EM4x69 tag from the GraphBuffer` +|`lf em 4x05 dump `|N |`dump EM4x05/EM4x69 tag` +|`lf em 4x05 info `|N |`tag information EM4x05/EM4x69` +|`lf em 4x05 read `|N |`read word data from EM4x05/EM4x69` +|`lf em 4x05 sniff `|Y |`Attempt to recover em4x05 commands from sample buffer` +|`lf em 4x05 unlock `|N |`execute tear off against EM4x05/EM4x69` +|`lf em 4x05 wipe `|N |`wipe EM4x05/EM4x69 tag` +|`lf em 4x05 write `|N |`write word data to EM4x05/EM4x69` + + +### lf em 4x50 + + { EM 4350 / 4450 commands... } + +|command |offline |description +|------- |------- |----------- +|`lf em 4x50 help `|Y |`This help` +|`lf em 4x50 brute `|N |`guess password of EM4x50` +|`lf em 4x50 chk `|N |`check passwords from dictionary` +|`lf em 4x50 dump `|N |`dump EM4x50 tag` +|`lf em 4x50 info `|N |`tag information EM4x50` +|`lf em 4x50 login `|N |`login into EM4x50` +|`lf em 4x50 rdbl `|N |`read word data from EM4x50` +|`lf em 4x50 wrbl `|N |`write word data to EM4x50` +|`lf em 4x50 writepwd `|N |`change password of EM4x50` +|`lf em 4x50 wipe `|N |`wipe EM4x50 tag` +|`lf em 4x50 reader `|N |`show standard read mode data of EM4x50` +|`lf em 4x50 restore `|N |`restore EM4x50 dump to tag` +|`lf em 4x50 sim `|N |`simulate EM4x50 tag` +|`lf em 4x50 eload `|N |`upload dump of EM4x50 to emulator memory` +|`lf em 4x50 esave `|N |`save emulator memory to file` +|`lf em 4x50 eview `|N |`view EM4x50 content in emulator memory` + + +### lf em 4x70 + + { EM 4070 / 4170 commands... } + +|command |offline |description +|------- |------- |----------- +|`lf em 4x70 help `|Y |`This help` +|`lf em 4x70 info `|N |`Tag information EM4x70` +|`lf em 4x70 write `|N |`Write EM4x70` +|`lf em 4x70 unlock `|N |`Unlock EM4x70 for writing` +|`lf em 4x70 auth `|N |`Authenticate EM4x70` +|`lf em 4x70 writepin `|N |`Write PIN` +|`lf em 4x70 writekey `|N |`Write Crypt Key` ### lf fdxb @@ -673,6 +742,7 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`lf hitag help `|Y |`This help` +|`lf hitag eload `|N |`Load Hitag dump file into emulator memory` |`lf hitag list `|N |`List Hitag trace history` |`lf hitag info `|N |`Tag information` |`lf hitag reader `|N |`Act like a Hitag Reader` @@ -953,13 +1023,34 @@ Check column "offline" for their availability. |------- |------- |----------- |`mem help `|Y |`This help` |`mem baudrate `|N |`Set Flash memory Spi baudrate` -|`mem spiffs `|N |`High level SPI FileSystem Flash manipulation` -|`mem info `|N |`Flash memory information` -|`mem load `|N |`Load data into flash memory` |`mem dump `|N |`Dump data from flash memory` +|`mem info `|N |`Flash memory information` +|`mem load `|N |`Load data to flash memory` |`mem wipe `|N |`Wipe data from flash memory` +### mem spiffs + + { SPI File system } + +|command |offline |description +|------- |------- |----------- +|`mem spiffs help `|Y |`This help` +|`mem spiffs copy `|N |`Copy a file to another (destructively) in SPIFFS file system` +|`mem spiffs check `|N |`Check/try to defrag faulty/fragmented file system` +|`mem spiffs dump `|N |`Dump a file from SPIFFS file system` +|`mem spiffs info `|N |`Print file system info and usage statistics` +|`mem spiffs mount `|N |`Mount the SPIFFS file system if not already mounted` +|`mem spiffs remove `|N |`Remove a file from SPIFFS file system` +|`mem spiffs rename `|N |`Rename/move a file in SPIFFS file system` +|`mem spiffs test `|N |`Test SPIFFS Operations` +|`mem spiffs tree `|N |`Print the Flash memory file system tree` +|`mem spiffs unmount `|N |`Un-mount the SPIFFS file system` +|`mem spiffs upload `|N |`Upload file into SPIFFS file system` +|`mem spiffs view `|N |`View file on SPIFFS file system` +|`mem spiffs wipe `|N |`Wipe all files from SPIFFS file system * dangerous *` + + ### reveng { CRC calculations from RevEng software... } @@ -988,9 +1079,9 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- -|`script help `|Y |`Usage info` +|`script help `|Y |`This help` |`script list `|Y |`List available scripts` -|`script run `|Y |` -- execute a script` +|`script run `|Y |` - execute a script` ### trace @@ -1034,3 +1125,44 @@ Check column "offline" for their availability. |`wiegand decode `|Y |`Convert raw hex to decoded wiegand format (currently for HID Prox)` +### pref + + { Edit preferences... } + +|command |offline |description +|------- |------- |----------- +|`pref help `|Y |`This help` +|`pref show `|Y |`Show all preferences` + + +### pref get + + { Get a preference } + +|command |offline |description +|------- |------- |----------- +|`pref get barmode `|Y |`Get bar mode preference` +|`pref get clientdebug `|Y |`Get client debug level preference` +|`pref get color `|Y |`Get color support preference` +|`pref get savepaths `|Y |`Get file folder ` +|`pref get emoji `|Y |`Get emoji display preference` +|`pref get hints `|Y |`Get hint display preference` +|`pref get plotsliders `|Y |`Get plot slider display preference` + + +### pref set + + { Set a preference } + +|command |offline |description +|------- |------- |----------- +|`pref set help `|Y |`This help` +|`pref set barmode `|Y |`Set bar mode` +|`pref set clientdebug `|Y |`Set client debug level` +|`pref set color `|Y |`Set color support` +|`pref set emoji `|Y |`Set emoji display` +|`pref set hints `|Y |`Set hint display` +|`pref set savepaths `|Y |`... to be adjusted next ... ` +|`pref set plotsliders `|Y |`Set plot slider display` + + From 60f08c906095c935e7bf11a8e65bfd0226d943ec Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 21:18:47 +0100 Subject: [PATCH 45/67] text --- doc/cliparser_todo.txt | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 6ebcfd7b3..1fed2f4a0 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -1,5 +1,4 @@ clear -pref analyse foo data biphaserawdecode data detectclock @@ -84,11 +83,17 @@ hf mf cview hf mf gen3uid hf mf gen3blk hf mf gen3freeze -lf em 410x -lf em 4x05 -lf em 4x50 -lf em 4x70 +lf em 4x05 sniff +lf em 4x50 rdbl lf hitag reader lf hitag writer lf hitag dump -mem spiffs +pref show +pref get barmode +pref get clientdebug +pref get color +pref get savepaths +pref get emoji +pref get hints +pref get plotsliders +pref set savepaths From 590c7ff71750d8649ce264ab5fc0f39290676232 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 22:02:08 +0100 Subject: [PATCH 46/67] fix helptext --- client/src/cmdlfem4x05.c | 8 ++++---- client/src/cmdlfem4x50.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index 0a65c1cb2..f0d2b6cf5 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -1962,11 +1962,11 @@ int CmdEM4x05Sniff(const char *Cmd) { bool haveData, sampleData = true; CLIParserContext *ctx; - CLIParserInit(&ctx, "lf em 4x05_sniff", + CLIParserInit(&ctx, "lf em 4x05 sniff", "Sniff EM4x05 commands sent from a programmer", - "lf em 4x05_sniff -> sniff via lf sniff\n" - "lf em 4x05_sniff -1 -> sniff from data loaded into the buffer\n" - "lf em 4x05_sniff -r -> reverse the bit order when showing block data" + "lf em 4x05 sniff --> sniff via lf sniff\n" + "lf em 4x05 sniff -1 --> sniff from data loaded into the buffer\n" + "lf em 4x05 sniff -r --> reverse the bit order when showing block data" ); void *argtable[] = { diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index fc4f75e5b..9fda23296 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -568,7 +568,7 @@ int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out) { int CmdEM4x50Read(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "lf em 4x50 read", + CLIParserInit(&ctx, "lf em 4x50 rdbl", "Reads single EM4x50 block/word.", "lf em 4x50 rdbl -b 3\n" "lf em 4x50 rdbl -b 32 -p 12345678 -> reads block 32 with pwd 0x12345678\n" From 683bacb1ac3f7a4c5927fad50ab924b40ba68837 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 22:03:00 +0100 Subject: [PATCH 47/67] text --- doc/cliparser_todo.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 1fed2f4a0..670cf344c 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -83,8 +83,6 @@ hf mf cview hf mf gen3uid hf mf gen3blk hf mf gen3freeze -lf em 4x05 sniff -lf em 4x50 rdbl lf hitag reader lf hitag writer lf hitag dump From 102fa451db8dd5759642455e0137efe9c98d54d6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 22:14:57 +0100 Subject: [PATCH 48/67] pref - now uses cliparser everywhere --- client/src/preferences.c | 92 +++++++++++++++++++++++++++++++++++++++- doc/cliparser_todo.txt | 9 ---- 2 files changed, 90 insertions(+), 11 deletions(-) diff --git a/client/src/preferences.c b/client/src/preferences.c index db08fbd37..41b8fc1a6 100644 --- a/client/src/preferences.c +++ b/client/src/preferences.c @@ -761,7 +761,7 @@ static int setCmdHint(const char *Cmd) { static int setCmdPlotSliders(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref set plotsliders ", + CLIParserInit(&ctx, "pref set plotsliders", "Set presistent preference of showing the plotslider control in the client", "pref set plotsliders --on" ); @@ -803,7 +803,7 @@ static int setCmdPlotSliders(const char *Cmd) { static int setCmdSavePaths(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref set savepath", + CLIParserInit(&ctx, "pref set savepaths", "Set presistent preference of file paths in the client", "pref set savepaths --dump /home/mydumpfolder -> all dump files will be saved into this folder\n" "pref set savepaths --def /home/myfolder -c -> create if needed, all files will be saved into this folder" @@ -930,36 +930,113 @@ static int setCmdBarMode(const char *Cmd) { } static int getCmdEmoji(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "pref get emoji", + "Get preference of using emojis in the client", + "pref get emoji" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); showEmojiState(prefShowNone); return PM3_SUCCESS; } static int getCmdHint(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "pref get hints", + "Get preference of showing hint messages in the client", + "pref get hints" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); showHintsState(prefShowNone); return PM3_SUCCESS; } static int getCmdColor(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "pref get color", + "Get preference of using colors in the client", + "pref get color" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); showColorState(prefShowNone); return PM3_SUCCESS; } static int getCmdDebug(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "pref get clientdebug", + "Get preference of using clientside debug level", + "pref get clientdebug" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); showClientDebugState(prefShowNone); return PM3_SUCCESS; } static int getCmdPlotSlider(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "pref get plotsliders", + "Get preference of showing the plotslider control in the client", + "pref get plotsliders" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); showPlotSliderState(prefShowNone); return PM3_SUCCESS; } static int getCmdBarMode(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "pref get barmode", + "Get preference of HF/LF tune command styled output in the client", + "pref get barmode" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); showBarModeState(prefShowNone); return PM3_SUCCESS; } static int getCmdSavePaths(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "pref get savepaths", + "Get preference of file paths in the client", + "pref get savepaths" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); showSavePathState(spDefault, prefShowNone); showSavePathState(spDump, prefShowNone); showSavePathState(spTrace, prefShowNone); @@ -1008,6 +1085,17 @@ static int CmdPrefSet(const char *Cmd) { } static int CmdPrefShow(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "pref show", + "Show all persistent preferences", + "pref show" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); if (session.preferences_loaded) { char *fn = prefGetFilename(); diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 670cf344c..188870467 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -86,12 +86,3 @@ hf mf gen3freeze lf hitag reader lf hitag writer lf hitag dump -pref show -pref get barmode -pref get clientdebug -pref get color -pref get savepaths -pref get emoji -pref get hints -pref get plotsliders -pref set savepaths From 410db6773a7a6aa51c89f7191585dd0297f293e1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Mar 2021 22:50:56 +0100 Subject: [PATCH 49/67] text --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 8b4aebc8f..02c08a7f8 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ | ------------------- |:-------------------:| -------------------:| |[What has changed?](#what-has-changed) | **[Setup and build for Linux](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md)** | [Compilation Instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)| |[Development](#development) | **[Important notes on ModemManager for Linux users](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md)** | [Validating proxmark client functionality](/doc/md/Use_of_Proxmark/1_Validation.md) | -|[Why didn't you base it on official Proxmark3 Master?](#why-didnt-you-base-it-on-official-proxmark3-master)| **[Homebrew (Mac OS X) & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md)** | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)| +|| **[Homebrew (Mac OS X) & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md)** | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)| |[Proxmark3 GUI](#proxmark3-gui)|**[Setup and build for Windows](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md)**|[Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)| |[Issues](#issues)|[Blue shark manual](/doc/bt_manual_v10.md) || |[Donations](#Donations)|[Maintainers](/doc/md/Development/Maintainers.md)|[Command Cheat sheet](/doc/cheatsheet.md)| @@ -154,10 +154,6 @@ To all distro, package maintainers, we tried to make your life easier. `make install` is now available and if you want to know more. - [Notes for maintainers](/doc/md/Development/Maintainers.md) -## Why didn't you base it on official Proxmark3 Master? - -The separation from official Proxmark3 repo gives us a lot of freedom to create a firmware/client that suits the RDV40 features. We don't want to mess up the official Proxmark3 repo with RDV40 specific code. - ## Proxmark3 GUI The official PM3-GUI from Gaucho will not work. Not to mention is quite old and not maintained any longer. From 92b627a0bd2aa1924bbd3517557f2378fffaa735 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 10 Mar 2021 04:59:44 +0100 Subject: [PATCH 50/67] hf mf rdsc - modified output --- client/src/cmdhfmf.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index cb338826b..62c06e6f7 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -522,21 +522,22 @@ static int32_t initSectorTable(sector_t **src, int32_t items) { static void decode_print_st(uint16_t blockno, uint8_t *data) { if (mfIsSectorTrailer(blockno)) { - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Sector trailer decoded:"); - PrintAndLogEx(NORMAL, "----------------------------------------------"); - PrintAndLogEx(NORMAL, "Key A " _GREEN_("%s"), sprint_hex_inrow(data, 6)); - PrintAndLogEx(NORMAL, "Key B " _GREEN_("%s"), sprint_hex_inrow(data + 10, 6)); - PrintAndLogEx(NORMAL, "Access rights"); + + PrintAndLogEx(INFO, "--------- " _CYAN_("Sector trailer") " -------------"); + PrintAndLogEx(INFO, "key A........ " _GREEN_("%s"), sprint_hex_inrow(data, 6)); + PrintAndLogEx(INFO, "acr.......... " _GREEN_("%s"), sprint_hex_inrow(data + 6, 3)); + PrintAndLogEx(INFO, "user / gdb... " _GREEN_("%02x"), data[9]); + PrintAndLogEx(INFO, "key B........ " _GREEN_("%s"), sprint_hex_inrow(data + 10, 6)); + PrintAndLogEx(INFO, "Access rights decoded"); int bln = mfFirstBlockOfSector(mfSectorNum(blockno)); int blinc = (mfNumBlocksPerSector(mfSectorNum(blockno)) > 4) ? 5 : 1; for (int i = 0; i < 4; i++) { - PrintAndLogEx(NORMAL, " block %d%s " _YELLOW_("%s"), bln, ((blinc > 1) && (i < 3) ? "+" : ""), mfGetAccessConditionsDesc(i, &data[6])); + PrintAndLogEx(INFO, " block %d%s " _YELLOW_("%s"), bln, ((blinc > 1) && (i < 3) ? "+" : ""), mfGetAccessConditionsDesc(i, &data[6])); bln += blinc; } - PrintAndLogEx(NORMAL, "UserData " _YELLOW_("0x%02x"), data[9]); - PrintAndLogEx(NORMAL, "----------------------------------------------"); + + PrintAndLogEx(INFO, "--------------------------------------"); } } @@ -789,7 +790,8 @@ static int CmdHF14AMfRdSc(const char *Cmd) { PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); return PM3_ESOFT; } - PrintAndLogEx(NORMAL, "--sector no %d, key %c - %s ", sectorNo, keyType ? 'B' : 'A', sprint_hex(key, 6)); + PrintAndLogEx(INFO, "reading sector no %d, key %c, " _YELLOW_("%s"), sectorNo, keyType ? 'B' : 'A', sprint_hex_inrow(key, 6)); + PrintAndLogEx(NORMAL, ""); uint8_t sc_size = mfNumBlocksPerSector(sectorNo) * 16; uint8_t *data = calloc(sc_size, sizeof(uint8_t)); @@ -804,8 +806,10 @@ static int CmdHF14AMfRdSc(const char *Cmd) { uint8_t blocks = NumBlocksPerSector(sectorNo); uint8_t start = FirstBlockOfSector(sectorNo); + PrintAndLogEx(INFO, "blk | data"); + PrintAndLogEx(INFO, "----+------------------------------------------------"); for (int i = 0; i < blocks; i++) { - PrintAndLogEx(NORMAL, "%3d | %s", start + i, sprint_hex(data + (i * 16), 16)); + PrintAndLogEx(INFO, "%3d | %s", start + i, sprint_hex(data + (i * 16), 16)); } decode_print_st(start + blocks - 1, data + ((blocks - 1) * 16)); From bf49f4432bdc12776c09d57ef8c7a3c5e1561bdf Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 10 Mar 2021 05:15:36 +0100 Subject: [PATCH 51/67] rdsc/egetsc/cgetsc - output unified --- client/src/cmdhfmf.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 62c06e6f7..757d40288 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -522,7 +522,7 @@ static int32_t initSectorTable(sector_t **src, int32_t items) { static void decode_print_st(uint16_t blockno, uint8_t *data) { if (mfIsSectorTrailer(blockno)) { - + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--------- " _CYAN_("Sector trailer") " -------------"); PrintAndLogEx(INFO, "key A........ " _GREEN_("%s"), sprint_hex_inrow(data, 6)); PrintAndLogEx(INFO, "acr.......... " _GREEN_("%s"), sprint_hex_inrow(data + 6, 3)); @@ -790,7 +790,6 @@ static int CmdHF14AMfRdSc(const char *Cmd) { PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); return PM3_ESOFT; } - PrintAndLogEx(INFO, "reading sector no %d, key %c, " _YELLOW_("%s"), sectorNo, keyType ? 'B' : 'A', sprint_hex_inrow(key, 6)); PrintAndLogEx(NORMAL, ""); uint8_t sc_size = mfNumBlocksPerSector(sectorNo) * 16; @@ -806,10 +805,16 @@ static int CmdHF14AMfRdSc(const char *Cmd) { uint8_t blocks = NumBlocksPerSector(sectorNo); uint8_t start = FirstBlockOfSector(sectorNo); - PrintAndLogEx(INFO, "blk | data"); - PrintAndLogEx(INFO, "----+------------------------------------------------"); + PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sectorNo, sectorNo); + PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); for (int i = 0; i < blocks; i++) { - PrintAndLogEx(INFO, "%3d | %s", start + i, sprint_hex(data + (i * 16), 16)); + if (start + i == 0) { + PrintAndLogEx(INFO, "%3d | " _RED_("%s"), start + i, sprint_hex_ascii(data + (i * 16), 16)); + } else if (mfIsSectorTrailer(i)) { + PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), start + i, sprint_hex_ascii(data + (i * 16), 16)); + } else { + PrintAndLogEx(INFO, "%3d | %s ", start + i, sprint_hex_ascii(data + (i * 16), 16)); + } } decode_print_st(start + blocks - 1, data + ((blocks - 1) * 16)); @@ -3775,8 +3780,10 @@ static int CmdHF14AMfEGetSc(const char *Cmd) { return PM3_ESOFT; } - PrintAndLogEx(NORMAL, "\n # | data - sector %02d / 0x%02X ", sector, sector); - PrintAndLogEx(NORMAL, "----+------------------------------------------------"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); + PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); + uint8_t blocks = 4; uint8_t start = sector * 4; if (sector >= 32) { @@ -3789,11 +3796,11 @@ static int CmdHF14AMfEGetSc(const char *Cmd) { int res = mfEmlGetMem(data, start + i, 1); if (res == PM3_SUCCESS) { if (start + i == 0) { - PrintAndLogEx(INFO, "%03d | " _RED_("%s"), start + i, sprint_hex_ascii(data, sizeof(data))); + PrintAndLogEx(INFO, "%3d | " _RED_("%s"), start + i, sprint_hex_ascii(data, sizeof(data))); } else if (mfIsSectorTrailer(i)) { - PrintAndLogEx(INFO, "%03d | " _YELLOW_("%s"), start + i, sprint_hex_ascii(data, sizeof(data))); + PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), start + i, sprint_hex_ascii(data, sizeof(data))); } else { - PrintAndLogEx(INFO, "%03d | %s ", start + i, sprint_hex_ascii(data, sizeof(data))); + PrintAndLogEx(INFO, "%3d | %s ", start + i, sprint_hex_ascii(data, sizeof(data))); } } } @@ -4471,8 +4478,10 @@ static int CmdHF14AMfCGetSc(const char *Cmd) { return PM3_ESOFT; } - PrintAndLogEx(NORMAL, "\n # | data - sector %02d / 0x%02X ", sector, sector); - PrintAndLogEx(NORMAL, "----+------------------------------------------------"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); + PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); + uint8_t blocks = 4; uint8_t start = sector * 4; if (sector >= 32) { @@ -4491,7 +4500,7 @@ static int CmdHF14AMfCGetSc(const char *Cmd) { PrintAndLogEx(ERR, "Can't read block. %d error=%d", start + i, res); return PM3_ESOFT; } - PrintAndLogEx(NORMAL, "%3d | %s", start + i, sprint_hex(data, 16)); + PrintAndLogEx(INFO, "%3d | %s ", start + i, sprint_hex_ascii(data, sizeof(data))); } decode_print_st(start + blocks - 1, data); return PM3_SUCCESS; From 1b2091932eba4f1ac046c89cf5a11c6333136787 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 10 Mar 2021 10:43:49 +0100 Subject: [PATCH 52/67] fix 'mem spiffs view' and bad file stats retrieval --- armsrc/spiffs.c | 13 +++++-------- client/src/cmdflashmemspiffs.c | 5 +++++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/armsrc/spiffs.c b/armsrc/spiffs.c index a1b3e8e39..8242df9fc 100644 --- a/armsrc/spiffs.c +++ b/armsrc/spiffs.c @@ -208,15 +208,12 @@ static void remove_from_spiffs(const char *filename) { Dbprintf("errno %i\n", SPIFFS_errno(&fs)); } -static spiffs_stat stat_in_spiffs(const char *filename) { - spiffs_stat s; - if (SPIFFS_stat(&fs, filename, &s) < 0) - Dbprintf("errno %i\n", SPIFFS_errno(&fs)); - return s; -} - uint32_t size_in_spiffs(const char *filename) { - spiffs_stat s = stat_in_spiffs(filename); + spiffs_stat s; + if (SPIFFS_stat(&fs, filename, &s) < 0) { + Dbprintf("errno %i\n", SPIFFS_errno(&fs)); + return 0; + } return s.size; } diff --git a/client/src/cmdflashmemspiffs.c b/client/src/cmdflashmemspiffs.c index 6da30392e..9409e52ee 100644 --- a/client/src/cmdflashmemspiffs.c +++ b/client/src/cmdflashmemspiffs.c @@ -497,6 +497,11 @@ static int CmdFlashMemSpiFFSView(const char *Cmd) { } uint32_t len = resp.data.asDwords[0]; + if (len == 0) { + PrintAndLogEx(ERR, "error, failed to retrieve file stats on SPIFFSS"); + return PM3_EFAILED; + } + uint8_t *dump = calloc(len, sizeof(uint8_t)); if (!dump) { PrintAndLogEx(ERR, "error, cannot allocate memory "); From d3a960717f188352727eaaecca12b09598945d24 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 10 Mar 2021 11:23:13 +0100 Subject: [PATCH 53/67] text --- client/src/cmdhw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhw.c b/client/src/cmdhw.c index fb560b2ee..8bd691e25 100644 --- a/client/src/cmdhw.c +++ b/client/src/cmdhw.c @@ -975,7 +975,7 @@ void pm3_version(bool verbose, bool oneliner) { } PrintAndLogEx(NORMAL, " device.................... %s", (is_genuine_rdv4) ? _GREEN_("RDV4") : _RED_("device / fw mismatch")); - PrintAndLogEx(NORMAL, " firmware.................. %s", _YELLOW_("RDV4")); + PrintAndLogEx(NORMAL, " firmware.................. %s", (is_genuine_rdv4) ? _GREEN_("RDV4") : _YELLOW_("RDV4")); PrintAndLogEx(NORMAL, " external flash............ %s", IfPm3Flash() ? _GREEN_("present") : _YELLOW_("absent")); PrintAndLogEx(NORMAL, " smartcard reader.......... %s", IfPm3Smartcard() ? _GREEN_("present") : _YELLOW_("absent")); PrintAndLogEx(NORMAL, " FPC USART for BT add-on... %s", IfPm3FpcUsartHost() ? _GREEN_("present") : _YELLOW_("absent")); From 3502fbd82bce2c24e432b7119258d50cd4452762 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 10 Mar 2021 12:08:22 +0100 Subject: [PATCH 54/67] Fix lf em4x05 unlock --- client/src/cmdlfem4x05.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index f0d2b6cf5..917dd21e3 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -1692,11 +1692,8 @@ int CmdEM4x05Unlock(const char *Cmd) { } // write - res = unlock_write_protect(use_pwd, pwd, write_value, verbose); - if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "failed unlock write"); - return PM3_ESOFT; - } + // don't check the return value. As a tear-off occurred, the write failed. + unlock_write_protect(use_pwd, pwd, write_value, verbose); // read after trigger res = em4x05_read_word_ext(14, pwd, use_pwd, &word14); From 64a04498bd0076bf09298bfa7e7e8699059c4115 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 10 Mar 2021 13:52:26 +0100 Subject: [PATCH 55/67] Add reader parity errors on MFC traces --- client/src/cmdtrace.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index 4369d3a71..e178a08fd 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -242,7 +242,6 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr } for (int j = 0; j < data_len && j / 18 < 18; j++) { - uint8_t parityBits = parityBytes[j >> 3]; if (protocol != LEGIC && protocol != ISO_14443B @@ -256,7 +255,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr && protocol != FELICA && protocol != LTO && protocol != PROTO_CRYPTORF - && (hdr->isResponse || protocol == ISO_14443A) + && (hdr->isResponse || protocol == ISO_14443A || protocol == PROTO_MIFARE) && (oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) { snprintf(line[j / 18] + ((j % 18) * 4), 120, "%02x! ", frame[j]); From 27dafa2bb02d472782781b83745ecc1dcead3c6f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 10 Mar 2021 14:08:33 +0100 Subject: [PATCH 56/67] marking of crc bytes overwrote first hex char --- client/src/cmdtrace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index e178a08fd..ba1987502 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -279,9 +279,9 @@ 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); + char *pos1 = line[(data_len - 2) / 18] + (((data_len - 2) % 18) * 4) - 1; (*pos1) = '['; - char *pos2 = line[(data_len) / 18] + (((data_len) % 18) * 4); + char *pos2 = line[(data_len) / 18] + (((data_len) % 18) * 4) - 1; sprintf(pos2, "%c", ']'); } } From e08d6e5ca50327da9ede571b6d08026e08487580 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 10 Mar 2021 23:46:24 +0100 Subject: [PATCH 57/67] added mf_trace_brute to recover upper 16 bits in offline mode only --- tools/mf_nonce_brute/Makefile | 8 +- tools/mf_nonce_brute/README.md | 2 +- tools/mf_nonce_brute/mf_trace_brute.c | 315 ++++++++++++++++++++++++++ 3 files changed, 321 insertions(+), 4 deletions(-) create mode 100644 tools/mf_nonce_brute/mf_trace_brute.c diff --git a/tools/mf_nonce_brute/Makefile b/tools/mf_nonce_brute/Makefile index cf565e72c..c68b828de 100644 --- a/tools/mf_nonce_brute/Makefile +++ b/tools/mf_nonce_brute/Makefile @@ -1,6 +1,6 @@ -MYSRCPATHS = ../../common ../../common/crapto1 +MYSRCPATHS = ../../common ../../common/crapto1 MYSRCS = crypto1.c crapto1.c bucketsort.c iso14443crc.c sleep.c -MYINCLUDES = -I../../include -I../../common +MYINCLUDES = -I../../include -I../../common MYCFLAGS = MYDEFS = MYLDLIBS = @@ -8,7 +8,7 @@ ifneq ($(SKIPPTHREAD),1) MYLDLIBS += -lpthread endif -BINS = mf_nonce_brute +BINS = mf_nonce_brute mf_trace_brute INSTALLTOOLS = $(BINS) include ../../Makefile.host @@ -21,3 +21,5 @@ ifneq (,$(findstring MINGW,$(platform))) endif mf_nonce_brute : $(OBJDIR)/mf_nonce_brute.o $(MYOBJS) + +mf_trace_brute : $(OBJDIR)/mf_trace_brute.o $(MYOBJS) \ No newline at end of file diff --git a/tools/mf_nonce_brute/README.md b/tools/mf_nonce_brute/README.md index c2e5f3e6f..6119412be 100644 --- a/tools/mf_nonce_brute/README.md +++ b/tools/mf_nonce_brute/README.md @@ -85,7 +85,7 @@ Example with parity (from this trace http://www.proxmark.org/forum/viewtopic.php ``` => ``` -./mf_nonce_brute 9c599b32 82a4166c 0000 a1e458ce 6eea41e0 0101 5cadf439 1001 3e709c8a +./mf_nonce_brute 9c599b32 82a4166c 0000 a1e458ce 6eea41e0 0101 5cadf439 1001 8e0e5db9 | | | | | | | | | +UID +nt_enc | +nr_enc +ar_enc | +at_enc | +encrypted next cmd +nt_par_err +at_par_err +at_par_err diff --git a/tools/mf_nonce_brute/mf_trace_brute.c b/tools/mf_nonce_brute/mf_trace_brute.c new file mode 100644 index 000000000..c3973f5dc --- /dev/null +++ b/tools/mf_nonce_brute/mf_trace_brute.c @@ -0,0 +1,315 @@ +// +// bruteforce the upper 16bits of a partial key recovered from mf_nonce_brute. +// J-run's original idea was a two part recovery vector with first a offline trace and then online for 2 bytes. +// +// This idea is two use only offline, to recover a nested authentication key. +// Assumption, we get a read/write command after a nested auth, we need 22 bytes of data. +// Iceman, 2021, +// + +#define __STDC_FORMAT_MACROS + +#if !defined(_WIN64) +#if defined(_WIN32) || defined(__WIN32__) +# define _USE_32BIT_TIME_T 1 +#endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include "ctype.h" +#include +#include "crapto1/crapto1.h" +#include "protocol.h" +#include "iso14443crc.h" + +// a global mutex to prevent interlaced printing from different threads +pthread_mutex_t print_lock; + +#define ENC_LEN (4 + 16 + 2) +//--------------------- define options here + +typedef struct thread_args { + int thread; + int idx; + uint32_t uid; + uint32_t part_key; + uint32_t nt_enc; + uint32_t nr_enc; + uint8_t enc[ENC_LEN]; // next encrypted command + a full read/write +} targs; + +//------------------------------------------------------------------ +uint8_t cmds[] = { + ISO14443A_CMD_READBLOCK, + ISO14443A_CMD_WRITEBLOCK, + MIFARE_AUTH_KEYA, + MIFARE_AUTH_KEYB, + MIFARE_CMD_INC, + MIFARE_CMD_DEC, + MIFARE_CMD_RESTORE, + MIFARE_CMD_TRANSFER +}; + +int global_counter = 0; +int global_fin_flag = 0; +int global_found = 0; +int global_found_candidate = 0; +size_t thread_count = 2; + +static int param_getptr(const char *line, int *bg, int *en, int paramnum) { + int i; + int len = strlen(line); + + *bg = 0; + *en = 0; + + // skip spaces + while (line[*bg] == ' ' || line[*bg] == '\t')(*bg)++; + if (*bg >= len) { + return 1; + } + + for (i = 0; i < paramnum; i++) { + while (line[*bg] != ' ' && line[*bg] != '\t' && line[*bg] != '\0')(*bg)++; + while (line[*bg] == ' ' || line[*bg] == '\t')(*bg)++; + + if (line[*bg] == '\0') return 1; + } + + *en = *bg; + while (line[*en] != ' ' && line[*en] != '\t' && line[*en] != '\0')(*en)++; + + (*en)--; + + return 0; +} + +static int param_gethex_to_eol(const char *line, int paramnum, uint8_t *data, int maxdatalen, int *datalen) { + int bg, en; + uint32_t temp; + char buf[5] = {0}; + + if (param_getptr(line, &bg, &en, paramnum)) return 1; + + *datalen = 0; + + int indx = bg; + while (line[indx]) { + if (line[indx] == '\t' || line[indx] == ' ') { + indx++; + continue; + } + + if (isxdigit(line[indx])) { + buf[strlen(buf) + 1] = 0x00; + buf[strlen(buf)] = line[indx]; + } else { + // if we have symbols other than spaces and hex + return 1; + } + + if (*datalen >= maxdatalen) { + // if we dont have space in buffer and have symbols to translate + return 2; + } + + if (strlen(buf) >= 2) { + sscanf(buf, "%x", &temp); + data[*datalen] = (uint8_t)(temp & 0xff); + *buf = 0; + (*datalen)++; + } + + indx++; + } + + if (strlen(buf) > 0) + //error when not completed hex bytes + return 3; + + return 0; +} + +static void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, const size_t hex_max_len, + const size_t min_str_len, const size_t spaces_between, bool uppercase) { + + if (buf == NULL) return; + + char *tmp = (char *)buf; + size_t i; + memset(tmp, 0x00, hex_max_len); + + size_t max_len = (hex_len > hex_max_len) ? hex_max_len : hex_len; + + for (i = 0; i < max_len; ++i, tmp += 2 + spaces_between) { + sprintf(tmp, (uppercase) ? "%02X" : "%02x", (unsigned int) hex_data[i]); + + for (size_t j = 0; j < spaces_between; j++) + sprintf(tmp + 2 + j, " "); + } + + i *= (2 + spaces_between); + + size_t mlen = min_str_len > i ? min_str_len : 0; + if (mlen > hex_max_len) + mlen = hex_max_len; + + for (; i < mlen; i++, tmp += 1) + sprintf(tmp, " "); + + // remove last space + *tmp = '\0'; + return; +} + +static char *sprint_hex_inrow_ex(const uint8_t *data, const size_t len, const size_t min_str_len) { + static char buf[100] = {0}; + hex_to_buffer((uint8_t *)buf, data, len, sizeof(buf) - 1, min_str_len, 0, true); + return buf; +} + +static void *brute_thread(void *arguments) { + + //int shift = (int)arg; + struct thread_args *args = (struct thread_args *) arguments; + + uint64_t key; // recovered key candidate + int found = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs = &mpcs; + + uint8_t local_enc[ENC_LEN] = {0}; + memcpy(local_enc, args->enc, sizeof(local_enc)); + + for (uint64_t count = args->idx; count < 0xFFFF; count += thread_count) { + + found = global_found; + if (found) { + break; + } + + key = (count << 32 | args->part_key); + + // Init cipher with key + pcs = crypto1_create(key); + + // NESTED decrypt nt with help of new key +// if (args->use_nested) +// crypto1_word(pcs, args->nt_enc ^ args->uid, 1) ^ args->nt_enc; +// else + crypto1_word(pcs, args->nt_enc ^ args->uid, 1); + + crypto1_word(pcs, args->nr_enc, 1); + crypto1_word(pcs, 0, 0); + crypto1_word(pcs, 0, 0); + + // decrypt 22 bytes + uint8_t dec[ENC_LEN] = {0}; + for (int i = 0; i < ENC_LEN; i++) + dec[i] = crypto1_byte(pcs, 0x00, 0) ^ local_enc[i]; + + crypto1_deinit(pcs); + + if (CheckCrc14443(CRC_14443_A, dec , 4)) { + + // check crc-16 in the end + + if (CheckCrc14443(CRC_14443_A, dec + 4, 18)) { + + // lock this section to avoid interlacing prints from different threats + pthread_mutex_lock(&print_lock); + printf("\nValid Key found: [%012" PRIx64 "]\n", key); + + printf("enc: %s\n", sprint_hex_inrow_ex(local_enc, ENC_LEN, 0)); + printf(" xx crcA crcA\n"); + printf("dec: %s\n", sprint_hex_inrow_ex(dec, ENC_LEN, 0)); + pthread_mutex_unlock(&print_lock); + + __sync_fetch_and_add(&global_found, 1); + } + } + } + free(args); + return NULL; +} + +static int usage(void) { + printf(" syntax: mf_trace_brute []\n\n"); + return 1; +} + +int main(int argc, char *argv[]) { + printf("Mifare classic nested auth key recovery. Phase 2.\n"); + if (argc < 3) return usage(); + + uint32_t uid = 0; // serial number + uint32_t part_key = 0; // last 4 keys of key + uint32_t nt_enc = 0; // noncce tag + uint32_t nr_enc = 0; // nonce reader encrypted + + sscanf(argv[1], "%x", &uid); + sscanf(argv[2], "%x", &part_key); + sscanf(argv[3], "%x", &nt_enc); + sscanf(argv[4], "%x", &nr_enc); + + int enc_len = 0; + uint8_t enc[ENC_LEN] = {0}; // next encrypted command + a full read/write + param_gethex_to_eol(argv[5], 0, enc, sizeof(enc), &enc_len); + + printf("-------------------------------------------------\n"); + printf("uid.......... %08x\n", uid); + printf("partial key.. %08x\n", part_key); + printf("nt enc....... %08x\n", nt_enc); + printf("nr enc....... %08x\n", nr_enc); + printf("next encrypted cmd: %s\n", sprint_hex_inrow_ex(enc, ENC_LEN ,0)); + + clock_t t1 = clock(); + +#if !defined(_WIN32) || !defined(__WIN32__) + thread_count = sysconf(_SC_NPROCESSORS_CONF); + if (thread_count < 2) + thread_count = 2; +#endif /* _WIN32 */ + + printf("\nBruteforce using %zu threads to find upper 16bits of key\n", thread_count); + + pthread_t threads[thread_count]; + + // create a mutex to avoid interlacing print commands from our different threads + pthread_mutex_init(&print_lock, NULL); + + // threads + for (int i = 0; i < thread_count; ++i) { + struct thread_args *a = malloc(sizeof(struct thread_args)); + a->thread = i; + a->idx = i; + a->uid = uid; + a->part_key = part_key; + a->nt_enc = nt_enc; + a->nr_enc = nr_enc; + memcpy(a->enc, enc, sizeof(a->enc)); + pthread_create(&threads[i], NULL, brute_thread, (void *)a); + } + + // wait for threads to terminate: + for (int i = 0; i < thread_count; ++i) + pthread_join(threads[i], NULL); + + if (!global_found && !global_found_candidate) { + printf("\nFailed to find a key\n\n"); + } + + t1 = clock() - t1; + if (t1 > 0) + printf("Execution time: %.0f ticks\n", (float)t1); + + // clean up mutex + pthread_mutex_destroy(&print_lock); + return 0; +} From 43d45b0331762d5ba93f69f8b561ba252b391431 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 11 Mar 2021 08:58:50 +0100 Subject: [PATCH 58/67] added the possibility to automatically bruteforce the key if four or more bytes of encrypted next command is available --- tools/mf_nonce_brute/mf_nonce_brute.c | 339 +++++++++++++++++++++++--- 1 file changed, 304 insertions(+), 35 deletions(-) diff --git a/tools/mf_nonce_brute/mf_nonce_brute.c b/tools/mf_nonce_brute/mf_nonce_brute.c index 9891b99cc..2bd500c90 100644 --- a/tools/mf_nonce_brute/mf_nonce_brute.c +++ b/tools/mf_nonce_brute/mf_nonce_brute.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "crapto1/crapto1.h" #include "protocol.h" #include "iso14443crc.h" @@ -42,24 +43,150 @@ typedef struct thread_args { bool ev1; } targs; +#define ENC_LEN (200) +typedef struct thread_key_args { + int thread; + int idx; + uint32_t uid; + uint32_t part_key; + uint32_t nt_enc; + uint32_t nr_enc; + uint16_t enc_len; + uint8_t enc[ENC_LEN]; // next encrypted command + a full read/write +} targs_key; + //------------------------------------------------------------------ -uint8_t cmds[] = { - ISO14443A_CMD_READBLOCK, - ISO14443A_CMD_WRITEBLOCK, - MIFARE_AUTH_KEYA, - MIFARE_AUTH_KEYB, - MIFARE_CMD_INC, - MIFARE_CMD_DEC, - MIFARE_CMD_RESTORE, - MIFARE_CMD_TRANSFER + +uint8_t cmds[8][2] = { + {ISO14443A_CMD_READBLOCK, 18}, + {ISO14443A_CMD_WRITEBLOCK, 18}, + {MIFARE_AUTH_KEYA, 0}, + {MIFARE_AUTH_KEYB, 0}, + {MIFARE_CMD_INC, 6}, + {MIFARE_CMD_DEC, 6}, + {MIFARE_CMD_RESTORE, 6}, + {MIFARE_CMD_TRANSFER, 0} }; int global_counter = 0; int global_fin_flag = 0; int global_found = 0; int global_found_candidate = 0; +uint64_t global_candiate_key = 0; size_t thread_count = 2; +static int param_getptr(const char *line, int *bg, int *en, int paramnum) { + int i; + int len = strlen(line); + + *bg = 0; + *en = 0; + + // skip spaces + while (line[*bg] == ' ' || line[*bg] == '\t')(*bg)++; + if (*bg >= len) { + return 1; + } + + for (i = 0; i < paramnum; i++) { + while (line[*bg] != ' ' && line[*bg] != '\t' && line[*bg] != '\0')(*bg)++; + while (line[*bg] == ' ' || line[*bg] == '\t')(*bg)++; + + if (line[*bg] == '\0') return 1; + } + + *en = *bg; + while (line[*en] != ' ' && line[*en] != '\t' && line[*en] != '\0')(*en)++; + + (*en)--; + + return 0; +} + +static int param_gethex_to_eol(const char *line, int paramnum, uint8_t *data, int maxdatalen, int *datalen) { + int bg, en; + uint32_t temp; + char buf[5] = {0}; + + if (param_getptr(line, &bg, &en, paramnum)) return 1; + + *datalen = 0; + + int indx = bg; + while (line[indx]) { + if (line[indx] == '\t' || line[indx] == ' ') { + indx++; + continue; + } + + if (isxdigit(line[indx])) { + buf[strlen(buf) + 1] = 0x00; + buf[strlen(buf)] = line[indx]; + } else { + // if we have symbols other than spaces and hex + return 1; + } + + if (*datalen >= maxdatalen) { + // if we dont have space in buffer and have symbols to translate + return 2; + } + + if (strlen(buf) >= 2) { + sscanf(buf, "%x", &temp); + data[*datalen] = (uint8_t)(temp & 0xff); + *buf = 0; + (*datalen)++; + } + + indx++; + } + + if (strlen(buf) > 0) + //error when not completed hex bytes + return 3; + + return 0; +} + +static void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, const size_t hex_max_len, + const size_t min_str_len, const size_t spaces_between, bool uppercase) { + + if (buf == NULL) return; + + char *tmp = (char *)buf; + size_t i; + memset(tmp, 0x00, hex_max_len); + + size_t max_len = (hex_len > hex_max_len) ? hex_max_len : hex_len; + + for (i = 0; i < max_len; ++i, tmp += 2 + spaces_between) { + sprintf(tmp, (uppercase) ? "%02X" : "%02x", (unsigned int) hex_data[i]); + + for (size_t j = 0; j < spaces_between; j++) + sprintf(tmp + 2 + j, " "); + } + + i *= (2 + spaces_between); + + size_t mlen = min_str_len > i ? min_str_len : 0; + if (mlen > hex_max_len) + mlen = hex_max_len; + + for (; i < mlen; i++, tmp += 1) + sprintf(tmp, " "); + + // remove last space + *tmp = '\0'; + return; +} + +static char *sprint_hex_inrow_ex(const uint8_t *data, const size_t len, const size_t min_str_len) { + static char buf[100] = {0}; + hex_to_buffer((uint8_t *)buf, data, len, sizeof(buf) - 1, min_str_len, 0, true); + return buf; +} + static uint16_t parity_from_err(uint32_t data, uint16_t par_err) { uint16_t par = 0; @@ -196,13 +323,33 @@ static bool candidate_nonce(uint32_t xored, uint32_t nt, bool ev1) { static bool checkValidCmd(uint32_t decrypted) { uint8_t cmd = (decrypted >> 24) & 0xFF; - for (int i = 0; i < sizeof(cmds); ++i) { - if (cmd == cmds[i]) + for (int i = 0; i < 8; ++i) { + if (cmd == cmds[i][0]) return true; } return false; } +static bool checkValidCmdByte(uint8_t *cmd, uint16_t n) { + + bool ok = false; + for (int i = 0; i < 8; ++i) { + if (cmd[0] == cmds[i][0]) { + + if (n >= 4) + ok = CheckCrc14443(CRC_14443_A, cmd, 4); + + if (cmds[i][1] > 0 && n >= cmds[i][1]) + ok = CheckCrc14443(CRC_14443_A, cmd + 4, cmds[i][1]); + + if (ok) { + return true; + } + } + } + return false; +} + static bool checkCRC(uint32_t decrypted) { uint8_t data[] = { (decrypted >> 24) & 0xFF, @@ -293,11 +440,13 @@ static void *brute_thread(void *arguments) { free(revstate); if (args->ev1) { - printf("\nKey candidate: [%012" PRIx64 "]\n\n", key); + printf("\nKey candidate [ %012" PRIx64 " ]\n\n", key); __sync_fetch_and_add(&global_found_candidate, 1); + __sync_fetch_and_add(&global_candiate_key, key); } else { - printf("\nValid Key found: [%012" PRIx64 "]\n\n", key); + printf("\nValid Key found [ %012" PRIx64 " ]\n\n", key); __sync_fetch_and_add(&global_found, 1); + __sync_fetch_and_add(&global_candiate_key, key); } //release lock pthread_mutex_unlock(&print_lock); @@ -307,18 +456,85 @@ static void *brute_thread(void *arguments) { return NULL; } +static void *brute_key_thread(void *arguments) { + + struct thread_key_args *args = (struct thread_key_args *) arguments; + + uint64_t key; // recovered key candidate + int found = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs = &mpcs; + + uint8_t local_enc[args->enc_len]; + memcpy(local_enc, args->enc, args->enc_len); + + for (uint64_t count = args->idx; count < 0xFFFF; count += thread_count) { + + found = global_found; + if (found) { + break; + } + + key = (count << 32 | args->part_key); + + // Init cipher with key + pcs = crypto1_create(key); + + // NESTED decrypt nt with help of new key + crypto1_word(pcs, args->nt_enc ^ args->uid, 1); + crypto1_word(pcs, args->nr_enc, 1); + crypto1_word(pcs, 0, 0); + crypto1_word(pcs, 0, 0); + + // decrypt 22 bytes + uint8_t dec[args->enc_len]; + for (int i = 0; i < args->enc_len; i++) + dec[i] = crypto1_byte(pcs, 0x00, 0) ^ local_enc[i]; + + crypto1_deinit(pcs); + + // check if cmd exists + uint8_t isOK = checkValidCmdByte(dec, args->enc_len); + if (isOK == false) { + continue; + } + + // lock this section to avoid interlacing prints from different threats + pthread_mutex_lock(&print_lock); + printf("\nenc: %s\n", sprint_hex_inrow_ex(local_enc, args->enc_len, 0)); + printf("dec: %s\n", sprint_hex_inrow_ex(dec, args->enc_len, 0)); + printf("\nValid Key found [ %012" PRIx64 " ]\n\n", key); + pthread_mutex_unlock(&print_lock); + __sync_fetch_and_add(&global_found, 1); + } + free(args); + return NULL; +} + static int usage(void) { - printf(" syntax: mf_nonce_brute []\n\n"); - printf(" example: nt in trace = 8c! 42 e6! 4e!\n"); - printf(" nt = 8c42e64e\n"); - printf(" nt_par_err = 1011\n\n"); - printf("\n expected outcome:\n"); - printf(" KEY 0xFFFFFFFFFFFF == fa247164 fb47c594 0000 71909d28 0c254817 1000 0dc7cfbd 1110\n"); + printf("\n"); + printf("syntax: mf_nonce_brute []\n\n"); + printf("how to convert trace data to needed input:\n"); + printf(" nt in trace = 8c! 42 e6! 4e!\n"); + printf(" nt = 8c42e64e\n"); + printf(" nt_par_err = 1011\n\n"); + printf("samples:\n"); + printf("\n"); + printf(" ./mf_nonce_brute fa247164 fb47c594 0000 71909d28 0c254817 1000 0dc7cfbd 1110\n"); + printf("\n"); + printf("**** Possible key candidate ****\n"); + printf("Key candidate: [ffffffffffff]\n"); + printf("\n"); + printf(" ./mf_nonce_brute 96519578 d7e3c6ac 0011 cd311951 9da49e49 0010 2bb22e00 0100 a4f7f398ebdb4e484d1cb2b174b939d18b469f3fa5d9caab\n"); + printf("\n"); + printf("enc: A4F7F398EBDB4E484D1CB2B174B939D18B469F3FA5D9CAABBFA018EC7E0CC5721DE2E590F64BD0A5B4EFCE71\n"); + printf("dec: 30084A24302F8102F44CA5020500A60881010104763930084A24302F8102F44CA5020500A608810101047639\n"); + printf("Valid Key found: [3b7e4fd575ad]\n\n"); return 1; } int main(int argc, char *argv[]) { - printf("Mifare classic nested auth key recovery. Phase 1.\n"); + printf("\nMifare classic nested auth key recovery\n\n"); if (argc < 9) return usage(); @@ -331,21 +547,28 @@ int main(int argc, char *argv[]) { sscanf(argv[7], "%x", &at_enc); sscanf(argv[8], "%x", &at_par_err); - if (argc > 9) - sscanf(argv[9], "%x", &cmd_enc); + int enc_len = 0; + uint8_t enc[ENC_LEN] = {0}; // next encrypted command + a full read/write + if (argc > 9) { +// sscanf(argv[9], "%x", &cmd_enc); + param_gethex_to_eol(argv[9], 0, enc, sizeof(enc), &enc_len); + cmd_enc = (enc[0] << 24 | enc[1] << 16 | enc[2] << 8 | enc[3]); + } - printf("-------------------------------------------------\n"); - printf("uid:\t\t%08x\n", uid); - printf("nt encrypted:\t%08x\n", nt_enc); - printf("nt parity err:\t%04x\n", nt_par_err); - printf("nr encrypted:\t%08x\n", nr_enc); - printf("ar encrypted:\t%08x\n", ar_enc); - printf("ar parity err:\t%04x\n", ar_par_err); - printf("at encrypted:\t%08x\n", at_enc); - printf("at parity err:\t%04x\n", at_par_err); + printf("----------- Phase 1 ------------------------\n"); + printf("uid............. %08x\n", uid); + printf("nt encrypted.... %08x\n", nt_enc); + printf("nt parity err... %04x\n", nt_par_err); + printf("nr encrypted.... %08x\n", nr_enc); + printf("ar encrypted.... %08x\n", ar_enc); + printf("ar parity err... %04x\n", ar_par_err); + printf("at encrypted.... %08x\n", at_enc); + printf("at parity err... %04x\n", at_par_err); - if (argc > 9) - printf("next cmd enc:\t%08x\n\n", cmd_enc); + if (argc > 9) { +// printf("next cmd enc:\t%08x\n\n", cmd_enc); + printf("next encrypted cmd: %s\n", sprint_hex_inrow_ex(enc, enc_len ,0)); + } clock_t t1 = clock(); uint16_t nt_par = parity_from_err(nt_enc, nt_par_err); @@ -386,6 +609,52 @@ int main(int argc, char *argv[]) { pthread_create(&threads[i + 1], NULL, brute_thread, (void *)b); } + // wait for threads to terminate: + for (int i = 0; i < thread_count; ++i) + pthread_join(threads[i], NULL); + + t1 = clock() - t1; + printf("execution time %.0f ticks\n", (float)t1); + + + if (!global_found && !global_found_candidate) { + printf("\nFailed to find a key\n\n"); + goto out; + } + + if (enc_len < 4) { + printf("skipping phase 2\n"); + goto out; + } + + // reset thread signals + __sync_fetch_and_add(&global_found, 0); + __sync_fetch_and_add(&global_found_candidate, 0); + t1 = clock(); + + printf("\n----------- Phase 2 ------------------------\n"); + printf("uid.......... %08x\n", uid); + printf("partial key.. %08x\n", (uint32_t)(global_candiate_key & 0xFFFFFFFF)); + printf("nt enc....... %08x\n", nt_enc); + printf("nr enc....... %08x\n", nr_enc); + printf("next encrypted cmd: %s\n", sprint_hex_inrow_ex(enc, enc_len ,0)); + printf("\nBruteforce using %zu threads to find upper 16 bits of key\n", thread_count); + fflush(stdout); + + // threads + for (int i = 0; i < thread_count; ++i) { + struct thread_key_args *b = malloc(sizeof(struct thread_key_args)); + b->thread = i; + b->idx = i; + b->uid = uid; + b->part_key = (uint32_t)(global_candiate_key & 0xFFFFFFFF); + b->nt_enc = nt_enc; + b->nr_enc = nr_enc; + b->enc_len = enc_len; + memcpy(b->enc, enc, enc_len); + pthread_create(&threads[i], NULL, brute_key_thread, (void *)b); + } + // wait for threads to terminate: for (int i = 0; i < thread_count; ++i) pthread_join(threads[i], NULL); @@ -395,9 +664,9 @@ int main(int argc, char *argv[]) { } t1 = clock() - t1; - if (t1 > 0) - printf("Execution time: %.0f ticks\n", (float)t1); + printf("execution time %.0f ticks\n", (float)t1); +out: // clean up mutex pthread_mutex_destroy(&print_lock); return 0; From c5c689f50fe4f67a15bbb9234d820abeacbe91a2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 11 Mar 2021 09:26:02 +0100 Subject: [PATCH 59/67] data fsktonrz - now uses cliparser --- client/src/cmddata.c | 63 ++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 41 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 82f05bb59..095725b35 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -251,15 +251,7 @@ static int usage_data_buffclear(void) { PrintAndLogEx(NORMAL, " h This help"); return PM3_SUCCESS; } -static int usage_data_fsktonrz(void) { - PrintAndLogEx(NORMAL, "Usage: data fsktonrz c l f "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " c enter the a clock (omit to autodetect)"); - PrintAndLogEx(NORMAL, " l enter a field clock (omit to autodetect)"); - PrintAndLogEx(NORMAL, " f enter a field clock (omit to autodetect)"); - return PM3_SUCCESS; -} + //set the demod buffer with given array of binary (one bit per byte) //by marshmellow @@ -2295,36 +2287,27 @@ static int FSKToNRZ(int *data, size_t *dataLen, uint8_t clk, uint8_t LowToneFC, } static int CmdFSKToNRZ(const char *Cmd) { - // take clk, fc_low, fc_high - // blank = auto; - bool errors = false; - char cmdp = 0; - int clk = 0, fc_low = 10, fc_high = 8; - while (param_getchar(Cmd, cmdp) != 0x00) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_data_fsktonrz(); - case 'c': - clk = param_get32ex(Cmd, cmdp + 1, 0, 10); - cmdp += 2; - break; - case 'f': - fc_high = param_get32ex(Cmd, cmdp + 1, 0, 10); - cmdp += 2; - break; - case 'l': - fc_low = param_get32ex(Cmd, cmdp + 1, 0, 10); - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - if (errors) break; - } - //Validations - if (errors) return usage_data_fsktonrz(); + + CLIParserContext *ctx; + CLIParserInit(&ctx, "data fsktonrz", + "Convert fsk2 to nrz wave for alternate fsk demodulating (for weak fsk)\n" + "Omitted values are autodetect instead", + "data fsktonrz\n" + "data fsktonrz -c 32 --low 8 --hi 10"); + + void *argtable[] = { + arg_param_begin, + arg_int0("c", "clk", "", "clock"), + arg_int0(NULL, "low", "", "low field clock"), + arg_int0(NULL, "hi", "", "high field clock"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int clk = arg_get_int_def(ctx, 1, 0); + int fc_low = arg_get_int_def(ctx, 2, 0); + int fc_high = arg_get_int_def(ctx, 3, 0); + CLIParserFree(ctx); setClockGrid(0, 0); DemodBufferLen = 0; @@ -2567,11 +2550,9 @@ static command_t CommandTable[] = { {"shiftgraphzero", CmdGraphShiftZero, AlwaysAvailable, " -- Shift 0 for Graphed wave + or - shift value"}, {"timescale", CmdTimeScale, AlwaysAvailable, "Set a timescale to get a differential reading between the yellow and purple markers as time duration\n"}, {"zerocrossings", CmdZerocrossings, AlwaysAvailable, "Count time between zero-crossings"}, - {"convertbitstream", CmdConvertBitStream, AlwaysAvailable, "Convert GraphBuffer's 0/1 values to 127 / -127"}, {"getbitstream", CmdGetBitStream, AlwaysAvailable, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"}, - {"-----------", CmdHelp, AlwaysAvailable, "------------------------- " _CYAN_("General") "-------------------------"}, {"bin2hex", Cmdbin2hex, AlwaysAvailable, "Converts binary to hexadecimal"}, {"bitsamples", CmdBitsamples, IfPm3Present, "Get raw samples as bitstring"}, From 40257bdc89ec723363874421df6ca555f3457bf6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 11 Mar 2021 09:38:37 +0100 Subject: [PATCH 60/67] update definitions for cliparser_todo docu --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e42c0caa9..b2dcba430 100644 --- a/Makefile +++ b/Makefile @@ -251,7 +251,7 @@ print-%: ; @echo $* = $($*) cliparser: # Get list of all commands - cat doc/commands.md | grep -e ^\|\` | cut -f 2 -d "\`" | grep -v 'help\|list\|mem spiffs\|quit\|exit' | awk '{$$1=$$1};1' > cliparser_all_commands.tmp + cat doc/commands.md | grep -e ^\|\` | cut -f 2 -d "\`" | grep -v 'help\|list\|script run\|quit\|exit' | awk '{$$1=$$1};1' > cliparser_all_commands.tmp # Get list of cliparserized commands grep -r CLIParserInit ./client/src/ | cut -f 2 -d "\"" | awk '{$$1=$$1};1' > cliparser_done.tmp # Determine commands that still need cliparser conversion From 2bd5831f27d894e383d0b0a1e4b4bbc2bc73f1c8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 11 Mar 2021 09:40:02 +0100 Subject: [PATCH 61/67] text --- armsrc/Standalone/readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/armsrc/Standalone/readme.md b/armsrc/Standalone/readme.md index 3775d848c..69880f1a3 100644 --- a/armsrc/Standalone/readme.md +++ b/armsrc/Standalone/readme.md @@ -77,6 +77,7 @@ If your mode is using one of the unique features of the RDV4, add it to the prop ``` STANDALONE_MODES_REQ_SMARTCARD := STANDALONE_MODES_REQ_FLASH := +STANDALONE_MODES_REQ_BT := ``` ## Update MAKEFILE.INC From aae08929dd93bb1c278b7b91adc24647f3838b6d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 11 Mar 2021 22:45:51 +0100 Subject: [PATCH 62/67] text --- client/src/cmdlf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index 2096c6eb0..c88b4bf36 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -1321,7 +1321,7 @@ static bool CheckChipType(bool getDeviceData) { goto out; } - PrintAndLogEx(NORMAL, "Couldn't identify a chipset"); + PrintAndLogEx(INFO, "Couldn't identify a chipset"); out: save_restoreGB(GRAPH_RESTORE); save_restoreDB(GRAPH_RESTORE); From ae0f98e8b227e57e67a03e0efa22e7892d8fce53 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 12 Mar 2021 13:54:41 +0100 Subject: [PATCH 63/67] trace list -t mf - now gives needed data for mf_nonce_brute to recover the nested authentication key --- client/src/cmdhflist.c | 41 ++++++++++++++++++++++++++++++++++++++--- client/src/cmdhflist.h | 1 + 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhflist.c b/client/src/cmdhflist.c index 6e292ad6f..d4dcb892f 100644 --- a/client/src/cmdhflist.c +++ b/client/src/cmdhflist.c @@ -1290,9 +1290,10 @@ void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8 MifareAuthState = masNrAr; if (AuthData.first_auth) { AuthData.nt = bytes_to_num(cmd, 4); + AuthData.nt_enc_par = 0; } else { AuthData.nt_enc = bytes_to_num(cmd, 4); - AuthData.nt_enc_par = parity[0]; + AuthData.nt_enc_par = parity[0] & 0xF0; } return; } else { @@ -1304,6 +1305,7 @@ void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8 snprintf(exp, size, "AUTH: nr ar (enc)"); MifareAuthState = masAt; AuthData.nr_enc = bytes_to_num(cmd, 4); + AuthData.nr_enc_par = parity[0] & 0xF0; AuthData.ar_enc = bytes_to_num(&cmd[4], 4); AuthData.ar_enc_par = parity[0] << 4; return; @@ -1316,7 +1318,7 @@ void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8 snprintf(exp, size, "AUTH: at (enc)"); MifareAuthState = masAuthComplete; AuthData.at_enc = bytes_to_num(cmd, 4); - AuthData.at_enc_par = parity[0]; + AuthData.at_enc_par = parity[0] & 0xF0; return; } else { MifareAuthState = masError; @@ -1335,6 +1337,17 @@ void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8 } +static void mf_get_paritybinstr(char *s, uint32_t val, uint8_t par) { + uint8_t foo[4] = {0,0,0,0}; + num_to_bytes(val, sizeof(uint32_t), foo); + for (uint8_t i = 0; i < 4; i++) { + if (oddparity8(foo[i]) != ((par >> (7 - (i & 0x0007))) & 0x01)) + sprintf(s++, "1"); + else + sprintf(s++, "0"); + } +} + bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isResponse, uint8_t *mfData, size_t *mfDataLen, const uint64_t *dicKeys, uint32_t dicKeysCount) { static struct Crypto1State *traceCrypto1; @@ -1428,7 +1441,29 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes //hardnested if (!traceCrypto1) { - PrintAndLogEx(NORMAL, "hardnested not implemented. uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc); + + //PrintAndLogEx(NORMAL, "hardnested not implemented. uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc); + + char snt[5] = {0,0,0,0,0}; + mf_get_paritybinstr(snt, AuthData.nt_enc, AuthData.nt_enc_par); + char sar[5] = {0,0,0,0,0}; + mf_get_paritybinstr(sar, AuthData.ar_enc, AuthData.ar_enc_par); + char sat[5] = {0,0,0,0,0}; + mf_get_paritybinstr(sat, AuthData.at_enc, AuthData.at_enc_par); + + PrintAndLogEx(NORMAL, "Nested authentication detected. "); + PrintAndLogEx(NORMAL, "tools/mf_nonce_brute/mf_nonce_brute %x %x %s %x %x %s %x %s %s\n" + , AuthData.uid + , AuthData.nt_enc + , snt + , AuthData.nr_enc + , AuthData.ar_enc + , sar + , AuthData.at_enc + , sat + , sprint_hex_inrow(cmd, cmdsize) + ); + MifareAuthState = masError; /* TOO SLOW( needs to have more strong filter. with this filter - aprox 4 mln tests diff --git a/client/src/cmdhflist.h b/client/src/cmdhflist.h index ff7f7f799..b59c9fca2 100644 --- a/client/src/cmdhflist.h +++ b/client/src/cmdhflist.h @@ -18,6 +18,7 @@ typedef struct { uint32_t nt_enc; // encrypted tag challenge uint8_t nt_enc_par; // encrypted tag challenge parity uint32_t nr_enc; // encrypted reader challenge + uint8_t nr_enc_par; // encrypted reader challenge parity uint32_t ar_enc; // encrypted reader response uint8_t ar_enc_par; // encrypted reader response parity uint32_t at_enc; // encrypted tag response From 692fc94a89c1a83396f6a605a834f4e9a6baa79c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 12 Mar 2021 13:55:02 +0100 Subject: [PATCH 64/67] flush --- client/src/cmdlf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index c88b4bf36..65f0386c9 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -768,6 +768,7 @@ int lfsim_upload_gb(void) { break; } PrintAndLogEx(NORMAL, "." NOLF); + fflush(stdout); payload_up.flag = 0; } PrintAndLogEx(NORMAL, ""); From 0ca5fcef1c8190ac310d0b7306bf65896f2aa1e8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 12 Mar 2021 20:41:19 +0100 Subject: [PATCH 65/67] if weak prng key found, no need for phase2 --- tools/mf_nonce_brute/mf_nonce_brute.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/mf_nonce_brute/mf_nonce_brute.c b/tools/mf_nonce_brute/mf_nonce_brute.c index 2bd500c90..d862607b2 100644 --- a/tools/mf_nonce_brute/mf_nonce_brute.c +++ b/tools/mf_nonce_brute/mf_nonce_brute.c @@ -614,7 +614,7 @@ int main(int argc, char *argv[]) { pthread_join(threads[i], NULL); t1 = clock() - t1; - printf("execution time %.0f ticks\n", (float)t1); + printf("execution time %.2f sec\n", (float)t1 / 1000000.0); if (!global_found && !global_found_candidate) { @@ -622,15 +622,18 @@ int main(int argc, char *argv[]) { goto out; } + if (global_found) { + goto out; + } + if (enc_len < 4) { - printf("skipping phase 2\n"); + printf("Too few next cmd bytes, skipping phase 2\n"); goto out; } // reset thread signals __sync_fetch_and_add(&global_found, 0); __sync_fetch_and_add(&global_found_candidate, 0); - t1 = clock(); printf("\n----------- Phase 2 ------------------------\n"); printf("uid.......... %08x\n", uid); @@ -663,9 +666,6 @@ int main(int argc, char *argv[]) { printf("\nFailed to find a key\n\n"); } - t1 = clock() - t1; - printf("execution time %.0f ticks\n", (float)t1); - out: // clean up mutex pthread_mutex_destroy(&print_lock); From 134bcd5e3e3a252fc376fb847d13fe4af3cbd679 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 12 Mar 2021 20:52:22 +0100 Subject: [PATCH 66/67] colors --- tools/mf_nonce_brute/mf_nonce_brute.c | 47 +++++++++++++++------------ 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/tools/mf_nonce_brute/mf_nonce_brute.c b/tools/mf_nonce_brute/mf_nonce_brute.c index d862607b2..23e369793 100644 --- a/tools/mf_nonce_brute/mf_nonce_brute.c +++ b/tools/mf_nonce_brute/mf_nonce_brute.c @@ -19,6 +19,12 @@ #include "protocol.h" #include "iso14443crc.h" +#define AEND "\x1b[0m" +#define _RED_(s) "\x1b[31m" s AEND +#define _GREEN_(s) "\x1b[32m" s AEND +#define _YELLOW_(s) "\x1b[33m" s AEND +#define _CYAN_(s) "\x1b[36m" s AEND + #define odd_parity(i) (( (i) ^ (i)>>1 ^ (i)>>2 ^ (i)>>3 ^ (i)>>4 ^ (i)>>5 ^ (i)>>6 ^ (i)>>7 ^ 1) & 0x01) // a global mutex to prevent interlaced printing from different threads @@ -412,8 +418,8 @@ static void *brute_thread(void *arguments) { #endif if (cmd_enc) { uint32_t decrypted = ks4 ^ cmd_enc; - printf("CMD enc(%08x)\n", cmd_enc); - printf(" dec(%08x)\t", decrypted); + printf("CMD enc( %08x )\n", cmd_enc); + printf(" dec( %08x ) ", decrypted); // check if cmd exists uint8_t isOK = checkValidCmd(decrypted); @@ -422,12 +428,12 @@ static void *brute_thread(void *arguments) { // Add a crc-check. isOK = checkCRC(decrypted); if (isOK == false) { - printf("<-- not a valid cmd\n"); + printf(_RED_("<-- not a valid cmd\n")); pthread_mutex_unlock(&print_lock); free(revstate); continue; } else { - printf("<-- Valid cmd\n"); + printf("<-- valid cmd\n"); } } @@ -440,11 +446,11 @@ static void *brute_thread(void *arguments) { free(revstate); if (args->ev1) { - printf("\nKey candidate [ %012" PRIx64 " ]\n\n", key); + printf("\nKey candidate [ " _YELLOW_("%012" PRIx64 )" ]\n\n", key); __sync_fetch_and_add(&global_found_candidate, 1); __sync_fetch_and_add(&global_candiate_key, key); } else { - printf("\nValid Key found [ %012" PRIx64 " ]\n\n", key); + printf("\nValid Key found [ " _GREEN_("%012" PRIx64) " ]\n\n", key); __sync_fetch_and_add(&global_found, 1); __sync_fetch_and_add(&global_candiate_key, key); } @@ -503,7 +509,7 @@ static void *brute_key_thread(void *arguments) { pthread_mutex_lock(&print_lock); printf("\nenc: %s\n", sprint_hex_inrow_ex(local_enc, args->enc_len, 0)); printf("dec: %s\n", sprint_hex_inrow_ex(dec, args->enc_len, 0)); - printf("\nValid Key found [ %012" PRIx64 " ]\n\n", key); + printf("\nValid Key found [ " _GREEN_("%012" PRIx64) " ]\n\n", key); pthread_mutex_unlock(&print_lock); __sync_fetch_and_add(&global_found, 1); } @@ -555,19 +561,18 @@ int main(int argc, char *argv[]) { cmd_enc = (enc[0] << 24 | enc[1] << 16 | enc[2] << 8 | enc[3]); } - printf("----------- Phase 1 ------------------------\n"); - printf("uid............. %08x\n", uid); - printf("nt encrypted.... %08x\n", nt_enc); - printf("nt parity err... %04x\n", nt_par_err); - printf("nr encrypted.... %08x\n", nr_enc); - printf("ar encrypted.... %08x\n", ar_enc); - printf("ar parity err... %04x\n", ar_par_err); - printf("at encrypted.... %08x\n", at_enc); - printf("at parity err... %04x\n", at_par_err); + printf("----------- " _CYAN_("Phase 1") " ------------------------\n"); + printf("uid.................. %08x\n", uid); + printf("nt encrypted......... %08x\n", nt_enc); + printf("nt parity err........ %04x\n", nt_par_err); + printf("nr encrypted......... %08x\n", nr_enc); + printf("ar encrypted......... %08x\n", ar_enc); + printf("ar parity err........ %04x\n", ar_par_err); + printf("at encrypted......... %08x\n", at_enc); + printf("at parity err........ %04x\n", at_par_err); if (argc > 9) { -// printf("next cmd enc:\t%08x\n\n", cmd_enc); - printf("next encrypted cmd: %s\n", sprint_hex_inrow_ex(enc, enc_len ,0)); + printf("next encrypted cmd... %s\n", sprint_hex_inrow_ex(enc, enc_len ,0)); } clock_t t1 = clock(); @@ -584,7 +589,7 @@ int main(int argc, char *argv[]) { thread_count = 2; #endif /* _WIN32 */ - printf("\nBruteforce using %zu threads to find encrypted tagnonce last bytes\n", thread_count); + printf("\nBruteforce using " _YELLOW_("%zu") " threads to find encrypted tagnonce last bytes\n", thread_count); pthread_t threads[thread_count]; @@ -635,13 +640,13 @@ int main(int argc, char *argv[]) { __sync_fetch_and_add(&global_found, 0); __sync_fetch_and_add(&global_found_candidate, 0); - printf("\n----------- Phase 2 ------------------------\n"); + printf("\n----------- " _CYAN_("Phase 2") " ------------------------\n"); printf("uid.......... %08x\n", uid); printf("partial key.. %08x\n", (uint32_t)(global_candiate_key & 0xFFFFFFFF)); printf("nt enc....... %08x\n", nt_enc); printf("nr enc....... %08x\n", nr_enc); printf("next encrypted cmd: %s\n", sprint_hex_inrow_ex(enc, enc_len ,0)); - printf("\nBruteforce using %zu threads to find upper 16 bits of key\n", thread_count); + printf("\nStart bruteforce to find upper 16 bits of key\n"); fflush(stdout); // threads From 5acff2f88eeb1ac0c524b5c786a8704748b4a41c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 12 Mar 2021 21:45:34 +0100 Subject: [PATCH 67/67] fixed some concurrency problems, changed some output --- tools/mf_nonce_brute/mf_nonce_brute.c | 39 ++++++++++----------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/tools/mf_nonce_brute/mf_nonce_brute.c b/tools/mf_nonce_brute/mf_nonce_brute.c index 23e369793..631976c15 100644 --- a/tools/mf_nonce_brute/mf_nonce_brute.c +++ b/tools/mf_nonce_brute/mf_nonce_brute.c @@ -75,7 +75,6 @@ uint8_t cmds[8][2] = { }; int global_counter = 0; -int global_fin_flag = 0; int global_found = 0; int global_found_candidate = 0; uint64_t global_candiate_key = 0; @@ -380,14 +379,12 @@ static void *brute_thread(void *arguments) { uint32_t p64 = 0; uint32_t count; - int found = 0; // TC == 4 ( // threads calls 0 ev1 == false // threads calls 0,1,2 ev1 == true for (count = args->idx; count < 0xFFFF; count += thread_count - 1) { - found = global_found; - if (found) { + if (__atomic_load_n(&global_found, __ATOMIC_ACQUIRE) == 1) { break; } @@ -446,16 +443,17 @@ static void *brute_thread(void *arguments) { free(revstate); if (args->ev1) { - printf("\nKey candidate [ " _YELLOW_("%012" PRIx64 )" ]\n\n", key); + // if it was EV1, we know for sure xxxAAAAAAAA recovery + printf("\nKey candidate [ " _YELLOW_("....%08" PRIx64 )" ]\n\n", key & 0xFFFFFFFF); __sync_fetch_and_add(&global_found_candidate, 1); - __sync_fetch_and_add(&global_candiate_key, key); } else { - printf("\nValid Key found [ " _GREEN_("%012" PRIx64) " ]\n\n", key); + printf("\nKey candidate [ " _GREEN_("....%08" PRIx64) " ]\n\n", key & 0xFFFFFFFF); __sync_fetch_and_add(&global_found, 1); - __sync_fetch_and_add(&global_candiate_key, key); } + __sync_fetch_and_add(&global_candiate_key, key); //release lock pthread_mutex_unlock(&print_lock); + break; } } free(args); @@ -465,26 +463,20 @@ static void *brute_thread(void *arguments) { static void *brute_key_thread(void *arguments) { struct thread_key_args *args = (struct thread_key_args *) arguments; - - uint64_t key; // recovered key candidate - int found = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs = &mpcs; - + uint64_t key; uint8_t local_enc[args->enc_len]; memcpy(local_enc, args->enc, args->enc_len); for (uint64_t count = args->idx; count < 0xFFFF; count += thread_count) { - found = global_found; - if (found) { + if (__atomic_load_n(&global_found, __ATOMIC_ACQUIRE) == 1) { break; } key = (count << 32 | args->part_key); // Init cipher with key - pcs = crypto1_create(key); + struct Crypto1State *pcs = crypto1_create(key); // NESTED decrypt nt with help of new key crypto1_word(pcs, args->nt_enc ^ args->uid, 1); @@ -504,7 +496,7 @@ static void *brute_key_thread(void *arguments) { if (isOK == false) { continue; } - + // lock this section to avoid interlacing prints from different threats pthread_mutex_lock(&print_lock); printf("\nenc: %s\n", sprint_hex_inrow_ex(local_enc, args->enc_len, 0)); @@ -512,6 +504,7 @@ static void *brute_key_thread(void *arguments) { printf("\nValid Key found [ " _GREEN_("%012" PRIx64) " ]\n\n", key); pthread_mutex_unlock(&print_lock); __sync_fetch_and_add(&global_found, 1); + break; } free(args); return NULL; @@ -572,7 +565,7 @@ int main(int argc, char *argv[]) { printf("at parity err........ %04x\n", at_par_err); if (argc > 9) { - printf("next encrypted cmd... %s\n", sprint_hex_inrow_ex(enc, enc_len ,0)); + printf("next encrypted cmd... %s\n", sprint_hex_inrow_ex(enc, enc_len ,0)); } clock_t t1 = clock(); @@ -627,18 +620,14 @@ int main(int argc, char *argv[]) { goto out; } - if (global_found) { - goto out; - } - if (enc_len < 4) { printf("Too few next cmd bytes, skipping phase 2\n"); goto out; } // reset thread signals - __sync_fetch_and_add(&global_found, 0); - __sync_fetch_and_add(&global_found_candidate, 0); + global_found = 0; + global_found_candidate = 0; printf("\n----------- " _CYAN_("Phase 2") " ------------------------\n"); printf("uid.......... %08x\n", uid);