From 5633768e810ca38305968e4875aeaf60f60a4ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Jen=C5=A1terle?= Date: Fri, 5 Mar 2021 10:58:52 +0100 Subject: [PATCH 001/373] desfire emulation standalone --- armsrc/Standalone/Makefile.hal | 5 +- armsrc/Standalone/Makefile.inc | 4 ++ armsrc/Standalone/hf_emuldes.c | 111 +++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 armsrc/Standalone/hf_emuldes.c diff --git a/armsrc/Standalone/Makefile.hal b/armsrc/Standalone/Makefile.hal index 552267611..3c0420f2d 100644 --- a/armsrc/Standalone/Makefile.hal +++ b/armsrc/Standalone/Makefile.hal @@ -50,6 +50,9 @@ define KNOWN_STANDALONE_DEFINITIONS | HF_COLIN | Mifare ultra fast sniff/sim/clone | | (RDV4 only) | - Colin Brigato | +----------------------------------------------------------+ +| HF_EMULDES | DESfire 14a simulation | +| | - Anze Jensterle | ++----------------------------------------------------------+ | HF_ICECLASS | Simulate HID iCLASS legacy ags | | (RDV4 only) | storing in flashmem | +----------------------------------------------------------+ @@ -71,7 +74,7 @@ define KNOWN_STANDALONE_DEFINITIONS endef STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RWC LF_HIDBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE -STANDALONE_MODES += HF_14ASNIFF HF_AVEFUL HF_BOG HF_COLIN HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_TCPRST HF_YOUNG +STANDALONE_MODES += HF_14ASNIFF HF_AVEFUL HF_BOG HF_COLIN HF_EMULDES HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_TCPRST HF_YOUNG STANDALONE_MODES_REQ_SMARTCARD := STANDALONE_MODES_REQ_FLASH := LF_ICEHID LF_THAREXDE HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),) diff --git a/armsrc/Standalone/Makefile.inc b/armsrc/Standalone/Makefile.inc index 519dc2087..bda3b2719 100644 --- a/armsrc/Standalone/Makefile.inc +++ b/armsrc/Standalone/Makefile.inc @@ -77,3 +77,7 @@ endif ifneq (,$(findstring WITH_STANDALONE_LF_THAREXDE,$(APP_CFLAGS))) SRC_STANDALONE = lf_tharexde.c endif +# WITH_STANDALONE_HF_EMULDES +ifneq (,$(findstring WITH_STANDALONE_HF_EMULDES,$(APP_CFLAGS))) + SRC_STANDALONE = hf_emuldes.c +endif \ No newline at end of file diff --git a/armsrc/Standalone/hf_emuldes.c b/armsrc/Standalone/hf_emuldes.c new file mode 100644 index 000000000..20a64bf00 --- /dev/null +++ b/armsrc/Standalone/hf_emuldes.c @@ -0,0 +1,111 @@ +//----------------------------------------------------------------------------- +// Copyright 2020 Anze Jensterle +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// main code for standalone HF/iso14a emulator +//----------------------------------------------------------------------------- + +/* + * `hf_basicbreak` scans a card + */ + +#include "standalone.h" +#include "proxmark3_arm.h" +#include "appmain.h" +#include "fpgaloader.h" +#include "util.h" +#include "dbprint.h" +#include "ticks.h" +#include "string.h" +#include "BigBuf.h" +#include "iso14443a.h" +#include "protocols.h" +#include "cmd.h" + +#define STATE_READ 0 +#define STATE_EMUL 1 + +typedef struct { + uint8_t uid[10]; + uint8_t uidlen; + uint8_t atqa[2]; + uint8_t sak; +} PACKED card_clone_t; + +void ModInfo(void) { + DbpString("hf_emuldes: standalone DESfire that scans a card and then emulates UID, SAK and ATQA"); +} + +void RunMod(void) { + StandAloneMode(); + Dbprintf("HF DESfire emulator started"); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + + // the main loop for your standalone mode + for (;;) { + WDT_HIT(); + + // exit from RunMod, send a usbcommand. + if (data_available()) break; + + iso14a_card_select_t card; + card_clone_t clone; + + SpinDelay(500); + + // 0 = search, 1 = read, 2 = emul + int state = STATE_READ; + + DbpString("Scanning..."); + int button_pressed = BUTTON_NO_CLICK; + for (;;) { + // Was our button held down or pressed? + button_pressed = BUTTON_HELD(1000); + + if (button_pressed != BUTTON_NO_CLICK || data_available()) + break; + else if (state == STATE_READ) { + iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); + if (!iso14443a_select_card(NULL, &card, NULL, true, 0, true)) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); + SpinDelay(500); + continue; + } else { + Dbprintf("Found card with SAQ: %02X, ATQA: %02X %02X, UID: ", card.sak, card.atqa[0], card.atqa[1]); + Dbhexdump(card.uidlen, card.uid, 0); + clone.uidlen = card.uidlen; + clone.sak = card.sak; + clone.atqa[0] = card.atqa[0]; + clone.atqa[1] = card.atqa[1]; + memcpy(clone.uid, card.uid, card.uidlen); + state = STATE_EMUL; + } + } else if (state == STATE_EMUL) { + uint8_t flags; + if (clone.uidlen == 4) flags |= FLAG_4B_UID_IN_DATA; + else if (clone.uidlen == 7) flags |= FLAG_7B_UID_IN_DATA; + else if (clone.uidlen == 10) flags |= FLAG_10B_UID_IN_DATA; + else { + Dbprintf("Unusual UID length, something is wrong. Try again please."); + state = STATE_READ; + continue; + } + + Dbprintf("Starting simulation, press pm3-button to stop and go back to search state."); + SimulateIso14443aTag(3, flags, card.uid, 0); + + // Go back to search state if user presses pm3-button + state = STATE_READ; + } + } + if (button_pressed == BUTTON_HOLD) //Holding down the button + break; + } + + DbpString("exiting"); + LEDsoff(); +} 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 002/373] 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 003/373] 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 004/373] 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 005/373] 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 006/373] 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 007/373] 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 008/373] 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 009/373] 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 010/373] 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 011/373] 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 012/373] 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 013/373] 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 014/373] 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 015/373] 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 016/373] 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 017/373] 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 018/373] 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 019/373] 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 020/373] 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 021/373] 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 022/373] 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 023/373] 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 024/373] 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 025/373] 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 026/373] 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 027/373] 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 028/373] 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 029/373] 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 030/373] 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 031/373] 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 032/373] 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 033/373] 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 034/373] 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 035/373] 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 036/373] 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 037/373] 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 038/373] 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 039/373] 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 040/373] 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 041/373] 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 042/373] 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); From ac36c0659020c5458d6c7f917724539811d41c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Jen=C5=A1terle?= Date: Mon, 15 Mar 2021 00:33:27 +0100 Subject: [PATCH 043/373] rename standalone --- armsrc/Standalone/Makefile.hal | 4 ++-- armsrc/Standalone/Makefile.inc | 6 +++--- armsrc/Standalone/{hf_emuldes.c => hf_craftbyte.c} | 0 3 files changed, 5 insertions(+), 5 deletions(-) rename armsrc/Standalone/{hf_emuldes.c => hf_craftbyte.c} (100%) diff --git a/armsrc/Standalone/Makefile.hal b/armsrc/Standalone/Makefile.hal index 3c0420f2d..78d65cbd7 100644 --- a/armsrc/Standalone/Makefile.hal +++ b/armsrc/Standalone/Makefile.hal @@ -50,7 +50,7 @@ define KNOWN_STANDALONE_DEFINITIONS | HF_COLIN | Mifare ultra fast sniff/sim/clone | | (RDV4 only) | - Colin Brigato | +----------------------------------------------------------+ -| HF_EMULDES | DESfire 14a simulation | +| HF_CRAFTBYTE | UID stealer | | | - Anze Jensterle | +----------------------------------------------------------+ | HF_ICECLASS | Simulate HID iCLASS legacy ags | @@ -74,7 +74,7 @@ define KNOWN_STANDALONE_DEFINITIONS endef STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RWC LF_HIDBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN LF_THAREXDE -STANDALONE_MODES += HF_14ASNIFF HF_AVEFUL HF_BOG HF_COLIN HF_EMULDES HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_TCPRST HF_YOUNG +STANDALONE_MODES += HF_14ASNIFF HF_AVEFUL HF_BOG HF_COLIN HF_CRAFTBYTE HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_TCPRST HF_YOUNG STANDALONE_MODES_REQ_SMARTCARD := STANDALONE_MODES_REQ_FLASH := LF_ICEHID LF_THAREXDE HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),) diff --git a/armsrc/Standalone/Makefile.inc b/armsrc/Standalone/Makefile.inc index bda3b2719..b24ac2f4f 100644 --- a/armsrc/Standalone/Makefile.inc +++ b/armsrc/Standalone/Makefile.inc @@ -77,7 +77,7 @@ endif ifneq (,$(findstring WITH_STANDALONE_LF_THAREXDE,$(APP_CFLAGS))) SRC_STANDALONE = lf_tharexde.c endif -# WITH_STANDALONE_HF_EMULDES -ifneq (,$(findstring WITH_STANDALONE_HF_EMULDES,$(APP_CFLAGS))) - SRC_STANDALONE = hf_emuldes.c +# WITH_STANDALONE_HF_CRAFTBYTE +ifneq (,$(findstring HF_CRAFTBYTE,$(APP_CFLAGS))) + SRC_STANDALONE = hf_craftbyte.c endif \ No newline at end of file diff --git a/armsrc/Standalone/hf_emuldes.c b/armsrc/Standalone/hf_craftbyte.c similarity index 100% rename from armsrc/Standalone/hf_emuldes.c rename to armsrc/Standalone/hf_craftbyte.c From fb34db5e1076cca5e0d992a601df974c6937d1d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Jen=C5=A1terle?= Date: Mon, 15 Mar 2021 00:36:46 +0100 Subject: [PATCH 044/373] Finish renaming standalone, add documentation --- CHANGELOG.md | 1 + armsrc/Standalone/Makefile.inc | 2 +- doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bced7ef1a..00077e5d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added HF_CRAFTBYTE standalone mode that reads and emulates 14a UID (@craftbyte) - Added a script to dump originality signatures from MFU EV1s and NTAGs (@aveao) - Added parsing of EF_CardAccess to display PACE algorithm, version and parameter in `hf emrtd info` (@aveao) - Change, numerous commands more uses cliparser (@tcprst, @iceman1001) diff --git a/armsrc/Standalone/Makefile.inc b/armsrc/Standalone/Makefile.inc index b24ac2f4f..d018ee927 100644 --- a/armsrc/Standalone/Makefile.inc +++ b/armsrc/Standalone/Makefile.inc @@ -78,6 +78,6 @@ ifneq (,$(findstring WITH_STANDALONE_LF_THAREXDE,$(APP_CFLAGS))) SRC_STANDALONE = lf_tharexde.c endif # WITH_STANDALONE_HF_CRAFTBYTE -ifneq (,$(findstring HF_CRAFTBYTE,$(APP_CFLAGS))) +ifneq (,$(findstring WITH_STANDALONE_HF_CRAFTBYTE,$(APP_CFLAGS))) SRC_STANDALONE = hf_craftbyte.c endif \ No newline at end of file diff --git a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md index 2ba6aeaba..0b17be23e 100644 --- a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md +++ b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md @@ -90,6 +90,7 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo | HF_14ASNIFF | 14a sniff storing to flashmem - Micolous | HF_AVEFUL | MIFARE Ultralight read/simulation - Ave Ozkal | HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth storing in flashmem - Bogito +| HF_CRAFTBYTE | UID Stealer - Anze Jensterle | HF_COLIN | Mifare ultra fast sniff/sim/clone - Colin Brigato | HF_ICECLASS | iCLASS 4-1 mode sim/read & dump/loclass/glitch & config to flashmem - Iceman1001 | HF_LEGIC | HF Legic Prime standalone - uhei From 73dd5a23e4e2633b8444e77c420355bd7875b793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Jen=C5=A1terle?= Date: Mon, 15 Mar 2021 00:55:25 +0100 Subject: [PATCH 045/373] fixed help for standalone --- armsrc/Standalone/Makefile.hal | 2 +- armsrc/Standalone/hf_craftbyte.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/Standalone/Makefile.hal b/armsrc/Standalone/Makefile.hal index 78d65cbd7..b0e343b0b 100644 --- a/armsrc/Standalone/Makefile.hal +++ b/armsrc/Standalone/Makefile.hal @@ -50,7 +50,7 @@ define KNOWN_STANDALONE_DEFINITIONS | HF_COLIN | Mifare ultra fast sniff/sim/clone | | (RDV4 only) | - Colin Brigato | +----------------------------------------------------------+ -| HF_CRAFTBYTE | UID stealer | +| HF_CRAFTBYTE | UID stealer - Emulates scanned 14a UID | | | - Anze Jensterle | +----------------------------------------------------------+ | HF_ICECLASS | Simulate HID iCLASS legacy ags | diff --git a/armsrc/Standalone/hf_craftbyte.c b/armsrc/Standalone/hf_craftbyte.c index 20a64bf00..d2f1eda94 100644 --- a/armsrc/Standalone/hf_craftbyte.c +++ b/armsrc/Standalone/hf_craftbyte.c @@ -36,7 +36,7 @@ typedef struct { } PACKED card_clone_t; void ModInfo(void) { - DbpString("hf_emuldes: standalone DESfire that scans a card and then emulates UID, SAK and ATQA"); + DbpString("hf_craftbyte: standalone DESfire that scans a card and then emulates UID, SAK and ATQA"); } void RunMod(void) { From 9a33e547f3865246ff7034a7338a15e4aa60d4dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Jen=C5=A1terle?= Date: Mon, 15 Mar 2021 00:58:38 +0100 Subject: [PATCH 046/373] more renaming and explaining --- armsrc/Standalone/hf_craftbyte.c | 4 ++-- doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/armsrc/Standalone/hf_craftbyte.c b/armsrc/Standalone/hf_craftbyte.c index d2f1eda94..dd4f54345 100644 --- a/armsrc/Standalone/hf_craftbyte.c +++ b/armsrc/Standalone/hf_craftbyte.c @@ -36,12 +36,12 @@ typedef struct { } PACKED card_clone_t; void ModInfo(void) { - DbpString("hf_craftbyte: standalone DESfire that scans a card and then emulates UID, SAK and ATQA"); + DbpString("hf_craftbyte: standalone UID Stealer - Scans and emulates 14a UID"); } void RunMod(void) { StandAloneMode(); - Dbprintf("HF DESfire emulator started"); + Dbprintf("HF UID emulator started"); FpgaDownloadAndGo(FPGA_BITSTREAM_HF); // the main loop for your standalone mode diff --git a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md index 0b17be23e..8f49e0b15 100644 --- a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md +++ b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md @@ -90,7 +90,7 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo | HF_14ASNIFF | 14a sniff storing to flashmem - Micolous | HF_AVEFUL | MIFARE Ultralight read/simulation - Ave Ozkal | HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth storing in flashmem - Bogito -| HF_CRAFTBYTE | UID Stealer - Anze Jensterle +| HF_CRAFTBYTE | UID stealer - Emulates scanned 14a UID - Anze Jensterle | HF_COLIN | Mifare ultra fast sniff/sim/clone - Colin Brigato | HF_ICECLASS | iCLASS 4-1 mode sim/read & dump/loclass/glitch & config to flashmem - Iceman1001 | HF_LEGIC | HF Legic Prime standalone - uhei From 85ab3650e39db70bc130a8cd70f4aa4c9d3f9350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Jen=C5=A1terle?= Date: Mon, 15 Mar 2021 01:08:11 +0100 Subject: [PATCH 047/373] fixed as per feedback --- armsrc/Standalone/Makefile.inc | 2 +- armsrc/Standalone/hf_craftbyte.c | 14 ++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/armsrc/Standalone/Makefile.inc b/armsrc/Standalone/Makefile.inc index d018ee927..2d77c7c03 100644 --- a/armsrc/Standalone/Makefile.inc +++ b/armsrc/Standalone/Makefile.inc @@ -80,4 +80,4 @@ endif # WITH_STANDALONE_HF_CRAFTBYTE ifneq (,$(findstring WITH_STANDALONE_HF_CRAFTBYTE,$(APP_CFLAGS))) SRC_STANDALONE = hf_craftbyte.c -endif \ No newline at end of file +endif diff --git a/armsrc/Standalone/hf_craftbyte.c b/armsrc/Standalone/hf_craftbyte.c index dd4f54345..eb3d7387a 100644 --- a/armsrc/Standalone/hf_craftbyte.c +++ b/armsrc/Standalone/hf_craftbyte.c @@ -9,7 +9,7 @@ //----------------------------------------------------------------------------- /* - * `hf_basicbreak` scans a card + * `hf_craftyte` scans a card's UID and then emulates it in 14a */ #include "standalone.h" @@ -52,7 +52,6 @@ void RunMod(void) { if (data_available()) break; iso14a_card_select_t card; - card_clone_t clone; SpinDelay(500); @@ -77,18 +76,13 @@ void RunMod(void) { } else { Dbprintf("Found card with SAQ: %02X, ATQA: %02X %02X, UID: ", card.sak, card.atqa[0], card.atqa[1]); Dbhexdump(card.uidlen, card.uid, 0); - clone.uidlen = card.uidlen; - clone.sak = card.sak; - clone.atqa[0] = card.atqa[0]; - clone.atqa[1] = card.atqa[1]; - memcpy(clone.uid, card.uid, card.uidlen); state = STATE_EMUL; } } else if (state == STATE_EMUL) { uint8_t flags; - if (clone.uidlen == 4) flags |= FLAG_4B_UID_IN_DATA; - else if (clone.uidlen == 7) flags |= FLAG_7B_UID_IN_DATA; - else if (clone.uidlen == 10) flags |= FLAG_10B_UID_IN_DATA; + if (card.uidlen == 4) flags |= FLAG_4B_UID_IN_DATA; + else if (card.uidlen == 7) flags |= FLAG_7B_UID_IN_DATA; + else if (card.uidlen == 10) flags |= FLAG_10B_UID_IN_DATA; else { Dbprintf("Unusual UID length, something is wrong. Try again please."); state = STATE_READ; From 2de475bdd91016c64a1fea2827c3d6667d77f1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Jen=C5=A1terle?= Date: Mon, 15 Mar 2021 01:21:30 +0100 Subject: [PATCH 048/373] q to k --- armsrc/Standalone/hf_craftbyte.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/Standalone/hf_craftbyte.c b/armsrc/Standalone/hf_craftbyte.c index eb3d7387a..5a20cab91 100644 --- a/armsrc/Standalone/hf_craftbyte.c +++ b/armsrc/Standalone/hf_craftbyte.c @@ -74,7 +74,7 @@ void RunMod(void) { SpinDelay(500); continue; } else { - Dbprintf("Found card with SAQ: %02X, ATQA: %02X %02X, UID: ", card.sak, card.atqa[0], card.atqa[1]); + Dbprintf("Found card with SAK: %02X, ATQA: %02X %02X, UID: ", card.sak, card.atqa[0], card.atqa[1]); Dbhexdump(card.uidlen, card.uid, 0); state = STATE_EMUL; } From bc4a5cf4dea6c527a8b2e5d3afa6e6dc3f8e054c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 15 Mar 2021 01:26:55 +0100 Subject: [PATCH 049/373] hf mf sim - testing to remove the field detection, its inside emcmd anyway --- armsrc/mifaresim.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index bba3132a7..6018f6b30 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -452,7 +452,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 uint8_t uid_len = 0; // 4,7, 10 uint32_t cuid = 0; - int vHf = 0; // in mV +// int vHf = 0; // in mV uint32_t selTimer = 0; uint32_t authTimer = 0; @@ -535,7 +535,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 WDT_HIT(); - if (counter == 1000) { + if (counter == 3000) { if (data_available()) { Dbprintf("----------- " _GREEN_("BREAKING") " ----------"); break; @@ -545,6 +545,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 counter++; } +/* // find reader field if (cardSTATE == MFEMUL_NOFIELD) { @@ -561,6 +562,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 button_pushed = BUTTON_PRESS(); continue; } + */ FpgaEnableTracing(); //Now, get data From 0851f3d947356568d1408ee318d8161200f92e9f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 15 Mar 2021 01:27:35 +0100 Subject: [PATCH 050/373] only 10bits available --- armsrc/iso14443a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 1509cc80c..cd64bae36 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2006,7 +2006,7 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) { analogCnt++; - analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF_RDV40]; + analogAVG += (AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF_RDV40] & 0x3FF); AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; @@ -2034,7 +2034,7 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) { analogCnt++; - analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF]; + analogAVG += (AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF] & 0x3FF); AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; From 7df6be9abd7f35c07484d719d5ff073eb1735598 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 15 Mar 2021 01:28:20 +0100 Subject: [PATCH 051/373] mf_nonce_brute - text --- tools/mf_nonce_brute/mf_nonce_brute.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/mf_nonce_brute/mf_nonce_brute.c b/tools/mf_nonce_brute/mf_nonce_brute.c index 631976c15..089d9e6ac 100644 --- a/tools/mf_nonce_brute/mf_nonce_brute.c +++ b/tools/mf_nonce_brute/mf_nonce_brute.c @@ -582,7 +582,8 @@ int main(int argc, char *argv[]) { thread_count = 2; #endif /* _WIN32 */ - printf("\nBruteforce using " _YELLOW_("%zu") " threads to find encrypted tagnonce last bytes\n", thread_count); + printf("\nBruteforce using " _YELLOW_("%zu") " threads\n", thread_count); + printf("looking for the last bytes of the encrypted tagnonce\n"); pthread_t threads[thread_count]; @@ -635,7 +636,7 @@ int main(int argc, char *argv[]) { 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("\nStart bruteforce to find upper 16 bits of key\n"); + printf("\nlooking for the upper 16 bits of key\n"); fflush(stdout); // threads @@ -657,7 +658,7 @@ int main(int argc, char *argv[]) { pthread_join(threads[i], NULL); if (!global_found && !global_found_candidate) { - printf("\nFailed to find a key\n\n"); + printf("\nfailed to find a key\n\n"); } out: From e425fba4aa62fb11b749043669d2973aa4077ef3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 15 Mar 2021 01:29:03 +0100 Subject: [PATCH 052/373] add new command "hw break" - to break out softwarewise from loops --- client/src/cmdhw.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/client/src/cmdhw.c b/client/src/cmdhw.c index 8bd691e25..49fe3cc9c 100644 --- a/client/src/cmdhw.c +++ b/client/src/cmdhw.c @@ -851,9 +851,30 @@ static int CmdConnect(const char *Cmd) { return PM3_SUCCESS; } +static int CmdBreak(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hw break", + "send break loop package", + "hw break\n" + ); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + clearCommandBuffer(); + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + return PM3_SUCCESS; +} + + static command_t CommandTable[] = { {"-------------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("Hardware") " -----------------------"}, {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"break", CmdBreak, IfPm3Present, "Send break loop usb command"}, {"connect", CmdConnect, AlwaysAvailable, "Connect Proxmark3 to serial port"}, {"dbg", CmdDbg, IfPm3Present, "Set Proxmark3 debug level"}, {"detectreader", CmdDetectReader, IfPm3Present, "Detect external reader field"}, From f70a49e894d1bd686910eff374563ce74818751b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 15 Mar 2021 01:29:48 +0100 Subject: [PATCH 053/373] lf simulate - less checks --- armsrc/lfops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 9555e59c1..1cfb68326 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -874,8 +874,8 @@ void SimulateTagLowFrequencyEx(int period, int gap, bool ledcontrol, int numcycl //wait until SSC_CLK goes LOW while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) { WDT_HIT(); - if (check == 1000) { - if (data_available() || BUTTON_PRESS()) + if (check == 2000) { + if (BUTTON_PRESS() || data_available()) goto OUT; check = 0; } From bb0577f97882c6ea7e41d872643626386f173ced Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 15 Mar 2021 01:31:36 +0100 Subject: [PATCH 054/373] minor --- armsrc/appmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 77af73cb2..75d74c9da 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -940,7 +940,7 @@ static void PacketReceived(PacketCommandNG *packet) { } PACKED; struct p *payload = (struct p *)packet->data.asBytes; // length, start gap, led control - SimulateTagLowFrequency(payload->len, payload->gap, 1); + SimulateTagLowFrequency(payload->len, payload->gap, true); reply_ng(CMD_LF_SIMULATE, PM3_EOPABORTED, NULL, 0); LED_A_OFF(); break; From 93ff66375576cd15ce5b65064894817c18bfd378 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 15 Mar 2021 15:53:37 +0100 Subject: [PATCH 055/373] text --- armsrc/Standalone/hf_14asniff.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/armsrc/Standalone/hf_14asniff.c b/armsrc/Standalone/hf_14asniff.c index 0a6b48b48..56a7c0cab 100644 --- a/armsrc/Standalone/hf_14asniff.c +++ b/armsrc/Standalone/hf_14asniff.c @@ -77,14 +77,14 @@ static void DownloadTraceInstructions(void) { } void ModInfo(void) { - DbpString(" ISO14443a sniff, storing in flashmem"); + DbpString(" HF 14A SNIFF, a ISO14443a sniffer with storing in flashmem"); DownloadTraceInstructions(); } void RunMod(void) { StandAloneMode(); - Dbprintf("Starting standalone mode: hf_14asniff"); + Dbprintf(_YELLOW_("HF 14A SNIFF started")); rdv40_spiffs_lazy_mount(); SniffIso14443a(0); @@ -118,7 +118,7 @@ void RunMod(void) { SpinErr(LED_A, 200, 5); SpinDelay(100); + Dbprintf("-=[ exit ]=-"); LEDsoff(); - SpinDelay(300); DownloadTraceInstructions(); } From b0d16a8905a1af685b07de3958caf8485854fe84 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 15 Mar 2021 15:53:47 +0100 Subject: [PATCH 056/373] text --- armsrc/Standalone/hf_craftbyte.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/armsrc/Standalone/hf_craftbyte.c b/armsrc/Standalone/hf_craftbyte.c index 5a20cab91..b58e89405 100644 --- a/armsrc/Standalone/hf_craftbyte.c +++ b/armsrc/Standalone/hf_craftbyte.c @@ -5,12 +5,12 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// main code for standalone HF/iso14a emulator +// main code for hf_craftbyte //----------------------------------------------------------------------------- - -/* - * `hf_craftyte` scans a card's UID and then emulates it in 14a - */ +// +// +// `hf_craftyte` continuesly scans for ISO14443a card UID and then emulates it. +// #include "standalone.h" #include "proxmark3_arm.h" @@ -28,20 +28,13 @@ #define STATE_READ 0 #define STATE_EMUL 1 -typedef struct { - uint8_t uid[10]; - uint8_t uidlen; - uint8_t atqa[2]; - uint8_t sak; -} PACKED card_clone_t; - void ModInfo(void) { - DbpString("hf_craftbyte: standalone UID Stealer - Scans and emulates 14a UID"); + DbpString("HF CRAFTBYTE mode - scans and emulates ISO14443a UID (craftbyte)"); } void RunMod(void) { StandAloneMode(); - Dbprintf("HF UID emulator started"); + Dbprintf(_YELLOW_("HF CRAFTBYTE mode started")); FpgaDownloadAndGo(FPGA_BITSTREAM_HF); // the main loop for your standalone mode @@ -100,6 +93,6 @@ void RunMod(void) { break; } - DbpString("exiting"); + Dbprintf("-=[ exit ]=-"); LEDsoff(); } From e5181d78477fa9b6aedf1b7566363243c3143693 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 15 Mar 2021 15:54:15 +0100 Subject: [PATCH 057/373] syntax --- armsrc/Standalone/lf_em4100rswb.c | 2 +- armsrc/Standalone/lf_em4100rwc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/Standalone/lf_em4100rswb.c b/armsrc/Standalone/lf_em4100rswb.c index aaf82b5b5..b3f2c571e 100644 --- a/armsrc/Standalone/lf_em4100rswb.c +++ b/armsrc/Standalone/lf_em4100rswb.c @@ -272,7 +272,7 @@ static int ExecuteMode(int mode, int slot) { case LF_RWSB_MODE_SIM: Dbprintf("[=] >> Sim mode started <<"); construct_EM410x_emul(rev_quads(low[slot])); - SimulateTagLowFrequency(buflen, 0, 1); + SimulateTagLowFrequency(buflen, 0, true); return LF_RWSB_UNKNOWN_RESULT; case LF_RWSB_MODE_WRITE: Dbprintf("[!!] >> Write mode started <<"); diff --git a/armsrc/Standalone/lf_em4100rwc.c b/armsrc/Standalone/lf_em4100rwc.c index 5df6e1a90..35f9b32b0 100644 --- a/armsrc/Standalone/lf_em4100rwc.c +++ b/armsrc/Standalone/lf_em4100rwc.c @@ -194,7 +194,7 @@ void RunMod(void) { construct_EM410x_emul(rev_quads(low[selected])); flash_leds(100, 5); - SimulateTagLowFrequency(buflen, 0, 1); + SimulateTagLowFrequency(buflen, 0, true); led_slot(selected); state = 0; // Switch to select mode } From 68033b8e2c45eb0891f9d8edf62a8359a8fd8c1e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 17 Mar 2021 10:40:05 +0100 Subject: [PATCH 058/373] hf mfdes info - text --- client/src/cmdhfmfdes.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index c208367bc..3c8aac0c5 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1447,10 +1447,10 @@ static int desfire_print_amk_keysetting(uint8_t key_settings, uint8_t num_keys, break; } - PrintAndLogEx(SUCCESS, " [1000] AMK Configuration changeable : %s", (key_settings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)"); - PrintAndLogEx(SUCCESS, " [0100] AMK required for create/delete : %s", (key_settings & (1 << 2)) ? "NO" : "YES"); - PrintAndLogEx(SUCCESS, " [0010] Directory list access with AMK : %s", (key_settings & (1 << 1)) ? "NO" : "YES"); - PrintAndLogEx(SUCCESS, " [0001] AMK is changeable : %s", (key_settings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)"); + PrintAndLogEx(SUCCESS, " [%c...] AMK Configuration changeable : %s", (key_settings & (1 << 3)) ? '1' : '0', (key_settings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)"); + PrintAndLogEx(SUCCESS, " [.%c..] AMK required for create/delete : %s", (key_settings & (1 << 2)) ? '1' : '0', (key_settings & (1 << 2)) ? "NO" : "YES"); + PrintAndLogEx(SUCCESS, " [..%c.] Directory list access with AMK : %s", (key_settings & (1 << 1)) ? '1' : '0', (key_settings & (1 << 1)) ? "NO" : "YES"); + PrintAndLogEx(SUCCESS, " [...%c] AMK is changeable : %s", (key_settings & (1 << 0)) ? '1' : '0', (key_settings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)"); return PM3_SUCCESS; } From b894365647bb6265786fbe524ac133af592c3407 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 17 Mar 2021 10:44:30 +0100 Subject: [PATCH 059/373] hf mfdes info - text --- client/src/cmdhfmfdes.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 3c8aac0c5..3a647514f 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1497,11 +1497,10 @@ static int desfire_print_piccmk_keysetting(uint8_t key_settings, uint8_t num_key (key_settings & (1 << 0)) ? '1' : '0' ); - PrintAndLogEx(SUCCESS, " [1...] CMK Configuration changeable : %s", (key_settings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)"); - PrintAndLogEx(SUCCESS, " [.1..] CMK required for create/delete : %s", (key_settings & (1 << 2)) ? _GREEN_("NO") : "YES"); - PrintAndLogEx(SUCCESS, " [..1.] Directory list access with CMK : %s", (key_settings & (1 << 1)) ? _GREEN_("NO") : "YES"); - PrintAndLogEx(SUCCESS, " [...1] CMK is changeable : %s", (key_settings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)"); - + PrintAndLogEx(SUCCESS, " [%c...] CMK Configuration changeable : %s", (key_settings & (1 << 3)) ? '1' : '0', (key_settings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)"); + PrintAndLogEx(SUCCESS, " [.%c..] CMK required for create/delete : %s", (key_settings & (1 << 2)) ? '1' : '0', (key_settings & (1 << 2)) ? _GREEN_("NO") : "YES"); + PrintAndLogEx(SUCCESS, " [..%c.] Directory list access with CMK : %s", (key_settings & (1 << 1)) ? '1' : '0', (key_settings & (1 << 1)) ? _GREEN_("NO") : "YES"); + PrintAndLogEx(SUCCESS, " [...%c] CMK is changeable : %s", (key_settings & (1 << 0)) ? '1' : '0', (key_settings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)"); return PM3_SUCCESS; } From 37e9fe9e13200f631c6c134d0c56dc1c030daa78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C5=BEe=20Jen=C5=A1terle?= Date: Sat, 20 Mar 2021 22:11:02 +0100 Subject: [PATCH 060/373] fixed typo in changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00077e5d8..1f00e0215 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] - - Added HF_CRAFTBYTE standalone mode that reads and emulates 14a UID (@craftbyte) + - Added `HF_CRAFTBYTE` standalone mode that reads and emulates 14a UID (@craftbyte) - Added a script to dump originality signatures from MFU EV1s and NTAGs (@aveao) - Added parsing of EF_CardAccess to display PACE algorithm, version and parameter in `hf emrtd info` (@aveao) - Change, numerous commands more uses cliparser (@tcprst, @iceman1001) From d7d17a07146b128e19e1f301380632b0fabc808d Mon Sep 17 00:00:00 2001 From: Gator96100 Date: Sat, 20 Mar 2021 22:39:05 +0100 Subject: [PATCH 061/373] Prevent Windows users from soft bricking their devices --- pm3 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pm3 b/pm3 index 6aadf2eb7..5496b3cf4 100755 --- a/pm3 +++ b/pm3 @@ -150,6 +150,12 @@ function get_pm3_list_Windows { # Normal SERIAL PORTS (COM) for DEV in $(wmic /locale:ms_409 path Win32_SerialPort Where "PNPDeviceID LIKE '%VID_9AC4&PID_4B8F%' Or PNPDeviceID LIKE '%VID_2D2D&PID_504D%'" Get DeviceID 2>/dev/null | awk -b '/^COM/{print $1}'); do DEV=${DEV/ */} + if [ ! $(wmic /locale:ms_409 path Win32_SerialPort Where "DeviceID='$DEV'" Get PNPDeviceID 2>/dev/null | awk -b '/^USB/{print $1}') = "USB\VID_9AC4&PID_4B8F\ICEMAN" ]; then + if [ $(basename -- "$0") = "pm3-flash-all" ]; then + echo -e "\033[0;31m[!] Using pm3-flash-all on an oudated bootloader, use pm3-flash-bootrom first!" + exit 1 + fi + fi PM3LIST+=("$DEV") if [ ${#PM3LIST[*]} -ge "$N" ]; then return From 52b4677036e2f0fc9757fa5a125f021c99241ac3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Mar 2021 18:02:17 +0100 Subject: [PATCH 062/373] data tune, setdebugmode, now uses cliparser --- client/src/cmddata.c | 68 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 7 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 095725b35..374b33880 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -381,9 +381,37 @@ void save_restoreDB(uint8_t saveOpt) { } static int CmdSetDebugMode(const char *Cmd) { - int demod = 0; - sscanf(Cmd, "%i", &demod); - g_debugMode = (uint8_t)demod; + CLIParserContext *ctx; + CLIParserInit(&ctx, "data setdebugmode", + "Set debugging level on client side", + "data setdebugmode" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0("0", NULL, "no debug messages"), + arg_lit0("1", NULL, "debug"), + arg_lit0("2", NULL, "verbose debugging"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool dg_0 = arg_get_lit(ctx, 0); + bool dg_1 = arg_get_lit(ctx, 1); + bool dg_2 = arg_get_lit(ctx, 2); + CLIParserFree(ctx); + + if (dg_0 + dg_1 + dg_2 > 1 ) { + PrintAndLogEx(INFO, "Select only one option"); + return PM3_EINVARG; + } + if (dg_0) + g_debugMode = 0; + + if (dg_1) + g_debugMode = 1; + + if (dg_2) + g_debugMode = 2; return PM3_SUCCESS; } @@ -1629,7 +1657,21 @@ static int CmdSamples(const char *Cmd) { } int CmdTuneSamples(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + + CLIParserContext *ctx; + CLIParserInit(&ctx, "data tune", + "Measure tuning of device antenna. Results shown in graph window.\n" + "This command doesn't actively tune your antennas, \n" + "it's only informative by measuring voltage that the antennas will generate", + "data tune" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + #define NON_VOLTAGE 1000 #define LF_UNUSABLE_V 2000 #define LF_MARGINAL_V 10000 @@ -1644,7 +1686,8 @@ int CmdTuneSamples(const char *Cmd) { int timeout = 0; int timeout_max = 20; - PrintAndLogEx(INFO, "REMINDER: " _YELLOW_("'hw tune' doesn't actively tune your antennas") ", it's only informative"); + PrintAndLogEx(INFO, "Reminder: `" _YELLOW_("hw tune") "` doesn't actively tune your antennas,"); + PrintAndLogEx(INFO, "it's only informative."); PrintAndLogEx(INFO, "Measuring antenna characteristics, please wait..."); clearCommandBuffer(); @@ -1938,7 +1981,18 @@ int CmdNorm(const char *Cmd) { } int CmdPlot(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + CLIParserContext *ctx; + CLIParserInit(&ctx, "data plot", + "Show graph window \n" + "hit 'h' in window for detail keystroke help available", + "data plot" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); ShowGraphWindow(); return PM3_SUCCESS; } @@ -2544,7 +2598,7 @@ static command_t CommandTable[] = { {"ltrim", CmdLtrim, AlwaysAvailable, " -- Trim samples from left of trace"}, {"mtrim", CmdMtrim, AlwaysAvailable, " -- Trim out samples from the specified start to the specified stop"}, {"norm", CmdNorm, AlwaysAvailable, "Normalize max/min to +/-128"}, - {"plot", CmdPlot, AlwaysAvailable, "Show graph window (hit 'h' in window for keystroke help)"}, + {"plot", CmdPlot, AlwaysAvailable, "Show graph window"}, {"rtrim", CmdRtrim, AlwaysAvailable, " -- Trim samples from right of trace"}, {"setgraphmarkers", CmdSetGraphMarkers, AlwaysAvailable, "[orange_marker] [blue_marker] (in graph window)"}, {"shiftgraphzero", CmdGraphShiftZero, AlwaysAvailable, " -- Shift 0 for Graphed wave + or - shift value"}, From d3f093ca4af99c6c48cb012a0781485dcb49af52 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Mar 2021 18:07:33 +0100 Subject: [PATCH 063/373] data plot, hide, now uses cliparser --- client/src/cmddata.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 374b33880..97026e644 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1542,7 +1542,17 @@ static int CmdHexsamples(const char *Cmd) { } static int CmdHide(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + CLIParserContext *ctx; + CLIParserInit(&ctx, "data hide", + "Show graph window", + "data hide" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); HideGraphWindow(); return PM3_SUCCESS; } @@ -1686,7 +1696,8 @@ int CmdTuneSamples(const char *Cmd) { int timeout = 0; int timeout_max = 20; - PrintAndLogEx(INFO, "Reminder: `" _YELLOW_("hw tune") "` doesn't actively tune your antennas,"); + PrintAndLogEx(INFO, "---------- " _CYAN_("Reminder") " ------------------------"); + PrintAndLogEx(INFO, "`" _YELLOW_("hw tune") "` doesn't actively tune your antennas,"); PrintAndLogEx(INFO, "it's only informative."); PrintAndLogEx(INFO, "Measuring antenna characteristics, please wait..."); From e3d5c581d4db00ea339bcf6a92c9f33c08351294 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Mar 2021 18:13:09 +0100 Subject: [PATCH 064/373] text --- client/src/cmddata.c | 20 +++++++++++++++++--- client/src/ui.c | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 97026e644..7b6cb2b7b 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -395,9 +395,9 @@ static int CmdSetDebugMode(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, true); - bool dg_0 = arg_get_lit(ctx, 0); - bool dg_1 = arg_get_lit(ctx, 1); - bool dg_2 = arg_get_lit(ctx, 2); + bool dg_0 = arg_get_lit(ctx, 1); + bool dg_1 = arg_get_lit(ctx, 2); + bool dg_2 = arg_get_lit(ctx, 3); CLIParserFree(ctx); if (dg_0 + dg_1 + dg_2 > 1 ) { @@ -412,6 +412,20 @@ static int CmdSetDebugMode(const char *Cmd) { if (dg_2) g_debugMode = 2; + + switch(g_debugMode) { + case 0: + PrintAndLogEx(INFO, "client debug level... %u ( no debug messages )", g_debugMode); + break; + case 1: + PrintAndLogEx(INFO, "client debug level... %u ( debug messages )", g_debugMode); + break; + case 2: + PrintAndLogEx(INFO, "client debug level... %u ( verbose debug messages )", g_debugMode); + break; + default: + break; + } return PM3_SUCCESS; } diff --git a/client/src/ui.c b/client/src/ui.c index 3c4069f5b..a044d7312 100644 --- a/client/src/ui.c +++ b/client/src/ui.c @@ -182,7 +182,7 @@ static uint8_t PrintAndLogEx_spinidx = 0; void PrintAndLogEx(logLevel_t level, const char *fmt, ...) { - // skip debug messages if client debugging is turned off i.e. 'DATA SETDEBUG 0' + // skip debug messages if client debugging is turned off i.e. 'DATA SETDEBUG -0' if (g_debugMode == 0 && level == DEBUG) return; From 443d5a3f3ab1e69dcbd5406aeda64bcc8ce5201e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Mar 2021 18:21:35 +0100 Subject: [PATCH 065/373] data samples - now uses cliparser --- client/src/cmddata.c | 22 +++++++++++++++++++--- doc/cheatsheet.md | 2 +- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 7b6cb2b7b..ea7a7e999 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1676,8 +1676,24 @@ int getSamplesEx(uint32_t start, uint32_t end, bool verbose) { } static int CmdSamples(const char *Cmd) { - int n = strtol(Cmd, NULL, 0); - return getSamples(n, false); + + CLIParserContext *ctx; + CLIParserInit(&ctx, "data samples", + "Get raw samples for graph window (GraphBuffer) from device.\n" + "If 0, then get whole big buffer from device.", + "data samples" + ); + void *argtable[] = { + arg_param_begin, + arg_int0("n","", "", "num of samples (512 - 40000)"), + arg_lit0("v", "verbose", "verbose"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + int n = arg_get_int_def(ctx, 1, 0); + bool verbose = arg_get_lit(ctx, 2); + CLIParserFree(ctx); + return getSamples(n, verbose); } int CmdTuneSamples(const char *Cmd) { @@ -2641,7 +2657,7 @@ static command_t CommandTable[] = { {"load", CmdLoad, AlwaysAvailable, "Load contents of file into graph window"}, {"ndef", CmdDataNDEF, AlwaysAvailable, "Decode NDEF records"}, {"print", CmdPrintDemodBuff, AlwaysAvailable, "print the data in the DemodBuffer"}, - {"samples", CmdSamples, IfPm3Present, "[512 - 40000] -- Get raw samples for graph window (GraphBuffer)"}, + {"samples", CmdSamples, IfPm3Present, "Get raw samples for graph window (GraphBuffer)"}, {"save", CmdSave, AlwaysAvailable, "Save signal trace data (from graph window)"}, {"setdebugmode", CmdSetDebugMode, AlwaysAvailable, "<0|1|2> -- Set Debugging Level on client side"}, {"tune", CmdTuneSamples, IfPm3Present, "Measure tuning of device antenna. Results shown in graph window"}, diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index 4ff857d9c..03b1854f5 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -592,7 +592,7 @@ pm3 --> lf t55xx wipe Get raw samples [512-40000] ``` -pm3 --> data samples +pm3 --> data samples -n ``` Save samples to file From c8dca0e9e0aedf26ad5eb339632bef096c322381 Mon Sep 17 00:00:00 2001 From: Gator96100 Date: Mon, 22 Mar 2021 20:46:39 +0100 Subject: [PATCH 066/373] WSL check for outdated bootloader --- pm3 | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/pm3 b/pm3 index 5496b3cf4..268a7e99e 100755 --- a/pm3 +++ b/pm3 @@ -150,8 +150,9 @@ function get_pm3_list_Windows { # Normal SERIAL PORTS (COM) for DEV in $(wmic /locale:ms_409 path Win32_SerialPort Where "PNPDeviceID LIKE '%VID_9AC4&PID_4B8F%' Or PNPDeviceID LIKE '%VID_2D2D&PID_504D%'" Get DeviceID 2>/dev/null | awk -b '/^COM/{print $1}'); do DEV=${DEV/ */} - if [ ! $(wmic /locale:ms_409 path Win32_SerialPort Where "DeviceID='$DEV'" Get PNPDeviceID 2>/dev/null | awk -b '/^USB/{print $1}') = "USB\VID_9AC4&PID_4B8F\ICEMAN" ]; then - if [ $(basename -- "$0") = "pm3-flash-all" ]; then + #prevent soft bricking when using pm3-flash-all on an outdated bootloader + if [ $(basename -- "$0") = "pm3-flash-all" ]; then + if [ ! $(wmic /locale:ms_409 path Win32_SerialPort Where "DeviceID='$DEV'" Get PNPDeviceID 2>/dev/null | awk -b '/^USB/{print $1}') = "USB\VID_9AC4&PID_4B8F\ICEMAN" ]; then echo -e "\033[0;31m[!] Using pm3-flash-all on an oudated bootloader, use pm3-flash-bootrom first!" exit 1 fi @@ -198,9 +199,18 @@ function get_pm3_list_WSL { fi # Normal SERIAL PORTS (COM) - for DEV in $($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object {\$_.PNPDeviceID -like '*VID_9AC4&PID_4B8F*' -or \$_.PNPDeviceID -like '*VID_2D2D&PID_504D*'} | Select DeviceID" 2>/dev/null | sed -nr 's#^COM([0-9]+)\b#/dev/ttyS\1#p'); do + for DEV in $($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object {\$_.PNPDeviceID -like '*VID_9AC4&PID_4B8F*' -or \$_.PNPDeviceID -like '*VID_2D2D&PID_504D*'} | Select -expandproperty DeviceID" 2>/dev/null | tr -dc '[:print:]'); do + _comport=$DEV + DEV=$(echo $DEV | sed -nr 's#^COM([0-9]+)\b#/dev/ttyS\1#p') # ttyS counterpart takes some more time to appear if [ -e "$DEV" ]; then + #prevent soft bricking when using pm3-flash-all on an outdated bootloader + if [ $(basename -- "$0") = "pm3-flash-all" ]; then + if [ ! $($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object {\$_.DeviceID -eq '$DEV'} | Select -expandproperty PNPDeviceID" 2>/dev/null) = "USB\VID_9AC4&PID_4B8F\ICEMAN" ]; then + echo -e "\033[0;31m[!] Using pm3-flash-all on an oudated bootloader, use pm3-flash-bootrom first!" + exit 1 + fi + fi PM3LIST+=("$DEV") if [ ! -w "$DEV" ]; then echo "[!] Let's give users read/write access to $DEV" From b36d049ee64fba4f0daae5ef800293677ba53787 Mon Sep 17 00:00:00 2001 From: Gator96100 Date: Mon, 22 Mar 2021 20:52:41 +0100 Subject: [PATCH 067/373] Fix --- pm3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pm3 b/pm3 index 268a7e99e..3c69fea61 100755 --- a/pm3 +++ b/pm3 @@ -206,7 +206,7 @@ function get_pm3_list_WSL { if [ -e "$DEV" ]; then #prevent soft bricking when using pm3-flash-all on an outdated bootloader if [ $(basename -- "$0") = "pm3-flash-all" ]; then - if [ ! $($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object {\$_.DeviceID -eq '$DEV'} | Select -expandproperty PNPDeviceID" 2>/dev/null) = "USB\VID_9AC4&PID_4B8F\ICEMAN" ]; then + if [ ! $($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object {\$_.DeviceID -eq '$_comport'} | Select -expandproperty PNPDeviceID" 2>/dev/null) = "USB\VID_9AC4&PID_4B8F\ICEMAN" ]; then echo -e "\033[0;31m[!] Using pm3-flash-all on an oudated bootloader, use pm3-flash-bootrom first!" exit 1 fi From 2250be7da1bb7a5128e72b78bb4f5562bcac1c33 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Mar 2021 20:54:08 +0100 Subject: [PATCH 068/373] data print - now uses cliparser --- client/src/cmddata.c | 189 ++++++++++++++++++------------------------- 1 file changed, 79 insertions(+), 110 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index ea7a7e999..87438eaee 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1,7 +1,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 2010 iZsh -// -// iceman 2019 +// modified Marshmellow, +// modified Iceman 2019, 2020, 2021 // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -36,17 +36,6 @@ int g_DemodClock = 0; static int CmdHelp(const char *Cmd); -static int usage_data_printdemodbuf(void) { - PrintAndLogEx(NORMAL, "Usage: data print x o l "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " i invert Demodbuffer before printing"); - PrintAndLogEx(NORMAL, " x output in hex (omit for binary output)"); - PrintAndLogEx(NORMAL, " o enter offset in # of bits"); - PrintAndLogEx(NORMAL, " l enter length to print in # of bits or hex characters respectively"); - PrintAndLogEx(NORMAL, " s strip leading zeroes, i.e. set offset to first bit equal to one"); - return PM3_SUCCESS; -} static int usage_data_manrawdecode(void) { PrintAndLogEx(NORMAL, "Usage: data manrawdecode [invert] [maxErr]"); PrintAndLogEx(NORMAL, " Takes 10 and 01 and converts to 0 and 1 respectively"); @@ -429,7 +418,6 @@ static int CmdSetDebugMode(const char *Cmd) { return PM3_SUCCESS; } -//by marshmellow // max output to 512 bits if we have more // doesn't take inconsideration where the demod offset or bitlen found. int printDemodBuff(uint8_t offset, bool strip_leading, bool invert, bool print_hex) { @@ -439,17 +427,24 @@ int printDemodBuff(uint8_t offset, bool strip_leading, bool invert, bool print_h return PM3_EINVARG; } - uint8_t *buf = NULL; + uint8_t *buf = calloc(len, sizeof(uint8_t)); + if (buf == NULL) { + PrintAndLogEx(WARNING, "dail, cannot allocate memory"); + return PM3_EMALLOC; + } + memcpy(buf, DemodBuffer, len); + + uint8_t *p = NULL; if (strip_leading) { - buf = (DemodBuffer + offset); + p = (buf + offset); if (len > (DemodBufferLen - offset)) len = (DemodBufferLen - offset); size_t i; for (i = 0; i < len; i++) { - if (buf[i] == 1) break; + if (p[i] == 1) break; } offset += i; } @@ -463,79 +458,64 @@ int printDemodBuff(uint8_t offset, bool strip_leading, bool invert, bool print_h } if (invert) { - buf = (DemodBuffer + offset); + p = (buf + offset); for (size_t i = 0; i < len; i++) { - if (buf[i] == 1) - buf[i] = 0; + if (p[i] == 1) + p[i] = 0; else { - if (buf[i] == 0) - buf[i] = 1; + if (p[i] == 0) + p[i] = 1; } } } if (print_hex) { - buf = (DemodBuffer + offset); + p = (buf + offset); char hex[512] = {0x00}; - int num_bits = binarraytohex(hex, sizeof(hex), (char *)buf, len); + int num_bits = binarraytohex(hex, sizeof(hex), (char *)p, len); if (num_bits == 0) { return PM3_ESOFT; } - PrintAndLogEx(SUCCESS, "DemodBuffer: %s", hex); + PrintAndLogEx(SUCCESS, "DemodBuffer:\n%s", hex); } else { - PrintAndLogEx(SUCCESS, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer + offset, len, 32)); + PrintAndLogEx(SUCCESS, "DemodBuffer:\n%s", sprint_bin_break(buf + offset, len, 32)); } + + p = NULL; + free(buf); return PM3_SUCCESS; } int CmdPrintDemodBuff(const char *Cmd) { - bool print_hex = false; - bool errors = false; - bool lstrip = false; - bool invert = false; - uint32_t offset = 0; - uint32_t length = 512; - char cmdp = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_data_printdemodbuf(); - case 'x': - print_hex = true; - cmdp++; - break; - case 'o': - offset = param_get32ex(Cmd, cmdp + 1, 0, 10); - if (!offset) errors = true; - cmdp += 2; - break; - case 'l': - length = param_get32ex(Cmd, cmdp + 1, 512, 10); - if (!length) errors = true; - cmdp += 2; - break; - case 's': - lstrip = true; - cmdp++; - break; - case 'i': - invert = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors) return usage_data_printdemodbuf(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "data print", + "Print the data in the DemodBuffer as hex or binary.\n" + "Defaults to binary output", + "data print" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0("i", "inv", "invert Demodbuffer before printing"), +// arg_int0("l","len", "", "length to print in # of bits or hex characters respectively"), + arg_int0("o","offset", "", "offset in # of bits"), + arg_lit0("s", "strip", "strip leading zeroes, i.e. set offset to first bit equal to one"), + arg_lit0("x", "hex", "output in hex (omit for binary output)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool invert = arg_get_lit(ctx, 1); + int os = arg_get_int_def(ctx, 2, 0); + bool lstrip = arg_get_lit(ctx, 3); + bool print_hex = arg_get_lit(ctx, 4); + CLIParserFree(ctx); + + uint8_t offset = (os & 0xFF); return printDemodBuff(offset, lstrip, invert, print_hex); } -//by marshmellow -//this function strictly converts >1 to 1 and <1 to 0 for each sample in the graphbuffer +// this function strictly converts >1 to 1 and <1 to 0 for each sample in the graphbuffer int CmdGetBitStream(const char *Cmd) { CmdHpf(Cmd); for (uint32_t i = 0; i < GraphTraceLen; i++) @@ -555,12 +535,11 @@ static int CmdConvertBitStream(const char *Cmd) { return PM3_SUCCESS; } -//by marshmellow -//Cmd Args: Clock, invert, maxErr, maxLen as integers and amplify as char == 'a' +// Cmd Args: Clock, invert, maxErr, maxLen as integers and amplify as char == 'a' // (amp may not be needed anymore) -//verbose will print results and demoding messages -//emSearch will auto search for EM410x format in bitstream -//askType switches decode: ask/raw = 0, ask/manchester = 1 +// verbose will print results and demoding messages +// emSearch will auto search for EM410x format in bitstream +// askType switches decode: ask/raw = 0, ask/manchester = 1 int ASKDemod_ext(int clk, int invert, int maxErr, size_t maxLen, bool amplify, bool verbose, bool emSearch, uint8_t askType, bool *stCheck) { PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) clk %i invert %i maxErr %i maxLen %zu amplify %i verbose %i emSearch %i askType %i ", clk, invert, maxErr, maxLen, amplify, verbose, emSearch, askType); uint8_t askamp = 0; @@ -652,10 +631,9 @@ int ASKDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, bool return ASKDemod_ext(clk, invert, maxErr, maxLen, amplify, verbose, emSearch, askType, &st); } -//by marshmellow -//takes 5 arguments - clock, invert, maxErr, maxLen as integers and amplify as char == 'a' -//attempts to demodulate ask while decoding manchester -//prints binary found and saves in graphbuffer for further commands +// takes 5 arguments - clock, invert, maxErr, maxLen as integers and amplify as char == 'a' +// attempts to demodulate ask while decoding manchester +// prints binary found and saves in graphbuffer for further commands static int Cmdaskmandemod(const char *Cmd) { size_t slen = strlen(Cmd); @@ -695,9 +673,8 @@ static int Cmdaskmandemod(const char *Cmd) { return ASKDemod_ext(clk, invert, maxErr, maxLen, amplify, true, true, 1, &st); } -//by marshmellow -//manchester decode -//strictly take 10 and 01 and convert to 0 and 1 +// manchester decode +// strictly take 10 and 01 and convert to 0 and 1 static int Cmdmandecoderaw(const char *Cmd) { size_t size = 0; int high = 0, low = 0; @@ -798,8 +775,7 @@ static int CmdBiphaseDecodeRaw(const char *Cmd) { return PM3_SUCCESS; } -//by marshmellow -// - ASK Demod then Biphase decode GraphBuffer samples +// ASK Demod then Biphase decode GraphBuffer samples int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) { //ask raw demod GraphBuffer first @@ -837,7 +813,8 @@ int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) { } return PM3_SUCCESS; } -//by marshmellow - see ASKbiphaseDemod + +// see ASKbiphaseDemod static int Cmdaskbiphdemod(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ab(); @@ -846,7 +823,7 @@ static int Cmdaskbiphdemod(const char *Cmd) { return ASKbiphaseDemod(offset, clk, invert, maxErr, true); } -//by marshmellow - see ASKDemod +// see ASKDemod static int Cmdaskrawdemod(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ar(); @@ -1097,8 +1074,7 @@ static int CmdUndecimate(const char *Cmd) { return PM3_SUCCESS; } -//by marshmellow -//shift graph zero up or down based on input + or - +// shift graph zero up or down based on input + or - static int CmdGraphShiftZero(const char *Cmd) { int shift = 0; //set options from parameters entered with the command @@ -1129,10 +1105,9 @@ int AskEdgeDetect(const int *in, int *out, int len, int threshold) { return PM3_SUCCESS; } -//by marshmellow -//use large jumps in read samples to identify edges of waves and then amplify that wave to max -//similar to dirtheshold, threshold commands -//takes a threshold length which is the measured length between two samples then determines an edge +// use large jumps in read samples to identify edges of waves and then amplify that wave to max +// similar to dirtheshold, threshold commands +// takes a threshold length which is the measured length between two samples then determines an edge static int CmdAskEdgeDetect(const char *Cmd) { int thresLen = 25; int ans = 0; @@ -1143,7 +1118,7 @@ static int CmdAskEdgeDetect(const char *Cmd) { return ans; } -/* Print our clock rate */ +// Print our clock rate // uses data from graphbuffer // adjusted to take char parameter for type of modulation to find the clock - by marshmellow. static int CmdDetectClockRate(const char *Cmd) { @@ -1198,10 +1173,9 @@ static char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert) { return fskType; } -//by marshmellow -//fsk raw demod and print binary -//takes 4 arguments - Clock, invert, fchigh, fclow -//defaults: clock = 50, invert=1, fchigh=10, fclow=8 (RF/10 RF/8 (fsk2a)) +// fsk raw demod and print binary +// takes 4 arguments - Clock, invert, fchigh, fclow +// defaults: clock = 50, invert=1, fchigh=10, fclow=8 (RF/10 RF/8 (fsk2a)) int FSKrawDemod(uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, bool verbose) { //raw fsk demod no manchester decoding no start bit finding just get binary from wave if (getSignalProperties()->isnoise) @@ -1257,10 +1231,9 @@ out: return PM3_SUCCESS; } -//by marshmellow -//fsk raw demod and print binary -//takes 4 arguments - Clock, invert, fchigh, fclow -//defaults: clock = 50, invert=1, fchigh=10, fclow=8 (RF/10 RF/8 (fsk2a)) +// fsk raw demod and print binary +// takes 4 arguments - Clock, invert, fchigh, fclow +// defaults: clock = 50, invert=1, fchigh=10, fclow=8 (RF/10 RF/8 (fsk2a)) static int CmdFSKrawdemod(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) > 20 || cmdp == 'h') return usage_data_rawdemod_fs(); @@ -1282,8 +1255,7 @@ static int CmdFSKrawdemod(const char *Cmd) { return FSKrawDemod(rfLen, invert, fchigh, fclow, true); } -//by marshmellow -//attempt to psk1 demod graph buffer +// attempt to psk1 demod graph buffer int PSKDemod(int clk, int invert, int maxErr, bool verbose) { if (getSignalProperties()->isnoise) return PM3_ESOFT; @@ -1323,7 +1295,6 @@ int PSKDemod(int clk, int invert, int maxErr, bool verbose) { return PM3_SUCCESS; } -// by marshmellow // takes 3 arguments - clock, invert, maxErr as integers // attempts to demodulate nrz only // prints binary found and saves in demodbuffer for further commands @@ -1392,7 +1363,6 @@ static int CmdNRZrawDemod(const char *Cmd) { return NRZrawDemod(clk, invert, maxErr, true); } -// by marshmellow // takes 3 arguments - clock, invert, max_err as integers // attempts to demodulate psk only // prints binary found and saves in demodbuffer for further commands @@ -1421,7 +1391,6 @@ int CmdPSK1rawDemod(const char *Cmd) { return PM3_SUCCESS; } -// by marshmellow // takes same args as cmdpsk1rawdemod static int CmdPSK2rawDemod(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); @@ -1448,7 +1417,7 @@ static int CmdPSK2rawDemod(const char *Cmd) { return PM3_SUCCESS; } -// by marshmellow - combines all raw demod functions into one menu command +// combines all raw demod functions into one menu command static int CmdRawDemod(const char *Cmd) { int ans = 0; @@ -1571,7 +1540,7 @@ static int CmdHide(const char *Cmd) { return PM3_SUCCESS; } -//zero mean GraphBuffer +// zero mean GraphBuffer int CmdHpf(const char *Cmd) { (void)Cmd; // Cmd is not used so far uint8_t bits[GraphTraceLen]; @@ -2634,7 +2603,7 @@ static command_t CommandTable[] = { {"undecimate", CmdUndecimate, AlwaysAvailable, "Un-decimate samples"}, {"hide", CmdHide, AlwaysAvailable, "Hide graph window"}, {"hpf", CmdHpf, AlwaysAvailable, "Remove DC offset from trace"}, - {"iir", CmdDataIIR, AlwaysAvailable, "apply IIR buttersworth filter on plotdata"}, + {"iir", CmdDataIIR, AlwaysAvailable, "Apply IIR buttersworth filter on plotdata"}, {"grid", CmdGrid, AlwaysAvailable, " -- overlay grid on graph window, use zero value to turn off either"}, {"ltrim", CmdLtrim, AlwaysAvailable, " -- Trim samples from left of trace"}, {"mtrim", CmdMtrim, AlwaysAvailable, " -- Trim out samples from the specified start to the specified stop"}, @@ -2656,10 +2625,10 @@ static command_t CommandTable[] = { {"hex2bin", Cmdhex2bin, AlwaysAvailable, "Converts hexadecimal to binary"}, {"load", CmdLoad, AlwaysAvailable, "Load contents of file into graph window"}, {"ndef", CmdDataNDEF, AlwaysAvailable, "Decode NDEF records"}, - {"print", CmdPrintDemodBuff, AlwaysAvailable, "print the data in the DemodBuffer"}, + {"print", CmdPrintDemodBuff, AlwaysAvailable, "Print the data in the DemodBuffer"}, {"samples", CmdSamples, IfPm3Present, "Get raw samples for graph window (GraphBuffer)"}, {"save", CmdSave, AlwaysAvailable, "Save signal trace data (from graph window)"}, - {"setdebugmode", CmdSetDebugMode, AlwaysAvailable, "<0|1|2> -- Set Debugging Level on client side"}, + {"setdebugmode", CmdSetDebugMode, AlwaysAvailable, "Set Debugging Level on client side"}, {"tune", CmdTuneSamples, IfPm3Present, "Measure tuning of device antenna. Results shown in graph window"}, {NULL, NULL, NULL, NULL} }; From b02d0769280b12a260755e9abb014f8fefb4b72f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Mar 2021 21:11:24 +0100 Subject: [PATCH 069/373] data ltrim, mtrim, rtrim - now uses cliparser --- client/src/cmddata.c | 86 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 14 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 87438eaee..ef9c7be45 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1918,11 +1918,25 @@ static int CmdLoad(const char *Cmd) { // trim graph from the end int CmdLtrim(const char *Cmd) { - - uint32_t ds = strtoul(Cmd, NULL, 10); + CLIParserContext *ctx; + CLIParserInit(&ctx, "data ltrim", + "Trim samples from left of trace", + "data ltrim -i 300 --> keep 300 - end" + ); + void *argtable[] = { + arg_param_begin, + arg_u64_1("i", "idx", "", "from index to beginning trace"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + uint32_t ds = arg_get_u32(ctx, 1); + CLIParserFree(ctx); // sanitycheck - if (GraphTraceLen <= ds) return PM3_ESOFT; + if (GraphTraceLen <= ds) { + PrintAndLogEx(WARNING, "index out of bounds"); + return PM3_EINVARG; + } for (uint32_t i = ds; i < GraphTraceLen; ++i) GraphBuffer[i - ds] = GraphBuffer[i]; @@ -1936,10 +1950,25 @@ int CmdLtrim(const char *Cmd) { // trim graph from the beginning static int CmdRtrim(const char *Cmd) { - uint32_t ds = strtoul(Cmd, NULL, 10); + CLIParserContext *ctx; + CLIParserInit(&ctx, "data rtrim", + "Trim samples from right of trace", + "data rtrim -i 4000 --> keep 0 - 4000" + ); + void *argtable[] = { + arg_param_begin, + arg_u64_1("i", "idx", "", "from index to end trace"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + uint32_t ds = arg_get_u32(ctx, 1); + CLIParserFree(ctx); // sanitycheck - if (GraphTraceLen <= ds) return PM3_ESOFT; + if (GraphTraceLen <= ds) { + PrintAndLogEx(WARNING, "index out of bounds"); + return PM3_EINVARG; + } GraphTraceLen = ds; RepaintGraphWindow(); @@ -1948,24 +1977,53 @@ static int CmdRtrim(const char *Cmd) { // trim graph (middle) piece static int CmdMtrim(const char *Cmd) { - uint32_t start = 0, stop = 0; - sscanf(Cmd, "%u %u", &start, &stop); - if (start > GraphTraceLen || stop > GraphTraceLen || start >= stop) - return PM3_ESOFT; + CLIParserContext *ctx; + CLIParserInit(&ctx, "data mtrim", + "Trim out samples from the specified start to the specified end point", + "data mtrim -s 1000 -e 2000 --> keep between 1000 and 2000" + ); + void *argtable[] = { + arg_param_begin, + arg_u64_1("s", "start", "", "start point"), + arg_u64_1("e", "end", "", "end point"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + uint32_t start = arg_get_u32(ctx, 1); + uint32_t stop = arg_get_u32(ctx, 2); + CLIParserFree(ctx); + + if (start > GraphTraceLen || stop > GraphTraceLen || start >= stop) { + PrintAndLogEx(WARNING, "start and end points doesn't align"); + return PM3_EINVARG; + } // leave start position sample start++; GraphTraceLen = stop - start; - for (uint32_t i = 0; i < GraphTraceLen; i++) + for (uint32_t i = 0; i < GraphTraceLen; i++) { GraphBuffer[i] = GraphBuffer[start + i]; + } return PM3_SUCCESS; } int CmdNorm(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + + CLIParserContext *ctx; + CLIParserInit(&ctx, "data norm", + "Normalize max/min to +/-128", + "data norm" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + int max = INT_MIN, min = INT_MAX; // Find local min, max @@ -2605,11 +2663,11 @@ static command_t CommandTable[] = { {"hpf", CmdHpf, AlwaysAvailable, "Remove DC offset from trace"}, {"iir", CmdDataIIR, AlwaysAvailable, "Apply IIR buttersworth filter on plotdata"}, {"grid", CmdGrid, AlwaysAvailable, " -- overlay grid on graph window, use zero value to turn off either"}, - {"ltrim", CmdLtrim, AlwaysAvailable, " -- Trim samples from left of trace"}, - {"mtrim", CmdMtrim, AlwaysAvailable, " -- Trim out samples from the specified start to the specified stop"}, + {"ltrim", CmdLtrim, AlwaysAvailable, "Trim samples from left of trace"}, + {"mtrim", CmdMtrim, AlwaysAvailable, "Trim out samples from the specified start to the specified stop"}, {"norm", CmdNorm, AlwaysAvailable, "Normalize max/min to +/-128"}, {"plot", CmdPlot, AlwaysAvailable, "Show graph window"}, - {"rtrim", CmdRtrim, AlwaysAvailable, " -- Trim samples from right of trace"}, + {"rtrim", CmdRtrim, AlwaysAvailable, "Trim samples from right of trace"}, {"setgraphmarkers", CmdSetGraphMarkers, AlwaysAvailable, "[orange_marker] [blue_marker] (in graph window)"}, {"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"}, From 22dac2d098522350d7729489979eb8fbe071dce5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Mar 2021 21:46:48 +0100 Subject: [PATCH 070/373] data clear, hex2bin - now uses cliparser --- client/src/cmddata.c | 85 +++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index ef9c7be45..ba3d2b5f1 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -223,24 +223,12 @@ static int usage_data_detectclock(void) { PrintAndLogEx(NORMAL, " data detectclock n = detect the clock of an nrz/direct modulated wave in the GraphBuffer"); return PM3_SUCCESS; } -static int usage_data_hex2bin(void) { - PrintAndLogEx(NORMAL, "Usage: data hex2bin "); - PrintAndLogEx(NORMAL, " This function will ignore all non-hexadecimal characters (but stop reading on whitespace)"); - return PM3_SUCCESS; -} + static int usage_data_bin2hex(void) { PrintAndLogEx(NORMAL, "Usage: data bin2hex "); PrintAndLogEx(NORMAL, " This function will ignore all characters not 1 or 0 (but stop reading on whitespace)"); return PM3_SUCCESS; } -static int usage_data_buffclear(void) { - PrintAndLogEx(NORMAL, "This function clears the bigbuff on deviceside"); - PrintAndLogEx(NORMAL, "Usage: data clear [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - return PM3_SUCCESS; -} - //set the demod buffer with given array of binary (one bit per byte) //by marshmellow @@ -971,7 +959,19 @@ static int CmdAutoCorr(const char *Cmd) { } static int CmdBitsamples(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + + CLIParserContext *ctx; + CLIParserInit(&ctx, "data bitsamples", + "Get raw samples from device as bitstring", + "data bitsamples" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + int cnt = 0; uint8_t got[12288]; @@ -994,9 +994,18 @@ static int CmdBitsamples(const char *Cmd) { } static int CmdBuffClear(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_data_buffclear(); - + CLIParserContext *ctx; + CLIParserInit(&ctx, "data clear", + "This function clears the bigbuff on deviceside\n" + "and graph window", + "data clear" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); clearCommandBuffer(); SendCommandNG(CMD_BUFF_CLEAR, NULL, 0); ClearGraph(true); @@ -2245,24 +2254,34 @@ static int Cmdbin2hex(const char *Cmd) { } static int Cmdhex2bin(const char *Cmd) { - int bg = 0, en = 0; - if (param_getptr(Cmd, &bg, &en, 0)) return usage_data_hex2bin(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "data hex2bin", + "This function will ignore all non-hexadecimal characters\n" + "but stop reading on whitespace", + "data hex2bin -d 01020304" + ); + void *argtable[] = { + arg_param_begin, + arg_str0("d", "data", "", "bytes to convert"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + int dlen = 0; + uint8_t data[200] = {0x00}; + int res = CLIParamHexToBuf(arg_get_str(ctx, 1), data, sizeof(data), &dlen); + CLIParserFree(ctx); - while (bg <= en) { - char x = Cmd[bg++]; - // capitalize - if (x >= 'a' && x <= 'f') - x -= 32; - // convert to numeric value - if (x >= '0' && x <= '9') - x -= '0'; - else if (x >= 'A' && x <= 'F') - x -= 'A' - 10; - else - continue; + if (res) { + PrintAndLogEx(FAILED, "Error parsing bytes"); + return PM3_EINVARG; + } - for (int i = 0 ; i < 4 ; ++i) - PrintAndLogEx(NORMAL, "%d" NOLF, (x >> (3 - i)) & 1); + PrintAndLogEx(SUCCESS, "" NOLF); + for (int i = 0; i < dlen; i++) { + char x = data[i]; + for (int j = 0 ; j < 4 ; ++j) { + PrintAndLogEx(NORMAL, "%d" NOLF, (x >> (3 - j)) & 1); + } } PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; From 8573695134ea61b7f042e6149e7f2160ab06e7ed Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 11:06:09 +0100 Subject: [PATCH 071/373] data bin2hex - now uses cliparser\n added a binary string input parser --- client/deps/cliparser/cliparser.c | 25 +++++++++ client/deps/cliparser/cliparser.h | 1 + client/src/cmddata.c | 54 ++++++++++++-------- client/src/util.c | 84 ++++++++++++++++++++++--------- client/src/util.h | 1 + 5 files changed, 121 insertions(+), 44 deletions(-) diff --git a/client/deps/cliparser/cliparser.c b/client/deps/cliparser/cliparser.c index f3f3c581e..174a540fc 100644 --- a/client/deps/cliparser/cliparser.c +++ b/client/deps/cliparser/cliparser.c @@ -231,6 +231,31 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int return res; } +int CLIParamBinToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) { + *datalen = 0; + + int tmplen = 0; + uint8_t tmpstr[(256 * 2) + 1] = {0}; + + // concat all strings in argstr into tmpstr[] + // + int res = CLIParamStrToBuf(argstr, tmpstr, sizeof(tmpstr), &tmplen); + if (res || tmplen == 0) { + return res; + } + + res = param_getbin_to_eol((char *)tmpstr, 0, data, maxdatalen, datalen); + switch (res) { + case 1: + PrintAndLogEx(ERR, "Parameter error: Invalid BINARY value\n"); + break; + case 2: + PrintAndLogEx(ERR, "Parameter error: parameter too large\n"); + break; + } + return res; +} + int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) { *datalen = 0; if (!argstr->count) diff --git a/client/deps/cliparser/cliparser.h b/client/deps/cliparser/cliparser.h index 78bb59f32..0213d1917 100644 --- a/client/deps/cliparser/cliparser.h +++ b/client/deps/cliparser/cliparser.h @@ -66,6 +66,7 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); +int CLIParamBinToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def); int arg_get_u64_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint64_t def, uint64_t *out, uint8_t nlen, bool optional); diff --git a/client/src/cmddata.c b/client/src/cmddata.c index ba3d2b5f1..2809fbecb 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -224,12 +224,6 @@ static int usage_data_detectclock(void) { return PM3_SUCCESS; } -static int usage_data_bin2hex(void) { - PrintAndLogEx(NORMAL, "Usage: data bin2hex "); - PrintAndLogEx(NORMAL, " This function will ignore all characters not 1 or 0 (but stop reading on whitespace)"); - return PM3_SUCCESS; -} - //set the demod buffer with given array of binary (one bit per byte) //by marshmellow void setDemodBuff(uint8_t *buff, size_t size, size_t start_idx) { @@ -2224,31 +2218,49 @@ static int CmdZerocrossings(const char *Cmd) { * @return */ static int Cmdbin2hex(const char *Cmd) { - int bg = 0, en = 0; - if (param_getptr(Cmd, &bg, &en, 0)) - return usage_data_bin2hex(); - //Number of digits supplied as argument - size_t length = en - bg + 1; - size_t bytelen = (length + 7) / 8; + CLIParserContext *ctx; + CLIParserInit(&ctx, "data bin2hex", + "This function converts binary to hexadecimal. It will ignore all\n" + "characters not 1 or 0 but stop reading on whitespace", + "data bin2hex -d 0101111001010" + ); + void *argtable[] = { + arg_param_begin, + arg_strx0("d", "data", "", "binary string to convert"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + int blen = 0; + uint8_t binarr[400] = {0x00}; + int res = CLIParamBinToBuf(arg_get_str(ctx, 1), binarr, sizeof(binarr), &blen); + CLIParserFree(ctx); + + if (res) { + PrintAndLogEx(FAILED, "Error parsing binary string"); + return PM3_EINVARG; + } + + // Number of digits supplied as argument + size_t bytelen = (blen + 7) / 8; uint8_t *arr = (uint8_t *) calloc(bytelen, sizeof(uint8_t)); memset(arr, 0, bytelen); BitstreamOut bout = { arr, 0, 0 }; - for (; bg <= en; bg++) { - char c = Cmd[bg]; - if (c == '1') + for (int i = 0; i < blen; i++) { + uint8_t c = binarr[i]; + if (c == 1) pushBit(&bout, 1); - else if (c == '0') + else if (c == 0) pushBit(&bout, 0); else - PrintAndLogEx(NORMAL, "Ignoring '%c'", c); + PrintAndLogEx(INFO, "Ignoring '%d' at pos %d", c, i); } if (bout.numbits % 8 != 0) - PrintAndLogEx(NORMAL, "[padded with %d zeroes]", 8 - (bout.numbits % 8)); + PrintAndLogEx(INFO, "[right padded with %d zeroes]", 8 - (bout.numbits % 8)); - PrintAndLogEx(NORMAL, "%s", sprint_hex(arr, bytelen)); + PrintAndLogEx(SUCCESS, _YELLOW_("%s"), sprint_hex(arr, bytelen)); free(arr); return PM3_SUCCESS; } @@ -2256,8 +2268,8 @@ static int Cmdbin2hex(const char *Cmd) { static int Cmdhex2bin(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data hex2bin", - "This function will ignore all non-hexadecimal characters\n" - "but stop reading on whitespace", + "This function converts hexadecimal to binary. It will ignore all\n" + "non-hexadecimal characters but stop reading on whitespace", "data hex2bin -d 01020304" ); void *argtable[] = { diff --git a/client/src/util.c b/client/src/util.c index 978cb4b45..bcebabfa0 100644 --- a/client/src/util.c +++ b/client/src/util.c @@ -285,36 +285,33 @@ char *sprint_hex_inrow_spaces(const uint8_t *data, const size_t len, size_t spac char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks) { // make sure we don't go beyond our char array memory - size_t in_index = 0, out_index = 0; - size_t rowlen = (len > MAX_BIN_BREAK_LENGTH) ? MAX_BIN_BREAK_LENGTH : len; - if (breaks > 0 && len % breaks != 0) - rowlen = (len + (len / breaks) > MAX_BIN_BREAK_LENGTH) ? MAX_BIN_BREAK_LENGTH : len + (len / breaks); - - //PrintAndLogEx(NORMAL, "(sprint_bin_break) rowlen %d", rowlen); - - static char buf[MAX_BIN_BREAK_LENGTH]; // 3072 + end of line characters if broken at 8 bits - //clear memory + // 3072 + end of line characters if broken at 8 bits + static char buf[MAX_BIN_BREAK_LENGTH]; memset(buf, 0x00, sizeof(buf)); char *tmp = buf; // loop through the out_index to make sure we don't go too far - for (out_index = 0; out_index < rowlen; out_index++) { - // set character - if (data[in_index] == 7) // Manchester wrong bit marker - sprintf(tmp++, "."); - else - sprintf(tmp++, "%u", data[in_index]); + for (int i = 0; i < rowlen; i++) { + + char c = data[i]; + // manchester wrong bit marker + if (c == 7) + c = '.'; + else + c += '0'; + + *(tmp++) = c; // check if a line break is needed and we have room to print it in our array - if ((breaks > 0) && !((in_index + 1) % breaks) && (out_index + 1 != rowlen)) { - sprintf(tmp++, "%s", "\n"); + if (breaks) { + if (((i + 1) % breaks) == 0) { + + *(tmp++) = '\n'; + } } - - in_index++; } - return buf; } /* @@ -714,6 +711,48 @@ int param_gethex_to_eol(const char *line, int paramnum, uint8_t *data, int maxda return 0; } +int param_getbin_to_eol(const char *line, int paramnum, uint8_t *data, int maxdatalen, int *datalen) { + int bg, en; + if (param_getptr(line, &bg, &en, paramnum)) { + return 1; + } + + *datalen = 0; + char buf[5] = {0}; + int indx = bg; + while (line[indx]) { + if (line[indx] == '\t' || line[indx] == ' ') { + indx++; + continue; + } + + if (line[indx] == '0' || line[indx] == '1') { + buf[strlen(buf) + 1] = 0x00; + buf[strlen(buf)] = line[indx]; + } else { + // if we have symbols other than spaces and 0/1 + return 1; + } + + if (*datalen >= maxdatalen) { + // if we dont have space in buffer and have symbols to translate + return 2; + } + + if (strlen(buf) > 0) { + uint32_t temp = 0; + sscanf(buf, "%d", &temp); + data[*datalen] = (uint8_t)(temp & 0xff); + *buf = 0; + (*datalen)++; + } + + indx++; + } + return 0; +} + + int param_getstr(const char *line, int paramnum, char *str, size_t buffersize) { int bg, en; @@ -768,9 +807,8 @@ int hextobinarray(char *target, char *source) { // convert hex to human readable binary string int hextobinstring(char *target, char *source) { - int length; - - if (!(length = hextobinarray(target, source))) + int length = hextobinarray(target, source); + if (length == 0) return 0; binarraytobinstring(target, target, length); return length; diff --git a/client/src/util.h b/client/src/util.h index 7577c216e..6a2933d5a 100644 --- a/client/src/util.h +++ b/client/src/util.h @@ -77,6 +77,7 @@ uint8_t param_isdec(const char *line, int paramnum); int param_gethex(const char *line, int paramnum, uint8_t *data, int hexcnt); int param_gethex_ex(const char *line, int paramnum, uint8_t *data, int *hexcnt); int param_gethex_to_eol(const char *line, int paramnum, uint8_t *data, int maxdatalen, int *datalen); +int param_getbin_to_eol(const char *line, int paramnum, uint8_t *data, int maxdatalen, int *datalen); int param_getstr(const char *line, int paramnum, char *str, size_t buffersize); int hextobinarray(char *target, char *source); From 28dbe756413005efe2d7c89bd0b208812eb1f19d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 11:06:35 +0100 Subject: [PATCH 072/373] text --- doc/cliparser_todo.txt | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 188870467..040d8f7ba 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -2,35 +2,20 @@ clear analyse foo data biphaserawdecode data detectclock -data fsktonrz data manrawdecode data rawdemod data askedgedetect data autocorr data dirthreshold -data hide data hpf data iir data grid -data ltrim -data mtrim -data norm -data plot -data rtrim data setgraphmarkers data shiftgraphzero data zerocrossings data convertbitstream data getbitstream -data bin2hex -data bitsamples -data clear data hexsamples -data hex2bin -data print -data samples -data setdebugmode -data tune hf 15 dump hf 15 info hf 15 raw From 2287390b7e0875a4dcbff8b0863e7964e19ce68b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 11:43:14 +0100 Subject: [PATCH 073/373] data hexsamples - now use cliparser --- client/src/cmddata.c | 58 ++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 2809fbecb..cf077d593 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1483,22 +1483,38 @@ static int CmdSetGraphMarkers(const char *Cmd) { } static int CmdHexsamples(const char *Cmd) { - uint32_t requested = 0; - uint32_t offset = 0; - char string_buf[25]; - char *string_ptr = string_buf; - uint8_t got[pm3_capabilities.bigbuf_size]; - sscanf(Cmd, "%u %u", &requested, &offset); + CLIParserContext *ctx; + CLIParserInit(&ctx, "data hexsamples", + "Dump big buffer as hex bytes", + "data hexsamples -n 128 --> dumps 128 bytes from offset 0" + ); + void *argtable[] = { + arg_param_begin, + arg_u64_0("b", "breaks", "", "row break, def 16"), + arg_u64_0("n", NULL, "", "num of bytes to download"), + arg_u64_0("o", "offset", "", "offset in big buffer"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + uint32_t breaks = arg_get_u32_def(ctx, 1, 16); + uint32_t requested = arg_get_u32_def(ctx, 2, 8); + uint32_t offset = arg_get_u32_def(ctx, 3, 0); + CLIParserFree(ctx); - /* if no args send something */ - if (requested == 0) - requested = 8; - if (requested > pm3_capabilities.bigbuf_size) + // sanity checks + if (requested > pm3_capabilities.bigbuf_size) { requested = pm3_capabilities.bigbuf_size; + PrintAndLogEx(INFO, "n is larger than big buffer size, will use %u", requested); + } + uint8_t got[pm3_capabilities.bigbuf_size]; if (offset + requested > sizeof(got)) { - PrintAndLogEx(NORMAL, "Tried to read past end of buffer, + > %d", pm3_capabilities.bigbuf_size); + PrintAndLogEx(NORMAL, "Tried to read past end of buffer, + > %d" + , requested + , offset + , pm3_capabilities.bigbuf_size + ); return PM3_EINVARG; } @@ -1507,23 +1523,7 @@ static int CmdHexsamples(const char *Cmd) { return PM3_ESOFT; } - uint8_t i = 0; - for (uint32_t j = 0; j < requested; j++) { - i++; - string_ptr += sprintf(string_ptr, "%02x ", got[j]); - if (i == 8) { - *(string_ptr - 1) = '\0'; // remove the trailing space - PrintAndLogEx(NORMAL, "%s", string_buf); - string_buf[0] = '\0'; - string_ptr = string_buf; - i = 0; - } - if (j == requested - 1 && string_buf[0] != '\0') { // print any remaining bytes - *(string_ptr - 1) = '\0'; - PrintAndLogEx(NORMAL, "%s", string_buf); - string_buf[0] = '\0'; - } - } + print_hex_break(got, requested, breaks); return PM3_SUCCESS; } @@ -2710,7 +2710,7 @@ static command_t CommandTable[] = { {"bin2hex", Cmdbin2hex, AlwaysAvailable, "Converts binary to hexadecimal"}, {"bitsamples", CmdBitsamples, IfPm3Present, "Get raw samples as bitstring"}, {"clear", CmdBuffClear, AlwaysAvailable, "Clears bigbuf on deviceside and graph window"}, - {"hexsamples", CmdHexsamples, IfPm3Present, " [] -- Dump big buffer as hex bytes"}, + {"hexsamples", CmdHexsamples, IfPm3Present, "Dump big buffer as hex bytes"}, {"hex2bin", Cmdhex2bin, AlwaysAvailable, "Converts hexadecimal to binary"}, {"load", CmdLoad, AlwaysAvailable, "Load contents of file into graph window"}, {"ndef", CmdDataNDEF, AlwaysAvailable, "Decode NDEF records"}, From e9dd4f6b4ae6fc4194e81c94b69f5d7b8313e0b5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 11:53:01 +0100 Subject: [PATCH 074/373] data hpf, convertbitstream, getbitstream - now uses cliparser --- client/src/cmddata.c | 46 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index cf077d593..cc0119c17 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -499,15 +499,42 @@ int CmdPrintDemodBuff(const char *Cmd) { // this function strictly converts >1 to 1 and <1 to 0 for each sample in the graphbuffer int CmdGetBitStream(const char *Cmd) { - CmdHpf(Cmd); - for (uint32_t i = 0; i < GraphTraceLen; i++) - GraphBuffer[i] = (GraphBuffer[i] >= 1) ? 1 : 0; + CLIParserContext *ctx; + CLIParserInit(&ctx, "data getbitstream", + "Convert GraphBuffer's value accordingly\n" + " - larger or equal to ONE becomes ONE\n" + " - less than ONE becomes ZERO", + "data getbitstream" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + CmdHpf(""); + for (uint32_t i = 0; i < GraphTraceLen; i++) { + GraphBuffer[i] = (GraphBuffer[i] >= 1) ? 1 : 0; + } RepaintGraphWindow(); return PM3_SUCCESS; } + static int CmdConvertBitStream(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "data convertbitstream", + "Convert GraphBuffer's 0|1 values to 127|-127", + "data convertbitstream" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + if (isGraphBitstream()) { convertGraphFromBitstream(); } else { @@ -1545,7 +1572,18 @@ static int CmdHide(const char *Cmd) { // zero mean GraphBuffer int CmdHpf(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + CLIParserContext *ctx; + CLIParserInit(&ctx, "data hpf", + "Remove DC offset from trace. It should centralize around 0", + "data hpf" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + uint8_t bits[GraphTraceLen]; size_t size = getFromGraphBuf(bits); removeSignalOffset(bits, size); From 8a99db5d9f766739d95355c8b18328e5a82c9f27 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 11:53:42 +0100 Subject: [PATCH 075/373] text --- doc/cliparser_todo.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 040d8f7ba..a4db9f8f5 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -7,15 +7,11 @@ data rawdemod data askedgedetect data autocorr data dirthreshold -data hpf data iir data grid data setgraphmarkers data shiftgraphzero data zerocrossings -data convertbitstream -data getbitstream -data hexsamples hf 15 dump hf 15 info hf 15 raw From 2480eb2d2932f63dfddcfc51ba60cd5d60c42d04 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 13:02:05 +0100 Subject: [PATCH 076/373] data grid, zerocrossings - now use cliparser --- client/src/cmddata.c | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index cc0119c17..2b929c674 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1496,7 +1496,24 @@ void setClockGrid(uint32_t clk, int offset) { } int CmdGrid(const char *Cmd) { - sscanf(Cmd, "%lf %lf", &PlotGridX, &PlotGridY); + CLIParserContext *ctx; + CLIParserInit(&ctx, "data grid", + "This function overlay grid on graph plot window.\n" + "use zero value to turn off either", + "data grid --> turn off\n" + "data grid -x 64 -y 50" + ); + void *argtable[] = { + arg_param_begin, + arg_dbl0("x", NULL, "", "plot grid X coord"), + arg_dbl0("y", NULL, "", "plot grid Y coord"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + PlotGridX = arg_get_dbl_def(ctx, 1, 0); + PlotGridY = arg_get_dbl_def(ctx, 2, 0); + CLIParserFree(ctx); + PrintAndLogEx(INFO, "Setting X %.0f Y %.0f", PlotGridX, PlotGridY); PlotGridXdefault = PlotGridX; PlotGridYdefault = PlotGridY; RepaintGraphWindow(); @@ -2219,7 +2236,18 @@ static int CmdDirectionalThreshold(const char *Cmd) { } static int CmdZerocrossings(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + CLIParserContext *ctx; + CLIParserInit(&ctx, "data zerocrossings", + "Count time between zero-crossings", + "data zerocrossings" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + // Zero-crossings aren't meaningful unless the signal is zero-mean. CmdHpf(""); @@ -2245,7 +2273,6 @@ static int CmdZerocrossings(const char *Cmd) { size_t size = getFromGraphBuf(bits); // set signal properties low/high/mean/amplitude and is_noise detection computeSignalProperties(bits, size); - RepaintGraphWindow(); return PM3_SUCCESS; } @@ -2731,7 +2758,7 @@ static command_t CommandTable[] = { {"hide", CmdHide, AlwaysAvailable, "Hide graph window"}, {"hpf", CmdHpf, AlwaysAvailable, "Remove DC offset from trace"}, {"iir", CmdDataIIR, AlwaysAvailable, "Apply IIR buttersworth filter on plotdata"}, - {"grid", CmdGrid, AlwaysAvailable, " -- overlay grid on graph window, use zero value to turn off either"}, + {"grid", CmdGrid, AlwaysAvailable, "overlay grid on graph window"}, {"ltrim", CmdLtrim, AlwaysAvailable, "Trim samples from left of trace"}, {"mtrim", CmdMtrim, AlwaysAvailable, "Trim out samples from the specified start to the specified stop"}, {"norm", CmdNorm, AlwaysAvailable, "Normalize max/min to +/-128"}, From 1550bada28b73c04ef020c81d5d4b6f3241af5f7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 13:02:21 +0100 Subject: [PATCH 077/373] text --- doc/cliparser_todo.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index a4db9f8f5..78abb0413 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -8,10 +8,8 @@ data askedgedetect data autocorr data dirthreshold data iir -data grid data setgraphmarkers data shiftgraphzero -data zerocrossings hf 15 dump hf 15 info hf 15 raw From 9b1f7ca7a30015cc2e890d6cc5bda3df4f521efa Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 13:13:10 +0100 Subject: [PATCH 078/373] data iir, shiftgraphzero - now uses cliparser --- client/src/cmddata.c | 37 +++++++++++++++++++++++++++++++------ doc/cliparser_todo.txt | 2 -- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 2b929c674..b60caef83 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1106,9 +1106,21 @@ static int CmdUndecimate(const char *Cmd) { // shift graph zero up or down based on input + or - static int CmdGraphShiftZero(const char *Cmd) { - int shift = 0; - //set options from parameters entered with the command - sscanf(Cmd, "%i", &shift); + + CLIParserContext *ctx; + CLIParserInit(&ctx, "data shiftgraphzero", + "Shift 0 for Graphed wave + or - shift value", + "data shiftgraphzero -n 10 --> shift 10 points\n" + "data shiftgraphzero -n -22 --> shift negative 22 points" + ); + void *argtable[] = { + arg_param_begin, + arg_int1("n", NULL, "", "shift + or -"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + int shift = arg_get_int_def(ctx, 1, 0); + CLIParserFree(ctx); for (size_t i = 0; i < GraphTraceLen; i++) { int shiftedVal = GraphBuffer[i] + shift; @@ -2536,8 +2548,21 @@ static int CmdFSKToNRZ(const char *Cmd) { } static int CmdDataIIR(const char *Cmd) { - uint8_t k = param_get8(Cmd, 0); - //iceIIR_Butterworth(GraphBuffer, GraphTraceLen); + + CLIParserContext *ctx; + CLIParserInit(&ctx, "data iir", + "Apply IIR buttersworth filter on plot data", + "data iir -n 2" + ); + void *argtable[] = { + arg_param_begin, + arg_u64_1("n", NULL, "", "factor n"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + uint8_t k = arg_get_u32_def(ctx, 1, 0); + CLIParserFree(ctx); + iceSimple_Filter(GraphBuffer, GraphTraceLen, k); uint8_t bits[GraphTraceLen]; @@ -2757,7 +2782,7 @@ static command_t CommandTable[] = { {"undecimate", CmdUndecimate, AlwaysAvailable, "Un-decimate samples"}, {"hide", CmdHide, AlwaysAvailable, "Hide graph window"}, {"hpf", CmdHpf, AlwaysAvailable, "Remove DC offset from trace"}, - {"iir", CmdDataIIR, AlwaysAvailable, "Apply IIR buttersworth filter on plotdata"}, + {"iir", CmdDataIIR, AlwaysAvailable, "Apply IIR buttersworth filter on plot data"}, {"grid", CmdGrid, AlwaysAvailable, "overlay grid on graph window"}, {"ltrim", CmdLtrim, AlwaysAvailable, "Trim samples from left of trace"}, {"mtrim", CmdMtrim, AlwaysAvailable, "Trim out samples from the specified start to the specified stop"}, diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 78abb0413..348c0cb27 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -7,9 +7,7 @@ data rawdemod data askedgedetect data autocorr data dirthreshold -data iir data setgraphmarkers -data shiftgraphzero hf 15 dump hf 15 info hf 15 raw From 7444702a659290f320a46ab1ace2a119b8ea9137 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 13:25:36 +0100 Subject: [PATCH 079/373] data setgraphmarkers --- client/src/cmddata.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index b60caef83..40f0f0f0f 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1533,7 +1533,23 @@ int CmdGrid(const char *Cmd) { } static int CmdSetGraphMarkers(const char *Cmd) { - sscanf(Cmd, "%i %i", &CursorCPos, &CursorDPos); + CLIParserContext *ctx; + CLIParserInit(&ctx, "data setgraphmarkers", + "Set blue and orange marker in graph window", + "data setgraphmarkers --> turn off\n" + "data setgraphmarkers -a 64 -b 50" + ); + void *argtable[] = { + arg_param_begin, + arg_u64_0("a", NULL, "", "orange marker"), + arg_u64_0("b", NULL, "", "blue marker"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CursorCPos = arg_get_u32_def(ctx, 1, 0); + CursorDPos = arg_get_u32_def(ctx, 2, 0); + CLIParserFree(ctx); + PrintAndLogEx(INFO, "Setting orange %u blue %u", CursorCPos, CursorDPos); RepaintGraphWindow(); return PM3_SUCCESS; } @@ -2560,7 +2576,7 @@ static int CmdDataIIR(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); - uint8_t k = arg_get_u32_def(ctx, 1, 0); + uint8_t k = (arg_get_u32_def(ctx, 1, 0) & 0xFF); CLIParserFree(ctx); iceSimple_Filter(GraphBuffer, GraphTraceLen, k); @@ -2789,8 +2805,8 @@ static command_t CommandTable[] = { {"norm", CmdNorm, AlwaysAvailable, "Normalize max/min to +/-128"}, {"plot", CmdPlot, AlwaysAvailable, "Show graph window"}, {"rtrim", CmdRtrim, AlwaysAvailable, "Trim samples from right of trace"}, - {"setgraphmarkers", CmdSetGraphMarkers, AlwaysAvailable, "[orange_marker] [blue_marker] (in graph window)"}, - {"shiftgraphzero", CmdGraphShiftZero, AlwaysAvailable, " -- Shift 0 for Graphed wave + or - shift value"}, + {"setgraphmarkers", CmdSetGraphMarkers, AlwaysAvailable, "Set blue and orange marker in graph window"}, + {"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"}, From d906f619572a3032485d03bfe5b9bc00687d8bd9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 13:44:55 +0100 Subject: [PATCH 080/373] data detectclock - now uses cliparser --- client/src/cmddata.c | 73 ++++++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 40f0f0f0f..a5340d03d 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -211,18 +211,6 @@ static int usage_data_autocorr(void) { PrintAndLogEx(NORMAL, " g save back to GraphBuffer (overwrite)"); return PM3_SUCCESS; } -static int usage_data_detectclock(void) { - PrintAndLogEx(NORMAL, "Usage: data detectclock [modulation] "); - PrintAndLogEx(NORMAL, " [modulation as char], specify the modulation type you want to detect the clock of"); - PrintAndLogEx(NORMAL, " , specify the clock (optional - to get best start position only)"); - PrintAndLogEx(NORMAL, " 'a' = ask, 'f' = fsk, 'n' = nrz/direct, 'p' = psk"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data detectclock a = detect the clock of an ask modulated wave in the GraphBuffer"); - PrintAndLogEx(NORMAL, " data detectclock f = detect the clock of an fsk modulated wave in the GraphBuffer"); - PrintAndLogEx(NORMAL, " data detectclock p = detect the clock of an psk modulated wave in the GraphBuffer"); - PrintAndLogEx(NORMAL, " data detectclock n = detect the clock of an nrz/direct modulated wave in the GraphBuffer"); - return PM3_SUCCESS; -} //set the demod buffer with given array of binary (one bit per byte) //by marshmellow @@ -1164,30 +1152,49 @@ static int CmdAskEdgeDetect(const char *Cmd) { // uses data from graphbuffer // adjusted to take char parameter for type of modulation to find the clock - by marshmellow. static int CmdDetectClockRate(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 6 || strlen(Cmd) == 0 || cmdp == 'h') - return usage_data_detectclock(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "data detectclock", + "Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer", + "data detectclock -A --> detect clock of an ask wave in GraphBuffer\n" + "data detectclock -F --> detect clock of an fsk wave in GraphBuffer\n" + "data detectclock -N --> detect clock of an psk wave in GraphBuffer\n" + "data detectclock -P --> detect clock of an nrz/direct wave in GraphBuffer" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0("A", "ASK", "specify ASK modulation clock detection"), + arg_lit0("F", "FSK", "specify FSK modulation clock detection"), + arg_lit0("N", "NZR", "specify NZR/DIRECT modulation clock detection"), + arg_lit0("P", "PSK", "specify PSK modulation clock detection"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + bool a = arg_get_lit(ctx, 1); + bool f = arg_get_lit(ctx, 2); + bool n = arg_get_lit(ctx, 3); + bool p = arg_get_lit(ctx, 4); + CLIParserFree(ctx); - int clock1 = 0; - switch (cmdp) { - case 'a' : - clock1 = GetAskClock(Cmd + 1, true); - break; - case 'f' : - clock1 = GetFskClock("", true); - break; - case 'n' : - clock1 = GetNrzClock("", true); - break; - case 'p' : - clock1 = GetPskClock("", true); - break; - default : - PrintAndLogEx(NORMAL, "Please specify a valid modulation to detect the clock of - see option h for help"); - break; + int tmp = (a + f + n + p); + if (tmp > 1) { + PrintAndLogEx(WARNING, "Only specify one modulation"); + return PM3_EINVARG; } + + if (a) + GetAskClock("", true); + + if (f) + GetFskClock("", true); + + if (n) + GetNrzClock("", true); + + if (p) + GetPskClock("", true); + RepaintGraphWindow(); - return clock1; + return PM3_SUCCESS; } static char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert) { From d84837a12a1499a3dcf44dee8fe75a07ef2f98c8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 13:56:38 +0100 Subject: [PATCH 081/373] data autocorr - now uses cliparser --- client/src/cmddata.c | 64 +++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index a5340d03d..b0e860009 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -202,15 +202,6 @@ static int usage_data_rawdemod_p2(void) { PrintAndLogEx(NORMAL, " data rawdemod p2 64 1 0 = demod a psk2 tag from GraphBuffer using a clock of RF/64, inverting output and allowing 0 demod errors"); return PM3_SUCCESS; } -static int usage_data_autocorr(void) { - PrintAndLogEx(NORMAL, "Autocorrelate is used to detect repeating sequences. We use it as detection of length in bits a message inside the signal is"); - PrintAndLogEx(NORMAL, "Usage: data autocorr w [g]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " w window length for correlation - default = 4000"); - PrintAndLogEx(NORMAL, " g save back to GraphBuffer (overwrite)"); - return PM3_SUCCESS; -} //set the demod buffer with given array of binary (one bit per byte) //by marshmellow @@ -931,39 +922,38 @@ int AutoCorrelate(const int *in, int *out, size_t len, size_t window, bool SaveG } static int CmdAutoCorr(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "data autocorr", + "Autocorrelate over window is used to detect repeating sequences.\n" + "We use it as detection of how long in bits a message inside the signal is", + "data autocorr -w 4000\n" + "data autocorr -w 4000 -g" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0("g", NULL, "save back to GraphBuffer (overwrite)"), + arg_u64_0("w", "win", "", "window length for correlation. def 4000"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + bool updateGrph = arg_get_lit(ctx, 1); + uint32_t window = arg_get_u32_def(ctx, 2, 4000); + CLIParserFree(ctx); - uint32_t window = 4000; - uint8_t cmdp = 0; - bool updateGrph = false; - bool errors = false; + PrintAndLogEx(INFO, "Using window size " _YELLOW_("%u"), window); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_data_autocorr(); - case 'g': - updateGrph = true; - cmdp++; - break; - case 'w': - window = param_get32ex(Cmd, cmdp + 1, 4000, 10); - if (window >= GraphTraceLen) { - PrintAndLogEx(WARNING, "window must be smaller than trace (%zu samples)", GraphTraceLen); - errors = true; - } - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } + if (GraphTraceLen == 0) { + PrintAndLogEx(WARNING, "GraphBuffer is empty"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("lf read") "` to collect samples"); + return PM3_ESOFT; + } + + if (window >= GraphTraceLen) { + PrintAndLogEx(WARNING, "window must be smaller than trace (" _YELLOW_("%zu") " samples)", GraphTraceLen); + return PM3_EINVARG; } - //Validations - if (errors || cmdp == 0) return usage_data_autocorr(); AutoCorrelate(GraphBuffer, GraphBuffer, GraphTraceLen, window, updateGrph, true); - return PM3_SUCCESS; } From e85ae1753d1dd93b06fe2d1b12751afcaed242f0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 14:04:22 +0100 Subject: [PATCH 082/373] data dirthreshold - now uses cliparser --- client/src/cmddata.c | 21 +++++++++++++++++---- doc/cliparser_todo.txt | 4 ---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index b0e860009..cf1d58d71 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -2243,10 +2243,23 @@ int directionalThreshold(const int *in, int *out, size_t len, int8_t up, int8_t } static int CmdDirectionalThreshold(const char *Cmd) { - int8_t up = param_get8(Cmd, 0); - int8_t down = param_get8(Cmd, 1); + CLIParserContext *ctx; + CLIParserInit(&ctx, "data dirthreshold", + "Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev.", + "data dirthreshold -u 10 -d -10" + ); + void *argtable[] = { + arg_param_begin, + arg_int1("d", "down", "", "threshold down"), + arg_int1("u", "up", "", "threshold up"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + int8_t down = arg_get_int(ctx, 1); + int8_t up = arg_get_int(ctx, 2); + CLIParserFree(ctx); - PrintAndLogEx(INFO, "Applying Up Threshold: %d, Down Threshold: %d\n", up, down); + PrintAndLogEx(INFO, "Applying up threshold: " _YELLOW_("%i") ", down threshold: " _YELLOW_("%i") "\n", up, down); directionalThreshold(GraphBuffer, GraphBuffer, GraphTraceLen, up, down); @@ -2790,7 +2803,7 @@ static command_t CommandTable[] = { {"-----------", CmdHelp, AlwaysAvailable, "------------------------- " _CYAN_("Graph") "-------------------------"}, {"askedgedetect", CmdAskEdgeDetect, AlwaysAvailable, "[threshold] Adjust Graph for manual ASK demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)"}, {"autocorr", CmdAutoCorr, AlwaysAvailable, "Autocorrelation over window"}, - {"dirthreshold", CmdDirectionalThreshold, AlwaysAvailable, " -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."}, + {"dirthreshold", CmdDirectionalThreshold, AlwaysAvailable, "Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."}, {"decimate", CmdDecimate, AlwaysAvailable, "Decimate samples"}, {"undecimate", CmdUndecimate, AlwaysAvailable, "Un-decimate samples"}, {"hide", CmdHide, AlwaysAvailable, "Hide graph window"}, diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 348c0cb27..8626e7216 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -1,13 +1,9 @@ clear analyse foo data biphaserawdecode -data detectclock data manrawdecode data rawdemod data askedgedetect -data autocorr -data dirthreshold -data setgraphmarkers hf 15 dump hf 15 info hf 15 raw From 200cd1d2f23bbd92cae28663e29b21ea8104dfaa Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 15:19:22 +0100 Subject: [PATCH 083/373] data askedgedetect - now uses cliparser --- client/src/cmddata.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index cf1d58d71..b5cc2cf80 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1129,13 +1129,26 @@ int AskEdgeDetect(const int *in, int *out, int len, int threshold) { // similar to dirtheshold, threshold commands // takes a threshold length which is the measured length between two samples then determines an edge static int CmdAskEdgeDetect(const char *Cmd) { - int thresLen = 25; - int ans = 0; - sscanf(Cmd, "%i", &thresLen); - ans = AskEdgeDetect(GraphBuffer, GraphBuffer, GraphTraceLen, thresLen); + CLIParserContext *ctx; + CLIParserInit(&ctx, "data askedgedetect", + "Adjust Graph for manual ASK demod using the length of sample differences\n" + "to detect the edge of a wave", + "data askedgedetect -t 20" + ); + void *argtable[] = { + arg_param_begin, + arg_int0("t", "thres", "", "threshold, use 20 - 45 (def 25)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + int threshold = arg_get_int_def(ctx, 1, 25); + CLIParserFree(ctx); + + PrintAndLogEx(INFO, "using threshold " _YELLOW_("%i"), threshold); + int res = AskEdgeDetect(GraphBuffer, GraphBuffer, GraphTraceLen, threshold); RepaintGraphWindow(); - return ans; + return res; } // Print our clock rate From 4a29d498802f98b44922fc731bd371fa97f95600 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 16:57:00 +0100 Subject: [PATCH 084/373] data biphasedecode - now uses cliparser --- client/src/cmddata.c | 66 ++++++++++++++++++++++-------------------- doc/cliparser_todo.txt | 1 - 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index b5cc2cf80..27b57212f 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -46,20 +46,6 @@ static int usage_data_manrawdecode(void) { PrintAndLogEx(NORMAL, " Example: data manrawdecode = decode manchester bitstream from the demodbuffer"); return PM3_SUCCESS; } -static int usage_data_biphaserawdecode(void) { - PrintAndLogEx(NORMAL, "Usage: data biphaserawdecode [offset] [invert] [maxErr]"); - PrintAndLogEx(NORMAL, " Converts 10 or 01 to 1 and 11 or 00 to 0"); - PrintAndLogEx(NORMAL, " --must have binary sequence in demodbuffer (run data askrawdemod first)"); - PrintAndLogEx(NORMAL, " --invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " [offset <0|1>], set to 0 not to adjust start position or to 1 to adjust decode start position"); - PrintAndLogEx(NORMAL, " [invert <0|1>], set to 1 to invert output"); - PrintAndLogEx(NORMAL, " [maxErr int], set max errors tolerated - default=20"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data biphaserawdecode = decode biphase bitstream from the demodbuffer"); - PrintAndLogEx(NORMAL, " Example: data biphaserawdecode 1 1 = decode biphase bitstream from the demodbuffer, set offset, and invert output"); - return PM3_SUCCESS; -} static int usage_data_rawdemod(void) { PrintAndLogEx(NORMAL, "Usage: data rawdemod [modulation] |"); PrintAndLogEx(NORMAL, " [modulation] as 2 char,"); @@ -724,40 +710,58 @@ static int Cmdmandecoderaw(const char *Cmd) { * param masxErr maximum tolerated errors */ static int CmdBiphaseDecodeRaw(const char *Cmd) { - size_t size = 0; - int offset = 0, invert = 0, maxErr = 20, errCnt = 0; - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 5 || cmdp == 'h') return usage_data_biphaserawdecode(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "data biphaserawdecode", + "Biphase decode bin stream in DemodBuffer\n" + "Converts 10 or 01 -> 1 and 11 or 00 -> 0\n" + " - must have binary sequence in demodbuffer (run `data askrawdemod` before)\n" + " - invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester", + "data biphaserawdecode --> decode biphase bitstream from the demodbuffer\n" + "data biphaserawdecode -oi --> decode biphase bitstream from the demodbuffer, adjust offset, and invert output" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0("o", "offset", "set to adjust decode start position"), + arg_lit0("i", "inv", "invert output"), + arg_int0(NULL, "err", "", "set max errors tolerated (def 20)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + int offset = arg_get_lit(ctx, 1); + bool invert = arg_get_lit(ctx, 2); + int max_err = arg_get_int_def(ctx, 3, 20); + CLIParserFree(ctx); - sscanf(Cmd, "%i %i %i", &offset, &invert, &maxErr); if (DemodBufferLen == 0) { PrintAndLogEx(WARNING, "DemodBuffer Empty - run " _YELLOW_("'data rawdemod ar'")" first"); return PM3_ESOFT; } uint8_t bits[MAX_DEMOD_BUF_LEN] = {0}; - size = sizeof(bits); + size_t size = sizeof(bits); if (!getDemodBuff(bits, &size)) return PM3_ESOFT; - errCnt = BiphaseRawDecode(bits, &size, &offset, invert); - if (errCnt < 0) { - PrintAndLogEx(ERR, "Error during decode:%d", errCnt); + int err_cnt = BiphaseRawDecode(bits, &size, &offset, invert); + if (err_cnt < 0) { + PrintAndLogEx(ERR, "Error during decode " _RED_("%i"), err_cnt); return PM3_ESOFT; } - if (errCnt > maxErr) { - PrintAndLogEx(ERR, "Too many errors attempting to decode: %d", errCnt); + if (err_cnt > max_err) { + PrintAndLogEx(ERR, "Too many errors attempting to decode " _RED_("%i"), err_cnt); return PM3_ESOFT; } - if (errCnt > 0) - PrintAndLogEx(WARNING, "# Errors found during Demod (shown as " _YELLOW_("7")" in bit stream): %d", errCnt); + if (err_cnt > 0) { + PrintAndLogEx(WARNING, "# %i errors found during demod (shown as " _YELLOW_(".")" in bit stream) ", err_cnt); + } - PrintAndLogEx(NORMAL, "Biphase Decoded using offset: %d - # invert:%d - data:", offset, invert); - PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 32)); + PrintAndLogEx(INFO, "Biphase decoded using offset: %d%s", offset, (invert) ? ", inverted" : ""); + PrintAndLogEx(INFO, "%s", sprint_bin_break(bits, size, 32)); //remove first bit from raw demod - if (offset) + if (offset) { setDemodBuff(DemodBuffer, DemodBufferLen - offset, offset); + } setClockGrid(g_DemodClock, g_DemodStartIdx + g_DemodClock * offset / 2); return PM3_SUCCESS; @@ -2814,7 +2818,7 @@ static command_t CommandTable[] = { {"rawdemod", CmdRawDemod, AlwaysAvailable, "Demodulate the data in the GraphBuffer and output binary"}, {"-----------", CmdHelp, AlwaysAvailable, "------------------------- " _CYAN_("Graph") "-------------------------"}, - {"askedgedetect", CmdAskEdgeDetect, AlwaysAvailable, "[threshold] Adjust Graph for manual ASK demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)"}, + {"askedgedetect", CmdAskEdgeDetect, AlwaysAvailable, "Adjust Graph for manual ASK demod using the length of sample differences to detect the edge of a wave"}, {"autocorr", CmdAutoCorr, AlwaysAvailable, "Autocorrelation over window"}, {"dirthreshold", CmdDirectionalThreshold, AlwaysAvailable, "Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."}, {"decimate", CmdDecimate, AlwaysAvailable, "Decimate samples"}, diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 8626e7216..62299f97a 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -3,7 +3,6 @@ analyse foo data biphaserawdecode data manrawdecode data rawdemod -data askedgedetect hf 15 dump hf 15 info hf 15 raw From 5ab381b28af8172bfb990178b370dbf4078cd360 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 17:06:53 +0100 Subject: [PATCH 085/373] clear - now uses cliparser --- client/src/cmdmain.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/client/src/cmdmain.c b/client/src/cmdmain.c index 7e0c823a4..85ec8e807 100644 --- a/client/src/cmdmain.c +++ b/client/src/cmdmain.c @@ -274,6 +274,17 @@ static int CmdPref(const char *Cmd) { } static int CmdClear(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "clear", + "Clear the Proxmark3 client terminal screen", + "clear" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); PrintAndLogEx(NORMAL, _CLEAR_ _TOP_ ""); return PM3_SUCCESS; } From 50fb9ff45bdde6d5a36239b3246b1d7c4f7f98f6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 17:07:49 +0100 Subject: [PATCH 086/373] text --- doc/cliparser_todo.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 62299f97a..7475952f2 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -1,6 +1,4 @@ -clear analyse foo -data biphaserawdecode data manrawdecode data rawdemod hf 15 dump From e69cc3936d496f0b61cbf552de518122f59ab6d1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 19:22:28 +0100 Subject: [PATCH 087/373] fw check --- client/src/cmdhw.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/src/cmdhw.c b/client/src/cmdhw.c index 49fe3cc9c..eed42dff5 100644 --- a/client/src/cmdhw.c +++ b/client/src/cmdhw.c @@ -1023,6 +1023,9 @@ void pm3_version(bool verbose, bool oneliner) { struct p *payload = (struct p *)&resp.data.asBytes; PrintAndLogEx(NORMAL, payload->versionstr); + if (strstr(payload->versionstr, "2s30vq100") == NULL) { + PrintAndLogEx(NORMAL, " FPGA firmware... %s", _RED_("chip mismatch")); + } lookupChipID(payload->id, payload->section_size); } From 585e067ba9f6d316c5631ee61d559e85a9b1c4c2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 19:27:17 +0100 Subject: [PATCH 088/373] data manrawdecode - now uses cliparser --- client/src/cmddata.c | 76 ++++++++++++++++++++++++------------------ doc/cliparser_todo.txt | 1 - 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 27b57212f..84705a586 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -36,16 +36,6 @@ int g_DemodClock = 0; static int CmdHelp(const char *Cmd); -static int usage_data_manrawdecode(void) { - PrintAndLogEx(NORMAL, "Usage: data manrawdecode [invert] [maxErr]"); - PrintAndLogEx(NORMAL, " Takes 10 and 01 and converts to 0 and 1 respectively"); - PrintAndLogEx(NORMAL, " --must have binary sequence in demodbuffer (run data askrawdemod first)"); - PrintAndLogEx(NORMAL, " [invert] invert output"); - PrintAndLogEx(NORMAL, " [maxErr] set number of errors allowed (default = 20)"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data manrawdecode = decode manchester bitstream from the demodbuffer"); - return PM3_SUCCESS; -} static int usage_data_rawdemod(void) { PrintAndLogEx(NORMAL, "Usage: data rawdemod [modulation] |"); PrintAndLogEx(NORMAL, " [modulation] as 2 char,"); @@ -650,18 +640,34 @@ static int Cmdaskmandemod(const char *Cmd) { // manchester decode // strictly take 10 and 01 and convert to 0 and 1 static int Cmdmandecoderaw(const char *Cmd) { - size_t size = 0; - int high = 0, low = 0; - size_t i = 0; - uint16_t errCnt = 0; - int invert = 0, maxErr = 20; - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 5 || cmdp == 'h') return usage_data_manrawdecode(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "data manrawdecode", + "Manchester decode binary stream in DemodBuffer\n" + "Converts 10 and 01 and converts to 0 and 1 respectively\n" + " - must have binary sequence in demodbuffer (run `data rawdemod ar` before)", + "data manrawdecode" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0("i", "inv", "invert output"), + arg_int0(NULL, "err", "", "set max errors tolerated (def 20)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + bool invert = arg_get_lit(ctx, 1); + int max_err = arg_get_int_def(ctx, 2, 20); + CLIParserFree(ctx); - if (DemodBufferLen == 0) return PM3_ESOFT; + if (DemodBufferLen == 0) { + PrintAndLogEx(WARNING, "DemodBuffer empty, run " _YELLOW_("`data rawdemod ar`")); + return PM3_ESOFT; + } uint8_t bits[MAX_DEMOD_BUF_LEN] = {0}; + // make sure its just binary data 0|1|7 in buffer + int high = 0, low = 0; + size_t i = 0; for (; i < DemodBufferLen; ++i) { if (DemodBuffer[i] > high) high = DemodBuffer[i]; @@ -671,23 +677,27 @@ static int Cmdmandecoderaw(const char *Cmd) { } if (high > 7 || low < 0) { - PrintAndLogEx(ERR, "Error: please raw demod the wave first then manchester raw decode"); + PrintAndLogEx(ERR, "Error: please first raw demod then manchester raw decode"); return PM3_ESOFT; } - sscanf(Cmd, "%i %i", &invert, &maxErr); - size = i; - uint8_t alignPos = 0; - errCnt = manrawdecode(bits, &size, invert, &alignPos); - if (errCnt >= maxErr) { - PrintAndLogEx(ERR, "Too many errors: %u", errCnt); + size_t size = i; + uint8_t offset = 0; + uint16_t err_cnt = manrawdecode(bits, &size, invert, &offset); + if (err_cnt > max_err) { + PrintAndLogEx(ERR, "Too many errors attempting to decode " _RED_("%i"), err_cnt); return PM3_ESOFT; } - PrintAndLogEx(NORMAL, "Manchester Decoded - # errors:%d - data:", errCnt); - PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 32)); + if (err_cnt > 0) { + PrintAndLogEx(WARNING, "# %i errors found during demod (shown as " _YELLOW_(".")" in bit stream) ", err_cnt); + } - if (errCnt == 0) { + PrintAndLogEx(INFO, "Manchester decoded %s", (invert) ? "( inverted )" : ""); + PrintAndLogEx(INFO, "%s", sprint_bin_break(bits, size, 32)); + + // try decode EM410x + if (err_cnt == 0) { uint64_t id = 0; uint32_t hi = 0; size_t idx = 0; @@ -697,6 +707,8 @@ static int Cmdmandecoderaw(const char *Cmd) { printEM410x(hi, id, false); } } + + setClockGrid(g_DemodClock, g_DemodStartIdx + g_DemodClock / 2); return PM3_SUCCESS; } @@ -712,9 +724,9 @@ static int Cmdmandecoderaw(const char *Cmd) { static int CmdBiphaseDecodeRaw(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data biphaserawdecode", - "Biphase decode bin stream in DemodBuffer\n" + "Biphase decode binary stream in DemodBuffer\n" "Converts 10 or 01 -> 1 and 11 or 00 -> 0\n" - " - must have binary sequence in demodbuffer (run `data askrawdemod` before)\n" + " - must have binary sequence in demodbuffer (run `data rawdemod ar` before)\n" " - invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester", "data biphaserawdecode --> decode biphase bitstream from the demodbuffer\n" "data biphaserawdecode -oi --> decode biphase bitstream from the demodbuffer, adjust offset, and invert output" @@ -733,7 +745,7 @@ static int CmdBiphaseDecodeRaw(const char *Cmd) { CLIParserFree(ctx); if (DemodBufferLen == 0) { - PrintAndLogEx(WARNING, "DemodBuffer Empty - run " _YELLOW_("'data rawdemod ar'")" first"); + PrintAndLogEx(WARNING, "DemodBuffer empty, run " _YELLOW_("`data rawdemod ar`")); return PM3_ESOFT; } @@ -755,7 +767,7 @@ static int CmdBiphaseDecodeRaw(const char *Cmd) { PrintAndLogEx(WARNING, "# %i errors found during demod (shown as " _YELLOW_(".")" in bit stream) ", err_cnt); } - PrintAndLogEx(INFO, "Biphase decoded using offset: %d%s", offset, (invert) ? ", inverted" : ""); + PrintAndLogEx(INFO, "Biphase decoded using offset %d%s", offset, (invert) ? "( inverted )" : ""); PrintAndLogEx(INFO, "%s", sprint_bin_break(bits, size, 32)); //remove first bit from raw demod diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 7475952f2..abaf61e0f 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -1,5 +1,4 @@ analyse foo -data manrawdecode data rawdemod hf 15 dump hf 15 info From dfa8a648acdfa2b94a42c0e37f88baff063cc618 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 23 Mar 2021 19:29:29 +0100 Subject: [PATCH 089/373] fix --- client/src/cmdanalyse.c | 2 +- doc/cliparser_todo.txt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/cmdanalyse.c b/client/src/cmdanalyse.c index eb83fdc9c..9a60bb9bc 100644 --- a/client/src/cmdanalyse.c +++ b/client/src/cmdanalyse.c @@ -1007,7 +1007,7 @@ static int CmdAnalyseFreq(const char *Cmd) { static int CmdAnalyseFoo(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "analyze foo", + CLIParserInit(&ctx, "analyse foo", "experiments of cliparse", "analyse foo -r a0000000a0002021" ); diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index abaf61e0f..9918f89d0 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -1,4 +1,3 @@ -analyse foo data rawdemod hf 15 dump hf 15 info From 9215aff9de54705b1ebcca40432d7901b178ea55 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 24 Mar 2021 18:39:34 +0100 Subject: [PATCH 090/373] more aid (thanks @anon) --- client/resources/aid_desfire.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/client/resources/aid_desfire.json b/client/resources/aid_desfire.json index c9360ae6a..e621cc43a 100644 --- a/client/resources/aid_desfire.json +++ b/client/resources/aid_desfire.json @@ -351,5 +351,13 @@ "Name": "Access control", "Description": "Cardax Card Data Application", "Type": "" - } + }, + { + "AID": "6F706C", + "Vendor": "Openpath", + "Country": "US", + "Name": "Access control", + "Description": "Openpath PACS Application", + "Type": "" + } ] From db3719792bc7e0fedd5efbaa6e031bb3dccd93d5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 24 Mar 2021 19:30:40 +0100 Subject: [PATCH 091/373] hf felica raw - now uses cliparser --- client/src/cmdhffelica.c | 279 ++++++++++++++++----------------------- 1 file changed, 117 insertions(+), 162 deletions(-) diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index b051f58c0..2cf30a5ec 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- // Copyright (C) 2017 October, Satsuoni -// 2017 iceman +// 2017,2021 iceman // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. @@ -23,6 +23,8 @@ #include "ui.h" #include "iso18.h" // felica_card_select_t struct #include "des.h" +#include "cliparser.h" // cliparser + #define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len)) static int CmdHelp(const char *Cmd); @@ -32,17 +34,90 @@ static void set_last_known_card(felica_card_select_t card) { last_known_card = card; } + +static void print_status_flag1_interpretation(void) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "Status Flag1:"); + PrintAndLogEx(INFO, " - 00h : Indicates the successful completion of a command."); + PrintAndLogEx(INFO, " - FFh : If an error occurs during the processing of a command that includes no list in the command packet, or if " + "an error occurs independently of any list, the card returns a response by setting FFh to Status Flag1."); + PrintAndLogEx(INFO, " - XXh : If an error occurs while processing a command that includes Service Code List or Block List " + "in the command packet, the card returns a response by setting a number in the list to Status Flag1, " + "indicating the location of the error."); +} + +static void print_status_flag2_interpration(void) { + PrintAndLogEx(INFO, "\nStatus Flag2:"); + PrintAndLogEx(INFO, " - 00h : Indicates the successful completion of a command."); + PrintAndLogEx(INFO, " - 01h : The calculated result is either less than zero when the purse data is decremented, or exceeds 4" + "Bytes when the purse data is incremented."); + PrintAndLogEx(INFO, " - 02h : The specified data exceeds the value of cashback data at cashback of purse."); + PrintAndLogEx(INFO, " - 70h : Memory error (fatal error)."); + PrintAndLogEx(INFO, " - 71h : The number of memory rewrites exceeds the upper limit (this is only a warning; data writing is " + "performed as normal). The maximum number of rewrites can differ, depending on the product being used."); + PrintAndLogEx(INFO, " In addition, Status Flag1 is either 00h or FFh depending on the product being used."); + PrintAndLogEx(INFO, " - A1h : Illegal Number of Service: Number of Service or Number of Node specified by the command falls outside the range of the prescribed value."); + PrintAndLogEx(INFO, " - A2h : Illegal command packet (specified Number of Block): Number of Block specified by the command falls outside the range of the prescribed values for the product."); + PrintAndLogEx(INFO, " - A3h : Illegal Block List (specified order of Service): Service Code List Order specified by Block List Element falls outside the Number of Service specified by the " + "command (or the Number of Service specified at the times of mutual authentication)."); + PrintAndLogEx(INFO, " - A4h : Illegal Service type: Area Attribute specified by the command or Service Attribute of Service Code is incorrect."); + PrintAndLogEx(INFO, " - A5h : Access is not allowed: Area or Service specified by the command cannot be accessed. " + "The parameter specified by the command does not satisfy the conditions for success."); + PrintAndLogEx(INFO, " - A6h : Illegal Service Code List: Target to be accessed, identified by Service Code List Order, specified by Block " + "List Element does not exist. Or, Node specified by Node Code List does not exist."); + PrintAndLogEx(INFO, " - A7h : Illegal Block List (Access Mode): Access Mode specified by Block List Element is incorrect."); + PrintAndLogEx(INFO, " - A8h : Illegal Block Number Block Number (access to the specified data is inhibited): specified by Block List Element exceeds the number of Blocks assigned to Service."); + PrintAndLogEx(INFO, " - A9h : Data write failure: This is the error that occurs in issuance commands."); + PrintAndLogEx(INFO, " - AAh : Key-change failure: Key change failed."); + PrintAndLogEx(INFO, " - ABh : Illegal Package Parity or illegal Package MAC: This is the error that occurs in issuance commands."); + PrintAndLogEx(INFO, " - ACh : Illegal parameter: This is the error that occurs in issuance commands."); + PrintAndLogEx(INFO, " - ADh : Service exists already: This is the error that occurs in issuance commands."); + PrintAndLogEx(INFO, " - AEh : Illegal System Code: This is the error that occurs in issuance commands."); + PrintAndLogEx(INFO, " - AFh : Too many simultaneous cyclic write operations: Number of simultaneous write Blocks specified by the command to Cyclic Service " + "exceeds the number of Blocks assigned to Service."); + PrintAndLogEx(INFO, " - C0h : Illegal Package Identifier: This is the error that occurs in issuance commands."); + PrintAndLogEx(INFO, " - C1h : Discrepancy of parameters inside and outside Package: This is the error that occurs in issuance commands."); + PrintAndLogEx(INFO, " - C2h : Command is disabled already: This is the error that occurs in issuance commands."); +} + +static void print_block_list_element_constraints(void) { + PrintAndLogEx(INFO, " - Each Block List Element shall satisfy the following conditions:"); + PrintAndLogEx(INFO, " - The value of Service Code List Order shall not exceed Number of Service."); + PrintAndLogEx(INFO, " - Access Mode shall be 000b."); + PrintAndLogEx(INFO, " - The target specified by Service Code shall not be Area or System."); + PrintAndLogEx(INFO, " - Service specified in Service Code List shall exist in System."); + PrintAndLogEx(INFO, " - Service Attribute of Service specified in Service Code List shall be authentication-not-required Service."); + PrintAndLogEx(INFO, " - Block Number shall be in the range of the number of Blocks assigned to the specified Service."); +} + +static void print_number_of_service_constraints(void) { + PrintAndLogEx(INFO, " - Number of Service: shall be a positive integer in the range of 1 to 16, inclusive."); +} + +static void print_number_of_block_constraints(void) { + PrintAndLogEx(INFO, " - Number of Block: shall be less than or equal to the maximum number of Blocks that can be read simultaneously. \n" + "The maximum number of Blocks that can be read simultaneously can differ, depending on the product being used. Use as default 01"); +} + +static void print_service_code_list_constraints(void) { + PrintAndLogEx(INFO, " - Service Code List: For Service Code List, only Service Code existing in the product shall be specified:"); + PrintAndLogEx(INFO, " - Even when Service Code exists in the product, Service Code not referenced from Block List shall not be specified to Service Code List."); + PrintAndLogEx(INFO, " - For existence or nonexistence of Service in a product, please check using the Request Service (or Request Service v2) command."); +} + + + /* static int usage_hf_felica_sim(void) { - PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa tag \n"); - PrintAndLogEx(NORMAL, "Usage: hf felica sim [h] t [v]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " t : 1 = FeliCa"); - PrintAndLogEx(NORMAL, " : 2 = FeliCaLiteS"); - PrintAndLogEx(NORMAL, " v : (Optional) Verbose"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf felica sim t 1 "); + PrintAndLogEx(INFO, "\n Emulating ISO/18092 FeliCa tag \n"); + PrintAndLogEx(INFO, "Usage: hf felica sim [h] t [v]"); + PrintAndLogEx(INFO, "Options:"); + PrintAndLogEx(INFO, " h : This help"); + PrintAndLogEx(INFO, " t : 1 = FeliCa"); + PrintAndLogEx(INFO, " : 2 = FeliCaLiteS"); + PrintAndLogEx(INFO, " v : (Optional) Verbose"); + PrintAndLogEx(INFO, "Examples:"); + PrintAndLogEx(INFO, " hf felica sim t 1 "); return PM3_SUCCESS; } */ @@ -83,17 +158,6 @@ static int usage_hf_felica_dumplite(void) { return PM3_SUCCESS; } -static int usage_hf_felica_raw(void) { - PrintAndLogEx(NORMAL, "Usage: hf felica raw [-h] [-r] [-c] [-k] [-a] <0A 0B 0C ... hex>"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -r do not read response"); - PrintAndLogEx(NORMAL, " -c calculate and append CRC"); - PrintAndLogEx(NORMAL, " -k keep signal field ON after receive"); - PrintAndLogEx(NORMAL, " -a active signal field ON without select"); - PrintAndLogEx(NORMAL, " -s active signal field ON with select"); - return PM3_SUCCESS; -} - static int usage_hf_felica_request_service(void) { PrintAndLogEx(NORMAL, "\nInfo: Use this command to verify the existence of Area and Service, and to acquire Key Version:"); PrintAndLogEx(NORMAL, " - When the specified Area or Service exists, the card returns Key Version."); @@ -123,75 +187,6 @@ static int usage_hf_felica_request_response(void) { return PM3_SUCCESS; } -static void print_status_flag1_interpretation(void) { - PrintAndLogEx(NORMAL, "\nStatus Flag1:"); - PrintAndLogEx(NORMAL, " - 00h : Indicates the successful completion of a command."); - PrintAndLogEx(NORMAL, " - FFh : If an error occurs during the processing of a command that includes no list in the command packet, or if " - "an error occurs independently of any list, the card returns a response by setting FFh to Status Flag1."); - PrintAndLogEx(NORMAL, " - XXh : If an error occurs while processing a command that includes Service Code List or Block List " - "in the command packet, the card returns a response by setting a number in the list to Status Flag1, " - "indicating the location of the error."); -} - -static void print_status_flag2_interpration(void) { - PrintAndLogEx(NORMAL, "\nStatus Flag2:"); - PrintAndLogEx(NORMAL, " - 00h : Indicates the successful completion of a command."); - PrintAndLogEx(NORMAL, " - 01h : The calculated result is either less than zero when the purse data is decremented, or exceeds 4" - "Bytes when the purse data is incremented."); - PrintAndLogEx(NORMAL, " - 02h : The specified data exceeds the value of cashback data at cashback of purse."); - PrintAndLogEx(NORMAL, " - 70h : Memory error (fatal error)."); - PrintAndLogEx(NORMAL, " - 71h : The number of memory rewrites exceeds the upper limit (this is only a warning; data writing is " - "performed as normal). The maximum number of rewrites can differ, depending on the product being used."); - PrintAndLogEx(NORMAL, " In addition, Status Flag1 is either 00h or FFh depending on the product being used."); - PrintAndLogEx(NORMAL, " - A1h : Illegal Number of Service: Number of Service or Number of Node specified by the command falls outside the range of the prescribed value."); - PrintAndLogEx(NORMAL, " - A2h : Illegal command packet (specified Number of Block): Number of Block specified by the command falls outside the range of the prescribed values for the product."); - PrintAndLogEx(NORMAL, " - A3h : Illegal Block List (specified order of Service): Service Code List Order specified by Block List Element falls outside the Number of Service specified by the " - "command (or the Number of Service specified at the times of mutual authentication)."); - PrintAndLogEx(NORMAL, " - A4h : Illegal Service type: Area Attribute specified by the command or Service Attribute of Service Code is incorrect."); - PrintAndLogEx(NORMAL, " - A5h : Access is not allowed: Area or Service specified by the command cannot be accessed. " - "The parameter specified by the command does not satisfy the conditions for success."); - PrintAndLogEx(NORMAL, " - A6h : Illegal Service Code List: Target to be accessed, identified by Service Code List Order, specified by Block " - "List Element does not exist. Or, Node specified by Node Code List does not exist."); - PrintAndLogEx(NORMAL, " - A7h : Illegal Block List (Access Mode): Access Mode specified by Block List Element is incorrect."); - PrintAndLogEx(NORMAL, " - A8h : Illegal Block Number Block Number (access to the specified data is inhibited): specified by Block List Element exceeds the number of Blocks assigned to Service."); - PrintAndLogEx(NORMAL, " - A9h : Data write failure: This is the error that occurs in issuance commands."); - PrintAndLogEx(NORMAL, " - AAh : Key-change failure: Key change failed."); - PrintAndLogEx(NORMAL, " - ABh : Illegal Package Parity or illegal Package MAC: This is the error that occurs in issuance commands."); - PrintAndLogEx(NORMAL, " - ACh : Illegal parameter: This is the error that occurs in issuance commands."); - PrintAndLogEx(NORMAL, " - ADh : Service exists already: This is the error that occurs in issuance commands."); - PrintAndLogEx(NORMAL, " - AEh : Illegal System Code: This is the error that occurs in issuance commands."); - PrintAndLogEx(NORMAL, " - AFh : Too many simultaneous cyclic write operations: Number of simultaneous write Blocks specified by the command to Cyclic Service " - "exceeds the number of Blocks assigned to Service."); - PrintAndLogEx(NORMAL, " - C0h : Illegal Package Identifier: This is the error that occurs in issuance commands."); - PrintAndLogEx(NORMAL, " - C1h : Discrepancy of parameters inside and outside Package: This is the error that occurs in issuance commands."); - PrintAndLogEx(NORMAL, " - C2h : Command is disabled already: This is the error that occurs in issuance commands."); -} - -static void print_block_list_element_constraints(void) { - PrintAndLogEx(NORMAL, " - Each Block List Element shall satisfy the following conditions:"); - PrintAndLogEx(NORMAL, " - The value of Service Code List Order shall not exceed Number of Service."); - PrintAndLogEx(NORMAL, " - Access Mode shall be 000b."); - PrintAndLogEx(NORMAL, " - The target specified by Service Code shall not be Area or System."); - PrintAndLogEx(NORMAL, " - Service specified in Service Code List shall exist in System."); - PrintAndLogEx(NORMAL, " - Service Attribute of Service specified in Service Code List shall be authentication-not-required Service."); - PrintAndLogEx(NORMAL, " - Block Number shall be in the range of the number of Blocks assigned to the specified Service."); -} - -static void print_number_of_service_constraints(void) { - PrintAndLogEx(NORMAL, " - Number of Service: shall be a positive integer in the range of 1 to 16, inclusive."); -} - -static void print_number_of_block_constraints(void) { - PrintAndLogEx(NORMAL, " - Number of Block: shall be less than or equal to the maximum number of Blocks that can be read simultaneously. " - "The maximum number of Blocks that can be read simultaneously can differ, depending on the product being used. Use as default 01"); -} - -static void print_service_code_list_constraints(void) { - PrintAndLogEx(NORMAL, " - Service Code List: For Service Code List, only Service Code existing in the product shall be specified:"); - PrintAndLogEx(NORMAL, " - Even when Service Code exists in the product, Service Code not referenced from Block List shall not be specified to Service Code List."); - PrintAndLogEx(NORMAL, " - For existence or nonexistence of Service in a product, please check using the Request Service (or Request Service v2) command."); -} - static int usage_hf_felica_read_without_encryption(void) { PrintAndLogEx(NORMAL, "\nInfo: Use this command to read Block Data from authentication-not-required Service."); PrintAndLogEx(NORMAL, " - Mode shall be Mode0."); @@ -335,6 +330,7 @@ static int usage_hf_felica_authentication2(void) { return PM3_SUCCESS; } + /** * Wait for response from pm3 or timeout. * Checks if receveid bytes have a valid CRC. @@ -1689,79 +1685,37 @@ static int CmdHFFelicaDumpLite(const char *Cmd) { } static int CmdHFFelicaCmdRaw(const char *Cmd) { - bool reply = 1; - bool crc = false; - bool keep_field_on = false; - bool active = false; - bool active_select = false; - uint16_t numbits = 0; - char buf[5] = ""; - int i = 0; + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica raw ", + "Send raw hex data to tag", + "hf felica raw -s 20" + ); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", NULL, "active signal field ON without select"), + arg_lit0("c", NULL, "calculate and append CRC"), + arg_lit0("k", NULL, "keep signal field ON after receive"), + arg_u64_0("n", NULL, "", "number of bits"), + arg_lit0("r", NULL, "do not read response"), + arg_lit0("s", NULL, "active signal field ON with select"), + arg_strx1(NULL, NULL, "", "raw bytes to send"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + bool active = arg_get_lit(ctx, 1); + bool crc = arg_get_lit(ctx, 2); + bool keep_field_on = arg_get_lit(ctx, 3); + uint16_t numbits = arg_get_u32_def(ctx, 4, 0) &0xFFFF; + bool reply = (arg_get_lit(ctx, 5) == false); + bool active_select = arg_get_lit(ctx, 6); + + int datalen = 0; uint8_t data[PM3_CMD_DATA_SIZE]; - uint16_t datalen = 0; - uint32_t temp; - - if (strlen(Cmd) < 2) return usage_hf_felica_raw(); - - // strip - while (*Cmd == ' ' || *Cmd == '\t') Cmd++; - - while (Cmd[i] != '\0') { - if (Cmd[i] == ' ' || Cmd[i] == '\t') { i++; continue; } - if (Cmd[i] == '-') { - switch (tolower(Cmd[i + 1])) { - case 'h': - return usage_hf_felica_raw(); - case 'r': - reply = false; - break; - case 'c': - crc = true; - break; - case 'k': - keep_field_on = true; - break; - case 'a': - active = true; - break; - case 's': - active_select = true; - break; - case 'b': - sscanf(Cmd + i + 2, "%d", &temp); - numbits = temp & 0xFFFF; - i += 3; - while (Cmd[i] != ' ' && Cmd[i] != '\0') { i++; } - i -= 2; - break; - default: - return usage_hf_felica_raw(); - } - i += 2; - continue; - } - if ((Cmd[i] >= '0' && Cmd[i] <= '9') || - (Cmd[i] >= 'a' && Cmd[i] <= 'f') || - (Cmd[i] >= 'A' && Cmd[i] <= 'F')) { - buf[strlen(buf) + 1] = 0; - buf[strlen(buf)] = Cmd[i]; - i++; - - if (strlen(buf) >= 2) { - sscanf(buf, "%x", &temp); - data[datalen] = (uint8_t)(temp & 0xff); - *buf = 0; - if (++datalen >= (sizeof(data) - 2)) { - if (crc) - PrintAndLogEx(WARNING, "Buffer is full, we can't add CRC to your data"); - break; - } - } - continue; - } - PrintAndLogEx(WARNING, "Invalid char on input"); - return PM3_EINVARG; - } + CLIGetHexWithReturn(ctx, 6, data, &datalen); + CLIParserFree(ctx); if (crc) { AddCrc(data, datalen); @@ -1788,6 +1742,7 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { clearCommandBuffer(); PrintAndLogEx(SUCCESS, "Data: %s", sprint_hex(data, datalen)); + SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); if (reply) { From 91b47eeb1f51647513b551351d4e51ed1dbb7ca2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 25 Mar 2021 09:39:40 +0100 Subject: [PATCH 092/373] hf felica litesim - now uses cliparser --- armsrc/appmain.c | 6 +- armsrc/felica.c | 92 +++++++++++++++++++----------- armsrc/felica.h | 4 +- client/src/cmdhffelica.c | 119 ++++++++++++++++++++++++++------------- 4 files changed, 145 insertions(+), 76 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 75d74c9da..75f85a7bd 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1311,7 +1311,11 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_HF_FELICALITE_SIMULATE: { - felica_sim_lite(packet->oldarg[0]); + struct p { + uint8_t uid[8]; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + felica_sim_lite(payload->uid); break; } case CMD_HF_FELICA_SNIFF: { diff --git a/armsrc/felica.c b/armsrc/felica.c index 7aa524e62..3783c802f 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -630,51 +630,74 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { #define R_READBLK_LEN 0x21 //simulate NFC Tag3 card - for now only poll response works // second half (4 bytes) of NDEF2 goes into nfcid2_0, first into nfcid2_1 -void felica_sim_lite(uint64_t uid) { +void felica_sim_lite(uint8_t *uid) { - int i, curlen = 0; - uint8_t *curresp = 0; - - uint8_t ndef[8]; - num_to_bytes(uid, 8, ndef); - - //prepare our 3 responses... + // prepare our 3 responses... uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2, 0x4d, 0x12, FELICA_POLL_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f}; uint8_t resp_poll1[R_POLL1_LEN] = { 0xb2, 0x4d, 0x14, FELICA_POLL_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0x88, 0xb4, 0xb3, 0x7f}; uint8_t resp_readblk[R_READBLK_LEN] = { 0xb2, 0x4d, 0x1d, FELICA_RDBLK_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x04, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x23, 0xcb, 0x6e}; - //NFC tag 3/ ISo technically. Many overlapping standards - DbpString("Felica Lite-S sim start"); + // NFC tag 3/ ISo technically. Many overlapping standards + DbpString("Felica Lite-S simulation start"); Dbprintf("NDEF2 UID: %02x %02x %02x %02x %02x %02x %02x %02x", - ndef[0], ndef[1], ndef[2], ndef[3], ndef[4], ndef[5], ndef[6], ndef[7] + uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7] ); - //fill in blanks - for (i = 0; i < 8; i++) { - resp_poll0[i + 4] = ndef[i]; - resp_poll1[i + 4] = ndef[i]; - resp_readblk[i + 4] = ndef[i]; + // fill in blanks + for (uint8_t i = 0; i < 8; i++) { + resp_poll0[i + 4] = uid[i]; + resp_poll1[i + 4] = uid[i]; + resp_readblk[i + 4] = uid[i]; } - //calculate and set CRC + // calculate and set CRC AddCrc(resp_poll0, resp_poll0[2]); AddCrc(resp_poll1, resp_poll1[2]); AddCrc(resp_readblk, resp_readblk[2]); iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD); + int retval = PM3_SUCCESS; + int curlen = 0; + uint8_t *curresp = NULL; bool listenmode = true; - //uint32_t frtm = GetCountSspClk(); + // uint32_t frtm = GetCountSspClk(); + + uint8_t flip = 0; + uint16_t checker = 0; for (;;) { - if (BUTTON_PRESS()) break; + + WDT_HIT(); + + // since simulation is a tight time critical loop, + // we only check for user request to end at iteration 3000, 9000. + if (flip == 3) { + if (data_available()) { + retval = PM3_EOPABORTED; + break; + } + flip = 0; + } + + if (checker >= 3000) { + + if (BUTTON_PRESS()) { + retval = PM3_EOPABORTED; + break; + } + flip++; + checker = 0; + } + ++checker; + WDT_HIT(); if (listenmode) { - //waiting for request... + // waiting for request... if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); - //frtm = GetCountSspClk(); + // frtm = GetCountSspClk(); Process18092Byte(dist); if (FelicaFrame.state == STATE_FULL) { @@ -683,7 +706,7 @@ void felica_sim_lite(uint64_t uid) { if (FelicaFrame.framebytes[2] == 6 && FelicaFrame.framebytes[3] == 0) { - //polling... there are two types of polling we answer to + // polling... there are two types of polling we answer to if (FelicaFrame.framebytes[6] == 0) { curresp = resp_poll0; curlen = R_POLL0_LEN; @@ -697,28 +720,30 @@ void felica_sim_lite(uint64_t uid) { } if (FelicaFrame.framebytes[2] > 5 && FelicaFrame.framebytes[3] == 0x06) { - //we should rebuild it depending on page size, but... - //Let's see first + // we should rebuild it depending on page size, but... + // Let's see first curresp = resp_readblk; curlen = R_READBLK_LEN; listenmode = false; } - //clear frame + // clear frame FelicaFrameReset(); } else { - //frame invalid, clear it out to allow for the next one + // frame invalid, clear it out to allow for the next one FelicaFrameReset(); } } } } - if (!listenmode) { - //trying to answer... here to start answering immediately. - //this one is a bit finicky. Seems that being a bit late is better than earlier - //TransmitFor18092_AsReader(curresp, curlen, frtm+512, 0, 0); + + + if (listenmode == false) { + // trying to answer... here to start answering immediately. + // this one is a bit finicky. Seems that being a bit late is better than earlier + // TransmitFor18092_AsReader(curresp, curlen, frtm+512, 0, 0); TransmitFor18092_AsReader(curresp, curlen, NULL, 0, 0); - //switch back + // switch back FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD); FelicaFrameReset(); @@ -730,10 +755,11 @@ void felica_sim_lite(uint64_t uid) { switch_off(); - //reset framing + // reset framing AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - DbpString("Felica Lite-S sim end"); + Dbprintf("FeliCa Lite-S emulator stopped. Trace length: %d ", BigBuf_get_traceLen()); + reply_ng(CMD_HF_FELICALITE_SIMULATE, retval, NULL, 0); } #define RES_SVC_LEN 11 + 3 diff --git a/armsrc/felica.h b/armsrc/felica.h index 885815abb..f30de4b6f 100644 --- a/armsrc/felica.h +++ b/armsrc/felica.h @@ -6,7 +6,7 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Definitions internal to the app source. +// Definitions internal to the FeliCa functionality //----------------------------------------------------------------------------- #ifndef __FELICA_H #define __FELICA_H @@ -16,7 +16,7 @@ void felica_sendraw(PacketCommandNG *c); void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip); -void felica_sim_lite(uint64_t uid); +void felica_sim_lite(uint8_t *uid); void felica_dump_lite_s(void); #endif diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 2cf30a5ec..246d5bff3 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -8,22 +8,21 @@ // High frequency ISO18092 / FeliCa commands //----------------------------------------------------------------------------- #include "cmdhffelica.h" - #include #include #include #include #include - -#include "cmdparser.h" // command_t +#include "cmdparser.h" // command_t #include "comms.h" #include "cmdtrace.h" #include "crc16.h" #include "util.h" #include "ui.h" -#include "iso18.h" // felica_card_select_t struct +#include "iso18.h" // felica_card_select_t struct #include "des.h" -#include "cliparser.h" // cliparser +#include "cliparser.h" // cliparser +#include "util_posix.h" // msleep #define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len)) @@ -136,28 +135,6 @@ static int usage_hf_felica_sniff(void) { return PM3_SUCCESS; } -static int usage_hf_felica_simlite(void) { - PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa Lite tag \n"); - PrintAndLogEx(NORMAL, "Usage: hf felica litesim [h] u "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " uid : UID in hexsymbol"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf felica litesim 11223344556677"); - return PM3_SUCCESS; -} - -static int usage_hf_felica_dumplite(void) { - PrintAndLogEx(NORMAL, "\n Dump ISO/18092 FeliCa Lite tag \n"); - PrintAndLogEx(NORMAL, "press button to abort run, otherwise it will loop for 200sec."); - PrintAndLogEx(NORMAL, "Usage: hf felica litedump [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf felica litedump"); - return PM3_SUCCESS; -} - static int usage_hf_felica_request_service(void) { PrintAndLogEx(NORMAL, "\nInfo: Use this command to verify the existence of Area and Service, and to acquire Key Version:"); PrintAndLogEx(NORMAL, " - When the specified Area or Service exists, the card returns Key Version."); @@ -1455,13 +1432,48 @@ static int CmdHFFelicaSniff(const char *Cmd) { // uid hex static int CmdHFFelicaSimLite(const char *Cmd) { - uint64_t uid = param_get64ex(Cmd, 0, 0, 16); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica litesim", + "Emulating ISO/18092 FeliCa Lite tag", + "hf felica litesim -u 1122334455667788" + ); + void *argtable[] = { + arg_param_begin, + arg_str1("u", "uid", "", "UID/NDEF2 8 hex bytes"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + int uid_len = 0; + struct p { + uint8_t uid[8]; + } PACKED payload; + CLIGetHexWithReturn(ctx, 1, payload.uid, &uid_len); + CLIParserFree(ctx); - if (!uid) - return usage_hf_felica_simlite(); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "Press " _GREEN_("") " or pm3-button to abort simulation"); clearCommandBuffer(); - SendCommandMIX(CMD_HF_FELICALITE_SIMULATE, uid, 0, 0, NULL, 0); + SendCommandNG(CMD_HF_FELICALITE_SIMULATE, payload.uid, sizeof(payload)); + PacketResponseNG resp; + + for (;;) { + if (kbd_enter_pressed()) { + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + PrintAndLogEx(DEBUG, "User aborted"); + msleep(300); + break; + } + + if (WaitForResponseTimeout(CMD_HF_FELICALITE_SIMULATE, &resp, 1000)) { + if (resp.status == PM3_EOPABORTED) { + PrintAndLogEx(DEBUG, "Button pressed, user aborted"); + break; + } + } + } + + PrintAndLogEx(INFO, "Done"); return PM3_SUCCESS; } @@ -1618,19 +1630,46 @@ static uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t trac static int CmdHFFelicaDumpLite(const char *Cmd) { - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_hf_felica_dumplite(); +/* +iceman 2021, +Why does this command say it dumps a FeliCa lite card +and then tries to print a trace?!? +Is this a trace list or a feclia dump cmd? +*/ + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica litedump", + "Dump ISO/18092 FeliCa Lite tag. It will timeout after 200sec", + "hf felica litedump" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + PrintAndLogEx(SUCCESS, "FeliCa lite - dump started"); - PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); + clearCommandBuffer(); SendCommandNG(CMD_HF_FELICALITE_DUMP, NULL, 0); PacketResponseNG resp; + PrintAndLogEx(INFO, "Press " _GREEN_("") " or pm3-button to abort dumping"); + uint8_t timeout = 0; - while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + while (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { + + if (kbd_enter_pressed()) { + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + PrintAndLogEx(DEBUG, "User aborted"); + return PM3_EOPABORTED; + } + timeout++; - PrintAndLogEx(NORMAL, "." NOLF); + PrintAndLogEx(INPLACE, "% 3i", timeout); + fflush(stdout); if (kbd_enter_pressed()) { PrintAndLogEx(WARNING, "\naborted via keyboard!\n"); @@ -1659,7 +1698,7 @@ static int CmdHFFelicaDumpLite(const char *Cmd) { uint8_t *trace = calloc(tracelen, sizeof(uint8_t)); if (trace == NULL) { - PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); + PrintAndLogEx(WARNING, "failed to allocate memory "); return PM3_EMALLOC; } @@ -1669,8 +1708,8 @@ static int CmdHFFelicaDumpLite(const char *Cmd) { return PM3_ETIMEOUT; } - PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %"PRIu32" bytes)", tracelen); + PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %"PRIu32" bytes)", tracelen); print_hex_break(trace, tracelen, 32); printSep(); @@ -1791,7 +1830,7 @@ int readFelicaUid(bool verbose) { } case 0: { PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "FeliCa tag info"); + PrintAndLogEx(SUCCESS, "-------- " _CYAN_("FeliCa tag info") " -------------------"); PrintAndLogEx(SUCCESS, "IDm %s", sprint_hex(card.IDm, sizeof(card.IDm))); PrintAndLogEx(SUCCESS, " - CODE %s", sprint_hex(card.code, sizeof(card.code))); @@ -1839,7 +1878,7 @@ static command_t CommandTable[] = { //{"writev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to authentication-required Service."}, //{"uprandomid", CmdHFFelicaNotImplementedYet, IfPm3Felica, "update Random ID (IDr)."}, {"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("FeliCa Light") " -----------------------"}, - {"litesim", CmdHFFelicaSimLite, IfPm3Felica, " - only reply to poll request"}, + {"litesim", CmdHFFelicaSimLite, IfPm3Felica, "Emulating ISO/18092 FeliCa Lite tag"}, {"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"}, // {"sim", CmdHFFelicaSim, IfPm3Felica, " -- Simulate ISO 18092/FeliCa tag"} {NULL, NULL, NULL, NULL} From 341bebdfcca0bbc28b1103013ca20302291480b1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 25 Mar 2021 14:59:46 +0100 Subject: [PATCH 093/373] fix data hex2bin --- client/src/cmddata.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 84705a586..6a2fd37dd 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -2411,15 +2411,14 @@ static int Cmdhex2bin(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, false); int dlen = 0; - uint8_t data[200] = {0x00}; - int res = CLIParamHexToBuf(arg_get_str(ctx, 1), data, sizeof(data), &dlen); + char data[200] = {0x00}; + int res = CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)data, sizeof(data), &dlen); CLIParserFree(ctx); if (res) { PrintAndLogEx(FAILED, "Error parsing bytes"); return PM3_EINVARG; } - PrintAndLogEx(SUCCESS, "" NOLF); for (int i = 0; i < dlen; i++) { char x = data[i]; From a1d21e56d87bf0e6c50a8e6802455cd3384b3b53 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 25 Mar 2021 15:19:43 +0100 Subject: [PATCH 094/373] fix ltrim missing param --- client/src/cmddata.c | 2 +- client/src/cmdlft55xx.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 6a2fd37dd..5036b6584 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -2774,7 +2774,7 @@ static int try_detect_modulation(void) { // allow undo save_restoreGB(GRAPH_SAVE); // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) - CmdLtrim("160"); + CmdLtrim("-i 160"); if ((PSKDemod(0, 0, 6, false) == PM3_SUCCESS)) { tests[hits].modulation = DEMOD_PSK1; tests[hits].bitrate = clk; diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index ae2beddd9..acea99f13 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -1127,7 +1127,7 @@ bool t55xxTryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32 // allow undo save_restoreGB(GRAPH_SAVE); // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) - CmdLtrim("160"); + CmdLtrim("-i 160"); if ((PSKDemod(0, 0, 6, false) == PM3_SUCCESS) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { tests[hits].modulation = DEMOD_PSK1; tests[hits].bitrate = bitRate; @@ -3555,7 +3555,7 @@ bool tryDetectP1(bool getData) { // allow undo // save_restoreGB(GRAPH_SAVE); // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) - //CmdLtrim("160"); + //CmdLtrim("-i 160"); if ((PSKDemod(0, 0, 6, false) == PM3_SUCCESS) && preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64)) { From 21f311cf8c57ffa0fc74747a71c6f095be63d4f7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 26 Mar 2021 14:09:09 +0100 Subject: [PATCH 095/373] auto - optional parameter to keep searching --- client/src/cmdmain.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/client/src/cmdmain.c b/client/src/cmdmain.c index 85ec8e807..a9ecfd907 100644 --- a/client/src/cmdmain.c +++ b/client/src/cmdmain.c @@ -129,27 +129,31 @@ static int CmdAuto(const char *Cmd) { void *argtable[] = { arg_param_begin, + arg_lit0("a", "all", ""), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); + bool exit_first = (arg_get_lit(ctx, 1) == false); CLIParserFree(ctx); PrintAndLogEx(INFO, "lf search"); int ret = CmdLFfind(""); - if (ret == PM3_SUCCESS) + if (ret == PM3_SUCCESS && exit_first) return ret; PrintAndLogEx(INFO, "hf search"); ret = CmdHFSearch(""); - if (ret == PM3_SUCCESS) + if (ret == PM3_SUCCESS && exit_first) return ret; PrintAndLogEx(INFO, "lf search - unknown"); ret = lf_search_plus(""); - if (ret == PM3_SUCCESS) + if (ret == PM3_SUCCESS && exit_first) return ret; - PrintAndLogEx(INFO, "Failed both LF / HF SEARCH,"); + if (ret != PM3_SUCCESS) + PrintAndLogEx(INFO, "Failed both LF / HF SEARCH,"); + PrintAndLogEx(INFO, "Trying " _YELLOW_("`lf read`") " and save a trace for you"); CmdPlot(""); From 96bdc45ccf84844cbca7563a0400e45df0ad5223 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 26 Mar 2021 19:30:22 +0100 Subject: [PATCH 096/373] text --- client/src/cmdhfmfu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 9488378fd..c9279592d 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -2598,7 +2598,7 @@ static int CmdHF14AMfUCAuth(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("k", "key", "", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"), + arg_str0("k", "key", "", "key for authentication (UL-C 16 bytes)"), arg_lit0("l", NULL, "swap entered key's endianness"), arg_lit0("k", NULL, "keep field on (only if a password is provided too)"), arg_param_end From b023602d83c2a2f011831afd4294d53936c39d6e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 26 Mar 2021 19:32:11 +0100 Subject: [PATCH 097/373] text --- client/src/cmdhficlass.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 7225a443b..3de202433 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -2314,9 +2314,9 @@ static void HFiClassCalcNewKey(uint8_t *CSN, uint8_t *OLDKEY, uint8_t *NEWKEY, u xor_div_key[i] = old_div_key[i] ^ new_div_key[i]; } if (verbose) { - PrintAndLogEx(SUCCESS, "Old div key : %s", sprint_hex(old_div_key, 8)); - PrintAndLogEx(SUCCESS, "New div key : %s", sprint_hex(new_div_key, 8)); - PrintAndLogEx(SUCCESS, "Xor div key : " _YELLOW_("%s") "\n", sprint_hex(xor_div_key, 8)); + PrintAndLogEx(SUCCESS, "Old div key......... %s", sprint_hex(old_div_key, 8)); + PrintAndLogEx(SUCCESS, "New div key......... %s", sprint_hex(new_div_key, 8)); + PrintAndLogEx(SUCCESS, "Xor div key......... " _YELLOW_("%s") "\n", sprint_hex(xor_div_key, 8)); } } @@ -2362,7 +2362,7 @@ static int CmdHFiClassCalcNewKey(const char *Cmd) { } else if (old_key_nr >= 0) { if (old_key_nr < ICLASS_KEYS_MAX) { memcpy(old_key, iClass_Key_Table[old_key_nr], 8); - PrintAndLogEx(SUCCESS, "Using old key[%d] " _GREEN_("%s"), old_key_nr, sprint_hex(iClass_Key_Table[old_key_nr], 8)); + PrintAndLogEx(SUCCESS, "Using old key[%d]... " _GREEN_("%s"), old_key_nr, sprint_hex(iClass_Key_Table[old_key_nr], 8)); } else { PrintAndLogEx(ERR, "Key number is invalid"); CLIParserFree(ctx); @@ -2395,7 +2395,7 @@ static int CmdHFiClassCalcNewKey(const char *Cmd) { } else if (new_key_nr >= 0) { if (new_key_nr < ICLASS_KEYS_MAX) { memcpy(new_key, iClass_Key_Table[new_key_nr], 8); - PrintAndLogEx(SUCCESS, "Using new key[%d] " _GREEN_("%s"), new_key_nr, sprint_hex(iClass_Key_Table[new_key_nr], 8)); + PrintAndLogEx(SUCCESS, "Using new key[%d]... " _GREEN_("%s"), new_key_nr, sprint_hex(iClass_Key_Table[new_key_nr], 8)); } else { PrintAndLogEx(ERR, "Key number is invalid"); CLIParserFree(ctx); From 7574606080d0e511b0c7643feb4a9be1796ef64b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 26 Mar 2021 21:01:50 +0100 Subject: [PATCH 098/373] hf felica sniff - now uses cliparser --- armsrc/appmain.c | 8 ++- armsrc/felica.c | 49 +++++++++++++---- client/src/cmdhffelica.c | 114 +++++++++++++++++++-------------------- 3 files changed, 99 insertions(+), 72 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 75f85a7bd..ec6ebb2c0 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1319,8 +1319,12 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_HF_FELICA_SNIFF: { - felica_sniff(packet->oldarg[0], packet->oldarg[1]); - reply_ng(CMD_HF_FELICA_SNIFF, PM3_SUCCESS, NULL, 0); + struct p { + uint32_t samples; + uint32_t triggers; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + felica_sniff(payload->samples, payload->triggers); break; } case CMD_HF_FELICALITE_DUMP: { diff --git a/armsrc/felica.c b/armsrc/felica.c index 3783c802f..182f496aa 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -572,23 +572,53 @@ void felica_sendraw(PacketCommandNG *c) { } void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { - int remFrames = (samplesToSkip) ? samplesToSkip : 0; - Dbprintf("Sniff Felica: Getting first %d frames, Skipping after %d triggers.\n", samplesToSkip, triggersToSkip); + clear_trace(); set_tracing(true); iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD); + LED_D_ON(); - uint16_t numbts = 0; + + int retval = PM3_SUCCESS; + int remFrames = (samplesToSkip) ? samplesToSkip : 0; int trigger_cnt = 0; uint32_t timeout = iso18092_get_timeout(); bool isReaderFrame = true; - while (!BUTTON_PRESS()) { + + uint8_t flip = 0; + uint16_t checker = 0; + for (;;) { + WDT_HIT(); + + // since simulation is a tight time critical loop, + // we only check for user request to end at iteration 3000, 9000. + if (flip == 3) { + if (data_available()) { + retval = PM3_EOPABORTED; + break; + } + flip = 0; + } + + if (checker >= 3000) { + + if (BUTTON_PRESS()) { + retval = PM3_EOPABORTED; + break; + } + flip++; + checker = 0; + } + ++checker; + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); Process18092Byte(dist); + if ((dist >= 178) && (++trigger_cnt > triggersToSkip)) { - Dbprintf("triggersToSkip kicked %d", dist); + Dbprintf("triggers To skip kicked %d", dist); break; } if (FelicaFrame.state == STATE_FULL) { @@ -599,7 +629,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { } remFrames--; if (remFrames <= 0) { - Dbprintf("Stop Sniffing - samplesToSkip reached!"); + Dbprintf("Stop Sniffing - samples To skip reached!"); break; } LogTrace(FelicaFrame.framebytes, @@ -609,7 +639,6 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { NULL, isReaderFrame ); - numbts += FelicaFrame.len; FelicaFrameReset(); } } @@ -617,11 +646,9 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { switch_off(); //reset framing AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - set_tracelen(numbts); - set_tracelen(BigBuf_max_traceLen()); - Dbprintf("Felica sniffing done, tracelen: %i, use " _YELLOW_("`hf felica list`") " for annotations", BigBuf_get_traceLen()); - reply_mix(CMD_ACK, 1, numbts, 0, 0, 0); + Dbprintf("Felica sniffing done, tracelen: %i", BigBuf_get_traceLen()); + reply_ng(CMD_HF_FELICA_SNIFF, retval, NULL, 0); LED_D_OFF(); } diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 246d5bff3..8516b3ad3 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -121,20 +121,6 @@ static int usage_hf_felica_sim(void) { } */ -static int usage_hf_felica_sniff(void) { - PrintAndLogEx(NORMAL, "\nInfo: It get data from the field and saves it into command buffer. "); - PrintAndLogEx(NORMAL, " Buffer accessible from command 'hf felica list'"); - PrintAndLogEx(NORMAL, "\nUsage: hf felica sniff [-h] [-s] [-t]"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -s samples to skip (decimal) max 9999"); - PrintAndLogEx(NORMAL, " -t triggers to skip (decimal) max 9999"); - - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf felica sniff"); - PrintAndLogEx(NORMAL, " hf felica sniff -s 10 -t 10"); - return PM3_SUCCESS; -} - static int usage_hf_felica_request_service(void) { PrintAndLogEx(NORMAL, "\nInfo: Use this command to verify the existence of Area and Service, and to acquire Key Version:"); PrintAndLogEx(NORMAL, " - When the specified Area or Service exists, the card returns Key Version."); @@ -1376,57 +1362,67 @@ static int CmdHFFelicaNotImplementedYet(const char *Cmd) { } static int CmdHFFelicaSniff(const char *Cmd) { - uint8_t paramCount = 0; - uint64_t samples2skip = 0; - uint64_t triggers2skip = 0; - strip_cmds(Cmd); - int i = 0; - while (Cmd[i] != '\0') { - if (Cmd[i] == '-') { - switch (tolower(Cmd[i + 1])) { - case 'H': - return usage_hf_felica_sniff(); - case 's': - paramCount++; - if (param_getlength(Cmd, paramCount) < 5) { - samples2skip = param_get32ex(Cmd, paramCount++, 0, 10); - } else { - PrintAndLogEx(ERR, "Invalid samples number!"); - return PM3_EINVARG; - } - break; - case 't': - paramCount++; - if (param_getlength(Cmd, paramCount) < 5) { - triggers2skip = param_get32ex(Cmd, paramCount++, 0, 10); - } else { - PrintAndLogEx(ERR, "Invalid triggers number!"); - return PM3_EINVARG; - } - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, paramCount)); - return usage_hf_felica_sniff(); - } - i += 2; - } - i++; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica sniff", + "Collect data from the field and save into command buffer.\n" + "Buffer accessible from `hf felica list`", + "hf felica sniff\n" + "hf felica sniff -s 10 -t 19" + ); + void *argtable[] = { + arg_param_begin, + arg_u64_0("s", "samples", "", "samples to skip"), + arg_u64_0("t", "trig", "", "triggers to skip "), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + struct p { + uint32_t samples; + uint32_t triggers; + } PACKED payload; + + payload.samples = arg_get_u32_def(ctx, 1, 10); + payload.triggers = arg_get_u32_def(ctx, 2, 5000); + CLIParserFree(ctx); + + if (payload.samples > 9999 ){ + payload.samples = 9999; + PrintAndLogEx(INFO, "Too large samples to skip value, using max value 9999"); + return PM3_EINVARG; } - if (samples2skip == 0) { - samples2skip = 10; - PrintAndLogEx(INFO, "Set default samples2skip: %" PRIu64, samples2skip); + if (payload.triggers > 9999 ){ + payload.triggers = 9999; + PrintAndLogEx(INFO, "Too large trigger to skip value, using max value 9999"); + return PM3_EINVARG; } - if (triggers2skip == 0) { - triggers2skip = 5000; - PrintAndLogEx(INFO, "Set default triggers2skip: %" PRIu64, triggers2skip); - } - PrintAndLogEx(INFO, "Start Sniffing now. You can stop sniffing with clicking the PM3 Button"); - PrintAndLogEx(INFO, "During sniffing, other pm3 commands may not response."); + PrintAndLogEx(INFO, "Sniff Felica, getting first %" PRIu32 " frames, skipping after %" PRIu32 " triggers", payload.samples, payload.triggers ); + PrintAndLogEx(INFO, "Press " _GREEN_("") " or pm3-button to abort sniffing"); clearCommandBuffer(); - SendCommandMIX(CMD_HF_FELICA_SNIFF, samples2skip, triggers2skip, 0, NULL, 0); + SendCommandNG(CMD_HF_FELICA_SNIFF, (uint8_t *)&payload, sizeof(payload)); + PacketResponseNG resp; + + for (;;) { + if (kbd_enter_pressed()) { + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + PrintAndLogEx(DEBUG, "User aborted"); + msleep(300); + break; + } + + if (WaitForResponseTimeout(CMD_HF_FELICA_SNIFF, &resp, 1000)) { + if (resp.status == PM3_EOPABORTED) { + PrintAndLogEx(DEBUG, "Button pressed, user aborted"); + break; + } + } + } + + PrintAndLogEx(HINT, "try `" _YELLOW_("hf felica list") "` to view"); + PrintAndLogEx(INFO, "Done"); return PM3_SUCCESS; } From c576fe949aead80d545401d29658ff5995381c02 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 26 Mar 2021 21:02:22 +0100 Subject: [PATCH 099/373] text --- doc/cliparser_todo.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 9918f89d0..27713fd58 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -1,4 +1,3 @@ -data rawdemod hf 15 dump hf 15 info hf 15 raw @@ -9,8 +8,6 @@ hf 15 wrbl hf 15 writeafi hf 15 writedsfid hf felica reader -hf felica sniff -hf felica raw hf felica rdunencrypted hf felica wrunencrypted hf felica rqservice @@ -21,8 +18,6 @@ hf felica auth1 hf felica auth2 hf felica rqspecver hf felica resetmode -hf felica litesim -hf felica litedump hf mf hardnested hf mf autopwn hf mf nack From f36da8a63937a54463196d715d90e1e2a638cf40 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 26 Mar 2021 21:26:29 +0100 Subject: [PATCH 100/373] fix cppchecker uninitvar --- armsrc/Standalone/hf_craftbyte.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/armsrc/Standalone/hf_craftbyte.c b/armsrc/Standalone/hf_craftbyte.c index b58e89405..0193002ce 100644 --- a/armsrc/Standalone/hf_craftbyte.c +++ b/armsrc/Standalone/hf_craftbyte.c @@ -61,7 +61,7 @@ void RunMod(void) { break; else if (state == STATE_READ) { iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); - if (!iso14443a_select_card(NULL, &card, NULL, true, 0, true)) { + if (iso14443a_select_card(NULL, &card, NULL, true, 0, true) == false) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); SpinDelay(500); @@ -72,11 +72,14 @@ void RunMod(void) { state = STATE_EMUL; } } else if (state == STATE_EMUL) { - uint8_t flags; - if (card.uidlen == 4) flags |= FLAG_4B_UID_IN_DATA; - else if (card.uidlen == 7) flags |= FLAG_7B_UID_IN_DATA; - else if (card.uidlen == 10) flags |= FLAG_10B_UID_IN_DATA; - else { + uint8_t flags = 0; + if (card.uidlen == 4) { + flags |= FLAG_4B_UID_IN_DATA; + } else if (card.uidlen == 7) { + flags |= FLAG_7B_UID_IN_DATA; + } else if (card.uidlen == 10){ + flags |= FLAG_10B_UID_IN_DATA; + } else { Dbprintf("Unusual UID length, something is wrong. Try again please."); state = STATE_READ; continue; From 8d18860c6ad6f9419cfd63e4f68148f9a62a75ca Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 26 Mar 2021 21:30:25 +0100 Subject: [PATCH 101/373] fix cppchecker --- armsrc/Standalone/hf_mattyrun.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/armsrc/Standalone/hf_mattyrun.c b/armsrc/Standalone/hf_mattyrun.c index e14e89789..8d03c911d 100644 --- a/armsrc/Standalone/hf_mattyrun.c +++ b/armsrc/Standalone/hf_mattyrun.c @@ -55,9 +55,9 @@ static iso14a_card_select_t p_card; // Pseudo-configuration block. static bool printKeys = false; // Prints keys -static bool transferToEml = true; // Transfer keys to emulator memory +//static bool transferToEml = true; // Transfer keys to emulator memory static bool ecfill = true; // Fill emulator memory with cards content. -static bool simulation = true; // Simulates an exact copy of the target tag +//static bool simulation = true; // Simulates an exact copy of the target tag static bool fillFromEmulator = false; // Dump emulator memory. //----------------------------------------------------------------------------- @@ -482,7 +482,8 @@ void RunMod(void) { // If enabled, transfers found keys to memory and loads target content in emulator memory. Then it simulates to be the tag it has basically cloned. - if ((transferToEml) && (allKeysFound)) { +// if ((transferToEml) && (allKeysFound)) { + if (allKeysFound) { emlClearMem(); @@ -517,7 +518,8 @@ void RunMod(void) { } } - if ((filled == PM3_SUCCESS) && simulation) { +// if ((filled == PM3_SUCCESS) && simulation) { + if (filled == PM3_SUCCESS) { Dbprintf("\t [✓] Emulator memory filled, simulation started."); // This will tell the fpga to emulate using previous keys and current target tag content. From 2ffcdc67f671272ccd688f1eeec6d282eb91e921 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 26 Mar 2021 21:32:42 +0100 Subject: [PATCH 102/373] fix cppchecker --- armsrc/Standalone/hf_tcprst.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/armsrc/Standalone/hf_tcprst.c b/armsrc/Standalone/hf_tcprst.c index f9d8b0b59..d60db82ad 100644 --- a/armsrc/Standalone/hf_tcprst.c +++ b/armsrc/Standalone/hf_tcprst.c @@ -326,7 +326,8 @@ void RunMod(void) { if (i == 4) { - if (apdubuffer[1] == 0x1b && apdubuffer[2] == 0xd1 && !gotndef) { //Get NDEF Data + // Get NDEF Data + if (apdubuffer[1] == 0x1b && apdubuffer[2] == 0xd1) { gotndef = true; memcpy(&ndef, &apdubuffer, apdulen - 2); break; From 4b8ee5a03911d17fc2bab7ebecec824e1f47ec2d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 26 Mar 2021 21:44:49 +0100 Subject: [PATCH 103/373] fix cppchecker --- client/src/proxmark3.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/client/src/proxmark3.c b/client/src/proxmark3.c index 3d92b8d00..f5d487fc7 100644 --- a/client/src/proxmark3.c +++ b/client/src/proxmark3.c @@ -518,10 +518,9 @@ static void set_my_user_directory(void) { if (my_user_directory == NULL) { uint16_t pathLen = FILENAME_MAX; // should be a good starting point - bool error = false; char *cwd_buffer = (char *)calloc(pathLen, sizeof(uint8_t)); - while (!error && (GetCurrentDir(cwd_buffer, pathLen) == NULL)) { + while (GetCurrentDir(cwd_buffer, pathLen) == NULL) { if (errno == ERANGE) { // Need bigger buffer pathLen += 10; // if buffer was too small add 10 characters and try again char *tmp = realloc(cwd_buffer, pathLen); @@ -537,16 +536,13 @@ static void set_my_user_directory(void) { } } - if (!error) { - - for (int i = 0; i < strlen(cwd_buffer); i++) { - if (cwd_buffer[i] == '\\') { - cwd_buffer[i] = '/'; - } + for (int i = 0; i < strlen(cwd_buffer); i++) { + if (cwd_buffer[i] == '\\') { + cwd_buffer[i] = '/'; } - - my_user_directory = cwd_buffer; } + + my_user_directory = cwd_buffer; } } From f0b4e6651ca5f28ee69cf37370f4093034aff3f4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 26 Mar 2021 21:47:13 +0100 Subject: [PATCH 104/373] fix cppchecker - null checks --- client/src/proxmark3.c | 4 ++++ client/src/scripting.c | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/client/src/proxmark3.c b/client/src/proxmark3.c index f5d487fc7..e804972f4 100644 --- a/client/src/proxmark3.c +++ b/client/src/proxmark3.c @@ -519,6 +519,10 @@ static void set_my_user_directory(void) { uint16_t pathLen = FILENAME_MAX; // should be a good starting point char *cwd_buffer = (char *)calloc(pathLen, sizeof(uint8_t)); + if (cwd_buffer == NULL) { + PrintAndLogEx(WARNING, "failed to allocate memory"); + return; + } while (GetCurrentDir(cwd_buffer, pathLen) == NULL) { if (errno == ERANGE) { // Need bigger buffer diff --git a/client/src/scripting.c b/client/src/scripting.c index 6ac012199..9287e1f31 100644 --- a/client/src/scripting.c +++ b/client/src/scripting.c @@ -1279,10 +1279,12 @@ static int l_ewd(lua_State *L) { static int l_cwd(lua_State *L) { uint16_t path_len = FILENAME_MAX; // should be a good starting point - bool error = false; char *cwd = (char *)calloc(path_len, sizeof(uint8_t)); + if (cwd == NULL) { + return returnToLuaWithError(L, "Failed to allocate memory"); + } - while (!error && (GetCurrentDir(cwd, path_len) == NULL)) { + while (GetCurrentDir(cwd, path_len) == NULL) { if (errno == ERANGE) { // Need bigger buffer path_len += 10; // if buffer was too small add 10 characters and try again cwd = realloc(cwd, path_len); From 4d6584f0271628636a568014a23c796f81d42b5d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 26 Mar 2021 22:26:28 +0100 Subject: [PATCH 105/373] fix coverity 315652 --- client/src/cmddata.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 5036b6584..d514b53ce 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -411,6 +411,8 @@ int printDemodBuff(uint8_t offset, bool strip_leading, bool invert, bool print_h char hex[512] = {0x00}; int num_bits = binarraytohex(hex, sizeof(hex), (char *)p, len); if (num_bits == 0) { + p = NULL; + free(buf); return PM3_ESOFT; } PrintAndLogEx(SUCCESS, "DemodBuffer:\n%s", hex); From 69d73a4d8dbdf466e9c0e4bac02a021ea2052fdd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 26 Mar 2021 22:33:31 +0100 Subject: [PATCH 106/373] fix coverity 315653 --- client/src/cmdhffelica.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 8516b3ad3..f72283a7b 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -104,8 +104,6 @@ static void print_service_code_list_constraints(void) { PrintAndLogEx(INFO, " - For existence or nonexistence of Service in a product, please check using the Request Service (or Request Service v2) command."); } - - /* static int usage_hf_felica_sim(void) { PrintAndLogEx(INFO, "\n Emulating ISO/18092 FeliCa tag \n"); @@ -1233,24 +1231,26 @@ static int CmdHFFelicaRequestSystemCode(const char *Cmd) { flags |= FELICA_APPEND_CRC; flags |= FELICA_RAW; clear_and_send_command(flags, datalen, data, 0); + PacketResponseNG resp; - if (!waitCmdFelica(0, &resp, 1)) { + if (waitCmdFelica(0, &resp, true) == false) { PrintAndLogEx(ERR, "\nGot no response from card"); return PM3_ERFTRANS; - } else { - felica_syscode_response_t rq_syscode_response; - memcpy(&rq_syscode_response, (felica_syscode_response_t *)resp.data.asBytes, sizeof(felica_syscode_response_t)); + } - if (rq_syscode_response.frame_response.IDm[0] != 0) { - PrintAndLogEx(SUCCESS, "\nGot Request Response:"); - PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(rq_syscode_response.frame_response.IDm, sizeof(rq_syscode_response.frame_response.IDm))); - PrintAndLogEx(SUCCESS, " - Number of Systems: %s", sprint_hex(rq_syscode_response.number_of_systems, sizeof(rq_syscode_response.number_of_systems))); - PrintAndLogEx(SUCCESS, " - System Codes: enumerated in ascending order starting from System 0."); - for (i = 0; i < rq_syscode_response.number_of_systems[0]; i++) { - PrintAndLogEx(SUCCESS, " - %s", sprint_hex(rq_syscode_response.system_code_list + i * 2, sizeof(uint8_t) * 2)); - } + felica_syscode_response_t rq_syscode_response; + memcpy(&rq_syscode_response, (felica_syscode_response_t *)resp.data.asBytes, sizeof(felica_syscode_response_t)); + + if (rq_syscode_response.frame_response.IDm[0] != 0) { + PrintAndLogEx(SUCCESS, "\nGot Request Response:"); + PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(rq_syscode_response.frame_response.IDm, sizeof(rq_syscode_response.frame_response.IDm))); + PrintAndLogEx(SUCCESS, " - Number of Systems: %s", sprint_hex(rq_syscode_response.number_of_systems, sizeof(rq_syscode_response.number_of_systems))); + PrintAndLogEx(SUCCESS, " - System Codes: enumerated in ascending order starting from System 0."); + for (i = 0; i < rq_syscode_response.number_of_systems[0]; i++) { + PrintAndLogEx(SUCCESS, " - %s", sprint_hex(rq_syscode_response.system_code_list + i * 2, sizeof(uint8_t) * 2)); } } + return PM3_SUCCESS; } @@ -1784,11 +1784,15 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { if (active_select) { PrintAndLogEx(SUCCESS, "Active select wait for FeliCa."); PacketResponseNG resp_IDm; - waitCmdFelica(1, &resp_IDm, 1); + if (waitCmdFelica(1, &resp_IDm, true) == false) { + return PM3_ERFTRANS; + } } if (datalen > 0) { PacketResponseNG resp_frame; - waitCmdFelica(0, &resp_frame, 1); + if (waitCmdFelica(0, &resp_frame, true) == false) { + return PM3_ERFTRANS; + } } } return PM3_SUCCESS; From 40f6ff431e9780da1cc8df61d6ddff16527459c2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 27 Mar 2021 10:20:54 +0100 Subject: [PATCH 107/373] text --- client/src/cmdhficlass.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 3de202433..c56af20fe 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -1329,7 +1329,7 @@ static int CmdHFiClassDump(const char *Cmd) { CLIParserFree(ctx); if ((use_replay + rawkey + elite) > 1) { - PrintAndLogEx(FAILED, "Can not use a combo of 'e', 'r', 'n'"); + PrintAndLogEx(ERR, "Can not use a combo of 'elite', 'raw', 'nr'"); return PM3_EINVARG; } @@ -1983,7 +1983,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { CLIParserFree(ctx); if ((use_replay + rawkey + elite) > 1) { - PrintAndLogEx(ERR, "Can not use a combo of 'e', 'r', 'n'"); + PrintAndLogEx(ERR, "Can not use a combo of 'elite', 'raw', 'nr'"); return PM3_EINVARG; } From d46c90b231a1983722eceb78968f4502525f98c3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 27 Mar 2021 10:21:27 +0100 Subject: [PATCH 108/373] text --- client/src/cmdhfmfdes.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 3a647514f..3be04b5e3 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -2932,13 +2932,13 @@ static int CmdHF14ADesReadData(const char *Cmd) { res = handler_desfire_readdata(&ft, type, cs); if (res == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "Successfully read data from file %d:", ft.fileno); - PrintAndLogEx(NORMAL, "\nOffset | Data | Ascii"); - PrintAndLogEx(NORMAL, "----------------------------------------------------------------------------"); + PrintAndLogEx(INFO, "\nOffset | Data | Ascii"); + PrintAndLogEx(INFO, "----------------------------------------------------------------------------"); uint32_t len = le24toh(ft.length); for (uint32_t i = 0; i < len; i += 16) { uint32_t l = len - i; - PrintAndLogEx(NORMAL, "%02d/0x%02X | %s| %s", i, i, sprint_hex(&ft.data[i], l > 16 ? 16 : l), sprint_ascii(&ft.data[i], l > 16 ? 16 : l)); + PrintAndLogEx(INFO, "%02d/0x%02X | %s| %s", i, i, sprint_hex(&ft.data[i], l > 16 ? 16 : l), sprint_ascii(&ft.data[i], l > 16 ? 16 : l)); } } else { PrintAndLogEx(ERR, "Couldn't read data. Error %d", res); From f0510cc0d5db387fcf4607522452cbee629f9201 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 27 Mar 2021 10:21:54 +0100 Subject: [PATCH 109/373] style --- client/src/mifare/desfire_crypto.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index d8fb62aaa..f08aeb7b8 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -899,12 +899,10 @@ void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, * function with tag, key and ivect defined. */ void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation) { - size_t block_size; - if (tag) { - if (!key) + if (key == NULL) key = DESFIRE(tag)->session_key; - if (!ivect) + if (ivect == NULL) ivect = DESFIRE(tag)->ivect; switch (DESFIRE(tag)->authentication_scheme) { @@ -916,8 +914,7 @@ void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *i } } - block_size = key_block_size(key); - + size_t block_size = key_block_size(key); size_t offset = 0; while (offset < data_size) { mifare_cypher_single_block(key, data + offset, ivect, direction, operation, block_size); From 517b5867ff9c606e7ef1dfb145602a067d69063a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 27 Mar 2021 12:44:21 +0100 Subject: [PATCH 110/373] wrong arrow --- client/src/cmdhflegic.c | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/client/src/cmdhflegic.c b/client/src/cmdhflegic.c index 709cf9390..083945609 100644 --- a/client/src/cmdhflegic.c +++ b/client/src/cmdhflegic.c @@ -390,9 +390,9 @@ static int CmdLegicRdbl(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf legic rdbl", "Read data from a LEGIC Prime tag", - "hf legic rdbl -o 0 -l 16 <- reads from byte[0] 16 bytes(system header)\n" - "hf legic rdbl -o 0 -l 4 --iv 55 <- reads from byte[0] 4 bytes with IV 0x55\n" - "hf legic rdbl -o 0 -l 256 --iv 55 <- reads from byte[0] 256 bytes with IV 0x55"); + "hf legic rdbl -o 0 -l 16 -> reads from byte[0] 16 bytes(system header)\n" + "hf legic rdbl -o 0 -l 4 --iv 55 -> reads from byte[0] 4 bytes with IV 0x55\n" + "hf legic rdbl -o 0 -l 256 --iv 55 -> reads from byte[0] 256 bytes with IV 0x55"); void *argtable[] = { arg_param_begin, @@ -444,9 +444,9 @@ static int CmdLegicSim(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf legic sim", "Simulates a LEGIC Prime tag. MIM22, MIM256, MIM1024 types can be emulated", - "hf legic sim -t 0 <- Simulate Type MIM22\n" - "hf legic sim -t 1 <- Simulate Type MIM256 (default)\n" - "hf legic sim -t 2 <- Simulate Type MIM1024"); + "hf legic sim -t 0 -> Simulate Type MIM22\n" + "hf legic sim -t 1 -> Simulate Type MIM256 (default)\n" + "hf legic sim -t 2 -> Simulate Type MIM1024"); void *argtable[] = { arg_param_begin, @@ -495,8 +495,8 @@ static int CmdLegicWrbl(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf legic wrbl", "Write data to a LEGIC Prime tag. It autodetects tagsize to ensure proper write", - "hf legic wrbl -o 0 -d 11223344 <- Write 0x11223344 starting from offset 0)\n" - "hf legic wrbl -o 10 -d DEADBEEF <- Write 0xdeadbeef starting from offset 10"); + "hf legic wrbl -o 0 -d 11223344 -> Write 0x11223344 starting from offset 0)\n" + "hf legic wrbl -o 10 -d DEADBEEF -> Write 0xdeadbeef starting from offset 10"); void *argtable[] = { arg_param_begin, @@ -599,7 +599,7 @@ static int CmdLegicCalcCrc(const char *Cmd) { CLIParserInit(&ctx, "hf legic crc", "Calculates the legic crc8/crc16 on the given data", "hf legic crc -d deadbeef1122\n" - "hf legic crc -d deadbeef1122 --mcc 9A -t 16 <- CRC Type 16"); + "hf legic crc -d deadbeef1122 --mcc 9A -t 16 -> CRC Type 16"); void *argtable[] = { arg_param_begin, @@ -758,9 +758,9 @@ static int CmdLegicDump(const char *Cmd) { CLIParserInit(&ctx, "hf legic dump", "Read all memory from LEGIC Prime MIM22, MIM256, MIM1024 and saves bin/eml/json dump file\n" "It autodetects card type.", - "hf legic dump <-- use UID as filename\n" - "hf legic dump -f myfile <-- use user specified filename\n" - "hf legic dump --deobfuscate <-- use UID as filename and deobfuscate data"); + "hf legic dump --> use UID as filename\n" + "hf legic dump -f myfile --> use user specified filename\n" + "hf legic dump --deobfuscate --> use UID as filename and deobfuscate data"); void *argtable[] = { arg_param_begin, @@ -852,8 +852,8 @@ static int CmdLegicRestore(const char *Cmd) { CLIParserInit(&ctx, "hf legic restore", "Reads binary file and it autodetects card type and verifies that the file has the same size\n" "Then write the data back to card. All bytes except the first 7bytes [UID(4) MCC(1) DCF(2)]", - "hf legic restore -f myfile <-- use user specified filename\n" - "hf legic restore -f myfile --obfuscate <-- use UID as filename and deobfuscate data"); + "hf legic restore -f myfile --> use user specified filename\n" + "hf legic restore -f myfile --obfuscate --> use UID as filename and deobfuscate data"); void *argtable[] = { arg_param_begin, @@ -951,9 +951,9 @@ static int CmdLegicELoad(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf legic eload", "Loads a LEGIC binary dump into emulator memory", - "hf legic eload -f myfile -t 0 <- Simulate Type MIM22\n" - "hf legic eload -f myfile -t 1 <- Simulate Type MIM256 (default)\n" - "hf legic eload -f myfile -t 2 <- Simulate Type MIM1024"); + "hf legic eload -f myfile -t 0 -> Simulate Type MIM22\n" + "hf legic eload -f myfile -t 1 -> Simulate Type MIM256 (default)\n" + "hf legic eload -f myfile -t 2 -> Simulate Type MIM1024"); void *argtable[] = { arg_param_begin, @@ -1019,10 +1019,10 @@ static int CmdLegicESave(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf legic esave", "Saves bin/eml/json dump file of emulator memory", - "hf legic esave <- uses UID as filename\n" - "hf legic esave -f myfile -t 0 <- Type MIM22\n" - "hf legic esave -f myfile -t 1 <- Type MIM256 (default)\n" - "hf legic esave -f myfile -t 2 <- Type MIM1024"); + "hf legic esave --> uses UID as filename\n" + "hf legic esave -f myfile -t 0 --> Type MIM22\n" + "hf legic esave -f myfile -t 1 --> Type MIM256 (default)\n" + "hf legic esave -f myfile -t 2 --> Type MIM1024"); void *argtable[] = { arg_param_begin, From d23eadb03458eb2bac6163b80832cddd52151e66 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 27 Mar 2021 12:45:10 +0100 Subject: [PATCH 111/373] wrong arrow --- client/src/cmdhf14a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 2b1631963..4ecca3f66 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -404,7 +404,7 @@ static int CmdHF14AReader(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf 14a reader", "Reader for ISO 14443A based tags", - "hf 14a reader -@ <- Continuous mode"); + "hf 14a reader -@ -> Continuous mode"); void *argtable[] = { arg_param_begin, @@ -557,7 +557,7 @@ static int CmdHF14ACUIDs(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf 14a cuids", "Collect n>0 ISO14443-a UIDs in one go", - "hf 14a cuids -n 5 <-- Collect 5 UIDs"); + "hf 14a cuids -n 5 --> Collect 5 UIDs"); void *argtable[] = { arg_param_begin, From 16d9199f525b54ad0fff67c4a727a5f276f08d5d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 27 Mar 2021 12:46:24 +0100 Subject: [PATCH 112/373] wrong arrow --- client/src/cmdhftopaz.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhftopaz.c b/client/src/cmdhftopaz.c index ba150cb71..9f174ca9d 100644 --- a/client/src/cmdhftopaz.c +++ b/client/src/cmdhftopaz.c @@ -494,7 +494,7 @@ static int CmdHFTopazSim(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf topaz sim", "Simulate a Topaz tag", - "hf topaz sim <- Not yet implemented"); + "hf topaz sim -> Not yet implemented"); void *argtable[] = { arg_param_begin, @@ -510,7 +510,7 @@ static int CmdHFTopazCmdRaw(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf topaz raw", "Send raw hex data to Topaz tags", - "hf topaz raw <- Not yet implemented"); + "hf topaz raw -> Not yet implemented"); void *argtable[] = { arg_param_begin, From 1284a0bb6a59f345d7f35f58d3c6b72b8b800cb5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 27 Mar 2021 13:22:23 +0100 Subject: [PATCH 113/373] added hf felica info\n hf felica reader, now supports cliparser and continuous mode --- client/src/cmdhffelica.c | 197 ++++++++++++++++++++++++++------------- client/src/cmdhffelica.h | 2 +- 2 files changed, 135 insertions(+), 64 deletions(-) diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index f72283a7b..903332120 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -373,9 +373,129 @@ static int CmdHFFelicaList(const char *Cmd) { return CmdTraceList(args); } +int read_felica_uid(bool loop, bool verbose) { + + int res = PM3_SUCCESS; + + do { + clearCommandBuffer(); + SendCommandMIX(CMD_HF_FELICA_COMMAND, FELICA_CONNECT, 0, 0, NULL, 0); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + + uint8_t status = resp.oldarg[0] & 0xFF; + + if (loop) { + if (status != 0) { + continue; + } + } else { + if (status != 0) { + if (verbose) PrintAndLogEx(WARNING, "FeliCa card select failed"); + res = PM3_EOPABORTED; + break; + } + } + + felica_card_select_t card; + memcpy(&card, (felica_card_select_t *)resp.data.asBytes, sizeof(felica_card_select_t)); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "IDm: " _GREEN_("%s"), sprint_hex_inrow(card.IDm, sizeof(card.IDm))); + set_last_known_card(card); + } + } while (loop && kbd_enter_pressed() == false); + + DropField(); + return res; +} + static int CmdHFFelicaReader(const char *Cmd) { - bool verbose = !(tolower(Cmd[0]) == 's'); - return readFelicaUid(verbose); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica reader", + "Reader for FeliCa based tags", + "hf felica reader -@ -> Continuous mode"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("s", "silent", "silent (no messages)"), + arg_lit0("@", NULL, "optional - continuous reader mode"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + bool verbose = (arg_get_lit(ctx, 1) == false); + bool cm = arg_get_lit(ctx, 2); + CLIParserFree(ctx); + + if (cm) { + PrintAndLogEx(INFO, "Press " _GREEN_("") " to exit"); + } + + CLIParserFree(ctx); + return read_felica_uid(cm, verbose); +} + +static int info_felica(bool verbose) { + + clearCommandBuffer(); + SendCommandMIX(CMD_HF_FELICA_COMMAND, FELICA_CONNECT, 0, 0, NULL, 0); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) { + if (verbose) PrintAndLogEx(WARNING, "FeliCa card select failed"); + return PM3_ESOFT; + } + + felica_card_select_t card; + memcpy(&card, (felica_card_select_t *)resp.data.asBytes, sizeof(felica_card_select_t)); + uint64_t status = resp.oldarg[0]; + + switch (status) { + case 1: { + if (verbose) + PrintAndLogEx(WARNING, "card timeout"); + return PM3_ETIMEOUT; + } + case 2: { + if (verbose) + PrintAndLogEx(WARNING, "card answered wrong"); + return PM3_ESOFT; + } + case 3: { + if (verbose) + PrintAndLogEx(WARNING, "CRC check failed"); + return PM3_ESOFT; + } + case 0: { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "-------- " _CYAN_("FeliCa tag info") " -------------------"); + PrintAndLogEx(SUCCESS, "IDm............ " _GREEN_("%s"), sprint_hex_inrow(card.IDm, sizeof(card.IDm))); + PrintAndLogEx(SUCCESS, "Code........... %s ", sprint_hex_inrow(card.code, sizeof(card.code))); + PrintAndLogEx(SUCCESS, "NFCID2......... %s", sprint_hex_inrow(card.uid, sizeof(card.uid))); + PrintAndLogEx(SUCCESS, "Parameter"); + PrintAndLogEx(SUCCESS, "PAD............ " _YELLOW_("%s"), sprint_hex_inrow(card.PMm, sizeof(card.PMm))); + PrintAndLogEx(SUCCESS, "IC code........ %s", sprint_hex_inrow(card.iccode, sizeof(card.iccode))); + PrintAndLogEx(SUCCESS, "MRT............ %s", sprint_hex_inrow(card.mrt, sizeof(card.mrt))); + PrintAndLogEx(SUCCESS, "Service code... " _YELLOW_("%s"), sprint_hex(card.servicecode, sizeof(card.servicecode))); + PrintAndLogEx(NORMAL, ""); + set_last_known_card(card); + break; + } + } + return PM3_SUCCESS; +} + +static int CmdHFFelicaInfo(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica info", + "Reader for FeliCa based tags", + "hf felica info"); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + return info_felica(false); } /** @@ -1234,7 +1354,7 @@ static int CmdHFFelicaRequestSystemCode(const char *Cmd) { PacketResponseNG resp; if (waitCmdFelica(0, &resp, true) == false) { - PrintAndLogEx(ERR, "\nGot no response from card"); + PrintAndLogEx(ERR, "Got no response from card"); return PM3_ERFTRANS; } @@ -1246,6 +1366,7 @@ static int CmdHFFelicaRequestSystemCode(const char *Cmd) { PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(rq_syscode_response.frame_response.IDm, sizeof(rq_syscode_response.frame_response.IDm))); PrintAndLogEx(SUCCESS, " - Number of Systems: %s", sprint_hex(rq_syscode_response.number_of_systems, sizeof(rq_syscode_response.number_of_systems))); PrintAndLogEx(SUCCESS, " - System Codes: enumerated in ascending order starting from System 0."); + for (i = 0; i < rq_syscode_response.number_of_systems[0]; i++) { PrintAndLogEx(SUCCESS, " - %s", sprint_hex(rq_syscode_response.system_code_list + i * 2, sizeof(uint8_t) * 2)); } @@ -1798,67 +1919,17 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { return PM3_SUCCESS; } -int readFelicaUid(bool verbose) { - - clearCommandBuffer(); - SendCommandMIX(CMD_HF_FELICA_COMMAND, FELICA_CONNECT, 0, 0, NULL, 0); - PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - if (verbose) PrintAndLogEx(WARNING, "FeliCa card select failed"); - return PM3_ESOFT; - } - - felica_card_select_t card; - memcpy(&card, (felica_card_select_t *)resp.data.asBytes, sizeof(felica_card_select_t)); - uint64_t status = resp.oldarg[0]; - - switch (status) { - case 1: { - if (verbose) - PrintAndLogEx(WARNING, "card timeout"); - return PM3_ETIMEOUT; - } - case 2: { - if (verbose) - PrintAndLogEx(WARNING, "card answered wrong"); - return PM3_ESOFT; - } - case 3: { - if (verbose) - PrintAndLogEx(WARNING, "CRC check failed"); - return PM3_ESOFT; - } - case 0: { - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "-------- " _CYAN_("FeliCa tag info") " -------------------"); - - PrintAndLogEx(SUCCESS, "IDm %s", sprint_hex(card.IDm, sizeof(card.IDm))); - PrintAndLogEx(SUCCESS, " - CODE %s", sprint_hex(card.code, sizeof(card.code))); - PrintAndLogEx(SUCCESS, " - NFCID2 %s", sprint_hex(card.uid, sizeof(card.uid))); - - PrintAndLogEx(SUCCESS, "Parameter (PAD) | %s", sprint_hex(card.PMm, sizeof(card.PMm))); - PrintAndLogEx(SUCCESS, " - IC CODE %s", sprint_hex(card.iccode, sizeof(card.iccode))); - PrintAndLogEx(SUCCESS, " - MRT %s", sprint_hex(card.mrt, sizeof(card.mrt))); - - PrintAndLogEx(SUCCESS, "SERVICE CODE %s", sprint_hex(card.servicecode, sizeof(card.servicecode))); - set_last_known_card(card); - break; - } - } - return PM3_SUCCESS; -} - static command_t CommandTable[] = { - - {"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("General") " -----------------------"}, {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"list", CmdHFFelicaList, AlwaysAvailable, "List ISO 18092/FeliCa history"}, + {"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("General") " -----------------------"}, + {"list", CmdHFFelicaList, AlwaysAvailable, "List ISO 18092/FeliCa history"}, {"reader", CmdHFFelicaReader, IfPm3Felica, "Act like an ISO18092/FeliCa reader"}, + {"info", CmdHFFelicaInfo, IfPm3Felica, "Tag information"}, {"sniff", CmdHFFelicaSniff, IfPm3Felica, "Sniff ISO 18092/FeliCa traffic"}, {"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"}, {"rdunencrypted", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from authentication-not-required Service."}, - {"wrunencrypted", CmdHFFelicaWriteWithoutEncryption, IfPm3Felica, "write Block Data to an authentication-not-required Service."}, - {"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("FeliCa Standard") " -----------------------"}, + {"wrunencrypted", CmdHFFelicaWriteWithoutEncryption, IfPm3Felica, "write Block Data to an authentication-not-required Service."}, + {"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("FeliCa Standard") " -----------------------"}, //{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, {"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."}, {"rqresponse", CmdHFFelicaRequestResponse, IfPm3Felica, "verify the existence of a card and its Mode."}, @@ -1870,17 +1941,17 @@ static command_t CommandTable[] = { //{"write", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."}, //{"scsvcodev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "verify the existence of Area or Service, and to acquire Key Version."}, //{"getsysstatus", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the setup information in System."}, - {"rqspecver", CmdHFFelicaRequestSpecificationVersion, IfPm3Felica, "acquire the version of card OS."}, + {"rqspecver", CmdHFFelicaRequestSpecificationVersion, IfPm3Felica, "acquire the version of card OS."}, {"resetmode", CmdHFFelicaResetMode, IfPm3Felica, "reset Mode to Mode 0."}, //{"auth1v2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, //{"auth2v2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, //{"readv2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, //{"writev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to authentication-required Service."}, //{"uprandomid", CmdHFFelicaNotImplementedYet, IfPm3Felica, "update Random ID (IDr)."}, - {"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("FeliCa Light") " -----------------------"}, - {"litesim", CmdHFFelicaSimLite, IfPm3Felica, "Emulating ISO/18092 FeliCa Lite tag"}, - {"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"}, - // {"sim", CmdHFFelicaSim, IfPm3Felica, " -- Simulate ISO 18092/FeliCa tag"} + {"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("FeliCa Light") " -----------------------"}, + {"litesim", CmdHFFelicaSimLite, IfPm3Felica, "Emulating ISO/18092 FeliCa Lite tag"}, + {"litedump", CmdHFFelicaDumpLite, IfPm3Felica, "Wait for and try dumping FelicaLite"}, + // {"sim", CmdHFFelicaSim, IfPm3Felica, " -- Simulate ISO 18092/FeliCa tag"} {NULL, NULL, NULL, NULL} }; diff --git a/client/src/cmdhffelica.h b/client/src/cmdhffelica.h index e7be7ede1..271a0d448 100644 --- a/client/src/cmdhffelica.h +++ b/client/src/cmdhffelica.h @@ -15,7 +15,7 @@ #include "iso18.h" int CmdHFFelica(const char *Cmd); -int readFelicaUid(bool verbose); +int read_felica_uid(bool loop, bool verbose); int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose); int send_rd_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp); From be4b36e605d3ebd4ab1eb16480cdc08721f140ed Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 27 Mar 2021 13:23:01 +0100 Subject: [PATCH 114/373] hf search - enabled FeliCa detection --- client/src/cmdhf.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index 2bc6edbfe..019062440 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -137,16 +137,15 @@ int CmdHFSearch(const char *Cmd) { } } - /* - PROMPT_CLEARLINE; - PrintAndLogEx(INPLACE, " Searching for FeliCa tag..."); - if (IfPm3Felica()) { - if (readFelicaUid(false) == PM3_SUCCESS) { - PrintAndLogEx(NORMAL, "\nValid " _GREEN_("ISO18092 / FeliCa tag") " found\n"); - res = PM3_SUCCESS; - } + PROMPT_CLEARLINE; + PrintAndLogEx(INPLACE, " Searching for FeliCa tag..."); + if (IfPm3Felica()) { + if (read_felica_uid(false, false) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO18092 / FeliCa tag") " found\n"); + res = PM3_SUCCESS; } - */ + } + /* PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, " Searching for CryptoRF tag..."); From a34bf3264ceb79a7be663837a455f194bfa0b1cc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 27 Mar 2021 18:44:49 +0100 Subject: [PATCH 115/373] hf cryptorf, now uses cliparser, *not enabled commands* --- client/src/cmdhf.c | 2 +- client/src/cmdhfcryptorf.c | 858 +++++++++++++++++-------------------- client/src/cmdhfcryptorf.h | 4 +- 3 files changed, 401 insertions(+), 463 deletions(-) diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index 019062440..c92fc8fbb 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -150,7 +150,7 @@ int CmdHFSearch(const char *Cmd) { PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, " Searching for CryptoRF tag..."); if (IfPm3Iso14443b()) { - if (readHFCryptoRF(false) == PM3_SUCCESS) { + if (readHFCryptoRF(false, false) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("CryptoRF tag") " found\n"); res = PM3_SUCCESS; } diff --git a/client/src/cmdhfcryptorf.c b/client/src/cmdhfcryptorf.c index bf2df530c..086fa4a11 100644 --- a/client/src/cmdhfcryptorf.c +++ b/client/src/cmdhfcryptorf.c @@ -18,94 +18,21 @@ #include "cmdtrace.h" #include "crc16.h" #include "cmdhf14a.h" -#include "protocols.h" // definitions of ISO14B protocol +#include "protocols.h" // definitions of ISO14B protocol #include "iso14b.h" +#include "cliparser.h" // cliparsing #define TIMEOUT 2000 + +#ifndef CRYPTORF_MEM_SIZE +# define CRYPTORF_MEM_SIZE 1024 +#endif + static int CmdHelp(const char *Cmd); -static int usage_hf_cryptorf_info(void) { - PrintAndLogEx(NORMAL, "Usage: hf cryptorf info [h] [v]\n" - "Options:\n" - " h this help\n" - " v verbose\n" - "\n" - "Example:\n" - _YELLOW_(" hf cryptorf info") - ); - return PM3_SUCCESS; -} -static int usage_hf_cryptorf_reader(void) { - PrintAndLogEx(NORMAL, "Usage: hf cryptorf reader [h] [v]\n" - "Options:\n" - " h this help\n" - " v verbose\n" - "\n" - "Example:\n" - _YELLOW_(" hf cryptorf reader") - ); - return PM3_SUCCESS; -} -static int usage_hf_cryptorf_sniff(void) { - PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer\n" - "Buffer accessible from command " _YELLOW_("'hf list cryptorf'") "\n" - "Usage: hf cryptorf sniff [h]\n" - "Options:\n" - " h this help\n" - "\n" - "Example:\n" - _YELLOW_(" hf cryptorf sniff") - ); - return PM3_SUCCESS; -} -static int usage_hf_cryptorf_sim(void) { - PrintAndLogEx(NORMAL, "Emulating CryptoRF tag with emulator memory\n" - "Usage: hf cryptorf sim [h] \n" - "Options:\n" - " h this help\n" - "\n" - "Example:\n" - _YELLOW_(" hf cryptorf sim") - ); - return PM3_SUCCESS; -} -static int usage_hf_cryptorf_dump(void) { - PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-14443-B tag and save it to file\n" - "\n" - "Usage: hf cryptorf dump [h] [card memory] \n" - "Options:\n" - " h this help\n" - " f filename, if no UID will be used as filename\n" - "\n" - "Examples:\n" - "\thf cryptorf dump\n" - "\thf cryptorf dump f mydump"); - return PM3_SUCCESS; -} -static int usage_hf_cryptorf_eload(void) { - PrintAndLogEx(NORMAL, "It loads a binary dump into emulator memory\n" - "Usage: hf cryptorf eload [f ]\n" - "Options:\n" - " h this help\n" - " f filename, if no UID will be used as filename\n" - "\n" - "Examples:\n" - _YELLOW_(" hf cryptorf eload f filename") - ); - return PM3_SUCCESS; -} -static int usage_hf_cryptorf_esave(void) { - PrintAndLogEx(NORMAL, "It saves bin/eml/json dump file of emulator memory\n" - " Usage: hf cryptorf esave [f ]\n" - "Options:\n" - " h this help\n" - " f filename, if no UID will be used as filename\n" - "\n" - "Examples:\n" - _YELLOW_(" hf cryptorf esave ") - _YELLOW_(" hf cryptorf esave f filename") - ); - return PM3_SUCCESS; +static iso14b_card_select_t last_known_card; +static void set_last_known_card(iso14b_card_select_t card) { + last_known_card = card; } static int switch_off_field_cryptorf(void) { @@ -125,8 +52,17 @@ static int CmdHFCryptoRFList(const char *Cmd) { } static int CmdHFCryptoRFSim(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_cryptorf_sim(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf cryptorf sim", + "Simulate a CryptoRF tag", + "hf cryptorf sim"); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + CLIParserFree(ctx); clearCommandBuffer(); SendCommandMIX(CMD_HF_CRYPTORF_SIM, 0, 0, 0, NULL, 0); @@ -134,12 +70,24 @@ static int CmdHFCryptoRFSim(const char *Cmd) { } static int CmdHFCryptoRFSniff(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf cryptorf sniff", + "Sniff the communication reader and tag", + "hf cryptorf sniff\n" + ); - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_cryptorf_sniff(); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); clearCommandBuffer(); SendCommandNG(CMD_HF_ISO14443B_SNIFF, NULL, 0); + + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf cryptorf list") "` to view captured tracelog"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -f hf_cryptorf_mytrace") "` to save tracelog for later analysing"); return PM3_SUCCESS; } @@ -172,343 +120,8 @@ static bool get_14b_UID(iso14b_card_select_t *card) { return false; } -static int CmdHFCryptoRFInfo(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_cryptorf_info(); - - bool verbose = (cmdp == 'v'); - - int res = infoHFCryptoRF(verbose); - if (res != PM3_SUCCESS && verbose) { - PrintAndLogEx(FAILED, "no 14443-B tag found"); - } - return res; -} - -static int CmdHFCryptoRFReader(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_cryptorf_reader(); - - bool verbose = (cmdp == 'v'); - - int res = readHFCryptoRF(verbose); - if (res != PM3_SUCCESS && verbose) { - PrintAndLogEx(FAILED, "no 14443-B tag found"); - } - return res; -} - -// need to write to file -static int CmdHFCryptoRFDump(const char *Cmd) { - - uint8_t fileNameLen = 0; - char filename[FILE_PATH_SIZE] = {0}; - char *fptr = filename; - bool errors = false; - uint8_t cmdp = 0, cardtype = 1; - uint16_t cardsize = 0; - uint8_t blocks = 0; - iso14b_card_select_t card; - - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_cryptorf_dump(); - case 'f': - fileNameLen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); - cmdp += 2; - break; - default: - if (cmdp == 0) { - cardtype = param_get8ex(Cmd, cmdp, 1, 10); - cmdp++; - } else { - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - } - - //Validations - if (errors) return usage_hf_cryptorf_dump(); - - switch (cardtype) { - case 2: - cardsize = (512 / 8) + 4; - blocks = 0x0F; - break; - case 1: - default: - cardsize = (4096 / 8) + 4; - blocks = 0x7F; - break; - } - - if (!get_14b_UID(&card)) { - PrintAndLogEx(WARNING, "No tag found."); - return PM3_SUCCESS; - } - - if (fileNameLen < 1) { - PrintAndLogEx(INFO, "Using UID as filename"); - fptr += sprintf(fptr, "hf-cryptorf-"); - FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen); - } - - // detect blocksize from card :) - PrintAndLogEx(NORMAL, "Reading memory from tag UID %s", sprint_hex(card.uid, card.uidlen)); - - uint8_t data[cardsize]; - memset(data, 0, sizeof(data)); - - int blocknum = 0; - uint8_t *recv = NULL; - - PacketResponseNG resp; - clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0, NULL, 0); - - //select - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - if (resp.oldarg[0]) { - PrintAndLogEx(INFO, "failed to select %" PRId64 " | %" PRId64, resp.oldarg[0], resp.oldarg[1]); - goto out; - } - } - - uint8_t req[2] = {ISO14443B_READ_BLK}; - - for (int retry = 0; retry < 5; retry++) { - - req[1] = blocknum; - - clearCommandBuffer(); - SendCommandOLD(CMD_HF_ISO14443B_COMMAND, ISO14B_APPEND_CRC | ISO14B_RAW, 2, 0, req, sizeof(req)); - - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - - uint8_t status = resp.oldarg[0] & 0xFF; - if (status > 0) { - continue; - } - - uint16_t len = (resp.oldarg[1] & 0xFFFF); - recv = resp.data.asBytes; - - if (!check_crc(CRC_14443_B, recv, len)) { - PrintAndLogEx(FAILED, "crc fail, retrying one more time"); - continue; - } - - memcpy(data + (blocknum * 4), resp.data.asBytes, 4); - - if (blocknum == 0xFF) { - //last read. - break; - } - - - retry = 0; - blocknum++; - if (blocknum > blocks) { - // read config block - blocknum = 0xFF; - } - - printf("."); - fflush(stdout); - } - } - - if (blocknum != 0xFF) { - PrintAndLogEx(NORMAL, "\n Dump failed"); - goto out; - } - - PrintAndLogEx(NORMAL, "\n"); - PrintAndLogEx(NORMAL, "block# | data | ascii"); - PrintAndLogEx(NORMAL, "---------+--------------+----------"); - - for (int i = 0; i <= blocks; i++) { - PrintAndLogEx(NORMAL, - "%3d/0x%02X | %s | %s", - i, - i, - sprint_hex(data + (i * 4), 4), - sprint_ascii(data + (i * 4), 4) - ); - } - - PrintAndLogEx(NORMAL, "\n"); - - - size_t datalen = (blocks + 1) * 4; - saveFileEML(filename, data, datalen, 4); - saveFile(filename, ".bin", data, datalen); -out: - return switch_off_field_cryptorf(); -} - -static int CmdHFCryptoRFELoad(const char *Cmd) { - - size_t datalen = 1024; - char filename[FILE_PATH_SIZE] = {0x00}; - bool errors = false, has_filename = false; - uint8_t cmdp = 0; - - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h' : - return usage_hf_cryptorf_eload(); - case 'f' : - if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { - PrintAndLogEx(FAILED, "Filename too long"); - errors = true; - break; - } - has_filename = true; - cmdp += 2; - break; - default : - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - if (has_filename == false) - errors = true; - - //Validations - if (errors || strlen(Cmd) == 0) return usage_hf_cryptorf_eload(); - - // set up buffer - uint8_t *data = calloc(datalen, sizeof(uint8_t)); - if (!data) { - PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); - return PM3_EMALLOC; - } - - if (loadFile_safe(filename, ".bin", (void **)&data, &datalen) != PM3_SUCCESS) { - free(data); - PrintAndLogEx(WARNING, "Error, reading file"); - return PM3_EFILE; - } - - PrintAndLogEx(SUCCESS, "Uploading to emulator memory"); - - /* - // fast push mode - conn.block_after_ACK = true; - - //Send to device - uint32_t bytes_sent = 0; - uint32_t bytes_remaining = bytes_read; - - while (bytes_remaining > 0) { - uint32_t bytes_in_packet = MIN(PM3_CMD_DATA_SIZE, bytes_remaining); - if (bytes_in_packet == bytes_remaining) { - // Disable fast mode on last packet - conn.block_after_ACK = false; - } - clearCommandBuffer(); - SendCommandOLD(CMD_HF_CRYPTORF_EML_MEMSET, bytes_sent, bytes_in_packet, 0, data + bytes_sent, bytes_in_packet); - bytes_remaining -= bytes_in_packet; - bytes_sent += bytes_in_packet; - } - */ - free(data); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "Done"); - return PM3_SUCCESS; -} - -static int CmdHFCryptoRFESave(const char *Cmd) { - - char filename[FILE_PATH_SIZE] = {0}; - char *fptr = filename; - int fileNameLen = 0; - size_t numofbytes = 1024; - bool errors = false; - uint8_t cmdp = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h' : - return usage_hf_cryptorf_esave(); - case 'f' : - fileNameLen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); - if (!fileNameLen) - errors = true; - if (fileNameLen > FILE_PATH_SIZE - 5) - fileNameLen = FILE_PATH_SIZE - 5; - cmdp += 2; - break; - default : - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors || strlen(Cmd) == 0) return usage_hf_cryptorf_esave(); - - // set up buffer - uint8_t *data = calloc(numofbytes, sizeof(uint8_t)); - if (!data) { - PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); - return PM3_EMALLOC; - } - - // download emulator memory - PrintAndLogEx(SUCCESS, "Reading emulator memory..."); - if (!GetFromDevice(BIG_BUF_EML, data, numofbytes, 0, NULL, 0, NULL, 2500, false)) { - PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); - free(data); - return PM3_ETIMEOUT; - } - - // user supplied filename? - if (fileNameLen < 1) { - PrintAndLogEx(INFO, "Using UID as filename"); - fptr += sprintf(fptr, "hf-cryptorf-"); - FillFileNameByUID(fptr, data, "-dump", 4); - } - - saveFile(filename, ".bin", data, numofbytes); - //needs to change - saveFileEML(filename, data, numofbytes, 8); - //needs to change - saveFileJSON(filename, jsfRaw, data, numofbytes, NULL); - return PM3_SUCCESS; -} - -static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"dump", CmdHFCryptoRFDump, IfPm3Iso14443b, "Read all memory pages of an CryptoRF tag, save to file"}, - {"info", CmdHFCryptoRFInfo, IfPm3Iso14443b, "Tag information"}, - {"list", CmdHFCryptoRFList, AlwaysAvailable, "List ISO 14443B history"}, - {"reader", CmdHFCryptoRFReader, IfPm3Iso14443b, "Act as a CryptoRF reader to identify a tag"}, - {"sim", CmdHFCryptoRFSim, IfPm3Iso14443b, "Fake CryptoRF tag"}, - {"sniff", CmdHFCryptoRFSniff, IfPm3Iso14443b, "Eavesdrop CryptoRF"}, - {"eload", CmdHFCryptoRFELoad, AlwaysAvailable, "Load binary dump to emulator memory"}, - {"esave", CmdHFCryptoRFESave, AlwaysAvailable, "Save emulator memory to binary file"}, - - {NULL, NULL, NULL, NULL} -}; - -static int CmdHelp(const char *Cmd) { - (void)Cmd; // Cmd is not used so far - CmdsHelp(CommandTable); - return PM3_SUCCESS; -} - -int CmdHFCryptoRF(const char *Cmd) { - clearCommandBuffer(); - return CmdsParse(CommandTable, Cmd); -} - // Print extented information about tag. -int infoHFCryptoRF(bool verbose) { +static int infoHFCryptoRF(bool verbose) { int res = PM3_ESOFT; @@ -550,43 +163,370 @@ int infoHFCryptoRF(bool verbose) { return res; } -// get and print general info cryptoRF -int readHFCryptoRF(bool verbose) { +static int CmdHFCryptoRFInfo(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf cryptorf info", + "Act as a CryptoRF reader.", + "hf cryptorf info"); - int res = PM3_ESOFT; - - // 14b get and print UID only (general info) - clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); - PacketResponseNG resp; - - if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); - return PM3_ETIMEOUT; - } - - iso14b_card_select_t card; - memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); - - uint64_t status = resp.oldarg[0]; - - switch (status) { - case 0: - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, " UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLogEx(SUCCESS, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); - PrintAndLogEx(SUCCESS, " CHIPID : %02X", card.chipid); - res = PM3_SUCCESS; - break; - case 2: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); - break; - case 3: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); - break; - default: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed"); - break; + void *argtable[] = { + arg_param_begin, + arg_lit0("v", "verbose", "verbose output"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + bool verbose = arg_get_lit(ctx, 1); + CLIParserFree(ctx); + int res = infoHFCryptoRF(verbose); + if (res != PM3_SUCCESS && verbose) { + PrintAndLogEx(FAILED, "no CryptoRF / ISO14443-B tag found"); } return res; } + +// get and print general info cryptoRF +int readHFCryptoRF(bool loop, bool verbose) { + + int res = PM3_ESOFT; + do { + clearCommandBuffer(); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + + uint8_t status = resp.oldarg[0] & 0xFF; + + if (loop) { + if (status != 0) { + continue; + } + } else { + // when not in continuous mode + if (status != 0) { + if (verbose) PrintAndLogEx(WARNING, "cryptoRF / ISO14443-b card select failed"); + res = PM3_EOPABORTED; + break; + } + } + + iso14b_card_select_t card; + memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex_inrow(card.uid, card.uidlen)); + set_last_known_card(card); + } + } while (loop && kbd_enter_pressed() == false); + + DropField(); + return res; +} + +static int CmdHFCryptoRFReader(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf cryptorf reader", + "Act as a cryptoRF reader. Look for cryptoRF tags until Enter or the pm3 button is pressed", + "hf cryptorf reader -@ -> continuous reader mode" + ); + + void *argtable[] = { + arg_param_begin, + arg_lit0("@", NULL, "optional - continuous reader mode"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + bool cm = arg_get_lit(ctx, 1); + CLIParserFree(ctx); + + if (cm) { + PrintAndLogEx(INFO, "Press " _GREEN_("") " to exit"); + } + return readHFCryptoRF(cm, false); +} + +// need to write to file +static int CmdHFCryptoRFDump(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf cryptorf dump", + "Dump all memory from a CryptoRF tag (512/4096 bit size)", + "hf cryptorf dump\n" + ); + + void *argtable[] = { + arg_param_begin, + arg_str0("f", "file", "", "filename to save dump to"), + arg_lit0(NULL, "64", "64byte / 512bit memory"), + arg_lit0(NULL, "512", "512byte / 4096bit memory"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + char *fnameptr = filename; + + bool m64 = arg_get_lit(ctx, 2); + bool m512 = arg_get_lit(ctx, 3); + CLIParserFree(ctx); + + if (m512 + m64 > 1) { + PrintAndLogEx(INFO, "Select only one card memory size"); + return PM3_EINVARG; + } + + uint16_t cardsize = 0; + uint8_t blocks = 0; + if (m64) { + cardsize = (512 / 8) + 4; + blocks = 0x0F; + } + if (m512) { + cardsize = (4096 / 8) + 4; + blocks = 0x7F; + } + + iso14b_card_select_t card; + if (get_14b_UID(&card) == false) { + PrintAndLogEx(WARNING, "No tag found."); + return PM3_SUCCESS; + } + + // detect blocksize from card :) + PrintAndLogEx(INFO, "Reading memory from tag UID " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen)); + + uint8_t data[cardsize]; + memset(data, 0, sizeof(data)); + + int blocknum = 0; + uint8_t *recv = NULL; + + PacketResponseNG resp; + clearCommandBuffer(); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0, NULL, 0); + + //select + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (resp.oldarg[0]) { + PrintAndLogEx(ERR, "failed to select %" PRId64 " | %" PRId64, resp.oldarg[0], resp.oldarg[1]); + goto out; + } + } + + uint8_t req[2] = {ISO14443B_READ_BLK}; + for (int retry = 0; retry < 5; retry++) { + + req[1] = blocknum; + + clearCommandBuffer(); + SendCommandOLD(CMD_HF_ISO14443B_COMMAND, ISO14B_APPEND_CRC | ISO14B_RAW, 2, 0, req, sizeof(req)); + + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + + uint8_t status = resp.oldarg[0] & 0xFF; + if (status > 0) { + continue; + } + + uint16_t len = (resp.oldarg[1] & 0xFFFF); + recv = resp.data.asBytes; + + if (!check_crc(CRC_14443_B, recv, len)) { + PrintAndLogEx(FAILED, "crc fail, retrying one more time"); + continue; + } + + memcpy(data + (blocknum * 4), resp.data.asBytes, 4); + + if (blocknum == 0xFF) { + //last read. + break; + } + + retry = 0; + blocknum++; + if (blocknum > blocks) { + // read config block + blocknum = 0xFF; + } + + printf("."); + fflush(stdout); + } + } + + if (blocknum != blocks) { + PrintAndLogEx(ERR, "\nDump failed"); + goto out; + } + + PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(INFO, "block# | data | ascii"); + PrintAndLogEx(INFO, "---------+--------------+----------"); + + for (int i = 0; i <= blocks; i++) { + PrintAndLogEx(INFO, + "%3d/0x%02X | %s | %s", + i, + i, + sprint_hex(data + (i * 4), 4), + sprint_ascii(data + (i * 4), 4) + ); + } + + PrintAndLogEx(NORMAL, ""); + + size_t datalen = (blocks + 1) * 4; + + if (fnlen < 1) { + PrintAndLogEx(INFO, "Using UID as filename"); + fnameptr += sprintf(fnameptr, "hf-cryptorf-"); + FillFileNameByUID(fnameptr, card.uid, "-dump", card.uidlen); + } + + saveFileEML(filename, data, datalen, 4); + saveFile(filename, ".bin", data, datalen); + //json +out: + return switch_off_field_cryptorf(); +} + +static int CmdHFCryptoRFELoad(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf cryptorf eload", + "Loads CryptoRF tag dump into emulator memory on device", + "hf cryptorf eload -f hf-cryptorf-0102030405-dump.bin\n" + ); + + void *argtable[] = { + arg_param_begin, + arg_str1("f", "file", "", "filename of dump"), + 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, FILE_PATH_SIZE, &fnlen); + + if (strlen(filename) == 0) { + PrintAndLogEx(ERR, "Error: Please specify a filename"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + size_t datalen = CRYPTORF_MEM_SIZE; + // set up buffer + uint8_t *data = calloc(datalen, sizeof(uint8_t)); + if (!data) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); + return PM3_EMALLOC; + } + + if (loadFile_safe(filename, ".bin", (void **)&data, &datalen) != PM3_SUCCESS) { + free(data); + PrintAndLogEx(WARNING, "Error, reading file"); + return PM3_EFILE; + } + + PrintAndLogEx(SUCCESS, "Uploading to emulator memory"); + + uint32_t bytes_sent = 0; + /* + //Send to device + uint32_t bytes_remaining = bytes_read; + + while (bytes_remaining > 0) { + uint32_t bytes_in_packet = MIN(PM3_CMD_DATA_SIZE, bytes_remaining); + if (bytes_in_packet == bytes_remaining) { + // Disable fast mode on last packet + conn.block_after_ACK = false; + } + clearCommandBuffer(); + SendCommandOLD(CMD_HF_CRYPTORF_EML_MEMSET, bytes_sent, bytes_in_packet, 0, data + bytes_sent, bytes_in_packet); + bytes_remaining -= bytes_in_packet; + bytes_sent += bytes_in_packet; + } + */ + free(data); + PrintAndLogEx(SUCCESS, "sent %d bytes of data to device emulator memory", bytes_sent); + return PM3_SUCCESS; +} + +static int CmdHFCryptoRFESave(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf cryptorf esave", + "Save emulator memory to bin/eml/json file\n" + "if filename is not supplied, UID will be used.", + "hf cryptorf esave\n" + "hf cryptorf esave -f filename" + ); + void *argtable[] = { + arg_param_begin, + arg_str0("f", "file", "", "filename of dumpfile"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + char *fnameptr = filename; + CLIParserFree(ctx); + + size_t numofbytes = CRYPTORF_MEM_SIZE; + + // set up buffer + uint8_t *data = calloc(numofbytes, sizeof(uint8_t)); + if (!data) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); + return PM3_EMALLOC; + } + + // download emulator memory + PrintAndLogEx(SUCCESS, "Reading emulator memory..."); + if (!GetFromDevice(BIG_BUF_EML, data, numofbytes, 0, NULL, 0, NULL, 2500, false)) { + PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); + free(data); + return PM3_ETIMEOUT; + } + + // user supplied filename? + if (fnlen < 1) { + PrintAndLogEx(INFO, "Using UID as filename"); + fnameptr += sprintf(fnameptr, "hf-cryptorf-"); + FillFileNameByUID(fnameptr, data, "-dump", 4); + } + + saveFile(filename, ".bin", data, numofbytes); + //needs to change + saveFileEML(filename, data, numofbytes, 8); + //needs to change + saveFileJSON(filename, jsfRaw, data, numofbytes, NULL); + return PM3_SUCCESS; +} + +static command_t CommandTable[] = { + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"dump", CmdHFCryptoRFDump, IfPm3Iso14443b, "Read all memory pages of an CryptoRF tag, save to file"}, + {"info", CmdHFCryptoRFInfo, IfPm3Iso14443b, "Tag information"}, + {"list", CmdHFCryptoRFList, AlwaysAvailable, "List ISO 14443B history"}, + {"reader", CmdHFCryptoRFReader, IfPm3Iso14443b, "Act as a CryptoRF reader to identify a tag"}, + {"sim", CmdHFCryptoRFSim, IfPm3Iso14443b, "Fake CryptoRF tag"}, + {"sniff", CmdHFCryptoRFSniff, IfPm3Iso14443b, "Eavesdrop CryptoRF"}, + {"eload", CmdHFCryptoRFELoad, AlwaysAvailable, "Load binary dump to emulator memory"}, + {"esave", CmdHFCryptoRFESave, AlwaysAvailable, "Save emulator memory to binary file"}, + {NULL, NULL, NULL, NULL} +}; + +static int CmdHelp(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + CmdsHelp(CommandTable); + return PM3_SUCCESS; +} + +int CmdHFCryptoRF(const char *Cmd) { + clearCommandBuffer(); + return CmdsParse(CommandTable, Cmd); +} + diff --git a/client/src/cmdhfcryptorf.h b/client/src/cmdhfcryptorf.h index 82508e415..544532d20 100644 --- a/client/src/cmdhfcryptorf.h +++ b/client/src/cmdhfcryptorf.h @@ -14,7 +14,5 @@ #include "common.h" int CmdHFCryptoRF(const char *Cmd); - -int infoHFCryptoRF(bool verbose); -int readHFCryptoRF(bool verbose); +int readHFCryptoRF(bool loop, bool verbose); #endif From 5e963a07467526c2a3d0690ff775124895ef0777 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 28 Mar 2021 18:46:27 +0200 Subject: [PATCH 116/373] data hex2bin - talk about brain melt --- client/src/cmddata.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index d514b53ce..3dd82f0d2 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -2421,9 +2421,30 @@ static int Cmdhex2bin(const char *Cmd) { PrintAndLogEx(FAILED, "Error parsing bytes"); return PM3_EINVARG; } + + for (int i = 0; i < dlen; i++) { + char x = data[i]; + if (isxdigit(x) == false) { + PrintAndLogEx(ERR, "Non hex digit found"); + return PM3_EINVARG; + } + } + PrintAndLogEx(SUCCESS, "" NOLF); for (int i = 0; i < dlen; i++) { char x = data[i]; + + // capitalize + if (x >= 'a' && x <= 'f') + x -= 32; + // convert to numeric value + if (x >= '0' && x <= '9') + x -= '0'; + else if (x >= 'A' && x <= 'F') + x -= 'A' - 10; + else + continue; + for (int j = 0 ; j < 4 ; ++j) { PrintAndLogEx(NORMAL, "%d" NOLF, (x >> (3 - j)) & 1); } From c00cbb6ae2452f11c29599e2e922022dc3bd30ed Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 28 Mar 2021 22:34:03 +0200 Subject: [PATCH 117/373] added link to another PM3 GUI project --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 02c08a7f8..850fc7395 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,9 @@ The official PM3-GUI from Gaucho will not work. Not to mention is quite old and The new [Proxmark3 Universal GUI](https://github.com/burma69/PM3UniversalGUI) will work more or less. Change is needed in order to show helptext when client isn't connected to a device. We don't know how active the maintainers are. There has been brought to our attention that there is quite a few Chinese Windows GUI available. Usually you find them on alibaba / taobao ads but we have no idea which fw/client they are compatible with. Proceed with caution if you decide to go down that road. +Another new [Proxmark3 GUI crosscompiled](https://github.com/wh201906/Proxmark3GUI/) which is recently updated and claims to support latest source of this repo. Give it a spin and let us know how it works for you. + + # Donations Nothing says thank you as much as a donation. So if you feel the love, do feel free to become a iceman patron. For some tiers it comes with rewards. From 758488f37734c6b21ad48fd00d74cde5d9c1b412 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 29 Mar 2021 10:38:47 +0200 Subject: [PATCH 118/373] text --- client/src/cmddata.c | 9 +- client/src/cmdhf14a.c | 3 +- client/src/cmdhffelica.c | 167 ++++++++++++++++---------------------- client/src/cmdhficlass.c | 1 - client/src/cmdhflto.c | 7 +- client/src/cmdlfem4x50.c | 1 - client/src/cmdsmartcard.c | 1 - client/src/util.c | 1 - 8 files changed, 80 insertions(+), 110 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 3dd82f0d2..b7a597eda 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -2697,20 +2697,21 @@ typedef struct { } lf_modulation_t; static int print_modulation(lf_modulation_t b) { - PrintAndLogEx(INFO, " Modulation.... " _GREEN_("%s"), GetSelectedModulationStr(b.modulation)); - PrintAndLogEx(INFO, " Bit clock..... " _GREEN_("RF/%d"), b.bitrate); + PrintAndLogEx(INFO, " Modulation........ " _GREEN_("%s"), GetSelectedModulationStr(b.modulation)); + PrintAndLogEx(INFO, " Bit clock......... " _GREEN_("RF/%d"), b.bitrate); + PrintAndLogEx(INFO, " Approx baudrate... " _GREEN_("%.f") "bauds", (125000 / (float)b.bitrate) ); switch (b.modulation) { case DEMOD_PSK1: case DEMOD_PSK2: case DEMOD_PSK3: - PrintAndLogEx(SUCCESS, " Carrier rate.. %d", b.carrier); + PrintAndLogEx(SUCCESS, " Carrier rate...... %d", b.carrier); break; case DEMOD_FSK: case DEMOD_FSK1: case DEMOD_FSK1a: case DEMOD_FSK2: case DEMOD_FSK2a: - PrintAndLogEx(SUCCESS, " Field Clocks.. FC/%u, FC/%u", b.fc1, b.fc2); + PrintAndLogEx(SUCCESS, " Field Clocks...... FC/%u, FC/%u", b.fc1, b.fc2); break; case DEMOD_NRZ: case DEMOD_ASK: diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 4ecca3f66..8e1134516 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -1628,8 +1628,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { } if (verbose) { - PrintAndLogEx(SUCCESS, "------ " _CYAN_("ISO14443-a Information") "------------------"); - PrintAndLogEx(SUCCESS, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, "--- " _CYAN_("ISO14443-a Information") "---------------------"); } PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen)); diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 903332120..ec649d959 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -119,24 +119,7 @@ static int usage_hf_felica_sim(void) { } */ -static int usage_hf_felica_request_service(void) { - PrintAndLogEx(NORMAL, "\nInfo: Use this command to verify the existence of Area and Service, and to acquire Key Version:"); - PrintAndLogEx(NORMAL, " - When the specified Area or Service exists, the card returns Key Version."); - PrintAndLogEx(NORMAL, " - When the specified Area or Service does not exist, the card returns FFFFh as Key Version."); - PrintAndLogEx(NORMAL, "For Node Code List of a command packet, Area Code or Service Code of the target " - "of acquisition of Key Version shall be enumerated in Little Endian format. " - "If Key Version of System is the target of acquisition, FFFFh shall be specified " - "in the command packet."); - PrintAndLogEx(NORMAL, "\nUsage: hf felica rqservice [-h] [-i] <01 Number of Node hex> <0A0B Node Code List hex (Little Endian)>"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); - PrintAndLogEx(NORMAL, " -a auto node number mode - iterates through all possible nodes 1 < n < 32"); - PrintAndLogEx(NORMAL, "\nExamples: "); - PrintAndLogEx(NORMAL, " hf felica rqservice 01 FFFF"); - PrintAndLogEx(NORMAL, " hf felica rqservice -a FFFF"); - PrintAndLogEx(NORMAL, " hf felica rqservice -i 01100910c11bc407 01 FFFF \n\n"); - return PM3_SUCCESS; -} + static int usage_hf_felica_request_response(void) { PrintAndLogEx(NORMAL, "\nInfo: Use this command to verify the existence of a card and its Mode."); @@ -331,20 +314,6 @@ static void strip_cmds(const char *Cmd) { } } -/** - * Converts integer value to equivalent hex value. - * Examples: 1 = 1, 11 = B - * @param number number of hex bytes. - * @return number as hex value. - */ -static uint8_t int_to_hex(uint16_t *number) { - uint32_t hex; - char dataLengthChar[5]; - sprintf(dataLengthChar, "%x", *number); - sscanf(dataLengthChar, "%x", &hex); - return (uint8_t)(hex & 0xff); -} - /** * Adds the last known IDm (8-Byte) to the data frame. * @param position start of where the IDm is added within the frame. @@ -353,10 +322,7 @@ static uint8_t int_to_hex(uint16_t *number) { */ static bool add_last_IDm(uint8_t position, uint8_t *data) { if (last_known_card.IDm[0] != 0 && last_known_card.IDm[1] != 0) { - for (int i = 0; i < 8; i++) { - uint16_t number = (uint16_t)last_known_card.IDm[i]; - data[position + i] = int_to_hex(&number); - } + memcpy(data + position, last_known_card.IDm, sizeof(last_known_card.IDm)); return true; } else { return false; @@ -390,6 +356,7 @@ int read_felica_uid(bool loop, bool verbose) { continue; } } else { + // when not in continuous mode if (status != 0) { if (verbose) PrintAndLogEx(WARNING, "FeliCa card select failed"); res = PM3_EOPABORTED; @@ -466,15 +433,15 @@ static int info_felica(bool verbose) { } case 0: { PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "-------- " _CYAN_("FeliCa tag info") " -------------------"); - PrintAndLogEx(SUCCESS, "IDm............ " _GREEN_("%s"), sprint_hex_inrow(card.IDm, sizeof(card.IDm))); - PrintAndLogEx(SUCCESS, "Code........... %s ", sprint_hex_inrow(card.code, sizeof(card.code))); - PrintAndLogEx(SUCCESS, "NFCID2......... %s", sprint_hex_inrow(card.uid, sizeof(card.uid))); - PrintAndLogEx(SUCCESS, "Parameter"); - PrintAndLogEx(SUCCESS, "PAD............ " _YELLOW_("%s"), sprint_hex_inrow(card.PMm, sizeof(card.PMm))); - PrintAndLogEx(SUCCESS, "IC code........ %s", sprint_hex_inrow(card.iccode, sizeof(card.iccode))); - PrintAndLogEx(SUCCESS, "MRT............ %s", sprint_hex_inrow(card.mrt, sizeof(card.mrt))); - PrintAndLogEx(SUCCESS, "Service code... " _YELLOW_("%s"), sprint_hex(card.servicecode, sizeof(card.servicecode))); + PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------"); + PrintAndLogEx(INFO, "IDm............ " _GREEN_("%s"), sprint_hex_inrow(card.IDm, sizeof(card.IDm))); + PrintAndLogEx(INFO, "Code........... %s ", sprint_hex_inrow(card.code, sizeof(card.code))); + PrintAndLogEx(INFO, "NFCID2......... %s", sprint_hex_inrow(card.uid, sizeof(card.uid))); + PrintAndLogEx(INFO, "Parameter"); + PrintAndLogEx(INFO, "PAD............ " _YELLOW_("%s"), sprint_hex_inrow(card.PMm, sizeof(card.PMm))); + PrintAndLogEx(INFO, "IC code........ %s", sprint_hex_inrow(card.iccode, sizeof(card.iccode))); + PrintAndLogEx(INFO, "MRT............ %s", sprint_hex_inrow(card.mrt, sizeof(card.mrt))); + PrintAndLogEx(INFO, "Service code... " _YELLOW_("%s"), sprint_hex(card.servicecode, sizeof(card.servicecode))); PrintAndLogEx(NORMAL, ""); set_last_known_card(card); break; @@ -554,9 +521,9 @@ static void print_rd_noEncrpytion_response(felica_read_without_encryption_respon PrintAndLogEx(INFO, "\t%s\t| %s ", bl_element_number, bl_data); } else { - PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(rd_noCry_resp->frame_response.IDm, sizeof(rd_noCry_resp->frame_response.IDm))); - PrintAndLogEx(SUCCESS, "Status Flag1: %s", sprint_hex(rd_noCry_resp->status_flags.status_flag1, sizeof(rd_noCry_resp->status_flags.status_flag1))); - PrintAndLogEx(SUCCESS, "Status Flag2: %s", sprint_hex(rd_noCry_resp->status_flags.status_flag1, sizeof(rd_noCry_resp->status_flags.status_flag1))); + PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex_inrow(rd_noCry_resp->frame_response.IDm, sizeof(rd_noCry_resp->frame_response.IDm))); + PrintAndLogEx(SUCCESS, " Status flag 1: %s", sprint_hex(rd_noCry_resp->status_flags.status_flag1, sizeof(rd_noCry_resp->status_flags.status_flag1))); + PrintAndLogEx(SUCCESS, " Status flag 2: %s", sprint_hex(rd_noCry_resp->status_flags.status_flag1, sizeof(rd_noCry_resp->status_flags.status_flag1))); } } @@ -571,14 +538,14 @@ int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool ve PrintAndLogEx(ERR, "\nGot no response from card"); return PM3_ERFTRANS; } - felica_request_service_response_t rqs_response; - memcpy(&rqs_response, (felica_request_service_response_t *)resp.data.asBytes, sizeof(felica_request_service_response_t)); + felica_request_service_response_t r; + memcpy(&r, (felica_request_service_response_t *)resp.data.asBytes, sizeof(felica_request_service_response_t)); - if (rqs_response.frame_response.IDm[0] != 0) { + if (r.frame_response.IDm[0] != 0) { PrintAndLogEx(SUCCESS, "\nGot Service Response:"); - PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(rqs_response.frame_response.IDm, sizeof(rqs_response.frame_response.IDm))); - PrintAndLogEx(SUCCESS, " -Node Number: %s", sprint_hex(rqs_response.node_number, sizeof(rqs_response.node_number))); - PrintAndLogEx(SUCCESS, " -Node Key Version List: %s\n", sprint_hex(rqs_response.node_key_versions, sizeof(rqs_response.node_key_versions))); + PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex_inrow(r.frame_response.IDm, sizeof(r.frame_response.IDm))); + PrintAndLogEx(SUCCESS, " Node number: %s", sprint_hex(r.node_number, sizeof(r.node_number))); + PrintAndLogEx(SUCCESS, " Node key version list: %s\n", sprint_hex(r.node_key_versions, sizeof(r.node_key_versions))); } return PM3_SUCCESS; } @@ -694,7 +661,7 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { } i++; } - data[0] = int_to_hex(&datalen); + data[0] = (datalen & 0xFF); data[1] = 0x10; // Command ID if (!custom_IDm && !check_last_idm(data, datalen)) { return PM3_EINVARG; @@ -842,7 +809,8 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { i++; } - data[0] = int_to_hex(&datalen); + data[0] = (datalen & 0xFF); + data[1] = 0x12; // Command ID if (!custom_IDm && !check_last_idm(data, datalen)) { return PM3_EINVARG; @@ -902,7 +870,7 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { PacketResponseNG resp; if (!waitCmdFelica(0, &resp, 1)) { - PrintAndLogEx(ERR, "\nGot no Response from card"); + PrintAndLogEx(ERR, "\nGot no response from card"); return PM3_ERFTRANS; } else { felica_auth2_response_t auth2_response; @@ -1381,40 +1349,48 @@ static int CmdHFFelicaRequestSystemCode(const char *Cmd) { * @return client result code. */ static int CmdHFFelicaRequestService(const char *Cmd) { - if (strlen(Cmd) < 2) return usage_hf_felica_request_service(); - int i = 0; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica rqservice", + "Use this command to verify the existence of Area and Service, and to acquire Key Version:\n" + " - When the specified Area or Service exists, the card returns Key Version.\n" + " - When the specified Area or Service does not exist, the card returns FFFFh as Key Version.\n" + "For Node Code List of a command packet, Area Code or Service Code of the target\n" + "of acquisition of Key Version shall be enumerated in Little Endian format.\n" + "If Key Version of System is the target of acquisition, FFFFh shall be specified\n" + "in the command packet.", + "hf felcia rqservice --node 01 --code FFFF\n" + "hf felcia rqservice -a --code FFFF\n" + "hf felica rqservice -i 011204126417E405 --node 01 --code FFFF" + ); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "all", "auto node number mode, iterates through all possible nodes 1 < n < 32"), + arg_str0("n", "node", "", "Number of Node"), + arg_str0("c", "code", "", "Node Code List (little endian)"), + arg_str0("i", "idm", "", "use custom IDm"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + bool all_nodes = arg_get_lit(ctx, 1); + +// int dlen = 0; +// int res = 0; + + CLIParserFree(ctx); + uint8_t data[PM3_CMD_DATA_SIZE]; bool custom_IDm = false; - bool all_nodes = false; uint16_t datalen = 13; // length (1) + CMD (1) + IDm(8) + Node Number (1) + Node Code List (2) - uint8_t flags = 0; - uint8_t paramCount = 0; - strip_cmds(Cmd); - while (Cmd[i] != '\0') { - if (Cmd[i] == '-') { - switch (tolower(Cmd[i + 1])) { - case 'h': - return usage_hf_felica_request_service(); - case 'i': - paramCount++; - custom_IDm = true; - if (!add_param(Cmd, paramCount, data, 2, 16)) { - return PM3_EINVARG; - } - paramCount++; - i += 16; - break; - case 'a': - paramCount++; - all_nodes = true; - break; - default: - return usage_hf_felica_request_service(); - } - i += 2; + +/* + case 'i': + + custom_IDm = true; + if (!add_param(Cmd, paramCount, data, 2, 16)) { + return PM3_EINVARG; } - i++; - } + if (!all_nodes) { // Node Number @@ -1441,8 +1417,9 @@ static int CmdHFFelicaRequestService(const char *Cmd) { PrintAndLogEx(ERR, "Incorrect parameter length!"); return PM3_EINVARG; } +*/ - flags |= FELICA_APPEND_CRC; + uint8_t flags = FELICA_APPEND_CRC; if (custom_IDm) { flags |= FELICA_NO_SELECT; } @@ -1452,25 +1429,21 @@ static int CmdHFFelicaRequestService(const char *Cmd) { } // Todo activate once datalen isn't hardcoded anymore... -// datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; if (!custom_IDm && !check_last_idm(data, datalen)) { return PM3_EINVARG; } - data[0] = int_to_hex(&datalen); + data[0] = (datalen & 0xFF); data[1] = 0x02; // Service Request Command ID if (all_nodes) { - for (uint16_t y = 1; y < 32; y++) { - data[10] = int_to_hex(&y); + for (uint8_t i = 1; i < 32; i++) { + data[10] = i; AddCrc(data, datalen); - datalen += 2; - send_request_service(flags, datalen, data, 1); - datalen -= 2; // Remove CRC bytes before adding new ones + send_request_service(flags, datalen + 2, data, 1); } } else { AddCrc(data, datalen); - datalen += 2; - send_request_service(flags, datalen, data, 1); + send_request_service(flags, datalen + 2, data, 1); } return PM3_SUCCESS; diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index c56af20fe..f4f9aa89a 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -3571,7 +3571,6 @@ int info_iclass(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--------------------- " _CYAN_("Tag Information") " ----------------------"); - PrintAndLogEx(INFO, "------------------------------------------------------------"); if (readStatus & FLAG_ICLASS_CSN) { PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " uid", sprint_hex(hdr->csn, sizeof(hdr->csn))); diff --git a/client/src/cmdhflto.c b/client/src/cmdhflto.c index 7c8545629..828a69993 100644 --- a/client/src/cmdhflto.c +++ b/client/src/cmdhflto.c @@ -159,9 +159,10 @@ int infoLTO(bool verbose) { if (ret_val == PM3_SUCCESS) { PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "UID......... " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number))); - PrintAndLogEx(SUCCESS, "Type info... " _YELLOW_("%s"), sprint_hex_inrow(type_info, sizeof(type_info))); - PrintAndLogEx(SUCCESS, "Memory...... " _YELLOW_("%s"), lto_print_size(type_info[1])); + PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------"); + PrintAndLogEx(INFO, "UID......... " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number))); + PrintAndLogEx(INFO, "Type info... " _YELLOW_("%s"), sprint_hex_inrow(type_info, sizeof(type_info))); + PrintAndLogEx(INFO, "Memory...... " _YELLOW_("%s"), lto_print_size(type_info[1])); if (type_info[1] > 3) { PrintAndLogEx(INFO, "Unknown LTO tag, report to @iceman!"); } diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index 9fda23296..bba8bf664 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -99,7 +99,6 @@ static void print_info_result(uint8_t *data, bool verbose) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------"); - PrintAndLogEx(INFO, "-------------------------------------------------------------"); // data section PrintAndLogEx(NORMAL, ""); diff --git a/client/src/cmdsmartcard.c b/client/src/cmdsmartcard.c index 247090dd0..94ca44875 100644 --- a/client/src/cmdsmartcard.c +++ b/client/src/cmdsmartcard.c @@ -639,7 +639,6 @@ static int CmdSmartInfo(const char *Cmd) { // print header PrintAndLogEx(INFO, "--- " _CYAN_("Smartcard Information") " ---------"); - PrintAndLogEx(INFO, "-------------------------------------------------------------"); PrintAndLogEx(INFO, "ISO7618-3 ATR : %s", sprint_hex(card.atr, card.atr_len)); PrintAndLogEx(INFO, "http://smartcard-atr.apdu.fr/parse?ATR=%s", sprint_hex_inrow(card.atr, card.atr_len)); diff --git a/client/src/util.c b/client/src/util.c index bcebabfa0..d55dee4bf 100644 --- a/client/src/util.c +++ b/client/src/util.c @@ -752,7 +752,6 @@ int param_getbin_to_eol(const char *line, int paramnum, uint8_t *data, int maxda return 0; } - int param_getstr(const char *line, int paramnum, char *str, size_t buffersize) { int bg, en; From 0582f47e2d304a1a227265ea68ca1b4ddefb22c6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 29 Mar 2021 10:46:10 +0200 Subject: [PATCH 119/373] text --- client/src/cmdhfst.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfst.c b/client/src/cmdhfst.c index 5fc151cc0..f53ace548 100644 --- a/client/src/cmdhfst.c +++ b/client/src/cmdhfst.c @@ -267,9 +267,9 @@ int infoHF_ST(void) { DropField(); return PM3_ESOFT; } - - print_st_cc_info(response, resplen - 2); - + // store st cc data for later + uint8_t st_cc_data[resplen - 2]; + memcpy(st_cc_data, response, sizeof(st_cc_data)); // --------------- System file reading ---------------- uint8_t aSELECT_FILE_SYS[30]; @@ -305,8 +305,14 @@ int infoHF_ST(void) { DropField(); return PM3_ESOFT; } + + + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------"); + PrintAndLogEx(NORMAL, ""); + print_st_cc_info(st_cc_data, sizeof(st_cc_data)); print_st_system_info(response, resplen - 2); -// PrintAndLogEx(NORMAL, "<<<< %s", sprint_hex(response, resplen)); return PM3_SUCCESS; } From 1a16160534e1acb34b7b283b3daf814884449108 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 29 Mar 2021 10:48:46 +0200 Subject: [PATCH 120/373] text --- client/src/cmdhfthinfilm.c | 2 ++ client/src/cmdhftopaz.c | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfthinfilm.c b/client/src/cmdhfthinfilm.c index 48844b759..976e1314d 100644 --- a/client/src/cmdhfthinfilm.c +++ b/client/src/cmdhfthinfilm.c @@ -124,6 +124,8 @@ int infoThinFilm(bool verbose) { if (resp.status == PM3_SUCCESS) { if (resp.length == 16 || resp.length == 32) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------"); print_barcode(resp.data.asBytes, resp.length, verbose); } else { if (verbose) diff --git a/client/src/cmdhftopaz.c b/client/src/cmdhftopaz.c index 9f174ca9d..a6564ae17 100644 --- a/client/src/cmdhftopaz.c +++ b/client/src/cmdhftopaz.c @@ -614,7 +614,6 @@ int readTopazUid(bool verbose) { // printing PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------"); - PrintAndLogEx(INFO, "-------------------------------------------------------------"); PrintAndLogEx(SUCCESS, " UID: %02x %02x %02x %02x %02x %02x %02x", topaz_tag.uid[6], topaz_tag.uid[5], From 48b9ec1e7be0a7937c7120b02aa71981c8d53438 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 29 Mar 2021 10:49:19 +0200 Subject: [PATCH 121/373] layout of main help --- client/src/cmdmain.c | 49 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/client/src/cmdmain.c b/client/src/cmdmain.c index a9ecfd907..e85935dfb 100644 --- a/client/src/cmdmain.c +++ b/client/src/cmdmain.c @@ -295,31 +295,30 @@ static int CmdClear(const char *Cmd) { static command_t CommandTable[] = { - {"--------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("Technology") " -----------------------"}, - - {"analyse", CmdAnalyse, AlwaysAvailable, "{ Analyse utils... }"}, - {"data", CmdData, AlwaysAvailable, "{ Plot window / data buffer manipulation... }"}, - {"emv", CmdEMV, AlwaysAvailable, "{ EMV ISO-14443 / ISO-7816... }"}, - {"hf", CmdHF, AlwaysAvailable, "{ High frequency commands... }"}, - {"hw", CmdHW, AlwaysAvailable, "{ Hardware commands... }"}, - {"lf", CmdLF, AlwaysAvailable, "{ Low frequency commands... }"}, - {"mem", CmdFlashMem, IfPm3Flash, "{ Flash memory manipulation... }"}, - {"reveng", CmdRev, AlwaysAvailable, "{ CRC calculations from RevEng software... }"}, - {"smart", CmdSmartcard, AlwaysAvailable, "{ Smart card ISO-7816 commands... }"}, - {"script", CmdScript, AlwaysAvailable, "{ Scripting commands... }"}, - {"trace", CmdTrace, AlwaysAvailable, "{ Trace manipulation... }"}, - {"usart", CmdUsart, IfPm3FpcUsartFromUsb, "{ USART commands... }"}, - {"wiegand", CmdWiegand, AlwaysAvailable, "{ Wiegand format manipulation... }"}, - {"--------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("General") " -----------------------"}, - {"auto", CmdAuto, IfPm3Present, "Automated detection process for unknown tags"}, - {"clear", CmdClear, AlwaysAvailable, "Clear screen"}, - {"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... }"}, - {"rem", CmdRem, AlwaysAvailable, "Add a text line in log file"}, - {"quit", CmdQuit, AlwaysAvailable, ""}, - {"exit", CmdQuit, AlwaysAvailable, "Exit program"}, + {"help", CmdHelp, AlwaysAvailable, "Use `" _YELLOW_(" help") "` for details of a command"}, + {"preferences", CmdPref, AlwaysAvailable, "{ Edit client/device preferences... }"}, + {"--------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("Technology") " -----------------------"}, + {"analyse", CmdAnalyse, AlwaysAvailable, "{ Analyse utils... }"}, + {"data", CmdData, AlwaysAvailable, "{ Plot window / data buffer manipulation... }"}, + {"emv", CmdEMV, AlwaysAvailable, "{ EMV ISO-14443 / ISO-7816... }"}, + {"hf", CmdHF, AlwaysAvailable, "{ High frequency commands... }"}, + {"hw", CmdHW, AlwaysAvailable, "{ Hardware commands... }"}, + {"lf", CmdLF, AlwaysAvailable, "{ Low frequency commands... }"}, + {"mem", CmdFlashMem, IfPm3Flash, "{ Flash memory manipulation... }"}, + {"reveng", CmdRev, AlwaysAvailable, "{ CRC calculations from RevEng software... }"}, + {"smart", CmdSmartcard, AlwaysAvailable, "{ Smart card ISO-7816 commands... }"}, + {"script", CmdScript, AlwaysAvailable, "{ Scripting commands... }"}, + {"trace", CmdTrace, AlwaysAvailable, "{ Trace manipulation... }"}, + {"usart", CmdUsart, IfPm3FpcUsartFromUsb, "{ USART commands... }"}, + {"wiegand", CmdWiegand, AlwaysAvailable, "{ Wiegand format manipulation... }"}, + {"--------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("General") " -----------------------"}, + {"auto", CmdAuto, IfPm3Present, "Automated detection process for unknown tags"}, + {"clear", CmdClear, AlwaysAvailable, "Clear screen"}, + {"hints", CmdHints, AlwaysAvailable, "Turn hints on / off"}, + {"msleep", CmdMsleep, AlwaysAvailable, "Add a pause in milliseconds"}, + {"rem", CmdRem, AlwaysAvailable, "Add a text line in log file"}, + {"quit", CmdQuit, AlwaysAvailable, ""}, + {"exit", CmdQuit, AlwaysAvailable, "Exit program"}, {NULL, NULL, NULL, NULL} }; From 8278c733fe0aac837b895feb9aa8d4e73d448209 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 29 Mar 2021 17:38:20 +0200 Subject: [PATCH 122/373] wiegand decode - added binary param to decode --- client/src/cmdwiegand.c | 33 ++++++++++++++++++++++++++------- client/src/util.c | 21 +++++++++++++++++++++ client/src/util.h | 1 + 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/client/src/cmdwiegand.c b/client/src/cmdwiegand.c index 3cdeb66b3..690626f93 100644 --- a/client/src/cmdwiegand.c +++ b/client/src/cmdwiegand.c @@ -114,28 +114,47 @@ int CmdWiegandDecode(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_lit0("p", "parity", "ignore invalid parity"), - arg_strx1("r", "raw", "", "raw hex to be decoded"), + arg_strx0("r", "raw", "", "raw hex to be decoded"), + arg_str0("b", "bin", "", "binary string to be decoded"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); bool ignore_parity = arg_get_lit(ctx, 1); - int len = 0; + int hlen = 0; char hex[40] = {0}; - CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)hex, sizeof(hex), &len); + CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)hex, sizeof(hex), &hlen); + + int blen = 0; + uint8_t binarr[100] = {0x00}; + int res = CLIParamBinToBuf(arg_get_str(ctx, 3), binarr, sizeof(binarr), &blen); CLIParserFree(ctx); - if (len == 0) { - PrintAndLogEx(ERR, "empty input"); + if (res) { + PrintAndLogEx(FAILED, "Error parsing binary string"); return PM3_EINVARG; } uint32_t top = 0, mid = 0, bot = 0; - hexstring_to_u96(&top, &mid, &bot, hex); + if (hlen) { + res = hexstring_to_u96(&top, &mid, &bot, hex); + if (res != hlen) { + PrintAndLogEx(ERR, "hex string contains none hex chars"); + return PM3_EINVARG; + } + } else if (blen) { + uint16_t n = binarray_to_u96(&top, &mid, &bot, binarr, blen); + if (n != blen) { + PrintAndLogEx(ERR, "Binary string contains none <0|1> chars"); + return PM3_EINVARG; + } + } else { + PrintAndLogEx(ERR, "empty input"); + return PM3_EINVARG; + } wiegand_message_t packed = initialize_message_object(top, mid, bot); HIDTryUnpack(&packed, ignore_parity); - return PM3_SUCCESS; } diff --git a/client/src/util.c b/client/src/util.c index d55dee4bf..4697ffe23 100644 --- a/client/src/util.c +++ b/client/src/util.c @@ -1041,6 +1041,27 @@ int binstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str) return i; } + +/** + * Converts a binary array to component "hi2", "hi" and "lo" 32-bit integers, + * one bit at a time. + * + * Returns the number of bits entered. + */ +int binarray_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, uint8_t *arr, int arrlen) { + int i = 0; + for(; i < arrlen; i++) { + uint8_t n = arr[i]; + if (n > 1) + break; + + *hi2 = (*hi2 << 1) | (*hi >> 31); + *hi = (*hi << 1) | (*lo >> 31); + *lo = (*lo << 1) | (n & 0x1); + } + return i; +} + inline uint32_t bitcount32(uint32_t a) { #if defined __GNUC__ return __builtin_popcountl(a); diff --git a/client/src/util.h b/client/src/util.h index 6a2933d5a..2730ed44f 100644 --- a/client/src/util.h +++ b/client/src/util.h @@ -107,6 +107,7 @@ char *str_dup(const char *src); char *str_ndup(const char *src, size_t len); int hexstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str); int binstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str); +int binarray_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, uint8_t *arr, int arrlen); uint32_t bitcount32(uint32_t a); uint64_t bitcount64(uint64_t a); From b7be78a8fb46c55e4a28626634e2755d5f81f7f3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 29 Mar 2021 21:52:36 +0200 Subject: [PATCH 123/373] cbc is already done in mifare_cypher_single_block (anon) --- client/src/mifare/desfire_crypto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index f08aeb7b8..1f36bacac 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -862,7 +862,7 @@ void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, mbedtls_aes_context actx; mbedtls_aes_init(&actx); mbedtls_aes_setkey_enc(&actx, key->data, 128); - mbedtls_aes_crypt_cbc(&actx, MBEDTLS_AES_ENCRYPT, sizeof(edata), ivect, data, edata); + mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_ENCRYPT, data, edata); mbedtls_aes_free(&actx); break; } @@ -870,7 +870,7 @@ void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, mbedtls_aes_context actx; mbedtls_aes_init(&actx); mbedtls_aes_setkey_dec(&actx, key->data, 128); - mbedtls_aes_crypt_cbc(&actx, MBEDTLS_AES_DECRYPT, sizeof(edata), ivect, edata, data); + mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_DECRYPT, edata, data); mbedtls_aes_free(&actx); break; } From 62031e640cadbccc2567eeb9770bc297f78f4fff Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 30 Mar 2021 09:34:17 +0200 Subject: [PATCH 124/373] swap arrays --- client/src/mifare/desfire_crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 1f36bacac..83e27e7b6 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -870,7 +870,7 @@ void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, mbedtls_aes_context actx; mbedtls_aes_init(&actx); mbedtls_aes_setkey_dec(&actx, key->data, 128); - mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_DECRYPT, edata, data); + mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_DECRYPT, data, edata); mbedtls_aes_free(&actx); break; } From 2f0b944554654268136b0300af4f23864075d743 Mon Sep 17 00:00:00 2001 From: Ryan Saridar <8403417+VortixDev@users.noreply.github.com> Date: Wed, 31 Mar 2021 02:42:03 +0100 Subject: [PATCH 125/373] Fix error byte index --- client/src/mifare/mifare4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/mifare/mifare4.c b/client/src/mifare/mifare4.c index 55961b15b..b83996098 100644 --- a/client/src/mifare/mifare4.c +++ b/client/src/mifare/mifare4.c @@ -194,7 +194,7 @@ int MifareAuth4(mf4Session_t *mf4session, uint8_t *keyn, uint8_t *key, bool acti } if (data[0] != 0x90) { - if (!silentMode) PrintAndLogEx(ERR, "Card response error: %02x", data[2]); + if (!silentMode) PrintAndLogEx(ERR, "Card response error: %02x", data[0]); if (dropFieldIfError) DropField(); return 3; } From b2f535f7889bf60620f7468c811dd626c46a1691 Mon Sep 17 00:00:00 2001 From: Ryan Saridar <8403417+VortixDev@users.noreply.github.com> Date: Wed, 31 Mar 2021 02:45:37 +0100 Subject: [PATCH 126/373] Make error verbose --- client/src/mifare/mifare4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/mifare/mifare4.c b/client/src/mifare/mifare4.c index b83996098..18b532349 100644 --- a/client/src/mifare/mifare4.c +++ b/client/src/mifare/mifare4.c @@ -194,7 +194,7 @@ int MifareAuth4(mf4Session_t *mf4session, uint8_t *keyn, uint8_t *key, bool acti } if (data[0] != 0x90) { - if (!silentMode) PrintAndLogEx(ERR, "Card response error: %02x", data[0]); + if (!silentMode) PrintAndLogEx(ERR, "Card response error: %02x %s", data[0], mfpGetErrorDescription(data[0])); if (dropFieldIfError) DropField(); return 3; } From e35ebf6b6938802d630c3d45a82c1af328ed33cf Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 31 Mar 2021 15:52:57 +0200 Subject: [PATCH 127/373] mem info , now supports loading PEM with private key --- client/src/cmdflashmem.c | 218 +++++++++++++++++++++++++-------------- client/src/fileutils.c | 2 +- 2 files changed, 140 insertions(+), 80 deletions(-) diff --git a/client/src/cmdflashmem.c b/client/src/cmdflashmem.c index 34f60bd51..c0a12cc39 100644 --- a/client/src/cmdflashmem.c +++ b/client/src/cmdflashmem.c @@ -17,6 +17,7 @@ #include "cmdflashmemspiffs.h" // spiffs commands #include "rsa.h" #include "sha1.h" +#include "pk.h" // PEM key load functions #define MCK 48000000 #define FLASH_MINFAST 24000000 //33000000 @@ -128,6 +129,7 @@ int rdv4_validate(rdv40_validation_t *mem) { return PM3_EFAILED; } + static int rdv4_sign_write(uint8_t *signature, uint8_t slen){ // save to mem clearCommandBuffer(); @@ -401,9 +403,9 @@ static int CmdFlashMemWipe(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "mem wipe", "Wipe flash memory on device, which fills it with 0xFF\n" - _WHITE_("[ ") _RED_("!!! OBS") " ] use with caution", - "mem wipe -p 0 -> wipes first page" -// "mem wipe -i -> inital total wipe" + _WHITE_("[ ") _RED_("!!! OBS") _WHITE_(" ] use with caution"), + "mem wipe -p 0 -> wipes first page" +// "mem wipe -i -> inital total wipe" ); void *argtable[] = { @@ -450,33 +452,84 @@ static int CmdFlashMemInfo(const char *Cmd) { CLIParserInit(&ctx, "mem info", "Collect signature and verify it from flash memory", "mem info" -// "mem info -s -d 0102030405060708" ); void *argtable[] = { arg_param_begin, arg_lit0("s", "sign", "create a signature"), arg_str0("d", NULL, "", "flash memory id, 8 hex bytes"), + arg_str0("p", "pem", "", "key in PEM format"), + arg_lit0("v", "verbose", "verbose output"), // 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); + bool 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); + int pemlen = 0; + char pem_fn[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)pem_fn, FILE_PATH_SIZE, &pemlen); + + bool verbose = arg_get_lit(ctx, 4); + bool shall_write = false; +// shall_write = arg_get_lit(ctx, 5); CLIParserFree(ctx); - if (dlen > 0 && dlen < sizeof(id) ) { + if (res || (dlen > 0 && dlen < sizeof(id)) ) { PrintAndLogEx(FAILED, "Error parsing flash memory id, expect 8, got %d", dlen); return PM3_EINVARG; } + + // set up PK key context now. + mbedtls_pk_context pkctx; + mbedtls_pk_init( &pkctx ); + bool got_private = false; + // PEM + if (pemlen) { + // PEM file + char *path = NULL; + if (searchFile(&path, RESOURCES_SUBDIR, pem_fn, ".pem", true) != PM3_SUCCESS) { + if (searchFile(&path, RESOURCES_SUBDIR, pem_fn, "", false) != PM3_SUCCESS) { + return PM3_EFILE; + } + } + + PrintAndLogEx(INFO, "loading file `" _YELLOW_("%s") "`" NOLF, path); + + // load private + res = mbedtls_pk_parse_keyfile(&pkctx, path, NULL); + //res = mbedtls_pk_parse_public_keyfile(&pkctx, path); + if (res == 0) { + PrintAndLogEx(NORMAL, " ( " _GREEN_("ok") " )"); + } else { + PrintAndLogEx(NORMAL, " ( " _RED_("fail") " )"); + mbedtls_pk_free(&pkctx); + free(path); + return PM3_EFILE; + } + + mbedtls_rsa_context *rsa = (mbedtls_rsa_context*)pkctx.pk_ctx; + if (rsa == NULL) { + PrintAndLogEx(FAILED, "failed to allocate rsa context memory"); + return PM3_EMALLOC; + } + free(path); + got_private = true; + } else { + + // it not loaded, we need to setup the context manually + if (mbedtls_pk_setup( &pkctx, mbedtls_pk_info_from_type( (mbedtls_pk_type_t) MBEDTLS_PK_RSA ) ) != 0 ) { + PrintAndLogEx(FAILED, "failed, mbedtls_pk_setup returned "); + return PM3_ESOFT; + } + } + // validate devicesignature data rdv40_validation_t mem; res = rdv4_get_signature(&mem); @@ -494,66 +547,69 @@ 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(NORMAL, ""); + PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA signature") " ---------------"); + for (int i = 0; i < (sizeof(mem.signature) / 32); i++) { + PrintAndLogEx(INFO, " %s", sprint_hex_inrow(mem.signature + (i * 32), 32)); + } 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++) { - PrintAndLogEx(INFO, " %s", sprint_hex_inrow(mem.signature + (i * 32), 32)); + + mbedtls_rsa_context *rsa = NULL; + + if (got_private) { + rsa = mbedtls_pk_rsa( pkctx ); + rsa->padding = MBEDTLS_RSA_PKCS_V15; + rsa->hash_id = 0; + rsa->len = RRG_RSA_KEY_LEN; + } else { + + rsa = (mbedtls_rsa_context *)calloc(1, sizeof(mbedtls_rsa_context)); + mbedtls_rsa_init(rsa, MBEDTLS_RSA_PKCS_V15, 0); + rsa->len = RRG_RSA_KEY_LEN; + + // add public key + mbedtls_mpi_read_string(&rsa->N, 16, RRG_RSA_N); + mbedtls_mpi_read_string(&rsa->E, 16, RRG_RSA_E); } - mbedtls_rsa_context rsa; - mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0); - - rsa.len = RRG_RSA_KEY_LEN; - - // add public key - mbedtls_mpi_read_string(&rsa.N, 16, RRG_RSA_N); - mbedtls_mpi_read_string(&rsa.E, 16, RRG_RSA_E); - - // add private key - mbedtls_mpi_read_string(&rsa.D, 16, RSA_D); - mbedtls_mpi_read_string(&rsa.P, 16, RSA_P); - mbedtls_mpi_read_string(&rsa.Q, 16, RSA_Q); - mbedtls_mpi_read_string(&rsa.DP, 16, RSA_DP); - mbedtls_mpi_read_string(&rsa.DQ, 16, RSA_DQ); - mbedtls_mpi_read_string(&rsa.QP, 16, RSA_QP); - - PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("RDV4 RSA Public key") " --------------"); + if (verbose) { + char str_exp[10]; + char str_pk[261]; + size_t exlen = 0, pklen = 0; + mbedtls_mpi_write_string(&rsa->E, 16, str_exp, sizeof(str_exp), &exlen); + mbedtls_mpi_write_string(&rsa->N, 16, str_pk, sizeof(str_pk), &pklen); - char str_exp[10]; - char str_pk[261]; - size_t exlen = 0, pklen = 0; - mbedtls_mpi_write_string(&rsa.E, 16, str_exp, sizeof(str_exp), &exlen); - mbedtls_mpi_write_string(&rsa.N, 16, str_pk, sizeof(str_pk), &pklen); + PrintAndLogEx(INFO, "Len.................. %"PRIu64, rsa->len); + PrintAndLogEx(INFO, "Exponent............. %s", str_exp); + PrintAndLogEx(INFO, "Public key modulus N"); + PrintAndLogEx(INFO, " %.64s", str_pk); + PrintAndLogEx(INFO, " %.64s", str_pk + 64); + PrintAndLogEx(INFO, " %.64s", str_pk + 128); + PrintAndLogEx(INFO, " %.64s", str_pk + 192); + PrintAndLogEx(NORMAL, ""); + } - PrintAndLogEx(INFO, "Len.................. %"PRIu64, rsa.len); - PrintAndLogEx(INFO, "Exponent............. %s", str_exp); - PrintAndLogEx(INFO, "Public key modulus N"); - PrintAndLogEx(INFO, " %.64s", str_pk); - PrintAndLogEx(INFO, " %.64s", str_pk + 64); - PrintAndLogEx(INFO, " %.64s", str_pk + 128); - PrintAndLogEx(INFO, " %.64s", str_pk + 192); - PrintAndLogEx(NORMAL, ""); - - bool is_keyok = (mbedtls_rsa_check_pubkey(&rsa) == 0); + bool is_keyok = (mbedtls_rsa_check_pubkey(rsa) == 0); PrintAndLogEx( (is_keyok) ? SUCCESS : FAILED, - "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 )", + "RRG/Iceman RSA public key check.... ( %s )", (is_keyok) ? _GREEN_("ok") : _RED_("fail") ); + is_keyok = (mbedtls_rsa_check_privkey(rsa) == 0); + if (verbose) { + PrintAndLogEx( + (is_keyok) ? SUCCESS : FAILED, + "RRG/Iceman RSA private key check... ( %s )", + (is_keyok) ? _GREEN_("ok") : _YELLOW_("N/A") + ); + } // to be verified uint8_t from_device[RRG_RSA_KEY_LEN]; @@ -565,43 +621,47 @@ 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))); + if (is_keyok) { - int is_signed = mbedtls_rsa_pkcs1_sign(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign); - PrintAndLogEx( - (is_signed == 0) ? SUCCESS : FAILED, - "RSA signing.......... ( %s )", - (is_signed == 0) ? _GREEN_("ok") : _RED_("fail") - ); - - if (shall_write) { - rdv4_sign_write(sign, RRG_RSA_KEY_LEN); - } - PrintAndLogEx(INFO, "Signed"); - for (int i = 0; i < (sizeof(sign) / 32); i++) { - PrintAndLogEx(INFO, " %s", sprint_hex_inrow(sign + (i * 32), 32)); + 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( + (is_signed == 0) ? SUCCESS : FAILED, + "RSA signing... ( %s )", + (is_signed == 0) ? _GREEN_("ok") : _RED_("fail") + ); + + if (shall_write) { + rdv4_sign_write(sign, RRG_RSA_KEY_LEN); + } + PrintAndLogEx(INFO, "New signature"); + for (int i = 0; i < (sizeof(sign) / 32); i++) { + PrintAndLogEx(INFO, " %s", sprint_hex_inrow(sign + (i * 32), 32)); + } + } else { + PrintAndLogEx(FAILED, "no private key available to sign"); } } // Verify (public key) - 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); + bool is_verified = (mbedtls_rsa_pkcs1_verify(rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device) == 0); + mbedtls_pk_free(&pkctx); + + PrintAndLogEx(NORMAL, ""); PrintAndLogEx( (is_verified) ? SUCCESS : FAILED, - "RSA verification..... ( %s )", - (is_verified) ? _GREEN_("ok") : _RED_("fail") + "Genuine Proxmark3 RDV4 signature detected... %s", + (is_verified) ? ":heavy_check_mark:" : ":x:" ); - if (is_verified) { - PrintAndLogEx(SUCCESS, "Genuine Proxmark3 RDV4 signature detected"); - } - PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } diff --git a/client/src/fileutils.c b/client/src/fileutils.c index dc7ac530a..6cc29d867 100644 --- a/client/src/fileutils.c +++ b/client/src/fileutils.c @@ -1805,7 +1805,7 @@ int searchFile(char **foundpath, const char *pm3dir, const char *searchname, con int res = searchFinalFile(foundpath, pm3dir, filename, silent); if (res != PM3_SUCCESS) { if ((res == PM3_EFILE) && (!silent)) - PrintAndLogEx(FAILED, "Error - can't find %s", filename); + PrintAndLogEx(FAILED, "Error - can't find `" _YELLOW_("%s") "`", filename); free(filename); return res; } From 27bae4567c71f51312327c9e5bfaf89d1924c924 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 31 Mar 2021 16:56:03 +0200 Subject: [PATCH 128/373] remove warning on ubuntu --- tools/hitag2crack/common/ht2crackutils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/hitag2crack/common/ht2crackutils.h b/tools/hitag2crack/common/ht2crackutils.h index 16f4fab5b..30ecfacac 100644 --- a/tools/hitag2crack/common/ht2crackutils.h +++ b/tools/hitag2crack/common/ht2crackutils.h @@ -16,7 +16,7 @@ #define HEX_PER_ROW 16 -void writebuf(unsigned char *buf, uint64_t val, unsigned int len); +void writebuf(unsigned char *buf, uint64_t val, uint16_t len); void shexdump(unsigned char *data, int data_len); void printbin(unsigned char *c); void printbin2(uint64_t val, unsigned int size); From b328d61c1983ce9150bc7eff58c6c908210a90f1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 31 Mar 2021 17:03:20 +0200 Subject: [PATCH 129/373] coverity fix --- client/src/cmdhfcryptorf.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfcryptorf.c b/client/src/cmdhfcryptorf.c index 086fa4a11..43dbcf6de 100644 --- a/client/src/cmdhfcryptorf.c +++ b/client/src/cmdhfcryptorf.c @@ -403,14 +403,13 @@ static int CmdHFCryptoRFELoad(const char *Cmd) { 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, FILE_PATH_SIZE, &fnlen); + CLIParserFree(ctx); - if (strlen(filename) == 0) { + if (fnlen == 0) { PrintAndLogEx(ERR, "Error: Please specify a filename"); - CLIParserFree(ctx); return PM3_EINVARG; } From 5d49661da33e9e866f937a95fe12a103736cf32c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 31 Mar 2021 23:39:49 +0200 Subject: [PATCH 130/373] hf mf restore - now can use "w" to use keyfile to authenticate --- client/src/cmdhfmf.c | 58 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 757d40288..804888674 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -158,12 +158,13 @@ static int usage_hf14_keybrute(void) { } */ static int usage_hf14_restore(void) { - PrintAndLogEx(NORMAL, "Usage: hf mf restore [card memory] u k f "); + PrintAndLogEx(NORMAL, "Usage: hf mf restore [card memory] u k f [w]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (MIFARE Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); PrintAndLogEx(NORMAL, " u : uid, try to restore from hf-mf--key.bin and hf-mf--dump.bin"); PrintAndLogEx(NORMAL, " k : key filename, specific the full filename of key file"); PrintAndLogEx(NORMAL, " f : data filename, specific the full filename of data file"); + PrintAndLogEx(NORMAL, " w : use specified keyfile to authenticate with"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, _YELLOW_(" hf mf restore") " -- read the UID from tag first, then restore from hf-mf--key.bin and and hf-mf--dump.bin"); @@ -1131,6 +1132,7 @@ static int CmdHF14AMfRestore(const char *Cmd) { char *fptr; FILE *fdump, *fkeys; + bool use_keyfile_for_auth = false; while (param_getchar(Cmd, cmdp) != 0x00) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': @@ -1151,6 +1153,10 @@ static int CmdHF14AMfRestore(const char *Cmd) { param_getstr(Cmd, cmdp + 1, dataFilename, FILE_PATH_SIZE); cmdp += 2; break; + case 'w': + use_keyfile_for_auth = true; + cmdp++; + break; default: if (cmdp == 0) { numSectors = NumOfSectors(param_getchar(Cmd, cmdp)); @@ -1216,7 +1222,6 @@ static int CmdHF14AMfRestore(const char *Cmd) { for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { for (blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) { uint8_t data[26]; - memcpy(data, key, 6); bytes_read = fread(bldata, 1, 16, fdump); if (bytes_read != 16) { PrintAndLogEx(ERR, "File reading error " _YELLOW_("%s"), dataFilename); @@ -1240,18 +1245,49 @@ static int CmdHF14AMfRestore(const char *Cmd) { bldata[15] = (keyB[sectorNo][5]); } - PrintAndLogEx(NORMAL, "Writing to block %3d: %s", FirstBlockOfSector(sectorNo) + blockNo, sprint_hex(bldata, 16)); - memcpy(data + 10, bldata, 16); - clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFARE_WRITEBL, FirstBlockOfSector(sectorNo) + blockNo, keyType, 0, data, sizeof(data)); - PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - uint8_t isOK = resp.oldarg[0] & 0xff; - PrintAndLogEx(SUCCESS, "isOk:%02x", isOK); + + if (use_keyfile_for_auth) { + for (uint8_t kt=0; kt < 2; kt++) { + + if (kt == 0) + memcpy(data, keyA[sectorNo], 6); + else + memcpy(data, keyB[sectorNo], 6); + + PrintAndLogEx(NORMAL, "Writing to block %3d: %s", FirstBlockOfSector(sectorNo) + blockNo, sprint_hex(bldata, 16)); + clearCommandBuffer(); + SendCommandMIX(CMD_HF_MIFARE_WRITEBL, FirstBlockOfSector(sectorNo) + blockNo, keyType, 0, data, sizeof(data)); + PacketResponseNG resp; + + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + uint8_t isOK = resp.oldarg[0] & 0xff; + if (isOK == 0) { + PrintAndLogEx(FAILED, "isOk: %02x", isOK); + } else { + break; + } + } else { + PrintAndLogEx(WARNING, "Command execute timeout"); + } + } + } else { - PrintAndLogEx(WARNING, "Command execute timeout"); + memcpy(data, key, 6); + PrintAndLogEx(NORMAL, "Writing to block %3d: %s", FirstBlockOfSector(sectorNo) + blockNo, sprint_hex(bldata, 16)); + clearCommandBuffer(); + SendCommandMIX(CMD_HF_MIFARE_WRITEBL, FirstBlockOfSector(sectorNo) + blockNo, keyType, 0, data, sizeof(data)); + + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + uint8_t isOK = resp.oldarg[0] & 0xff; + if (isOK == 0) { + PrintAndLogEx(FAILED, "isOk: %02x", isOK); + } + } else { + PrintAndLogEx(WARNING, "Command execute timeout"); + } } } } From d2421a2dd421516aaf286415b7d76298f2ec8122 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 1 Apr 2021 00:00:28 +0200 Subject: [PATCH 131/373] hf mf restore - forgot to swap keytype --- client/src/cmdhfmf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 804888674..a61c4e874 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -1258,7 +1258,7 @@ static int CmdHF14AMfRestore(const char *Cmd) { PrintAndLogEx(NORMAL, "Writing to block %3d: %s", FirstBlockOfSector(sectorNo) + blockNo, sprint_hex(bldata, 16)); clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFARE_WRITEBL, FirstBlockOfSector(sectorNo) + blockNo, keyType, 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_MIFARE_WRITEBL, FirstBlockOfSector(sectorNo) + blockNo, kt, 0, data, sizeof(data)); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { From 924a8163d0b4162440f8a0c979c9f8fcd858ee5c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 1 Apr 2021 00:08:22 +0200 Subject: [PATCH 132/373] hf mf restore - when using keyfile as auth, use dump data for sectortrailer --- client/src/cmdhfmf.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index a61c4e874..45ec8fc56 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -1230,19 +1230,21 @@ static int CmdHF14AMfRestore(const char *Cmd) { return 2; } - if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer - bldata[0] = (keyA[sectorNo][0]); - bldata[1] = (keyA[sectorNo][1]); - bldata[2] = (keyA[sectorNo][2]); - bldata[3] = (keyA[sectorNo][3]); - bldata[4] = (keyA[sectorNo][4]); - bldata[5] = (keyA[sectorNo][5]); - bldata[10] = (keyB[sectorNo][0]); - bldata[11] = (keyB[sectorNo][1]); - bldata[12] = (keyB[sectorNo][2]); - bldata[13] = (keyB[sectorNo][3]); - bldata[14] = (keyB[sectorNo][4]); - bldata[15] = (keyB[sectorNo][5]); + if (use_keyfile_for_auth == false) { + if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer + bldata[0] = (keyA[sectorNo][0]); + bldata[1] = (keyA[sectorNo][1]); + bldata[2] = (keyA[sectorNo][2]); + bldata[3] = (keyA[sectorNo][3]); + bldata[4] = (keyA[sectorNo][4]); + bldata[5] = (keyA[sectorNo][5]); + bldata[10] = (keyB[sectorNo][0]); + bldata[11] = (keyB[sectorNo][1]); + bldata[12] = (keyB[sectorNo][2]); + bldata[13] = (keyB[sectorNo][3]); + bldata[14] = (keyB[sectorNo][4]); + bldata[15] = (keyB[sectorNo][5]); + } } memcpy(data + 10, bldata, 16); From 144dab14e986335f8ea4048a816013a042548e7e Mon Sep 17 00:00:00 2001 From: Gator96100 Date: Thu, 1 Apr 2021 16:38:45 +0200 Subject: [PATCH 133/373] Windows prioritise USB connections --- pm3 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pm3 b/pm3 index 3c69fea61..5fef9e6ee 100755 --- a/pm3 +++ b/pm3 @@ -157,7 +157,8 @@ function get_pm3_list_Windows { exit 1 fi fi - PM3LIST+=("$DEV") + #Prioritise USB connections + PM3LIST=("$DEV" "${PM3LIST[@]}") if [ ${#PM3LIST[*]} -ge "$N" ]; then return fi @@ -211,7 +212,8 @@ function get_pm3_list_WSL { exit 1 fi fi - PM3LIST+=("$DEV") + #Prioritise USB connections + PM3LIST=("$DEV" "${PM3LIST[@]}") if [ ! -w "$DEV" ]; then echo "[!] Let's give users read/write access to $DEV" sudo chmod 666 "$DEV" From b639586159061a59303c10d4184ca6f2d0a764b9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 1 Apr 2021 18:00:02 +0200 Subject: [PATCH 134/373] text --- README.md | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 850fc7395..cf6cd7ecd 100644 --- a/README.md +++ b/README.md @@ -79,28 +79,27 @@ This repo compiles nicely on - Proxspace v3.x - [latest release v3.8](https://github.com/Gator96100/ProxSpace/releases) - Windows/mingw environment with Qt5.6.1 & GCC 4.9 - - Ubuntu 16.04 -> 20.04 - - ParrotOS, Gentoo, Pentoo, Kali, Nethunter, Archlinux, Fedora, Debian + - Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, Nethunter, Archlinux, Fedora, Debian - Rasbian - Android / Termux - - Mac OS X / Homebrew / Apple Silicon - - WSL1 (Windows subsystem linux) on Windows 10 + - Mac OS X / Homebrew / Apple Silicon M1 + - WSL1 on Windows 10 - Docker container - [ RRG / Iceman repo based ubuntu 18.04 container ](https://hub.docker.com/r/secopsconsult/proxmark3) - [ Iceman fork based container v1.7 ](https://hub.docker.com/r/iceman1001/proxmark3/) Hardware to run client on - PC - - Android + - Android Phone - Raspberry Pi, Raspberry Pi Zero - Nvidia Jetson Nano ## Precompiled binaries We don't maintain any precompiled binaries in this repo. There is community effort over at the Proxmark3 forum where [@gator96100](https://github.com/gator96100) has set up a AWS bucket with precompiled Proxspace (Mingw) binaries which is recompiled every night and with that also up-to-date. We link to these files here as to make it easier for users. -_If you use his pre-compiled Proxspace binaries do consider buy him a coffee for his efforts. Remember nothing says thank you as good as a donation._ +_If you use his pre-compiled Proxspace binaries do consider buy him a coffee for his efforts. Remember nothing says thank you as much as a donation._ -If you are having troubles with these files, contact the package maintainer [@gator96100](https://github.com/gator96100) and read the [homepage of his proxmark builds](https://www.proxmarkbuilds.org/) or read the [sticky thread at forum](http://www.proxmark.org/forum/viewtopic.php?pid=24763#p24763) where known issues has been documented with regards to the precompiled builds. +If you are having troubles with these files, contact package maintainer [@gator96100](https://github.com/gator96100) and read the [homepage of his proxmark builds](https://www.proxmarkbuilds.org/) or read the [sticky thread at forum](http://www.proxmark.org/forum/viewtopic.php?pid=24763#p24763) where known issues has been documented with regards to the precompiled builds. ### Proxmark3 RDV4 devices - [Precompiled builds for RDV40 dedicated x64](https://www.proxmarkbuilds.org/#rdv40-64/) @@ -121,16 +120,14 @@ We usually merge your contributions fast since we do like the idea of getting a Please search the [issues](https://github.com/rfidresearchgroup/proxmark3/issues) page here and see if your issue is listed in the first instance. Read the [Troubleshooting guide](/doc/md/Installation_Instructions/Troubleshooting.md) to weed out most known problems. -Next place to visit is the [Proxmark3 Forum](http://www.proxmark.org/forum/index.php). Learn to search it well and finally Google / duckduckgo is your friend :) -You will find many blogposts, youtube videos, tweets, reddit +Next place to visit is the [Proxmark3 Forum](http://www.proxmark.org/forum/index.php). + ### Offical channels - [RFID Hacking community discord server](https://discord.gg/QfPvGFRQxH) - [Proxmark3 IRC channel](http://webchat.freenode.net/?channels=#proxmark3) - [Proxmark3 sub reddit](https://www.reddit.com/r/proxmark3/) - - [Proxmark3 Twitter](https://twitter.com/proxmark3/) - [Proxmark3 forum](http://www.proxmark.org/forum/index.php) - - _no slack channel_ ### Youtube channels @@ -158,14 +155,12 @@ To all distro, package maintainers, we tried to make your life easier. The official PM3-GUI from Gaucho will not work. Not to mention is quite old and not maintained any longer. -The new [Proxmark3 Universal GUI](https://github.com/burma69/PM3UniversalGUI) will work more or less. Change is needed in order to show helptext when client isn't connected to a device. We don't know how active the maintainers are. There has been brought to our attention that there is quite a few Chinese Windows GUI available. Usually you find them on alibaba / taobao ads but we have no idea which fw/client they are compatible with. Proceed with caution if you decide to go down that road. +- [Proxmark3 Universal GUI](https://github.com/burma69/PM3UniversalGUI) will work more or less. -Another new [Proxmark3 GUI crosscompiled](https://github.com/wh201906/Proxmark3GUI/) which is recently updated and claims to support latest source of this repo. Give it a spin and let us know how it works for you. +- [Proxmark3 GUI crosscompiled](https://github.com/wh201906/Proxmark3GUI/) which is recently updated and claims to support latest source of this repo. Give it a spin and let us know how it works for you. # Donations -Nothing says thank you as much as a donation. So if you feel the love, do feel free to become a iceman patron. For some tiers it comes with rewards. - -https://www.patreon.com/iceman1001 +Nothing says thank you as much as a donation. So if you feel the love, do feel free to become a [Iceman patron](https://www.patreon.com/iceman1001) From f4694a4cd57bf22e2e3d5696b4fce53f9e9a8682 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 1 Apr 2021 21:14:38 +0200 Subject: [PATCH 135/373] added new command 'hf mf wipe' - which takes a keyfile to wipe a MFC to default values --- client/src/cmdhfmf.c | 140 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 131 insertions(+), 9 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 45ec8fc56..a72383d86 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -868,16 +868,16 @@ static int CmdHF14AMfDump(const char *Cmd) { CLIParserInit(&ctx, "hf mf dump", "Dump MIFARE Classic tag to binary file\n" "If no given, UID will be used as filename", - "hf mf dump --mini --> MIFARE Mini\n" - "hf mf dump --1k --> MIFARE Classic 1k\n" - "hf mf dump --2k --> MIFARE 2k\n" - "hf mf dump --4k --> MIFARE 4k\n" - "hf mf dump -f hf-mf-066C8B78-key-5.bin --> MIFARE 1k with keys from specified file\n"); + "hf mf dump --mini --> MIFARE Mini\n" + "hf mf dump --1k --> MIFARE Classic 1k\n" + "hf mf dump --2k --> MIFARE 2k\n" + "hf mf dump --4k --> MIFARE 4k\n" + "hf mf dump --keys hf-mf-066C8B78-key.bin --> MIFARE 1k with keys from specified file\n"); void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "filename of dump"), - arg_str0("k", "keys", "", "filename of keys"), + arg_str0("f", "file", "", "filename of dump"), + arg_str0("k", "keys", "", "filename of keys"), arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"), arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (default)"), arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"), @@ -1294,7 +1294,7 @@ static int CmdHF14AMfRestore(const char *Cmd) { } } fclose(fdump); - PrintAndLogEx(INFO, "Finish restore"); + PrintAndLogEx(INFO, "Done!"); return PM3_SUCCESS; } @@ -5441,7 +5441,6 @@ static int CmdHf14AGen3Freeze(const char *Cmd) { return PM3_SUCCESS; } - static void des_decrypt(void *out, const void *in, const void *key) { mbedtls_des_context ctx; mbedtls_des_setkey_dec(&ctx, key); @@ -5582,6 +5581,127 @@ static int CmdHf14AMfSuperCard(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHF14AMfWipe(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf wipe", + "Wipe card to zeros and default keys/acc. This command taks a key file to wipe card\n" + "New A/B keys FF FF FF FF FF FF\n" + "New acc FF 07 80\n" + "New GDB 69", + "hf mf wipe" + ); + void *argtable[] = { + arg_param_begin, + arg_str0("f", "file", "", "key filename"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int keyfnlen = 0; + char keyFilename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)keyFilename, FILE_PATH_SIZE, &keyfnlen); + + CLIParserFree(ctx); + + char *fptr; + if (keyfnlen == 0) { + fptr = GenerateFilename("hf-mf-", "-key.bin"); + if (fptr == NULL) + return PM3_ESOFT; + + strcpy(keyFilename, fptr); + free(fptr); + } + + uint8_t *keys; + size_t keyslen = 0; + if (loadFile_safeEx(keyFilename, ".bin", (void **)&keys, (size_t *)&keyslen, false) != PM3_SUCCESS) { + PrintAndLogEx(FAILED, "failed to load key file"); + return PM3_ESOFT; + } + + uint8_t keyA[MIFARE_4K_MAXSECTOR * 6]; + uint8_t keyB[MIFARE_4K_MAXSECTOR * 6]; + uint8_t num_sectors = 0; + + switch (keyslen) { + case (MIFARE_MINI_MAXSECTOR * 2 * 6): { + PrintAndLogEx(INFO, "Loaded keys matching MIFARE Classic Mini 320b"); + memcpy(keyA, keys, (MIFARE_MINI_MAXSECTOR * 6)); + memcpy(keyB, keys + (MIFARE_MINI_MAXSECTOR * 6), (MIFARE_MINI_MAXSECTOR * 6)); + num_sectors = NumOfSectors('0'); + break; + } + case (MIFARE_1K_MAXSECTOR * 2 * 6): { + PrintAndLogEx(INFO, "Loaded keys matching MIFARE Classic 1K"); + memcpy(keyA, keys, (MIFARE_1K_MAXSECTOR * 6)); + memcpy(keyB, keys + (MIFARE_1K_MAXSECTOR * 6), (MIFARE_1K_MAXSECTOR * 6)); + num_sectors = NumOfSectors('1'); + break; + } + case (MIFARE_4K_MAXSECTOR * 2 * 6): { + PrintAndLogEx(INFO, "Loaded keys matching MIFARE Classic 4K"); + memcpy(keyA, keys, (MIFARE_4K_MAXSECTOR * 6)); + memcpy(keyB, keys + (MIFARE_4K_MAXSECTOR * 6), (MIFARE_4K_MAXSECTOR * 6)); + num_sectors = NumOfSectors('4'); + break; + } + default: { + PrintAndLogEx(INFO, "wrong key file size"); + goto out; + } + } + + uint8_t zeros[MFBLOCK_SIZE] = {0}; + memset(zeros, 0x00, sizeof(zeros)); + uint8_t st[MFBLOCK_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + // time to wipe card + for (uint8_t s = 0; s < num_sectors; s++) { + + for (uint8_t b = 0; b < NumBlocksPerSector(s); b++) { + + uint8_t data[26]; + memset(data, 0, sizeof(data)); + if (mfIsSectorTrailer(b)) { + memcpy(data + 10, st, sizeof(st)); + } else { + memcpy(data + 10, zeros, sizeof(zeros)); + } + + // try both A/B keys, start with B key first + for (int8_t kt = 1; kt > -1; kt--) { + + if (kt == 0) + memcpy(data, keyA + (s * 6), 6); + else + memcpy(data, keyB + (s * 6), 6); + + PrintAndLogEx(INFO, "Writing to block %3d: %s", FirstBlockOfSector(s) + b, sprint_hex(data + 10, MFBLOCK_SIZE)); + clearCommandBuffer(); + SendCommandMIX(CMD_HF_MIFARE_WRITEBL, FirstBlockOfSector(s) + b, kt, 0, data, sizeof(data)); + PacketResponseNG resp; + + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + uint8_t isOK = resp.oldarg[0] & 0xff; + if (isOK == 0) { + PrintAndLogEx(FAILED, "isOk: %02x", isOK); + } else { + break; + } + } else { + PrintAndLogEx(WARNING, "Command execute timeout"); + } + } + } + } + + PrintAndLogEx(INFO, "Done!"); +out: + free(keys); + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"list", CmdHF14AMfList, AlwaysAvailable, "List MIFARE history"}, @@ -5607,7 +5727,9 @@ static command_t CommandTable[] = { {"rdsc", CmdHF14AMfRdSc, IfPm3Iso14443a, "Read MIFARE Classic sector"}, {"restore", CmdHF14AMfRestore, IfPm3Iso14443a, "Restore MIFARE Classic binary file to BLANK tag"}, {"setmod", CmdHf14AMfSetMod, IfPm3Iso14443a, "Set MIFARE Classic EV1 load modulation strength"}, + {"wipe", CmdHF14AMfWipe, IfPm3Iso14443a, "Wipe card to zeros and default keys/acc"}, {"wrbl", CmdHF14AMfWrBl, IfPm3Iso14443a, "Write MIFARE Classic block"}, + // {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"}, {"sim", CmdHF14AMfSim, IfPm3Iso14443a, "Simulate MIFARE card"}, From b6ab166377f47dbfd92993f76ff6edbfb0a9d496 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 2 Apr 2021 08:00:26 +0200 Subject: [PATCH 136/373] updated the changelog... --- CHANGELOG.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f00e0215..d1763dfbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,60 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added `hf mf wipe` - takes a keyfile and wipes a MFC to default values (@iceman1001) + - Changed `pm3 shell` - now prioritise USB connections in WSL1 (@gator96100) + - Added `hf mf restore -w` - now supports usage of specified keyfile to authenticate with instead of default FFFFFF key (@iceman1001) + - Added `mem info --pem`- now supports loading of private key in PEM format (@iceman1001) + - Changed `hf mfp auth` - more verbose message (@vortixdev) + - Fix `hf mfdes rd` - AES chained mode fixes (@anon) + - Added `weigand decode -b` - now supports binary wiegand string as input (@iceman1001) + - Updated `README.md` - new link to a GUI project, and textual update (@iceman1001) + - Changed `hf search` - reenabled FeliCa search (@iceman1001) + - Changed `auto -a` - now allows for keep on searching, useful when detecting unknown multi tech cards (@iceman1001) + - Added more aid (@anon) + - Changed `hw version` - now also looks for FPGA chip id match (@iceman1001) + - Added WSL checks for outdated bootloader (@gator96100) + - Changed many, many more commands uses cliparser (@iceman1001) + - Changed many many cppchecker fixes (@iceman1001) + - Changed some coverity scan fixes (@iceman1001) + - Added `hw break` - to break device side loops from client (@iceman1001) + - Changed `hf mf sim` - removed field detection on device side (@iceman1001) + - Changed `mf_nonce_brute` - to recover key for nested authentications from traces (@iceman1001) + - Changed `trace list -t mf` - now prints needed data for mf_nonce_brute (@iceman1001) + - Fix `trace list -t mf` crc overwrote first hex char (@iceman1001) + - Fix `trace list -t mf` to print correct parity "!" (@doegox) + - Fix `lf em 4x05 unlock` not to break when tear off happens (@doegox) + - Fix `mem spiffs view` to not print when file doesn't exist on flash mem (@iceman1001) + - Changed `hf mf rdsc, egetsc, cgetsc` to have unified output (@iceman1001) + - Changed `hf mf rdsc` output to be more clear (@iceman1001) + - Changed `mem dump -c` now supports optional column breaks of output (@iceman1001) + - Changed unified client menu's to use curly brackets to indicate a sub category (@iceman1001) + - Added `mem spiffs view` to view external flash memory (@iceman1001) + - Fix 'lf t55xx config, chk, bruteforce' some logic to got mixed up in cliparser conversion (@mwalker33) + - Moved countones / bitcount fcts to utils.c (@doegox) + - Changed tunings in `hf mfu opttear` (@doegox) + - Updated the text in T5577_Guide.md to match new output (@iceman1001) + - Added a new t55xx configblock found in the wild (@iceman1001) + - Added `mem info -d` to support manual input of data (@iceman1001) + - Fix 'lf t55xx detect' some logic to got mixed up in cliparser conversion (@mwalker33) - Added `HF_CRAFTBYTE` standalone mode that reads and emulates 14a UID (@craftbyte) + - Added cryptoRF trace (@iceman1001) + - Changed default tcp port to 18888 (@iceman1001) + - Added more default keys to MFC dictionary (@iceman1001) + - Added one more icode slix2 signature to recover_pk.py (@iceman1001) + - Changed C15001 format to use OEM = 900 by default (@iceman1001) - Added a script to dump originality signatures from MFU EV1s and NTAGs (@aveao) + - Fix `hf emrtd` segfaults (@aveao) + - Fix `lf em 4150` timings on device side (@tharexde) + -Changed dependecies fixes in build scripts (@doegox, @iceman1001, @gator96100) + - Changed `recover_pk.py` to support colors (@iceman1001) + - Changed flashing feedback text to include needed steps (@iceman1001) + - Changed `lf_em4100_bulk.lua` in order to handle Proxspace odd 32b limit (@iceman1001) + - Added `script run lf_em4100_bulk.lua` a EM4100 bulk enrolling script (@iceman1001) + - Changed amiitool now linked, compiles in cmake, and outlined code usage in cmdhfmfu.c (@iceman1001) + - Changed `hf mfu info` - to have a fingerprint fct (@iceman1001) - Added parsing of EF_CardAccess to display PACE algorithm, version and parameter in `hf emrtd info` (@aveao) - - Change, numerous commands more uses cliparser (@tcprst, @iceman1001) + - Changed numerous commands more uses cliparser (@tcprst, @iceman1001) - Added more originality public keys (@anon) - Added `hf 14a info` - now also verify MFC Ev1 signatures (@iceman1001) - Added `LF_THAREXDE` standalone mode which simulates and reads EM4x50 cards (@tharexde) @@ -20,7 +70,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added support for older vid/pid detection (@Gator96100) - Added `hf mfdes bruteaid` - proper bruteforce of DESFire AID when no reading of files is possible (@craftbyte) - Added support for bidirectional communication for `lf em 4x50 sim` (@tharexde) - - Change `PLATFORM=PM3OTHER` to `PLATFORM=PM3GENERIC` (@iceman1001) + - Changed `PLATFORM=PM3OTHER` to `PLATFORM=PM3GENERIC` (@iceman1001) - Added `tools/hitag2crack/crack5opencl`, an optimized version of `crack5gpu` (@matrix) - Fixed Makefile to account for changes when running on Apple Silicon (@tcprst) - Added support for debugging ARM with JTAG & VSCode (@Gator96100) From a3ac00b20acccd0433b919b6c2f58299e5306e12 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 3 Apr 2021 15:44:13 +0200 Subject: [PATCH 137/373] hf search - disasbled felica detection #1233 again until felica is table enough --- client/src/cmdhf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index c92fc8fbb..7f53fea57 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -137,6 +137,7 @@ int CmdHFSearch(const char *Cmd) { } } + /* PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, " Searching for FeliCa tag..."); if (IfPm3Felica()) { @@ -146,7 +147,6 @@ int CmdHFSearch(const char *Cmd) { } } - /* PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, " Searching for CryptoRF tag..."); if (IfPm3Iso14443b()) { From 160941c280d642874c85444fe5db366254079d44 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 3 Apr 2021 16:14:53 +0200 Subject: [PATCH 138/373] text --- client/src/cmddata.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index b7a597eda..1cbbe3277 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1903,11 +1903,15 @@ int CmdTuneSamples(const char *Cmd) { const double approx_vdd_other_max = 8840; // 1% over threshold and supposedly non-RDV4 - if ((approx_vdd > approx_vdd_other_max * 1.01) && (! IfPm3Rdv4Fw())) - PrintAndLogEx(WARNING, "Contradicting measures seem to indicate you're running a " _YELLOW_("PM3_OTHER firmware on a RDV4") ", please check your setup"); + if ((approx_vdd > approx_vdd_other_max * 1.01) && (!IfPm3Rdv4Fw())) { + PrintAndLogEx(WARNING, "Contradicting measures seem to indicate you're running a " _YELLOW_("PM3_GENERIC firmware on a RDV4")); + PrintAndLogEx(WARNING, "False positives is possible but please check your setup"); + } // 1% below threshold and supposedly RDV4 - if ((approx_vdd < approx_vdd_other_max * 0.99) && (IfPm3Rdv4Fw())) - PrintAndLogEx(WARNING, "Contradicting measures seem to indicate you're running a " _YELLOW_("PM3_RDV4 firmware on a non-RDV4") ", please check your setup"); + if ((approx_vdd < approx_vdd_other_max * 0.99) && (IfPm3Rdv4Fw())) { + PrintAndLogEx(WARNING, "Contradicting measures seem to indicate you're running a " _YELLOW_("PM3_RDV4 firmware on a generic device")); + PrintAndLogEx(WARNING, "False positives is possible but please check your setup"); + } } } From a9aea6c72692169d2ff6fdfe50b584d2b8ac24f7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 4 Apr 2021 07:48:53 +0200 Subject: [PATCH 139/373] fix in nr demodulation , which fixes a crash in "lf em 4x05 info" --- common/lfdemod.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index 221dba8d6..7972e8788 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -1720,8 +1720,13 @@ int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, } else if (bits[i] <= low) { bits[bitnum++] = *invert ^ 1; } else if (i - lastBit >= *clk / 2 + tol) { - bits[bitnum] = bits[bitnum - 1]; - bitnum++; + if (bitnum > 0) { + bits[bitnum] = bits[bitnum - 1]; + bitnum++; + } else { + bits[bitnum] = 0; + bitnum++; + } } else { //in tolerance - looking for peak continue; } From ce9a6930c9ea8a44d39f5ad591d7c47748a4f176 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 4 Apr 2021 11:20:44 +0200 Subject: [PATCH 140/373] lets increase it... --- include/mifare.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mifare.h b/include/mifare.h index 804d6bd78..50bf94861 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -126,7 +126,7 @@ typedef struct { //----------------------------------------------------------------------------- typedef struct { uint8_t atr_len; - uint8_t atr[30]; + uint8_t atr[50]; } PACKED smart_card_atr_t; typedef enum SMARTCARD_COMMAND { From 31f7f1776648ef76ba9d211e857fd385dc828529 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 4 Apr 2021 11:21:17 +0200 Subject: [PATCH 141/373] smart, loop 5 times, and shorten delay instead --- armsrc/i2c.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/armsrc/i2c.c b/armsrc/i2c.c index 162126d76..2b9bac13a 100644 --- a/armsrc/i2c.c +++ b/armsrc/i2c.c @@ -219,7 +219,7 @@ static bool I2C_WaitForSim(void) { // 8051 speaks with smart card. // 1000*50*3.07 = 153.5ms // 1byte transfer == 1ms with max frame being 256bytes - if (!WaitSCL_H_delay(10 * 1000 * 50)) + if (!WaitSCL_H_delay(10 * 1000 * 30)) return false; return true; @@ -626,7 +626,7 @@ int I2C_get_version(uint8_t *maj, uint8_t *min) { // Will read response from smart card module, retries 3 times to get the data. bool sc_rx_bytes(uint8_t *dest, uint8_t *destlen) { - uint8_t i = 3; + uint8_t i = 5; int16_t len = 0; while (i--) { @@ -634,7 +634,6 @@ bool sc_rx_bytes(uint8_t *dest, uint8_t *destlen) { len = I2C_BufferRead(dest, *destlen, I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN); - LED_C_ON(); if (len > 1) { From 3b944adbd0ff1aa6f1f817b6b27d4dd83187d247 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 4 Apr 2021 11:31:48 +0200 Subject: [PATCH 142/373] text --- client/src/cmdsmartcard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdsmartcard.c b/client/src/cmdsmartcard.c index 94ca44875..2f099dfb1 100644 --- a/client/src/cmdsmartcard.c +++ b/client/src/cmdsmartcard.c @@ -622,7 +622,7 @@ static int CmdSmartInfo(const char *Cmd) { PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_SMART_ATR, &resp, 2500)) { if (verbose) { - PrintAndLogEx(WARNING, "smart card select failed"); + PrintAndLogEx(WARNING, "smart card timeout"); } return PM3_ETIMEOUT; } From 26aeae1f3e7131a10f4747164db3b4d5e8cbad21 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 4 Apr 2021 14:57:35 +0200 Subject: [PATCH 143/373] allow for larger strings (hex) to be input --- client/deps/cliparser/cliparser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/deps/cliparser/cliparser.c b/client/deps/cliparser/cliparser.c index 174a540fc..ff7b71d94 100644 --- a/client/deps/cliparser/cliparser.c +++ b/client/deps/cliparser/cliparser.c @@ -261,7 +261,7 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int if (!argstr->count) return 0; - uint8_t tmpstr[(256 * 2) + 1] = {0}; + uint8_t tmpstr[(512 * 2) + 1] = {0}; int ibuf = 0; for (int i = 0; i < argstr->count; i++) { From d19da982f044cfe18e17c0fc4a1e061d79829bd8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 4 Apr 2021 17:01:43 +0200 Subject: [PATCH 144/373] looping for smart card, inverted the silent to verbose, updated cardhelper stuff --- armsrc/i2c.c | 15 ++-- client/src/cmdflashmem.c | 45 +----------- client/src/cmdhficlass.c | 144 ++++++++++++++++++++++++++++++++++++-- client/src/cmdhficlass.h | 6 ++ client/src/cmdsmartcard.c | 96 ++++++++++++++----------- client/src/cmdsmartcard.h | 4 +- client/src/emv/emvcore.c | 2 +- common/cardhelper.c | 105 ++++++++++++++++++++++++--- common/cardhelper.h | 6 +- 9 files changed, 316 insertions(+), 107 deletions(-) diff --git a/armsrc/i2c.c b/armsrc/i2c.c index 2b9bac13a..49136d364 100644 --- a/armsrc/i2c.c +++ b/armsrc/i2c.c @@ -32,7 +32,7 @@ #define I2C_ERROR "I2C_WaitAck Error" -static volatile uint32_t c; +//static // Direct use the loop to delay. 6 instructions loop, Masterclock 48MHz, // delay=1 is about 200kbps @@ -40,6 +40,7 @@ static volatile uint32_t c; // I2CSpinDelayClk(4) = 12.31us // I2CSpinDelayClk(1) = 3.07us static void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) { + volatile uint32_t c; for (c = delay * 2; c; c--) {}; } @@ -160,7 +161,7 @@ static bool WaitSCL_H_delay(uint32_t delay) { // 5000 * 3.07us = 15350us. 15.35ms // 15000 * 3.07us = 46050us. 46.05ms static bool WaitSCL_H(void) { - return WaitSCL_H_delay(15000); + return WaitSCL_H_delay(10000); } static bool WaitSCL_L_delay(uint32_t delay) { @@ -174,7 +175,7 @@ static bool WaitSCL_L_delay(uint32_t delay) { } // 5000 * 3.07us = 15350us. 15.35ms static bool WaitSCL_L(void) { - return WaitSCL_L_delay(15000); + return WaitSCL_L_delay(10000); } // Wait max 1800ms or until SCL goes LOW. @@ -219,10 +220,7 @@ static bool I2C_WaitForSim(void) { // 8051 speaks with smart card. // 1000*50*3.07 = 153.5ms // 1byte transfer == 1ms with max frame being 256bytes - if (!WaitSCL_H_delay(10 * 1000 * 30)) - return false; - - return true; + return WaitSCL_H_delay(10 * 1000 * 50); } // send i2c STOP @@ -713,6 +711,9 @@ void SmartCardAtr(void) { I2C_Reset_EnterMainProgram(); smart_card_atr_t card; int res = GetATR(&card, true) ? PM3_SUCCESS : PM3_ETIMEOUT; + if (res == PM3_ETIMEOUT) { + I2C_Reset_EnterMainProgram(); + } reply_ng(CMD_SMART_ATR, res, (uint8_t *)&card, sizeof(smart_card_atr_t)); set_tracing(false); LEDsoff(); diff --git a/client/src/cmdflashmem.c b/client/src/cmdflashmem.c index c0a12cc39..bdc5dfd92 100644 --- a/client/src/cmdflashmem.c +++ b/client/src/cmdflashmem.c @@ -17,7 +17,7 @@ #include "cmdflashmemspiffs.h" // spiffs commands #include "rsa.h" #include "sha1.h" -#include "pk.h" // PEM key load functions +#include "pk.h" // PEM key load functions #define MCK 48000000 #define FLASH_MINFAST 24000000 //33000000 @@ -41,45 +41,6 @@ static int CmdHelp(const char *Cmd); "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" \ - "91386C0077937FE33FA3252D28855837" \ - "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ - "DF79C5CE07EE72C7F123142198164234" \ - "CABB724CF78B8173B9F880FC86322407" \ - "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ - "071513A1E85B5DFA031F21ECAE91A34D" - -// prime P -#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ - "2C01CAD19EA484A87EA4377637E75500" \ - "FCB2005C5C7DD6EC4AC023CDA285D796" \ - "C3D9E75E1EFC42488BB4F1D13AC30A57" - -// prime Q -#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ - "E211C2B9E5DB1ED0BF61D0D9899620F4" \ - "910E4168387E3C30AA1E00C339A79508" \ - "8452DD96A9A5EA5D9DCA68DA636032AF" - -#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \ - "3C94D22288ACD763FD8E5600ED4A702D" \ - "F84198A5F06C2E72236AE490C93F07F8" \ - "3CC559CD27BC2D1CA488811730BB5725" - -#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \ - "D8AAEA56749EA28623272E4F7D0592AF" \ - "7C1F1313CAC9471B5C523BFE592F517B" \ - "407A1BD76C164B93DA2D32A383E58357" - -#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \ - "F38D18D2B2F0E2DD275AA977E2BF4411" \ - "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ - "A74206CEC169D74BF5A8C50D6F48EA08" int rdv4_get_signature(rdv40_validation_t *out) { if (out == NULL) { @@ -107,7 +68,6 @@ int rdv4_get_signature(rdv40_validation_t *out) { // validate signature int rdv4_validate(rdv40_validation_t *mem) { - // Flash ID hash (sha1) uint8_t sha_hash[20] = {0}; mbedtls_sha1(mem->flashid, sizeof(mem->flashid), sha_hash); @@ -129,7 +89,6 @@ int rdv4_validate(rdv40_validation_t *mem) { return PM3_EFAILED; } - static int rdv4_sign_write(uint8_t *signature, uint8_t slen){ // save to mem clearCommandBuffer(); @@ -485,7 +444,6 @@ static int CmdFlashMemInfo(const char *Cmd) { return PM3_EINVARG; } - // set up PK key context now. mbedtls_pk_context pkctx; mbedtls_pk_init( &pkctx ); @@ -536,6 +494,7 @@ static int CmdFlashMemInfo(const char *Cmd) { if (res != PM3_SUCCESS) { return res; } + res = rdv4_validate(&mem); // Flash ID hash (sha1) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index f4f9aa89a..6df780f06 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -35,6 +35,7 @@ #define ICLASS_KEYS_MAX 8 #define ICLASS_AUTH_RETRY 10 #define ICLASS_DECRYPTION_BIN "iclass_decryptionkey.bin" + static uint8_t empty[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; static int CmdHelp(const char *Cmd); @@ -127,6 +128,89 @@ uint8_t card_app2_limit[] = { 0xff, }; +iclass_config_card_item_t iclass_config_types[14]= { + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + {"", "", ""}, + // must be the last entry + {"no config card info available", "", ""} +}; + +static bool check_config_card(const iclass_config_card_item_t *o) { + if (o == NULL || strlen(o->desc) == 0) { + PrintAndLogEx(INFO, "No data available"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass config -l") "` to download from cardhelper"); + return false; + } + return true; +} + +static int load_config_cards(void) { + PrintAndLogEx(INFO, "Detecting cardhelper..."); + + if (IsCardHelperPresent(false) == false) + return PM3_ENODATA; + + for (int i = 0; i < ARRAYLEN(iclass_config_types); ++i) { + + PrintAndLogEx(INPLACE, "loading idx %i", i); + iclass_config_card_item_t *ret = &iclass_config_types[i]; + + uint8_t desc[70] = {0}; + if (GetConfigCardStrByIdx(i, desc) == PM3_SUCCESS) { + memcpy(ret->desc, desc, sizeof(desc)); + } + + uint8_t blocks[16] = {0}; + if (GetConfigCardByIdx(i, blocks) == PM3_SUCCESS) { + memcpy(ret->blk6, blocks, sizeof(ret->blk6)); + memcpy(ret->blk7, blocks + sizeof(ret->blk6), sizeof(ret->blk7)); + } + } + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass configcard -p") "` to list all"); + return PM3_SUCCESS; +} + +static const iclass_config_card_item_t *get_config_card_item(uint8_t idx) { + iclass_config_card_item_t *ret = &iclass_config_types[idx]; + return ret; +} + +static void print_config_cards(void) { + if (check_config_card(&iclass_config_types[0])) { + PrintAndLogEx(INFO, "---- " _CYAN_("Config cards available") " ------------"); + for (int i = 0; i < ARRAYLEN(iclass_config_types); ++i) { + PrintAndLogEx(INFO, "%2d, %s", i, iclass_config_types[i].desc); + } + PrintAndLogEx(NORMAL, ""); + } +} + +static void print_config_card(const iclass_config_card_item_t *o) { + if (check_config_card(o)) { + PrintAndLogEx(INFO, "description... %s", o->desc); + PrintAndLogEx(INFO, "block 6....... " _YELLOW_("%s"), sprint_hex_inrow(o->blk6, sizeof(o->blk6))); + PrintAndLogEx(INFO, "block 7....... " _YELLOW_("%s"), sprint_hex_inrow(o->blk7, sizeof(o->blk7))); + } +} + +static void generate_config_card(const iclass_config_card_item_t *o) { + if (check_config_card(o)) { + + } +} + static uint8_t isset(uint8_t val, uint8_t mask) { return (val & mask); } @@ -937,7 +1021,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { uint8_t dec_data[8] = {0}; bool use_sc = false; if (have_key == false) { - use_sc = IsCryptoHelperPresent(verbose); + use_sc = IsCardHelperPresent(verbose); if (use_sc == false) { size_t keylen = 0; int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&keyptr, &keylen); @@ -1047,7 +1131,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { PrintAndLogEx(INFO, "Block 7 decoder"); - char hexstr[8 + 1] = {0}; + char hexstr[16 + 1] = {0}; hex_to_buffer((uint8_t *)hexstr, decrypted + (8 * 7), 8, sizeof(hexstr) - 1, 0, 0, true); char binstr[8 * 8 + 1] = {0}; @@ -1157,7 +1241,7 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) { bool use_sc = false; if (have_key == false) { - use_sc = IsCryptoHelperPresent(verbose); + use_sc = IsCardHelperPresent(verbose); if (use_sc == false) { size_t keylen = 0; int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&keyptr, &keylen); @@ -2008,7 +2092,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) { if (memcmp(data, empty, 8) == 0) return PM3_SUCCESS; - bool use_sc = IsCryptoHelperPresent(verbose); + bool use_sc = IsCardHelperPresent(verbose); if (use_sc == false) return PM3_SUCCESS; @@ -3391,7 +3475,7 @@ static int CmdHFiClassEncode(const char *Cmd) { } if (have_enc_key == false) { - use_sc = IsCryptoHelperPresent(false); + use_sc = IsCardHelperPresent(false); if (use_sc == false) { size_t keylen = 0; int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&enckeyptr, &keylen); @@ -3489,6 +3573,55 @@ static int CmdHFiClassAutopwn(const char *Cmd) { } */ +static int CmdHFiClassConfigCard(const char * Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf iclass configcard", + "Manage reader configuration card via Cardhelper", + "hf iclass configcard -l --> download config cards " + "hf iclass configcard -p --> print config card" + "hf iclass configcard -g --ki 1 --> generate config dump file based on idx 1" + ); + + void *argtable[] = { + arg_param_begin, + arg_int0(NULL, "ki", "", "select index in list"), + arg_lit0("g", NULL, "generate card dump file"), + arg_lit0("l", NULL, "load available cards"), + arg_lit0("p", NULL, "print available cards"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int idx = arg_get_int_def(ctx, 1, -1); + bool generate = arg_get_lit(ctx, 2); + bool load = arg_get_lit(ctx, 3); + bool print = arg_get_lit(ctx, 4); + CLIParserFree(ctx); + + if (load) { + if (load_config_cards() != PM3_SUCCESS) { + PrintAndLogEx(INFO, "failed to load, check your cardhelper"); + } + } + + if (print) { + print_config_cards(); + } + + if (idx >= 0) { + const iclass_config_card_item_t *item = get_config_card_item(idx); + print_config_card(item); + } + + if (generate) { + const iclass_config_card_item_t *item = get_config_card_item(idx); + generate_config_card(item); + } + + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("operations") " ---------------------"}, {"help", CmdHelp, AlwaysAvailable, "This help"}, @@ -3514,6 +3647,7 @@ static command_t CommandTable[] = { {"eview", CmdHFiClassEView, IfPm3Iclass, "View emulator memory"}, {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("utils") " ---------------------"}, + {"configcard", CmdHFiClassConfigCard, AlwaysAvailable, "Reader configuration card"}, {"calcnewkey", CmdHFiClassCalcNewKey, AlwaysAvailable, "Calc diversified keys (blocks 3 & 4) to write new keys"}, {"encode", CmdHFiClassEncode, AlwaysAvailable, "Encode binary wiegand to block 7"}, {"encrypt", CmdHFiClassEncryptBlk, AlwaysAvailable, "Encrypt given block data"}, diff --git a/client/src/cmdhficlass.h b/client/src/cmdhficlass.h index d060d1275..06a55122c 100644 --- a/client/src/cmdhficlass.h +++ b/client/src/cmdhficlass.h @@ -28,6 +28,12 @@ typedef struct iclass_prekey { uint8_t key[8]; } iclass_prekey_t; +typedef struct { + char desc[70]; + uint8_t blk6[8]; + uint8_t blk7[8]; +} iclass_config_card_item_t; + int CmdHFiClass(const char *Cmd); int info_iclass(void); diff --git a/client/src/cmdsmartcard.c b/client/src/cmdsmartcard.c index 2f099dfb1..c69404432 100644 --- a/client/src/cmdsmartcard.c +++ b/client/src/cmdsmartcard.c @@ -255,31 +255,43 @@ static void PrintATR(uint8_t *atr, size_t atrlen) { } } -static int smart_wait(uint8_t *data, bool silent) { - PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - if (!silent) PrintAndLogEx(WARNING, "smart card response timeout"); - return -1; - } +static int smart_wait(uint8_t *data, bool verbose) { + int i = 5; + uint32_t len = 0; + do { + clearCommandBuffer(); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - uint32_t len = resp.oldarg[0]; - if (!len) { - if (!silent) PrintAndLogEx(WARNING, "smart card response failed"); - return -2; - } - memcpy(data, resp.data.asBytes, len); - if (len >= 2) { - if (!silent) PrintAndLogEx(SUCCESS, "%02X%02X | %s", data[len - 2], data[len - 1], GetAPDUCodeDescription(data[len - 2], data[len - 1])); - } else { - if (!silent) PrintAndLogEx(SUCCESS, " %d | %s", len, sprint_hex_inrow_ex(data, len, 8)); - } + len = resp.oldarg[0]; + if (len == 0) { + if (verbose) PrintAndLogEx(WARNING, "smart card response failed"); + return -2; + } - return len; + memcpy(data, resp.data.asBytes, len); + if (len >= 2) { + if (verbose) { + PrintAndLogEx(SUCCESS, "%02X%02X | %s", data[len - 2], data[len - 1], GetAPDUCodeDescription(data[len - 2], data[len - 1])); + } + } else { + if (verbose) { + PrintAndLogEx(SUCCESS, " %d | %s", len, sprint_hex_inrow_ex(data, len, 8)); + } + } + return len; + } + } while (i--); + + if (verbose) { + PrintAndLogEx(WARNING, "smart card response timeout"); + } + return -1; } -static int smart_responseEx(uint8_t *data, bool silent) { +static int smart_responseEx(uint8_t *data, bool verbose) { - int datalen = smart_wait(data, silent); + int datalen = smart_wait(data, verbose); bool needGetData = false; if (datalen < 2) { @@ -293,13 +305,13 @@ static int smart_responseEx(uint8_t *data, bool silent) { if (needGetData) { int len = data[datalen - 1]; - if (!silent) PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len); + if (verbose) PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len); uint8_t getstatus[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, len}; clearCommandBuffer(); SendCommandMIX(CMD_SMART_RAW, SC_RAW, sizeof(getstatus), 0, getstatus, sizeof(getstatus)); - datalen = smart_wait(data, silent); + datalen = smart_wait(data, verbose); if (datalen < 2) { goto out; @@ -310,7 +322,7 @@ static int smart_responseEx(uint8_t *data, bool silent) { // data with ACK if (datalen == len + 2 + 1) { // 2 - response, 1 - ACK if (data[0] != ISO7816_GET_RESPONSE) { - if (!silent) { + if (verbose) { PrintAndLogEx(ERR, "GetResponse ACK error. len 0x%x | data[0] %02X", len, data[0]); } datalen = 0; @@ -321,7 +333,7 @@ static int smart_responseEx(uint8_t *data, bool silent) { memmove(data, &data[1], datalen); } else { // wrong length - if (!silent) { + if (verbose) { PrintAndLogEx(WARNING, "GetResponse wrong length. Must be 0x%02X got 0x%02X", len, datalen - 3); } } @@ -333,7 +345,7 @@ out: } static int smart_response(uint8_t *data) { - return smart_responseEx(data, false); + return smart_responseEx(data, true); } static int CmdSmartRaw(const char *Cmd) { @@ -358,7 +370,7 @@ static int CmdSmartRaw(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, true); - bool reply = arg_get_lit(ctx, 1); + bool reply = (arg_get_lit(ctx, 1) == false); bool active = arg_get_lit(ctx, 2); bool active_select = arg_get_lit(ctx, 3); bool decode_tlv = arg_get_lit(ctx, 4); @@ -807,7 +819,7 @@ static void smart_brute_prim(void) { clearCommandBuffer(); SendCommandMIX(CMD_SMART_RAW, SC_RAW_T0, 5, 0, get_card_data + i, 5); - int len = smart_responseEx(buf, true); + int len = smart_responseEx(buf, false); if (len > 2) { // if ( decodeTLV ) { @@ -849,14 +861,14 @@ static int smart_brute_sfi(bool decodeTLV) { clearCommandBuffer(); SendCommandMIX(CMD_SMART_RAW, SC_RAW_T0, sizeof(READ_RECORD), 0, READ_RECORD, sizeof(READ_RECORD)); - len = smart_responseEx(buf, true); + len = smart_responseEx(buf, false); if (buf[0] == 0x6C) { READ_RECORD[4] = buf[1]; clearCommandBuffer(); SendCommandMIX(CMD_SMART_RAW, SC_RAW_T0, sizeof(READ_RECORD), 0, READ_RECORD, sizeof(READ_RECORD)); - len = smart_responseEx(buf, true); + len = smart_responseEx(buf, false); READ_RECORD[4] = 0; } @@ -892,7 +904,7 @@ static void smart_brute_options(bool decodeTLV) { clearCommandBuffer(); SendCommandMIX(CMD_SMART_RAW, SC_RAW_T0, sizeof(GET_PROCESSING_OPTIONS), 0, GET_PROCESSING_OPTIONS, sizeof(GET_PROCESSING_OPTIONS)); - int len = smart_responseEx(buf, true); + int len = smart_responseEx(buf, false); if (len > 4) { PrintAndLogEx(SUCCESS, "Got processing options"); if (decodeTLV) { @@ -988,7 +1000,7 @@ static int CmdSmartBruteforceSFI(const char *Cmd) { clearCommandBuffer(); SendCommandOLD(CMD_SMART_RAW, SC_RAW_T0, hexlen, 0, cmddata, hexlen); - int len = smart_responseEx(buf, true); + int len = smart_responseEx(buf, false); if (len < 3) continue; @@ -1056,12 +1068,16 @@ int CmdSmartcard(const char *Cmd) { return CmdsParse(CommandTable, Cmd); } -int ExchangeAPDUSC(bool silent, uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { +int ExchangeAPDUSC(bool verbose, uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { *dataoutlen = 0; - if (activateCard) - smart_select(true, NULL); + if (activateCard) { + if (smart_select(false, NULL) == false) { + PrintAndLogEx(DEBUG, "APDU SC - select card failed"); + return 1; + } + } PrintAndLogEx(DEBUG, "APDU SC"); @@ -1073,7 +1089,7 @@ int ExchangeAPDUSC(bool silent, uint8_t *datain, int datainlen, bool activateCar clearCommandBuffer(); SendCommandOLD(CMD_SMART_RAW, flags, datainlen, 0, datain, datainlen); - int len = smart_responseEx(dataout, silent); + int len = smart_responseEx(dataout, verbose); if (len < 0) { return 1; } @@ -1090,14 +1106,14 @@ int ExchangeAPDUSC(bool silent, uint8_t *datain, int datainlen, bool activateCar // something fishy: we have only 5 bytes but we put datainlen in arg1? SendCommandMIX(CMD_SMART_RAW, SC_RAW_T0, datainlen, 0, data, sizeof(data)); - len = smart_responseEx(dataout, silent); + len = smart_responseEx(dataout, verbose); } *dataoutlen = len; return 0; } -bool smart_select(bool silent, smart_card_atr_t *atr) { +bool smart_select(bool verbose, smart_card_atr_t *atr) { if (atr) memset(atr, 0, sizeof(smart_card_atr_t)); @@ -1106,12 +1122,12 @@ bool smart_select(bool silent, smart_card_atr_t *atr) { PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_SMART_ATR, &resp, 2500)) { - if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); + if (verbose) PrintAndLogEx(WARNING, "smart card select failed"); return false; } if (resp.status != PM3_SUCCESS) { - if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); + if (verbose) PrintAndLogEx(WARNING, "smart card select failed"); return false; } @@ -1121,7 +1137,7 @@ bool smart_select(bool silent, smart_card_atr_t *atr) { if (atr) memcpy(atr, &card, sizeof(smart_card_atr_t)); - if (!silent) + if (verbose) PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len)); return true; diff --git a/client/src/cmdsmartcard.h b/client/src/cmdsmartcard.h index 798ea4678..ca4733724 100644 --- a/client/src/cmdsmartcard.h +++ b/client/src/cmdsmartcard.h @@ -16,7 +16,7 @@ int CmdSmartcard(const char *Cmd); -bool smart_select(bool silent, smart_card_atr_t *atr); -int ExchangeAPDUSC(bool silent, uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); +bool smart_select(bool verbose, smart_card_atr_t *atr); +int ExchangeAPDUSC(bool verbose, uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); #endif diff --git a/client/src/emv/emvcore.c b/client/src/emv/emvcore.c index f9cbe4f82..8d2ce0f86 100644 --- a/client/src/emv/emvcore.c +++ b/client/src/emv/emvcore.c @@ -307,7 +307,7 @@ static int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool Lea case ECC_CONTACT: res = 1; if (IfPm3Smartcard()) - res = ExchangeAPDUSC(true, data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); + res = ExchangeAPDUSC(false, data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); if (res) { return res; diff --git a/common/cardhelper.c b/common/cardhelper.c index ce57f6051..c2206da20 100644 --- a/common/cardhelper.c +++ b/common/cardhelper.c @@ -17,19 +17,26 @@ #define CARD_INS_DECRYPT 0x01 #define CARD_INS_ENCRYPT 0x02 +#define CARD_INS_VEIRFY_RRG 0x05 #define CARD_INS_DECODE 0x06 #define CARD_INS_NUMBLOCKS 0x07 #define CARD_INS_PINSIZE 0x08 +#define CARD_INS_CC 0x81 +#define CARD_INS_CC_DESC 0x82 static uint8_t cmd[] = {0x96, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -// look for CryptoHelper -bool IsCryptoHelperPresent(bool verbose) { +// look for CardHelper +bool IsCardHelperPresent(bool verbose) { if (IfPm3Smartcard()) { int resp_len = 0; uint8_t version[] = {0x96, 0x69, 0x00, 0x00, 0x00}; uint8_t resp[20] = {0}; - ExchangeAPDUSC(true, version, sizeof(version), true, true, resp, sizeof(resp), &resp_len); + ExchangeAPDUSC(verbose, version, sizeof(version), true, true, resp, sizeof(resp), &resp_len); + + if (resp_len < 8) { + return false; + } if (strstr("CryptoHelper", (char *)resp) == 0) { if (verbose) { @@ -48,7 +55,7 @@ static bool executeCrypto(uint8_t ins, uint8_t *src, uint8_t *dest) { cmd[1] = ins; memcpy(cmd + 5, src, 8); - ExchangeAPDUSC(true, cmd, sizeof(cmd), false, true, dec, sizeof(dec), &resp_len); + ExchangeAPDUSC(false, cmd, sizeof(cmd), false, false, dec, sizeof(dec), &resp_len); if (resp_len == 10) { memcpy(dest, dec, 8); @@ -74,12 +81,23 @@ void DecodeBlock6(uint8_t *src) { memcpy(c + 6, src, 8); // first part - ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + ExchangeAPDUSC(false, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + + + if (resp_len < 11) { + return; + } + PrintAndLogEx(SUCCESS, "%.*s", resp_len - 11, resp + 9); // second part c[5] = 0x02; - ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + ExchangeAPDUSC(false, c, sizeof(c), false, false, resp, sizeof(resp), &resp_len); + + + if (resp_len < 11) { + return; + } PrintAndLogEx(SUCCESS, "%.*s", resp_len - 11, resp + 9); } @@ -89,7 +107,13 @@ uint8_t GetNumberBlocksForUserId(uint8_t *src) { uint8_t resp[254] = {0}; uint8_t c[] = {0x96, CARD_INS_NUMBLOCKS, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; memcpy(c + 5, src, 8); - ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + ExchangeAPDUSC(false, c, sizeof(c), false, false, resp, sizeof(resp), &resp_len); + + + if (resp_len < 8) { + return 0; + } + return resp[8]; } @@ -99,10 +123,75 @@ uint8_t GetPinSize(uint8_t *src) { uint8_t resp[254] = {0}; uint8_t c[] = {0x96, CARD_INS_PINSIZE, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; memcpy(c + 5, src, 8); - ExchangeAPDUSC(true, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + ExchangeAPDUSC(false, c, sizeof(c), false, false, resp, sizeof(resp), &resp_len); + if (resp_len < 2) { + return 0; + } if (resp[resp_len - 2] == 0x90 && resp[resp_len - 1] == 0x00) { return resp[8]; } return 0; } + +int GetConfigCardByIdx(uint8_t typ, uint8_t *blocks) { + if (blocks == NULL) + return PM3_EINVARG; + + int resp_len = 0; + uint8_t resp[254] = {0}; + uint8_t c[] = {0x96, CARD_INS_CC, 0x00, 0x00, 17, typ, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + ExchangeAPDUSC(false, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + + if (resp_len < 2) { + return PM3_ESOFT; + } + + if (resp[resp_len - 2] == 0x90 && resp[resp_len - 1] == 0x00) { + memcpy(blocks, resp + 1, 16); + return PM3_SUCCESS; + } + return PM3_ESOFT; +} + +int GetConfigCardStrByIdx(uint8_t typ, uint8_t *out) { + if (out == NULL) + return PM3_EINVARG; + + int resp_len = 0; + uint8_t resp[254] = {0}; + uint8_t c[] = {0x96, CARD_INS_CC_DESC, 0x00, 0x00, 1, typ}; + ExchangeAPDUSC(false, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); + + if (resp_len < 2) { + return PM3_ESOFT; + } + + if (resp[resp_len - 2] == 0x90 && resp[resp_len - 1] == 0x00) { + memcpy(out, resp + 1, resp_len - 2 - 1); + return PM3_SUCCESS; + } + return PM3_ESOFT; +} + +int VerifyRdv4Signature(uint8_t *memid, uint8_t *signature) { + if (memid == NULL || signature == NULL) + return PM3_EINVARG; + + int resp_len = 0; + uint8_t resp[254] = {0}; + uint8_t c[5 + 8 + 128] = {0x96, CARD_INS_VEIRFY_RRG, 0x00, 0x00, 8 + 128}; + + memcpy(c + 5, memid, 8); + memcpy(c + 5 + 8, signature, 128); + + ExchangeAPDUSC(false, c, sizeof(c), true, false, resp, sizeof(resp), &resp_len); + if (resp_len < 2) { + return PM3_ESOFT; + } + + if (memcmp(resp + resp_len - 4, "\x6f\x6b\x90\x00", 4) == 0) { + return PM3_SUCCESS; + } + return PM3_ESOFT; +} diff --git a/common/cardhelper.h b/common/cardhelper.h index d55ae6701..1ef5b646e 100644 --- a/common/cardhelper.h +++ b/common/cardhelper.h @@ -14,10 +14,14 @@ #include #include "common.h" -bool IsCryptoHelperPresent(bool verbose); +bool IsCardHelperPresent(bool verbose); bool Encrypt(uint8_t *src, uint8_t *dest); bool Decrypt(uint8_t *src, uint8_t *dest); void DecodeBlock6(uint8_t *src); uint8_t GetNumberBlocksForUserId(uint8_t *src); uint8_t GetPinSize(uint8_t *src); + +int GetConfigCardByIdx(uint8_t typ, uint8_t *blocks); +int GetConfigCardStrByIdx(uint8_t typ, uint8_t *out); +int VerifyRdv4Signature(uint8_t *memid, uint8_t *signature); #endif From 86e682fefff313ce743f0e6d2850509d8ef788dc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 4 Apr 2021 17:02:55 +0200 Subject: [PATCH 145/373] reverse read_reply in 14b raw --- client/src/cmdhf14b.c | 20 ++++++++++---------- client/src/cmdhffelica.c | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index a9524abb4..3934ea5d6 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -279,15 +279,15 @@ static int CmdHF14BCmdRaw(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_lit0("k", "keep", "leave the signal field ON after receive response"), - arg_lit0("s", "std", "activate field, use ISO14B select"), - arg_lit0(NULL, "sr", "activate field, use SRx ST select"), - arg_lit0(NULL, "cts", "activate field, use ASK C-ticket select"), - arg_lit0("c", "crc", "calculate and append CRC"), - arg_lit0(NULL, "noresponse", "do not read response from card"), - arg_int0("t", "timeout", "", "timeout in ms"), - arg_lit0("v", "verbose", "verbose"), - arg_strx0("d", "data", "", "data, bytes to send"), + arg_lit0("k", "keep", "leave the signal field ON after receive response"), + arg_lit0("s", "std", "activate field, use ISO14B select"), + arg_lit0(NULL, "sr", "activate field, use SRx ST select"), + arg_lit0(NULL, "cts", "activate field, use ASK C-ticket select"), + arg_lit0("c", "crc", "calculate and append CRC"), + arg_lit0("-r", NULL, "do not read response from card"), + arg_int0("t", "timeout", "", "timeout in ms"), + arg_lit0("v", "verbose", "verbose"), + arg_strx0("d", "data", "", "data, bytes to send"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -297,7 +297,7 @@ static int CmdHF14BCmdRaw(const char *Cmd) { bool select_sr = arg_get_lit(ctx, 3); bool select_cts = arg_get_lit(ctx, 4); bool add_crc = arg_get_lit(ctx, 5); - bool read_reply = !arg_get_lit(ctx, 6); + bool read_reply = (arg_get_lit(ctx, 6) == false); int user_timeout = arg_get_int_def(ctx, 7, -1); bool verbose = arg_get_lit(ctx, 8); diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index ec649d959..7948dbadb 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -433,7 +433,7 @@ static int info_felica(bool verbose) { } case 0: { PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------"); + PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------"); PrintAndLogEx(INFO, "IDm............ " _GREEN_("%s"), sprint_hex_inrow(card.IDm, sizeof(card.IDm))); PrintAndLogEx(INFO, "Code........... %s ", sprint_hex_inrow(card.code, sizeof(card.code))); PrintAndLogEx(INFO, "NFCID2......... %s", sprint_hex_inrow(card.uid, sizeof(card.uid))); From 02a6ebecb572ef80872868f5e1b30fa132f87780 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 4 Apr 2021 17:04:26 +0200 Subject: [PATCH 146/373] ...single params must be single char --- client/src/cmdhf14b.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index 3934ea5d6..3671b476c 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -279,12 +279,12 @@ static int CmdHF14BCmdRaw(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_lit0("k", "keep", "leave the signal field ON after receive response"), - arg_lit0("s", "std", "activate field, use ISO14B select"), - arg_lit0(NULL, "sr", "activate field, use SRx ST select"), - arg_lit0(NULL, "cts", "activate field, use ASK C-ticket select"), - arg_lit0("c", "crc", "calculate and append CRC"), - arg_lit0("-r", NULL, "do not read response from card"), + arg_lit0("k", "keep", "leave the signal field ON after receive response"), + arg_lit0("s", "std", "activate field, use ISO14B select"), + arg_lit0(NULL, "sr", "activate field, use SRx ST select"), + arg_lit0(NULL, "cts", "activate field, use ASK C-ticket select"), + arg_lit0("c", "crc", "calculate and append CRC"), + arg_lit0("r", NULL, "do not read response from card"), arg_int0("t", "timeout", "", "timeout in ms"), arg_lit0("v", "verbose", "verbose"), arg_strx0("d", "data", "", "data, bytes to send"), From 48012061a6b5b12ed8719b14b82d0f46e9f3d504 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 4 Apr 2021 17:05:35 +0200 Subject: [PATCH 147/373] hitag cliparser stuff --- client/src/cmdlfhitag.c | 219 +++++++++++++++++++++++----------------- 1 file changed, 125 insertions(+), 94 deletions(-) diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index cb711a65c..cdefd8a00 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -51,20 +51,6 @@ static size_t nbytes(size_t nbits) { } */ -static int usage_hitag_sim(void) { - PrintAndLogEx(NORMAL, "Simulate " _YELLOW_("Hitag2 / HitagS")" transponder"); - PrintAndLogEx(NORMAL, "Usage: lf hitag sim [h] [2|s] e|j|b "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " [2|s] 2 = hitag2, s = hitagS"); - PrintAndLogEx(NORMAL, " e Load data from EML file"); - PrintAndLogEx(NORMAL, " j Load data from JSON file"); - PrintAndLogEx(NORMAL, " b Load data from BIN file"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf hitag sim 2 b lf-hitag-dump"); - return PM3_SUCCESS; -} /* static int usage_hitag_dump(void) { PrintAndLogEx(NORMAL, "Usage: lf hitag dump [h] p f "); @@ -273,84 +259,128 @@ static int CmdLFHitagSniff(const char *Cmd) { return PM3_SUCCESS; } -static int CmdLFHitagSim(const char *Cmd) { - bool errors = false; - bool tag_mem_supplied = false; - uint8_t cmdp = 0; - size_t maxdatalen = 48; - uint8_t *data = calloc(4 * 64, sizeof(uint8_t)); - size_t datalen = 0; +// eload , to be implemented +static int CmdLFHitagEload(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf hitag eload", + "Loads hitag tag dump into emulator memory on device", + "lf hitag eload -f lf-hitag-11223344-dump.bin\n"); + + void *argtable[] = { + arg_param_begin, + arg_str1("f", "file", "", "filename of dump"), + arg_lit0("1", NULL, "simulate Hitag1"), + arg_lit0("2", NULL, "simulate Hitag2"), + arg_lit0("s", NULL, "simulate HitagS"), + 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, FILE_PATH_SIZE, &fnlen); + + bool use_ht1 = arg_get_lit(ctx, 2); + bool use_ht2 = arg_get_lit(ctx, 3); + bool use_hts = arg_get_lit(ctx, 4); + CLIParserFree(ctx); + + uint8_t n = (use_ht1 + use_ht2 + use_hts); + if (n != 1) { + PrintAndLogEx(ERR, "error, only specify one Hitag type"); + return PM3_EINVARG; + } + + DumpFileType_t dftype = getfiletype(filename); + size_t dumplen = 0; + uint8_t *dump = NULL; int res = 0; - char filename[FILE_PATH_SIZE] = { 0x00 }; - - uint16_t cmd = CMD_LF_HITAG_SIMULATE; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - free(data); - return usage_hitag_sim(); - case '2': - maxdatalen = 48; - cmdp++; - break; - case 's': - cmd = CMD_LF_HITAGS_SIMULATE; - maxdatalen = 4 * 64; - cmdp++; - break; - case 'e': - param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); - res = loadFileEML(filename, data, &datalen); - if (res > 0 || datalen != maxdatalen) { - PrintAndLogEx(FAILED, "error, bytes read mismatch file size"); - errors = true; - break; - } - tag_mem_supplied = true; - cmdp += 2; - break; - case 'j': - param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); - res = loadFileJSON(filename, data, maxdatalen, &datalen, NULL); - if (res > 0) { - errors = true; - break; - } - tag_mem_supplied = true; - cmdp += 2; - break; - case 'b': - param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); - res = loadFile(filename, ".bin", data, maxdatalen, &datalen); - if (res > 0) { - errors = true; - break; - } - tag_mem_supplied = true; - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; + switch (dftype) { + case BIN: { + res = loadFile_safe(filename, ".bin", (void **)&dump, &dumplen); + break; + } + case EML: { + res = loadFileEML_safe(filename, (void **)&dump, &dumplen); + break; + } + case JSON: { + dumplen = 4 * 64; + dump = calloc(dumplen, sizeof(uint8_t)); + if (dump == NULL) { + PrintAndLogEx(ERR, "error, cannot allocate memory"); + return PM3_EMALLOC; + } + res = loadFileJSON(filename, dump, dumplen, &dumplen, NULL); + break; + } + case DICTIONARY: { + PrintAndLogEx(ERR, "error, only BIN/JSON/EML formats allowed"); + return PM3_EINVARG; } } - //Validations - if (errors || cmdp == 0) { - free(data); - return usage_hitag_sim(); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "error, something went wrong when loading file"); + free(dump); + return PM3_EFILE; } + // check dump len.. + if (dumplen == 48 || dumplen == 4 * 64) { + struct { + uint16_t len; + uint8_t *data; + } PACKED payload; + payload.len = dumplen; + memcpy(payload.data, dump, dumplen); + + clearCommandBuffer(); + SendCommandNG(CMD_LF_HITAG_ELOAD, (uint8_t *)&payload, 2 + dumplen); + } else { + PrintAndLogEx(ERR, "error, wrong dump file size. got %u", dumplen); + } + + return PM3_SUCCESS; +} + +static int CmdLFHitagSim(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf hitag sim", + "Simulate Hitag2 / HitagS transponder\n" + "You need to `lf hitag eload` first", + "lf hitag sim -2" + ); + + void *argtable[] = { + arg_param_begin, + arg_lit0("1", NULL, "simulate Hitag1"), + arg_lit0("2", NULL, "simulate Hitag2"), + arg_lit0("s", NULL, "simulate HitagS"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool use_ht1 = arg_get_lit(ctx, 1); + bool use_ht2 = arg_get_lit(ctx, 2); + bool use_hts = arg_get_lit(ctx, 3); + CLIParserFree(ctx); + + if ((use_ht1 + use_ht2 + use_hts) > 1 ) { + PrintAndLogEx(ERR, "error, Only specify one Hitag type"); + return PM3_EINVARG; + } + + uint16_t cmd = CMD_LF_HITAG_SIMULATE; +// if (use_ht1) +// cmd = CMD_LF_HITAG1_SIMULATE; + + if (use_hts) + cmd = CMD_LF_HITAGS_SIMULATE; + clearCommandBuffer(); - if (tag_mem_supplied) { - SendCommandMIX(cmd, 1, 0, 0, data, datalen); - } else { - SendCommandMIX(cmd, 0, 0, 0, NULL, 0); - } - - free(data); + SendCommandMIX(cmd, 0, 0, 0, NULL, 0); return PM3_SUCCESS; } @@ -631,7 +661,7 @@ static int CmdLFHitagCheckChallenges(const char *Cmd) { 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); + PrintAndLogEx(ERR, "Error, file length mismatch. Expected %d, got %zu", 8*60, datalen); } } if (data) { @@ -780,15 +810,16 @@ void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool } static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help" }, - {"list", CmdLFHitagList, IfPm3Hitag, "List Hitag trace history" }, - {"info", CmdLFHitagInfo, IfPm3Hitag, "Tag information" }, - {"reader", CmdLFHitagReader, IfPm3Hitag, "Act like a Hitag Reader" }, - {"sim", CmdLFHitagSim, IfPm3Hitag, "Simulate Hitag transponder" }, - {"sniff", CmdLFHitagSniff, IfPm3Hitag, "Eavesdrop Hitag communication" }, - {"writer", CmdLFHitagWriter, IfPm3Hitag, "Act like a Hitag Writer" }, - {"dump", CmdLFHitag2Dump, IfPm3Hitag, "Dump Hitag2 tag" }, - {"cc", CmdLFHitagCheckChallenges, IfPm3Hitag, "Test all challenges" }, + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"eload", CmdLFHitagEload, IfPm3Hitag, "Load Hitag dump file into emulator memory"}, + {"list", CmdLFHitagList, IfPm3Hitag, "List Hitag trace history"}, + {"info", CmdLFHitagInfo, IfPm3Hitag, "Tag information"}, + {"reader", CmdLFHitagReader, IfPm3Hitag, "Act like a Hitag Reader"}, + {"sim", CmdLFHitagSim, IfPm3Hitag, "Simulate Hitag transponder"}, + {"sniff", CmdLFHitagSniff, IfPm3Hitag, "Eavesdrop Hitag communication"}, + {"writer", CmdLFHitagWriter, IfPm3Hitag, "Act like a Hitag Writer"}, + {"dump", CmdLFHitag2Dump, IfPm3Hitag, "Dump Hitag2 tag"}, + {"cc", CmdLFHitagCheckChallenges, IfPm3Hitag, "Test all challenges"}, { NULL, NULL, 0, NULL } }; From d012a879f2dcf94554eb679335826027c6270343 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 4 Apr 2021 17:06:48 +0200 Subject: [PATCH 148/373] WIP - hitag sniff, eload, sim --- armsrc/appmain.c | 15 +- armsrc/hitag2.c | 364 +++++++++++++++++++++++++++++++++++++++-------- armsrc/hitag2.h | 5 +- 3 files changed, 318 insertions(+), 66 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index ec6ebb2c0..b0a78ccb1 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -49,6 +49,7 @@ #include "commonutil.h" #include "crc16.h" + #ifdef WITH_LCD #include "LCD_disabled.h" #endif @@ -1084,7 +1085,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_LF_HITAG_SIMULATE: { // Simulate Hitag tag, args = memory content - SimulateHitag2((bool)packet->oldarg[0], packet->data.asBytes); + SimulateHitag2(); break; } case CMD_LF_HITAG_READER: { // Reader for Hitag tags, args = type and function @@ -1111,6 +1112,18 @@ static void PacketReceived(PacketCommandNG *packet) { } break; } + case CMD_LF_HITAG_ELOAD: { + /* + struct p { + uint16_t len; + uint8_t *data; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + uint8_t *mem = BigBuf_get_EM_addr(); + memcpy((uint8_t *)mem.sectors, payload->data, payload->len); + */ + break; + } #endif #ifdef WITH_EM4x50 diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index c2916bfe2..b7db20919 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -106,15 +106,13 @@ static int16_t blocknr; static size_t flipped_bit = 0; static uint32_t byte_value = 0; -static int hitag2_reset(void) { +static void hitag2_reset(void) { tag.state = TAG_STATE_RESET; tag.crypto_active = 0; - return 0; } -static int hitag2_init(void) { +static void hitag2_init(void) { hitag2_reset(); - return 0; } // Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) @@ -126,14 +124,14 @@ static int hitag2_init(void) { #endif #define HITAG_FRAME_LEN 20 -#define HITAG_T_STOP 36 /* T_EOF should be > 36 */ -#define HITAG_T_LOW 8 /* T_LOW should be 4..10 */ -#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */ +#define HITAG_T_STOP 37 /* T_EOF should be > 36 */ +#define HITAG_T_LOW 4 /* T_LOW should be 4..10 */ +#define HITAG_T_0_MIN 17 /* T[0] should be 18..22 */ #define HITAG_T_0 20 /* T[0] should be 18..22 */ #define HITAG_T_1_MIN 25 /* T[1] should be 26..30 */ #define HITAG_T_1 30 /* T[1] should be 26..30 */ //#define HITAG_T_EOF 40 /* T_EOF should be > 36 */ -#define HITAG_T_EOF 80 /* T_EOF should be > 36 */ +#define HITAG_T_EOF 40 /* T_EOF should be > 36 */ #define HITAG_T_WAIT_1_MIN 199 /* T_wresp should be 199..206 */ #define HITAG_T_WAIT_2_MIN 90 /* T_wait2 should be at least 90 */ #define HITAG_T_WAIT_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */ @@ -987,84 +985,330 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t return true; } +void EloadHitag(uint8_t *data, uint16_t len) { + memcpy(tag.sectors, data, sizeof(tag.sectors)); +} + // Hitag2 Sniffing + +// T0 18-22 fc (total time ZERO) +// T1 26-32 fc (total time ONE) +// Tstop 36 > fc (high field stop limit) +// Tlow 4-10 fc (reader field low time) void SniffHitag2(void) { + DbpString("Starting Hitag2 sniffing"); + LED_D_ON(); + + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); set_tracing(true); - auth_table_len = 0; - auth_table_pos = 0; - - auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); - memset(auth_table, 0x00, AUTH_TABLE_LENGTH); - - DbpString("Starting Hitag2 sniffing"); - LED_D_ON(); - +/* lf_init(false, false); - g_logging = false; + // no logging of the raw signal + g_logging = lf_get_reader_modulation(); + uint32_t total_count = 0; - uint8_t periods_bytes[4]; - -// int16_t checked = 0; - - /*bool waiting_for_first_edge = true;*/ - LED_C_ON(); - - uint32_t signal_size = 10000; + uint8_t rx[20 * 8 * 2]; while (BUTTON_PRESS() == false) { - // use malloc - initSampleBufferEx(&signal_size, false); + lf_reset_counter(); WDT_HIT(); - /* - // only every 1000th times, in order to save time when collecting samples. - if (checked == 1000) { - if (data_available()) { - checked = -1; - break; - } else { - checked = 0; - } - } - ++checked; - */ + size_t periods = 0; + uint16_t rxlen = 0; + memset(rx, 0x00, sizeof(rx)); + // Use the current modulation state as starting point + uint8_t mod_state = lf_get_reader_modulation(); - // Receive frame, watch for at most T0*EOF periods -// lf_reset_counter(); - - // Wait "infinite" for reader modulation - size_t periods = lf_detect_gap(10000); - - // Test if we detected the first reader modulation edge - if (periods != 0) { - if (g_logging == false) { - g_logging = true; - LED_D_ON(); + while (rxlen < sizeof(rx)) { + periods = lf_count_edge_periods(64); + // Evaluate the number of periods before the next edge + if (periods >= 24 && periods < 64) { + // Detected two sequential equal bits and a modulation switch + // NRZ modulation: (11 => --|) or (11 __|) + rx[rxlen++] = mod_state; + rx[rxlen++] = mod_state; + // toggle tag modulation state + mod_state ^= 1; + } else if (periods > 0 && periods < 24) { + // Detected one bit and a modulation switch + // NRZ modulation: (1 => -|) or (0 _|) + rx[rxlen++] = mod_state; + mod_state ^= 1; + } else { + mod_state ^= 1; + break; } } + + if (rxlen == 0) + continue; - /*lf_count_edge_periods(10000);*/ - while ((periods = lf_detect_gap(64)) != 0) { - num_to_bytes(periods, 4, periods_bytes); - LogTrace(periods_bytes, 4, 0, 0, NULL, true); + // tag sends 11111 + uid, + bool got_tag = ((memcmp(rx, "\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00", 10) == 0)); + + if (got_tag) { + // mqnchester decode + bool bad_man = false; + uint16_t bitnum = 0; + for (uint16_t i = 0; i < rxlen; i += 2) { + if (rx[i] == 1 && (rx[i + 1] == 0)) { + rx[bitnum++] = 0; + } else if ((rx[i] == 0) && rx[i + 1] == 1) { + rx[bitnum++] = 1; + } else { + bad_man = true; + } + } + + if (bad_man) { + DBG DbpString("bad manchester"); + continue; + } + + if (bitnum < 5) { + DBG DbpString("too few bits"); + continue; + } + + // skip header 11111 + uint16_t i = 0; + if (got_tag) { + i = 5; + } + + // Pack the response into a byte array + rxlen = 0; + for (; i < bitnum; i++) { + uint8_t b = rx[i]; + rx[rxlen >> 3] |= b << (7 - (rxlen % 8)); + rxlen++; + } + + // skip spurious bit + if (rxlen % 8 == 1) { + rxlen--; + } + + // nothing to log + if (rxlen == 0) + continue; + + LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false); + total_count += nbytes(rxlen); + } else { + // decode reader comms + LogTrace(rx, rxlen, 0, 0, NULL, true); + total_count += rxlen; + // Pack the response into a byte array + + // LogTrace(rx, nbytes(rdr), 0, 0, NULL, true); + // total_count += nbytes(rdr); } + LED_A_INV(); } lf_finalize(); - DbpString("Hitag2 sniffing finish. Use `lf hitag list` for annotations"); + Dbprintf("Collected %u bytes", total_count); + + */ + + // Set up eavesdropping mode, frequency divisor which will drive the FPGA + // and analog mux selection. + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); // 125Khz + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); + + // Configure output pin that is connected to the FPGA (for modulating) + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + + // Disable modulation, we are going to eavesdrop, not modulate ;) + LOW(GPIO_SSC_DOUT); + + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; + + // Disable timer during configuration + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + + // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // external trigger rising edge, load RA on rising edge of TIOA. + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH; + + // Enable and reset counter + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + + int frame_count = 0, response = 0, overflow = 0, lastbit = 1, tag_sof = 4; + bool rising_edge = false, reader_frame = false, bSkip = true; + uint8_t rx[HITAG_FRAME_LEN]; + size_t rxlen = 0; + + auth_table_len = 0; + auth_table_pos = 0; + + // Reset the received frame, frame count and timing info + memset(rx, 0x00, sizeof(rx)); + + auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); + memset(auth_table, 0x00, AUTH_TABLE_LENGTH); + + while(BUTTON_PRESS() == false) { + + WDT_HIT(); + memset(rx, 0x00, sizeof(rx)); + + // Receive frame, watch for at most T0 * EOF periods + while (AT91C_BASE_TC1->TC_CV < (HITAG_T0 * HITAG_T_EOF) ) { + // Check if rising edge in modulation is detected + if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { + // Retrieve the new timing values + int ra = (AT91C_BASE_TC1->TC_RA / HITAG_T0); + + // Find out if we are dealing with a rising or falling edge + rising_edge = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME) > 0; + + // Shorter periods will only happen with reader frames + if (reader_frame == false && rising_edge && ra < HITAG_T_TAG_CAPTURE_ONE_HALF) { + // Switch from tag to reader capture + LED_C_OFF(); + reader_frame = true; + rxlen = 0; + } + + // Only handle if reader frame and rising edge, or tag frame and falling edge + if (reader_frame == rising_edge) { + overflow += ra; + continue; + } + + // Add the buffered timing values of earlier captured edges which were skipped + ra += overflow; + overflow = 0; + + if (reader_frame) { + LED_B_ON(); + // Capture reader frame + if(ra >= HITAG_T_STOP) { +// if (rxlen != 0) { + //DbpString("wierd0?"); +// } + // Capture the T0 periods that have passed since last communication or field drop (reset) + response = (ra - HITAG_T_LOW); + } else if(ra >= HITAG_T_1_MIN ) { + // '1' bit + rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); + rxlen++; + } else if(ra >= HITAG_T_0_MIN) { + // '0' bit + rx[rxlen / 8] |= 0 << (7-(rxlen%8)); + rxlen++; + } + + } else { + LED_C_ON(); + // Capture tag frame (manchester decoding using only falling edges) + if(ra >= HITAG_T_EOF) { +// if (rxlen != 0) { + //DbpString("wierd1?"); +// } + // Capture the T0 periods that have passed since last communication or field drop (reset) + // We always recieve a 'one' first, which has the falling edge after a half period |-_| + response = ra - HITAG_T_TAG_HALF_PERIOD; + + } else if(ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { + // Manchester coding example |-_|_-|-_| (101) + rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); + rxlen++; + rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); + rxlen++; + + } else if(ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { + // Manchester coding example |_-|...|_-|-_| (0...01) + rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); + rxlen++; + // We have to skip this half period at start and add the 'one' the second time + if (bSkip == false) { + rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); + rxlen++; + } + lastbit = !lastbit; + bSkip = !bSkip; + + } else if(ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { + // Manchester coding example |_-|_-| (00) or |-_|-_| (11) + if (tag_sof) { + // Ignore bits that are transmitted during SOF + tag_sof--; + } else { + // bit is same as last bit + rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8)); + rxlen++; + } + } + } + } + } + + // Check if frame was captured + if(rxlen) { + frame_count++; + LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame); + + // Check if we recognize a valid authentication attempt + if (nbytes(rxlen) == 8) { + // Store the authentication attempt + if (auth_table_len < (AUTH_TABLE_LENGTH - 8)) { + memcpy(auth_table + auth_table_len, rx, 8); + auth_table_len += 8; + } + } + + // Reset the received frame and response timing info + memset(rx, 0x00, sizeof(rx)); + response = 0; + reader_frame = false; + lastbit = 1; + bSkip = true; + tag_sof = 4; + overflow = 0; + + LED_B_OFF(); + LED_C_OFF(); + } else { + // Save the timer overflow, will be 0 when frame was received + overflow += (AT91C_BASE_TC1->TC_CV / HITAG_T0); + } + // Reset the frame length + rxlen = 0; + // Reset the timer to restart while-loop that receives frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + } + + LEDsoff(); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(false); + + Dbprintf("frame received: %d",frame_count); + Dbprintf("Authentication Attempts: %d",(auth_table_len / 8)); + } // Hitag2 simulation -void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) { +void SimulateHitag2() { BigBuf_free(); BigBuf_Clear_ext(false); @@ -1092,12 +1336,6 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) { // hitag2 state machine? hitag2_init(); - // copy user supplied emulation data - if (tag_mem_supplied) { - DbpString("Loading hitag2 memory..."); - memcpy((uint8_t *)tag.sectors, data, 48); - } - // printing uint32_t block = 0; for (size_t i = 0; i < 12; i++) { diff --git a/armsrc/hitag2.h b/armsrc/hitag2.h index ec3d0d7f3..ef92f0560 100644 --- a/armsrc/hitag2.h +++ b/armsrc/hitag2.h @@ -1,5 +1,6 @@ //----------------------------------------------------------------------------- // (c) 2012 Roel Verdult +// modified 2021 Iceman // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -15,8 +16,8 @@ #include "hitag.h" void SniffHitag2(void); -void SimulateHitag2(bool tag_mem_supplied, uint8_t *data); +void SimulateHitag2(void); void ReaderHitag(hitag_function htf, hitag_data *htd); void WriterHitag(hitag_function htf, hitag_data *htd, int page); - +void EloadHitag(uint8_t *data, uint16_t len); #endif From 7d83f5de82aaf23663585e17561760507e7c15aa Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 4 Apr 2021 17:08:19 +0200 Subject: [PATCH 149/373] adaptations to lf hitag.. --- armsrc/lfadc.c | 50 ++++++++++++++++++++++++++++++++++++++++++-------- armsrc/lfadc.h | 1 + 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index 1fb1bccde..037481ba7 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -52,9 +52,12 @@ bool lf_test_periods(size_t expected, size_t count) { ////////////////////////////////////////////////////////////////////////////// // Low frequency (LF) adc passthrough functionality ////////////////////////////////////////////////////////////////////////////// -static uint8_t previous_adc_val = 0; +static uint8_t previous_adc_val = 0; //0xFF; static uint8_t adc_avg = 0; +uint8_t get_adc_avg(void) { + return adc_avg; +} void lf_sample_mean(void) { uint8_t periods = 0; uint32_t adc_sum = 0; @@ -66,20 +69,44 @@ void lf_sample_mean(void) { } // division by 32 adc_avg = adc_sum >> 5; + previous_adc_val = adc_avg; if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("LF ADC average %u", adc_avg); } static size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { + +#define LIMIT_DEV 20 + + // timeout limit to 100 000 w/o + uint32_t timeout = 100000; size_t periods = 0; - uint8_t avg_peak = adc_avg + 3, avg_through = adc_avg - 3; + uint8_t avg_peak = adc_avg + LIMIT_DEV; + uint8_t avg_through = adc_avg - LIMIT_DEV; while (BUTTON_PRESS() == false) { + WDT_HIT(); + + timeout--; + if (timeout == 0) { + return 0; + } + + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0x00; + continue; + } + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - volatile uint8_t adc_val = AT91C_BASE_SSC->SSC_RHR; + periods++; + // reset timeout + timeout = 100000; + + volatile uint8_t adc_val = AT91C_BASE_SSC->SSC_RHR; + if (g_logging) logSampleSimple(adc_val); // Only test field changes if state of adc values matter @@ -94,21 +121,28 @@ static size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { } else { // Trigger on a modulation swap by observing an edge change if (rising_edge) { + if ((previous_adc_val > avg_peak) && (adc_val <= previous_adc_val)) { rising_edge = false; return periods; } + } else { + if ((previous_adc_val < avg_through) && (adc_val >= previous_adc_val)) { rising_edge = true; return periods; } + } - } + } } + previous_adc_val = adc_val; - if (periods >= max) return 0; + if (periods >= max) { + return 0; + } } } @@ -169,10 +203,10 @@ void lf_init(bool reader, bool simulate) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); } else { if (simulate) -// FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC); else // Sniff + //FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); } @@ -185,10 +219,10 @@ void lf_init(bool reader, bool simulate) { // When in reader mode, give the field a bit of time to settle. // 313T0 = 313 * 8us = 2504us = 2.5ms Hitag2 tags needs to be fully powered. - if (reader) { +// if (reader) { // 10 ms SpinDelay(10); - } +// } // Steal this pin from the SSP (SPI communication channel with fpga) and use it to control the modulation AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; diff --git a/armsrc/lfadc.h b/armsrc/lfadc.h index 66c6da534..ee2ffbbab 100644 --- a/armsrc/lfadc.h +++ b/armsrc/lfadc.h @@ -17,6 +17,7 @@ extern bool g_logging; +uint8_t get_adc_avg(void); void lf_sample_mean(void); bool lf_test_periods(size_t expected, size_t count); size_t lf_count_edge_periods(size_t max); From e3765a7ec0fa0cae7fb7bfcb42630c6c1aecfac3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Apr 2021 08:14:59 +0200 Subject: [PATCH 150/373] fix coverity CID 317112,CID 317111 --- client/src/cmdlfhitag.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index cdefd8a00..a9f21d4fe 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -339,9 +339,10 @@ static int CmdLFHitagEload(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_LF_HITAG_ELOAD, (uint8_t *)&payload, 2 + dumplen); } else { - PrintAndLogEx(ERR, "error, wrong dump file size. got %u", dumplen); + PrintAndLogEx(ERR, "error, wrong dump file size. got %zu", dumplen); } + free(dump); return PM3_SUCCESS; } From e9df21d3ab428912441a47ea1e343eb2926fe705 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Apr 2021 08:26:17 +0200 Subject: [PATCH 151/373] guard, fix coverity CID 408545 --- client/src/preferences.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/client/src/preferences.c b/client/src/preferences.c index 41b8fc1a6..ccdcd249f 100644 --- a/client/src/preferences.c +++ b/client/src/preferences.c @@ -437,17 +437,19 @@ static void showSavePathState(savePaths_t path_index, prefShowOpt_t opt) { strcpy(s, _RED_("unknown")" save path......"); } - if ((session.defaultPaths[path_index] == NULL) || (strcmp(session.defaultPaths[path_index], "") == 0)) { - PrintAndLogEx(INFO, " %s %s "_WHITE_("not set"), - prefShowMsg(opt), - s - ); - } else { - PrintAndLogEx(INFO, " %s %s "_GREEN_("%s"), - prefShowMsg(opt), - s, - session.defaultPaths[path_index] - ); + if (path_index < spItemCount) { + if ((session.defaultPaths[path_index] == NULL) || (strcmp(session.defaultPaths[path_index], "") == 0)) { + PrintAndLogEx(INFO, " %s %s "_WHITE_("not set"), + prefShowMsg(opt), + s + ); + } else { + PrintAndLogEx(INFO, " %s %s "_GREEN_("%s"), + prefShowMsg(opt), + s, + session.defaultPaths[path_index] + ); + } } } From 753d074c546480d54c830125762bcce759d19ee6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Apr 2021 08:26:46 +0200 Subject: [PATCH 152/373] WIP --- armsrc/hitag2.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index b7db20919..eb232fb05 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -130,8 +130,7 @@ static void hitag2_init(void) { #define HITAG_T_0 20 /* T[0] should be 18..22 */ #define HITAG_T_1_MIN 25 /* T[1] should be 26..30 */ #define HITAG_T_1 30 /* T[1] should be 26..30 */ -//#define HITAG_T_EOF 40 /* T_EOF should be > 36 */ -#define HITAG_T_EOF 40 /* T_EOF should be > 36 */ +#define HITAG_T_EOF 80 /* T_EOF should be > 36 and must be larger than HITAG_T_TAG_CAPTURE_FOUR_HALF */ #define HITAG_T_WAIT_1_MIN 199 /* T_wresp should be 199..206 */ #define HITAG_T_WAIT_2_MIN 90 /* T_wait2 should be at least 90 */ #define HITAG_T_WAIT_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */ From 1b59b38058a079a615e68275787923fa662bbdb0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Apr 2021 08:47:03 +0200 Subject: [PATCH 153/373] fix coverity 314850, and textual changes --- armsrc/spiffs.c | 34 +++++++++++----------------------- armsrc/spiffs.h | 2 +- client/src/cmdflashmemspiffs.c | 11 +++++++++-- 3 files changed, 21 insertions(+), 26 deletions(-) diff --git a/armsrc/spiffs.c b/armsrc/spiffs.c index 8242df9fc..d200eafc7 100644 --- a/armsrc/spiffs.c +++ b/armsrc/spiffs.c @@ -549,17 +549,13 @@ void rdv40_spiffs_safe_print_fsinfo(void) { rdv40_spiffs_fsinfo fsinfo; rdv40_spiffs_getfsinfo(&fsinfo, RDV40_SPIFFS_SAFETY_SAFE); - DbpString(_CYAN_("Flash Memory FileSystem Info (SPIFFS)")); - - - Dbprintf(" Logical Block Size........." _YELLOW_("%d")" bytes", fsinfo.blockSize); - Dbprintf(" Logical Page Size.........." _YELLOW_("%d")" bytes", fsinfo.pageSize); - Dbprintf(""); - Dbprintf(" Max Open Files............." _YELLOW_("%d")" file descriptors", fsinfo.maxOpenFiles); - Dbprintf(" Max Path Length............" _YELLOW_("%d")" chars", fsinfo.maxPathLength); + Dbprintf(" Logical block size......... " _YELLOW_("%d")" bytes", fsinfo.blockSize); + Dbprintf(" Logical page size.......... " _YELLOW_("%d")" bytes", fsinfo.pageSize); + Dbprintf(" Max open files............. " _YELLOW_("%d")" file descriptors", fsinfo.maxOpenFiles); + Dbprintf(" Max path length............ " _YELLOW_("%d")" chars", fsinfo.maxPathLength); DbpString(""); - Dbprintf(" filesystem size used available use% mounted"); - Dbprintf(" spiffs %6d B %6d B %6d B " _YELLOW_("%2d%")" /" + Dbprintf(" Filesystem size used available use% mounted"); + Dbprintf(" spiffs %6d B %6d B %6d B " _YELLOW_("%2d%")" /" , fsinfo.totalBytes , fsinfo.usedBytes , fsinfo.freeBytes @@ -574,20 +570,13 @@ void rdv40_spiffs_safe_print_fsinfo(void) { // maintaining prefix list sorting, unique_checking, THEN outputing precomputed // tree Other solutio nwould be to add directory support to SPIFFS, but that we // dont want, as prefix are way easier and lighter in every aspect. -void rdv40_spiffs_safe_print_tree(uint8_t banner) { - - if (banner) { - DbpString(_CYAN_("Flash Memory FileSystem tree (SPIFFS)")); - Dbprintf("-------------------------------------"); - } - +void rdv40_spiffs_safe_print_tree(void) { int changed = rdv40_spiffs_lazy_mount(); spiffs_DIR d; struct spiffs_dirent e; struct spiffs_dirent *pe = &e; SPIFFS_opendir(&fs, "/", &d); - Dbprintf(" \t \t/"); while ((pe = SPIFFS_readdir(&d, pe))) { char resolvedlink[11 + SPIFFS_OBJ_NAME_LEN]; @@ -601,10 +590,9 @@ void rdv40_spiffs_safe_print_tree(uint8_t banner) { memset(resolvedlink, 0, sizeof(resolvedlink)); } - Dbprintf("[%04x]\t %ibytes \t|-- %s%s", pe->obj_id, pe->size, pe->name, resolvedlink); + Dbprintf("[%04x]\t " _YELLOW_("%i") " B |-- %s%s", pe->obj_id, pe->size, pe->name, resolvedlink); } SPIFFS_closedir(&d); - rdv40_spiffs_lazy_mount_rollback(changed); } @@ -651,7 +639,7 @@ void test_spiffs(void) { int changed = rdv40_spiffs_lazy_mount(); Dbprintf(" Printing tree.............."); - rdv40_spiffs_safe_print_tree(false); + rdv40_spiffs_safe_print_tree(); Dbprintf(" Writing 'I love Proxmark3 RDV4' in a testspiffs.txt"); @@ -660,13 +648,13 @@ void test_spiffs(void) { rdv40_spiffs_write((char *)"testspiffs.txt", (uint8_t *)"I love Proxmark3 RDV4", 21, RDV40_SPIFFS_SAFETY_SAFE); Dbprintf(" Printing tree again......."); - rdv40_spiffs_safe_print_tree(false); + rdv40_spiffs_safe_print_tree(); Dbprintf(" Making a symlink to testspiffs.txt"); rdv40_spiffs_make_symlink((char *)"testspiffs.txt", (char *)"linktotestspiffs.txt", RDV40_SPIFFS_SAFETY_SAFE); Dbprintf(" Printing tree again......."); - rdv40_spiffs_safe_print_tree(false); + rdv40_spiffs_safe_print_tree(); // TODO READBACK, rename,print tree read back, remove, print tree; Dbprintf(" Rollbacking The mount status IF things have changed"); diff --git a/armsrc/spiffs.h b/armsrc/spiffs.h index 8754cb432..520ff8809 100644 --- a/armsrc/spiffs.h +++ b/armsrc/spiffs.h @@ -45,7 +45,7 @@ int rdv40_spiffs_read_as_symlink(char *filename, uint8_t *dst, uint32_t size, RD void write_to_spiffs(const char *filename, uint8_t *src, uint32_t size); void read_from_spiffs(const char *filename, uint8_t *dst, uint32_t size); void test_spiffs(void); -void rdv40_spiffs_safe_print_tree(uint8_t banner); +void rdv40_spiffs_safe_print_tree(void); int rdv40_spiffs_unmount(void); int rdv40_spiffs_mount(void); int rdv40_spiffs_is_symlink(const char *s); diff --git a/client/src/cmdflashmemspiffs.c b/client/src/cmdflashmemspiffs.c index 9409e52ee..3b9214e95 100644 --- a/client/src/cmdflashmemspiffs.c +++ b/client/src/cmdflashmemspiffs.c @@ -39,8 +39,11 @@ int flashmem_spiffs_load(char *destfn, uint8_t *data, size_t datalen) { 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)); + + uint8_t fnlen = MIN(sizeof(payload->fn), strlen(destfn)); + + payload->fnlen = fnlen; + memcpy(payload->fn, destfn, fnlen); payload->bytes_in_packet = bytes_in_packet; memset(payload->data, 0, bytes_in_packet); @@ -158,6 +161,8 @@ static int CmdFlashMemSpiFFSTree(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, true); CLIParserFree(ctx); + + PrintAndLogEx(INFO, "--- " _CYAN_("Flash Memory tree (SPIFFS)") " -----------------"); clearCommandBuffer(); SendCommandNG(CMD_SPIFFS_PRINT_TREE, NULL, 0); return PM3_SUCCESS; @@ -175,6 +180,8 @@ static int CmdFlashMemSpiFFSInfo(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, true); CLIParserFree(ctx); + + PrintAndLogEx(INFO, "--- " _CYAN_("Flash Memory info (SPIFFS)") " -----------------"); clearCommandBuffer(); SendCommandNG(CMD_SPIFFS_PRINT_FSINFO, NULL, 0); return PM3_SUCCESS; From 7e94cf39b4213072021a95f7c6ca708dfda7b5f3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Apr 2021 08:49:15 +0200 Subject: [PATCH 154/373] missed this change --- armsrc/appmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index b0a78ccb1..c64a61cbc 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -2069,7 +2069,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_SPIFFS_PRINT_TREE: { - rdv40_spiffs_safe_print_tree(false); + rdv40_spiffs_safe_print_tree(); break; } case CMD_SPIFFS_PRINT_FSINFO: { From cf287818f3df136911f9a9c7486b53451c83e78d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Apr 2021 09:02:15 +0200 Subject: [PATCH 155/373] fix coverity 308279 --- client/src/cmdhfemrtd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index feb8806e7..dde315418 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1668,7 +1668,7 @@ static int emrtd_parse_ef_sod_hash_algo(uint8_t *data, size_t datalen, int *hash PrintAndLogEx(DEBUG, "trying: %s", hashalg_table[hashi].name); // We're only interested in checking if the length matches to avoid memory shenanigans if (hashalg_table[hashi].descriptorlen != hashalgosetlen) { - PrintAndLogEx(DEBUG, "len mismatch: %i", hashalgosetlen); + PrintAndLogEx(DEBUG, "len mismatch: %zu", hashalgosetlen); continue; } From 8da99277ffc279493845806d7a95206961ce93f9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Apr 2021 09:05:25 +0200 Subject: [PATCH 156/373] fix coverity CID 308278 --- client/src/cmdhfemrtd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index dde315418..2c08ca8a8 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1557,16 +1557,16 @@ static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen) { // ...and I doubt many states are using them. switch (taglist[i + 1]) { case 0x19: - PrintAndLogEx(SUCCESS, "Issuing Authority.....: " _YELLOW_("%.*s"), tagdatalen, tagdata); + PrintAndLogEx(SUCCESS, "Issuing Authority.....: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata); break; case 0x26: emrtd_print_issuance((char *) tagdata, tagdatalen != 4); break; case 0x1b: - PrintAndLogEx(SUCCESS, "Endorsements & Observations: " _YELLOW_("%.*s"), tagdatalen, tagdata); + PrintAndLogEx(SUCCESS, "Endorsements & Observations: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata); break; case 0x1c: - PrintAndLogEx(SUCCESS, "Tax/Exit Requirements.: " _YELLOW_("%.*s"), tagdatalen, tagdata); + PrintAndLogEx(SUCCESS, "Tax/Exit Requirements.: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata); break; case 0x1d: saveFile("FrontOfDocument", tagdata[0] == 0xFF ? ".jpg" : ".jp2", tagdata, tagdatalen); @@ -1578,7 +1578,7 @@ static int emrtd_print_ef_dg12_info(uint8_t *data, size_t datalen) { emrtd_print_personalization_timestamp(tagdata); break; case 0x56: - PrintAndLogEx(SUCCESS, "Serial of Personalization System: " _YELLOW_("%.*s"), tagdatalen, tagdata); + PrintAndLogEx(SUCCESS, "Serial of Personalization System: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata); break; case 0x85: emrtd_print_unknown_timestamp_5f85(tagdata); From ce40c4d067f24ed7c1a692f16d79f36b1a453410 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Apr 2021 12:20:31 +0200 Subject: [PATCH 157/373] hf iclass config - out of bounds check --- client/src/cmdhficlass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 6df780f06..6023e086d 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -3609,7 +3609,7 @@ static int CmdHFiClassConfigCard(const char * Cmd) { print_config_cards(); } - if (idx >= 0) { + if (idx > -1 && idx < 14) { const iclass_config_card_item_t *item = get_config_card_item(idx); print_config_card(item); } From 5ee8c9c75e04c416728fc3157ce82b39d80027d6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Apr 2021 12:21:56 +0200 Subject: [PATCH 158/373] text --- client/src/cmdhficlass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 6023e086d..0d785d8df 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -207,7 +207,7 @@ static void print_config_card(const iclass_config_card_item_t *o) { static void generate_config_card(const iclass_config_card_item_t *o) { if (check_config_card(o)) { - + PrintAndLogEx(INFO, "to be implemented..."); } } From 2a9d064fd6fb53b1f628fc7d319b3fa9edda6382 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Apr 2021 12:24:54 +0200 Subject: [PATCH 159/373] hf emrtd, maybe this makes coverity more calm --- client/src/cmdhfemrtd.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 2c08ca8a8..df10bc432 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -262,13 +262,22 @@ static int emrtd_get_asn1_data_length(uint8_t *datain, int datainlen, int offset // https://wf.lavatech.top/ave-but-random/emrtd-data-quirks#EF_SOD return datainlen; } else if (lenfield == 0x81) { - return ((int) * (datain + offset + 1)); + int tmp = (*(datain + offset + 1) << 8); + return tmp; + //return ((int) * (datain + offset + 1)); } else if (lenfield == 0x82) { - return ((int) * (datain + offset + 1) << 8) | ((int) * (datain + offset + 2)); + int tmp = (*(datain + offset + 1) << 8); + tmp |= *(datain + offset + 2); + return tmp; + //return ((int) * (datain + offset + 1) << 8) | ((int) * (datain + offset + 2)); } else if (lenfield == 0x83) { - return (((int) * (datain + offset + 1) << 16) | ((int) * (datain + offset + 2)) << 8) | ((int) * (datain + offset + 3)); + int tmp = (*(datain + offset + 1) << 16); + tmp |= (*(datain + offset + 2) << 8); + tmp |= *(datain + offset + 3); + return tmp; + //return (((int) * (datain + offset + 1) << 16) | ((int) * (datain + offset + 2)) << 8) | ((int) * (datain + offset + 3)); } - return false; + return 0; } static int emrtd_get_asn1_field_length(uint8_t *datain, int datainlen, int offset) { @@ -284,7 +293,7 @@ static int emrtd_get_asn1_field_length(uint8_t *datain, int datainlen, int offse } else if (lenfield == 0x83) { return 4; } - return false; + return 0; } static void des_encrypt_ecb(uint8_t *key, uint8_t *input, uint8_t *output) { @@ -839,12 +848,13 @@ static int emrtd_dump_ef_sod(uint8_t *file_contents, size_t file_length, const c if (fieldlen + 1 > EMRTD_MAX_FILE_SIZE) { PrintAndLogEx(ERR, "error (emrtd_dump_ef_sod) fieldlen out-of-bounds"); - return PM3_SUCCESS; + return PM3_EOUTOFBOUND; } char *filepath = calloc(strlen(path) + 100, sizeof(char)); if (filepath == NULL) return PM3_EMALLOC; + strcpy(filepath, path); strncat(filepath, PATHSEP, 2); strcat(filepath, dg_table[EF_SOD].filename); From 372a6958fa41cdd8607032b502cc3f61541d4116 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 5 Apr 2021 19:33:25 +0200 Subject: [PATCH 160/373] cppchecker fix, we can simplify test meanwhile --- client/src/loclass/hash1_brute.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/loclass/hash1_brute.c b/client/src/loclass/hash1_brute.c index 49f2cd3de..2f2842b2f 100644 --- a/client/src/loclass/hash1_brute.c +++ b/client/src/loclass/hash1_brute.c @@ -29,7 +29,8 @@ static void calc_score(uint8_t *csn, uint8_t *k) { // goodvals[k[i]] = 1; // } - else if (k[i] >= 16) { +// else if (k[i] >= 16) { + else { badscore++; badval = k[i]; } From 30a10b266b1168661a144f3b3c7d474e17b7e11f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 6 Apr 2021 23:37:45 +0200 Subject: [PATCH 161/373] fix #1234 - cliparse allow empty line, loop now user interuptable --- armsrc/iso15693.c | 10 ++++------ client/src/cmdhf15.c | 38 +++++++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 66539c807..9ead4c117 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -1853,7 +1853,7 @@ void BruteforceIso15693Afi(uint32_t speed) { Dbprintf("NoAFI UID = %s", iso15693_sprintUID(NULL, recv + 2)); } else { DbpString("Failed to select card"); - reply_ng(CMD_ACK, PM3_ESOFT, NULL, 0); + reply_ng(CMD_HF_ISO15693_FINDAFI, PM3_ESOFT, NULL, 0); switch_off(); return; } @@ -1881,10 +1881,8 @@ void BruteforceIso15693Afi(uint32_t speed) { Dbprintf("AFI = %i UID = %s", i, iso15693_sprintUID(NULL, recv + 2)); } - aborted = BUTTON_PRESS(); - + aborted = BUTTON_PRESS() && data_available(); if (aborted) { - DbpString("button pressed, aborting.."); break; } } @@ -1893,9 +1891,9 @@ void BruteforceIso15693Afi(uint32_t speed) { switch_off(); if (aborted) { - reply_ng(CMD_ACK, PM3_EOPABORTED, NULL, 0); + reply_ng(CMD_HF_ISO15693_FINDAFI, PM3_EOPABORTED, NULL, 0); } else { - reply_ng(CMD_ACK, PM3_SUCCESS, NULL, 0); + reply_ng(CMD_HF_ISO15693_FINDAFI, PM3_SUCCESS, NULL, 0); } } diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 1fd1fb034..b69d1447c 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -35,6 +35,7 @@ #include "cmddata.h" // getsamples #include "fileutils.h" // savefileEML #include "cliparser.h" +#include "util_posix.h" // msleep #define FrameSOF Iso15693FrameSOF #define Logic0 Iso15693Logic0 @@ -1151,28 +1152,43 @@ static int CmdHF15FindAfi(const char *Cmd) { arg_param_begin, arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, false); + CLIExecWithReturn(ctx, Cmd, argtable, true); CLIParserFree(ctx); - PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); - + PrintAndLogEx(INFO, "click " _GREEN_("pm3 button") " or press " _GREEN_("Enter") " to exit"); clearCommandBuffer(); PacketResponseNG resp; SendCommandMIX(CMD_HF_ISO15693_FINDAFI, strtol(Cmd, NULL, 0), 0, 0, NULL, 0); - uint32_t timeout = 0; - while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - timeout++; + for (;;) { + + if (kbd_enter_pressed()) { + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + PrintAndLogEx(DEBUG, "User aborted"); + msleep(300); + break; + } + + uint32_t timeout = 0; + if (WaitForResponseTimeout(CMD_HF_ISO15693_FINDAFI, &resp, 2000)){ + if (resp.status == PM3_EOPABORTED) { + PrintAndLogEx(DEBUG, "Button pressed, user aborted"); + break; + } + } else { + timeout++; + + // should be done in about 2 minutes + if (timeout > 180) { + PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting..."); + break; + } - // should be done in about 2 minutes - if (timeout > 180) { - PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting..."); - DropField(); - return PM3_ETIMEOUT; } } DropField(); + PrintAndLogEx(INFO, "Done"); return resp.status; // PM3_EOPABORTED or PM3_SUCCESS } From 750db71f1585452514f67d106caa783ff405fd3c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 6 Apr 2021 23:43:01 +0200 Subject: [PATCH 162/373] text --- CHANGELOG.md | 1 + README.md | 28 +++------------------------- 2 files changed, 4 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1763dfbe..888617fbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fixed `hf 15 findafi` - cliparser bug, and loop is user interruptable (@iceman1001) - Added `hf mf wipe` - takes a keyfile and wipes a MFC to default values (@iceman1001) - Changed `pm3 shell` - now prioritise USB connections in WSL1 (@gator96100) - Added `hf mf restore -w` - now supports usage of specified keyfile to authenticate with instead of default FFFFFF key (@iceman1001) diff --git a/README.md b/README.md index cf6cd7ecd..149738cff 100644 --- a/README.md +++ b/README.md @@ -47,9 +47,7 @@ See the instruction links in the tables above to build, flash and run for your P In order to build this repo for generic Proxmark3 platforms we urge you to read [Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md) With generic Proxmark3 platforms we mean: - - RDV1 - - RDV2 - - RDV3 easy + - RDV1, RDV2, RDV3 easy - Proxmark Evolution (needs extra care) - Radiowar black PCB version - Ryscorp green PCB version @@ -68,8 +66,7 @@ On the hardware side: * added FPC connector On the software side: - -quite a lot, see the [Changelog file](CHANGELOG.md) which we try to keep updated. +see the [Changelog file](CHANGELOG.md) which we try to keep updated. ## Development @@ -88,18 +85,13 @@ This repo compiles nicely on - [ RRG / Iceman repo based ubuntu 18.04 container ](https://hub.docker.com/r/secopsconsult/proxmark3) - [ Iceman fork based container v1.7 ](https://hub.docker.com/r/iceman1001/proxmark3/) -Hardware to run client on - - PC - - Android Phone - - Raspberry Pi, Raspberry Pi Zero - - Nvidia Jetson Nano ## Precompiled binaries We don't maintain any precompiled binaries in this repo. There is community effort over at the Proxmark3 forum where [@gator96100](https://github.com/gator96100) has set up a AWS bucket with precompiled Proxspace (Mingw) binaries which is recompiled every night and with that also up-to-date. We link to these files here as to make it easier for users. _If you use his pre-compiled Proxspace binaries do consider buy him a coffee for his efforts. Remember nothing says thank you as much as a donation._ -If you are having troubles with these files, contact package maintainer [@gator96100](https://github.com/gator96100) and read the [homepage of his proxmark builds](https://www.proxmarkbuilds.org/) or read the [sticky thread at forum](http://www.proxmark.org/forum/viewtopic.php?pid=24763#p24763) where known issues has been documented with regards to the precompiled builds. +If you are having troubles with these files, contact package maintainer [@gator96100](https://github.com/gator96100) and read the [homepage of his proxmark builds](https://www.proxmarkbuilds.org/) or read the [sticky thread at forum](http://www.proxmark.org/forum/viewtopic.php?pid=24763#p24763) ### Proxmark3 RDV4 devices - [Precompiled builds for RDV40 dedicated x64](https://www.proxmarkbuilds.org/#rdv40-64/) @@ -130,20 +122,6 @@ Next place to visit is the [Proxmark3 Forum](http://www.proxmark.org/forum/index - [Proxmark3 forum](http://www.proxmark.org/forum/index.php) -### Youtube channels -Iceman has quite a few videos on his channel and Quentyn has risen up the last year with good informative videos. We suggest you check them out and smash that subscribe buttons! - - - [Iceman channel](https://www.youtube.com/c/ChrisHerrmann1001) - - [Quentyn Taylor](https://www.youtube.com/channel/UCL91C3IZDv3wfj2ABhdRIrw) - - [Hacker warehouse channel](https://www.youtube.com/channel/UCimS6P854cQ23j6c_xst7EQ) - -_if you think of some more good youtube channels to be on this list, let us know!_ - -## Cheat sheet - -You can enjoy a [command cheat sheet](/doc/cheatsheet.md) and we are trying to keep it updated. -[Thanks to Alex Dib!](https://github.com/scund00r) - ## Maintainers ( package, distro ) To all distro, package maintainers, we tried to make your life easier. From 501b31cf453596023cb0a79ebf133810f48eb473 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 6 Apr 2021 23:55:24 +0200 Subject: [PATCH 163/373] fix coverity #308236 --- client/src/cmdhfemrtd.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index df10bc432..ac1d713e7 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1187,11 +1187,12 @@ static void emrtd_print_legal_sex(char *legal_sex) { static int emrtd_mrz_determine_length(char *mrz, int offset, int max_length) { int i; - for (i = max_length; i >= 0; i--) { - if (mrz[offset + i - 1] != '<') { + for (i = max_length - 1; i >= 0; i--) { + if (mrz[offset + i] != '<') { break; } } + // if not found, it will return -1 return i; } @@ -1216,6 +1217,9 @@ static void emrtd_mrz_replace_pad(char *data, int datalen, char newchar) { static void emrtd_print_optional_elements(char *mrz, int offset, int length, bool verify_check_digit) { int i = emrtd_mrz_determine_length(mrz, offset, length); + if (i == -1){ + return; + } // Only print optional elements if they're available if (i != 0) { @@ -1229,6 +1233,9 @@ static void emrtd_print_optional_elements(char *mrz, int offset, int length, boo static void emrtd_print_document_number(char *mrz, int offset) { int i = emrtd_mrz_determine_length(mrz, offset, 9); + if (i == -1) { + return; + } PrintAndLogEx(SUCCESS, "Document Number.......: " _YELLOW_("%.*s"), i, mrz + offset); @@ -1240,6 +1247,9 @@ static void emrtd_print_document_number(char *mrz, int offset) { static void emrtd_print_name(char *mrz, int offset, int max_length, bool localized) { char final_name[100] = { 0x00 }; int namelen = emrtd_mrz_determine_length(mrz, offset, max_length); + if (namelen == -1) { + return; + } int sep = emrtd_mrz_determine_separator(mrz, offset, namelen); // Account for mononyms From 51ec7c2178ff421618aeadb75fce27de9e861bba Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 6 Apr 2021 23:57:25 +0200 Subject: [PATCH 164/373] fix coverity #308283 --- client/src/cmdhfemrtd.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index ac1d713e7..ab2e3d896 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1502,37 +1502,37 @@ static int emrtd_print_ef_dg11_info(uint8_t *data, size_t datalen) { emrtd_print_name((char *) tagdata, 0, tagdatalen, false); break; case 0x10: - PrintAndLogEx(SUCCESS, "Personal Number.......: " _YELLOW_("%.*s"), tagdatalen, tagdata); + PrintAndLogEx(SUCCESS, "Personal Number.......: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata); break; case 0x11: // TODO: acc for < separation - PrintAndLogEx(SUCCESS, "Place of Birth........: " _YELLOW_("%.*s"), tagdatalen, tagdata); + PrintAndLogEx(SUCCESS, "Place of Birth........: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata); break; case 0x42: // TODO: acc for < separation - PrintAndLogEx(SUCCESS, "Permanent Address.....: " _YELLOW_("%.*s"), tagdatalen, tagdata); + PrintAndLogEx(SUCCESS, "Permanent Address.....: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata); break; case 0x12: - PrintAndLogEx(SUCCESS, "Telephone.............: " _YELLOW_("%.*s"), tagdatalen, tagdata); + PrintAndLogEx(SUCCESS, "Telephone.............: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata); break; case 0x13: - PrintAndLogEx(SUCCESS, "Profession............: " _YELLOW_("%.*s"), tagdatalen, tagdata); + PrintAndLogEx(SUCCESS, "Profession............: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata); break; case 0x14: - PrintAndLogEx(SUCCESS, "Title.................: " _YELLOW_("%.*s"), tagdatalen, tagdata); + PrintAndLogEx(SUCCESS, "Title.................: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata); break; case 0x15: - PrintAndLogEx(SUCCESS, "Personal Summary......: " _YELLOW_("%.*s"), tagdatalen, tagdata); + PrintAndLogEx(SUCCESS, "Personal Summary......: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata); break; case 0x16: saveFile("ProofOfCitizenship", tagdata[0] == 0xFF ? ".jpg" : ".jp2", tagdata, tagdatalen); break; case 0x17: // TODO: acc for < separation - PrintAndLogEx(SUCCESS, "Other valid TDs nums..: " _YELLOW_("%.*s"), tagdatalen, tagdata); + PrintAndLogEx(SUCCESS, "Other valid TDs nums..: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata); break; case 0x18: - PrintAndLogEx(SUCCESS, "Custody Information...: " _YELLOW_("%.*s"), tagdatalen, tagdata); + PrintAndLogEx(SUCCESS, "Custody Information...: " _YELLOW_("%.*s"), (int)tagdatalen, tagdata); break; case 0x2b: emrtd_print_dob((char *) tagdata, 0, true, tagdatalen != 4); From f53de10c60d7554795bec82e6390aecc6ddbeff9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 7 Apr 2021 01:19:28 +0200 Subject: [PATCH 165/373] hf 15 findafi, bad loop var --- client/src/cmdhf15.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index b69d1447c..e24af1671 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1160,6 +1160,7 @@ static int CmdHF15FindAfi(const char *Cmd) { PacketResponseNG resp; SendCommandMIX(CMD_HF_ISO15693_FINDAFI, strtol(Cmd, NULL, 0), 0, 0, NULL, 0); + uint32_t timeout = 0; for (;;) { if (kbd_enter_pressed()) { @@ -1169,7 +1170,6 @@ static int CmdHF15FindAfi(const char *Cmd) { break; } - uint32_t timeout = 0; if (WaitForResponseTimeout(CMD_HF_ISO15693_FINDAFI, &resp, 2000)){ if (resp.status == PM3_EOPABORTED) { PrintAndLogEx(DEBUG, "Button pressed, user aborted"); @@ -1189,7 +1189,7 @@ static int CmdHF15FindAfi(const char *Cmd) { DropField(); PrintAndLogEx(INFO, "Done"); - return resp.status; // PM3_EOPABORTED or PM3_SUCCESS + return PM3_SUCCESS; } // Writes the AFI (Application Family Identifier) of a card From 871820f8f7981ea2012c8462655dc734ffa6c29a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 7 Apr 2021 09:13:45 +0200 Subject: [PATCH 166/373] fixing padding @anon --- client/src/mifare/desfire_crypto.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 83e27e7b6..d13563344 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -652,8 +652,7 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes free(edata); break; - case MDCM_ENCIPHERED: - (*nbytes)--; + case MDCM_ENCIPHERED: { bool verified = false; int crc_pos = 0x00; int end_crc_pos = 0x00; @@ -702,11 +701,13 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes if (res != NULL) { memcpy(res, data, *nbytes); - crc_pos = (*nbytes) - 16 - 3; - if (crc_pos < 0) { - /* Single block */ - crc_pos = 0; + size_t padding_start_pos = *nbytes - 1; + while (padding_start_pos > 0 && ((uint8_t *) res)[padding_start_pos] == 0x00) { + padding_start_pos--; } + //TODO: Add support for cases where there is no padding. Uncommon but possible. + crc_pos = padding_start_pos - 4; + memcpy((uint8_t *) res + crc_pos + 1, (uint8_t *) res + crc_pos, *nbytes - crc_pos); ((uint8_t *) res)[crc_pos] = 0x00; crc_pos++; @@ -747,6 +748,7 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes ((uint8_t *)data)[(*nbytes)++] = 0x00; break; case AS_NEW: + *nbytes = crc_pos - 1; /* The status byte was already before the CRC */ break; } @@ -775,6 +777,7 @@ void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes } break; + } default: PrintAndLogEx(ERR, "Unknown communication settings"); *nbytes = -1; From ac0ad24bfe6236fb0d2344de9718e2d03cb6f585 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 7 Apr 2021 12:32:47 +0200 Subject: [PATCH 167/373] hf 15 findafi, client side now breaks when finished --- client/src/cmdhf15.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index e24af1671..189002d1a 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1145,7 +1145,8 @@ static int CmdHF15Sim(const char *Cmd) { static int CmdHF15FindAfi(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf 15 findafi", - "This command attempts to brute force AFI of an ISO15693 tag\n", + "This command attempts to brute force AFI of an ISO15693 tag\n" + "Estimated execution time is around 2 minutes", "hf 15 findafi"); void *argtable[] = { @@ -1173,18 +1174,16 @@ static int CmdHF15FindAfi(const char *Cmd) { if (WaitForResponseTimeout(CMD_HF_ISO15693_FINDAFI, &resp, 2000)){ if (resp.status == PM3_EOPABORTED) { PrintAndLogEx(DEBUG, "Button pressed, user aborted"); - break; } - } else { - timeout++; - - // should be done in about 2 minutes - if (timeout > 180) { - PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting..."); - break; - } - + break; } + + // should be done in about 2 minutes + if (timeout > 180) { + PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting..."); + break; + } + timeout++; } DropField(); From e223258aa25a83671c7fe210c9903dde05586026 Mon Sep 17 00:00:00 2001 From: Ryan Saridar <8403417+VortixDev@users.noreply.github.com> Date: Wed, 7 Apr 2021 22:17:57 +0100 Subject: [PATCH 168/373] Fix error typo --- client/src/mifare/mifare4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/mifare/mifare4.c b/client/src/mifare/mifare4.c index 18b532349..e12885252 100644 --- a/client/src/mifare/mifare4.c +++ b/client/src/mifare/mifare4.c @@ -179,7 +179,7 @@ int MifareAuth4(mf4Session_t *mf4session, uint8_t *keyn, uint8_t *key, bool acti uint8_t cmd1[] = {0x70, keyn[1], keyn[0], 0x00}; int res = ExchangeRAW14a(cmd1, sizeof(cmd1), activateField, true, data, sizeof(data), &datalen, silentMode); if (res) { - if (!silentMode) PrintAndLogEx(ERR, "Exchande raw error: %d", res); + if (!silentMode) PrintAndLogEx(ERR, "Exchange raw error: %d", res); if (dropFieldIfError) DropField(); return 2; } @@ -223,7 +223,7 @@ int MifareAuth4(mf4Session_t *mf4session, uint8_t *keyn, uint8_t *key, bool acti res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, true, data, sizeof(data), &datalen, silentMode); if (res) { - if (!silentMode) PrintAndLogEx(ERR, "Exchande raw error: %d", res); + if (!silentMode) PrintAndLogEx(ERR, "Exchange raw error: %d", res); if (dropFieldIfError) DropField(); return 4; } From 6f9a60f5214f0fe61f2a7b32a08f38bb9609bc27 Mon Sep 17 00:00:00 2001 From: Ryan Saridar <8403417+VortixDev@users.noreply.github.com> Date: Wed, 7 Apr 2021 22:56:21 +0100 Subject: [PATCH 169/373] Fix swapped DESELECT and WTX annotations --- client/src/cmdhflist.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhflist.c b/client/src/cmdhflist.c index d4dcb892f..278928d08 100644 --- a/client/src/cmdhflist.c +++ b/client/src/cmdhflist.c @@ -743,10 +743,10 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { // S-block 11xxx010 if ((cmd[0] & 0xC0) && (cmdsize == 3)) { switch ((cmd[0] & 0x30)) { - case 0x30: + case 0x00: snprintf(exp, size, "S-block DESELECT"); break; - case 0x00: + case 0x30: snprintf(exp, size, "S-block WTX"); break; default: From af2ba79810dfbba770b760f6921f06f32477ed69 Mon Sep 17 00:00:00 2001 From: Ryan Saridar <8403417+VortixDev@users.noreply.github.com> Date: Wed, 7 Apr 2021 22:57:06 +0100 Subject: [PATCH 170/373] Update the changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 888617fbd..ae88615f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fix swapped DESELECT and WTX annotations (@VortixDev) - Fixed `hf 15 findafi` - cliparser bug, and loop is user interruptable (@iceman1001) - Added `hf mf wipe` - takes a keyfile and wipes a MFC to default values (@iceman1001) - Changed `pm3 shell` - now prioritise USB connections in WSL1 (@gator96100) From d6d984a995daf82fc6c2ac2c5119b07a70a2996b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 8 Apr 2021 08:55:26 +0200 Subject: [PATCH 171/373] text --- README.md | 70 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 149738cff..d9ac828de 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,10 @@ | ------------------- |:-------------------:| -------------------:| |[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) | -|| **[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)| +|[Maintainers](#maintainers--package-distro-)| **[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)| +|[Precompiled binaries](#precompiled-binaries)|[Blue shark manual](/doc/bt_manual_v10.md) || +|[Donations](#donations)||[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)**|[T5577 Introduction Guide](/doc/T5577_Guide.md)| @@ -59,39 +59,58 @@ With generic Proxmark3 platforms we mean: ## What has changed? -On the hardware side: - - * added flash memory 256kb. +Proxmark3 RDV4 hardware modifications: + * added flash memory 256kb * added smart card module * added FPC connector + * improved antennas, swappable, multi Q factor for LF + * tiny PCB form factor + * ABS case + +This repo vs official Proxmark3 repo: +see the [Changelog file](CHANGELOG.md) which we try to keep updated. In short this repo gives you an complete different user experience when it comes to Proxmark3. + * richer CLI with use of colors / emojis + * help text system implemented everywhere + * hints system + * user preference settings + * extensive testing with continues built systems and static analyse tools like + * [coverity scan](https://scan.coverity.com/projects/proxmark3-rrg-iceman-repo/) + * cppchecker + * CLANG + * auto detection of serial ports and seamless intergration with bluetooth addon + * reconnect to device + * -On the software side: -see the [Changelog file](CHANGELOG.md) which we try to keep updated. ## Development > ⚠ **Note**: This is a bleeding edge repository. The maintainers actively is working out of this repository and will be periodically re-structuring the code to make it easier to comprehend, navigate, build, test, and contribute to, so **DO expect significant changes to code layout on a regular basis**. +> 👉 **Remember!** If you intend to contribute to the code, please read the [coding style notes](HACKING.md) first. +We usually merge your contributions fast since we do like the idea of getting a functionality in the Proxmark3 and weed out the bugs afterwards. + +The [public roadmap](https://github.com/RfidResearchGroup/proxmark3/wiki/Public-Roadmap) is an excellent start to read if you are interesting in contributing. + + +## Supported operative systems This repo compiles nicely on - - Proxspace v3.x - - [latest release v3.8](https://github.com/Gator96100/ProxSpace/releases) - - Windows/mingw environment with Qt5.6.1 & GCC 4.9 - - Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, Nethunter, Archlinux, Fedora, Debian - - Rasbian + - WSL1 on Windows 10 + - Proxspace v3.8 [release v3.8](https://github.com/Gator96100/ProxSpace/releases) + - Windows/mingw environment + - Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, Nethunter, Archlinux, Fedora, Debian, Rasbian - Android / Termux - Mac OS X / Homebrew / Apple Silicon M1 - - WSL1 on Windows 10 - Docker container - [ RRG / Iceman repo based ubuntu 18.04 container ](https://hub.docker.com/r/secopsconsult/proxmark3) - [ Iceman fork based container v1.7 ](https://hub.docker.com/r/iceman1001/proxmark3/) ## Precompiled binaries -We don't maintain any precompiled binaries in this repo. There is community effort over at the Proxmark3 forum where [@gator96100](https://github.com/gator96100) has set up a AWS bucket with precompiled Proxspace (Mingw) binaries which is recompiled every night and with that also up-to-date. We link to these files here as to make it easier for users. +We don't maintain any precompiled binaries in this repo. There is community effort over at the Proxmark3 forum where package maintainer [@gator96100](https://github.com/gator96100) has set up a AWS bucket with precompiled Proxspace (Mingw) binaries which is recompiled every night and with that also up-to-date. We link to these files here as to make it easier for users. _If you use his pre-compiled Proxspace binaries do consider buy him a coffee for his efforts. Remember nothing says thank you as much as a donation._ -If you are having troubles with these files, contact package maintainer [@gator96100](https://github.com/gator96100) and read the [homepage of his proxmark builds](https://www.proxmarkbuilds.org/) or read the [sticky thread at forum](http://www.proxmark.org/forum/viewtopic.php?pid=24763#p24763) +If you are having troubles with these files, we suggest to read the [homepage of his proxmark builds](https://www.proxmarkbuilds.org/) or read the [sticky thread at forum](http://www.proxmark.org/forum/viewtopic.php?pid=24763#p24763) ### Proxmark3 RDV4 devices - [Precompiled builds for RDV40 dedicated x64](https://www.proxmarkbuilds.org/#rdv40-64/) @@ -101,21 +120,8 @@ If you are having troubles with these files, contact package maintainer [@gator9 - [Precompiled builds for RRG / Iceman repository x64](https://www.proxmarkbuilds.org/#rrg_other-64/) -## Roadmap -The [public roadmap](https://github.com/RfidResearchGroup/proxmark3/wiki/Public-Roadmap) is an excellent start to read if you are interesting in contributing. - -> 👉 **Remember!** If you intend to contribute to the code, please read the [coding style notes](HACKING.md) first. -We usually merge your contributions fast since we do like the idea of getting a functionality in the Proxmark3 and weed out the bugs afterwards. - - -## Issues & Troubleshooting -Please search the [issues](https://github.com/rfidresearchgroup/proxmark3/issues) page here and see if your issue is listed in the first instance. -Read the [Troubleshooting guide](/doc/md/Installation_Instructions/Troubleshooting.md) to weed out most known problems. - -Next place to visit is the [Proxmark3 Forum](http://www.proxmark.org/forum/index.php). - - -### Offical channels +## Offical channels +Where do you find the community? - [RFID Hacking community discord server](https://discord.gg/QfPvGFRQxH) - [Proxmark3 IRC channel](http://webchat.freenode.net/?channels=#proxmark3) - [Proxmark3 sub reddit](https://www.reddit.com/r/proxmark3/) @@ -135,7 +141,7 @@ The official PM3-GUI from Gaucho will not work. Not to mention is quite old and - [Proxmark3 Universal GUI](https://github.com/burma69/PM3UniversalGUI) will work more or less. -- [Proxmark3 GUI crosscompiled](https://github.com/wh201906/Proxmark3GUI/) which is recently updated and claims to support latest source of this repo. Give it a spin and let us know how it works for you. +- [Proxmark3 GUI crosscompiled](https://github.com/wh201906/Proxmark3GUI/) which is recently updated and claims to support latest source of this repo. # Donations From 4fb28e5149d96c920abfabfaf95172d024328704 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 8 Apr 2021 09:02:37 +0200 Subject: [PATCH 172/373] text --- README.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index d9ac828de..a22b5fac1 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ |[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) | |[Maintainers](#maintainers--package-distro-)| **[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)| -|[Precompiled binaries](#precompiled-binaries)|[Blue shark manual](/doc/bt_manual_v10.md) || +|[Pre-compiled binaries](#precompiled-binaries)|[Blue shark manual](/doc/bt_manual_v10.md) || |[Donations](#donations)||[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)| @@ -39,19 +39,18 @@ |[Notes on Color usage](/doc/colors_notes.md)|[Makefile vs CMake](/doc/md/Development/Makefile-vs-CMake.md)|[Notes on Cloner guns](/doc/cloner_notes.md)| |[Notes on cliparser usage](/doc/cliparser.md)|[Notes on clocks](/doc/clocks.md)|| - -## Build for Proxmark3 RDV4 +# How to build? +## Proxmark3 RDV4 See the instruction links in the tables above to build, flash and run for your Proxmark3 RDV4 device. -## Build for generic Proxmark3 platforms +## Generic Proxmark3 platforms In order to build this repo for generic Proxmark3 platforms we urge you to read [Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md) With generic Proxmark3 platforms we mean: - RDV1, RDV2, RDV3 easy - Proxmark Evolution (needs extra care) + - Ryscorp green PCB version, Pm3 Pro - Radiowar black PCB version - - Ryscorp green PCB version - - Ryscorp Pm3Pro - VX - numerous Chinese adapted versions of the RDV3 easy (kkmoon, pisworks etc) @@ -63,7 +62,10 @@ Proxmark3 RDV4 hardware modifications: * added flash memory 256kb * added smart card module * added FPC connector - * improved antennas, swappable, multi Q factor for LF + * improved antennas + * swappable + * LF Q factor switch + * LF 125/134 freqency switch * tiny PCB form factor * ABS case @@ -79,7 +81,6 @@ see the [Changelog file](CHANGELOG.md) which we try to keep updated. In short th * CLANG * auto detection of serial ports and seamless intergration with bluetooth addon * reconnect to device - * ## Development @@ -106,11 +107,7 @@ This repo compiles nicely on ## Precompiled binaries -We don't maintain any precompiled binaries in this repo. There is community effort over at the Proxmark3 forum where package maintainer [@gator96100](https://github.com/gator96100) has set up a AWS bucket with precompiled Proxspace (Mingw) binaries which is recompiled every night and with that also up-to-date. We link to these files here as to make it easier for users. - -_If you use his pre-compiled Proxspace binaries do consider buy him a coffee for his efforts. Remember nothing says thank you as much as a donation._ - -If you are having troubles with these files, we suggest to read the [homepage of his proxmark builds](https://www.proxmarkbuilds.org/) or read the [sticky thread at forum](http://www.proxmark.org/forum/viewtopic.php?pid=24763#p24763) +We don't maintain any precompiled binaries in this repo. There is community effort over at the Proxmark3 forum where package maintainer [@gator96100](https://github.com/gator96100) has set up a AWS bucket with precompiled Proxspace (Mingw) binaries which is recompiled every night and with that also up-to-date. We link to these files here as to make it easier for users. If you are having troubles with these files, we suggest to read the [homepage of his proxmark builds](https://www.proxmarkbuilds.org/) or read the [sticky thread at forum](http://www.proxmark.org/forum/viewtopic.php?pid=24763#p24763) ### Proxmark3 RDV4 devices - [Precompiled builds for RDV40 dedicated x64](https://www.proxmarkbuilds.org/#rdv40-64/) @@ -146,5 +143,8 @@ The official PM3-GUI from Gaucho will not work. Not to mention is quite old and # Donations -Nothing says thank you as much as a donation. So if you feel the love, do feel free to become a [Iceman patron](https://www.patreon.com/iceman1001) +Nothing says thank you as much as a donation. +If you feel the love, do feel free to become a [Iceman patron](https://www.patreon.com/iceman1001). + +If you are using @gator96100 's Proxspace with pre-compiled binaries do consider buy him a coffee for his efforts. From 8a05a4d1d7c24b49caa94bb72f5ff037a0ab8718 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 8 Apr 2021 09:34:11 +0200 Subject: [PATCH 173/373] smart raw - now use NG.\nhf iclass config - added more support for keyrollning (WIP)\n --- armsrc/Standalone/hf_iceclass.c | 6 +- armsrc/appmain.c | 2 +- armsrc/i2c.c | 71 ++++---- armsrc/i2c.h | 4 +- armsrc/iclass.c | 22 +-- armsrc/iclass.h | 4 +- client/src/cmdhficlass.c | 296 ++++++++++++++++++++++++-------- client/src/cmdhficlass.h | 5 +- client/src/cmdsmartcard.c | 271 +++++++++++++++++------------ client/src/cmdsmartcard.h | 2 +- client/src/fileutils.c | 4 +- common/cardhelper.c | 13 +- include/mifare.h | 18 -- include/pm3_cmd.h | 29 +++- 14 files changed, 485 insertions(+), 262 deletions(-) diff --git a/armsrc/Standalone/hf_iceclass.c b/armsrc/Standalone/hf_iceclass.c index bbebcab6e..ee34b98e8 100644 --- a/armsrc/Standalone/hf_iceclass.c +++ b/armsrc/Standalone/hf_iceclass.c @@ -109,7 +109,7 @@ static bool have_aa2(void) { return memcmp(aa2_key, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8); } -static uint8_t get_pagemap(const picopass_hdr *hdr) { +static uint8_t get_pagemap(const picopass_hdr_t *hdr) { return (hdr->conf.fuses & (FUSE_CRYPT0 | FUSE_CRYPT1)) >> 3; } @@ -322,7 +322,7 @@ static int reader_dump_mode(void) { set_tracing(false); - picopass_hdr *hdr = (picopass_hdr *)card_data; + picopass_hdr_t *hdr = (picopass_hdr_t *)card_data; // select tag. uint32_t eof_time = 0; @@ -458,7 +458,7 @@ static int dump_sim_mode(void) { set_tracing(false); - picopass_hdr *hdr = (picopass_hdr *)card_data; + picopass_hdr_t *hdr = (picopass_hdr_t *)card_data; // select tag. uint32_t eof_time = 0; diff --git a/armsrc/appmain.c b/armsrc/appmain.c index c64a61cbc..7c1bde05b 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1746,7 +1746,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_SMART_RAW: { - SmartCardRaw(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); + SmartCardRaw((smart_card_raw_t*)packet->data.asBytes); break; } case CMD_SMART_UPLOAD: { diff --git a/armsrc/i2c.c b/armsrc/i2c.c index 49136d364..dab9108cc 100644 --- a/armsrc/i2c.c +++ b/armsrc/i2c.c @@ -32,15 +32,13 @@ #define I2C_ERROR "I2C_WaitAck Error" -//static - // Direct use the loop to delay. 6 instructions loop, Masterclock 48MHz, // delay=1 is about 200kbps // timer. // I2CSpinDelayClk(4) = 12.31us // I2CSpinDelayClk(1) = 3.07us +static volatile uint32_t c; static void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) { - volatile uint32_t c; for (c = delay * 2; c; c--) {}; } @@ -101,7 +99,7 @@ void I2C_init(void) { AT91C_BASE_PIOA->PIO_PER |= (GPIO_SCL | GPIO_SDA | GPIO_RST); bool isok = (SCL_read && SDA_read); - if (!isok) + if (isok == false) I2C_recovery(); } @@ -161,7 +159,7 @@ static bool WaitSCL_H_delay(uint32_t delay) { // 5000 * 3.07us = 15350us. 15.35ms // 15000 * 3.07us = 46050us. 46.05ms static bool WaitSCL_H(void) { - return WaitSCL_H_delay(10000); + return WaitSCL_H_delay(15000); } static bool WaitSCL_L_delay(uint32_t delay) { @@ -175,14 +173,14 @@ static bool WaitSCL_L_delay(uint32_t delay) { } // 5000 * 3.07us = 15350us. 15.35ms static bool WaitSCL_L(void) { - return WaitSCL_L_delay(10000); + return WaitSCL_L_delay(15000); } // Wait max 1800ms or until SCL goes LOW. // It timeout reading response from card // Which ever comes first static bool WaitSCL_L_timeout(void) { - volatile uint32_t delay = 1800; + volatile uint32_t delay = 1700; while (delay--) { // exit on SCL LOW if (!SCL_read) @@ -195,7 +193,8 @@ static bool WaitSCL_L_timeout(void) { static bool I2C_Start(void) { - I2C_DELAY_XCLK(4); + I2C_DELAY_2CLK; + I2C_DELAY_2CLK; SDA_H; I2C_DELAY_1CLK; SCL_H; @@ -220,7 +219,7 @@ static bool I2C_WaitForSim(void) { // 8051 speaks with smart card. // 1000*50*3.07 = 153.5ms // 1byte transfer == 1ms with max frame being 256bytes - return WaitSCL_H_delay(10 * 1000 * 50); + return WaitSCL_H_delay(1000 * 300); } // send i2c STOP @@ -233,7 +232,10 @@ static void I2C_Stop(void) { I2C_DELAY_2CLK; if (!WaitSCL_H()) return; SDA_H; - I2C_DELAY_XCLK(8); + I2C_DELAY_2CLK; + I2C_DELAY_2CLK; + I2C_DELAY_2CLK; + I2C_DELAY_2CLK; } // Send i2c ACK @@ -653,7 +655,7 @@ bool sc_rx_bytes(uint8_t *dest, uint8_t *destlen) { bool GetATR(smart_card_atr_t *card_ptr, bool verbose) { - if (!card_ptr) + if (card_ptr == NULL) return false; card_ptr->atr_len = 0; @@ -710,53 +712,62 @@ void SmartCardAtr(void) { set_tracing(true); I2C_Reset_EnterMainProgram(); smart_card_atr_t card; - int res = GetATR(&card, true) ? PM3_SUCCESS : PM3_ETIMEOUT; - if (res == PM3_ETIMEOUT) { - I2C_Reset_EnterMainProgram(); + if (GetATR(&card, true)) { + reply_ng(CMD_SMART_ATR, PM3_SUCCESS, (uint8_t *)&card, sizeof(smart_card_atr_t)); + } else { + reply_ng(CMD_SMART_ATR, PM3_ETIMEOUT, NULL, 0); } - reply_ng(CMD_SMART_ATR, res, (uint8_t *)&card, sizeof(smart_card_atr_t)); set_tracing(false); LEDsoff(); +// StopTicks(); } -void SmartCardRaw(uint64_t arg0, uint64_t arg1, uint8_t *data) { - +void SmartCardRaw(smart_card_raw_t *p) { LED_D_ON(); uint8_t len = 0; uint8_t *resp = BigBuf_malloc(ISO7618_MAX_FRAME); - smartcard_command_t flags = arg0; + // check if alloacted... + smartcard_command_t flags = p->flags; if ((flags & SC_CLEARLOG) == SC_CLEARLOG) clear_trace(); if ((flags & SC_LOG) == SC_LOG) set_tracing(true); - else + else set_tracing(false); - if ((flags & SC_CONNECT)) { + if ((flags & SC_CONNECT) == SC_CONNECT) { I2C_Reset_EnterMainProgram(); - if ((flags & SC_SELECT)) { + if ((flags & SC_SELECT) == SC_SELECT) { smart_card_atr_t card; bool gotATR = GetATR(&card, true); //reply_old(CMD_ACK, gotATR, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t)); - if (!gotATR) + if (gotATR == false) { + reply_ng(CMD_SMART_RAW, PM3_ESOFT, NULL, 0); goto OUT; + } } } if ((flags & SC_RAW) || (flags & SC_RAW_T0)) { - LogTrace(data, arg1, 0, 0, NULL, true); + LogTrace(p->data, p->len, 0, 0, NULL, true); - // Send raw bytes - // asBytes = A0 A4 00 00 02 - // arg1 = len 5 - bool res = I2C_BufferWrite(data, arg1, ((flags & SC_RAW_T0) ? I2C_DEVICE_CMD_SEND_T0 : I2C_DEVICE_CMD_SEND), I2C_DEVICE_ADDRESS_MAIN); - if (!res && DBGLEVEL > 3) DbpString(I2C_ERROR); + bool res = I2C_BufferWrite( + p->data, + p->len, + ((flags & SC_RAW_T0) ? I2C_DEVICE_CMD_SEND_T0 : I2C_DEVICE_CMD_SEND), + I2C_DEVICE_ADDRESS_MAIN + ); + if (res == false && DBGLEVEL > 3) { + DbpString(I2C_ERROR); + reply_ng(CMD_SMART_RAW, PM3_ESOFT, NULL, 0); + goto OUT; + } // read bytes from module len = ISO7618_MAX_FRAME; @@ -767,8 +778,10 @@ void SmartCardRaw(uint64_t arg0, uint64_t arg1, uint8_t *data) { len = 0; } } + + reply_ng(CMD_SMART_RAW, PM3_SUCCESS, resp, len); + OUT: - reply_mix(CMD_ACK, len, 0, 0, resp, len); BigBuf_free(); set_tracing(false); LEDsoff(); diff --git a/armsrc/i2c.h b/armsrc/i2c.h index 5f0f6dd18..bf80585eb 100644 --- a/armsrc/i2c.h +++ b/armsrc/i2c.h @@ -2,7 +2,7 @@ #define __I2C_H #include "common.h" -#include "mifare.h" +#include "pm3_cmd.h" #define I2C_DEVICE_ADDRESS_BOOT 0xB0 #define I2C_DEVICE_ADDRESS_MAIN 0xC0 @@ -39,7 +39,7 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose); // generice functions void SmartCardAtr(void); -void SmartCardRaw(uint64_t arg0, uint64_t arg1, uint8_t *data); +void SmartCardRaw(smart_card_raw_t *packet); void SmartCardUpgrade(uint64_t arg0); void SmartCardSetBaud(uint64_t arg0); void SmartCardSetClock(uint64_t arg0); diff --git a/armsrc/iclass.c b/armsrc/iclass.c index e149254f7..856db35f7 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -35,7 +35,7 @@ #include "ticks.h" #include "iso15693.h" -static uint8_t get_pagemap(const picopass_hdr *hdr) { +static uint8_t get_pagemap(const picopass_hdr_t *hdr) { return (hdr->conf.fuses & (FUSE_CRYPT0 | FUSE_CRYPT1)) >> 3; } @@ -217,7 +217,7 @@ void iclass_simulate(uint8_t sim_type, uint8_t num_csns, bool send_reply, uint8_ //This is 'full sim' mode, where we use the emulator storage for data. //ie: BigBuf_get_EM_addr should be previously filled with data from the "eload" command - picopass_hdr *hdr = (picopass_hdr *)BigBuf_get_EM_addr(); + picopass_hdr_t *hdr = (picopass_hdr_t *)BigBuf_get_EM_addr(); uint8_t pagemap = get_pagemap(hdr); if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { do_iclass_simulation_nonsec(); @@ -1275,7 +1275,7 @@ static bool iclass_send_cmd_with_retries(uint8_t *cmd, size_t cmdsize, uint8_t * * @return false = fail * true = Got all. */ -static bool select_iclass_tag_ex(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_time, uint8_t *status) { +static bool select_iclass_tag_ex(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time, uint8_t *status) { static uint8_t act_all[] = { ICLASS_CMD_ACTALL }; static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 }; @@ -1393,7 +1393,7 @@ static bool select_iclass_tag_ex(picopass_hdr *hdr, bool use_credit_key, uint32_ return true; } -bool select_iclass_tag(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_time) { +bool select_iclass_tag(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time) { uint8_t result = 0; return select_iclass_tag_ex(hdr, use_credit_key, eof_time, &result); } @@ -1402,7 +1402,7 @@ bool select_iclass_tag(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_tim // turn off afterwards void ReaderIClass(uint8_t flags) { - picopass_hdr hdr = {0}; + picopass_hdr_t hdr = {0}; // uint8_t last_csn[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t resp[ICLASS_BUFFER_SIZE] = {0}; memset(resp, 0xFF, sizeof(resp)); @@ -1470,7 +1470,7 @@ void ReaderIClass(uint8_t flags) { switch_off(); } -bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out) { +bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr_t *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out) { uint8_t cmd_check[9] = { ICLASS_CMD_CHECK }; uint8_t mac[4] = {0}; @@ -1538,7 +1538,7 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) { readcheck_cc[0] = 0x10 | ICLASS_CMD_READCHECK; // select card / e-purse - picopass_hdr hdr = {0}; + picopass_hdr_t hdr = {0}; iclass_premac_t *keys = (iclass_premac_t *)datain; @@ -1628,7 +1628,7 @@ void iClass_ReadBlock(uint8_t *msg) { // select tag. uint32_t eof_time = 0; - picopass_hdr hdr = {0}; + picopass_hdr_t hdr = {0}; bool res = select_iclass_tag(&hdr, payload->use_credit_key, &eof_time); if (res == false) { if (payload->send_reply) { @@ -1701,7 +1701,7 @@ void iClass_Dump(uint8_t *msg) { // select tag. uint32_t eof_time = 0; - picopass_hdr hdr = {0}; + picopass_hdr_t hdr = {0}; bool res = select_iclass_tag(&hdr, req->use_credit_key, &eof_time); if (res == false) { if (req->send_reply) { @@ -1828,7 +1828,7 @@ void iClass_WriteBlock(uint8_t *msg) { // select tag. uint32_t eof_time = 0; - picopass_hdr hdr = {0}; + picopass_hdr_t hdr = {0}; uint8_t res = select_iclass_tag(&hdr, payload->req.use_credit_key, &eof_time); if (res == false) { goto out; @@ -1950,7 +1950,7 @@ void iClass_Restore(iclass_restore_req_t *msg) { uint16_t written = 0; uint32_t eof_time = 0; - picopass_hdr hdr = {0}; + picopass_hdr_t hdr = {0}; // select bool res = select_iclass_tag(&hdr, msg->req.use_credit_key, &eof_time); diff --git a/armsrc/iclass.h b/armsrc/iclass.h index b41b79ce8..83d6df302 100644 --- a/armsrc/iclass.h +++ b/armsrc/iclass.h @@ -34,6 +34,6 @@ bool iclass_auth(iclass_auth_req_t *payload, uint8_t *out); void iClass_ReadBlock(uint8_t *msg); bool iclass_read_block(uint16_t blockno, uint8_t *data, uint32_t *start_time, uint32_t *eof_time); -bool select_iclass_tag(picopass_hdr *hdr, bool use_credit_key, uint32_t *eof_time); -bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out); +bool select_iclass_tag(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_time); +bool authenticate_iclass_tag(iclass_auth_req_t *payload, picopass_hdr_t *hdr, uint32_t *start_time, uint32_t *eof_time, uint8_t *mac_out); #endif diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 0d785d8df..e40cde2a1 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -30,12 +30,18 @@ #include "cardhelper.h" #include "wiegand_formats.h" #include "wiegand_formatutils.h" +#include "cmdsmartcard.h" // smart select fct #define NUM_CSNS 9 #define ICLASS_KEYS_MAX 8 #define ICLASS_AUTH_RETRY 10 #define ICLASS_DECRYPTION_BIN "iclass_decryptionkey.bin" +static picopass_hdr_t iclass_last_known_card; +static void iclass_set_last_known_card(picopass_hdr_t *card) { + memcpy(&iclass_last_known_card, card, sizeof(picopass_hdr_t)); +} + static uint8_t empty[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; static int CmdHelp(const char *Cmd); @@ -129,21 +135,21 @@ uint8_t card_app2_limit[] = { }; iclass_config_card_item_t iclass_config_types[14]= { - {"", "", ""}, - {"", "", ""}, - {"", "", ""}, - {"", "", ""}, - {"", "", ""}, - {"", "", ""}, - {"", "", ""}, - {"", "", ""}, - {"", "", ""}, - {"", "", ""}, - {"", "", ""}, - {"", "", ""}, - {"", "", ""}, + {"", ""}, + {"", ""}, + {"", ""}, + {"", ""}, + {"", ""}, + {"", ""}, + {"", ""}, + {"", ""}, + {"", ""}, + {"", ""}, + {"", ""}, + {"", ""}, + {"", ""}, // must be the last entry - {"no config card info available", "", ""} + {"no config card info available", ""} }; static bool check_config_card(const iclass_config_card_item_t *o) { @@ -156,14 +162,15 @@ static bool check_config_card(const iclass_config_card_item_t *o) { } static int load_config_cards(void) { - PrintAndLogEx(INFO, "Detecting cardhelper..."); - - if (IsCardHelperPresent(false) == false) + PrintAndLogEx(INFO, "detecting cardhelper..."); + if (IsCardHelperPresent(false) == false) { + PrintAndLogEx(FAILED, "failed to detect cardhelper"); return PM3_ENODATA; + } for (int i = 0; i < ARRAYLEN(iclass_config_types); ++i) { - PrintAndLogEx(INPLACE, "loading idx %i", i); + PrintAndLogEx(INPLACE, "loading setting %i", i); iclass_config_card_item_t *ret = &iclass_config_types[i]; uint8_t desc[70] = {0}; @@ -173,8 +180,7 @@ static int load_config_cards(void) { uint8_t blocks[16] = {0}; if (GetConfigCardByIdx(i, blocks) == PM3_SUCCESS) { - memcpy(ret->blk6, blocks, sizeof(ret->blk6)); - memcpy(ret->blk7, blocks + sizeof(ret->blk6), sizeof(ret->blk7)); + memcpy(ret->data, blocks, sizeof(blocks)); } } PrintAndLogEx(NORMAL, ""); @@ -182,9 +188,11 @@ static int load_config_cards(void) { return PM3_SUCCESS; } -static const iclass_config_card_item_t *get_config_card_item(uint8_t idx) { - iclass_config_card_item_t *ret = &iclass_config_types[idx]; - return ret; +static const iclass_config_card_item_t *get_config_card_item(int idx) { + if (idx < 0 && idx > 13) { + idx = 13; + } + return &iclass_config_types[idx]; } static void print_config_cards(void) { @@ -200,15 +208,134 @@ static void print_config_cards(void) { static void print_config_card(const iclass_config_card_item_t *o) { if (check_config_card(o)) { PrintAndLogEx(INFO, "description... %s", o->desc); - PrintAndLogEx(INFO, "block 6....... " _YELLOW_("%s"), sprint_hex_inrow(o->blk6, sizeof(o->blk6))); - PrintAndLogEx(INFO, "block 7....... " _YELLOW_("%s"), sprint_hex_inrow(o->blk7, sizeof(o->blk7))); + PrintAndLogEx(INFO, "data....... " _YELLOW_("%s"), sprint_hex_inrow(o->data, sizeof(o->data))); } } -static void generate_config_card(const iclass_config_card_item_t *o) { - if (check_config_card(o)) { - PrintAndLogEx(INFO, "to be implemented..."); +static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *key, bool got_kr) { + if (check_config_card(o) == false) { + return PM3_EINVARG; } + // get header from card + //bool have = memcmp(iclass_last_known_card.csn, "\x00\x00\x00\x00\x00\x00\x00\x00", 8); + PrintAndLogEx(INFO, "trying to read a card.."); + int res = read_iclass_csn(false, false); + if (res != PM3_SUCCESS) { + PrintAndLogEx(FAILED, "Put a card on antenna and try again..."); + return res; + } + + // generate dump file + uint8_t app1_limit = iclass_last_known_card.conf.app_limit; + uint8_t old_limit = app1_limit; + uint8_t tot_bytes = (app1_limit + 1) * 8; + + // normal size + uint8_t *data = calloc(1, tot_bytes); + if (data == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } + memset(data, 0xFF, tot_bytes); + + // Keyrolling configuration cards are special. + if (strstr(o->desc, "Keyroll") != NULL) { + + if (got_kr == false) { + PrintAndLogEx(ERR, "please specifiy KEYROLL key!"); + return PM3_EINVARG; + } + + if (app1_limit < 0x16) { + // if card wasn't large enough before, adapt to new size + PrintAndLogEx(WARNING, "Adapting applimit1 for KEY rolling.."); + + app1_limit = 0x16; + iclass_last_known_card.conf.app_limit = 0x16; + tot_bytes = (app1_limit + 1) * 8; + + uint8_t *p; + p = realloc(data, tot_bytes); + if (p == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + free(data); + return PM3_EMALLOC; + } + data = p; + memset(data, 0xFF, tot_bytes); + } + + // need to encrypt + PrintAndLogEx(INFO, "Detecting cardhelper..."); + if (IsCardHelperPresent(false) == false) { + PrintAndLogEx(FAILED, "failed to detect cardhelper"); + return PM3_ENODATA; + } + + uint8_t ffs[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + if (Encrypt(ffs, ffs) == false) { + PrintAndLogEx(WARNING, "failed to encrypt FF"); + } + + uint8_t enckey1[8]; + if (Encrypt(key, enckey1) == false) { + PrintAndLogEx(WARNING, "failed to encrypt key1"); + } + + memcpy(data, &iclass_last_known_card, sizeof(picopass_hdr_t)); + memcpy(data + (6 * 8), o->data, sizeof(o->data)); + + // encrypted keyroll key 0D + memcpy(data + (0xD * 8), enckey1, sizeof(enckey1)); + // encrypted 0xFF + for (uint8_t i = 0xe; i < 0x14; i++) { + memcpy(data + (i*8), ffs, sizeof(ffs)); + } + + // encrypted partial keyroll key 14 + uint8_t foo[8] = {0x15}; + memcpy(foo + 1, key, 7); + uint8_t enckey2[8]; + if (Encrypt(foo, enckey2) == false) { + PrintAndLogEx(WARNING, "failed to encrypt partial 1"); + } + memcpy(data + (0x14 * 8), enckey2, sizeof(enckey2)); + + // encrypted partial keyroll key 15 + memset(foo, 0xFF, sizeof(foo)); + foo[0] = key[7]; + if (Encrypt(foo, enckey2) == false) { + PrintAndLogEx(WARNING, "failed to encrypt partial 2"); + } + memcpy(data + (0x15 * 8), enckey2, sizeof(enckey2)); + + // encrypted 0xFF + for (uint8_t i = 0x16; i <= app1_limit; i++) { + memcpy(data + (i * 8), ffs, sizeof(ffs)); + } + + + // revert potential modified app1_limit + iclass_last_known_card.conf.app_limit = old_limit; + + } else { + memcpy(data, &iclass_last_known_card, sizeof(picopass_hdr_t)); + memcpy(data + (6*8), o->data, sizeof(o->data)); + } + + // create filename + char filename[FILE_PATH_SIZE] = {0}; + char *fptr = filename; + fptr += snprintf(fptr, sizeof(filename), "hf-iclass-"); + FillFileNameByUID(fptr, data, "-dump", 8); + + // save dump file + saveFile(filename, ".bin", data, tot_bytes); + saveFileEML(filename, data, tot_bytes, 8); + saveFileJSON(filename, jsfIclass, data, tot_bytes, NULL); + + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass view -f %s.bin") "` to view dump file", filename); + return PM3_SUCCESS; } static uint8_t isset(uint8_t val, uint8_t mask) { @@ -219,11 +346,11 @@ static uint8_t notset(uint8_t val, uint8_t mask) { return !(val & mask); } -uint8_t get_pagemap(const picopass_hdr *hdr) { +uint8_t get_pagemap(const picopass_hdr_t *hdr) { return (hdr->conf.fuses & (FUSE_CRYPT0 | FUSE_CRYPT1)) >> 3; } -static void fuse_config(const picopass_hdr *hdr) { +static void fuse_config(const picopass_hdr_t *hdr) { uint16_t otp = (hdr->conf.otp[1] << 8 | hdr->conf.otp[0]); @@ -308,7 +435,7 @@ static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *app_areas, } } -static uint8_t get_mem_config(const picopass_hdr *hdr) { +static uint8_t get_mem_config(const picopass_hdr_t *hdr) { // three configuration bits that decides sizes uint8_t type = (hdr->conf.chip_config & 0x10) >> 2; // 16K bit 0 == 1== @@ -320,7 +447,7 @@ static uint8_t get_mem_config(const picopass_hdr *hdr) { return type; } -static void mem_app_config(const picopass_hdr *hdr) { +static void mem_app_config(const picopass_hdr_t *hdr) { uint8_t mem = hdr->conf.mem_config; uint8_t chip = hdr->conf.chip_config; uint8_t kb = 2; @@ -365,13 +492,13 @@ static void mem_app_config(const picopass_hdr *hdr) { } } -static void print_picopass_info(const picopass_hdr *hdr) { +static void print_picopass_info(const picopass_hdr_t *hdr) { PrintAndLogEx(INFO, "-------------------- " _CYAN_("card configuration") " --------------------"); fuse_config(hdr); mem_app_config(hdr); } -static void print_picopass_header(const picopass_hdr *hdr) { +static void print_picopass_header(const picopass_hdr_t *hdr) { PrintAndLogEx(INFO, "--------------------------- " _CYAN_("card") " ---------------------------"); PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " uid", sprint_hex(hdr->csn, sizeof(hdr->csn))); PrintAndLogEx(SUCCESS, " Config: %s Card configuration", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf))); @@ -555,7 +682,7 @@ static int CmdHFiClassSim(const char *Cmd) { saveFile("iclass_mac_attack", ".bin", dump, datalen); free(dump); - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass loclass -h") "` to recover elite key"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass loclass -f iclass_mac_attack.bin") "` to recover elite key"); break; } case ICLASS_SIM_MODE_READER_ATTACK_KEYROLL: { @@ -621,7 +748,8 @@ static int CmdHFiClassSim(const char *Cmd) { saveFile("iclass_mac_attack_keyroll_B", ".bin", dump, datalen); free(dump); - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass loclass -h") "` to recover elite key"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass loclass -f iclass_mac_attack_keyroll_A.bin") "` to recover elite key"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass loclass -f iclass_mac_attack_keyroll_B.bin") "` to recover elite key"); break; } case ICLASS_SIM_MODE_CSN: @@ -683,9 +811,16 @@ int read_iclass_csn(bool loop, bool verbose) { } } - picopass_hdr *hdr = (picopass_hdr *)resp.data.asBytes; - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "iCLASS / Picopass CSN: " _GREEN_("%s"), sprint_hex(hdr->csn, sizeof(hdr->csn))); + picopass_hdr_t *card = calloc(1, sizeof(picopass_hdr_t)); + if (card) { + memcpy(card, (picopass_hdr_t *)resp.data.asBytes, sizeof(picopass_hdr_t)); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "iCLASS / Picopass CSN: " _GREEN_("%s"), sprint_hex(card->csn, sizeof(card->csn))); + iclass_set_last_known_card(card); + free(card); + } else { + PrintAndLogEx(FAILED, "failed to allocate memory"); + } } } while (loop && kbd_enter_pressed() == false); @@ -800,8 +935,8 @@ static int CmdHFiClassELoad(const char *Cmd) { dump = newdump; } - print_picopass_header((picopass_hdr *) dump); - print_picopass_info((picopass_hdr *) dump); + print_picopass_header((picopass_hdr_t *) dump); + print_picopass_info((picopass_hdr_t *) dump); // fast push mode conn.block_after_ACK = true; @@ -882,7 +1017,7 @@ static int CmdHFiClassESave(const char *Cmd) { saveFileJSON(filename, jsfIclass, dump, bytes, NULL); free(dump); - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass view") "` to view dump file"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass view -f %s.bin") "` to view dump file", filename); return PM3_SUCCESS; } @@ -935,8 +1070,8 @@ static int CmdHFiClassEView(const char *Cmd) { } if (verbose) { - print_picopass_header((picopass_hdr *) dump); - print_picopass_info((picopass_hdr *) dump); + print_picopass_header((picopass_hdr_t *) dump); + print_picopass_info((picopass_hdr_t *) dump); } PrintAndLogEx(NORMAL, ""); @@ -1056,7 +1191,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { if (have_file) { - picopass_hdr *hdr = (picopass_hdr *)decrypted; + picopass_hdr_t *hdr = (picopass_hdr_t *)decrypted; uint8_t mem = hdr->conf.mem_config; uint8_t chip = hdr->conf.chip_config; @@ -1291,7 +1426,7 @@ static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool verbose) { return false; } - picopass_hdr *hdr = (picopass_hdr *)resp.data.asBytes; + picopass_hdr_t *hdr = (picopass_hdr_t *)resp.data.asBytes; if (CSN != NULL) memcpy(CSN, hdr->csn, 8); @@ -1436,7 +1571,7 @@ static int CmdHFiClassDump(const char *Cmd) { DropField(); uint8_t readStatus = resp.oldarg[0] & 0xff; - picopass_hdr *hdr = (picopass_hdr *)resp.data.asBytes; + picopass_hdr_t *hdr = (picopass_hdr_t *)resp.data.asBytes; if (readStatus == 0) { PrintAndLogEx(FAILED, "no tag found"); @@ -1645,8 +1780,8 @@ write_dump: saveFileEML(filename, tag_data, bytes_got, 8); saveFileJSON(filename, jsfIclass, tag_data, bytes_got, NULL); - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass decrypt") "` to decrypt dump file"); - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass view") "` to view dump file"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass decrypt -f %s.bin") "` to decrypt dump file", filename); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass view -f %s.bin") "` to view dump file", filename); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -1941,7 +2076,7 @@ static int CmdHFiClassRestore(const char *Cmd) { if (resp.status == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "iCLASS restore " _GREEN_("successful")); - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass rdbl ") "` to verify data on card"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass rdbl") "` to verify data on card"); } else { PrintAndLogEx(WARNING, "iCLASS restore " _RED_("failed")); } @@ -2201,8 +2336,8 @@ static int CmdHFiClass_loclass(const char *Cmd) { void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize) { - picopass_hdr *hdr = (picopass_hdr *)iclass_dump; -// picopass_ns_hdr *ns_hdr = (picopass_ns_hdr *)iclass_dump; + picopass_hdr_t *hdr = (picopass_hdr_t *)iclass_dump; +// picopass_ns_hdr_t *ns_hdr = (picopass_ns_hdr_t *)iclass_dump; // uint8_t pagemap = get_pagemap(hdr); // if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { } @@ -2357,8 +2492,8 @@ static int CmdHFiClassView(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - print_picopass_header((picopass_hdr *) dump); - print_picopass_info((picopass_hdr *) dump); + print_picopass_header((picopass_hdr_t *) dump); + print_picopass_info((picopass_hdr_t *) dump); printIclassDumpContents(dump, startblock, endblock, bytes_read); free(dump); return PM3_SUCCESS; @@ -2700,7 +2835,7 @@ static void add_key(uint8_t *key) { if (i == ICLASS_KEYS_MAX) { PrintAndLogEx(INFO, "Couldn't find an empty keyslot"); } else { - PrintAndLogEx(HINT, "Try " _YELLOW_("`hf iclass managekeys -p`") " to view keys"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass managekeys -p") "` to view keys"); } } @@ -3578,14 +3713,17 @@ static int CmdHFiClassConfigCard(const char * Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf iclass configcard", "Manage reader configuration card via Cardhelper", - "hf iclass configcard -l --> download config cards " - "hf iclass configcard -p --> print config card" - "hf iclass configcard -g --ki 1 --> generate config dump file based on idx 1" + "hf iclass configcard -l --> download config cards\n" + "hf iclass configcard -p --> print config card\n" + "hf iclass configcard --ci 1 --> use config card in slot 1\n" + "hf iclass configcard -g --ci 0 --> generate config file from slot 0" + ); void *argtable[] = { arg_param_begin, - arg_int0(NULL, "ki", "", "select index in list"), + arg_int0(NULL, "ci", "", "use config slot at index"), + arg_int0(NULL, "ki", "", "Key index to select key from memory 'hf iclass managekeys'"), arg_lit0("g", NULL, "generate card dump file"), arg_lit0("l", NULL, "load available cards"), arg_lit0("p", NULL, "print available cards"), @@ -3593,12 +3731,26 @@ static int CmdHFiClassConfigCard(const char * Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, false); - int idx = arg_get_int_def(ctx, 1, -1); - bool generate = arg_get_lit(ctx, 2); - bool load = arg_get_lit(ctx, 3); - bool print = arg_get_lit(ctx, 4); + int ccidx = arg_get_int_def(ctx, 1, -1); + int kidx = arg_get_int_def(ctx, 2, -1); + bool generate = arg_get_lit(ctx, 3); + bool load = arg_get_lit(ctx, 4); + bool print = arg_get_lit(ctx, 5); CLIParserFree(ctx); + bool got_kr = false; + uint8_t key[8] = {0}; + if (kidx >= 0) { + if (kidx < ICLASS_KEYS_MAX) { + got_kr = true; + memcpy(key, iClass_Key_Table[kidx], 8); + PrintAndLogEx(SUCCESS, "Using key[%d] " _GREEN_("%s"), kidx, sprint_hex(iClass_Key_Table[kidx], 8)); + } else { + PrintAndLogEx(ERR, "--ki number is invalid"); + return PM3_EINVARG; + } + } + if (load) { if (load_config_cards() != PM3_SUCCESS) { PrintAndLogEx(INFO, "failed to load, check your cardhelper"); @@ -3609,14 +3761,20 @@ static int CmdHFiClassConfigCard(const char * Cmd) { print_config_cards(); } - if (idx > -1 && idx < 14) { - const iclass_config_card_item_t *item = get_config_card_item(idx); + if (ccidx > -1 && ccidx < 14) { + const iclass_config_card_item_t *item = get_config_card_item(ccidx); print_config_card(item); } if (generate) { - const iclass_config_card_item_t *item = get_config_card_item(idx); - generate_config_card(item); + const iclass_config_card_item_t *item = get_config_card_item(ccidx); + if (strstr(item->desc, "Keyroll") != NULL) { + if (got_kr == false) { + PrintAndLogEx(ERR, "please specifiy KEYROLL key!"); + return PM3_EINVARG; + } + } + generate_config_card(item, key, got_kr); } return PM3_SUCCESS; @@ -3700,8 +3858,8 @@ int info_iclass(void) { return PM3_EOPABORTED; } - picopass_hdr *hdr = (picopass_hdr *)resp.data.asBytes; - picopass_ns_hdr *ns_hdr = (picopass_ns_hdr *)resp.data.asBytes; + picopass_hdr_t *hdr = (picopass_hdr_t *)resp.data.asBytes; + picopass_ns_hdr_t *ns_hdr = (picopass_ns_hdr_t *)resp.data.asBytes; PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--------------------- " _CYAN_("Tag Information") " ----------------------"); diff --git a/client/src/cmdhficlass.h b/client/src/cmdhficlass.h index 06a55122c..f96c9b1b2 100644 --- a/client/src/cmdhficlass.h +++ b/client/src/cmdhficlass.h @@ -30,8 +30,7 @@ typedef struct iclass_prekey { typedef struct { char desc[70]; - uint8_t blk6[8]; - uint8_t blk7[8]; + uint8_t data[16]; } iclass_config_card_item_t; int CmdHFiClass(const char *Cmd); @@ -46,6 +45,6 @@ void GenerateMacKeyFrom(uint8_t *CSN, uint8_t *CCNR, bool use_raw, bool use_elit void PrintPreCalcMac(uint8_t *keys, uint32_t keycnt, iclass_premac_t *pre_list); void PrintPreCalc(iclass_prekey_t *list, uint32_t itemcnt); -uint8_t get_pagemap(const picopass_hdr *hdr); +uint8_t get_pagemap(const picopass_hdr_t *hdr); bool check_known_default(uint8_t *csn, uint8_t *epurse, uint8_t *rmac, uint8_t *tmac, uint8_t *key); #endif diff --git a/client/src/cmdsmartcard.c b/client/src/cmdsmartcard.c index c69404432..00d730d62 100644 --- a/client/src/cmdsmartcard.c +++ b/client/src/cmdsmartcard.c @@ -255,28 +255,44 @@ static void PrintATR(uint8_t *atr, size_t atrlen) { } } -static int smart_wait(uint8_t *data, bool verbose) { - int i = 5; +static int smart_wait(uint8_t *out, int maxoutlen, bool verbose) { + int i = 4; uint32_t len = 0; do { clearCommandBuffer(); PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_SMART_RAW, &resp, 1000)) { + + if (resp.status != PM3_SUCCESS) { + if (verbose) PrintAndLogEx(WARNING, "smart card response status failed"); + return -3; + } - len = resp.oldarg[0]; + len = resp.length; if (len == 0) { if (verbose) PrintAndLogEx(WARNING, "smart card response failed"); return -2; } - memcpy(data, resp.data.asBytes, len); + if (len > maxoutlen) { + if (verbose) PrintAndLogEx(ERR, "Response too large. Got %u, expected %d", len, maxoutlen); + return -4; + } + + memcpy(out, resp.data.asBytes, len); if (len >= 2) { if (verbose) { - PrintAndLogEx(SUCCESS, "%02X%02X | %s", data[len - 2], data[len - 1], GetAPDUCodeDescription(data[len - 2], data[len - 1])); + + + if (out[len - 2] == 0x90 && out[len - 1] == 0x00) { + PrintAndLogEx(SUCCESS, _GREEN_("%02X%02X") " | %s", out[len - 2], out[len - 1], GetAPDUCodeDescription(out[len - 2], out[len - 1])); + } else { + PrintAndLogEx(SUCCESS, "%02X%02X | %s", out[len - 2], out[len - 1], GetAPDUCodeDescription(out[len - 2], out[len - 1])); + } } } else { if (verbose) { - PrintAndLogEx(SUCCESS, " %d | %s", len, sprint_hex_inrow_ex(data, len, 8)); + PrintAndLogEx(SUCCESS, " %d | %s", len, sprint_hex_inrow_ex(out, len, 8)); } } return len; @@ -289,29 +305,35 @@ static int smart_wait(uint8_t *data, bool verbose) { return -1; } -static int smart_responseEx(uint8_t *data, bool verbose) { +static int smart_responseEx(uint8_t *out, int maxoutlen, bool verbose) { - int datalen = smart_wait(data, verbose); + int datalen = smart_wait(out, maxoutlen, verbose); bool needGetData = false; if (datalen < 2) { goto out; } - if (data[datalen - 2] == 0x61 || data[datalen - 2] == 0x9F) { + if (out[datalen - 2] == 0x61 || out[datalen - 2] == 0x9F) { needGetData = true; } if (needGetData) { - int len = data[datalen - 1]; + int len = out[datalen - 1]; - if (verbose) PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len); + if (verbose) PrintAndLogEx(INFO, "Requesting " _YELLOW_("0x%02X") " bytes response", len); + + uint8_t cmd_getresp[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, len}; + smart_card_raw_t *payload = calloc(1, sizeof(smart_card_raw_t) + sizeof(cmd_getresp)); + payload->flags = SC_RAW | SC_LOG; + payload->len = sizeof(cmd_getresp); + memcpy(payload->data, cmd_getresp, sizeof(cmd_getresp)); - uint8_t getstatus[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, len}; clearCommandBuffer(); - SendCommandMIX(CMD_SMART_RAW, SC_RAW, sizeof(getstatus), 0, getstatus, sizeof(getstatus)); + SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + sizeof(cmd_getresp)); + free(payload); - datalen = smart_wait(data, verbose); + datalen = smart_wait(out, maxoutlen, verbose); if (datalen < 2) { goto out; @@ -321,16 +343,16 @@ static int smart_responseEx(uint8_t *data, bool verbose) { if (datalen != len + 2) { // data with ACK if (datalen == len + 2 + 1) { // 2 - response, 1 - ACK - if (data[0] != ISO7816_GET_RESPONSE) { + if (out[0] != ISO7816_GET_RESPONSE) { if (verbose) { - PrintAndLogEx(ERR, "GetResponse ACK error. len 0x%x | data[0] %02X", len, data[0]); + PrintAndLogEx(ERR, "GetResponse ACK error. len 0x%x | data[0] %02X", len, out[0]); } datalen = 0; goto out; } datalen--; - memmove(data, &data[1], datalen); + memmove(out, &out[1], datalen); } else { // wrong length if (verbose) { @@ -344,8 +366,8 @@ out: return datalen; } -static int smart_response(uint8_t *data) { - return smart_responseEx(data, true); +static int smart_response(uint8_t *out, int maxoutlen) { + return smart_responseEx(out, maxoutlen, true); } static int CmdSmartRaw(const char *Cmd) { @@ -386,61 +408,76 @@ static int CmdSmartRaw(const char *Cmd) { return PM3_EINVARG; } - uint8_t flags = SC_LOG; + smart_card_raw_t *payload = calloc(1, sizeof(smart_card_raw_t) + dlen); + if (payload == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } + payload->len = dlen; + memcpy(payload->data, data, dlen); + + payload->flags = SC_LOG; if (active || active_select) { - flags |= (SC_CONNECT | SC_CLEARLOG); + payload->flags |= (SC_CONNECT | SC_CLEARLOG); if (active_select) - flags |= SC_SELECT; + payload->flags |= SC_SELECT; } - if (dlen > 0) { + if (dlen > 0) { if (use_t0) - flags |= SC_RAW_T0; + payload->flags |= SC_RAW_T0; else - flags |= SC_RAW; + payload->flags |= SC_RAW; + } + + uint8_t *buf = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t)); + if (buf == NULL) { + PrintAndLogEx(DEBUG, "failed to allocate memory"); + return PM3_EMALLOC; } clearCommandBuffer(); - SendCommandOLD(CMD_SMART_RAW, flags, dlen, 0, data, dlen); + SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + dlen); + + if (reply == false) { + goto out; + } // reading response from smart card - if (reply) { - - uint8_t *buf = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t)); - if (!buf) - return PM3_EMALLOC; - - int len = smart_response(buf); - if (len < 0) { - free(buf); - return PM3_ESOFT; - } - - if (buf[0] == 0x6C) { - data[4] = buf[1]; - - clearCommandBuffer(); - SendCommandMIX(CMD_SMART_RAW, 0, dlen, 0, data, dlen); - len = smart_response(buf); - - data[4] = 0; - } - - if (decode_tlv && len > 4) - TLVPrintFromBuffer(buf, len - 2); - else { - if (len > 16) { - for (int i = 0; i < len; i += 16) { - PrintAndLogEx(SUCCESS, "%s", sprint_hex_ascii(buf + i, 16)) ; - } - } else { - PrintAndLogEx(SUCCESS, "%s", sprint_hex_ascii(buf, len)) ; - } - } - + int len = smart_response(buf, PM3_CMD_DATA_SIZE); + if (len < 0) { free(buf); + return PM3_ESOFT; } + + if (buf[0] == 0x6C) { + + // request more bytes to download + data[4] = buf[1]; + memcpy(payload->data, data, dlen); + clearCommandBuffer(); + SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + dlen); + + len = smart_response(buf, PM3_CMD_DATA_SIZE); + + data[4] = 0; + } + + if (decode_tlv && len > 4) + TLVPrintFromBuffer(buf, len - 2); + else { + if (len > 2) { + PrintAndLogEx(INFO, "Response data:"); + PrintAndLogEx(INFO, " # | bytes | ascii"); + PrintAndLogEx(INFO, "---+-------------------------------------------------+-----------------"); + print_hex_break(buf, len, 16); + } + } + PrintAndLogEx(NORMAL, ""); +out: + free(payload); + free(buf); return PM3_SUCCESS; } @@ -632,7 +669,7 @@ static int CmdSmartInfo(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_SMART_ATR, NULL, 0); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_SMART_ATR, &resp, 2500)) { + if (WaitForResponseTimeout(CMD_SMART_ATR, &resp, 2500) == false) { if (verbose) { PrintAndLogEx(WARNING, "smart card timeout"); } @@ -683,7 +720,6 @@ static int CmdSmartInfo(const char *Cmd) { } static int CmdSmartReader(const char *Cmd) { - CLIParserContext *ctx; CLIParserInit(&ctx, "smart reader", "Act as a smart card reader.", @@ -702,7 +738,7 @@ static int CmdSmartReader(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_SMART_ATR, NULL, 0); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_SMART_ATR, &resp, 2500)) { + if (WaitForResponseTimeout(CMD_SMART_ATR, &resp, 2500) == false) { if (verbose) { PrintAndLogEx(WARNING, "smart card select failed"); } @@ -715,10 +751,8 @@ static int CmdSmartReader(const char *Cmd) { } return PM3_ESOFT; } - smart_card_atr_t card; - memcpy(&card, (smart_card_atr_t *)resp.data.asBytes, sizeof(smart_card_atr_t)); - - PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len)); + smart_card_atr_t *card = (smart_card_atr_t *)resp.data.asBytes; + PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card->atr, card->atr_len)); return PM3_SUCCESS; } @@ -816,17 +850,18 @@ static void smart_brute_prim(void) { for (int i = 0; i < ARRAYLEN(get_card_data); i += 5) { + smart_card_raw_t *payload = calloc(1, sizeof(smart_card_raw_t) + 5); + payload->flags = SC_RAW_T0; + payload->len = 5; + memcpy(payload->data, get_card_data + i, 5); + clearCommandBuffer(); - SendCommandMIX(CMD_SMART_RAW, SC_RAW_T0, 5, 0, get_card_data + i, 5); - - int len = smart_responseEx(buf, false); + SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + 5); + free(payload); + int len = smart_responseEx(buf, PM3_CMD_DATA_SIZE, false); if (len > 2) { - // if ( decodeTLV ) { - // if (!TLVPrintFromBuffer(buf, len-2)) { PrintAndLogEx(SUCCESS, "\tHEX %d |: %s", len, sprint_hex(buf, len)); - // } - // } } } free(buf); @@ -858,21 +893,29 @@ static int smart_brute_sfi(bool decodeTLV) { READ_RECORD[2] = rec; READ_RECORD[3] = (sfi << 3) | 4; - clearCommandBuffer(); - SendCommandMIX(CMD_SMART_RAW, SC_RAW_T0, sizeof(READ_RECORD), 0, READ_RECORD, sizeof(READ_RECORD)); + smart_card_raw_t *payload = calloc(1, sizeof(smart_card_raw_t) + sizeof(READ_RECORD)); + payload->flags = SC_RAW_T0; + payload->len = sizeof(READ_RECORD); + memcpy(payload->data, READ_RECORD, sizeof(READ_RECORD)); - len = smart_responseEx(buf, false); + clearCommandBuffer(); + SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + sizeof(READ_RECORD)); + + len = smart_responseEx(buf, PM3_CMD_DATA_SIZE, false); if (buf[0] == 0x6C) { READ_RECORD[4] = buf[1]; + memcpy(payload->data, READ_RECORD, sizeof(READ_RECORD)); clearCommandBuffer(); - SendCommandMIX(CMD_SMART_RAW, SC_RAW_T0, sizeof(READ_RECORD), 0, READ_RECORD, sizeof(READ_RECORD)); - len = smart_responseEx(buf, false); + SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + sizeof(READ_RECORD)); + len = smart_responseEx(buf, PM3_CMD_DATA_SIZE, false); READ_RECORD[4] = 0; } + free(payload); + if (len > 4) { PrintAndLogEx(SUCCESS, "\n\t file %02d, record %02d found", sfi, rec); @@ -898,13 +941,19 @@ static void smart_brute_options(bool decodeTLV) { if (!buf) return; + // Get processing options command uint8_t GET_PROCESSING_OPTIONS[] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00}; - // Get processing options command - clearCommandBuffer(); - SendCommandMIX(CMD_SMART_RAW, SC_RAW_T0, sizeof(GET_PROCESSING_OPTIONS), 0, GET_PROCESSING_OPTIONS, sizeof(GET_PROCESSING_OPTIONS)); + smart_card_raw_t *payload = calloc(1, sizeof(smart_card_raw_t) + sizeof(GET_PROCESSING_OPTIONS)); + payload->flags = SC_RAW_T0; + payload->len = sizeof(GET_PROCESSING_OPTIONS); + memcpy(payload->data, GET_PROCESSING_OPTIONS, sizeof(GET_PROCESSING_OPTIONS)); - int len = smart_responseEx(buf, false); + clearCommandBuffer(); + SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + sizeof(GET_PROCESSING_OPTIONS)); + free(payload); + + int len = smart_responseEx(buf, PM3_CMD_DATA_SIZE, false); if (len > 4) { PrintAndLogEx(SUCCESS, "Got processing options"); if (decodeTLV) { @@ -997,10 +1046,16 @@ static int CmdSmartBruteforceSFI(const char *Cmd) { if (res) continue; - clearCommandBuffer(); - SendCommandOLD(CMD_SMART_RAW, SC_RAW_T0, hexlen, 0, cmddata, hexlen); + smart_card_raw_t *payload = calloc(1, sizeof(smart_card_raw_t) + hexlen); + payload->flags = SC_RAW_T0; + payload->len = hexlen; - int len = smart_responseEx(buf, false); + memcpy(payload->data, cmddata, hexlen); + clearCommandBuffer(); + SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + hexlen); + free(payload); + + int len = smart_responseEx(buf, PM3_CMD_DATA_SIZE, false); if (len < 3) continue; @@ -1072,43 +1127,38 @@ int ExchangeAPDUSC(bool verbose, uint8_t *datain, int datainlen, bool activateCa *dataoutlen = 0; + smart_card_raw_t *payload = calloc(1, sizeof(smart_card_raw_t) + datainlen); + payload->flags = (SC_RAW_T0 | SC_LOG); if (activateCard) { - if (smart_select(false, NULL) == false) { - PrintAndLogEx(DEBUG, "APDU SC - select card failed"); - return 1; - } - } - - PrintAndLogEx(DEBUG, "APDU SC"); - - uint8_t flags = SC_RAW_T0; - if (activateCard) { - flags |= SC_SELECT | SC_CONNECT; + payload->flags |= (SC_SELECT | SC_CONNECT); } + payload->len = datainlen; + memcpy(payload->data, datain, datainlen); clearCommandBuffer(); - SendCommandOLD(CMD_SMART_RAW, flags, datainlen, 0, datain, datainlen); + SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + datainlen); - int len = smart_responseEx(dataout, verbose); + int len = smart_responseEx(dataout, maxdataoutlen, verbose); if (len < 0) { return 1; } // retry if (len > 1 && dataout[len - 2] == 0x6c && datainlen > 4) { - uint8_t data [5]; - memcpy(data, datain, 5); + payload->flags = SC_RAW_T0; + payload->len = 5; // transfer length via T=0 - data[4] = dataout[len - 1]; - + datain[4] = dataout[len - 1]; + memcpy(payload->data, datain, 5); clearCommandBuffer(); - // something fishy: we have only 5 bytes but we put datainlen in arg1? - SendCommandMIX(CMD_SMART_RAW, SC_RAW_T0, datainlen, 0, data, sizeof(data)); - - len = smart_responseEx(dataout, verbose); + SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + 5); + datain[4] = 0; + len = smart_responseEx(dataout, maxdataoutlen, verbose); } + free(payload); + *dataoutlen = len; return 0; } @@ -1120,9 +1170,8 @@ bool smart_select(bool verbose, smart_card_atr_t *atr) { clearCommandBuffer(); SendCommandNG(CMD_SMART_ATR, NULL, 0); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_SMART_ATR, &resp, 2500)) { - - if (verbose) PrintAndLogEx(WARNING, "smart card select failed"); + if (WaitForResponseTimeout(CMD_SMART_ATR, &resp, 2500) == false) { + if (verbose) PrintAndLogEx(WARNING, "smart card select timeouted"); return false; } diff --git a/client/src/cmdsmartcard.h b/client/src/cmdsmartcard.h index ca4733724..8bd70b2bd 100644 --- a/client/src/cmdsmartcard.h +++ b/client/src/cmdsmartcard.h @@ -12,7 +12,7 @@ #define CMDSMARTCARD_H__ #include "common.h" -#include "mifare.h" // structs +#include "pm3_cmd.h" // structs int CmdSmartcard(const char *Cmd); diff --git a/client/src/fileutils.c b/client/src/fileutils.c index 6cc29d867..24538497e 100644 --- a/client/src/fileutils.c +++ b/client/src/fileutils.c @@ -466,13 +466,13 @@ int saveFileJSONex(const char *preferredName, JSONFileType ftype, uint8_t *data, case jsfIclass: { JsonSaveStr(root, "FileType", "iclass"); - picopass_hdr *hdr = (picopass_hdr *)data; + picopass_hdr_t *hdr = (picopass_hdr_t *)data; JsonSaveBufAsHexCompact(root, "$.Card.CSN", hdr->csn, sizeof(hdr->csn)); JsonSaveBufAsHexCompact(root, "$.Card.Configuration", (uint8_t *)&hdr->conf, sizeof(hdr->conf)); uint8_t pagemap = get_pagemap(hdr); if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { - picopass_ns_hdr *ns_hdr = (picopass_ns_hdr *)data; + picopass_ns_hdr_t *ns_hdr = (picopass_ns_hdr_t *)data; JsonSaveBufAsHexCompact(root, "$.Card.AIA", ns_hdr->app_issuer_area, sizeof(ns_hdr->app_issuer_area)); } else { JsonSaveBufAsHexCompact(root, "$.Card.Epurse", hdr->epurse, sizeof(hdr->epurse)); diff --git a/common/cardhelper.c b/common/cardhelper.c index c2206da20..9b7ea9e9e 100644 --- a/common/cardhelper.c +++ b/common/cardhelper.c @@ -23,7 +23,6 @@ #define CARD_INS_PINSIZE 0x08 #define CARD_INS_CC 0x81 #define CARD_INS_CC_DESC 0x82 -static uint8_t cmd[] = {0x96, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // look for CardHelper bool IsCardHelperPresent(bool verbose) { @@ -31,7 +30,7 @@ bool IsCardHelperPresent(bool verbose) { if (IfPm3Smartcard()) { int resp_len = 0; uint8_t version[] = {0x96, 0x69, 0x00, 0x00, 0x00}; - uint8_t resp[20] = {0}; + uint8_t resp[30] = {0}; ExchangeAPDUSC(verbose, version, sizeof(version), true, true, resp, sizeof(resp), &resp_len); if (resp_len < 8) { @@ -49,14 +48,12 @@ bool IsCardHelperPresent(bool verbose) { } static bool executeCrypto(uint8_t ins, uint8_t *src, uint8_t *dest) { - int resp_len = 0; - uint8_t dec[11] = {0}; - - cmd[1] = ins; + uint8_t cmd[] = {0x96, ins, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; memcpy(cmd + 5, src, 8); - ExchangeAPDUSC(false, cmd, sizeof(cmd), false, false, dec, sizeof(dec), &resp_len); - + int resp_len = 0; + uint8_t dec[11] = {0}; + ExchangeAPDUSC(false, cmd, sizeof(cmd), false, true, dec, sizeof(dec), &resp_len); if (resp_len == 10) { memcpy(dest, dec, 8); return true; diff --git a/include/mifare.h b/include/mifare.h index 50bf94861..d31368102 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -121,23 +121,5 @@ typedef struct { } state; } PACKED nonces_t; -//----------------------------------------------------------------------------- -// ISO 7618 Smart Card -//----------------------------------------------------------------------------- -typedef struct { - uint8_t atr_len; - uint8_t atr[50]; -} PACKED smart_card_atr_t; - -typedef enum SMARTCARD_COMMAND { - SC_CONNECT = (1 << 0), - SC_NO_DISCONNECT = (1 << 1), - SC_RAW = (1 << 2), - SC_SELECT = (1 << 3), - SC_RAW_T0 = (1 << 4), - SC_CLEARLOG = (1 << 5), - SC_LOG = (1 << 6), -} smartcard_command_t; - #endif // _MIFARE_H_ diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index a2193a85b..8459bdd22 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -368,14 +368,14 @@ typedef struct { uint8_t key_d[8]; uint8_t key_c[8]; uint8_t app_issuer_area[8]; -} PACKED picopass_hdr; +} PACKED picopass_hdr_t; // iCLASS non-secure mode memory mapping typedef struct { uint8_t csn[8]; picopass_conf_block_t conf; uint8_t app_issuer_area[8]; -} PACKED picopass_ns_hdr; +} PACKED picopass_ns_hdr_t; typedef struct { @@ -393,6 +393,31 @@ typedef struct { uint8_t data[]; } PACKED flashmem_write_t; +//----------------------------------------------------------------------------- +// ISO 7618 Smart Card +//----------------------------------------------------------------------------- +typedef struct { + uint8_t atr_len; + uint8_t atr[50]; +} PACKED smart_card_atr_t; + +typedef enum SMARTCARD_COMMAND { + SC_CONNECT = (1 << 0), + SC_NO_DISCONNECT = (1 << 1), + SC_RAW = (1 << 2), + SC_SELECT = (1 << 3), + SC_RAW_T0 = (1 << 4), + SC_CLEARLOG = (1 << 5), + SC_LOG = (1 << 6), +} smartcard_command_t; + +typedef struct { + uint8_t flags; + uint16_t len; + uint8_t data[]; +} PACKED smart_card_raw_t; + + // For the bootloader #define CMD_DEVICE_INFO 0x0000 //#define CMD_SETUP_WRITE 0x0001 From d2e709158d7b513631799ea7be0695e5e3194f36 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 8 Apr 2021 09:48:44 +0200 Subject: [PATCH 174/373] remove newline --- client/src/cmddata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 1cbbe3277..63d65fa25 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -2873,7 +2873,7 @@ static command_t CommandTable[] = { {"rtrim", CmdRtrim, AlwaysAvailable, "Trim samples from right of trace"}, {"setgraphmarkers", CmdSetGraphMarkers, AlwaysAvailable, "Set blue and orange marker in graph window"}, {"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"}, + {"timescale", CmdTimeScale, AlwaysAvailable, "Set a timescale to get a differential reading between the yellow and purple markers as time duration"}, {"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"}, From 7567e7601d1da57010c32e44f172a34e47e77e39 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 8 Apr 2021 09:50:03 +0200 Subject: [PATCH 175/373] textual --- client/src/cmdhf14b.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index 3671b476c..47b795bb4 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -268,11 +268,10 @@ static int CmdHF14BSniff(const char *Cmd) { } static int CmdHF14BCmdRaw(const char *Cmd) { - CLIParserContext *ctx; CLIParserInit(&ctx, "hf 14b raw", "Sends raw bytes to card", - "hf 14b raw -cks --data 0200a40400 -> standard select\n" + "hf 14b raw -cks --data 0200a40400 -> standard select, apdu 0200a4000 (7816)\n" "hf 14b raw -ck --sr --data 0200a40400 -> SRx select\n" "hf 14b raw -ck --cts --data 0200a40400 -> C-ticket select\n" ); @@ -457,7 +456,7 @@ static int print_atqb_resp(uint8_t *data, uint8_t cid) { PrintAndLogEx(SUCCESS, " Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4", (protocolT) ? "" : "not "); uint8_t fwt = data[6] >> 4; - if (fwt < 16) { + if (fwt < 15) { uint32_t etus = (32 << fwt); uint32_t fwt_time = (302 << fwt); PrintAndLogEx(SUCCESS, "Frame Wait Integer: %u - %u ETUs | %u us", fwt, etus, fwt_time); @@ -1126,7 +1125,7 @@ static int CmdHF14BWriteSri(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf 14b sriwrite", - "Write data to a SRI512 | SRIX4K block", + "Write data to a SRI512 or SRIX4K block", "hf 14b sriwrite --4k -b 100 -d 11223344\n" "hf 14b sriwrite --4k --sb -d 11223344 --> special block write\n" "hf 14b sriwrite --512 -b 15 -d 11223344\n" From 2537fbde20fa2d2c2a20f416ea6c588aeef18e5b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 8 Apr 2021 09:51:23 +0200 Subject: [PATCH 176/373] text --- client/src/cmdhf14b.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index 47b795bb4..244d88f83 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -26,7 +26,7 @@ #include "mifare/ndef.h" // NDEFRecordsDecodeAndPrint #include "aidsearch.h" -#define MAX_14B_TIMEOUT 40542464U // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s +#define MAX_14B_TIMEOUT (4949000U >> 2) #define TIMEOUT 2000 #define APDU_TIMEOUT 2000 @@ -1931,7 +1931,7 @@ static command_t CommandTable[] = { {"sim", CmdHF14BSim, IfPm3Iso14443b, "Fake ISO 14443B tag"}, {"sniff", CmdHF14BSniff, IfPm3Iso14443b, "Eavesdrop ISO 14443B"}, {"rdbl", CmdHF14BSriRdBl, IfPm3Iso14443b, "Read SRI512/SRIX4x block"}, - {"sriwrite", CmdHF14BWriteSri, IfPm3Iso14443b, "Write data to a SRI512 | SRIX4K tag"}, + {"sriwrite", CmdHF14BWriteSri, IfPm3Iso14443b, "Write data to a SRI512 or SRIX4K tag"}, // {"valid", srix4kValid, AlwaysAvailable, "srix4k checksum test"}, {NULL, NULL, NULL, NULL} }; From 3db85ac47beef0dd56bb421235cb6454d297464f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 8 Apr 2021 09:55:11 +0200 Subject: [PATCH 177/373] text --- doc/commands.md | 121 +++++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 59 deletions(-) diff --git a/doc/commands.md b/doc/commands.md index 862ae353f..e1d41758d 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -10,9 +10,9 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- +|`help `|Y |`Use ` help` for details of a command` |`auto `|N |`Automated detection process for unknown tags` |`clear `|Y |`Clear screen` -|`help `|Y |`Use ' help' for details of a particular command.` |`hints `|Y |`Turn hints on / off` |`msleep `|Y |`Add a pause in milliseconds` |`rem `|Y |`Add a text line in log file` @@ -20,6 +20,47 @@ Check column "offline" for their availability. |`exit `|Y |`Exit program` +### preferences + + { Edit client/device preferences... } + +|command |offline |description +|------- |------- |----------- +|`preferences help `|Y |`This help` +|`preferences show `|Y |`Show all preferences` + + +### preferences get + + { Get a preference } + +|command |offline |description +|------- |------- |----------- +|`preferences get barmode`|Y |`Get bar mode preference` +|`preferences get clientdebug`|Y |`Get client debug level preference` +|`preferences get color `|Y |`Get color support preference` +|`preferences get savepaths`|Y |`Get file folder ` +|`preferences get emoji `|Y |`Get emoji display preference` +|`preferences get hints `|Y |`Get hint display preference` +|`preferences get plotsliders`|Y |`Get plot slider display preference` + + +### preferences set + + { Set a preference } + +|command |offline |description +|------- |------- |----------- +|`preferences set help `|Y |`This help` +|`preferences set barmode`|Y |`Set bar mode` +|`preferences set clientdebug`|Y |`Set client debug level` +|`preferences set color `|Y |`Set color support` +|`preferences set emoji `|Y |`Set emoji display` +|`preferences set hints `|Y |`Set hint display` +|`preferences set savepaths`|Y |`... to be adjusted next ... ` +|`preferences set plotsliders`|Y |`Set plot slider display` + + ### analyse { Analyse utils... } @@ -53,38 +94,37 @@ Check column "offline" for their availability. |`data manrawdecode `|Y |`Manchester decode binary stream in DemodBuffer` |`data modulation `|Y |`Identify LF signal for clock and modulation` |`data rawdemod `|Y |`Demodulate the data in the GraphBuffer and output binary` -|`data askedgedetect `|Y |`[threshold] Adjust Graph for manual ASK demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)` +|`data askedgedetect `|Y |`Adjust Graph for manual ASK demod using the length of sample differences to detect the edge of a wave` |`data autocorr `|Y |`Autocorrelation over window` -|`data dirthreshold `|Y |` -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev.` +|`data dirthreshold `|Y |`Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev.` |`data decimate `|Y |`Decimate samples` |`data undecimate `|Y |`Un-decimate samples` |`data hide `|Y |`Hide graph window` |`data hpf `|Y |`Remove DC offset from trace` -|`data iir `|Y |`apply IIR buttersworth filter on plotdata` -|`data grid `|Y |` -- overlay grid on graph window, use zero value to turn off either` -|`data ltrim `|Y |` -- Trim samples from left of trace` -|`data mtrim `|Y |` -- Trim out samples from the specified start to the specified stop` +|`data iir `|Y |`Apply IIR buttersworth filter on plot data` +|`data grid `|Y |`overlay grid on graph window` +|`data ltrim `|Y |`Trim samples from left of trace` +|`data mtrim `|Y |`Trim out samples from the specified start to the specified stop` |`data norm `|Y |`Normalize max/min to +/-128` -|`data plot `|Y |`Show graph window (hit 'h' in window for keystroke help)` -|`data rtrim `|Y |` -- Trim samples from right of trace` -|`data setgraphmarkers `|Y |`[orange_marker] [blue_marker] (in graph window)` -|`data shiftgraphzero `|Y |` -- Shift 0 for Graphed wave + or - shift value` -|`data timescale `|Y |`Set a timescale to get a differential reading between the yellow and purple markers as time duration -` +|`data plot `|Y |`Show graph window` +|`data rtrim `|Y |`Trim samples from right of trace` +|`data setgraphmarkers `|Y |`Set blue and orange marker in graph window` +|`data shiftgraphzero `|Y |`Shift 0 for Graphed wave + or - shift value` +|`data timescale `|Y |`Set a timescale to get a differential reading between the yellow and purple markers as time duration` |`data zerocrossings `|Y |`Count time between zero-crossings` |`data convertbitstream `|Y |`Convert GraphBuffer's 0/1 values to 127 / -127` |`data getbitstream `|Y |`Convert GraphBuffer's >=1 values to 1 and <1 to 0` |`data bin2hex `|Y |`Converts binary to hexadecimal` |`data bitsamples `|N |`Get raw samples as bitstring` |`data clear `|Y |`Clears bigbuf on deviceside and graph window` -|`data hexsamples `|N |` [] -- Dump big buffer as hex bytes` +|`data hexsamples `|N |`Dump big buffer as hex bytes` |`data hex2bin `|Y |`Converts hexadecimal to binary` |`data load `|Y |`Load contents of file into graph window` |`data ndef `|Y |`Decode NDEF records` -|`data print `|Y |`print the data in the DemodBuffer` -|`data samples `|N |`[512 - 40000] -- Get raw samples for graph window (GraphBuffer)` +|`data print `|Y |`Print the data in the DemodBuffer` +|`data samples `|N |`Get raw samples for graph window (GraphBuffer)` |`data save `|Y |`Save signal trace data (from graph window)` -|`data setdebugmode `|Y |`<0|1|2> -- Set Debugging Level on client side` +|`data setdebugmode `|Y |`Set Debugging Level on client side` |`data tune `|N |`Measure tuning of device antenna. Results shown in graph window` @@ -223,6 +263,7 @@ Check column "offline" for their availability. |`hf felica help `|Y |`This help` |`hf felica list `|Y |`List ISO 18092/FeliCa history` |`hf felica reader `|N |`Act like an ISO18092/FeliCa reader` +|`hf felica info `|N |`Tag information` |`hf felica sniff `|N |`Sniff ISO 18092/FeliCa traffic` |`hf felica raw `|N |`Send raw hex data to tag` |`hf felica rdunencrypted`|N |`read Block Data from authentication-not-required Service.` @@ -235,7 +276,7 @@ Check column "offline" for their availability. |`hf felica auth2 `|N |`allow a card to authenticate a Reader/Writer. Complete mutual authentication` |`hf felica rqspecver `|N |`acquire the version of card OS.` |`hf felica resetmode `|N |`reset Mode to Mode 0.` -|`hf felica litesim `|N |` - only reply to poll request` +|`hf felica litesim `|N |`Emulating ISO/18092 FeliCa Lite tag` |`hf felica litedump `|N |`Wait for and try dumping FelicaLite` @@ -289,6 +330,7 @@ Check column "offline" for their availability. |`hf iclass eload `|N |`Load Picopass / iCLASS dump file into emulator memory` |`hf iclass esave `|N |`Save emulator memory to file` |`hf iclass eview `|N |`View emulator memory` +|`hf iclass configcard `|Y |`Reader configuration card` |`hf iclass calcnewkey `|Y |`Calc diversified keys (blocks 3 & 4) to write new keys` |`hf iclass encode `|Y |`Encode binary wiegand to block 7` |`hf iclass encrypt `|Y |`Encrypt given block data` @@ -361,6 +403,7 @@ Check column "offline" for their availability. |`hf mf rdsc `|N |`Read MIFARE Classic sector` |`hf mf restore `|N |`Restore MIFARE Classic binary file to BLANK tag` |`hf mf setmod `|N |`Set MIFARE Classic EV1 load modulation strength` +|`hf mf wipe `|N |`Wipe card to zeros and default keys/acc` |`hf mf wrbl `|N |`Write MIFARE Classic block` |`hf mf sim `|N |`Simulate MIFARE card` |`hf mf ecfill `|N |`Fill simulator memory with help of keys from simulator` @@ -520,6 +563,7 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`hw help `|Y |`This help` +|`hw break `|N |`Send break loop usb command` |`hw connect `|Y |`Connect Proxmark3 to serial port` |`hw dbg `|N |`Set Proxmark3 debug level` |`hw detectreader `|N |`Detect external reader field` @@ -1125,44 +1169,3 @@ 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 d2fdecb8ed9277a2934ce82039017b343e92fb1d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 8 Apr 2021 09:58:06 +0200 Subject: [PATCH 178/373] text --- doc/commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/commands.md b/doc/commands.md index e1d41758d..8404a9b69 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -202,7 +202,7 @@ Check column "offline" for their availability. |`hf 14b sim `|N |`Fake ISO 14443B tag` |`hf 14b sniff `|N |`Eavesdrop ISO 14443B` |`hf 14b rdbl `|N |`Read SRI512/SRIX4x block` -|`hf 14b sriwrite `|N |`Write data to a SRI512 | SRIX4K tag` +|`hf 14b sriwrite `|N |`Write data to a SRI512 or SRIX4K tag` ### hf 15 From a731bccb012f28a9e9f178155b0fea78fd061047 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 8 Apr 2021 10:01:18 +0200 Subject: [PATCH 179/373] inverse to please osx --- client/src/cmdhficlass.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index e40cde2a1..a40affc42 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -189,10 +189,10 @@ static int load_config_cards(void) { } static const iclass_config_card_item_t *get_config_card_item(int idx) { - if (idx < 0 && idx > 13) { - idx = 13; + if (idx > -1 && idx < 14) { + return &iclass_config_types[idx]; } - return &iclass_config_types[idx]; + return &iclass_config_types[13]; } static void print_config_cards(void) { From 3e1b041ff866f915c58f05c3b6a63310b81b676f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 8 Apr 2021 10:37:33 +0200 Subject: [PATCH 180/373] fix coverity CID 317346 --- client/src/cmdsmartcard.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/src/cmdsmartcard.c b/client/src/cmdsmartcard.c index 00d730d62..1b89b7301 100644 --- a/client/src/cmdsmartcard.c +++ b/client/src/cmdsmartcard.c @@ -434,6 +434,7 @@ static int CmdSmartRaw(const char *Cmd) { uint8_t *buf = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t)); if (buf == NULL) { PrintAndLogEx(DEBUG, "failed to allocate memory"); + free(payload); return PM3_EMALLOC; } @@ -447,6 +448,7 @@ static int CmdSmartRaw(const char *Cmd) { // reading response from smart card int len = smart_response(buf, PM3_CMD_DATA_SIZE); if (len < 0) { + free(payload); free(buf); return PM3_ESOFT; } @@ -1140,6 +1142,7 @@ int ExchangeAPDUSC(bool verbose, uint8_t *datain, int datainlen, bool activateCa int len = smart_responseEx(dataout, maxdataoutlen, verbose); if (len < 0) { + free(payload); return 1; } @@ -1158,7 +1161,6 @@ int ExchangeAPDUSC(bool verbose, uint8_t *datain, int datainlen, bool activateCa } free(payload); - *dataoutlen = len; return 0; } From 31c5722ac0fcd73c4f3b88cd2f6ea7f3f403ecdd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 8 Apr 2021 10:38:10 +0200 Subject: [PATCH 181/373] fix coverity CID 317343,317344 ... --- client/src/cmdhficlass.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index a40affc42..aff0be344 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -243,6 +243,7 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke if (got_kr == false) { PrintAndLogEx(ERR, "please specifiy KEYROLL key!"); + free(data); return PM3_EINVARG; } @@ -269,6 +270,7 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke PrintAndLogEx(INFO, "Detecting cardhelper..."); if (IsCardHelperPresent(false) == false) { PrintAndLogEx(FAILED, "failed to detect cardhelper"); + free(data); return PM3_ENODATA; } @@ -335,6 +337,7 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke saveFileJSON(filename, jsfIclass, data, tot_bytes, NULL); PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass view -f %s.bin") "` to view dump file", filename); + free(data); return PM3_SUCCESS; } From 27184d7f5b8675d1bcd1a0155e621e9f986d884f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 8 Apr 2021 10:44:31 +0200 Subject: [PATCH 182/373] style --- armsrc/Standalone/hf_craftbyte.c | 4 +- armsrc/Standalone/hf_tcprst.c | 2 +- armsrc/appmain.c | 4 +- armsrc/felica.c | 6 +- armsrc/hitag2.c | 510 ++++++++++----------- armsrc/i2c.c | 12 +- armsrc/lfadc.c | 8 +- armsrc/mifarecmd.c | 8 +- armsrc/mifaresim.c | 32 +- armsrc/spiffs.c | 2 +- client/deps/amiitool/amiibo.c | 2 +- client/deps/hardnested/hardnested_tables.c | 8 +- client/luascripts/lf_em4100_bulk.lua | 14 +- client/src/preferences.c | 14 +- client/src/proxmark3.c | 2 +- client/src/scripting.c | 2 +- client/src/util.c | 8 +- common/cardhelper.c | 4 +- tools/mf_nonce_brute/Makefile | 6 +- tools/mf_nonce_brute/mf_trace_brute.c | 18 +- tools/recover_pk.py | 2 +- 21 files changed, 334 insertions(+), 334 deletions(-) diff --git a/armsrc/Standalone/hf_craftbyte.c b/armsrc/Standalone/hf_craftbyte.c index 0193002ce..83bc01896 100644 --- a/armsrc/Standalone/hf_craftbyte.c +++ b/armsrc/Standalone/hf_craftbyte.c @@ -5,7 +5,7 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// main code for hf_craftbyte +// main code for hf_craftbyte //----------------------------------------------------------------------------- // // @@ -77,7 +77,7 @@ void RunMod(void) { flags |= FLAG_4B_UID_IN_DATA; } else if (card.uidlen == 7) { flags |= FLAG_7B_UID_IN_DATA; - } else if (card.uidlen == 10){ + } else if (card.uidlen == 10) { flags |= FLAG_10B_UID_IN_DATA; } else { Dbprintf("Unusual UID length, something is wrong. Try again please."); diff --git a/armsrc/Standalone/hf_tcprst.c b/armsrc/Standalone/hf_tcprst.c index d60db82ad..a15e4a7eb 100644 --- a/armsrc/Standalone/hf_tcprst.c +++ b/armsrc/Standalone/hf_tcprst.c @@ -327,7 +327,7 @@ void RunMod(void) { if (i == 4) { // Get NDEF Data - if (apdubuffer[1] == 0x1b && apdubuffer[2] == 0xd1) { + if (apdubuffer[1] == 0x1b && apdubuffer[2] == 0xd1) { gotndef = true; memcpy(&ndef, &apdubuffer, apdulen - 2); break; diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 7c1bde05b..dfbec3780 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1112,7 +1112,7 @@ static void PacketReceived(PacketCommandNG *packet) { } break; } - case CMD_LF_HITAG_ELOAD: { + case CMD_LF_HITAG_ELOAD: { /* struct p { uint16_t len; @@ -1746,7 +1746,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_SMART_RAW: { - SmartCardRaw((smart_card_raw_t*)packet->data.asBytes); + SmartCardRaw((smart_card_raw_t *)packet->data.asBytes); break; } case CMD_SMART_UPLOAD: { diff --git a/armsrc/felica.c b/armsrc/felica.c index 182f496aa..a00378881 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -592,7 +592,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { WDT_HIT(); // since simulation is a tight time critical loop, - // we only check for user request to end at iteration 3000, 9000. + // we only check for user request to end at iteration 3000, 9000. if (flip == 3) { if (data_available()) { retval = PM3_EOPABORTED; @@ -689,7 +689,7 @@ void felica_sim_lite(uint8_t *uid) { uint8_t *curresp = NULL; bool listenmode = true; // uint32_t frtm = GetCountSspClk(); - + uint8_t flip = 0; uint16_t checker = 0; for (;;) { @@ -697,7 +697,7 @@ void felica_sim_lite(uint8_t *uid) { WDT_HIT(); // since simulation is a tight time critical loop, - // we only check for user request to end at iteration 3000, 9000. + // we only check for user request to end at iteration 3000, 9000. if (flip == 3) { if (data_available()) { retval = PM3_EOPABORTED; diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index eb232fb05..07feb80e0 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -998,311 +998,311 @@ void SniffHitag2(void) { DbpString("Starting Hitag2 sniffing"); LED_D_ON(); - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); set_tracing(true); -/* - lf_init(false, false); + /* + lf_init(false, false); - // no logging of the raw signal - g_logging = lf_get_reader_modulation(); - uint32_t total_count = 0; + // no logging of the raw signal + g_logging = lf_get_reader_modulation(); + uint32_t total_count = 0; - uint8_t rx[20 * 8 * 2]; - while (BUTTON_PRESS() == false) { + uint8_t rx[20 * 8 * 2]; + while (BUTTON_PRESS() == false) { - lf_reset_counter(); + lf_reset_counter(); - WDT_HIT(); + WDT_HIT(); - size_t periods = 0; - uint16_t rxlen = 0; - memset(rx, 0x00, sizeof(rx)); + size_t periods = 0; + uint16_t rxlen = 0; + memset(rx, 0x00, sizeof(rx)); - // Use the current modulation state as starting point - uint8_t mod_state = lf_get_reader_modulation(); + // Use the current modulation state as starting point + uint8_t mod_state = lf_get_reader_modulation(); - while (rxlen < sizeof(rx)) { - periods = lf_count_edge_periods(64); - // Evaluate the number of periods before the next edge - if (periods >= 24 && periods < 64) { - // Detected two sequential equal bits and a modulation switch - // NRZ modulation: (11 => --|) or (11 __|) - rx[rxlen++] = mod_state; - rx[rxlen++] = mod_state; - // toggle tag modulation state - mod_state ^= 1; - } else if (periods > 0 && periods < 24) { - // Detected one bit and a modulation switch - // NRZ modulation: (1 => -|) or (0 _|) - rx[rxlen++] = mod_state; - mod_state ^= 1; - } else { - mod_state ^= 1; - break; - } - } - - if (rxlen == 0) - continue; - - // tag sends 11111 + uid, - bool got_tag = ((memcmp(rx, "\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00", 10) == 0)); - - if (got_tag) { - // mqnchester decode - bool bad_man = false; - uint16_t bitnum = 0; - for (uint16_t i = 0; i < rxlen; i += 2) { - if (rx[i] == 1 && (rx[i + 1] == 0)) { - rx[bitnum++] = 0; - } else if ((rx[i] == 0) && rx[i + 1] == 1) { - rx[bitnum++] = 1; + while (rxlen < sizeof(rx)) { + periods = lf_count_edge_periods(64); + // Evaluate the number of periods before the next edge + if (periods >= 24 && periods < 64) { + // Detected two sequential equal bits and a modulation switch + // NRZ modulation: (11 => --|) or (11 __|) + rx[rxlen++] = mod_state; + rx[rxlen++] = mod_state; + // toggle tag modulation state + mod_state ^= 1; + } else if (periods > 0 && periods < 24) { + // Detected one bit and a modulation switch + // NRZ modulation: (1 => -|) or (0 _|) + rx[rxlen++] = mod_state; + mod_state ^= 1; } else { - bad_man = true; + mod_state ^= 1; + break; } } - if (bad_man) { - DBG DbpString("bad manchester"); - continue; - } - - if (bitnum < 5) { - DBG DbpString("too few bits"); - continue; - } - - // skip header 11111 - uint16_t i = 0; - if (got_tag) { - i = 5; - } - - // Pack the response into a byte array - rxlen = 0; - for (; i < bitnum; i++) { - uint8_t b = rx[i]; - rx[rxlen >> 3] |= b << (7 - (rxlen % 8)); - rxlen++; - } - - // skip spurious bit - if (rxlen % 8 == 1) { - rxlen--; - } - - // nothing to log if (rxlen == 0) continue; - LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false); - total_count += nbytes(rxlen); - } else { - // decode reader comms - LogTrace(rx, rxlen, 0, 0, NULL, true); - total_count += rxlen; - // Pack the response into a byte array + // tag sends 11111 + uid, + bool got_tag = ((memcmp(rx, "\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00", 10) == 0)); - // LogTrace(rx, nbytes(rdr), 0, 0, NULL, true); - // total_count += nbytes(rdr); + if (got_tag) { + // mqnchester decode + bool bad_man = false; + uint16_t bitnum = 0; + for (uint16_t i = 0; i < rxlen; i += 2) { + if (rx[i] == 1 && (rx[i + 1] == 0)) { + rx[bitnum++] = 0; + } else if ((rx[i] == 0) && rx[i + 1] == 1) { + rx[bitnum++] = 1; + } else { + bad_man = true; + } + } + + if (bad_man) { + DBG DbpString("bad manchester"); + continue; + } + + if (bitnum < 5) { + DBG DbpString("too few bits"); + continue; + } + + // skip header 11111 + uint16_t i = 0; + if (got_tag) { + i = 5; + } + + // Pack the response into a byte array + rxlen = 0; + for (; i < bitnum; i++) { + uint8_t b = rx[i]; + rx[rxlen >> 3] |= b << (7 - (rxlen % 8)); + rxlen++; + } + + // skip spurious bit + if (rxlen % 8 == 1) { + rxlen--; + } + + // nothing to log + if (rxlen == 0) + continue; + + LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false); + total_count += nbytes(rxlen); + } else { + // decode reader comms + LogTrace(rx, rxlen, 0, 0, NULL, true); + total_count += rxlen; + // Pack the response into a byte array + + // LogTrace(rx, nbytes(rdr), 0, 0, NULL, true); + // total_count += nbytes(rdr); + } + LED_A_INV(); } - LED_A_INV(); - } - lf_finalize(); + lf_finalize(); - Dbprintf("Collected %u bytes", total_count); + Dbprintf("Collected %u bytes", total_count); - */ + */ - // Set up eavesdropping mode, frequency divisor which will drive the FPGA - // and analog mux selection. - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); // 125Khz - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); + // Set up eavesdropping mode, frequency divisor which will drive the FPGA + // and analog mux selection. + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); // 125Khz + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); - // Configure output pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + // Configure output pin that is connected to the FPGA (for modulating) + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + + // Disable modulation, we are going to eavesdrop, not modulate ;) + LOW(GPIO_SSC_DOUT); + + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; + + // Disable timer during configuration + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + + // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // external trigger rising edge, load RA on rising edge of TIOA. + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH; + + // Enable and reset counter + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - // Disable modulation, we are going to eavesdrop, not modulate ;) - LOW(GPIO_SSC_DOUT); - - // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); - AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - - // Disable timer during configuration - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, - // external trigger rising edge, load RA on rising edge of TIOA. - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH; - - // Enable and reset counter - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - int frame_count = 0, response = 0, overflow = 0, lastbit = 1, tag_sof = 4; - bool rising_edge = false, reader_frame = false, bSkip = true; - uint8_t rx[HITAG_FRAME_LEN]; - size_t rxlen = 0; - - auth_table_len = 0; - auth_table_pos = 0; + bool rising_edge = false, reader_frame = false, bSkip = true; + uint8_t rx[HITAG_FRAME_LEN]; + size_t rxlen = 0; + + auth_table_len = 0; + auth_table_pos = 0; + + // Reset the received frame, frame count and timing info + memset(rx, 0x00, sizeof(rx)); - // Reset the received frame, frame count and timing info - memset(rx, 0x00, sizeof(rx)); - auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); - memset(auth_table, 0x00, AUTH_TABLE_LENGTH); + memset(auth_table, 0x00, AUTH_TABLE_LENGTH); - while(BUTTON_PRESS() == false) { + while (BUTTON_PRESS() == false) { - WDT_HIT(); + WDT_HIT(); memset(rx, 0x00, sizeof(rx)); - // Receive frame, watch for at most T0 * EOF periods - while (AT91C_BASE_TC1->TC_CV < (HITAG_T0 * HITAG_T_EOF) ) { - // Check if rising edge in modulation is detected - if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values - int ra = (AT91C_BASE_TC1->TC_RA / HITAG_T0); - - // Find out if we are dealing with a rising or falling edge - rising_edge = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME) > 0; + // Receive frame, watch for at most T0 * EOF periods + while (AT91C_BASE_TC1->TC_CV < (HITAG_T0 * HITAG_T_EOF)) { + // Check if rising edge in modulation is detected + if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { + // Retrieve the new timing values + int ra = (AT91C_BASE_TC1->TC_RA / HITAG_T0); - // Shorter periods will only happen with reader frames - if (reader_frame == false && rising_edge && ra < HITAG_T_TAG_CAPTURE_ONE_HALF) { - // Switch from tag to reader capture - LED_C_OFF(); - reader_frame = true; - rxlen = 0; - } - - // Only handle if reader frame and rising edge, or tag frame and falling edge - if (reader_frame == rising_edge) { + // Find out if we are dealing with a rising or falling edge + rising_edge = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME) > 0; + + // Shorter periods will only happen with reader frames + if (reader_frame == false && rising_edge && ra < HITAG_T_TAG_CAPTURE_ONE_HALF) { + // Switch from tag to reader capture + LED_C_OFF(); + reader_frame = true; + rxlen = 0; + } + + // Only handle if reader frame and rising edge, or tag frame and falling edge + if (reader_frame == rising_edge) { overflow += ra; - continue; - } - - // Add the buffered timing values of earlier captured edges which were skipped - ra += overflow; - overflow = 0; - - if (reader_frame) { - LED_B_ON(); - // Capture reader frame - if(ra >= HITAG_T_STOP) { + continue; + } + + // Add the buffered timing values of earlier captured edges which were skipped + ra += overflow; + overflow = 0; + + if (reader_frame) { + LED_B_ON(); + // Capture reader frame + if (ra >= HITAG_T_STOP) { // if (rxlen != 0) { - //DbpString("wierd0?"); + //DbpString("wierd0?"); // } - // Capture the T0 periods that have passed since last communication or field drop (reset) - response = (ra - HITAG_T_LOW); - } else if(ra >= HITAG_T_1_MIN ) { - // '1' bit - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } else if(ra >= HITAG_T_0_MIN) { - // '0' bit - rx[rxlen / 8] |= 0 << (7-(rxlen%8)); - rxlen++; - } + // Capture the T0 periods that have passed since last communication or field drop (reset) + response = (ra - HITAG_T_LOW); + } else if (ra >= HITAG_T_1_MIN) { + // '1' bit + rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); + rxlen++; + } else if (ra >= HITAG_T_0_MIN) { + // '0' bit + rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); + rxlen++; + } - } else { - LED_C_ON(); - // Capture tag frame (manchester decoding using only falling edges) - if(ra >= HITAG_T_EOF) { + } else { + LED_C_ON(); + // Capture tag frame (manchester decoding using only falling edges) + if (ra >= HITAG_T_EOF) { // if (rxlen != 0) { - //DbpString("wierd1?"); + //DbpString("wierd1?"); // } - // Capture the T0 periods that have passed since last communication or field drop (reset) - // We always recieve a 'one' first, which has the falling edge after a half period |-_| - response = ra - HITAG_T_TAG_HALF_PERIOD; + // Capture the T0 periods that have passed since last communication or field drop (reset) + // We always recieve a 'one' first, which has the falling edge after a half period |-_| + response = ra - HITAG_T_TAG_HALF_PERIOD; - } else if(ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { - // Manchester coding example |-_|_-|-_| (101) - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; + } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { + // Manchester coding example |-_|_-|-_| (101) + rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); + rxlen++; + rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); + rxlen++; - } else if(ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { - // Manchester coding example |_-|...|_-|-_| (0...01) - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - // We have to skip this half period at start and add the 'one' the second time - if (bSkip == false) { - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } - lastbit = !lastbit; - bSkip = !bSkip; + } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { + // Manchester coding example |_-|...|_-|-_| (0...01) + rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); + rxlen++; + // We have to skip this half period at start and add the 'one' the second time + if (bSkip == false) { + rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); + rxlen++; + } + lastbit = !lastbit; + bSkip = !bSkip; - } else if(ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { - // Manchester coding example |_-|_-| (00) or |-_|-_| (11) - if (tag_sof) { - // Ignore bits that are transmitted during SOF - tag_sof--; - } else { - // bit is same as last bit - rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8)); - rxlen++; - } - } - } - } - } - - // Check if frame was captured - if(rxlen) { - frame_count++; - LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame); - - // Check if we recognize a valid authentication attempt - if (nbytes(rxlen) == 8) { - // Store the authentication attempt - if (auth_table_len < (AUTH_TABLE_LENGTH - 8)) { - memcpy(auth_table + auth_table_len, rx, 8); - auth_table_len += 8; - } - } - - // Reset the received frame and response timing info - memset(rx, 0x00, sizeof(rx)); - response = 0; - reader_frame = false; - lastbit = 1; - bSkip = true; - tag_sof = 4; - overflow = 0; - - LED_B_OFF(); - LED_C_OFF(); - } else { - // Save the timer overflow, will be 0 when frame was received - overflow += (AT91C_BASE_TC1->TC_CV / HITAG_T0); - } - // Reset the frame length - rxlen = 0; - // Reset the timer to restart while-loop that receives frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { + // Manchester coding example |_-|_-| (00) or |-_|-_| (11) + if (tag_sof) { + // Ignore bits that are transmitted during SOF + tag_sof--; + } else { + // bit is same as last bit + rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8)); + rxlen++; + } + } + } + } + } + + // Check if frame was captured + if (rxlen) { + frame_count++; + LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame); + + // Check if we recognize a valid authentication attempt + if (nbytes(rxlen) == 8) { + // Store the authentication attempt + if (auth_table_len < (AUTH_TABLE_LENGTH - 8)) { + memcpy(auth_table + auth_table_len, rx, 8); + auth_table_len += 8; + } + } + + // Reset the received frame and response timing info + memset(rx, 0x00, sizeof(rx)); + response = 0; + reader_frame = false; + lastbit = 1; + bSkip = true; + tag_sof = 4; + overflow = 0; + + LED_B_OFF(); + LED_C_OFF(); + } else { + // Save the timer overflow, will be 0 when frame was received + overflow += (AT91C_BASE_TC1->TC_CV / HITAG_T0); + } + // Reset the frame length + rxlen = 0; + // Reset the timer to restart while-loop that receives frames AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; - } + AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + } LEDsoff(); - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - set_tracing(false); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(false); - Dbprintf("frame received: %d",frame_count); - Dbprintf("Authentication Attempts: %d",(auth_table_len / 8)); + Dbprintf("frame received: %d", frame_count); + Dbprintf("Authentication Attempts: %d", (auth_table_len / 8)); } diff --git a/armsrc/i2c.c b/armsrc/i2c.c index dab9108cc..1b5a001ba 100644 --- a/armsrc/i2c.c +++ b/armsrc/i2c.c @@ -735,7 +735,7 @@ void SmartCardRaw(smart_card_raw_t *p) { if ((flags & SC_LOG) == SC_LOG) set_tracing(true); - else + else set_tracing(false); if ((flags & SC_CONNECT) == SC_CONNECT) { @@ -758,11 +758,11 @@ void SmartCardRaw(smart_card_raw_t *p) { LogTrace(p->data, p->len, 0, 0, NULL, true); bool res = I2C_BufferWrite( - p->data, - p->len, - ((flags & SC_RAW_T0) ? I2C_DEVICE_CMD_SEND_T0 : I2C_DEVICE_CMD_SEND), - I2C_DEVICE_ADDRESS_MAIN - ); + p->data, + p->len, + ((flags & SC_RAW_T0) ? I2C_DEVICE_CMD_SEND_T0 : I2C_DEVICE_CMD_SEND), + I2C_DEVICE_ADDRESS_MAIN + ); if (res == false && DBGLEVEL > 3) { DbpString(I2C_ERROR); reply_ng(CMD_SMART_RAW, PM3_ESOFT, NULL, 0); diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index 037481ba7..6a351bfca 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -79,7 +79,7 @@ static size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { #define LIMIT_DEV 20 - // timeout limit to 100 000 w/o + // timeout limit to 100 000 w/o uint32_t timeout = 100000; size_t periods = 0; uint8_t avg_peak = adc_avg + LIMIT_DEV; @@ -135,7 +135,7 @@ static size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { } } - } + } } previous_adc_val = adc_val; @@ -220,8 +220,8 @@ void lf_init(bool reader, bool simulate) { // When in reader mode, give the field a bit of time to settle. // 313T0 = 313 * 8us = 2504us = 2.5ms Hitag2 tags needs to be fully powered. // if (reader) { - // 10 ms - SpinDelay(10); + // 10 ms + SpinDelay(10); // } // Steal this pin from the SSP (SPI communication channel with fpga) and use it to control the modulation diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index bcb47aa24..b35a4d6e3 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -663,10 +663,10 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain) { // Return 1 if the nonce is invalid else return 0 static int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) { return ( - (oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1, 16))) && \ - (oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1, 8))) && \ - (oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1, 0))) - ) ? 1 : 0; + (oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1, 16))) && \ + (oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1, 8))) && \ + (oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1, 0))) + ) ? 1 : 0; } void MifareAcquireNonces(uint32_t arg0, uint32_t flags) { diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 6018f6b30..ee8560994 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -545,24 +545,24 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 counter++; } -/* - // find reader field - if (cardSTATE == MFEMUL_NOFIELD) { + /* + // find reader field + if (cardSTATE == MFEMUL_NOFIELD) { -#if defined RDV4 - vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * SumAdc(ADC_CHAN_HF_RDV40, 32)) >> 15; -#else - vHf = (MAX_ADC_HF_VOLTAGE * SumAdc(ADC_CHAN_HF, 32)) >> 15; -#endif + #if defined RDV4 + vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * SumAdc(ADC_CHAN_HF_RDV40, 32)) >> 15; + #else + vHf = (MAX_ADC_HF_VOLTAGE * SumAdc(ADC_CHAN_HF, 32)) >> 15; + #endif - if (vHf > MF_MINFIELDV) { - cardSTATE_TO_IDLE(); - LED_A_ON(); - } - button_pushed = BUTTON_PRESS(); - continue; - } - */ + if (vHf > MF_MINFIELDV) { + cardSTATE_TO_IDLE(); + LED_A_ON(); + } + button_pushed = BUTTON_PRESS(); + continue; + } + */ FpgaEnableTracing(); //Now, get data diff --git a/armsrc/spiffs.c b/armsrc/spiffs.c index d200eafc7..d5af6c399 100644 --- a/armsrc/spiffs.c +++ b/armsrc/spiffs.c @@ -213,7 +213,7 @@ uint32_t size_in_spiffs(const char *filename) { if (SPIFFS_stat(&fs, filename, &s) < 0) { Dbprintf("errno %i\n", SPIFFS_errno(&fs)); return 0; - } + } return s.size; } diff --git a/client/deps/amiitool/amiibo.c b/client/deps/amiitool/amiibo.c index edf7eb45f..7ef471f48 100644 --- a/client/deps/amiitool/amiibo.c +++ b/client/deps/amiitool/amiibo.c @@ -148,7 +148,7 @@ bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys *amiiboKeys) { return false; } - if ((amiiboKeys->data.magicBytesSize > 16) || (amiiboKeys->tag.magicBytesSize > 16)) { + if ((amiiboKeys->data.magicBytesSize > 16) || (amiiboKeys->tag.magicBytesSize > 16)) { free(dump); return false; } diff --git a/client/deps/hardnested/hardnested_tables.c b/client/deps/hardnested/hardnested_tables.c index f0155946f..1ab600275 100644 --- a/client/deps/hardnested/hardnested_tables.c +++ b/client/deps/hardnested/hardnested_tables.c @@ -376,7 +376,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t count[odd_even], odd_even == EVEN_STATE ? "even" : "odd", bitflip, - (1 << 24) - count[odd_even], + (1 << 24) - count[odd_even], (float)((1 << 24) - count[odd_even]) / (1 << 24) * 100.0); #ifndef TEST_RUN write_bitflips_file(odd_even, bitflip, sum_a0, test_bitarray[odd_even], count[odd_even]); @@ -404,7 +404,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t count[odd_even], odd_even == EVEN_STATE ? "even" : "odd", bitflip | BITFLIP_2ND_BYTE, - (1 << 24) - count[odd_even], + (1 << 24) - count[odd_even], (float)((1 << 24) - count[odd_even]) / (1 << 24) * 100.0); #ifndef TEST_RUN write_bitflips_file(odd_even, bitflip | BITFLIP_2ND_BYTE, sum_a0, test_bitarray_2nd, count[odd_even]); @@ -490,7 +490,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t count[odd_even], odd_even == EVEN_STATE ? "even" : "odd", bitflip | 0x100, - (1 << 24) - count[odd_even], + (1 << 24) - count[odd_even], (float)((1 << 24) - count[odd_even]) / (1 << 24) * 100.0); #ifndef TEST_RUN write_bitflips_file(odd_even, bitflip | 0x100, sum_a0, test_not_bitarray[odd_even], count[odd_even]); @@ -517,7 +517,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t printf("Writing %u possible %s states for bitflip property %03x (%u (%1.2f%%) states eliminated)\n", count[odd_even], odd_even == EVEN_STATE ? "even" : "odd", - bitflip | 0x100 | BITFLIP_2ND_BYTE, + bitflip | 0x100 | BITFLIP_2ND_BYTE, (1 << 24) - count[odd_even], (float)((1 << 24) - count[odd_even]) / (1 << 24) * 100.0); #ifndef TEST_RUN diff --git a/client/luascripts/lf_em4100_bulk.lua b/client/luascripts/lf_em4100_bulk.lua index d4cdfdd8d..3ec8a8387 100644 --- a/client/luascripts/lf_em4100_bulk.lua +++ b/client/luascripts/lf_em4100_bulk.lua @@ -14,12 +14,12 @@ Any other input char will exit the script. You can supply a password, which will set the config block / block 7 on the T5577. -The verify option will issue a 'lf em 410x reader' command, so you can manually verify +The verify option will issue a 'lf em 410x reader' command, so you can manually verify that the write worked. ]] example = [[ - -- resets and start enrolling EM410x id 11CC334455 + -- resets and start enrolling EM410x id 11CC334455 script run lf_em4100_bulk.lua -s 11CC334455 -- continue enrolling from where last iteration @@ -28,7 +28,7 @@ example = [[ -- reset and start enrolling from 11223344, -- protecting the tag with password 010203 -- and verify the em id write. - script run lf_em4100_bulk.lua -s 1122334455 -p 01020304 -v + script run lf_em4100_bulk.lua -s 1122334455 -p 01020304 -v ]] usage = [[ script run lf_en4100_bulk.lua [-h] [-c] [-p password] [-s ] [-v] @@ -143,7 +143,7 @@ local function main(args) end -- if reset/start over, check -s - if not shall_continue then + if not shall_continue then if startid == nil then return oops('empty card number string') end if #startid == 0 then return oops('empty card number string') end if #startid ~= 10 then return oops('card number wrong length. Must be 5 hex bytes') end @@ -159,7 +159,7 @@ local function main(args) print(ac.red..'disable hints for less output'..ac.reset) core.console('pref set hint --off') print('') - + local hi = tonumber(startid:sub(1, 2), 16) local low = tonumber(startid:sub(3, 10), 16) local pwd = tonumber(ipwd, 16) @@ -178,7 +178,7 @@ local function main(args) else print('reset & starting enrolling from refresh') end - + local template = 'EM4100 ID '..ac.green..'%02X%08X'..ac.reset for i = low, low + 10000, 1 do print('') @@ -186,7 +186,7 @@ local function main(args) local msg = (template):format(hi, i) local ans = utils.input(msg, 'y'):lower() if ans == 'y' then - core.console( ('lf em 410x clone --id %02X%08X'):format(hi, i) ) + core.console( ('lf em 410x clone --id %02X%08X'):format(hi, i) ) -- print ( ('lf em 410x clone --id %02X%08X'):format(hi, i) ) if got_pwd then diff --git a/client/src/preferences.c b/client/src/preferences.c index ccdcd249f..2a9f12650 100644 --- a/client/src/preferences.c +++ b/client/src/preferences.c @@ -440,15 +440,15 @@ static void showSavePathState(savePaths_t path_index, prefShowOpt_t opt) { if (path_index < spItemCount) { if ((session.defaultPaths[path_index] == NULL) || (strcmp(session.defaultPaths[path_index], "") == 0)) { PrintAndLogEx(INFO, " %s %s "_WHITE_("not set"), - prefShowMsg(opt), - s - ); + prefShowMsg(opt), + s + ); } else { PrintAndLogEx(INFO, " %s %s "_GREEN_("%s"), - prefShowMsg(opt), - s, - session.defaultPaths[path_index] - ); + prefShowMsg(opt), + s, + session.defaultPaths[path_index] + ); } } } diff --git a/client/src/proxmark3.c b/client/src/proxmark3.c index e804972f4..18dcf6bb5 100644 --- a/client/src/proxmark3.c +++ b/client/src/proxmark3.c @@ -521,7 +521,7 @@ static void set_my_user_directory(void) { char *cwd_buffer = (char *)calloc(pathLen, sizeof(uint8_t)); if (cwd_buffer == NULL) { PrintAndLogEx(WARNING, "failed to allocate memory"); - return; + return; } while (GetCurrentDir(cwd_buffer, pathLen) == NULL) { diff --git a/client/src/scripting.c b/client/src/scripting.c index 9287e1f31..e64276767 100644 --- a/client/src/scripting.c +++ b/client/src/scripting.c @@ -1281,7 +1281,7 @@ static int l_cwd(lua_State *L) { uint16_t path_len = FILENAME_MAX; // should be a good starting point char *cwd = (char *)calloc(path_len, sizeof(uint8_t)); if (cwd == NULL) { - return returnToLuaWithError(L, "Failed to allocate memory"); + return returnToLuaWithError(L, "Failed to allocate memory"); } while (GetCurrentDir(cwd, path_len) == NULL) { diff --git a/client/src/util.c b/client/src/util.c index 4697ffe23..c18917f08 100644 --- a/client/src/util.c +++ b/client/src/util.c @@ -299,7 +299,7 @@ char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t brea // manchester wrong bit marker if (c == 7) c = '.'; - else + else c += '0'; *(tmp++) = c; @@ -308,7 +308,7 @@ char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t brea if (breaks) { if (((i + 1) % breaks) == 0) { - *(tmp++) = '\n'; + *(tmp++) = '\n'; } } } @@ -1026,7 +1026,7 @@ int hexstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str) int binstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str) { uint32_t n = 0, i = 0; - for(;;) { + for (;;) { int res = sscanf(&str[i], "%1u", &n); if ((res != 1) || (n > 1)) @@ -1050,7 +1050,7 @@ int binstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str) */ int binarray_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, uint8_t *arr, int arrlen) { int i = 0; - for(; i < arrlen; i++) { + for (; i < arrlen; i++) { uint8_t n = arr[i]; if (n > 1) break; diff --git a/common/cardhelper.c b/common/cardhelper.c index 9b7ea9e9e..db62c49f6 100644 --- a/common/cardhelper.c +++ b/common/cardhelper.c @@ -91,7 +91,7 @@ void DecodeBlock6(uint8_t *src) { c[5] = 0x02; ExchangeAPDUSC(false, c, sizeof(c), false, false, resp, sizeof(resp), &resp_len); - + if (resp_len < 11) { return; } @@ -137,7 +137,7 @@ int GetConfigCardByIdx(uint8_t typ, uint8_t *blocks) { int resp_len = 0; uint8_t resp[254] = {0}; - uint8_t c[] = {0x96, CARD_INS_CC, 0x00, 0x00, 17, typ, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + uint8_t c[] = {0x96, CARD_INS_CC, 0x00, 0x00, 17, typ, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; ExchangeAPDUSC(false, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len); if (resp_len < 2) { diff --git a/tools/mf_nonce_brute/Makefile b/tools/mf_nonce_brute/Makefile index c68b828de..17bff27cc 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 = @@ -22,4 +22,4 @@ 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 +mf_trace_brute : $(OBJDIR)/mf_trace_brute.o $(MYOBJS) diff --git a/tools/mf_nonce_brute/mf_trace_brute.c b/tools/mf_nonce_brute/mf_trace_brute.c index c3973f5dc..0217bcdee 100644 --- a/tools/mf_nonce_brute/mf_trace_brute.c +++ b/tools/mf_nonce_brute/mf_trace_brute.c @@ -1,11 +1,11 @@ -// +// // 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 @@ -41,7 +41,7 @@ typedef struct thread_args { uint32_t part_key; uint32_t nt_enc; uint32_t nr_enc; - uint8_t enc[ENC_LEN]; // next encrypted command + a full read/write + uint8_t enc[ENC_LEN]; // next encrypted command + a full read/write } targs; //------------------------------------------------------------------ @@ -137,7 +137,7 @@ static int param_gethex_to_eol(const char *line, int paramnum, uint8_t *data, in } 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) { + const size_t min_str_len, const size_t spaces_between, bool uppercase) { if (buf == NULL) return; @@ -216,10 +216,10 @@ static void *brute_thread(void *arguments) { crypto1_deinit(pcs); - if (CheckCrc14443(CRC_14443_A, dec , 4)) { + 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 @@ -259,7 +259,7 @@ int main(int argc, char *argv[]) { sscanf(argv[4], "%x", &nr_enc); int enc_len = 0; - uint8_t enc[ENC_LEN] = {0}; // next encrypted command + a full read/write + 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"); @@ -267,7 +267,7 @@ int main(int argc, char *argv[]) { 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)); + printf("next encrypted cmd: %s\n", sprint_hex_inrow_ex(enc, ENC_LEN, 0)); clock_t t1 = clock(); diff --git a/tools/recover_pk.py b/tools/recover_pk.py index b242ff4cc..470f406ae 100755 --- a/tools/recover_pk.py +++ b/tools/recover_pk.py @@ -147,7 +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 007b9166435dadc9fcb4161d0ba6cad128fbae43 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 8 Apr 2021 11:08:39 +0200 Subject: [PATCH 183/373] style --- client/src/cmdflashmem.c | 20 ++--- client/src/cmdflashmemspiffs.c | 6 +- client/src/cmdhf14a.c | 2 +- client/src/cmdhf15.c | 4 +- client/src/cmdhfcryptorf.c | 26 +++---- client/src/cmdhfemrtd.c | 2 +- client/src/cmdhffelica.c | 136 ++++++++++++++++----------------- client/src/cmdhficlass.c | 38 ++++----- client/src/cmdhflist.c | 36 ++++----- client/src/cmdhflist.h | 2 +- client/src/cmdhfmf.c | 12 +-- client/src/cmdhfmfu.c | 52 ++++++------- client/src/cmdlf.c | 4 +- client/src/cmdlfem4x50.c | 2 +- client/src/cmdlfhid.c | 2 +- client/src/cmdlfhitag.c | 14 ++-- client/src/cmdlft55xx.c | 44 +++++------ client/src/cmdmain.c | 8 +- client/src/cmdsmartcard.c | 30 ++++---- client/src/comms.c | 2 +- client/src/mifare/mifarehost.c | 10 +-- 21 files changed, 226 insertions(+), 226 deletions(-) diff --git a/client/src/cmdflashmem.c b/client/src/cmdflashmem.c index bdc5dfd92..dfd5517d0 100644 --- a/client/src/cmdflashmem.c +++ b/client/src/cmdflashmem.c @@ -43,7 +43,7 @@ static int CmdHelp(const char *Cmd); //------------------------------------------------------------------------------------- int rdv4_get_signature(rdv40_validation_t *out) { - if (out == NULL) { + if (out == NULL) { return PM3_EINVARG; } @@ -89,7 +89,7 @@ int rdv4_validate(rdv40_validation_t *mem) { return PM3_EFAILED; } -static int rdv4_sign_write(uint8_t *signature, uint8_t slen){ +static int rdv4_sign_write(uint8_t *signature, uint8_t slen) { // save to mem clearCommandBuffer(); PacketResponseNG resp; @@ -439,14 +439,14 @@ static int CmdFlashMemInfo(const char *Cmd) { // shall_write = arg_get_lit(ctx, 5); CLIParserFree(ctx); - if (res || (dlen > 0 && dlen < sizeof(id)) ) { + if (res || (dlen > 0 && dlen < sizeof(id))) { PrintAndLogEx(FAILED, "Error parsing flash memory id, expect 8, got %d", dlen); return PM3_EINVARG; } // set up PK key context now. mbedtls_pk_context pkctx; - mbedtls_pk_init( &pkctx ); + mbedtls_pk_init(&pkctx); bool got_private = false; // PEM if (pemlen) { @@ -472,7 +472,7 @@ static int CmdFlashMemInfo(const char *Cmd) { return PM3_EFILE; } - mbedtls_rsa_context *rsa = (mbedtls_rsa_context*)pkctx.pk_ctx; + mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)pkctx.pk_ctx; if (rsa == NULL) { PrintAndLogEx(FAILED, "failed to allocate rsa context memory"); return PM3_EMALLOC; @@ -482,7 +482,7 @@ static int CmdFlashMemInfo(const char *Cmd) { } else { // it not loaded, we need to setup the context manually - if (mbedtls_pk_setup( &pkctx, mbedtls_pk_info_from_type( (mbedtls_pk_type_t) MBEDTLS_PK_RSA ) ) != 0 ) { + if (mbedtls_pk_setup(&pkctx, mbedtls_pk_info_from_type((mbedtls_pk_type_t) MBEDTLS_PK_RSA)) != 0) { PrintAndLogEx(FAILED, "failed, mbedtls_pk_setup returned "); return PM3_ESOFT; } @@ -491,7 +491,7 @@ static int CmdFlashMemInfo(const char *Cmd) { // validate devicesignature data rdv40_validation_t mem; res = rdv4_get_signature(&mem); - if (res != PM3_SUCCESS) { + if (res != PM3_SUCCESS) { return res; } @@ -521,7 +521,7 @@ static int CmdFlashMemInfo(const char *Cmd) { mbedtls_rsa_context *rsa = NULL; if (got_private) { - rsa = mbedtls_pk_rsa( pkctx ); + rsa = mbedtls_pk_rsa(pkctx); rsa->padding = MBEDTLS_RSA_PKCS_V15; rsa->hash_id = 0; rsa->len = RRG_RSA_KEY_LEN; @@ -531,7 +531,7 @@ static int CmdFlashMemInfo(const char *Cmd) { mbedtls_rsa_init(rsa, MBEDTLS_RSA_PKCS_V15, 0); rsa->len = RRG_RSA_KEY_LEN; - // add public key + // add public key mbedtls_mpi_read_string(&rsa->N, 16, RRG_RSA_N); mbedtls_mpi_read_string(&rsa->E, 16, RRG_RSA_E); } @@ -587,7 +587,7 @@ static int CmdFlashMemInfo(const char *Cmd) { PrintAndLogEx(INFO, "--- " _CYAN_("Enter signing") " --------------------"); if (dlen == 8) { - mbedtls_sha1(id, sizeof(id), sha_hash); + mbedtls_sha1(id, sizeof(id), sha_hash); } PrintAndLogEx(INFO, "Signing....... %s", sprint_hex_inrow(sha_hash, sizeof(sha_hash))); diff --git a/client/src/cmdflashmemspiffs.c b/client/src/cmdflashmemspiffs.c index 3b9214e95..a3695e658 100644 --- a/client/src/cmdflashmemspiffs.c +++ b/client/src/cmdflashmemspiffs.c @@ -334,7 +334,7 @@ static int CmdFlashMemSpiFFSDump(const char *Cmd) { 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_lit0("e", "eml", "also save in EML format"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -351,7 +351,7 @@ static int CmdFlashMemSpiFFSDump(const char *Cmd) { CLIParserFree(ctx); // get size from spiffs itself ! - clearCommandBuffer(); + clearCommandBuffer(); SendCommandNG(CMD_SPIFFS_STAT, (uint8_t *)src, slen); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_SPIFFS_STAT, &resp, 2000) == false) { @@ -495,7 +495,7 @@ static int CmdFlashMemSpiFFSView(const char *Cmd) { CLIParserFree(ctx); // get size from spiffs itself ! - clearCommandBuffer(); + clearCommandBuffer(); SendCommandNG(CMD_SPIFFS_STAT, (uint8_t *)src, slen); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_SPIFFS_STAT, &resp, 2000) == false) { diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 8e1134516..095bd5a44 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -2104,7 +2104,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { uint8_t signature[32] = {0}; res = detect_mfc_ev1_signature(signature); if (res == PM3_SUCCESS) { - mfc_ev1_print_signature(card.uid, card.uidlen, signature, sizeof(signature)); + mfc_ev1_print_signature(card.uid, card.uidlen, signature, sizeof(signature)); } PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mf`") " commands"); diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 189002d1a..9ac4385d1 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1171,7 +1171,7 @@ static int CmdHF15FindAfi(const char *Cmd) { break; } - if (WaitForResponseTimeout(CMD_HF_ISO15693_FINDAFI, &resp, 2000)){ + if (WaitForResponseTimeout(CMD_HF_ISO15693_FINDAFI, &resp, 2000)) { if (resp.status == PM3_EOPABORTED) { PrintAndLogEx(DEBUG, "Button pressed, user aborted"); } @@ -1370,7 +1370,7 @@ static int CmdHF15Dump(const char *Cmd) { // copy uid to read command memcpy(req + 2, uid, sizeof(uid)); - + PrintAndLogEx(INFO, "." NOLF); for (int retry = 0; retry < 5; retry++) { diff --git a/client/src/cmdhfcryptorf.c b/client/src/cmdhfcryptorf.c index 43dbcf6de..3640b9639 100644 --- a/client/src/cmdhfcryptorf.c +++ b/client/src/cmdhfcryptorf.c @@ -26,7 +26,7 @@ #ifndef CRYPTORF_MEM_SIZE # define CRYPTORF_MEM_SIZE 1024 -#endif +#endif static int CmdHelp(const char *Cmd); @@ -85,7 +85,7 @@ static int CmdHFCryptoRFSniff(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_HF_ISO14443B_SNIFF, NULL, 0); - + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf cryptorf list") "` to view captured tracelog"); PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -f hf_cryptorf_mytrace") "` to save tracelog for later analysing"); return PM3_SUCCESS; @@ -247,9 +247,9 @@ static int CmdHFCryptoRFReader(const char *Cmd) { static int CmdHFCryptoRFDump(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf cryptorf dump", - "Dump all memory from a CryptoRF tag (512/4096 bit size)", - "hf cryptorf dump\n" - ); + "Dump all memory from a CryptoRF tag (512/4096 bit size)", + "hf cryptorf dump\n" + ); void *argtable[] = { arg_param_begin, @@ -393,9 +393,9 @@ static int CmdHFCryptoRFELoad(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf cryptorf eload", - "Loads CryptoRF tag dump into emulator memory on device", - "hf cryptorf eload -f hf-cryptorf-0102030405-dump.bin\n" - ); + "Loads CryptoRF tag dump into emulator memory on device", + "hf cryptorf eload -f hf-cryptorf-0102030405-dump.bin\n" + ); void *argtable[] = { arg_param_begin, @@ -455,11 +455,11 @@ static int CmdHFCryptoRFESave(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf cryptorf esave", - "Save emulator memory to bin/eml/json file\n" - "if filename is not supplied, UID will be used.", - "hf cryptorf esave\n" - "hf cryptorf esave -f filename" - ); + "Save emulator memory to bin/eml/json file\n" + "if filename is not supplied, UID will be used.", + "hf cryptorf esave\n" + "hf cryptorf esave -f filename" + ); void *argtable[] = { arg_param_begin, arg_str0("f", "file", "", "filename of dumpfile"), diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index ab2e3d896..caa24b4ac 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1217,7 +1217,7 @@ static void emrtd_mrz_replace_pad(char *data, int datalen, char newchar) { static void emrtd_print_optional_elements(char *mrz, int offset, int length, bool verify_check_digit) { int i = emrtd_mrz_determine_length(mrz, offset, length); - if (i == -1){ + if (i == -1) { return; } diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 7948dbadb..8cf536e49 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -1351,24 +1351,24 @@ static int CmdHFFelicaRequestSystemCode(const char *Cmd) { static int CmdHFFelicaRequestService(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf felica rqservice", - "Use this command to verify the existence of Area and Service, and to acquire Key Version:\n" - " - When the specified Area or Service exists, the card returns Key Version.\n" - " - When the specified Area or Service does not exist, the card returns FFFFh as Key Version.\n" - "For Node Code List of a command packet, Area Code or Service Code of the target\n" - "of acquisition of Key Version shall be enumerated in Little Endian format.\n" - "If Key Version of System is the target of acquisition, FFFFh shall be specified\n" - "in the command packet.", - "hf felcia rqservice --node 01 --code FFFF\n" - "hf felcia rqservice -a --code FFFF\n" - "hf felica rqservice -i 011204126417E405 --node 01 --code FFFF" - ); + "Use this command to verify the existence of Area and Service, and to acquire Key Version:\n" + " - When the specified Area or Service exists, the card returns Key Version.\n" + " - When the specified Area or Service does not exist, the card returns FFFFh as Key Version.\n" + "For Node Code List of a command packet, Area Code or Service Code of the target\n" + "of acquisition of Key Version shall be enumerated in Little Endian format.\n" + "If Key Version of System is the target of acquisition, FFFFh shall be specified\n" + "in the command packet.", + "hf felcia rqservice --node 01 --code FFFF\n" + "hf felcia rqservice -a --code FFFF\n" + "hf felica rqservice -i 011204126417E405 --node 01 --code FFFF" + ); void *argtable[] = { arg_param_begin, arg_lit0("a", "all", "auto node number mode, iterates through all possible nodes 1 < n < 32"), arg_str0("n", "node", "", "Number of Node"), arg_str0("c", "code", "", "Node Code List (little endian)"), - arg_str0("i", "idm", "", "use custom IDm"), + arg_str0("i", "idm", "", "use custom IDm"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -1383,41 +1383,41 @@ static int CmdHFFelicaRequestService(const char *Cmd) { bool custom_IDm = false; uint16_t datalen = 13; // length (1) + CMD (1) + IDm(8) + Node Number (1) + Node Code List (2) -/* - case 'i': + /* + case 'i': - custom_IDm = true; - if (!add_param(Cmd, paramCount, data, 2, 16)) { - return PM3_EINVARG; - } - - - if (!all_nodes) { - // Node Number - if (param_getlength(Cmd, paramCount) == 2) { - - if (param_gethex(Cmd, paramCount++, data + 10, 2) == 1) { - PrintAndLogEx(ERR, "Failed param key"); + custom_IDm = true; + if (!add_param(Cmd, paramCount, data, 2, 16)) { return PM3_EINVARG; } + + if (!all_nodes) { + // Node Number + if (param_getlength(Cmd, paramCount) == 2) { + + if (param_gethex(Cmd, paramCount++, data + 10, 2) == 1) { + PrintAndLogEx(ERR, "Failed param key"); + return PM3_EINVARG; + } + + } else { + PrintAndLogEx(ERR, "Incorrect Node number length!"); + return PM3_EINVARG; + } + } + + if (param_getlength(Cmd, paramCount) == 4) { + + if (param_gethex(Cmd, paramCount++, data + 11, 4) == 1) { + PrintAndLogEx(ERR, "Failed param key"); + return PM3_EINVARG; + } } else { - PrintAndLogEx(ERR, "Incorrect Node number length!"); + PrintAndLogEx(ERR, "Incorrect parameter length!"); return PM3_EINVARG; } - } - - if (param_getlength(Cmd, paramCount) == 4) { - - if (param_gethex(Cmd, paramCount++, data + 11, 4) == 1) { - PrintAndLogEx(ERR, "Failed param key"); - return PM3_EINVARG; - } - } else { - PrintAndLogEx(ERR, "Incorrect parameter length!"); - return PM3_EINVARG; - } -*/ + */ uint8_t flags = FELICA_APPEND_CRC; if (custom_IDm) { @@ -1458,11 +1458,11 @@ static int CmdHFFelicaNotImplementedYet(const char *Cmd) { static int CmdHFFelicaSniff(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf felica sniff", - "Collect data from the field and save into command buffer.\n" - "Buffer accessible from `hf felica list`", - "hf felica sniff\n" - "hf felica sniff -s 10 -t 19" - ); + "Collect data from the field and save into command buffer.\n" + "Buffer accessible from `hf felica list`", + "hf felica sniff\n" + "hf felica sniff -s 10 -t 19" + ); void *argtable[] = { arg_param_begin, arg_u64_0("s", "samples", "", "samples to skip"), @@ -1480,20 +1480,20 @@ static int CmdHFFelicaSniff(const char *Cmd) { payload.triggers = arg_get_u32_def(ctx, 2, 5000); CLIParserFree(ctx); - if (payload.samples > 9999 ){ + if (payload.samples > 9999) { payload.samples = 9999; PrintAndLogEx(INFO, "Too large samples to skip value, using max value 9999"); return PM3_EINVARG; } - if (payload.triggers > 9999 ){ + if (payload.triggers > 9999) { payload.triggers = 9999; PrintAndLogEx(INFO, "Too large trigger to skip value, using max value 9999"); return PM3_EINVARG; } - PrintAndLogEx(INFO, "Sniff Felica, getting first %" PRIu32 " frames, skipping after %" PRIu32 " triggers", payload.samples, payload.triggers ); + PrintAndLogEx(INFO, "Sniff Felica, getting first %" PRIu32 " frames, skipping after %" PRIu32 " triggers", payload.samples, payload.triggers); PrintAndLogEx(INFO, "Press " _GREEN_("") " or pm3-button to abort sniffing"); clearCommandBuffer(); SendCommandNG(CMD_HF_FELICA_SNIFF, (uint8_t *)&payload, sizeof(payload)); @@ -1524,9 +1524,9 @@ static int CmdHFFelicaSniff(const char *Cmd) { static int CmdHFFelicaSimLite(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf felica litesim", - "Emulating ISO/18092 FeliCa Lite tag", - "hf felica litesim -u 1122334455667788" - ); + "Emulating ISO/18092 FeliCa Lite tag", + "hf felica litesim -u 1122334455667788" + ); void *argtable[] = { arg_param_begin, arg_str1("u", "uid", "", "UID/NDEF2 8 hex bytes"), @@ -1538,7 +1538,7 @@ static int CmdHFFelicaSimLite(const char *Cmd) { uint8_t uid[8]; } PACKED payload; CLIGetHexWithReturn(ctx, 1, payload.uid, &uid_len); - CLIParserFree(ctx); + CLIParserFree(ctx); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "Press " _GREEN_("") " or pm3-button to abort simulation"); @@ -1720,26 +1720,26 @@ static uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t trac static int CmdHFFelicaDumpLite(const char *Cmd) { -/* -iceman 2021, -Why does this command say it dumps a FeliCa lite card -and then tries to print a trace?!? -Is this a trace list or a feclia dump cmd? -*/ + /* + iceman 2021, + Why does this command say it dumps a FeliCa lite card + and then tries to print a trace?!? + Is this a trace list or a feclia dump cmd? + */ CLIParserContext *ctx; CLIParserInit(&ctx, "hf felica litedump", - "Dump ISO/18092 FeliCa Lite tag. It will timeout after 200sec", - "hf felica litedump" - ); + "Dump ISO/18092 FeliCa Lite tag. It will timeout after 200sec", + "hf felica litedump" + ); void *argtable[] = { arg_param_begin, arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - CLIParserFree(ctx); - + CLIParserFree(ctx); + PrintAndLogEx(SUCCESS, "FeliCa lite - dump started"); clearCommandBuffer(); @@ -1814,12 +1814,12 @@ Is this a trace list or a feclia dump cmd? } static int CmdHFFelicaCmdRaw(const char *Cmd) { - + CLIParserContext *ctx; CLIParserInit(&ctx, "hf felica raw ", - "Send raw hex data to tag", - "hf felica raw -s 20" - ); + "Send raw hex data to tag", + "hf felica raw -s 20" + ); void *argtable[] = { arg_param_begin, @@ -1837,7 +1837,7 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { bool active = arg_get_lit(ctx, 1); bool crc = arg_get_lit(ctx, 2); bool keep_field_on = arg_get_lit(ctx, 3); - uint16_t numbits = arg_get_u32_def(ctx, 4, 0) &0xFFFF; + uint16_t numbits = arg_get_u32_def(ctx, 4, 0) & 0xFFFF; bool reply = (arg_get_lit(ctx, 5) == false); bool active_select = arg_get_lit(ctx, 6); diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index aff0be344..1628d95a2 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -37,7 +37,7 @@ #define ICLASS_AUTH_RETRY 10 #define ICLASS_DECRYPTION_BIN "iclass_decryptionkey.bin" -static picopass_hdr_t iclass_last_known_card; +static picopass_hdr_t iclass_last_known_card; static void iclass_set_last_known_card(picopass_hdr_t *card) { memcpy(&iclass_last_known_card, card, sizeof(picopass_hdr_t)); } @@ -134,7 +134,7 @@ uint8_t card_app2_limit[] = { 0xff, }; -iclass_config_card_item_t iclass_config_types[14]= { +iclass_config_card_item_t iclass_config_types[14] = { {"", ""}, {"", ""}, {"", ""}, @@ -148,7 +148,7 @@ iclass_config_card_item_t iclass_config_types[14]= { {"", ""}, {"", ""}, {"", ""}, - // must be the last entry + // must be the last entry {"no config card info available", ""} }; @@ -167,7 +167,7 @@ static int load_config_cards(void) { PrintAndLogEx(FAILED, "failed to detect cardhelper"); return PM3_ENODATA; } - + for (int i = 0; i < ARRAYLEN(iclass_config_types); ++i) { PrintAndLogEx(INPLACE, "loading setting %i", i); @@ -198,7 +198,7 @@ static const iclass_config_card_item_t *get_config_card_item(int idx) { static void print_config_cards(void) { if (check_config_card(&iclass_config_types[0])) { PrintAndLogEx(INFO, "---- " _CYAN_("Config cards available") " ------------"); - for (int i = 0; i < ARRAYLEN(iclass_config_types); ++i) { + for (int i = 0; i < ARRAYLEN(iclass_config_types); ++i) { PrintAndLogEx(INFO, "%2d, %s", i, iclass_config_types[i].desc); } PrintAndLogEx(NORMAL, ""); @@ -225,7 +225,7 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke return res; } - // generate dump file + // generate dump file uint8_t app1_limit = iclass_last_known_card.conf.app_limit; uint8_t old_limit = app1_limit; uint8_t tot_bytes = (app1_limit + 1) * 8; @@ -246,16 +246,16 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke free(data); return PM3_EINVARG; } - + if (app1_limit < 0x16) { // if card wasn't large enough before, adapt to new size PrintAndLogEx(WARNING, "Adapting applimit1 for KEY rolling.."); - + app1_limit = 0x16; iclass_last_known_card.conf.app_limit = 0x16; tot_bytes = (app1_limit + 1) * 8; - uint8_t *p; + uint8_t *p; p = realloc(data, tot_bytes); if (p == NULL) { PrintAndLogEx(FAILED, "failed to allocate memory"); @@ -265,8 +265,8 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke data = p; memset(data, 0xFF, tot_bytes); } - - // need to encrypt + + // need to encrypt PrintAndLogEx(INFO, "Detecting cardhelper..."); if (IsCardHelperPresent(false) == false) { PrintAndLogEx(FAILED, "failed to detect cardhelper"); @@ -274,7 +274,7 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke return PM3_ENODATA; } - uint8_t ffs[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + uint8_t ffs[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; if (Encrypt(ffs, ffs) == false) { PrintAndLogEx(WARNING, "failed to encrypt FF"); } @@ -291,7 +291,7 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke memcpy(data + (0xD * 8), enckey1, sizeof(enckey1)); // encrypted 0xFF for (uint8_t i = 0xe; i < 0x14; i++) { - memcpy(data + (i*8), ffs, sizeof(ffs)); + memcpy(data + (i * 8), ffs, sizeof(ffs)); } // encrypted partial keyroll key 14 @@ -320,10 +320,10 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke // revert potential modified app1_limit iclass_last_known_card.conf.app_limit = old_limit; - } else { + } else { memcpy(data, &iclass_last_known_card, sizeof(picopass_hdr_t)); - memcpy(data + (6*8), o->data, sizeof(o->data)); - } + memcpy(data + (6 * 8), o->data, sizeof(o->data)); + } // create filename char filename[FILE_PATH_SIZE] = {0}; @@ -1167,7 +1167,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { PrintAndLogEx(INFO, "Couldn't find any decryption methods"); return PM3_EINVARG; } - + if (keylen != 16) { PrintAndLogEx(ERR, "Failed to load transport key from file"); free(keyptr); @@ -3711,7 +3711,7 @@ static int CmdHFiClassAutopwn(const char *Cmd) { } */ -static int CmdHFiClassConfigCard(const char * Cmd) { +static int CmdHFiClassConfigCard(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf iclass configcard", @@ -3756,7 +3756,7 @@ static int CmdHFiClassConfigCard(const char * Cmd) { if (load) { if (load_config_cards() != PM3_SUCCESS) { - PrintAndLogEx(INFO, "failed to load, check your cardhelper"); + PrintAndLogEx(INFO, "failed to load, check your cardhelper"); } } diff --git a/client/src/cmdhflist.c b/client/src/cmdhflist.c index 278928d08..6a6d57fd7 100644 --- a/client/src/cmdhflist.c +++ b/client/src/cmdhflist.c @@ -59,8 +59,8 @@ uint8_t iso14443A_CRC_check(bool isResponse, uint8_t *d, uint8_t n) { if (n < 3) return 2; if (isResponse && (n < 6)) return 2; if (d[1] == 0x50 && - d[0] >= ISO14443A_CMD_ANTICOLL_OR_SELECT && - d[0] <= ISO14443A_CMD_ANTICOLL_OR_SELECT_3) { + d[0] >= ISO14443A_CMD_ANTICOLL_OR_SELECT && + d[0] <= ISO14443A_CMD_ANTICOLL_OR_SELECT_3) { return 2; } return check_crc(CRC_14443_A, d, n); @@ -1337,13 +1337,13 @@ 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}; +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 + else sprintf(s++, "0"); } } @@ -1444,25 +1444,25 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes //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}; + 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}; + 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}; + 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) - ); + , AuthData.uid + , AuthData.nt_enc + , snt + , AuthData.nr_enc + , AuthData.ar_enc + , sar + , AuthData.at_enc + , sat + , sprint_hex_inrow(cmd, cmdsize) + ); MifareAuthState = masError; diff --git a/client/src/cmdhflist.h b/client/src/cmdhflist.h index b59c9fca2..fe4a99208 100644 --- a/client/src/cmdhflist.h +++ b/client/src/cmdhflist.h @@ -18,7 +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 + 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 diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index a72383d86..b07e1573b 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -1251,7 +1251,7 @@ static int CmdHF14AMfRestore(const char *Cmd) { if (use_keyfile_for_auth) { - for (uint8_t kt=0; kt < 2; kt++) { + for (uint8_t kt = 0; kt < 2; kt++) { if (kt == 0) memcpy(data, keyA[sectorNo], 6); @@ -5589,7 +5589,7 @@ static int CmdHF14AMfWipe(const char *Cmd) { "New acc FF 07 80\n" "New GDB 69", "hf mf wipe" - ); + ); void *argtable[] = { arg_param_begin, arg_str0("f", "file", "", "key filename"), @@ -5652,12 +5652,12 @@ static int CmdHF14AMfWipe(const char *Cmd) { } } - uint8_t zeros[MFBLOCK_SIZE] = {0}; - memset(zeros, 0x00, sizeof(zeros)); - uint8_t st[MFBLOCK_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + uint8_t zeros[MFBLOCK_SIZE] = {0}; + memset(zeros, 0x00, sizeof(zeros)); + uint8_t st[MFBLOCK_SIZE] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // time to wipe card - for (uint8_t s = 0; s < num_sectors; s++) { + for (uint8_t s = 0; s < num_sectors; s++) { for (uint8_t b = 0; b < NumBlocksPerSector(s); b++) { diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index c9279592d..88b7849d5 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -949,7 +949,7 @@ static int mfu_decrypt_amiibo(uint8_t *encrypted, uint16_t elen, uint8_t *decryp if (elen < NFC3D_AMIIBO_SIZE / 4) { PrintAndLogEx(ERR, "ERR, data wrong length, got %zu , expected %zu", elen, (NFC3D_AMIIBO_SIZE / 4)); - return PM3_ESOFT; + return PM3_ESOFT; } nfc3d_amiibo_keys amiibo_keys = {0}; @@ -961,7 +961,7 @@ static int mfu_decrypt_amiibo(uint8_t *encrypted, uint16_t elen, uint8_t *decryp PrintAndLogEx(ERR, "WARNING, Tag signature was NOT valid"); } - *dlen = NFC3D_AMIIBO_SIZE; + *dlen = NFC3D_AMIIBO_SIZE; return PM3_SUCCESS; } static int mfu_dump_tag(uint16_t pages, void **pdata, uint16_t *len) { @@ -1016,10 +1016,10 @@ out: } */ /* -Lego Dimensions, +Lego Dimensions, Version: 00 04 04 02 01 00 0F 03 - - matching bytes: + + matching bytes: index 12 ( 3 * 4 ) E1 10 12 00 01 03 A0 0C 34 03 13 D1 01 0F 54 02 65 6E */ @@ -1075,7 +1075,7 @@ static mfu_identify_t mfu_ident_table[] = { {NULL, NULL, 0, 0, NULL, NULL, NULL, NULL} }; -static mfu_identify_t* mfu_match_fingerprint(uint8_t *version, uint8_t *data) { +static mfu_identify_t *mfu_match_fingerprint(uint8_t *version, uint8_t *data) { uint8_t i = 0; do { @@ -1140,7 +1140,7 @@ static int mfu_fingerprint(void) { res = PM3_ESOFT; goto out; } - + maxbytes = ((maxbytes / 4) + 1) * 4; data = calloc(maxbytes, sizeof(uint8_t)); if (data == NULL) { @@ -1184,7 +1184,7 @@ static int mfu_fingerprint(void) { uint8_t version[8] = {0}; uint8_t uid[7] = {0}; if (mfu_get_version_uid(version, uid) == PM3_SUCCESS) { - mfu_identify_t* item = mfu_match_fingerprint(version, data); + mfu_identify_t *item = mfu_match_fingerprint(version, data); if (item) { PrintAndLogEx(SUCCESS, "Found " _GREEN_("%s"), item->desc); @@ -3280,30 +3280,30 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) { if (memcmp(pre, post, sizeof(pre)) == 0) { PrintAndLogEx(INFO, "Current : %02d (0x%02X) %s" - , blockno - , blockno - , poststr - ); + , blockno + , blockno + , poststr + ); } else { PrintAndLogEx(INFO, _CYAN_("Tear off occurred") " : %02d (0x%02X) %s => " _RED_("%s") - , blockno - , blockno - , prestr - , poststr - ); + , blockno + , blockno + , prestr + , poststr + ); lock_on = true; - if ((phase_begin_clear == -1) && (bitcount32(*(uint32_t*)pre) > bitcount32(*(uint32_t*)post))) + 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)) + 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)))) + 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)) @@ -3346,7 +3346,7 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) { if ((phase_begin_clear > - 1) && (phase_begin_clear != start)) { PrintAndLogEx(INFO, "Erase phase start boundary around " _YELLOW_("%5d") " us", phase_begin_clear); } - if ((phase_end_clear > - 1) && (phase_end_clear != start)){ + 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) { @@ -3754,8 +3754,8 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) { */ -// -// name, identifying bytes, decode function, hints text +// +// name, identifying bytes, decode function, hints text // identifying bits // 1. getversion data must match. // 2. magic bytes in the readable payload @@ -3889,7 +3889,7 @@ static int CmdHF14MfuNDEF(const char *Cmd) { } } } - char *mattel = strstr((char*)records, ".pid.mattel/"); + char *mattel = strstr((char *)records, ".pid.mattel/"); if (mattel) { mattel += 12; while (mattel) { @@ -3906,7 +3906,7 @@ static int CmdHF14MfuNDEF(const char *Cmd) { PrintAndLogEx(INFO, "decoded... %s", sprint_hex(arr, arrlen)); break; } - } + } } free(records); diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index 65f0386c9..c1d0e4bb1 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -562,7 +562,7 @@ int CmdLFConfig(const char *Cmd) { config.decimation = 8; } - if (divisor> -1) { + if (divisor > -1) { config.divisor = divisor; if (config.divisor < 19) { PrintAndLogEx(ERR, "divisor must be between 19 and 255"); @@ -1437,7 +1437,7 @@ int CmdLFfind(const char *Cmd) { if (demodIOProx(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("IO Prox ID") " found!"); goto out;} if (demodPyramid(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Pyramid ID") " found!"); goto out;} if (demodParadox(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!"); goto out;} - + // psk if (demodIdteck(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!"); goto out;} if (demodKeri(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("KERI ID") " found!"); goto out;} diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index bba8bf664..0b188ec24 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -470,7 +470,7 @@ int CmdEM4x50Chk(const char *Cmd) { // upload to flash. datalen = MIN(bytes_remaining, keyblock); - res = flashmem_spiffs_load((char*)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/cmdlfhid.c b/client/src/cmdlfhid.c index 02ccd5801..ff3a27fd9 100644 --- a/client/src/cmdlfhid.c +++ b/client/src/cmdlfhid.c @@ -388,7 +388,7 @@ static int CmdHIDClone(const char *Cmd) { packed.Mid = mid; packed.Bot = bot; } else if (bin_len) { - int res = binstring_to_u96(&top, &mid, &bot, (const char*)bin); + int res = binstring_to_u96(&top, &mid, &bot, (const char *)bin); if (res != bin_len) { PrintAndLogEx(ERR, "Binary string contains none <0|1> chars"); return PM3_EINVARG; diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index a9f21d4fe..c03a9ca89 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -292,7 +292,7 @@ static int CmdLFHitagEload(const char *Cmd) { return PM3_EINVARG; } - DumpFileType_t dftype = getfiletype(filename); + DumpFileType_t dftype = getfiletype(filename); size_t dumplen = 0; uint8_t *dump = NULL; int res = 0; @@ -327,7 +327,7 @@ static int CmdLFHitagEload(const char *Cmd) { return PM3_EFILE; } - // check dump len.. + // check dump len.. if (dumplen == 48 || dumplen == 4 * 64) { struct { uint16_t len; @@ -337,7 +337,7 @@ static int CmdLFHitagEload(const char *Cmd) { memcpy(payload.data, dump, dumplen); clearCommandBuffer(); - SendCommandNG(CMD_LF_HITAG_ELOAD, (uint8_t *)&payload, 2 + dumplen); + SendCommandNG(CMD_LF_HITAG_ELOAD, (uint8_t *)&payload, 2 + dumplen); } else { PrintAndLogEx(ERR, "error, wrong dump file size. got %zu", dumplen); } @@ -368,7 +368,7 @@ static int CmdLFHitagSim(const char *Cmd) { bool use_hts = arg_get_lit(ctx, 3); CLIParserFree(ctx); - if ((use_ht1 + use_ht2 + use_hts) > 1 ) { + if ((use_ht1 + use_ht2 + use_hts) > 1) { PrintAndLogEx(ERR, "error, Only specify one Hitag type"); return PM3_EINVARG; } @@ -659,11 +659,11 @@ static int CmdLFHitagCheckChallenges(const char *Cmd) { size_t datalen = 0; int res = loadFile_safe(filename, ".cc", (void **)&data, &datalen); if (res == PM3_SUCCESS) { - if (datalen == (8 * 60) ) { + if (datalen == (8 * 60)) { SendCommandOLD(CMD_LF_HITAGS_TEST_TRACES, 1, 0, 0, data, datalen); } else { - PrintAndLogEx(ERR, "Error, file length mismatch. Expected %d, got %zu", 8*60, datalen); - } + PrintAndLogEx(ERR, "Error, file length mismatch. Expected %d, got %zu", 8 * 60, datalen); + } } if (data) { free(data); diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index acea99f13..99db98058 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -440,8 +440,8 @@ static int CmdT55xxSetConfig(const char *Cmd) { 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(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"), @@ -458,9 +458,9 @@ static int CmdT55xxSetConfig(const char *Cmd) { 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++; + mods[idx - 1] = arg_get_lit(ctx, idx); + verify_mods += mods[idx - 1]; + idx++; } // Not these flags are used to Toggle the values. @@ -516,7 +516,7 @@ static int CmdT55xxSetConfig(const char *Cmd) { break; } } - if (i == 9){ + if (i == 9) { PrintAndLogEx(FAILED, "Error select a valid bitrate"); return PM3_EINVARG; } @@ -532,7 +532,7 @@ static int CmdT55xxSetConfig(const char *Cmd) { // 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) { + if (use_st) { config.ST ^= use_st; config.block0 = ((config.block0 & ~(0x8)) | (config.ST << 3)); } @@ -557,7 +557,7 @@ static int CmdT55xxSetConfig(const char *Cmd) { config.downlink_mode = downlink_mode; // validate user specific modulation - if (mods[0]){ + if (mods[0]) { config.modulation = DEMOD_FSK; } else if (mods[1]) { config.modulation = DEMOD_FSK1; @@ -587,7 +587,7 @@ static int CmdT55xxSetConfig(const char *Cmd) { } else if (mods[11]) { config.modulation = DEMOD_BIa; config.inverted = 1; - } + } config.block0 = ((config.block0 & ~(0x1f000)) | (config.modulation << 12)); @@ -643,10 +643,10 @@ static int CmdT55xxReadBlock(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf t55xx read", "Read T55xx block data. This commands defaults to page 0.\n\n" - _RED_(" * * * WARNING * * *") "\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_(" * * * * * * * * * *"), + _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" @@ -657,7 +657,7 @@ static int CmdT55xxReadBlock(const char *Cmd) { 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("o", "override", "override safety check"), arg_lit0(NULL, "pg1", "read page 1"), }; uint8_t idx = 5; @@ -1680,7 +1680,7 @@ static int CmdT55xxReadTrace(const char *Cmd) { // 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"), + 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); @@ -1731,7 +1731,7 @@ static int CmdT55xxReadTrace(const char *Cmd) { } } - if (DemodBufferLen == 0){ + if (DemodBufferLen == 0) { return PM3_ESOFT; } @@ -2360,13 +2360,13 @@ static int CmdT55xxRestore(const char *Cmd) { } } - if (retval != PM3_SUCCESS) { + 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. // // @@ -3058,9 +3058,9 @@ static int CmdT55xxChkPwds(const char *Cmd) { } 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 (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) @@ -3069,7 +3069,7 @@ static int CmdT55xxChkPwds(const char *Cmd) { downlink_mode = ref1of4; 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"); } @@ -3265,10 +3265,10 @@ static int CmdT55xxBruteForce(const char *Cmd) { } 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. + // 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 +// else if (r1) downlink_mode = refLongLeading; else if (r2) diff --git a/client/src/cmdmain.c b/client/src/cmdmain.c index e85935dfb..e54ee9275 100644 --- a/client/src/cmdmain.c +++ b/client/src/cmdmain.c @@ -280,9 +280,9 @@ static int CmdPref(const char *Cmd) { static int CmdClear(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "clear", - "Clear the Proxmark3 client terminal screen", - "clear" - ); + "Clear the Proxmark3 client terminal screen", + "clear" + ); void *argtable[] = { arg_param_begin, arg_param_end @@ -296,7 +296,7 @@ static int CmdClear(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "Use `" _YELLOW_(" help") "` for details of a command"}, - {"preferences", CmdPref, AlwaysAvailable, "{ Edit client/device preferences... }"}, + {"preferences", CmdPref, AlwaysAvailable, "{ Edit client/device preferences... }"}, {"--------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("Technology") " -----------------------"}, {"analyse", CmdAnalyse, AlwaysAvailable, "{ Analyse utils... }"}, {"data", CmdData, AlwaysAvailable, "{ Plot window / data buffer manipulation... }"}, diff --git a/client/src/cmdsmartcard.c b/client/src/cmdsmartcard.c index 1b89b7301..7c2e615d7 100644 --- a/client/src/cmdsmartcard.c +++ b/client/src/cmdsmartcard.c @@ -262,7 +262,7 @@ static int smart_wait(uint8_t *out, int maxoutlen, bool verbose) { clearCommandBuffer(); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_SMART_RAW, &resp, 1000)) { - + if (resp.status != PM3_SUCCESS) { if (verbose) PrintAndLogEx(WARNING, "smart card response status failed"); return -3; @@ -283,7 +283,7 @@ static int smart_wait(uint8_t *out, int maxoutlen, bool verbose) { if (len >= 2) { if (verbose) { - + if (out[len - 2] == 0x90 && out[len - 1] == 0x00) { PrintAndLogEx(SUCCESS, _GREEN_("%02X%02X") " | %s", out[len - 2], out[len - 1], GetAPDUCodeDescription(out[len - 2], out[len - 1])); } else { @@ -299,7 +299,7 @@ static int smart_wait(uint8_t *out, int maxoutlen, bool verbose) { } } while (i--); - if (verbose) { + if (verbose) { PrintAndLogEx(WARNING, "smart card response timeout"); } return -1; @@ -330,7 +330,7 @@ static int smart_responseEx(uint8_t *out, int maxoutlen, bool verbose) { memcpy(payload->data, cmd_getresp, sizeof(cmd_getresp)); clearCommandBuffer(); - SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + sizeof(cmd_getresp)); + SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + sizeof(cmd_getresp)); free(payload); datalen = smart_wait(out, maxoutlen, verbose); @@ -424,7 +424,7 @@ static int CmdSmartRaw(const char *Cmd) { payload->flags |= SC_SELECT; } - if (dlen > 0) { + if (dlen > 0) { if (use_t0) payload->flags |= SC_RAW_T0; else @@ -439,9 +439,9 @@ static int CmdSmartRaw(const char *Cmd) { } clearCommandBuffer(); - SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + dlen); + SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + dlen); - if (reply == false) { + if (reply == false) { goto out; } @@ -459,7 +459,7 @@ static int CmdSmartRaw(const char *Cmd) { data[4] = buf[1]; memcpy(payload->data, data, dlen); clearCommandBuffer(); - SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + dlen); + SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + dlen); len = smart_response(buf, PM3_CMD_DATA_SIZE); @@ -858,7 +858,7 @@ static void smart_brute_prim(void) { memcpy(payload->data, get_card_data + i, 5); clearCommandBuffer(); - SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + 5); + SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + 5); free(payload); int len = smart_responseEx(buf, PM3_CMD_DATA_SIZE, false); @@ -901,7 +901,7 @@ static int smart_brute_sfi(bool decodeTLV) { memcpy(payload->data, READ_RECORD, sizeof(READ_RECORD)); clearCommandBuffer(); - SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + sizeof(READ_RECORD)); + SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + sizeof(READ_RECORD)); len = smart_responseEx(buf, PM3_CMD_DATA_SIZE, false); @@ -910,7 +910,7 @@ static int smart_brute_sfi(bool decodeTLV) { memcpy(payload->data, READ_RECORD, sizeof(READ_RECORD)); clearCommandBuffer(); - SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + sizeof(READ_RECORD)); + SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + sizeof(READ_RECORD)); len = smart_responseEx(buf, PM3_CMD_DATA_SIZE, false); READ_RECORD[4] = 0; @@ -952,7 +952,7 @@ static void smart_brute_options(bool decodeTLV) { memcpy(payload->data, GET_PROCESSING_OPTIONS, sizeof(GET_PROCESSING_OPTIONS)); clearCommandBuffer(); - SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + sizeof(GET_PROCESSING_OPTIONS)); + SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + sizeof(GET_PROCESSING_OPTIONS)); free(payload); int len = smart_responseEx(buf, PM3_CMD_DATA_SIZE, false); @@ -1054,7 +1054,7 @@ static int CmdSmartBruteforceSFI(const char *Cmd) { memcpy(payload->data, cmddata, hexlen); clearCommandBuffer(); - SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + hexlen); + SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + hexlen); free(payload); int len = smart_responseEx(buf, PM3_CMD_DATA_SIZE, false); @@ -1138,7 +1138,7 @@ int ExchangeAPDUSC(bool verbose, uint8_t *datain, int datainlen, bool activateCa memcpy(payload->data, datain, datainlen); clearCommandBuffer(); - SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + datainlen); + SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + datainlen); int len = smart_responseEx(dataout, maxdataoutlen, verbose); if (len < 0) { @@ -1155,7 +1155,7 @@ int ExchangeAPDUSC(bool verbose, uint8_t *datain, int datainlen, bool activateCa datain[4] = dataout[len - 1]; memcpy(payload->data, datain, 5); clearCommandBuffer(); - SendCommandNG(CMD_SMART_RAW, (uint8_t*)payload, sizeof(smart_card_raw_t) + 5); + SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + 5); datain[4] = 0; len = smart_responseEx(dataout, maxdataoutlen, verbose); } diff --git a/client/src/comms.c b/client/src/comms.c index 26c68d889..4e624aa86 100644 --- a/client/src/comms.c +++ b/client/src/comms.c @@ -839,7 +839,7 @@ 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, + // Spiffs download is converted to NG, if (response->cmd == CMD_SPIFFS_DOWNLOAD) return true; diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index 4a34421ba..48ac96acd 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((char*)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); @@ -769,7 +769,7 @@ int mfReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t *data) { mf_readblock_t payload = { .blockno = blockNo, .keytype = keyType - }; + }; memcpy(payload.key, key, sizeof(payload.key)); clearCommandBuffer(); @@ -1224,13 +1224,13 @@ int detect_mfc_ev1_signature(uint8_t *signature) { return PM3_EINVARG; } uint8_t sign[32] = {0}; - uint8_t key[] = {0x4b, 0x79, 0x1b, 0xea, 0x7b, 0xcc}; + uint8_t key[] = {0x4b, 0x79, 0x1b, 0xea, 0x7b, 0xcc}; int res = mfReadBlock(69, 1, key, sign); - if ( res == PM3_SUCCESS) { + if (res == PM3_SUCCESS) { res = mfReadBlock(70, 1, key, sign + 16); if (res == PM3_SUCCESS) { memcpy(signature, sign, sizeof(sign)); } } return res; -} \ No newline at end of file +} From 44fec5b0c7856bc0f6ad1974ff5d5014ceb9ee79 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 8 Apr 2021 11:29:54 +0200 Subject: [PATCH 184/373] text --- CHANGELOG.md | 2 ++ doc/cliparser_todo.txt | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae88615f8..cd5926616 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Changed `smart raw` - now uses NG (@iceman1001) + - Added `hf iclass configcard` - now can download / generate config card dumps with a cardhelper [WIP] (@iceman1001) - Fix swapped DESELECT and WTX annotations (@VortixDev) - Fixed `hf 15 findafi` - cliparser bug, and loop is user interruptable (@iceman1001) - Added `hf mf wipe` - takes a keyfile and wipes a MFC to default values (@iceman1001) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 27713fd58..e5a15c37f 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -7,10 +7,8 @@ hf 15 restore hf 15 wrbl hf 15 writeafi hf 15 writedsfid -hf felica reader hf felica rdunencrypted hf felica wrunencrypted -hf felica rqservice hf felica rqresponse hf felica scsvcode hf felica rqsyscode From 7becdffd6d53dc18ff1ba80feff0f20280211df6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 8 Apr 2021 15:57:13 +0300 Subject: [PATCH 185/373] work with apple/google pay --- client/src/emv/cmdemv.c | 2 ++ client/src/emv/emv_tags.c | 6 ++++-- client/src/emv/emvcore.c | 7 ++++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/client/src/emv/cmdemv.c b/client/src/emv/cmdemv.c index 3e0fec872..08f9435fd 100644 --- a/client/src/emv/cmdemv.c +++ b/client/src/emv/cmdemv.c @@ -52,6 +52,8 @@ static void ParamLoadDefaults(struct tlvdb *tlvRoot) { //95:(Terminal Verification Results) len:5 // all OK TVR TLV_ADD(0x95, "\x00\x00\x00\x00\x00"); + // 9F4E Merchant Name and Location len:x + TLV_ADD(0x9F4E, "proxmrk3rdv\x00"); } static void PrintChannel(EMVCommandChannel channel) { diff --git a/client/src/emv/emv_tags.c b/client/src/emv/emv_tags.c index f86b88826..6499bcd8e 100644 --- a/client/src/emv/emv_tags.c +++ b/client/src/emv/emv_tags.c @@ -271,6 +271,7 @@ static const struct emv_tag emv_tags[] = { { 0x9f21, "Transaction Time", EMV_TAG_GENERIC, NULL }, { 0x9f22, "Certification Authority Public Key Index - Terminal", EMV_TAG_GENERIC, NULL }, { 0x9f23, "Upper Consecutive Offline Limit", EMV_TAG_GENERIC, NULL }, + { 0x9f24, "Payment Account Reference (PAR)", EMV_TAG_GENERIC, NULL }, { 0x9f26, "Application Cryptogram", EMV_TAG_GENERIC, NULL }, { 0x9f27, "Cryptogram Information Data", EMV_TAG_CID, NULL }, { 0x9f2a, "Kernel Identifier", EMV_TAG_GENERIC, NULL }, @@ -339,7 +340,7 @@ static const struct emv_tag emv_tags[] = { { 0x9f66, "PUNATC (Track2) / Terminal Transaction Qualifiers (TTQ)", EMV_TAG_BITMASK, &EMV_TTQ }, { 0x9f67, "NATC (Track2) / MSD Offset", EMV_TAG_GENERIC, NULL }, { 0x9f68, "Cardholder verification method list (PayPass)", EMV_TAG_GENERIC, NULL }, - { 0x9f69, "Card Authentication Related Data (UDOL)", EMV_TAG_GENERIC, NULL }, + { 0x9f69, "Card Authentication Related Data (UDOL)", EMV_TAG_DOL, NULL }, { 0x9f6a, "Unpredictable Number", EMV_TAG_NUMERIC, NULL }, { 0x9f6b, "Track 2 Data", EMV_TAG_GENERIC, NULL }, { 0x9f6c, "Card Transaction Qualifiers (CTQ)", EMV_TAG_BITMASK, &EMV_CTQ }, @@ -359,6 +360,7 @@ static const struct emv_tag emv_tags[] = { { 0x9f79, "Unprotected Data Envelope 5", EMV_TAG_GENERIC, NULL }, { 0x9f7c, "Merchant Custom Data / Customer Exclusive Data (CED)", EMV_TAG_GENERIC, NULL }, { 0x9f7d, "DS Summary 1", EMV_TAG_GENERIC, NULL }, + { 0x9f7e, "Application Life Cycle Data", EMV_TAG_GENERIC, NULL }, { 0x9f7f, "DS Unpredictable Number", EMV_TAG_GENERIC, NULL }, { 0xa5, "File Control Information (FCI) Proprietary Template", EMV_TAG_GENERIC, NULL }, @@ -392,7 +394,7 @@ static const struct emv_tag emv_tags[] = { { 0xdf8117, "Card Data Input Capability", EMV_TAG_GENERIC, NULL }, { 0xdf8118, "CVM Capability - CVM Required", EMV_TAG_GENERIC, NULL }, { 0xdf8119, "CVM Capability - No CVM Required", EMV_TAG_GENERIC, NULL }, - { 0xdf811a, "Default UDOL", EMV_TAG_GENERIC, NULL }, + { 0xdf811a, "Default UDOL", EMV_TAG_DOL, NULL }, { 0xdf811b, "Kernel Configuration", EMV_TAG_GENERIC, NULL }, { 0xdf811c, "Max Lifetime of Torn Transaction Log Record", EMV_TAG_GENERIC, NULL }, { 0xdf811d, "Max Number of Torn Transaction Log Records", EMV_TAG_GENERIC, NULL }, diff --git a/client/src/emv/emvcore.c b/client/src/emv/emvcore.c index 8d2ce0f86..5a8236595 100644 --- a/client/src/emv/emvcore.c +++ b/client/src/emv/emvcore.c @@ -647,7 +647,12 @@ int EMVInternalAuthenticate(EMVCommandChannel channel, bool LeaveFieldON, uint8_ } int MSCComputeCryptoChecksum(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *UDOL, uint8_t UDOLlen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { - return EMVExchange(channel, LeaveFieldON, (sAPDU) {0x80, 0x2a, 0x8e, 0x80, UDOLlen, UDOL}, Result, MaxResultLen, ResultLen, sw, tlv); + int res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x80, 0x2a, 0x8e, 0x80, UDOLlen, UDOL}, true, Result, MaxResultLen, ResultLen, sw, tlv); + if (*sw == 0x6700 || *sw == 0x6f00) { + PrintAndLogEx(INFO, ">>> trying to reissue command without Le..."); + res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU) {0x80, 0x2a, 0x8e, 0x80, UDOLlen, UDOL}, false, Result, MaxResultLen, ResultLen, sw, tlv); + } + return res; } // Authentication From a99a52f5a64c2676e3d0fa70caa2e76e51742c9d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 8 Apr 2021 17:58:25 +0300 Subject: [PATCH 186/373] check CDA SDAD present --- client/src/emv/cmdemv.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/client/src/emv/cmdemv.c b/client/src/emv/cmdemv.c index 08f9435fd..83f268f57 100644 --- a/client/src/emv/cmdemv.c +++ b/client/src/emv/cmdemv.c @@ -1143,9 +1143,13 @@ static int CmdEMVExec(const char *Cmd) { // CDA PrintAndLogEx(NORMAL, "\n* CDA:"); struct tlvdb *ac_tlv = tlvdb_parse_multi(buf, len); - res = trCDA(tlvRoot, ac_tlv, pdol_data_tlv, cdol_data_tlv); - if (res) { - PrintAndLogEx(NORMAL, "CDA error (%d)", res); + if (tlvdb_get(ac_tlv, 0x9f4b, NULL)) { + res = trCDA(tlvRoot, ac_tlv, pdol_data_tlv, cdol_data_tlv); + if (res) { + PrintAndLogEx(NORMAL, "CDA error (%d)", res); + } + } else { + PrintAndLogEx(NORMAL, "\n* Signed Dynamic Application Data (0x9f4b) not present"); } free(ac_tlv); From 2f634923bb584765e0cd2d39318943f03caab50a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 8 Apr 2021 17:59:47 +0300 Subject: [PATCH 187/373] if SSAD present before check it (A@Pay) --- client/src/emv/emv_pki.c | 2 +- client/src/emv/emvcore.c | 26 +++++++++++++++----------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/client/src/emv/emv_pki.c b/client/src/emv/emv_pki.c index f06a5ea69..456e2960a 100644 --- a/client/src/emv/emv_pki.c +++ b/client/src/emv/emv_pki.c @@ -349,7 +349,7 @@ unsigned char *emv_pki_sdatl_fill(const struct tlvdb *db, size_t *sdatl_len) { } struct tlvdb *emv_pki_recover_dac_ex(const struct emv_pk *enc_pk, const struct tlvdb *db, const struct tlv *sda_tlv, bool showData) { - size_t data_len; + size_t data_len = 0; // Static Data Authentication Tag List size_t sdatl_len; diff --git a/client/src/emv/emvcore.c b/client/src/emv/emvcore.c index 5a8236595..6e3767546 100644 --- a/client/src/emv/emvcore.c +++ b/client/src/emv/emvcore.c @@ -970,17 +970,21 @@ int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_tlv, st sprint_hex(icc_pk->serial, 3) ); - struct tlvdb *dac_db = emv_pki_recover_dac(issuer_pk, tlv, sda_tlv); - if (dac_db) { - const struct tlv *dac_tlv = tlvdb_get(dac_db, 0x9f45, NULL); - PrintAndLogEx(SUCCESS, "SSAD verified (%s) (%02hhx:%02hhx)", _GREEN_("ok"), dac_tlv->value[0], dac_tlv->value[1]); - tlvdb_add(tlv, dac_db); - } else { - PrintAndLogEx(ERR, "Error: SSAD verify error"); - emv_pk_free(pk); - emv_pk_free(issuer_pk); - emv_pk_free(icc_pk); - return 4; + // Signed Static Application Data (SSAD) check + const struct tlv *ssad_tlv = tlvdb_get(tlv, 0x93, NULL); + if (ssad_tlv && ssad_tlv->len > 1) { + struct tlvdb *dac_db = emv_pki_recover_dac(issuer_pk, tlv, sda_tlv); + if (dac_db) { + const struct tlv *dac_tlv = tlvdb_get(dac_db, 0x9f45, NULL); + PrintAndLogEx(SUCCESS, "Signed Static Application Data (SSAD) verified (%s) (%02hhx:%02hhx)", _GREEN_("ok"), dac_tlv->value[0], dac_tlv->value[1]); + tlvdb_add(tlv, dac_db); + } else { + PrintAndLogEx(ERR, "Error: Signed Static Application Data (SSAD) verify error"); + emv_pk_free(pk); + emv_pk_free(issuer_pk); + emv_pk_free(icc_pk); + return 4; + } } PrintAndLogEx(INFO, "* * Check Signed Dynamic Application Data (SDAD)"); From 2e09354bbaa122f49806590244199d58e82b8e45 Mon Sep 17 00:00:00 2001 From: Ryan Saridar <8403417+VortixDev@users.noreply.github.com> Date: Thu, 8 Apr 2021 16:51:21 +0100 Subject: [PATCH 188/373] Fix RESTORE mis-annotation --- client/src/cmdhflist.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhflist.c b/client/src/cmdhflist.c index 6a6d57fd7..baf60406d 100644 --- a/client/src/cmdhflist.c +++ b/client/src/cmdhflist.c @@ -228,7 +228,10 @@ int applyIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { snprintf(exp, size, "DEC(%d)", cmd[1]); break; case MIFARE_CMD_RESTORE: - snprintf(exp, size, "RESTORE(%d)", cmd[1]); + if (cmdsize == 4) + snprintf(exp, size, "RESTORE(%d)", cmd[1]); + else + return 0; break; case MIFARE_CMD_TRANSFER: snprintf(exp, size, "TRANSFER(%d)", cmd[1]); From 7aaa5c93417ec4cf26104b8167faca66e47f8ccf Mon Sep 17 00:00:00 2001 From: Ryan Saridar <8403417+VortixDev@users.noreply.github.com> Date: Thu, 8 Apr 2021 16:51:47 +0100 Subject: [PATCH 189/373] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd5926616..1823134ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fix RESTORE mis-annotation (@VortixDev) - Changed `smart raw` - now uses NG (@iceman1001) - Added `hf iclass configcard` - now can download / generate config card dumps with a cardhelper [WIP] (@iceman1001) - Fix swapped DESELECT and WTX annotations (@VortixDev) From 505c3959b3c4aba2b6464f93a69721367406df42 Mon Sep 17 00:00:00 2001 From: Gator96100 Date: Fri, 9 Apr 2021 01:46:55 +0200 Subject: [PATCH 190/373] deal with special characters --- pm3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pm3 b/pm3 index 5fef9e6ee..cd7b56b52 100755 --- a/pm3 +++ b/pm3 @@ -207,7 +207,7 @@ function get_pm3_list_WSL { if [ -e "$DEV" ]; then #prevent soft bricking when using pm3-flash-all on an outdated bootloader if [ $(basename -- "$0") = "pm3-flash-all" ]; then - if [ ! $($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object {\$_.DeviceID -eq '$_comport'} | Select -expandproperty PNPDeviceID" 2>/dev/null) = "USB\VID_9AC4&PID_4B8F\ICEMAN" ]; then + if [ ! $($PSHEXE -command "Get-CimInstance -ClassName Win32_serialport | Where-Object {\$_.DeviceID -eq '$_comport'} | Select -expandproperty PNPDeviceID" 2>/dev/null | tr -dc '[:print:]') = "USB\VID_9AC4&PID_4B8F\ICEMAN" ]; then echo -e "\033[0;31m[!] Using pm3-flash-all on an oudated bootloader, use pm3-flash-bootrom first!" exit 1 fi From a4fa6f8226165e480143896f0903ce23bec906df Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 9 Apr 2021 15:24:18 +0200 Subject: [PATCH 191/373] hitag2crack text --- tools/hitag2crack/README.md | 2 +- tools/hitag2crack/crack5opencl/README.md | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/hitag2crack/README.md b/tools/hitag2crack/README.md index cf6bffb8d..2d38de395 100644 --- a/tools/hitag2crack/README.md +++ b/tools/hitag2crack/README.md @@ -233,7 +233,7 @@ or $ ./ht2crack5opencl ``` -5opencl supports a number of additional parameters, see crack5opencl/README.md for details. +5opencl supports a number of additional parameters, see [crack5opencl/README.md](/tools/hitag2crack/crack5opencl/README.md) for details. Usage details: Next steps ------------------------- diff --git a/tools/hitag2crack/crack5opencl/README.md b/tools/hitag2crack/crack5opencl/README.md index 1b7d05455..63c586679 100644 --- a/tools/hitag2crack/crack5opencl/README.md +++ b/tools/hitag2crack/crack5opencl/README.md @@ -44,12 +44,21 @@ Options: -V : enable debug messages -v : show the version -h : show this help +``` -Example, select devices 1, 2 and 3 using platform 1 and 2, with random queue engine: +Example, + +``` +simple + +./ht2crack5opencl 2ab12bf2 4B71E49D 6A606453 D79BD94B 16A2255B + +select devices 1, 2 and 3 using platform 1 and 2, with random queue engine: ./ht2crack5opencl -D 2 -Q 2 -p 1,2 -d 1,2,3 2ab12bf2 4B71E49D 6A606453 D79BD94B 16A2255B ``` + You can find the correct OpenCL Platform ID (-p) and Device ID (-d) with: ``` From 36c6c0a3d03117be1f7ac11fca1268d5a31d997b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 9 Apr 2021 15:27:06 +0200 Subject: [PATCH 192/373] makes crack5opencl / crack5gpu / crack5 unhappy --- tools/hitag2crack/common/ht2crackutils.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/hitag2crack/common/ht2crackutils.h b/tools/hitag2crack/common/ht2crackutils.h index 30ecfacac..b2c50beaf 100644 --- a/tools/hitag2crack/common/ht2crackutils.h +++ b/tools/hitag2crack/common/ht2crackutils.h @@ -6,7 +6,9 @@ #include #include #include -#include +#ifndef (__MINGW64__) +# include +#endif #include #include #include From a7fad57060f4a49b1e3135e283402cf13d86a209 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 9 Apr 2021 15:28:09 +0200 Subject: [PATCH 193/373] crack5opencl ,.. dont have this fct in PS. maybe a linker problem but lets just add it for now --- tools/hitag2crack/crack5opencl/ht2crack5opencl.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tools/hitag2crack/crack5opencl/ht2crack5opencl.c b/tools/hitag2crack/crack5opencl/ht2crack5opencl.c index 924932b2c..ec261dff8 100644 --- a/tools/hitag2crack/crack5opencl/ht2crack5opencl.c +++ b/tools/hitag2crack/crack5opencl/ht2crack5opencl.c @@ -35,6 +35,18 @@ #include "hitag2.h" #include "dolphin_macro.h" +#if defined(__MINGW64__) +#define timersub(a, b, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ + if ((result)->tv_usec < 0) { \ + --(result)->tv_sec; \ + (result)->tv_usec += 1000000;\ + } \ + } while (0) +#endif + #define MAX_BITSLICES 32 #define VECTOR_SIZE (MAX_BITSLICES/8) From d77a4d1a5cc431a54424251ad000bd9ec486c8b5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 9 Apr 2021 15:31:27 +0200 Subject: [PATCH 194/373] crack5opencl - mark found key message --- tools/hitag2crack/crack5opencl/ht2crack5opencl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/hitag2crack/crack5opencl/ht2crack5opencl.c b/tools/hitag2crack/crack5opencl/ht2crack5opencl.c index ec261dff8..be70c9f9a 100644 --- a/tools/hitag2crack/crack5opencl/ht2crack5opencl.c +++ b/tools/hitag2crack/crack5opencl/ht2crack5opencl.c @@ -1152,12 +1152,12 @@ int main(int argc, char **argv) { if (thread_count > 1) printf("[%zu] ", y); - printf("Key found @ slice %zu/%zu: ", t_arg[y].slice, t_arg[y].max_slices); + printf("\nKey found @ slice %zu/%zu: [", t_arg[y].slice, t_arg[y].max_slices); for (int i = 0; i < 6; i++) { printf("%02X", (uint8_t)(t_arg[y].key & 0xff)); t_arg[y].key = t_arg[y].key >> 8; } - printf("\n"); + printf(" ]\n"); fflush(stdout); break; } @@ -1178,7 +1178,7 @@ int main(int argc, char **argv) { printf("\nAttack 5 - opencl - end"); - if (show_overall_time) printf(" in %ld.%06ld second(s).\n\n", (long int)cpu_t_result.tv_sec, (long int)cpu_t_result.tv_usec); + if (show_overall_time) printf(" in %ld.%2ld second(s).\n\n", (long int)cpu_t_result.tv_sec, (long int)cpu_t_result.tv_usec); else printf("\n"); fflush(stdout); From c850b5376d1f68528f76b42710d6c4e21dac4e0c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 9 Apr 2021 15:41:00 +0200 Subject: [PATCH 195/373] crack5opencl - textual --- tools/hitag2crack/common/ht2crackutils.h | 2 +- tools/hitag2crack/crack5opencl/threads.c | 37 +++++++++--------------- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/tools/hitag2crack/common/ht2crackutils.h b/tools/hitag2crack/common/ht2crackutils.h index b2c50beaf..1ce71af1d 100644 --- a/tools/hitag2crack/common/ht2crackutils.h +++ b/tools/hitag2crack/common/ht2crackutils.h @@ -6,7 +6,7 @@ #include #include #include -#ifndef (__MINGW64__) +#ifndef __MINGW64__ # include #endif #include diff --git a/tools/hitag2crack/crack5opencl/threads.c b/tools/hitag2crack/crack5opencl/threads.c index 963425cff..f44861cc4 100644 --- a/tools/hitag2crack/crack5opencl/threads.c +++ b/tools/hitag2crack/crack5opencl/threads.c @@ -427,20 +427,6 @@ int thread_stop(thread_ctx_t *ctx) { return 0; } -__attribute__((format(printf, 1, 2))) -void tprintf(const char *restrict format, ...) { - flockfile(stdout); - - va_list va_args; - va_start(va_args, format); - vprintf(format, va_args); - va_end(va_args); - - funlockfile(stdout); - - fflush(stdout); -} - const char *thread_status_strdesc(thread_status_t s) { switch (s) { case TH_START: @@ -470,13 +456,13 @@ bool thread_setEnd(thread_ctx_t *ctx, thread_args_t *t_arg) { for (z = 0; z < ctx->thread_count; z++) { int m_ret = pthread_mutex_lock(&ctx->thread_mutexs[z]); if (m_ret != 0) { - tprintf("[%zu] [%s] Error: pthread_mutex_lock() failed (%d): %s\n", z, __func__, m_ret, strerror(m_ret)); + printf("[%zu] [%s] Error: pthread_mutex_lock() failed (%d): %s\n", z, __func__, m_ret, strerror(m_ret)); } thread_status_t tmp = t_arg[z].status; #if DEBUGME > 0 - tprintf("[%zu] [%s] Thread status: %s\n", z, __func__, thread_status_strdesc(t_arg[z].status)); + printf("[%zu] [%s] Thread status: %s\n", z, __func__, thread_status_strdesc(t_arg[z].status)); #endif if (tmp == TH_FOUND_KEY || tmp == TH_END || tmp == TH_ERROR) { @@ -486,19 +472,19 @@ bool thread_setEnd(thread_ctx_t *ctx, thread_args_t *t_arg) { } #if DEBUGME > 0 - tprintf("[%zu] [%s] Set thread status to TH_END\n", z, __func__); + printf("[%zu] [%s] Set thread status to TH_END\n", z, __func__); #endif t_arg[z].status = TH_END; if (tmp == TH_WAIT) { #if DEBUGME > 0 - tprintf("[%zu] [%s] Send cond_signal to thread\n", z, __func__); + printf("[%zu] [%s] Send cond_signal to thread\n", z, __func__); #endif c_ret = pthread_cond_signal(&ctx->thread_conds[z]); if (c_ret != 0) { - tprintf("[%zu] [%s] Error: pthread_cond_signal() failed (%d): %s\n", z, __func__, c_ret, strerror(c_ret)); + printf("[%zu] [%s] Error: pthread_cond_signal() failed (%d): %s\n", z, __func__, c_ret, strerror(c_ret)); } } @@ -529,17 +515,19 @@ void *computing_process(void *arg) { off = wu.off; a->slice = wu.id + 1; + float progress = (((wu.id + 1) * 100.0) / wu.max); if (ctx->queue_ctx.queue_type == QUEUE_TYPE_RANDOM) { + #if DEBUGME > 0 printf("[%zu] Slice %zu (off %zu), max %zu, remain %zu slice(s)\n", z, wu.id + 1, wu.off, wu.max, wu.rem); #else - printf("[%zu] Slice %zu/%zu (%zu remain)\n", z, wu.id + 1, wu.max, wu.rem); + printf("\r[%zu] Slice %zu/%zu (%zu remain) ( %2.1f%% )", z, wu.id + 1, wu.max, wu.rem, progress); #endif // DEBUGME } else { #if DEBUGME > 0 printf("[%zu] Slice %zu/%zu, off %zu\n", z, wu.id + 1, wu.max, wu.off); #else - printf("[%zu] Slice %zu/%zu\n", z, wu.id + 1, wu.max); + printf("\r[%zu] Slice %zu/%zu ( %2.1f%% )", z, wu.id + 1, wu.max, progress); #endif // DEBUGME } fflush(stdout); @@ -577,6 +565,7 @@ void *computing_process(void *arg) { } pthread_exit(NULL); + return NULL; } void *computing_process_async(void *arg) { @@ -684,17 +673,18 @@ void *computing_process_async(void *arg) { off = wu.off; a->slice = wu.id + 1; + float progress = (((wu.id + 1) * 100.0) / wu.max); if (ctx->queue_ctx.queue_type == QUEUE_TYPE_RANDOM) { #if DEBUGME > 0 printf("[%zu] Slice %zu (off %zu), max %zu, remain %zu slice(s)\n", z, wu.id + 1, wu.off, wu.max, wu.rem); #else - printf("[%zu] Slice %zu/%zu (%zu remain)\n", z, wu.id + 1, wu.max, wu.rem); + printf("[%zu] Slice %zu/%zu (%zu remain) ( %2.1f%% )", z, wu.id + 1, wu.max, wu.rem, progress); #endif // DEBUGME } else { #if DEBUGME > 0 printf("[%zu] Slice %zu/%zu, off %zu\n", z, wu.id + 1, wu.max, wu.off); #else - printf("[%zu] Slice %zu/%zu\n", z, wu.id + 1, wu.max); + printf("\r[%zu] Slice %zu/%zu ( %2.1f%% )", z, wu.id + 1, wu.max, progress); #endif // DEBUGME } @@ -874,4 +864,5 @@ void *computing_process_async(void *arg) { } while (status < TH_FOUND_KEY); pthread_exit(NULL); + return NULL; } From 8daf61876d145bdaec6a330ce50e3571f461a305 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 9 Apr 2021 15:42:06 +0200 Subject: [PATCH 196/373] cleanup --- tools/hitag2crack/crack5opencl/threads.h | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/hitag2crack/crack5opencl/threads.h b/tools/hitag2crack/crack5opencl/threads.h index 0442a8f8c..6aa958fad 100644 --- a/tools/hitag2crack/crack5opencl/threads.h +++ b/tools/hitag2crack/crack5opencl/threads.h @@ -128,7 +128,6 @@ int thread_stop(thread_ctx_t *ctx); int thread_start_scheduler(thread_ctx_t *ctx, thread_args_t *t_arg, wu_queue_ctx_t *queue_ctx); bool thread_setEnd(thread_ctx_t *ctx, thread_args_t *t_arg); -void tprintf(const char *restrict format, ...); const char *thread_strerror(int error); const char *thread_status_strdesc(thread_status_t s); From 56fd1f5857ed5a4f98543271304860f73b90d59b Mon Sep 17 00:00:00 2001 From: Gator96100 Date: Fri, 9 Apr 2021 16:59:11 +0200 Subject: [PATCH 197/373] Fixes for ProxSpace v3.9 --- .github/workflows/windows.yml | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 78ee6c3cf..d3e6ee423 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -27,7 +27,7 @@ jobs: - name: ProxSpace version run: | - $psversion = (Select-String -Pattern 'PSVERSION=' -SimpleMatch -Path "C:\ProxSpace\msys2\ps\09-proxspace_setup.post").Line.Split("""")[1] + $psversion = (Select-String -Pattern 'PSVERSION=' -SimpleMatch -Path "C:\ProxSpace\setup\09-proxspace_setup.post").Line.Split("""")[1] Write-Host "ProxSpace version: $psversion" - name: ProxSpace initial startup diff --git a/appveyor.yml b/appveyor.yml index 899202bf1..b07bce303 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -106,7 +106,7 @@ clone_script: Write-Host "[ OK ]" -ForegroundColor Gree - $psversion = (Select-String -Pattern 'PSVERSION=' -SimpleMatch -Path "$env:proxspace_path\msys2\ps\09-proxspace_setup.post").Line.Split("""")[1] + $psversion = (Select-String -Pattern 'PSVERSION=' -SimpleMatch -Path "$env:proxspace_path\setup\09-proxspace_setup.post").Line.Split("""")[1] Write-Host "ProxSpace version: $psversion" -ForegroundColor Yellow From 916e5d7ba2557d4f214d377e9fcbe7ef7fe7d973 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 10 Apr 2021 08:05:33 +0200 Subject: [PATCH 198/373] versbose text --- client/src/mifare/mifare4.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/client/src/mifare/mifare4.c b/client/src/mifare/mifare4.c index e12885252..80c0287b9 100644 --- a/client/src/mifare/mifare4.c +++ b/client/src/mifare/mifare4.c @@ -45,25 +45,25 @@ const char *mfpGetErrorDescription(uint8_t errorCode) { } AccessConditions_t MFAccessConditions[] = { - {0x00, "rdAB wrAB incAB dectrAB"}, - {0x01, "rdAB dectrAB"}, - {0x02, "rdAB"}, - {0x03, "rdB wrB"}, - {0x04, "rdAB wrB"}, - {0x05, "rdB"}, - {0x06, "rdAB wrB incB dectrAB"}, - {0x07, "none"} + {0x00, "read AB; write AB; increment AB; decrement transfer restore AB"}, + {0x01, "read AB; decrement transfer restore AB"}, + {0x02, "read AB"}, + {0x03, "read B; write B"}, + {0x04, "read AB; writeB"}, + {0x05, "read B"}, + {0x06, "read AB; write B; increment B; decrement transfer restore AB"}, + {0x07, "none"} }; AccessConditions_t MFAccessConditionsTrailer[] = { - {0x00, "rdAbyA rdCbyA rdBbyA wrBbyA"}, - {0x01, "wrAbyA rdCbyA wrCbyA rdBbyA wrBbyA"}, - {0x02, "rdCbyA rdBbyA"}, - {0x03, "wrAbyB rdCbyAB wrCbyB wrBbyB"}, - {0x04, "wrAbyB rdCbyAB wrBbyB"}, - {0x05, "rdCbyAB wrCbyB"}, - {0x06, "rdCbyAB"}, - {0x07, "rdCbyAB"} + {0x00, "read A by A; read ACCESS by A; read B by A; write B by A"}, + {0x01, "write A by A; read ACCESS by A write ACCESS by A; read B by A; write B by A"}, + {0x02, "read ACCESS by A; read B by A"}, + {0x03, "write A by B; read ACCESS by AB; write ACCESS by B; write B by B"}, + {0x04, "write A by B; read ACCESS by AB; write B by B"}, + {0x05, "read ACCESS by AB; write ACCESS by B"}, + {0x06, "read ACCESS by AB"}, + {0x07, "read ACCESS by AB"} }; const char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data) { From a8a17b70d3ca8d953098ac40bc9feb14d97e1a77 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 10 Apr 2021 09:01:00 +0200 Subject: [PATCH 199/373] hf mf egetsc/egetblk/cgetsc/cgetsc - now use cliparser and can decode st --- client/src/cmdhfmf.c | 224 ++++++++++++++++++++++++++----------------- 1 file changed, 136 insertions(+), 88 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index b07e1573b..9856774bb 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -188,25 +188,8 @@ static int usage_hf14_decryptbytes(void) { return PM3_SUCCESS; } -static int usage_hf14_egetblk(void) { - PrintAndLogEx(NORMAL, "Usage: hf mf egetblk "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " block number"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf egetblk 0")); - return PM3_SUCCESS; -} -static int usage_hf14_egetsc(void) { - PrintAndLogEx(NORMAL, "Get sector data from emulator memory.\n"); - PrintAndLogEx(NORMAL, "Usage: hf mf egetsc [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " sector number"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf egetsc 0")); - return PM3_SUCCESS; -} + + static int usage_hf14_eclr(void) { PrintAndLogEx(NORMAL, "It set card emulator memory to empty data blocks and key A/B FFFFFFFFFFFF \n"); PrintAndLogEx(NORMAL, "Usage: hf mf eclr"); @@ -321,28 +304,7 @@ static int usage_hf14_cload(void) { PrintAndLogEx(NORMAL, _YELLOW_(" hf mf cload e")); return PM3_SUCCESS; } -static int usage_hf14_cgetblk(void) { - PrintAndLogEx(NORMAL, "Get block data from magic Chinese card. Only works with magic cards\n"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf cgetblk [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " block number"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf cgetblk 1")); - return PM3_SUCCESS; -} -static int usage_hf14_cgetsc(void) { - PrintAndLogEx(NORMAL, "Get sector data from magic Chinese card. Only works with magic cards\n"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf cgetsc [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " sector number"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf cgetsc 0")); - return PM3_SUCCESS; -} + static int usage_hf14_csave(void) { PrintAndLogEx(NORMAL, "It saves `magic Chinese` card dump into the file `filename.eml` or `cardID.eml`"); PrintAndLogEx(NORMAL, "or into emulator memory"); @@ -524,21 +486,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(INFO, "--------- " _CYAN_("Sector trailer") " -------------"); + PrintAndLogEx(INFO, "----------------------- " _CYAN_("Sector trailer decoder") " -----------------------"); 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"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, " # | Access rights"); + PrintAndLogEx(INFO, "----+-----------------------------------------------------------------"); int bln = mfFirstBlockOfSector(mfSectorNum(blockno)); int blinc = (mfNumBlocksPerSector(mfSectorNum(blockno)) > 4) ? 5 : 1; for (int i = 0; i < 4; i++) { - PrintAndLogEx(INFO, " block %d%s " _YELLOW_("%s"), bln, ((blinc > 1) && (i < 3) ? "+" : ""), mfGetAccessConditionsDesc(i, &data[6])); + PrintAndLogEx(INFO, "%3d%c| " _YELLOW_("%s"), bln, ((blinc > 1) && (i < 3) ? '+' : ' '), mfGetAccessConditionsDesc(i, &data[6])); bln += blinc; } - - PrintAndLogEx(INFO, "--------------------------------------"); + PrintAndLogEx(INFO, "----------------------------------------------------------------------"); } } @@ -3794,30 +3757,70 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto // EMULATOR COMMANDS static int CmdHF14AMfEGetBlk(const char *Cmd) { - char c = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || c == 'h') return usage_hf14_egetblk(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf egetblk", + "Get emulator memory block", + "hf mf egetblk -b 0 -> get block 0 (manufacturer)\n" + "hf mf egetblk -b 3 -v -> get block 3, decode sector trailer\n" + ); + void *argtable[] = { + arg_param_begin, + arg_int1("b", "blk", "", "block number"), + arg_lit0("v", "verbose", "verbose output"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + int b = arg_get_int_def(ctx, 1, 0); + bool verbose = arg_get_lit(ctx, 2); + CLIParserFree(ctx); + + if (b > 255) { + return PM3_EINVARG; + } + uint8_t blockno = (uint8_t)b; uint8_t data[16] = {0x00}; - uint8_t blockNo = param_get8(Cmd, 0); + if (mfEmlGetMem(data, blockno, 1) == PM3_SUCCESS) { + + uint8_t sector = GetSectorFromBlockNo(blockno); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); + PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); + if (blockno == 0) { + PrintAndLogEx(INFO, "%3d | " _RED_("%s"), blockno, sprint_hex_ascii(data, sizeof(data))); + } else if (mfIsSectorTrailer(blockno)) { + PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), blockno, sprint_hex_ascii(data, sizeof(data))); + if (verbose) { + decode_print_st(blockno, data); + } + } else { + PrintAndLogEx(INFO, "%3d | %s ", blockno, sprint_hex_ascii(data, sizeof(data))); + } - PrintAndLogEx(NORMAL, ""); - if (mfEmlGetMem(data, blockNo, 1) == PM3_SUCCESS) { - PrintAndLogEx(NORMAL, "data[%3d]:%s", blockNo, sprint_hex(data, sizeof(data))); } return PM3_SUCCESS; } static int CmdHF14AMfEGetSc(const char *Cmd) { - uint8_t data[16] = {0}; - - char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_egetsc(); - - uint8_t sector = param_get8(Cmd, 0); - if (sector > 39) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf egetsc", + "Get emulator memory sector", + "hf mf egetsc -s 0" + ); + void *argtable[] = { + arg_param_begin, + arg_int1("s", "sec", "", "sector number"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + int s = arg_get_int_def(ctx, 1, 0); + CLIParserFree(ctx); + if (s > 39) { PrintAndLogEx(WARNING, "Sector number must be less then 40"); - return PM3_ESOFT; + return PM3_EINVARG; } + uint8_t sector = (uint8_t)s; + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); @@ -3829,8 +3832,8 @@ static int CmdHF14AMfEGetSc(const char *Cmd) { start = 128 + (sector - 32) * 16; } + uint8_t data[16] = {0}; for (int i = 0; i < blocks; i++) { - int res = mfEmlGetMem(data, start + i, 1); if (res == PM3_SUCCESS) { if (start + i == 0) { @@ -4483,39 +4486,77 @@ static int CmdHF14AMfCLoad(const char *Cmd) { } static int CmdHF14AMfCGetBlk(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf cgetblk", + "Get block data from magic Chinese card.\n" + "Only works with magic gen1a cards", + "hf mf cgetblk -b 0 -> get block 0 (manufacturer)\n" + "hf mf cgetblk -b 3 -v -> get block 3, decode sector trailer\n" + ); + void *argtable[] = { + arg_param_begin, + arg_int1("b", "blk", "", "block number"), + arg_lit0("v", "verbose", "verbose output"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + int b = arg_get_int_def(ctx, 1, 0); + bool verbose = arg_get_lit(ctx, 2); + CLIParserFree(ctx); + + if (b > 255) { + return PM3_EINVARG; + } + + uint8_t blockno = (uint8_t)b; uint8_t data[16] = {0}; - - char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_cgetblk(); - - uint8_t blockNo = param_get8(Cmd, 0); - - PrintAndLogEx(NORMAL, "--block number:%2d ", blockNo); - - int res = mfCGetBlock(blockNo, data, MAGIC_SINGLE); + int res = mfCGetBlock(blockno, data, MAGIC_SINGLE); if (res) { PrintAndLogEx(ERR, "Can't read block. error=%d", res); return PM3_ESOFT; } - PrintAndLogEx(NORMAL, "data: %s", sprint_hex(data, sizeof(data))); - decode_print_st(blockNo, data); + uint8_t sector = GetSectorFromBlockNo(blockno); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); + PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); + if (blockno == 0) { + PrintAndLogEx(INFO, "%3d | " _RED_("%s"), blockno, sprint_hex_ascii(data, sizeof(data))); + } else if (mfIsSectorTrailer(blockno)) { + PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), blockno, sprint_hex_ascii(data, sizeof(data))); + if (verbose) { + decode_print_st(blockno, data); + } + } else { + PrintAndLogEx(INFO, "%3d | %s ", blockno, sprint_hex_ascii(data, sizeof(data))); + } + return PM3_SUCCESS; } static int CmdHF14AMfCGetSc(const char *Cmd) { - uint8_t data[16] = {0}; - - char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_cgetsc(); - - uint8_t sector = param_get8(Cmd, 0); - if (sector > 39) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf cgetsc", + "Get sector data from magic Chinese card.\n" + "Only works with magic gen1a cards", + "hf mf cgetsc -s 0" + ); + void *argtable[] = { + arg_param_begin, + arg_int1("s", "sec", "", "sector number"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + int s = arg_get_int_def(ctx, 1, 0); + CLIParserFree(ctx); + if (s > 39) { PrintAndLogEx(WARNING, "Sector number must be less then 40"); - return PM3_ESOFT; + return PM3_EINVARG; } + uint8_t sector = (uint8_t)s; + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); @@ -4528,7 +4569,7 @@ static int CmdHF14AMfCGetSc(const char *Cmd) { } int flags = MAGIC_INIT + MAGIC_WUPC; - + uint8_t data[16] = {0}; for (int i = 0; i < blocks; i++) { if (i == 1) flags = 0; if (i == blocks - 1) flags = MAGIC_HALT + MAGIC_OFF; @@ -4538,7 +4579,14 @@ static int CmdHF14AMfCGetSc(const char *Cmd) { PrintAndLogEx(ERR, "Can't read block. %d error=%d", start + i, res); return PM3_ESOFT; } - PrintAndLogEx(INFO, "%3d | %s ", start + i, sprint_hex_ascii(data, sizeof(data))); + + if (start + i == 0) { + PrintAndLogEx(INFO, "%3d | " _RED_("%s"), start + i, sprint_hex_ascii(data, sizeof(data))); + } else if (mfIsSectorTrailer(i)) { + PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), start + i, sprint_hex_ascii(data, sizeof(data))); + } else { + PrintAndLogEx(INFO, "%3d | %s ", start + i, sprint_hex_ascii(data, sizeof(data))); + } } decode_print_st(start + blocks - 1, data); return PM3_SUCCESS; @@ -5733,14 +5781,14 @@ static command_t CommandTable[] = { // {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"}, {"sim", CmdHF14AMfSim, IfPm3Iso14443a, "Simulate MIFARE card"}, - {"ecfill", CmdHF14AMfECFill, IfPm3Iso14443a, "Fill simulator memory with help of keys from simulator"}, - {"eclr", CmdHF14AMfEClear, IfPm3Iso14443a, "Clear simulator memory"}, - {"egetblk", CmdHF14AMfEGetBlk, IfPm3Iso14443a, "Get simulator memory block"}, - {"egetsc", CmdHF14AMfEGetSc, IfPm3Iso14443a, "Get simulator memory sector"}, - {"ekeyprn", CmdHF14AMfEKeyPrn, IfPm3Iso14443a, "Print keys from simulator memory"}, + {"ecfill", CmdHF14AMfECFill, IfPm3Iso14443a, "Fill emulator memory with help of keys from emulator"}, + {"eclr", CmdHF14AMfEClear, IfPm3Iso14443a, "Clear emulator memory"}, + {"egetblk", CmdHF14AMfEGetBlk, IfPm3Iso14443a, "Get emulator memory block"}, + {"egetsc", CmdHF14AMfEGetSc, IfPm3Iso14443a, "Get emulator memory sector"}, + {"ekeyprn", CmdHF14AMfEKeyPrn, IfPm3Iso14443a, "Print keys from emulator memory"}, {"eload", CmdHF14AMfELoad, IfPm3Iso14443a, "Load from file emul dump"}, {"esave", CmdHF14AMfESave, IfPm3Iso14443a, "Save to file emul dump"}, - {"eset", CmdHF14AMfESet, IfPm3Iso14443a, "Set simulator memory block"}, + {"eset", CmdHF14AMfESet, IfPm3Iso14443a, "Set emulator memory block"}, {"eview", CmdHF14AMfEView, IfPm3Iso14443a, "View emul memory"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen1") " -----------------------"}, {"cgetblk", CmdHF14AMfCGetBlk, IfPm3Iso14443a, "Read block"}, From 1cb9b37d8317daad88fb791d3d1e48f2f0148982 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 10 Apr 2021 09:51:18 +0200 Subject: [PATCH 200/373] hf mf rdbl,rdsc - now use cliparser --- client/src/cmdhfmf.c | 158 ++++++++++++++++++++++++------------------- 1 file changed, 90 insertions(+), 68 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 9856774bb..d9820caa0 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -188,8 +188,6 @@ static int usage_hf14_decryptbytes(void) { return PM3_SUCCESS; } - - static int usage_hf14_eclr(void) { PrintAndLogEx(NORMAL, "It set card emulator memory to empty data blocks and key A/B FFFFFFFFFFFF \n"); PrintAndLogEx(NORMAL, "Usage: hf mf eclr"); @@ -502,6 +500,7 @@ static void decode_print_st(uint16_t blockno, uint8_t *data) { bln += blinc; } PrintAndLogEx(INFO, "----------------------------------------------------------------------"); + PrintAndLogEx(NORMAL, ""); } } @@ -684,92 +683,120 @@ static int CmdHF14AMfWrBl(const char *Cmd) { } static int CmdHF14AMfRdBl(const char *Cmd) { - uint8_t blockNo = 0; - uint8_t keyType = 0; - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - char cmdp = 0x00; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf rdbl", + "Read MIFARE Classic block", + "hf mf rdbl --blk 0 -k FFFFFFFFFFFF\n" + "hf mf rdbl -b 3 -v -> get block 3, decode sector trailer\n" + ); + void *argtable[] = { + arg_param_begin, + arg_int1(NULL, "blk", "", "block number"), + arg_lit0("a", NULL, "input key specified is A key (def)"), + arg_lit0("b", NULL, "input key specified is B key"), + arg_str0("k", "key", "", "key specified as 6 hex bytes"), + arg_lit0("v", "verbose", "verbose output"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + int b = arg_get_int_def(ctx, 1, 0); - if (strlen(Cmd) < 3) { - PrintAndLogEx(NORMAL, "Usage: hf mf rdbl "); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf rdbl 0 A FFFFFFFFFFFF "); - return PM3_SUCCESS; + uint8_t keytype = 0; + if (arg_get_lit(ctx, 2) && arg_get_lit(ctx, 3)) { + CLIParserFree(ctx); + PrintAndLogEx(WARNING, "Input key type must be A or B"); + return PM3_EINVARG; + } else if (arg_get_lit(ctx, 3)) { + keytype = 1; } - blockNo = param_get8(Cmd, 0); - cmdp = tolower(param_getchar(Cmd, 1)); - if (cmdp == 0x00) { - PrintAndLogEx(NORMAL, "Key type must be A or B"); - return PM3_ESOFT; - } + int keylen = 0; + uint8_t key[6] = {0}; + CLIGetHexWithReturn(ctx, 4, key, &keylen); - if (cmdp != 'a') - keyType = 1; + bool verbose = arg_get_lit(ctx, 5); + CLIParserFree(ctx); - if (param_gethex(Cmd, 2, key, 12)) { - PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); - return PM3_ESOFT; + if (b > 255) { + return PM3_EINVARG; } - PrintAndLogEx(NORMAL, "--block no %d, key %c - %s", blockNo, keyType ? 'B' : 'A', sprint_hex(key, 6)); + uint8_t blockno = (uint8_t)b; uint8_t data[16] = {0}; - int res = mfReadBlock(blockNo, keyType, key, data); + int res = mfReadBlock(blockno, keytype, key, data); if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "data: %s", sprint_hex(data, 16)); - if ((data[6] || data[7] || data[8])) { - decode_print_st(blockNo, data); + + uint8_t sector = GetSectorFromBlockNo(blockno); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); + PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); + if (blockno == 0) { + PrintAndLogEx(INFO, "%3d | " _RED_("%s"), blockno, sprint_hex_ascii(data, sizeof(data))); + } else if (mfIsSectorTrailer(blockno)) { + PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), blockno, sprint_hex_ascii(data, sizeof(data))); + if (verbose) { + decode_print_st(blockno, data); + } + } else { + PrintAndLogEx(INFO, "%3d | %s ", blockno, sprint_hex_ascii(data, sizeof(data))); } } - return PM3_SUCCESS; + PrintAndLogEx(NORMAL, ""); + return res; } static int CmdHF14AMfRdSc(const char *Cmd) { - uint8_t sectorNo = 0, keyType = 0; - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - char cmdp = 0x00; - if (strlen(Cmd) < 3) { - PrintAndLogEx(NORMAL, "Usage: hf mf rdsc "); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf rdsc 0 A FFFFFFFFFFFF "); - return PM3_SUCCESS; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf rdbl", + "Read MIFARE Classic sector", + "hf mf rdbl -s 0 -k FFFFFFFFFFFF\n" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0("a", NULL, "input key specified is A key (def)"), + arg_lit0("b", NULL, "input key specified is B key"), + arg_str0("k", "key", "", "key specified as 6 hex bytes"), + arg_int1("s", "sec", "", "sector number"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + uint8_t keytype = 0; + if (arg_get_lit(ctx, 1) && arg_get_lit(ctx, 2)) { + CLIParserFree(ctx); + PrintAndLogEx(WARNING, "Input key type must be A or B"); + return PM3_EINVARG; + } else if (arg_get_lit(ctx, 2)) { + keytype = 1; } - sectorNo = param_get8(Cmd, 0); - if (sectorNo > MIFARE_4K_MAXSECTOR) { - PrintAndLogEx(NORMAL, "Sector number must be less than 40"); - return PM3_ESOFT; + int keylen = 0; + uint8_t key[6] = {0}; + CLIGetHexWithReturn(ctx, 3, key, &keylen); + + int s = arg_get_int_def(ctx, 4, 0); + CLIParserFree(ctx); + + if (s > MIFARE_4K_MAXSECTOR) { + PrintAndLogEx(WARNING, "Sector number must be less then 40"); + return PM3_EINVARG; } - - cmdp = tolower(param_getchar(Cmd, 1)); - if (cmdp != 'a' && cmdp != 'b') { - PrintAndLogEx(NORMAL, "Key type must be A or B"); - return PM3_ESOFT; - } - - if (cmdp != 'a') - keyType = 1; - - if (param_gethex(Cmd, 2, key, 12)) { - PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); - return PM3_ESOFT; - } - PrintAndLogEx(NORMAL, ""); - - uint8_t sc_size = mfNumBlocksPerSector(sectorNo) * 16; + uint8_t sector = (uint8_t)s; + uint8_t sc_size = mfNumBlocksPerSector(sector) * 16; uint8_t *data = calloc(sc_size, sizeof(uint8_t)); if (data == NULL) { PrintAndLogEx(ERR, "failed to allocate memory"); return PM3_EMALLOC; } - int res = mfReadSector(sectorNo, keyType, key, data); + int res = mfReadSector(sector, keytype, key, data); if (res == PM3_SUCCESS) { - uint8_t blocks = NumBlocksPerSector(sectorNo); - uint8_t start = FirstBlockOfSector(sectorNo); + uint8_t blocks = NumBlocksPerSector(sector); + uint8_t start = FirstBlockOfSector(sector); - PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sectorNo, sectorNo); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); for (int i = 0; i < blocks; i++) { if (start + i == 0) { @@ -781,7 +808,6 @@ static int CmdHF14AMfRdSc(const char *Cmd) { } } decode_print_st(start + blocks - 1, data + ((blocks - 1) * 16)); - } free(data); return PM3_SUCCESS; @@ -3825,12 +3851,8 @@ static int CmdHF14AMfEGetSc(const char *Cmd) { PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); - uint8_t blocks = 4; - uint8_t start = sector * 4; - if (sector >= 32) { - blocks = 16; - start = 128 + (sector - 32) * 16; - } + uint8_t blocks = NumBlocksPerSector(sector); + uint8_t start = FirstBlockOfSector(sector); uint8_t data[16] = {0}; for (int i = 0; i < blocks; i++) { From f8771f2ebb2a0453c207982d866b8abb1456643e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 10 Apr 2021 09:51:42 +0200 Subject: [PATCH 201/373] text --- doc/cliparser_todo.txt | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index e5a15c37f..33f0f5ef0 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -1,3 +1,18 @@ +preferences show +preferences get barmode +preferences get clientdebug +preferences get color +preferences get savepaths +preferences get emoji +preferences get hints +preferences get plotsliders +preferences set barmode +preferences set clientdebug +preferences set color +preferences set emoji +preferences set hints +preferences set savepaths +preferences set plotsliders hf 15 dump hf 15 info hf 15 raw @@ -20,22 +35,17 @@ hf mf hardnested hf mf autopwn hf mf nack hf mf decrypt -hf mf rdbl hf mf rdsc hf mf restore hf mf setmod hf mf wrbl hf mf ecfill hf mf eclr -hf mf egetblk -hf mf egetsc hf mf ekeyprn hf mf eload hf mf esave hf mf eset hf mf eview -hf mf cgetblk -hf mf cgetsc hf mf cload hf mf csave hf mf csetblk From 49b830266ca14c250b8f89c4bbcccbce7d8afcde Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 10 Apr 2021 12:28:39 +0200 Subject: [PATCH 202/373] text --- client/src/cmdmain.c | 2 +- client/src/preferences.c | 66 ++++++++++++++++++++-------------------- doc/cliparser_todo.txt | 15 --------- doc/commands.md | 52 +++++++++++++++---------------- 4 files changed, 60 insertions(+), 75 deletions(-) diff --git a/client/src/cmdmain.c b/client/src/cmdmain.c index e54ee9275..94365e6d5 100644 --- a/client/src/cmdmain.c +++ b/client/src/cmdmain.c @@ -296,7 +296,7 @@ static int CmdClear(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "Use `" _YELLOW_(" help") "` for details of a command"}, - {"preferences", CmdPref, AlwaysAvailable, "{ Edit client/device preferences... }"}, + {"prefs", CmdPref, AlwaysAvailable, "{ Edit client/device preferences... }"}, {"--------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("Technology") " -----------------------"}, {"analyse", CmdAnalyse, AlwaysAvailable, "{ Analyse utils... }"}, {"data", CmdData, AlwaysAvailable, "{ Plot window / data buffer manipulation... }"}, diff --git a/client/src/preferences.c b/client/src/preferences.c index 2a9f12650..3228498f4 100644 --- a/client/src/preferences.c +++ b/client/src/preferences.c @@ -504,9 +504,9 @@ static void showBarModeState(prefShowOpt_t opt) { static int setCmdEmoji(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref set emoji ", + CLIParserInit(&ctx, "prefs set emoji ", "Set presistent preference of using emojis in the client", - "pref set emoji --alias" + "prefs set emoji --alias" ); void *argtable[] = { @@ -558,9 +558,9 @@ static int setCmdEmoji(const char *Cmd) { static int setCmdColor(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref set color ", + CLIParserInit(&ctx, "prefs set color ", "Set presistent preference of using colors in the client", - "pref set color --ansi" + "prefs set color --ansi" ); void *argtable[] = { @@ -602,9 +602,9 @@ static int setCmdColor(const char *Cmd) { static int setCmdDebug(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref set clientdebug ", + CLIParserInit(&ctx, "prefs set clientdebug ", "Set presistent preference of using clientside debug level", - "pref set clientdebug --simple" + "prefs set clientdebug --simple" ); void *argtable[] = { @@ -653,9 +653,9 @@ static int setCmdDebug(const char *Cmd) { static int setCmdDeviceDebug (const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref set devicedebug ", + CLIParserInit(&ctx, "prefs set devicedebug ", "Set presistent preference of device side debug level", - "pref set devicedebug --on" + "prefs set devicedebug --on" ); void *argtable[] = { @@ -720,9 +720,9 @@ static int setCmdDeviceDebug (const char *Cmd) static int setCmdHint(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref set hints ", + CLIParserInit(&ctx, "prefs set hints ", "Set presistent preference of showing hint messages in the client", - "pref set hints --on" + "prefs set hints --on" ); void *argtable[] = { @@ -763,9 +763,9 @@ static int setCmdHint(const char *Cmd) { static int setCmdPlotSliders(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref set plotsliders", + CLIParserInit(&ctx, "prefs set plotsliders", "Set presistent preference of showing the plotslider control in the client", - "pref set plotsliders --on" + "prefs set plotsliders --on" ); void *argtable[] = { @@ -805,10 +805,10 @@ static int setCmdPlotSliders(const char *Cmd) { static int setCmdSavePaths(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref set savepaths", + CLIParserInit(&ctx, "prefs 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" + "prefs set savepaths --dump /home/mydumpfolder -> all dump files will be saved into this folder\n" + "prefs set savepaths --def /home/myfolder -c -> create if needed, all files will be saved into this folder" ); void *argtable[] = { @@ -886,9 +886,9 @@ static int setCmdSavePaths(const char *Cmd) { static int setCmdBarMode(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref set barmode", + CLIParserInit(&ctx, "prefs set barmode", "Set presistent preference of HF/LF tune command styled output in the client", - "pref set barmode --mix" + "prefs set barmode --mix" ); void *argtable[] = { @@ -933,9 +933,9 @@ static int setCmdBarMode(const char *Cmd) { static int getCmdEmoji(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref get emoji", + CLIParserInit(&ctx, "prefs get emoji", "Get preference of using emojis in the client", - "pref get emoji" + "prefs get emoji" ); void *argtable[] = { arg_param_begin, @@ -949,9 +949,9 @@ static int getCmdEmoji(const char *Cmd) { static int getCmdHint(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref get hints", + CLIParserInit(&ctx, "prefs get hints", "Get preference of showing hint messages in the client", - "pref get hints" + "prefs get hints" ); void *argtable[] = { arg_param_begin, @@ -965,9 +965,9 @@ static int getCmdHint(const char *Cmd) { static int getCmdColor(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref get color", + CLIParserInit(&ctx, "prefs get color", "Get preference of using colors in the client", - "pref get color" + "prefs get color" ); void *argtable[] = { arg_param_begin, @@ -981,9 +981,9 @@ static int getCmdColor(const char *Cmd) { static int getCmdDebug(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref get clientdebug", + CLIParserInit(&ctx, "prefs get clientdebug", "Get preference of using clientside debug level", - "pref get clientdebug" + "prefs get clientdebug" ); void *argtable[] = { arg_param_begin, @@ -997,9 +997,9 @@ static int getCmdDebug(const char *Cmd) { static int getCmdPlotSlider(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref get plotsliders", + CLIParserInit(&ctx, "prefs get plotsliders", "Get preference of showing the plotslider control in the client", - "pref get plotsliders" + "prefs get plotsliders" ); void *argtable[] = { arg_param_begin, @@ -1013,9 +1013,9 @@ static int getCmdPlotSlider(const char *Cmd) { static int getCmdBarMode(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref get barmode", + CLIParserInit(&ctx, "prefs get barmode", "Get preference of HF/LF tune command styled output in the client", - "pref get barmode" + "prefs get barmode" ); void *argtable[] = { arg_param_begin, @@ -1029,9 +1029,9 @@ static int getCmdBarMode(const char *Cmd) { static int getCmdSavePaths(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref get savepaths", + CLIParserInit(&ctx, "prefs get savepaths", "Get preference of file paths in the client", - "pref get savepaths" + "prefs get savepaths" ); void *argtable[] = { arg_param_begin, @@ -1088,9 +1088,9 @@ static int CmdPrefSet(const char *Cmd) { static int CmdPrefShow(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "pref show", + CLIParserInit(&ctx, "prefs show", "Show all persistent preferences", - "pref show" + "prefs show" ); void *argtable[] = { arg_param_begin, diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 33f0f5ef0..5904252aa 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -1,18 +1,3 @@ -preferences show -preferences get barmode -preferences get clientdebug -preferences get color -preferences get savepaths -preferences get emoji -preferences get hints -preferences get plotsliders -preferences set barmode -preferences set clientdebug -preferences set color -preferences set emoji -preferences set hints -preferences set savepaths -preferences set plotsliders hf 15 dump hf 15 info hf 15 raw diff --git a/doc/commands.md b/doc/commands.md index 8404a9b69..72a2eb1b7 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -20,45 +20,45 @@ Check column "offline" for their availability. |`exit `|Y |`Exit program` -### preferences +### prefs { Edit client/device preferences... } |command |offline |description |------- |------- |----------- -|`preferences help `|Y |`This help` -|`preferences show `|Y |`Show all preferences` +|`prefs help `|Y |`This help` +|`prefs show `|Y |`Show all preferences` -### preferences get +### prefs get { Get a preference } |command |offline |description |------- |------- |----------- -|`preferences get barmode`|Y |`Get bar mode preference` -|`preferences get clientdebug`|Y |`Get client debug level preference` -|`preferences get color `|Y |`Get color support preference` -|`preferences get savepaths`|Y |`Get file folder ` -|`preferences get emoji `|Y |`Get emoji display preference` -|`preferences get hints `|Y |`Get hint display preference` -|`preferences get plotsliders`|Y |`Get plot slider display preference` +|`prefs get barmode `|Y |`Get bar mode preference` +|`prefs get clientdebug `|Y |`Get client debug level preference` +|`prefs get color `|Y |`Get color support preference` +|`prefs get savepaths `|Y |`Get file folder ` +|`prefs get emoji `|Y |`Get emoji display preference` +|`prefs get hints `|Y |`Get hint display preference` +|`prefs get plotsliders `|Y |`Get plot slider display preference` -### preferences set +### prefs set { Set a preference } |command |offline |description |------- |------- |----------- -|`preferences set help `|Y |`This help` -|`preferences set barmode`|Y |`Set bar mode` -|`preferences set clientdebug`|Y |`Set client debug level` -|`preferences set color `|Y |`Set color support` -|`preferences set emoji `|Y |`Set emoji display` -|`preferences set hints `|Y |`Set hint display` -|`preferences set savepaths`|Y |`... to be adjusted next ... ` -|`preferences set plotsliders`|Y |`Set plot slider display` +|`prefs set help `|Y |`This help` +|`prefs set barmode `|Y |`Set bar mode` +|`prefs set clientdebug `|Y |`Set client debug level` +|`prefs set color `|Y |`Set color support` +|`prefs set emoji `|Y |`Set emoji display` +|`prefs set hints `|Y |`Set hint display` +|`prefs set savepaths `|Y |`... to be adjusted next ... ` +|`prefs set plotsliders `|Y |`Set plot slider display` ### analyse @@ -406,14 +406,14 @@ Check column "offline" for their availability. |`hf mf wipe `|N |`Wipe card to zeros and default keys/acc` |`hf mf wrbl `|N |`Write MIFARE Classic block` |`hf mf sim `|N |`Simulate MIFARE card` -|`hf mf ecfill `|N |`Fill simulator memory with help of keys from simulator` -|`hf mf eclr `|N |`Clear simulator memory` -|`hf mf egetblk `|N |`Get simulator memory block` -|`hf mf egetsc `|N |`Get simulator memory sector` -|`hf mf ekeyprn `|N |`Print keys from simulator memory` +|`hf mf ecfill `|N |`Fill emulator memory with help of keys from emulator` +|`hf mf eclr `|N |`Clear emulator memory` +|`hf mf egetblk `|N |`Get emulator memory block` +|`hf mf egetsc `|N |`Get emulator memory sector` +|`hf mf ekeyprn `|N |`Print keys from emulator memory` |`hf mf eload `|N |`Load from file emul dump` |`hf mf esave `|N |`Save to file emul dump` -|`hf mf eset `|N |`Set simulator memory block` +|`hf mf eset `|N |`Set emulator memory block` |`hf mf eview `|N |`View emul memory` |`hf mf cgetblk `|N |`Read block` |`hf mf cgetsc `|N |`Read sector` From e1b856b5fc19f6786abebb5dd97bacc524faedc0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 10 Apr 2021 15:08:27 +0200 Subject: [PATCH 203/373] hf mf ekeyprn, eclr, nack - now uses cliparser --- client/src/cmdhfmf.c | 150 +++++++++++++++++++++++-------------------- 1 file changed, 79 insertions(+), 71 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index d9820caa0..bfb5a421f 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -188,13 +188,6 @@ static int usage_hf14_decryptbytes(void) { return PM3_SUCCESS; } -static int usage_hf14_eclr(void) { - PrintAndLogEx(NORMAL, "It set card emulator memory to empty data blocks and key A/B FFFFFFFFFFFF \n"); - PrintAndLogEx(NORMAL, "Usage: hf mf eclr"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf eclr")); - return PM3_SUCCESS; -} static int usage_hf14_eset(void) { PrintAndLogEx(NORMAL, "Usage: hf mf eset "); PrintAndLogEx(NORMAL, "Examples:"); @@ -243,19 +236,7 @@ static int usage_hf14_ecfill(void) { PrintAndLogEx(NORMAL, _YELLOW_(" hf mf ecfill A 4")); return PM3_SUCCESS; } -static int usage_hf14_ekeyprn(void) { - PrintAndLogEx(NORMAL, "Download and print the keys from emulator memory"); - PrintAndLogEx(NORMAL, "Usage: hf mf ekeyprn [card memory] [d]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); - PrintAndLogEx(NORMAL, " d write keys to binary file `hf-mf--key.bin`"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf ekeyprn 1")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf ekeyprn d")); - return PM3_SUCCESS; -} + static int usage_hf14_csetuid(void) { PrintAndLogEx(NORMAL, "Set UID, ATQA, and SAK for magic Chinese card. Only works with magic cards"); @@ -333,17 +314,7 @@ static int usage_hf14_cview(void) { PrintAndLogEx(NORMAL, _YELLOW_(" hf mf cview 1")); return PM3_SUCCESS; } -static int usage_hf14_nack(void) { - PrintAndLogEx(NORMAL, "Test a MIFARE Classic based card for the NACK bug."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf nack [h] [v]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " v verbose"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf nack")); - return PM3_SUCCESS; -} + static int usage_hf14_gen3uid(void) { PrintAndLogEx(NORMAL, "Set UID for magic GEN 3 card without manufacturer block changing"); PrintAndLogEx(NORMAL, ""); @@ -868,7 +839,7 @@ static int CmdHF14AMfDump(const char *Cmd) { arg_str0("f", "file", "", "filename of dump"), arg_str0("k", "keys", "", "filename of keys"), arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"), - arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (default)"), + arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"), arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"), arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"), arg_param_end @@ -909,7 +880,7 @@ static int CmdHF14AMfDump(const char *Cmd) { m1 = true; } - uint8_t numSectors = 1; + uint8_t numSectors = MIFARE_1K_MAXSECTOR; if (m0) { numSectors = MIFARE_MINI_MAXSECTOR; @@ -3727,6 +3698,7 @@ void printKeyTable(uint8_t sectorscnt, sector_t *e_sector) { void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_sector) { char strA[12 + 1] = {0}; char strB[12 + 1] = {0}; + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, "|-----|----------------|---|----------------|---|"); PrintAndLogEx(SUCCESS, "| Sec | key A |res| key B |res|"); PrintAndLogEx(SUCCESS, "|-----|----------------|---|----------------|---|"); @@ -3778,6 +3750,7 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto } else { PrintAndLogEx(SUCCESS, "( " _YELLOW_("0") ":Failed / " _YELLOW_("1") ":Success)"); } + PrintAndLogEx(NORMAL, ""); } @@ -3872,9 +3845,17 @@ static int CmdHF14AMfEGetSc(const char *Cmd) { } static int CmdHF14AMfEClear(const char *Cmd) { - char c = tolower(param_getchar(Cmd, 0)); - if (c == 'h') return usage_hf14_eclr(); - + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf eclr", + "It set card emulator memory to empty data blocks and key A/B FFFFFFFFFFFF", + "hf mf eclr" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); clearCommandBuffer(); SendCommandNG(CMD_HF_MIFARE_EML_MEMCLR, NULL, 0); return PM3_SUCCESS; @@ -4163,37 +4144,52 @@ static int CmdHF14AMfECFill(const char *Cmd) { static int CmdHF14AMfEKeyPrn(const char *Cmd) { - uint8_t sectors_cnt = MIFARE_1K_MAXSECTOR; - uint8_t data[16]; - uint8_t uid[4]; - uint8_t cmdp = 0; - bool errors = false, createDumpFile = false; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf ekeyprn", + "Download and print the keys from emulator memory", + "hf mf ekeyprn --1k --> print MFC 1K keyset\n" + "hf mf ekeyprn -w --> write keys to binary file" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0("w", "write", "write keys to binary file `hf-mf--key.bin`"), + arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"), + arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"), + arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"), + arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool create_dumpfile = arg_get_lit(ctx, 1); + bool m0 = arg_get_lit(ctx, 2); + bool m1 = arg_get_lit(ctx, 3); + bool m2 = arg_get_lit(ctx, 4); + bool m4 = arg_get_lit(ctx, 5); + CLIParserFree(ctx); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - char ctmp = tolower(param_getchar(Cmd, cmdp)); - switch (ctmp) { - case 'd': - createDumpFile = true; - cmdp++; - break; - case 'h': - return usage_hf14_ekeyprn(); - case '0': - case '1': - case '2': - case '4': - sectors_cnt = NumOfSectors(ctmp); - if (sectors_cnt == 0) return usage_hf14_ekeyprn(); - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } // validations - if (errors) return usage_hf14_ekeyprn(); + if ((m0 + m1 + m2 + m4) > 1) { + PrintAndLogEx(WARNING, "Only specify one MIFARE Type"); + return PM3_EINVARG; + } else if ((m0 + m1 + m2 + m4) == 0) { + m1 = true; + } + + uint8_t sectors_cnt = MIFARE_1K_MAXSECTOR; + + if (m0) { + sectors_cnt = MIFARE_MINI_MAXSECTOR; + } else if (m1) { + sectors_cnt = MIFARE_1K_MAXSECTOR; + } else if (m2) { + sectors_cnt = MIFARE_2K_MAXSECTOR; + } else if (m4) { + sectors_cnt = MIFARE_4K_MAXSECTOR; + } else { + PrintAndLogEx(WARNING, "Please specify a MIFARE Type"); + return PM3_EINVARG; + } sector_t *e_sector = NULL; @@ -4205,12 +4201,15 @@ static int CmdHF14AMfEKeyPrn(const char *Cmd) { } // read UID from EMUL + uint8_t data[16]; if (mfEmlGetMem(data, 0, 1) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "error get block %d", 0); + PrintAndLogEx(WARNING, "error get block 0"); free(e_sector); return PM3_ESOFT; } + // assuming 4byte UID. + uint8_t uid[4]; memcpy(uid, data, sizeof(uid)); // download keys from EMUL @@ -4232,7 +4231,7 @@ static int CmdHF14AMfEKeyPrn(const char *Cmd) { printKeyTable(sectors_cnt, e_sector); // dump the keys - if (createDumpFile) { + if (create_dumpfile) { char filename[FILE_PATH_SIZE] = {0}; char *fptr = filename; @@ -4925,10 +4924,19 @@ static int CmdHf14AMfSetMod(const char *Cmd) { // MIFARE NACK bug detection static int CmdHf14AMfNack(const char *Cmd) { - - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_hf14_nack(); - bool verbose = (ctmp == 'v'); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf nack", + "Test a MIFARE Classic based card for the NACK bug", + "hf mf nack" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0("v", "verbose", "verbose output`"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + bool verbose = arg_get_lit(ctx, 1); + CLIParserFree(ctx); if (verbose) PrintAndLogEx(INFO, "Started testing card for NACK bug. Press Enter to abort"); From d551a662562e42b38959ef605e3ebf5d4c05518a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 10 Apr 2021 15:40:25 +0200 Subject: [PATCH 204/373] new command "hf mf view".\nhf mf eview - now uses cliparser --- client/src/cmdhfmf.c | 178 +++++++++++++++++++++++++++++-------------- 1 file changed, 119 insertions(+), 59 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index bfb5a421f..ad3158116 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -215,16 +215,7 @@ static int usage_hf14_esave(void) { PrintAndLogEx(NORMAL, _YELLOW_(" hf mf esave 4 filename")); return PM3_SUCCESS; } -static int usage_hf14_eview(void) { - PrintAndLogEx(NORMAL, "It displays emul memory"); - PrintAndLogEx(NORMAL, " Usage: hf mf eview [card memory]"); - PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (MIFARE Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf eview")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf eview 4")); - return PM3_SUCCESS; -} + static int usage_hf14_ecfill(void) { PrintAndLogEx(NORMAL, "Read card and transfer its data to emulator memory."); PrintAndLogEx(NORMAL, "Keys must be laid in the emulator memory. \n"); @@ -543,6 +534,28 @@ static char GetFormatFromSector(uint8_t sectorNo) { } } +static void mf_print_block(uint8_t blockno, uint8_t *d) { + if (blockno == 0) { + PrintAndLogEx(INFO, "%3d | " _RED_("%s"), blockno, sprint_hex_ascii(d + (blockno * 16), 16)); + } else if (mfIsSectorTrailer(blockno)) { + PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), blockno, sprint_hex_ascii(d + (blockno * 16), 16)); + } else { + PrintAndLogEx(INFO, "%3d | %s ", blockno, sprint_hex_ascii(d + (blockno * 16), 16)); + } +} +static void mf_print_blocks(uint16_t n, uint8_t *d) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); + PrintAndLogEx(INFO, "blk | data | ascii"); + PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); + for (uint16_t i = 0; i < n; i++) { + mf_print_block(i, d); + } + PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); + PrintAndLogEx(NORMAL, ""); +} + + static int CmdHF14AMfDarkside(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf darkside", @@ -4060,50 +4073,67 @@ static int CmdHF14AMfESave(const char *Cmd) { static int CmdHF14AMfEView(const char *Cmd) { - uint8_t *dump; - int bytes; - uint16_t blocks; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf eview", + "It displays emulator memory", + "hf mf eview\n" + "hf mf eview --4k" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"), + arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"), + arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"), + arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + bool m0 = arg_get_lit(ctx, 1); + bool m1 = arg_get_lit(ctx, 2); + bool m2 = arg_get_lit(ctx, 3); + bool m4 = arg_get_lit(ctx, 4); + CLIParserFree(ctx); - char c = tolower(param_getchar(Cmd, 0)); - if (c == 'h') return usage_hf14_eview(); - - if (c != 0) { - blocks = NumOfBlocks(c); - if (blocks == 0) return usage_hf14_eview(); - } else { - blocks = MIFARE_1K_MAXBLOCK; + // validations + if ((m0 + m1 + m2 + m4) > 1) { + PrintAndLogEx(WARNING, "Only specify one MIFARE Type"); + return PM3_EINVARG; + } else if ((m0 + m1 + m2 + m4) == 0) { + m1 = true; } - bytes = blocks * MFBLOCK_SIZE; - dump = calloc(bytes, sizeof(uint8_t)); - if (!dump) { + uint16_t block_cnt = MIFARE_1K_MAXBLOCK; + + if (m0) { + block_cnt = MIFARE_MINI_MAXBLOCK; + } else if (m1) { + block_cnt = MIFARE_1K_MAXBLOCK; + } else if (m2) { + block_cnt = MIFARE_2K_MAXBLOCK; + } else if (m4) { + block_cnt = MIFARE_4K_MAXBLOCK; + } else { + PrintAndLogEx(WARNING, "Please specify a MIFARE Type"); + return PM3_EINVARG; + } + + int bytes = block_cnt * MFBLOCK_SIZE; + + uint8_t *dump = calloc(bytes, sizeof(uint8_t)); + if (dump == NULL) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return PM3_EMALLOC; } memset(dump, 0, bytes); - PrintAndLogEx(INFO, "downloading from emulator memory"); + PrintAndLogEx(INFO, "downloading emulator memory"); if (!GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); free(dump); return PM3_ETIMEOUT; } - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); - PrintAndLogEx(INFO, "blk | data | ascii"); - PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); - for (uint16_t i = 0; i < blocks; i++) { - if (i == 0) { - PrintAndLogEx(INFO, "%03d | " _RED_("%s"), i, sprint_hex_ascii(dump + (i * 16), 16)); - } else if (mfIsSectorTrailer(i)) { - PrintAndLogEx(INFO, "%03d | " _YELLOW_("%s"), i, sprint_hex_ascii(dump + (i * 16), 16)); - } else { - PrintAndLogEx(INFO, "%03d | %s ", i, sprint_hex_ascii(dump + (i * 16), 16)); - } - } - PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); - PrintAndLogEx(NORMAL, ""); + mf_print_blocks(block_cnt, dump); free(dump); return PM3_SUCCESS; } @@ -4782,7 +4812,7 @@ static int CmdHF14AMfCView(const char *Cmd) { PrintAndLogEx(INFO, "." NOLF); uint8_t *dump = calloc(bytes, sizeof(uint8_t)); - if (!dump) { + if (dump == NULL) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return PM3_EMALLOC; } @@ -4824,27 +4854,11 @@ static int CmdHF14AMfCView(const char *Cmd) { free(dump); return PM3_ESOFT; } - PrintAndLogEx(NORMAL, "." NOLF); fflush(stdout); } - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); - PrintAndLogEx(INFO, "blk | data | ascii"); - PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); - for (uint16_t i = 0; i < numblocks; i++) { - - if (i == 0) { - PrintAndLogEx(INFO, "%03d | " _RED_("%s"), i, sprint_hex_ascii(dump + (i * 16), 16)); - } else if (mfIsSectorTrailer(i)) { - PrintAndLogEx(INFO, "%03d | " _YELLOW_("%s"), i, sprint_hex_ascii(dump + (i * 16), 16)); - } else { - PrintAndLogEx(INFO, "%03d | %s ", i, sprint_hex_ascii(dump + (i * 16), 16)); - } - } - PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); - PrintAndLogEx(NORMAL, ""); + mf_print_blocks(numblocks, dump); free(dump); return PM3_SUCCESS; } @@ -5780,6 +5794,51 @@ out: return PM3_SUCCESS; } +static int CmdHF14AMfView(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf view", + "Print a MIFARE Classic dump file", + "hf mf view -f hf-mf-01020304-dump.bin" + ); + void *argtable[] = { + arg_param_begin, + arg_str1("f", "file", "", "filename of dump"), + arg_lit0("v", "verbose", "verbose output"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int fnlen = 0; + char filename[FILE_PATH_SIZE]; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + bool verbose = arg_get_lit(ctx, 2); + CLIParserFree(ctx); + + uint8_t *dump = NULL; + size_t bytes_read = 0; + if (loadFile_safe(filename, "", (void **)&dump, &bytes_read) != PM3_SUCCESS) { + PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); + return PM3_EFILE; + } + uint16_t block_cnt = MIFARE_1K_MAXBLOCK; + if (bytes_read == 320) + block_cnt = MIFARE_MINI_MAXBLOCK; + else if (bytes_read == 2048) + block_cnt = MIFARE_2K_MAXBLOCK; + else if (bytes_read == 4096) + block_cnt = MIFARE_4K_MAXBLOCK; + + if (verbose) { + PrintAndLogEx(INFO, "File: " _YELLOW_("%s"), filename); + PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, block_cnt, block_cnt); + } + + mf_print_blocks(block_cnt, dump); + free(dump); + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"list", CmdHF14AMfList, AlwaysAvailable, "List MIFARE history"}, @@ -5805,6 +5864,7 @@ static command_t CommandTable[] = { {"rdsc", CmdHF14AMfRdSc, IfPm3Iso14443a, "Read MIFARE Classic sector"}, {"restore", CmdHF14AMfRestore, IfPm3Iso14443a, "Restore MIFARE Classic binary file to BLANK tag"}, {"setmod", CmdHf14AMfSetMod, IfPm3Iso14443a, "Set MIFARE Classic EV1 load modulation strength"}, + {"view", CmdHF14AMfView, IfPm3Iso14443a, "Display content from tag dump file"}, {"wipe", CmdHF14AMfWipe, IfPm3Iso14443a, "Wipe card to zeros and default keys/acc"}, {"wrbl", CmdHF14AMfWrBl, IfPm3Iso14443a, "Write MIFARE Classic block"}, @@ -5819,7 +5879,7 @@ static command_t CommandTable[] = { {"eload", CmdHF14AMfELoad, IfPm3Iso14443a, "Load from file emul dump"}, {"esave", CmdHF14AMfESave, IfPm3Iso14443a, "Save to file emul dump"}, {"eset", CmdHF14AMfESet, IfPm3Iso14443a, "Set emulator memory block"}, - {"eview", CmdHF14AMfEView, IfPm3Iso14443a, "View emul memory"}, + {"eview", CmdHF14AMfEView, IfPm3Iso14443a, "View emulator memory"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen1") " -----------------------"}, {"cgetblk", CmdHF14AMfCGetBlk, IfPm3Iso14443a, "Read block"}, {"cgetsc", CmdHF14AMfCGetSc, IfPm3Iso14443a, "Read sector"}, From 0ea906a3f8eab851bdc96951a4b3b2e568b8c3bf Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 10 Apr 2021 15:42:21 +0200 Subject: [PATCH 205/373] text --- doc/cliparser_todo.txt | 4 ---- doc/commands.md | 3 ++- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 5904252aa..e434ea617 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -18,19 +18,15 @@ hf felica rqspecver hf felica resetmode hf mf hardnested hf mf autopwn -hf mf nack hf mf decrypt hf mf rdsc hf mf restore hf mf setmod hf mf wrbl hf mf ecfill -hf mf eclr -hf mf ekeyprn hf mf eload hf mf esave hf mf eset -hf mf eview hf mf cload hf mf csave hf mf csetblk diff --git a/doc/commands.md b/doc/commands.md index 72a2eb1b7..ff84df328 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -403,6 +403,7 @@ Check column "offline" for their availability. |`hf mf rdsc `|N |`Read MIFARE Classic sector` |`hf mf restore `|N |`Restore MIFARE Classic binary file to BLANK tag` |`hf mf setmod `|N |`Set MIFARE Classic EV1 load modulation strength` +|`hf mf view `|Y |`Display content from tag dump file` |`hf mf wipe `|N |`Wipe card to zeros and default keys/acc` |`hf mf wrbl `|N |`Write MIFARE Classic block` |`hf mf sim `|N |`Simulate MIFARE card` @@ -414,7 +415,7 @@ Check column "offline" for their availability. |`hf mf eload `|N |`Load from file emul dump` |`hf mf esave `|N |`Save to file emul dump` |`hf mf eset `|N |`Set emulator memory block` -|`hf mf eview `|N |`View emul memory` +|`hf mf eview `|N |`View emulator memory` |`hf mf cgetblk `|N |`Read block` |`hf mf cgetsc `|N |`Read sector` |`hf mf cload `|N |`Load dump` From 43c42a06a03c5cda6b86a490437d40884f9bc640 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 10 Apr 2021 18:13:11 +0200 Subject: [PATCH 206/373] hf mf eload - now uses cliparser, and fixes for block printing etc. --- client/src/cmdhfmf.c | 327 +++++++++++++++++++++++-------------------- 1 file changed, 172 insertions(+), 155 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index ad3158116..decca851f 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -188,22 +188,6 @@ static int usage_hf14_decryptbytes(void) { return PM3_SUCCESS; } -static int usage_hf14_eset(void) { - PrintAndLogEx(NORMAL, "Usage: hf mf eset "); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf eset 1 000102030405060708090a0b0c0d0e0f")); - return PM3_SUCCESS; -} -static int usage_hf14_eload(void) { - PrintAndLogEx(NORMAL, "It loads emul dump from the file `filename.eml`"); - PrintAndLogEx(NORMAL, "Usage: hf mf eload [card memory] [numblocks]"); - PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (MIFARE Mini), 1 = 1K (default), 2 = 2K, 4 = 4K, u = UL"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf eload filename")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf eload 4 filename")); - return PM3_SUCCESS; -} static int usage_hf14_esave(void) { PrintAndLogEx(NORMAL, "It saves emul dump into the file `filename.eml` or `cardID.eml`"); PrintAndLogEx(NORMAL, " Usage: hf mf esave [card memory] [file name w/o `.eml`]"); @@ -215,7 +199,6 @@ static int usage_hf14_esave(void) { PrintAndLogEx(NORMAL, _YELLOW_(" hf mf esave 4 filename")); return PM3_SUCCESS; } - static int usage_hf14_ecfill(void) { PrintAndLogEx(NORMAL, "Read card and transfer its data to emulator memory."); PrintAndLogEx(NORMAL, "Keys must be laid in the emulator memory. \n"); @@ -274,7 +257,6 @@ static int usage_hf14_cload(void) { PrintAndLogEx(NORMAL, _YELLOW_(" hf mf cload e")); return PM3_SUCCESS; } - static int usage_hf14_csave(void) { PrintAndLogEx(NORMAL, "It saves `magic Chinese` card dump into the file `filename.eml` or `cardID.eml`"); PrintAndLogEx(NORMAL, "or into emulator memory"); @@ -536,20 +518,21 @@ static char GetFormatFromSector(uint8_t sectorNo) { static void mf_print_block(uint8_t blockno, uint8_t *d) { if (blockno == 0) { - PrintAndLogEx(INFO, "%3d | " _RED_("%s"), blockno, sprint_hex_ascii(d + (blockno * 16), 16)); + PrintAndLogEx(INFO, "%3d | " _RED_("%s"), blockno, sprint_hex_ascii(d, MFBLOCK_SIZE)); } else if (mfIsSectorTrailer(blockno)) { - PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), blockno, sprint_hex_ascii(d + (blockno * 16), 16)); + PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), blockno, sprint_hex_ascii(d, MFBLOCK_SIZE)); } else { - PrintAndLogEx(INFO, "%3d | %s ", blockno, sprint_hex_ascii(d + (blockno * 16), 16)); + PrintAndLogEx(INFO, "%3d | %s ", blockno, sprint_hex_ascii(d, MFBLOCK_SIZE)); } } + static void mf_print_blocks(uint16_t n, uint8_t *d) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); PrintAndLogEx(INFO, "blk | data | ascii"); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); for (uint16_t i = 0; i < n; i++) { - mf_print_block(i, d); + mf_print_block(i, d + (i * MFBLOCK_SIZE)); } PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); PrintAndLogEx(NORMAL, ""); @@ -697,7 +680,6 @@ static int CmdHF14AMfRdBl(const char *Cmd) { int keylen = 0; uint8_t key[6] = {0}; CLIGetHexWithReturn(ctx, 4, key, &keylen); - bool verbose = arg_get_lit(ctx, 5); CLIParserFree(ctx); @@ -714,15 +696,9 @@ static int CmdHF14AMfRdBl(const char *Cmd) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); - if (blockno == 0) { - PrintAndLogEx(INFO, "%3d | " _RED_("%s"), blockno, sprint_hex_ascii(data, sizeof(data))); - } else if (mfIsSectorTrailer(blockno)) { - PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), blockno, sprint_hex_ascii(data, sizeof(data))); - if (verbose) { - decode_print_st(blockno, data); - } - } else { - PrintAndLogEx(INFO, "%3d | %s ", blockno, sprint_hex_ascii(data, sizeof(data))); + mf_print_block(blockno, data); + if (verbose) { + decode_print_st(blockno, data); } } PrintAndLogEx(NORMAL, ""); @@ -742,6 +718,7 @@ static int CmdHF14AMfRdSc(const char *Cmd) { arg_lit0("b", NULL, "input key specified is B key"), arg_str0("k", "key", "", "key specified as 6 hex bytes"), arg_int1("s", "sec", "", "sector number"), + arg_lit0("v", "verbose", "verbose output"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -759,6 +736,7 @@ static int CmdHF14AMfRdSc(const char *Cmd) { CLIGetHexWithReturn(ctx, 3, key, &keylen); int s = arg_get_int_def(ctx, 4, 0); + bool verbose = arg_get_lit(ctx, 5); CLIParserFree(ctx); if (s > MIFARE_4K_MAXSECTOR) { @@ -766,7 +744,7 @@ static int CmdHF14AMfRdSc(const char *Cmd) { return PM3_EINVARG; } uint8_t sector = (uint8_t)s; - uint8_t sc_size = mfNumBlocksPerSector(sector) * 16; + uint8_t sc_size = mfNumBlocksPerSector(sector) * MFBLOCK_SIZE; uint8_t *data = calloc(sc_size, sizeof(uint8_t)); if (data == NULL) { PrintAndLogEx(ERR, "failed to allocate memory"); @@ -783,17 +761,15 @@ static int CmdHF14AMfRdSc(const char *Cmd) { PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); for (int i = 0; i < blocks; i++) { - 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)); - } + mf_print_block(start + i, data + (i * MFBLOCK_SIZE)); } - decode_print_st(start + blocks - 1, data + ((blocks - 1) * 16)); + + if (verbose) { + decode_print_st(start + blocks - 1, data + ((blocks - 1) * MFBLOCK_SIZE)); + } } free(data); + PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -3772,8 +3748,8 @@ static int CmdHF14AMfEGetBlk(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf egetblk", "Get emulator memory block", - "hf mf egetblk -b 0 -> get block 0 (manufacturer)\n" - "hf mf egetblk -b 3 -v -> get block 3, decode sector trailer\n" + "hf mf egetblk --blk 0 -> get block 0 (manufacturer)\n" + "hf mf egetblk --blk 3 -v -> get block 3, decode sector trailer\n" ); void *argtable[] = { arg_param_begin, @@ -3798,20 +3774,16 @@ static int CmdHF14AMfEGetBlk(const char *Cmd) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); - if (blockno == 0) { - PrintAndLogEx(INFO, "%3d | " _RED_("%s"), blockno, sprint_hex_ascii(data, sizeof(data))); - } else if (mfIsSectorTrailer(blockno)) { - PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), blockno, sprint_hex_ascii(data, sizeof(data))); - if (verbose) { - decode_print_st(blockno, data); - } - } else { - PrintAndLogEx(INFO, "%3d | %s ", blockno, sprint_hex_ascii(data, sizeof(data))); - } - + mf_print_block(blockno, data); + } + if (verbose) { + decode_print_st(blockno, data); + } else { + PrintAndLogEx(NORMAL, ""); } return PM3_SUCCESS; } + static int CmdHF14AMfEGetSc(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf egetsc", @@ -3821,11 +3793,14 @@ static int CmdHF14AMfEGetSc(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_int1("s", "sec", "", "sector number"), + arg_lit0("v", "verbose", "verbose output"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); int s = arg_get_int_def(ctx, 1, 0); + bool verbose = arg_get_lit(ctx, 2); CLIParserFree(ctx); + if (s > 39) { PrintAndLogEx(WARNING, "Sector number must be less then 40"); return PM3_EINVARG; @@ -3844,16 +3819,14 @@ static int CmdHF14AMfEGetSc(const char *Cmd) { for (int i = 0; i < blocks; i++) { int res = mfEmlGetMem(data, start + i, 1); if (res == PM3_SUCCESS) { - if (start + i == 0) { - PrintAndLogEx(INFO, "%3d | " _RED_("%s"), start + i, sprint_hex_ascii(data, sizeof(data))); - } else if (mfIsSectorTrailer(i)) { - PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), start + i, sprint_hex_ascii(data, sizeof(data))); - } else { - PrintAndLogEx(INFO, "%3d | %s ", start + i, sprint_hex_ascii(data, sizeof(data))); - } + mf_print_block(start + i, data); } } - decode_print_st(start + blocks - 1, data); + if (verbose) { + decode_print_st(start + blocks - 1, data); + } else { + PrintAndLogEx(NORMAL, ""); + } return PM3_SUCCESS; } @@ -3875,66 +3848,114 @@ static int CmdHF14AMfEClear(const char *Cmd) { } static int CmdHF14AMfESet(const char *Cmd) { - char c = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 3 || c == 'h') - return usage_hf14_eset(); - uint8_t memBlock[16]; - memset(memBlock, 0x00, sizeof(memBlock)); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf esetblk", + "Set emulator memory block", + "hf mf esetblk --blk 1 -d 000102030405060708090a0b0c0d0e0f" + ); + void *argtable[] = { + arg_param_begin, + arg_int1("b", "blk", "", "block number"), + arg_str0("d", "data", "", "bytes to write, 16 hex bytes"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); - uint8_t blockNo = param_get8(Cmd, 0); + int b = arg_get_int_def(ctx, 1, 0); - if (param_gethex(Cmd, 1, memBlock, 32)) { - PrintAndLogEx(WARNING, "block data must include 32 HEX symbols"); - return PM3_ESOFT; + uint8_t data[16] = {0x00}; + int datalen = 0; + int res = CLIParamHexToBuf(arg_get_str(ctx, 2), data, sizeof(data), &datalen); + CLIParserFree(ctx); + if (res) { + PrintAndLogEx(FAILED, "Error parsing bytes"); + return PM3_EINVARG; + } + + if (b > 255) { + return PM3_EINVARG; + } + + if (datalen != sizeof(data)) { + PrintAndLogEx(WARNING, "block data must include 16 HEX bytes. Got %i", datalen); + return PM3_EINVARG; } // 1 - blocks count - return mfEmlSetMem(memBlock, blockNo, 1); + return mfEmlSetMem(data, b, 1); } int CmdHF14AMfELoad(const char *Cmd) { - size_t counter = 0; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf eload", + "Load emulator memory with data from `filename.eml` dump file", + "hf mf eload -f hf-mf-01020304.eml\n" + "hf mf eload --4k -f hf-mf-01020304.eml\n" + ); + void *argtable[] = { + arg_param_begin, + arg_str1("f", "file", "", "filename of dump"), + arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"), + arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"), + arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"), + arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"), + arg_lit0(NULL, "ul", "MIFARE Ultralight family"), + arg_int0(NULL, "blks", "", "manually set number of blocks (overrides)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int fnlen = 0; char filename[FILE_PATH_SIZE]; - int blockNum, numBlocks, nameParamNo = 1; - uint8_t blockWidth = 16; - char c = tolower(param_getchar(Cmd, 0)); + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - if (strlen(Cmd) < 2 && c == 'h') - return usage_hf14_eload(); + bool m0 = arg_get_lit(ctx, 2); + bool m1 = arg_get_lit(ctx, 3); + bool m2 = arg_get_lit(ctx, 4); + bool m4 = arg_get_lit(ctx, 5); + bool mu = arg_get_lit(ctx, 6); - switch (c) { - case '0' : - numBlocks = MIFARE_MINI_MAXBLOCK; - break; - case '1' : - case '\0': - numBlocks = MIFARE_1K_MAXBLOCK; - break; - case '2' : - numBlocks = MIFARE_2K_MAXBLOCK; - break; - case '4' : - numBlocks = MIFARE_4K_MAXBLOCK; - break; - case 'u' : - numBlocks = 255; - blockWidth = 4; - break; - default: { - numBlocks = MIFARE_1K_MAXBLOCK; - nameParamNo = 0; - } + int numblks = arg_get_int_def(ctx, 7, -1); + + CLIParserFree(ctx); + + // validations + if ((m0 + m1 + m2 + m4 + mu) > 1) { + PrintAndLogEx(WARNING, "Only specify one MIFARE Type"); + return PM3_EINVARG; + } else if ((m0 + m1 + m2 + m4 + mu) == 0) { + m1 = true; } - uint32_t numblk2 = param_get32ex(Cmd, 2, 0, 10); - if (numblk2 > 0) - numBlocks = numblk2; - if (0 == param_getstr(Cmd, nameParamNo, filename, sizeof(filename))) - return usage_hf14_eload(); + uint8_t block_width = 16; + uint16_t block_cnt = MIFARE_1K_MAXBLOCK; - uint8_t *data = calloc(4096, sizeof(uint8_t)); + if (m0) { + block_cnt = MIFARE_MINI_MAXBLOCK; + } else if (m1) { + block_cnt = MIFARE_1K_MAXBLOCK; + } else if (m2) { + block_cnt = MIFARE_2K_MAXBLOCK; + } else if (m4) { + block_cnt = MIFARE_4K_MAXBLOCK; + } else if (mu) { + block_cnt = 255; + block_width = 4; + } else { + PrintAndLogEx(WARNING, "Please specify a MIFARE Type"); + return PM3_EINVARG; + } + + PrintAndLogEx(INFO, "%d blocks ( %u bytes ) to upload", block_cnt, block_cnt * block_width); + + if (numblks > 0) { + block_cnt = MIN(numblks, block_cnt); + PrintAndLogEx(INFO, "overriding number of blocks, will use %d blocks ( %u bytes )", block_cnt, block_cnt * block_width); + } + + uint8_t *data = calloc(MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK, sizeof(uint8_t)); if (data == NULL) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return PM3_EMALLOC; @@ -3949,15 +3970,14 @@ int CmdHF14AMfELoad(const char *Cmd) { } // 64 or 256 blocks. - if ((datalen % blockWidth) != 0) { + if ((datalen % block_width) != 0) { PrintAndLogEx(FAILED, "File content error. Size doesn't match blockwidth "); free(data); return PM3_ESOFT; } // convert plain or old mfu format to new format - if (blockWidth == 4) { - + if (block_width == 4) { res = convert_mfu_dump_format(&data, &datalen, true); if (res != PM3_SUCCESS) { PrintAndLogEx(FAILED, "Failed convert on load to new Ultralight/NTAG format"); @@ -3969,7 +3989,8 @@ int CmdHF14AMfELoad(const char *Cmd) { printMFUdumpEx(mfu_dump, mfu_dump->pages + 1, 0); // update expected blocks to match converted data. - numBlocks = datalen / 4; + block_cnt = datalen / 4; + PrintAndLogEx(INFO, "MIFARE Ultralight override, will use %d ( %u bytes )", block_cnt, block_cnt * block_width); } PrintAndLogEx(INFO, "Uploading to emulator memory"); @@ -3977,46 +3998,47 @@ int CmdHF14AMfELoad(const char *Cmd) { // fast push mode conn.block_after_ACK = true; - blockNum = 0; - while (datalen) { - if (datalen == blockWidth) { + + size_t offset = 0; + int cnt = 0; + + while (datalen && cnt < block_cnt) { + if (datalen == block_width) { // Disable fast mode on last packet conn.block_after_ACK = false; } - if (mfEmlSetMem_xt(data + counter, blockNum, 1, blockWidth) != PM3_SUCCESS) { - PrintAndLogEx(FAILED, "Cant set emul block: %3d", blockNum); + if (mfEmlSetMem_xt(data + offset, cnt, 1, block_width) != PM3_SUCCESS) { + PrintAndLogEx(FAILED, "Can't set emulator mem at block: %3d", cnt); free(data); return PM3_ESOFT; } PrintAndLogEx(NORMAL, "." NOLF); fflush(stdout); - blockNum++; - counter += blockWidth; - datalen -= blockWidth; + cnt++; + offset += block_width; + datalen -= block_width; } free(data); PrintAndLogEx(NORMAL, "\n"); - if (blockWidth == 4) { + if (block_width == 4) { PrintAndLogEx(HINT, "You are ready to simulate. See " _YELLOW_("`hf mfu sim h`")); // MFU / NTAG - if ((blockNum != numBlocks)) { - PrintAndLogEx(WARNING, "Warning, Ultralight/Ntag file content, Loaded %d blocks of expected %d blocks into emulator memory", blockNum, numBlocks); + if ((cnt != block_cnt)) { + PrintAndLogEx(WARNING, "Warning, Ultralight/Ntag file content, Loaded %d blocks of expected %d blocks into emulator memory", cnt, block_cnt); return PM3_SUCCESS; } } else { PrintAndLogEx(HINT, "You are ready to simulate. See " _YELLOW_("`hf mf sim -h`")); // MFC - if ((blockNum != numBlocks)) { - PrintAndLogEx(WARNING, "Error, file content, Only loaded %d blocks, must be %d blocks into emulator memory", blockNum, numBlocks); - + if ((cnt != block_cnt)) { + PrintAndLogEx(WARNING, "Error, file content, Only loaded %d blocks, must be %d blocks into emulator memory", cnt, block_cnt); return PM3_SUCCESS; } - } - PrintAndLogEx(SUCCESS, "Done"); + PrintAndLogEx(SUCCESS, "Done!"); return PM3_SUCCESS; } @@ -4541,8 +4563,8 @@ static int CmdHF14AMfCGetBlk(const char *Cmd) { CLIParserInit(&ctx, "hf mf cgetblk", "Get block data from magic Chinese card.\n" "Only works with magic gen1a cards", - "hf mf cgetblk -b 0 -> get block 0 (manufacturer)\n" - "hf mf cgetblk -b 3 -v -> get block 3, decode sector trailer\n" + "hf mf cgetblk --blk 0 --> get block 0 (manufacturer)\n" + "hf mf cgetblk --blk 3 -v --> get block 3, decode sector trailer\n" ); void *argtable[] = { arg_param_begin, @@ -4567,22 +4589,17 @@ static int CmdHF14AMfCGetBlk(const char *Cmd) { return PM3_ESOFT; } - uint8_t sector = GetSectorFromBlockNo(blockno); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); - if (blockno == 0) { - PrintAndLogEx(INFO, "%3d | " _RED_("%s"), blockno, sprint_hex_ascii(data, sizeof(data))); - } else if (mfIsSectorTrailer(blockno)) { - PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), blockno, sprint_hex_ascii(data, sizeof(data))); - if (verbose) { - decode_print_st(blockno, data); - } + mf_print_block(blockno, data); + + if (verbose) { + decode_print_st(blockno, data); } else { - PrintAndLogEx(INFO, "%3d | %s ", blockno, sprint_hex_ascii(data, sizeof(data))); + PrintAndLogEx(NORMAL, ""); } - return PM3_SUCCESS; } @@ -4596,10 +4613,12 @@ static int CmdHF14AMfCGetSc(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_int1("s", "sec", "", "sector number"), + arg_lit0("v", "verbose", "verbose output"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); int s = arg_get_int_def(ctx, 1, 0); + bool verbose = arg_get_lit(ctx, 2); CLIParserFree(ctx); if (s > 39) { PrintAndLogEx(WARNING, "Sector number must be less then 40"); @@ -4630,16 +4649,13 @@ static int CmdHF14AMfCGetSc(const char *Cmd) { PrintAndLogEx(ERR, "Can't read block. %d error=%d", start + i, res); return PM3_ESOFT; } - - if (start + i == 0) { - PrintAndLogEx(INFO, "%3d | " _RED_("%s"), start + i, sprint_hex_ascii(data, sizeof(data))); - } else if (mfIsSectorTrailer(i)) { - PrintAndLogEx(INFO, "%3d | " _YELLOW_("%s"), start + i, sprint_hex_ascii(data, sizeof(data))); - } else { - PrintAndLogEx(INFO, "%3d | %s ", start + i, sprint_hex_ascii(data, sizeof(data))); - } + mf_print_block(start + i, data); + } + if (verbose) { + decode_print_st(start + blocks - 1, data); + } else { + PrintAndLogEx(NORMAL, ""); } - decode_print_st(start + blocks - 1, data); return PM3_SUCCESS; } @@ -4858,6 +4874,7 @@ static int CmdHF14AMfCView(const char *Cmd) { fflush(stdout); } + PrintAndLogEx(NORMAL, ""); mf_print_blocks(numblocks, dump); free(dump); return PM3_SUCCESS; @@ -5864,7 +5881,7 @@ static command_t CommandTable[] = { {"rdsc", CmdHF14AMfRdSc, IfPm3Iso14443a, "Read MIFARE Classic sector"}, {"restore", CmdHF14AMfRestore, IfPm3Iso14443a, "Restore MIFARE Classic binary file to BLANK tag"}, {"setmod", CmdHf14AMfSetMod, IfPm3Iso14443a, "Set MIFARE Classic EV1 load modulation strength"}, - {"view", CmdHF14AMfView, IfPm3Iso14443a, "Display content from tag dump file"}, + {"view", CmdHF14AMfView, AlwaysAvailable, "Display content from tag dump file"}, {"wipe", CmdHF14AMfWipe, IfPm3Iso14443a, "Wipe card to zeros and default keys/acc"}, {"wrbl", CmdHF14AMfWrBl, IfPm3Iso14443a, "Write MIFARE Classic block"}, @@ -5878,16 +5895,16 @@ static command_t CommandTable[] = { {"ekeyprn", CmdHF14AMfEKeyPrn, IfPm3Iso14443a, "Print keys from emulator memory"}, {"eload", CmdHF14AMfELoad, IfPm3Iso14443a, "Load from file emul dump"}, {"esave", CmdHF14AMfESave, IfPm3Iso14443a, "Save to file emul dump"}, - {"eset", CmdHF14AMfESet, IfPm3Iso14443a, "Set emulator memory block"}, + {"esetblk", CmdHF14AMfESet, IfPm3Iso14443a, "Set emulator memory block"}, {"eview", CmdHF14AMfEView, IfPm3Iso14443a, "View emulator memory"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen1") " -----------------------"}, - {"cgetblk", CmdHF14AMfCGetBlk, IfPm3Iso14443a, "Read block"}, - {"cgetsc", CmdHF14AMfCGetSc, IfPm3Iso14443a, "Read sector"}, - {"cload", CmdHF14AMfCLoad, IfPm3Iso14443a, "Load dump"}, + {"cgetblk", CmdHF14AMfCGetBlk, IfPm3Iso14443a, "Read block from card"}, + {"cgetsc", CmdHF14AMfCGetSc, IfPm3Iso14443a, "Read sector from card"}, + {"cload", CmdHF14AMfCLoad, IfPm3Iso14443a, "Load dump to card"}, {"csave", CmdHF14AMfCSave, IfPm3Iso14443a, "Save dump from card into file or emulator"}, - {"csetblk", CmdHF14AMfCSetBlk, IfPm3Iso14443a, "Write block"}, - {"csetuid", CmdHF14AMfCSetUID, IfPm3Iso14443a, "Set UID"}, - {"cview", CmdHF14AMfCView, IfPm3Iso14443a, "view card"}, + {"csetblk", CmdHF14AMfCSetBlk, IfPm3Iso14443a, "Write block to card"}, + {"csetuid", CmdHF14AMfCSetUID, IfPm3Iso14443a, "Set UID on card"}, + {"cview", CmdHF14AMfCView, IfPm3Iso14443a, "View card"}, {"cwipe", CmdHF14AMfCWipe, IfPm3Iso14443a, "Wipe card to default UID/Sectors/Keys"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen3") " -----------------------"}, {"gen3uid", CmdHf14AGen3UID, IfPm3Iso14443a, "Set UID without manufacturer block"}, From 5ac7b9fd9f75d9b1d8e18e812711601df61e55d4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 10 Apr 2021 18:21:38 +0200 Subject: [PATCH 207/373] hf mfu eload - now works again :) --- client/src/cmdhfmf.c | 4 ++-- client/src/cmdhfmfu.c | 13 ++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index decca851f..4d08bf5b2 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -3902,7 +3902,7 @@ int CmdHF14AMfELoad(const char *Cmd) { arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"), arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"), arg_lit0(NULL, "ul", "MIFARE Ultralight family"), - arg_int0(NULL, "blks", "", "manually set number of blocks (overrides)"), + arg_int0("q", "qty", "", "manually set number of blocks (overrides)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -3990,7 +3990,7 @@ int CmdHF14AMfELoad(const char *Cmd) { // update expected blocks to match converted data. block_cnt = datalen / 4; - PrintAndLogEx(INFO, "MIFARE Ultralight override, will use %d ( %u bytes )", block_cnt, block_cnt * block_width); + PrintAndLogEx(INFO, "MIFARE Ultralight override, will use %d blocks ( %u bytes )", block_cnt, block_cnt * block_width); } PrintAndLogEx(INFO, "Uploading to emulator memory"); diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 88b7849d5..6fe59084d 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -2536,22 +2536,21 @@ static int CmdHF14AMfUeLoad(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfu eload", - "It loads emul dump from the file `filename.eml`", - "hf mfu eload -u -f myfile\n" - "hf mfu eload -u -f myfile -q 57 -> load 57 blocks from myfile" + "Load emulator memory with data from `filename.eml` dump file\n" + "\nSee `script run data_mfu_bin2eml` to convert the .bin to .eml", + "hf mfu eload --ul -f hf-mfu-04010203040506.eml\n" + "hf mfu eload --ul -f hf-mfu-04010203040506.eml -q 57 -> load 57 blocks from myfile" ); void *argtable[] = { arg_param_begin, - arg_str1("f", "file", "", "specify a filename w/o `.eml` to load"), - arg_lit1("u", NULL, "Ultralight Family type"), + arg_str1("f", "file", "", "filename of dump"), + arg_lit1(NULL, "ul", "MIFARE Ultralight family"), arg_int0("q", "qty", "", "number of blocks to load from eml file"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); CLIParserFree(ctx); - - PrintAndLogEx(HINT, "Hint: See " _YELLOW_("`script run data_mfu_bin2eml`") " to convert the .bin to .eml"); return CmdHF14AMfELoad(Cmd); } // From 40d920ebd8a484ff5019630cb6c13c59e6b29487 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 10 Apr 2021 18:22:31 +0200 Subject: [PATCH 208/373] textual --- doc/cliparser_todo.txt | 2 -- doc/commands.md | 14 +++++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index e434ea617..4f27fd219 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -24,9 +24,7 @@ hf mf restore hf mf setmod hf mf wrbl hf mf ecfill -hf mf eload hf mf esave -hf mf eset hf mf cload hf mf csave hf mf csetblk diff --git a/doc/commands.md b/doc/commands.md index ff84df328..04546c2e9 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -414,15 +414,15 @@ Check column "offline" for their availability. |`hf mf ekeyprn `|N |`Print keys from emulator memory` |`hf mf eload `|N |`Load from file emul dump` |`hf mf esave `|N |`Save to file emul dump` -|`hf mf eset `|N |`Set emulator memory block` +|`hf mf esetblk `|N |`Set emulator memory block` |`hf mf eview `|N |`View emulator memory` -|`hf mf cgetblk `|N |`Read block` -|`hf mf cgetsc `|N |`Read sector` -|`hf mf cload `|N |`Load dump` +|`hf mf cgetblk `|N |`Read block from card` +|`hf mf cgetsc `|N |`Read sector from card` +|`hf mf cload `|N |`Load dump to card` |`hf mf csave `|N |`Save dump from card into file or emulator` -|`hf mf csetblk `|N |`Write block` -|`hf mf csetuid `|N |`Set UID` -|`hf mf cview `|N |`view card` +|`hf mf csetblk `|N |`Write block to card` +|`hf mf csetuid `|N |`Set UID on card` +|`hf mf cview `|N |`View card` |`hf mf cwipe `|N |`Wipe card to default UID/Sectors/Keys` |`hf mf gen3uid `|N |`Set UID without manufacturer block` |`hf mf gen3blk `|N |`Overwrite full manufacturer block` From 93a9750d93a68b70cb71e80fe944a9e57d5d4ba5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 10 Apr 2021 19:08:32 +0200 Subject: [PATCH 209/373] hf mf ecfill - now uses cliparser --- client/src/cmdhfmf.c | 94 +++++++++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 35 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 4d08bf5b2..579ef8fb5 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -199,18 +199,6 @@ static int usage_hf14_esave(void) { PrintAndLogEx(NORMAL, _YELLOW_(" hf mf esave 4 filename")); return PM3_SUCCESS; } -static int usage_hf14_ecfill(void) { - PrintAndLogEx(NORMAL, "Read card and transfer its data to emulator memory."); - PrintAndLogEx(NORMAL, "Keys must be laid in the emulator memory. \n"); - PrintAndLogEx(NORMAL, "Usage: hf mf ecfill [card memory]"); - PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (MIFARE Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf ecfill A")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf ecfill A 4")); - return PM3_SUCCESS; -} - static int usage_hf14_csetuid(void) { PrintAndLogEx(NORMAL, "Set UID, ATQA, and SAK for magic Chinese card. Only works with magic cards"); @@ -659,8 +647,8 @@ static int CmdHF14AMfRdBl(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_int1(NULL, "blk", "", "block number"), - arg_lit0("a", NULL, "input key specified is A key (def)"), - arg_lit0("b", NULL, "input key specified is B key"), + arg_lit0("a", NULL, "input key type is key A (def)"), + arg_lit0("b", NULL, "input key type is key B"), arg_str0("k", "key", "", "key specified as 6 hex bytes"), arg_lit0("v", "verbose", "verbose output"), arg_param_end @@ -4161,36 +4149,72 @@ static int CmdHF14AMfEView(const char *Cmd) { } static int CmdHF14AMfECFill(const char *Cmd) { - uint8_t keyType = 0; - uint8_t numSectors = 16; - char c = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || c == 'h') - return usage_hf14_ecfill(); - - if (c != 'a' && c != 'b') { - PrintAndLogEx(WARNING, "Key type must be A or B"); - return PM3_ESOFT; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf ecfill", + "Dump card and transfer the data to emulator memory.\n" + "Keys must be laid in the emulator memory", + "hf mf ecfill --> use key type A\n" + "hf mf ecfill --4k -b --> target 4K card with key type B" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0("a", NULL, "input key type is key A(def)"), + arg_lit0("b", NULL, "input key type is key B"), + arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"), + arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"), + arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"), + arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + uint8_t keytype = 0; + if (arg_get_lit(ctx, 1) && arg_get_lit(ctx, 2)) { + CLIParserFree(ctx); + PrintAndLogEx(WARNING, "Input key type must be A or B"); + return PM3_EINVARG; + } else if (arg_get_lit(ctx, 2)) { + keytype = 1; } - if (c != 'a') - keyType = 1; - c = tolower(param_getchar(Cmd, 1)); - if (c != 0) { - numSectors = NumOfSectors(c); - if (numSectors == 0) return usage_hf14_ecfill(); + bool m0 = arg_get_lit(ctx, 3); + bool m1 = arg_get_lit(ctx, 4); + bool m2 = arg_get_lit(ctx, 5); + bool m4 = arg_get_lit(ctx, 6); + CLIParserFree(ctx); + + // validations + if ((m0 + m1 + m2 + m4) > 1) { + PrintAndLogEx(WARNING, "Only specify one MIFARE Type"); + return PM3_EINVARG; + } else if ((m0 + m1 + m2 + m4) == 0) { + m1 = true; + } + + uint8_t sectors_cnt = MIFARE_1K_MAXSECTOR; + + if (m0) { + sectors_cnt = MIFARE_MINI_MAXSECTOR; + } else if (m1) { + sectors_cnt = MIFARE_1K_MAXSECTOR; + } else if (m2) { + sectors_cnt = MIFARE_2K_MAXSECTOR; + } else if (m4) { + sectors_cnt = MIFARE_4K_MAXSECTOR; } else { - numSectors = MIFARE_1K_MAXSECTOR; + PrintAndLogEx(WARNING, "Please specify a MIFARE Type"); + return PM3_EINVARG; } - PrintAndLogEx(NORMAL, "--params: numSectors: %d, keyType: %c\n", numSectors, (keyType == 0) ? 'A' : 'B'); - - mfc_eload_t payload; - payload.sectorcnt = numSectors; - payload.keytype = keyType; + mfc_eload_t payload = { + .sectorcnt = sectors_cnt, + .keytype = keytype + }; clearCommandBuffer(); SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload)); + + // 2021, iceman: should get a response from device when its done. return PM3_SUCCESS; } From 99cb92e736bf2e208ec5f54994bce2a0b476c5d9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 10 Apr 2021 19:25:50 +0200 Subject: [PATCH 210/373] hf mf esave - now uses cliparser --- client/src/cmdhficlass.c | 7 ++-- client/src/cmdhfmf.c | 88 ++++++++++++++++++++++++---------------- 2 files changed, 56 insertions(+), 39 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 1628d95a2..cd7e5b62e 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -985,8 +985,6 @@ static int CmdHFiClassESave(const char *Cmd) { int fnlen = 0; char filename[FILE_PATH_SIZE] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - char *fnameptr = filename; - uint16_t bytes = arg_get_int_def(ctx, 2, 256); if (bytes > 4096) { @@ -1011,8 +1009,9 @@ static int CmdHFiClassESave(const char *Cmd) { // user supplied filename? if (fnlen < 1) { - fnameptr += snprintf(fnameptr, sizeof(filename), "hf-iclass-"); - FillFileNameByUID(fnameptr, dump, "-dump", 8); + char *fptr = filename; + fptr += snprintf(fptr, sizeof(filename), "hf-iclass-"); + FillFileNameByUID(fptr, dump, "-dump", 8); } saveFile(filename, ".bin", dump, bytes); diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 579ef8fb5..647e90372 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -188,18 +188,6 @@ static int usage_hf14_decryptbytes(void) { return PM3_SUCCESS; } -static int usage_hf14_esave(void) { - PrintAndLogEx(NORMAL, "It saves emul dump into the file `filename.eml` or `cardID.eml`"); - PrintAndLogEx(NORMAL, " Usage: hf mf esave [card memory] [file name w/o `.eml`]"); - PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (MIFARE Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf esave")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf esave 4")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf esave 4 filename")); - return PM3_SUCCESS; -} - static int usage_hf14_csetuid(void) { PrintAndLogEx(NORMAL, "Set UID, ATQA, and SAK for magic Chinese card. Only works with magic cards"); PrintAndLogEx(NORMAL, ""); @@ -4032,46 +4020,76 @@ int CmdHF14AMfELoad(const char *Cmd) { static int CmdHF14AMfESave(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf esave", + "Save emulator memory into three files (BIN/EML/JSON) ", + "hf mf esave\n" + "hf mf esave --4k\n" + "hf mf esave --4k -f hf-mf-01020304.eml" + ); + void *argtable[] = { + arg_param_begin, + arg_str0("f", "file", "", "filename of dump"), + arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"), + arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"), + arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"), + arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int fnlen = 0; char filename[FILE_PATH_SIZE]; - char *fnameptr = filename; - uint8_t *dump; - int len, bytes, nameParamNo = 1; - uint16_t blocks; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - memset(filename, 0, sizeof(filename)); + bool m0 = arg_get_lit(ctx, 2); + bool m1 = arg_get_lit(ctx, 3); + bool m2 = arg_get_lit(ctx, 4); + bool m4 = arg_get_lit(ctx, 5); + CLIParserFree(ctx); - char c = tolower(param_getchar(Cmd, 0)); - if (c == 'h') return usage_hf14_esave(); - - if (c != 0) { - blocks = NumOfBlocks(c); - if (blocks == 0) return usage_hf14_esave(); - } else { - blocks = MIFARE_1K_MAXBLOCK; + // validations + if ((m0 + m1 + m2 + m4) > 1) { + PrintAndLogEx(WARNING, "Only specify one MIFARE Type"); + return PM3_EINVARG; + } else if ((m0 + m1 + m2 + m4) == 0) { + m1 = true; } - bytes = blocks * MFBLOCK_SIZE; - dump = calloc(bytes, sizeof(uint8_t)); - if (!dump) { + uint16_t block_cnt = MIFARE_1K_MAXBLOCK; + + if (m0) { + block_cnt = MIFARE_MINI_MAXBLOCK; + } else if (m1) { + block_cnt = MIFARE_1K_MAXBLOCK; + } else if (m2) { + block_cnt = MIFARE_2K_MAXBLOCK; + } else if (m4) { + block_cnt = MIFARE_4K_MAXBLOCK; + } + + int bytes = block_cnt * MFBLOCK_SIZE; + + // reserv memory + uint8_t *dump = calloc(bytes, sizeof(uint8_t)); + if (dump == NULL) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return PM3_EMALLOC; } memset(dump, 0, bytes); - PrintAndLogEx(INFO, "downloading from emulator memory"); + PrintAndLogEx(INFO, "downloading %u bytes from emulator memory", bytes); if (!GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); free(dump); return PM3_ETIMEOUT; } - len = param_getstr(Cmd, nameParamNo, filename, sizeof(filename)); - if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; - // user supplied filename? - if (len < 1) { - fnameptr += snprintf(fnameptr, sizeof(filename), "hf-mf-"); - FillFileNameByUID(fnameptr, dump, "-dump", 4); + if (fnlen < 1) { + char *fptr = filename; + fptr += snprintf(fptr, sizeof(filename), "hf-mf-"); + FillFileNameByUID(fptr, dump, "-dump", 4); } saveFile(filename, ".bin", dump, bytes); From e8d0a1e7831ea6a183fb7d13558e666aafb942ef Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 10 Apr 2021 19:38:01 +0200 Subject: [PATCH 211/373] hf mf cview - now uses cliparser --- client/src/cmdhfmf.c | 100 ++++++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 45 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 647e90372..3a5de1428 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -251,18 +251,6 @@ static int usage_hf14_csave(void) { PrintAndLogEx(NORMAL, _YELLOW_(" hf mf csave 4 o filename")); return PM3_SUCCESS; } -static int usage_hf14_cview(void) { - PrintAndLogEx(NORMAL, "View `magic Chinese` card "); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf cview [h] [card memory]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " card memory 0 = 320 bytes (MIFARE Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf cview 1")); - return PM3_SUCCESS; -} static int usage_hf14_gen3uid(void) { PrintAndLogEx(NORMAL, "Set UID for magic GEN 3 card without manufacturer block changing"); @@ -4837,38 +4825,59 @@ static int CmdHF14AMfCSave(const char *Cmd) { static int CmdHF14AMfCView(const char *Cmd) { - bool errors = false; - int flags; - char ctmp = '1'; - uint8_t cmdp = 0; - uint16_t numblocks = NumOfBlocks(ctmp); - uint16_t bytes = numblocks * MFBLOCK_SIZE; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf cview", + "View `magic gen1a` card memory", + "hf mf cview\n" + "hf mf cview --4k" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"), + arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"), + arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"), + arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + bool m0 = arg_get_lit(ctx, 1); + bool m1 = arg_get_lit(ctx, 2); + bool m2 = arg_get_lit(ctx, 3); + bool m4 = arg_get_lit(ctx, 4); + CLIParserFree(ctx); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - ctmp = tolower(param_getchar(Cmd, cmdp)); - switch (ctmp) { - case 'h': - return usage_hf14_cview(); - case '0': - case '1': - case '2': - case '4': - numblocks = NumOfBlocks(ctmp); - bytes = numblocks * MFBLOCK_SIZE; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } + // validations + if ((m0 + m1 + m2 + m4) > 1) { + PrintAndLogEx(WARNING, "Only specify one MIFARE Type"); + return PM3_EINVARG; + } else if ((m0 + m1 + m2 + m4) == 0) { + m1 = true; } - if (errors) return usage_hf14_cview(); + char s[6]; + memset(s, 0, sizeof(s)); - PrintAndLogEx(SUCCESS, "View magic MIFARE " _GREEN_("%cK"), ctmp); + uint16_t block_cnt = MIFARE_1K_MAXBLOCK; + if (m0) { + block_cnt = MIFARE_MINI_MAXBLOCK; + strncpy(s, "Mini", 5); + } else if (m1) { + block_cnt = MIFARE_1K_MAXBLOCK; + strncpy(s, "1K", 3); + } else if (m2) { + block_cnt = MIFARE_2K_MAXBLOCK; + strncpy(s, "2K", 3); + } else if (m4) { + block_cnt = MIFARE_4K_MAXBLOCK; + strncpy(s, "4K", 3); + } else { + PrintAndLogEx(WARNING, "Please specify a MIFARE Type"); + return PM3_EINVARG; + } + PrintAndLogEx(SUCCESS, "View magic Gen1a MIFARE Classic " _GREEN_("%s"), s); PrintAndLogEx(INFO, "." NOLF); + int bytes = block_cnt * MFBLOCK_SIZE; uint8_t *dump = calloc(bytes, sizeof(uint8_t)); if (dump == NULL) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); @@ -4879,8 +4888,8 @@ static int CmdHF14AMfCView(const char *Cmd) { clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(WARNING, "iso14443a card select failed"); + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) { + PrintAndLogEx(WARNING, "iso14443a card select timeout"); free(dump); return PM3_ESOFT; } @@ -4902,13 +4911,14 @@ static int CmdHF14AMfCView(const char *Cmd) { iso14a_card_select_t card; memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); - flags = MAGIC_INIT + MAGIC_WUPC; - for (uint16_t i = 0; i < numblocks; i++) { + uint8_t flags = MAGIC_INIT + MAGIC_WUPC; + for (uint16_t i = 0; i < block_cnt; i++) { if (i == 1) flags = 0; - if (i == numblocks - 1) flags = MAGIC_HALT + MAGIC_OFF; + if (i == block_cnt - 1) flags = MAGIC_HALT + MAGIC_OFF; if (mfCGetBlock(i, dump + (i * MFBLOCK_SIZE), flags)) { - PrintAndLogEx(WARNING, "Cant get block: %d", i); + PrintAndLogEx(WARNING, "Can't get block: %d", i); + PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position"); free(dump); return PM3_ESOFT; } @@ -4917,7 +4927,7 @@ static int CmdHF14AMfCView(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - mf_print_blocks(numblocks, dump); + mf_print_blocks(block_cnt, dump); free(dump); return PM3_SUCCESS; } From e98a42c417c580f6c3f3fd612541d2709a2a837c Mon Sep 17 00:00:00 2001 From: Gator96100 Date: Sun, 11 Apr 2021 02:06:42 +0200 Subject: [PATCH 212/373] Update README.md for Proxspace v3.9 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a22b5fac1..8dd1ccf5e 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ The [public roadmap](https://github.com/RfidResearchGroup/proxmark3/wiki/Public- ## Supported operative systems This repo compiles nicely on - WSL1 on Windows 10 - - Proxspace v3.8 [release v3.8](https://github.com/Gator96100/ProxSpace/releases) + - Proxspace v3.9 [release v3.9](https://github.com/Gator96100/ProxSpace/releases) - Windows/mingw environment - Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, Nethunter, Archlinux, Fedora, Debian, Rasbian - Android / Termux From 9f0c5aa315d09d2e47ce090f66ef20a7e97adc0c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 11 Apr 2021 10:43:10 +0200 Subject: [PATCH 213/373] text --- doc/cheatsheet.md | 118 ++++++++++++++++++++++++---------------------- 1 file changed, 62 insertions(+), 56 deletions(-) diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index 03b1854f5..7816c1140 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -173,11 +173,11 @@ Options -t, --type Simulation type to use --csn Specify CSN as 8 bytes (16 hex symbols) to use with sim type 0 Types: -0 simulate the given CSN -1 simulate default CSN -2 Runs online part of LOCLASS attack -3 Full simulation using emulator memory (see 'hf iclass eload') -4 Runs online part of LOCLASS attack against reader in keyroll mode + 0 simulate the given CSN + 1 simulate default CSN + 2 runs online part of LOCLASS attack + 3 full simulation using emulator memory (see 'hf iclass eload') + 4 runs online part of LOCLASS attack against reader in keyroll mode pm3 --> hf iclass sim -t 3 ``` @@ -224,18 +224,18 @@ Check for default keys ``` Options --- - -k, --key Key specified as 12 hex symbols - --blk Input block number - -a Target Key A, if found also check Key B for duplicate - -b Target Key B - -*, --all Target both key A & B (default) - --mini MIFARE Classic Mini / S20 - --1k MIFARE Classic 1k / S50 (default) - --2k MIFARE Classic/Plus 2k - --4k MIFARE Classic 4k / S70 - --emu Fill simulator keys from found keys - --dump Dump found keys to binary file - -f, --file filename of dictionary +-k, --key Key specified as 12 hex symbols + --blk Input block number +-a Target Key A, if found also check Key B for duplicate +-b Target Key B +-*, --all Target both key A & B (default) + --mini MIFARE Classic Mini / S20 + --1k MIFARE Classic 1k / S50 (default) + --2k MIFARE Classic/Plus 2k + --4k MIFARE Classic 4k / S70 + --emu Fill simulator keys from found keys + --dump Dump found keys to binary file +-f, --file filename of dictionary pm3 --> hf mf chk --1k -f mfc_default_keys ``` @@ -244,15 +244,15 @@ Check for default keys from local memory ``` Options --- - -k, --key Key specified as 12 hex symbols - --mini MIFARE Classic Mini / S20 - --1k MIFARE Classic 1k / S50 (default) - --2k MIFARE Classic/Plus 2k - --4k MIFARE Classic 4k / S70 - --emu Fill simulator keys from found keys - --dump Dump found keys to binary file - --mem Use dictionary from flashmemory - -f, --file filename of dictionary +-k, --key Key specified as 12 hex symbols + --mini MIFARE Classic Mini / S20 + --1k MIFARE Classic 1k / S50 (default) + --2k MIFARE Classic/Plus 2k + --4k MIFARE Classic 4k / S70 + --emu Fill simulator keys from found keys + --dump Dump found keys to binary file + --mem Use dictionary from flashmemory +-f, --file filename of dictionary pm3 --> hf mf fchk --1k --mem ``` @@ -260,12 +260,12 @@ pm3 --> hf mf fchk --1k --mem Dump MIFARE card contents ``` options: - -f, --file filename of dump - -k, --keys filename of keys - --mini MIFARE Classic Mini / S20 - --1k MIFARE Classic 1k / S50 (default) - --2k MIFARE Classic/Plus 2k - --4k MIFARE Classic 4k / S70 +-f, --file filename of dump +-k, --keys filename of keys + --mini MIFARE Classic Mini / S20 + --1k MIFARE Classic 1k / S50 (default) + --2k MIFARE Classic/Plus 2k + --4k MIFARE Classic 4k / S70 examples/notes: hf mf dump --mini -> MIFARE Mini @@ -282,9 +282,10 @@ Convert .bin to .eml ``` Options --- -i : Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used +-i dump-file (input). If omitted, 'dumpdata.bin' is used +-o output file, if omitted, .eml is use -pm3 --> script run data_mf_bin2eml -i dumpdata.bin +pm3 --> script run data_mf_bin2eml -i dumpdata.bin -o hf-mf-myfile.bin ``` Write to MIFARE block @@ -314,15 +315,21 @@ w : Acquire nonces and write them to binary file nonces.bin pm3 --> hf mf hardnested 0 A 8829da9daf76 0 A w ``` -Load MIFARE emul dump file into memory for simulation +Load MIFARE Classic dump file into emulator memory for simulation +Accepts (BIN/EML/JSON) ``` Options --- - -[card memory]: 0 = 320 bytes (MIFARE Mini), 1 = 1K (default), 2 = 2K, 4 = 4K, u = UL +-f, --file filename of dump + --mini MIFARE Classic Mini / S20 + --1k MIFARE Classic 1k / S50 (def) + --2k MIFARE Classic/Plus 2k + --4k MIFARE Classic 4k / S70 + --ul MIFARE Ultralight family +-q, --qty manually set number of blocks (overrides) -pm3 --> hf mf eload hf-mf-353C2AA6 -pm3 --> hf mf eload 1 hf-mf-353C2AA6 +pm3 --> hf mf eload -f hf-mf-353C2AA6-dump.bin +pm3 --> hf mf eload --1k -f hf-mf-353C2AA6-dump.bin ``` Simulate MIFARE @@ -334,16 +341,15 @@ pm3 --> hf mf sim -u 353c2aa6 Simulate MIFARE Sequence ``` -pm3 --> hf mf chk -* --1k --all -f mfc_default_keys -pm3 --> hf mf dump 1 -pm3 --> script run data_mf_bin2eml -i dumpdata.bin -pm3 --> hf mf eload 353C2AA6 +pm3 --> hf mf fchk -1k -f mfc_default_keys.dic +pm3 --> hf mf dump +pm3 --> hf mf eload -f hf-mf--dump.bin pm3 --> hf mf sim -u 353c2aa6 ``` Clone MIFARE 1K Sequence ``` -pm3 --> hf mf chk -* --1k --all -f mfc_default_keys +pm3 --> hf mf fchk --1k -f mfc_default_keys.dic pm3 --> hf mf dump pm3 --> hf mf restore 1 u 4A6CE843 k hf-mf-A29558E4-key.bin f hf-mf-A29558E4-dump.bin ``` @@ -356,8 +362,7 @@ pm3 --> hf mfu info Clone MIFARE Ultralight EV1 Sequence ``` pm3 --> hf mfu dump -k FFFFFFFF -pm3 --> script run data_mfu_bin2eml -i hf-mfu-XXXX-dump.bin -o hf-mfu-XXXX-dump.eml -pm3 --> hf mfu eload -u -f hf-mfu-XXXX-dump.eml +pm3 --> hf mfu eload -u -f hf-mfu-XXXX-dump.bin pm3 --> hf mfu sim -t 7 ``` @@ -383,23 +388,24 @@ Convert Site & Facility code to Wiegand raw hex ``` Options --- --w --oem --fc --cn --issue + --fc facility number + --cn card number + --issue issue level + --oem OEM code +-w, --wiegand see `wiegand list` for available formats + --pre add HID ProxII preamble to wiegand output --w wiegand format to use - --oem OEM number / site code - --fc facility code - --cn card number - --issue issue level - -pm3 --> wiegand encode -w H10301 --oem 0 --fc 56 --cn 150 +pm3 --> wiegand encode -w H10301 --oem 0 --fc 101 --cn 1337 +pm3 --> wiegand encode --fc 101 --cn 1337 ``` Convert Site & Facility code from Wiegand raw hex to numbers ``` Options --- --p ignore parity errors - --raw raw hex to be decoded +-p, --parity ignore invalid parity +-r, --raw raw hex to be decoded +-b, --bin binary string to be decoded pm3 --> wiegand decode --raw 2006f623ae ``` From e4648ba1c347de9b343fc577b9d84aa407bc9636 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 11 Apr 2021 10:59:55 +0200 Subject: [PATCH 214/373] hf mf eload / cload now takes BIN/EML/JSON files --- client/src/cmdhfmf.c | 205 ++++++++++++++++++++++++++----------------- 1 file changed, 125 insertions(+), 80 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 3a5de1428..b5153e8c4 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -217,22 +217,7 @@ static int usage_hf14_csetblk(void) { PrintAndLogEx(NORMAL, _YELLOW_(" hf mf csetblk 1 01020304050607080910111213141516 w")); return PM3_SUCCESS; } -static int usage_hf14_cload(void) { - PrintAndLogEx(NORMAL, "It loads magic Chinese card from the file `filename.eml`"); - PrintAndLogEx(NORMAL, "or from emulator memory"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf cload [h] [e] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " e load card with data from emulator memory"); - PrintAndLogEx(NORMAL, " j load card with data from json file"); - PrintAndLogEx(NORMAL, " b load card with data from binary file"); - PrintAndLogEx(NORMAL, " load card with data from eml file"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf cload mydump")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf cload e")); - return PM3_SUCCESS; -} + static int usage_hf14_csave(void) { PrintAndLogEx(NORMAL, "It saves `magic Chinese` card dump into the file `filename.eml` or `cardID.eml`"); PrintAndLogEx(NORMAL, "or into emulator memory"); @@ -3854,8 +3839,8 @@ int CmdHF14AMfELoad(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf eload", - "Load emulator memory with data from `filename.eml` dump file", - "hf mf eload -f hf-mf-01020304.eml\n" + "Load emulator memory with data from (bin/eml/json) dump file", + "hf mf eload -f hf-mf-01020304.bin\n" "hf mf eload --4k -f hf-mf-01020304.eml\n" ); void *argtable[] = { @@ -3926,8 +3911,27 @@ int CmdHF14AMfELoad(const char *Cmd) { } size_t datalen = 0; - //int res = loadFile(filename, ".bin", data, maxdatalen, &datalen); - int res = loadFileEML(filename, data, &datalen); + int res = PM3_SUCCESS; + DumpFileType_t dftype = getfiletype(filename); + switch (dftype) { + case BIN: { + res = loadFile_safe(filename, ".bin", (void **)&data, &datalen); + break; + } + case EML: { + res = loadFileEML_safe(filename, (void **)&data, &datalen); + break; + } + case JSON: { + res = loadFileJSON(filename, data, MIFARE_4K_MAXBLOCK * MFBLOCK_SIZE, &datalen, NULL); + break; + } + case DICTIONARY: { + PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); + return PM3_EINVARG; + } + } + if (res != PM3_SUCCESS) { free(data); return PM3_EFILE; @@ -4002,7 +4006,7 @@ int CmdHF14AMfELoad(const char *Cmd) { return PM3_SUCCESS; } } - PrintAndLogEx(SUCCESS, "Done!"); + PrintAndLogEx(INFO, "Done!"); return PM3_SUCCESS; } @@ -4467,124 +4471,165 @@ static int CmdHF14AMfCSetBlk(const char *Cmd) { static int CmdHF14AMfCLoad(const char *Cmd) { - uint8_t fillFromEmulator = 0; - bool fillFromJson = false; - bool fillFromBin = false; - char fileName[50] = {0}; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf cload", + "Load magic gen1a card with data from (bin/eml/json) dump file\n" + "or from emulator memory.", + "hf mf cload --emu\n" + "hf mf cload -f hf-mf-01020304.eml\n" + ); + void *argtable[] = { + arg_param_begin, + arg_str1("f", "file", "", "filename of dump"), + arg_lit0(NULL, "emu", "from emulator memory"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int fnlen = 0; + char filename[FILE_PATH_SIZE]; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - char ctmp = tolower(param_getchar(Cmd, 0)); - if (param_getlength(Cmd, 0) == 1) { - if (ctmp == 'h' || ctmp == 0x00) return usage_hf14_cload(); - if (ctmp == 'e') fillFromEmulator = 1; - if (ctmp == 'j') fillFromJson = true; - if (ctmp == 'b') fillFromBin = true; - } + bool fill_from_emulator = arg_get_lit(ctx, 2); + CLIParserFree(ctx); - if (fillFromJson || fillFromBin) - param_getstr(Cmd, 1, fileName, sizeof(fileName)); - - - if (fillFromEmulator) { + if (fill_from_emulator) { PrintAndLogEx(INFO, "Start upload to emulator memory"); PrintAndLogEx(INFO, "." NOLF); - for (int blockNum = 0; blockNum < 16 * 4; blockNum += 1) { + for (int b = 0; b < MIFARE_1K_MAXBLOCK; b++) { int flags = 0; - uint8_t buf8[16] = {0x00}; - if (mfEmlGetMem(buf8, blockNum, 1)) { - PrintAndLogEx(WARNING, "Cant get block: %d", blockNum); - return 2; - } - if (blockNum == 0) flags = MAGIC_INIT + MAGIC_WUPC; // switch on field and send magic sequence - if (blockNum == 1) flags = 0; // just write - if (blockNum == 16 * 4 - 1) flags = MAGIC_HALT + MAGIC_OFF; // Done. Magic Halt and switch off field. + uint8_t buf8[MFBLOCK_SIZE] = {0x00}; - if (mfCSetBlock(blockNum, buf8, NULL, flags)) { - PrintAndLogEx(WARNING, "Cant set magic card block: %d", blockNum); + // read from emul memory + if (mfEmlGetMem(buf8, b, 1)) { + PrintAndLogEx(WARNING, "Can't read from emul block: %d", b); + return PM3_ESOFT; + } + + // switch on field and send magic sequence + if (b == 0) { + flags = MAGIC_INIT + MAGIC_WUPC; + } + + // just write + if (b == 1) { + flags = 0; + } + + // Done. Magic Halt and switch off field. + if (b == ((MFBLOCK_SIZE * 4) - 1)) { + flags = MAGIC_HALT + MAGIC_OFF; + } + + // write to card + if (mfCSetBlock(b, buf8, NULL, flags)) { + PrintAndLogEx(WARNING, "Can't set magic card block: %d", b); return PM3_ESOFT; } PrintAndLogEx(NORMAL, "." NOLF); fflush(stdout); } - PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } - size_t maxdatalen = 4096; - uint8_t *data = calloc(maxdatalen, sizeof(uint8_t)); - if (!data) { + uint8_t *data = calloc(MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK, sizeof(uint8_t)); + if (data == NULL) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return PM3_EMALLOC; } - size_t datalen = 0; + size_t bytes_read = 0; int res = 0; - if (fillFromBin) { - res = loadFile(fileName, ".bin", data, maxdatalen, &datalen); - } else { - if (fillFromJson) { - res = loadFileJSON(fileName, data, maxdatalen, &datalen, NULL); - } else { - res = loadFileEML(Cmd, data, &datalen); + DumpFileType_t dftype = getfiletype(filename); + switch (dftype) { + case BIN: { + res = loadFile_safe(filename, ".bin", (void **)&data, &bytes_read); + break; + } + case EML: { + res = loadFileEML_safe(filename, (void **)&data, &bytes_read); + break; + } + case JSON: { + res = loadFileJSON(filename, data, MIFARE_4K_MAXBLOCK * MFBLOCK_SIZE, &bytes_read, NULL); + break; + } + case DICTIONARY: { + PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); + return PM3_EINVARG; } } - if (res) { + if (res != PM3_SUCCESS) { free(data); return PM3_EFILE; } // 64 or 256blocks. - if (datalen != 1024 && datalen != 4096) { - PrintAndLogEx(ERR, "File content error. "); + if (bytes_read != (MIFARE_1K_MAXBLOCK * MFBLOCK_SIZE) && + bytes_read != (MIFARE_4K_MAXBLOCK * MFBLOCK_SIZE)) { + PrintAndLogEx(ERR, "File content error. Read %zu bytes", bytes_read); free(data); return PM3_EFILE; } - PrintAndLogEx(INFO, "Copying to magic card"); + PrintAndLogEx(INFO, "Copying to magic gen1a card"); PrintAndLogEx(INFO, "." NOLF); - int blockNum = 0; + int blockno = 0; int flags = 0; - while (datalen) { + while (bytes_read) { // switch on field and send magic sequence - if (blockNum == 0) flags = MAGIC_INIT + MAGIC_WUPC; + if (blockno == 0) { + flags = MAGIC_INIT + MAGIC_WUPC; + } // write - if (blockNum == 1) flags = 0; + if (blockno == 1) { + flags = 0; + } // Switch off field. - if (blockNum == 16 * 4 - 1) flags = MAGIC_HALT + MAGIC_OFF; + if (blockno == MFBLOCK_SIZE * 4 - 1) { + flags = MAGIC_HALT + MAGIC_OFF; + } - if (mfCSetBlock(blockNum, data + (16 * blockNum), NULL, flags)) { - PrintAndLogEx(WARNING, "Can't set magic card block: %d", blockNum); + if (mfCSetBlock(blockno, data + (MFBLOCK_SIZE * blockno), NULL, flags)) { + PrintAndLogEx(WARNING, "Can't set magic card block: %d", blockno); free(data); return PM3_ESOFT; } - datalen -= 16; + bytes_read -= MFBLOCK_SIZE; PrintAndLogEx(NORMAL, "." NOLF); fflush(stdout); - blockNum++; + blockno++; // magic card type - mifare 1K - if (blockNum >= MIFARE_1K_MAXBLOCK) break; + if (blockno >= MIFARE_1K_MAXBLOCK) break; } PrintAndLogEx(NORMAL, "\n"); - // 64 or 256blocks. - if (blockNum != 16 * 4 && blockNum != 32 * 4 + 8 * 16) { - PrintAndLogEx(ERR, "File content error. There must be 64 blocks"); - free(data); + free(data); + + // confirm number written blocks. Must be 64 or 256 blocks + if (blockno != MIFARE_1K_MAXBLOCK) { + if (blockno != MIFARE_4K_MAXBLOCK) { + PrintAndLogEx(ERR, "File content error. There must be %u blocks", MIFARE_4K_MAXBLOCK); + return PM3_EFILE; + } + PrintAndLogEx(ERR, "File content error. There must be %d blocks", MIFARE_1K_MAXBLOCK); return PM3_EFILE; } - PrintAndLogEx(SUCCESS, "Card loaded %d blocks from file", blockNum); - free(data); + PrintAndLogEx(SUCCESS, "Card loaded %d blocks from file", blockno); + PrintAndLogEx(INFO, "Done!"); return PM3_SUCCESS; } From c0d4a3020e082fa7b4a7f1023b60e88a5947066d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 11 Apr 2021 11:01:14 +0200 Subject: [PATCH 215/373] text --- doc/cliparser_todo.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 4f27fd219..89d90f617 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -23,13 +23,9 @@ hf mf rdsc hf mf restore hf mf setmod hf mf wrbl -hf mf ecfill -hf mf esave -hf mf cload hf mf csave hf mf csetblk hf mf csetuid -hf mf cview hf mf gen3uid hf mf gen3blk hf mf gen3freeze From 65427193d6b956289fcc980b9e0ec00b353381e0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 11 Apr 2021 11:30:09 +0200 Subject: [PATCH 216/373] hf mf csave - now use cliparser\nhf mf view - now accepts BIN/EML/JSON --- client/src/cmdhfmf.c | 265 ++++++++++++++++++++++++------------------- 1 file changed, 149 insertions(+), 116 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index b5153e8c4..f3dc00132 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -218,25 +218,6 @@ static int usage_hf14_csetblk(void) { return PM3_SUCCESS; } -static int usage_hf14_csave(void) { - PrintAndLogEx(NORMAL, "It saves `magic Chinese` card dump into the file `filename.eml` or `cardID.eml`"); - PrintAndLogEx(NORMAL, "or into emulator memory"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf csave [h] [e] [u] [card memory] o "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " e save data to emulator memory"); - PrintAndLogEx(NORMAL, " u save data to file, use carduid as filename"); - PrintAndLogEx(NORMAL, " card memory 0 = 320 bytes (MIFARE Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); - PrintAndLogEx(NORMAL, " o save data to file"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf csave u 1")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf csave e 1")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf csave 4 o filename")); - return PM3_SUCCESS; -} - static int usage_hf14_gen3uid(void) { PrintAndLogEx(NORMAL, "Set UID for magic GEN 3 card without manufacturer block changing"); PrintAndLogEx(NORMAL, ""); @@ -4593,7 +4574,7 @@ static int CmdHF14AMfCLoad(const char *Cmd) { flags = 0; } - // Switch off field. + // switch off field if (blockno == MFBLOCK_SIZE * 4 - 1) { flags = MAGIC_HALT + MAGIC_OFF; } @@ -4735,76 +4716,74 @@ static int CmdHF14AMfCGetSc(const char *Cmd) { } static int CmdHF14AMfCSave(const char *Cmd) { - + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf csave", + "Save magic gen1a card memory into three files (BIN/EML/JSON)" + "or into emulator memory", + "hf mf csave\n" + "hf mf csave --4k" + ); + void *argtable[] = { + arg_param_begin, + arg_str0("f", "file", "", "filename of dump"), + arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"), + arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"), + arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"), + arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"), + arg_lit0(NULL, "emu", "from emulator memory"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int fnlen = 0; char filename[FILE_PATH_SIZE]; - char *fnameptr = filename; - uint8_t *dump; - bool fillEmulator = false; - bool errors = false, hasname = false, useuid = false; - int i, len, flags; - uint16_t numblocks = 0, cmdp = 0; - uint16_t bytes = 0; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - char ctmp = tolower(param_getchar(Cmd, cmdp)); - switch (ctmp) { - case 'e': - useuid = true; - fillEmulator = true; - cmdp++; - break; - case 'h': - return usage_hf14_csave(); - case '0': - case '1': - case '2': - case '4': - numblocks = NumOfBlocks(ctmp); - bytes = numblocks * MFBLOCK_SIZE; - PrintAndLogEx(SUCCESS, "Saving magic MIFARE %cK", ctmp); - cmdp++; - break; - case 'u': - useuid = true; - hasname = true; - cmdp++; - break; - case 'o': - len = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); - if (len < 1) { - errors = true; - break; - } + bool m0 = arg_get_lit(ctx, 2); + bool m1 = arg_get_lit(ctx, 3); + bool m2 = arg_get_lit(ctx, 4); + bool m4 = arg_get_lit(ctx, 5); + bool fill_emulator = arg_get_lit(ctx, 6); + CLIParserFree(ctx); - useuid = false; - hasname = true; - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } + // validations + if ((m0 + m1 + m2 + m4) > 1) { + PrintAndLogEx(WARNING, "Only specify one MIFARE Type"); + return PM3_EINVARG; + } else if ((m0 + m1 + m2 + m4) == 0) { + m1 = true; } - if (!hasname && !fillEmulator) errors = true; - - if (errors || cmdp == 0) return usage_hf14_csave(); - - dump = calloc(bytes, sizeof(uint8_t)); - if (!dump) { - PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); - return PM3_EMALLOC; + char s[6]; + memset(s, 0, sizeof(s)); + uint16_t block_cnt = MIFARE_1K_MAXBLOCK; + if (m0) { + block_cnt = MIFARE_MINI_MAXBLOCK; + strncpy(s, "Mini", 5); + } else if (m1) { + block_cnt = MIFARE_1K_MAXBLOCK; + strncpy(s, "1K", 3); + } else if (m2) { + block_cnt = MIFARE_2K_MAXBLOCK; + strncpy(s, "2K", 3); + } else if (m4) { + block_cnt = MIFARE_4K_MAXBLOCK; + strncpy(s, "4K", 3); + } else { + PrintAndLogEx(WARNING, "Please specify a MIFARE Type"); + return PM3_EINVARG; } + PrintAndLogEx(SUCCESS, "Dumping magic Gen1a MIFARE Classic " _GREEN_("%s") " card memory", s); + PrintAndLogEx(INFO, "." NOLF); + // Select card to get UID/UIDLEN information clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(WARNING, "iso14443a card select failed"); - free(dump); - return PM3_ESOFT; + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) { + PrintAndLogEx(WARNING, "iso14443a card select timeout"); + return PM3_ETIMEOUT; } /* @@ -4814,53 +4793,74 @@ static int CmdHF14AMfCSave(const char *Cmd) { 3: proprietary Anticollision */ uint64_t select_status = resp.oldarg[0]; - if (select_status == 0) { PrintAndLogEx(WARNING, "iso14443a card select failed"); - free(dump); return select_status; } + // store card info iso14a_card_select_t card; memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); - flags = MAGIC_INIT + MAGIC_WUPC; - for (i = 0; i < numblocks; i++) { - if (i == 1) flags = 0; - if (i == numblocks - 1) flags = MAGIC_HALT + MAGIC_OFF; + // reserve memory + uint16_t bytes = block_cnt * MFBLOCK_SIZE; + uint8_t *dump = calloc(bytes, sizeof(uint8_t)); + if (dump == NULL) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); + return PM3_EMALLOC; + } + + // switch on field and send magic sequence + uint8_t flags = MAGIC_INIT + MAGIC_WUPC; + for (uint16_t i = 0; i < block_cnt; i++) { + + // read + if (i == 1) { + flags = 0; + } + // switch off field + if (i == block_cnt - 1) { + flags = MAGIC_HALT + MAGIC_OFF; + } if (mfCGetBlock(i, dump + (i * MFBLOCK_SIZE), flags)) { - PrintAndLogEx(WARNING, "Cant get block: %d", i); + PrintAndLogEx(WARNING, "Can't get magic card block: %d", i); + PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position"); free(dump); return PM3_ESOFT; } + PrintAndLogEx(NORMAL, "." NOLF); + fflush(stdout); } + PrintAndLogEx(NORMAL, ""); - if (useuid) { - fnameptr += snprintf(fnameptr, sizeof(filename), "hf-mf-"); - FillFileNameByUID(fnameptr, card.uid, "-dump", card.uidlen); - } - - if (fillEmulator) { + if (fill_emulator) { PrintAndLogEx(INFO, "uploading to emulator memory"); PrintAndLogEx(INFO, "." NOLF); // fast push mode conn.block_after_ACK = true; - for (i = 0; i < numblocks; i += 5) { - if (i == numblocks - 1) { + for (int i = 0; i < block_cnt; i += 5) { + if (i == block_cnt - 1) { // Disable fast mode on last packet conn.block_after_ACK = false; } if (mfEmlSetMem(dump + (i * MFBLOCK_SIZE), i, 5) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "Cant set emul block: %d", i); + PrintAndLogEx(WARNING, "Can't set emul block: %d", i); } PrintAndLogEx(NORMAL, "." NOLF); fflush(stdout); } - PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, "uploaded %d bytes to emulator memory", bytes); } + // user supplied filename? + if (fnlen < 1) { + char *fptr = filename; + fptr += snprintf(fptr, sizeof(filename), "hf-mf-"); + FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen); + } + saveFile(filename, ".bin", dump, bytes); saveFileEML(filename, dump, bytes, MFBLOCK_SIZE); saveFileJSON(filename, jsfCardMemory, dump, bytes, NULL); @@ -4901,7 +4901,6 @@ static int CmdHF14AMfCView(const char *Cmd) { char s[6]; memset(s, 0, sizeof(s)); - uint16_t block_cnt = MIFARE_1K_MAXBLOCK; if (m0) { block_cnt = MIFARE_MINI_MAXBLOCK; @@ -4922,21 +4921,13 @@ static int CmdHF14AMfCView(const char *Cmd) { PrintAndLogEx(SUCCESS, "View magic Gen1a MIFARE Classic " _GREEN_("%s"), s); PrintAndLogEx(INFO, "." NOLF); - int bytes = block_cnt * MFBLOCK_SIZE; - uint8_t *dump = calloc(bytes, sizeof(uint8_t)); - if (dump == NULL) { - PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); - return PM3_EMALLOC; - } - // Select card to get UID/UIDLEN information clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) { PrintAndLogEx(WARNING, "iso14443a card select timeout"); - free(dump); - return PM3_ESOFT; + return PM3_ETIMEOUT; } /* @@ -4949,20 +4940,34 @@ static int CmdHF14AMfCView(const char *Cmd) { if (select_status == 0) { PrintAndLogEx(WARNING, "iso14443a card select failed"); - free(dump); return select_status; } iso14a_card_select_t card; memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); + // reserve memory + uint16_t bytes = block_cnt * MFBLOCK_SIZE; + uint8_t *dump = calloc(bytes, sizeof(uint8_t)); + if (dump == NULL) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); + return PM3_EMALLOC; + } + + // switch on field and send magic sequence uint8_t flags = MAGIC_INIT + MAGIC_WUPC; for (uint16_t i = 0; i < block_cnt; i++) { - if (i == 1) flags = 0; - if (i == block_cnt - 1) flags = MAGIC_HALT + MAGIC_OFF; + // read + if (i == 1) { + flags = 0; + } + // switch off field + if (i == block_cnt - 1) { + flags = MAGIC_HALT + MAGIC_OFF; + } if (mfCGetBlock(i, dump + (i * MFBLOCK_SIZE), flags)) { - PrintAndLogEx(WARNING, "Can't get block: %d", i); + PrintAndLogEx(WARNING, "Can't get magic card block: %u", i); PrintAndLogEx(HINT, "Verify your card size, and try again or try another tag position"); free(dump); return PM3_ESOFT; @@ -5912,7 +5917,7 @@ static int CmdHF14AMfView(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf view", - "Print a MIFARE Classic dump file", + "Print a MIFARE Classic dump file (bin/eml/json)", "hf mf view -f hf-mf-01020304-dump.bin" ); void *argtable[] = { @@ -5921,21 +5926,49 @@ static int CmdHF14AMfView(const char *Cmd) { arg_lit0("v", "verbose", "verbose output"), arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, true); - + CLIExecWithReturn(ctx, Cmd, argtable, false); int fnlen = 0; char filename[FILE_PATH_SIZE]; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); bool verbose = arg_get_lit(ctx, 2); CLIParserFree(ctx); - uint8_t *dump = NULL; + // reserve memory + uint8_t *dump = calloc(MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK, sizeof(uint8_t)); + if (dump == NULL) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); + return PM3_EMALLOC; + } + size_t bytes_read = 0; - if (loadFile_safe(filename, "", (void **)&dump, &bytes_read) != PM3_SUCCESS) { + int res = 0; + DumpFileType_t dftype = getfiletype(filename); + switch (dftype) { + case BIN: { + res = loadFile_safe(filename, ".bin", (void **)&dump, &bytes_read); + break; + } + case EML: { + res = loadFileEML_safe(filename, (void **)&dump, &bytes_read); + break; + } + case JSON: { + res = loadFileJSON(filename, dump, MIFARE_4K_MAXBLOCK * MFBLOCK_SIZE, &bytes_read, NULL); + break; + } + case DICTIONARY: { + PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); + return PM3_EINVARG; + } + } + + if (res != PM3_SUCCESS) { PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); + free(dump); return PM3_EFILE; } - uint16_t block_cnt = MIFARE_1K_MAXBLOCK; + + uint16_t block_cnt = MIN(MIFARE_1K_MAXBLOCK, (bytes_read / MFBLOCK_SIZE)); if (bytes_read == 320) block_cnt = MIFARE_MINI_MAXBLOCK; else if (bytes_read == 2048) From 3c2b04aa565ae9f51f975fd2f96aac9aad1fe080 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 11 Apr 2021 11:34:45 +0200 Subject: [PATCH 217/373] text --- doc/cliparser_todo.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 89d90f617..aa7168c26 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -23,7 +23,6 @@ hf mf rdsc hf mf restore hf mf setmod hf mf wrbl -hf mf csave hf mf csetblk hf mf csetuid hf mf gen3uid From e448d582918df9efc8866fc974ac8dca63e63ec6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 11 Apr 2021 12:46:45 +0200 Subject: [PATCH 218/373] hf mf csetuid - now supports cliparser. Also experimental 7byte support. Not seen one in the wild. untested --- client/src/cmdhfmf.c | 168 +++++++++++++++++---------------- client/src/mifare/mifarehost.c | 68 +++++++++---- client/src/mifare/mifarehost.h | 2 +- doc/cliparser_todo.txt | 1 - doc/magic_cards_notes.md | 4 +- 5 files changed, 138 insertions(+), 105 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index f3dc00132..cf1c31478 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -188,21 +188,6 @@ static int usage_hf14_decryptbytes(void) { return PM3_SUCCESS; } -static int usage_hf14_csetuid(void) { - PrintAndLogEx(NORMAL, "Set UID, ATQA, and SAK for magic Chinese card. Only works with magic cards"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf csetuid [h] [ATQA 4 hex symbols] [SAK 2 hex symbols] [w]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " w wipe card before writing"); - PrintAndLogEx(NORMAL, " UID 8 hex symbols"); - PrintAndLogEx(NORMAL, " ATQA 4 hex symbols"); - PrintAndLogEx(NORMAL, " SAK 2 hex symbols"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf csetuid 01020304")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf csetuid 01020304 0004 08 w")); - return PM3_SUCCESS; -} static int usage_hf14_csetblk(void) { PrintAndLogEx(NORMAL, "Set block data for magic Chinese card. Only works with magic cards"); PrintAndLogEx(NORMAL, ""); @@ -4313,109 +4298,126 @@ static int CmdHF14AMfEKeyPrn(const char *Cmd) { // CHINESE MAGIC COMMANDS static int CmdHF14AMfCSetUID(const char *Cmd) { - uint8_t wipeCard = 0; - uint8_t uid[8] = {0x00}; - uint8_t oldUid[8] = {0x00}; + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf csetuid", + "Set UID, ATQA, and SAK for magic gen1a card", + "hf mf csetuid -u 01020304\n" + "hf mf csetuid -w -u 01020304 --atqa 0004 --sak 08" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0("w", "wipe", "wipes card with backdoor cmd`"), + arg_str0("u", "uid", "", "UID, 4/7 hex bytes"), + arg_str0("a", "atqa", "", "ATQA, 2 hex bytes"), + arg_str0("s", "sak", "", "SAK, 1 hex byte"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + uint8_t wipe_card = arg_get_lit(ctx, 1); + + int uidlen = 0; + uint8_t uid[7] = {0x00}; + CLIGetHexWithReturn(ctx, 2, uid, &uidlen); + + int alen = 0; uint8_t atqa[2] = {0x00}; + CLIGetHexWithReturn(ctx, 3, atqa, &alen); + + int slen = 0; uint8_t sak[1] = {0x00}; - uint8_t atqaPresent = 1; - int res, argi = 0; - char ctmp; + CLIGetHexWithReturn(ctx, 4, sak, &slen); + CLIParserFree(ctx); - if (strlen(Cmd) < 1 || param_getchar(Cmd, argi) == 'h') - return usage_hf14_csetuid(); - - if (param_getchar(Cmd, argi) && param_gethex(Cmd, argi, uid, 8)) - return usage_hf14_csetuid(); - - argi++; - - ctmp = tolower(param_getchar(Cmd, argi)); - if (ctmp == 'w') { - wipeCard = 1; - atqaPresent = 0; + // sanity checks + if (uidlen != 4 && uidlen != 7) { + PrintAndLogEx(FAILED, "UID must be 4 or 7 hex bytes. Got %d", uidlen); + return PM3_EINVARG; + } + if (alen && alen != 2) { + PrintAndLogEx(FAILED, "ATQA must be 2 hex bytes. Got %d", alen); + return PM3_EINVARG; + } + if (slen && slen != 1) { + PrintAndLogEx(FAILED, "SAK must be 1 hex byte. Got %d", slen); + return PM3_EINVARG; } - if (atqaPresent) { - if (param_getchar(Cmd, argi)) { - if (param_gethex(Cmd, argi, atqa, 4)) { - PrintAndLogEx(WARNING, "ATQA must include 4 HEX symbols"); - return PM3_ESOFT; - } - argi++; - if (!param_getchar(Cmd, argi) || param_gethex(Cmd, argi, sak, 2)) { - PrintAndLogEx(WARNING, "SAK must include 2 HEX symbols"); - return PM3_ESOFT; - } - argi++; - } else - atqaPresent = 0; - } + uint8_t old_uid[7] = {0}; + uint8_t verify_uid[7] = {0}; - if (!wipeCard) { - ctmp = tolower(param_getchar(Cmd, argi)); - if (ctmp == 'w') { - wipeCard = 1; - } - } + int res = mfCSetUID( + uid, + uidlen, + (alen) ? atqa : NULL, + (slen) ? sak : NULL, + old_uid, + verify_uid, + wipe_card + ); - PrintAndLogEx(NORMAL, "--wipe card:%s uid:%s", (wipeCard) ? "YES" : "NO", sprint_hex(uid, 4)); - - res = mfCSetUID(uid, (atqaPresent) ? atqa : NULL, (atqaPresent) ? sak : NULL, oldUid, wipeCard); if (res) { - PrintAndLogEx(ERR, "Can't set UID. error=%d", res); + PrintAndLogEx(ERR, "Can't set UID. error %d", res); return PM3_ESOFT; } - PrintAndLogEx(SUCCESS, "Old UID : %s", sprint_hex(oldUid, 4)); - PrintAndLogEx(SUCCESS, "New UID : %s", sprint_hex(uid, 4)); + res = memcmp(uid, verify_uid, uidlen); + + PrintAndLogEx(SUCCESS, "Old UID... %s", sprint_hex(old_uid, uidlen)); + PrintAndLogEx(SUCCESS, "New UID... %s ( %s )", + sprint_hex(verify_uid, uidlen), + (res == 0) ? _GREEN_("verified") : _RED_("fail") + ); return PM3_SUCCESS; } static int CmdHF14AMfCWipe(const char *cmd) { - uint8_t uid[8] = {0x00}; - int uidLen = 0; - uint8_t atqa[2] = {0x00}; - int atqaLen = 0; - uint8_t sak[1] = {0x00}; - int sakLen = 0; - CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf cwipe", - "Wipe gen1 magic chinese card. Set UID/ATQA/SAK/Data/Keys/Access to default values.", - "hf mf cwipe --> wipe card\n" + "Wipe gen1 magic chinese card.\n" + "Set UID / ATQA / SAK / Data / Keys / Access to default values", + "hf mf cwipe\n" "hf mf cwipe -u 09080706 -a 0004 -s 18 --> set UID, ATQA and SAK and wipe card"); void *argtable[] = { arg_param_begin, - arg_str0("u", "uid", "", "UID for card"), - arg_str0("a", "atqa", "", "ATQA for card"), - arg_str0("s", "sak", "", "SAK for card"), + arg_str0("u", "uid", "", "UID, 4 hex bytes"), + arg_str0("a", "atqa", "", "ATQA, 2 hex bytes"), + arg_str0("s", "sak", "", "SAK, 1 hex byte"), arg_param_end }; CLIExecWithReturn(ctx, cmd, argtable, true); - CLIGetHexWithReturn(ctx, 1, uid, &uidLen); - CLIGetHexWithReturn(ctx, 2, atqa, &atqaLen); - CLIGetHexWithReturn(ctx, 3, sak, &sakLen); + int uidlen = 0; + uint8_t uid[8] = {0x00}; + CLIGetHexWithReturn(ctx, 1, uid, &uidlen); + + int alen = 0; + uint8_t atqa[2] = {0x00}; + CLIGetHexWithReturn(ctx, 2, atqa, &alen); + + int slen = 0; + uint8_t sak[1] = {0x00}; + CLIGetHexWithReturn(ctx, 3, sak, &slen); CLIParserFree(ctx); - if (uidLen && uidLen != 4) { - PrintAndLogEx(ERR, "UID length must be 4 bytes instead of: %d", uidLen); + if (uidlen && uidlen != 4) { + PrintAndLogEx(ERR, "UID length must be 4 bytes, got %d", uidlen); return PM3_EINVARG; } - if (atqaLen && atqaLen != 2) { - PrintAndLogEx(ERR, "ATQA length must be 2 bytes instead of: %d", atqaLen); + if (alen && alen != 2) { + PrintAndLogEx(ERR, "ATQA length must be 2 bytes, got %d", alen); return PM3_EINVARG; } - if (sakLen && sakLen != 1) { - PrintAndLogEx(ERR, "SAK length must be 1 byte instead of: %d", sakLen); + if (slen && slen != 1) { + PrintAndLogEx(ERR, "SAK length must be 1 byte, got %d", slen); return PM3_EINVARG; } - int res = mfCWipe((uidLen) ? uid : NULL, (atqaLen) ? atqa : NULL, (sakLen) ? sak : NULL); + int res = mfCWipe((uidlen) ? uid : NULL, (alen) ? atqa : NULL, (slen) ? sak : NULL); if (res) { - PrintAndLogEx(ERR, "Can't wipe card. error=%d", res); + PrintAndLogEx(ERR, "Can't wipe card. error %d", res); return PM3_ESOFT; } diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index 48ac96acd..c87e96442 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -853,37 +853,69 @@ int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidt } // "MAGIC" CARD -int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_t wipecard) { +int mfCSetUID(uint8_t *uid, uint8_t uidlen, uint8_t *atqa, uint8_t *sak, uint8_t *old_uid, uint8_t *verifed_uid, uint8_t wipecard) { uint8_t params = MAGIC_SINGLE; uint8_t block0[16]; memset(block0, 0x00, sizeof(block0)); - int old = mfCGetBlock(0, block0, params); - if (old == 0) - PrintAndLogEx(SUCCESS, "old block 0: %s", sprint_hex(block0, sizeof(block0))); - else - PrintAndLogEx(FAILED, "couldn't get old data. Will write over the last bytes of Block 0."); + int res = mfCGetBlock(0, block0, params); + if (res == 0) { + PrintAndLogEx(SUCCESS, "old block 0... %s", sprint_hex_inrow(block0, sizeof(block0))); + if (old_uid) { + memcpy(old_uid, block0, uidlen); + } + } else { + PrintAndLogEx(INFO, "couldn't get old data. Will write over the last bytes of block 0"); + } // fill in the new values // UID - memcpy(block0, uid, 4); + memcpy(block0, uid, uidlen); // Mifare UID BCC - block0[4] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3]; - // mifare classic SAK(byte 5) and ATQA(byte 6 and 7, reversed) - if (sak != NULL) - block0[5] = sak[0]; + if (uidlen == 4) { + block0[4] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3]; - if (atqa != NULL) { - block0[6] = atqa[1]; - block0[7] = atqa[0]; + // mifare classic SAK(byte 5) and ATQA(byte 6 and 7, reversed) + if (sak) + block0[5] = sak[0]; + + if (atqa) { + block0[6] = atqa[1]; + block0[7] = atqa[0]; + } + + } else if (uidlen == 7) { + block0[7] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3] ^ block0[4] ^ block0[5] ^ block0[6]; + + // mifare classic SAK(byte 8) and ATQA(byte 9 and 10, reversed) + if (sak) + block0[8] = sak[0]; + + if (atqa) { + block0[9] = atqa[1]; + block0[10] = atqa[0]; + } } - PrintAndLogEx(SUCCESS, "new block 0: %s", sprint_hex(block0, 16)); - if (wipecard) params |= MAGIC_WIPE; - if (oldUID != NULL) params |= MAGIC_UID; + PrintAndLogEx(SUCCESS, "new block 0... %s", sprint_hex_inrow(block0, 16)); - return mfCSetBlock(0, block0, oldUID, params); + if (wipecard) { + params |= MAGIC_WIPE; + } + + res = mfCSetBlock(0, block0, NULL, params); + if (res == PM3_SUCCESS) { + params = MAGIC_SINGLE; + memset(block0, 0, sizeof(block0)); + res = mfCGetBlock(0, block0, params); + if (res == 0) { + if (verifed_uid) { + memcpy(verifed_uid, block0, uidlen); + } + } + } + return res; } int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak) { diff --git a/client/src/mifare/mifarehost.h b/client/src/mifare/mifarehost.h index c4c65737a..49adc8cbe 100644 --- a/client/src/mifare/mifarehost.h +++ b/client/src/mifare/mifarehost.h @@ -76,7 +76,7 @@ int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount); int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount); int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth); -int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_t wipecard); +int mfCSetUID(uint8_t *uid, uint8_t uidlen, uint8_t *atqa, uint8_t *sak, uint8_t *old_uid, uint8_t *verifed_uid, uint8_t wipecard); int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak); int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params); int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params); diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index aa7168c26..c8e72098e 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -24,7 +24,6 @@ hf mf restore hf mf setmod hf mf wrbl hf mf csetblk -hf mf csetuid hf mf gen3uid hf mf gen3blk hf mf gen3freeze diff --git a/doc/magic_cards_notes.md b/doc/magic_cards_notes.md index d24a0b7c5..0a73a83b8 100644 --- a/doc/magic_cards_notes.md +++ b/doc/magic_cards_notes.md @@ -189,9 +189,9 @@ hf mf cwipe -u 11223344 -a 0044 -s 18 or just fixing block0: ``` # MFC Gen1A 1k: -hf mf csetuid 11223344 0004 08 +hf mf csetuid -u 11223344 -a 0004 -s 08 # MFC Gen1A 4k: -hf mf csetuid 11223344 0044 18 +hf mf csetuid -u 11223344 -a 0044 -s 18 ``` ``` From cc5debd628c99fd69ed8fdedea2be356d675c434 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 11 Apr 2021 13:14:13 +0200 Subject: [PATCH 219/373] hf mf csetblk - now uses cliparser. plus print refactoring --- client/src/cmdhfmf.c | 99 ++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index cf1c31478..3ccec1a10 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -188,21 +188,6 @@ static int usage_hf14_decryptbytes(void) { return PM3_SUCCESS; } -static int usage_hf14_csetblk(void) { - PrintAndLogEx(NORMAL, "Set block data for magic Chinese card. Only works with magic cards"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf csetblk [h] [w]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " w wipe card before writing"); - PrintAndLogEx(NORMAL, " block number"); - PrintAndLogEx(NORMAL, " block data to write (32 hex symbols)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf csetblk 1 01020304050607080910111213141516")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf csetblk 1 01020304050607080910111213141516 w")); - return PM3_SUCCESS; -} - static int usage_hf14_gen3uid(void) { PrintAndLogEx(NORMAL, "Set UID for magic GEN 3 card without manufacturer block changing"); PrintAndLogEx(NORMAL, ""); @@ -453,6 +438,11 @@ static void mf_print_blocks(uint16_t n, uint8_t *d) { PrintAndLogEx(NORMAL, ""); } +static void mf_print_sector_hdr(uint8_t sector) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, " # | sector " _GREEN_("%02d") " / " _GREEN_("0x%02X") " | ascii", sector, sector); + PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); +} static int CmdHF14AMfDarkside(const char *Cmd) { CLIParserContext *ctx; @@ -608,9 +598,7 @@ static int CmdHF14AMfRdBl(const char *Cmd) { if (res == PM3_SUCCESS) { uint8_t sector = GetSectorFromBlockNo(blockno); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); - PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); + mf_print_sector_hdr(sector); mf_print_block(blockno, data); if (verbose) { decode_print_st(blockno, data); @@ -672,9 +660,7 @@ static int CmdHF14AMfRdSc(const char *Cmd) { uint8_t blocks = NumBlocksPerSector(sector); uint8_t start = FirstBlockOfSector(sector); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); - PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); + mf_print_sector_hdr(sector); for (int i = 0; i < blocks; i++) { mf_print_block(start + i, data + (i * MFBLOCK_SIZE)); } @@ -3686,9 +3672,7 @@ static int CmdHF14AMfEGetBlk(const char *Cmd) { if (mfEmlGetMem(data, blockno, 1) == PM3_SUCCESS) { uint8_t sector = GetSectorFromBlockNo(blockno); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); - PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); + mf_print_sector_hdr(sector); mf_print_block(blockno, data); } if (verbose) { @@ -3722,10 +3706,7 @@ static int CmdHF14AMfEGetSc(const char *Cmd) { } uint8_t sector = (uint8_t)s; - - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); - PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); + mf_print_sector_hdr(sector); uint8_t blocks = NumBlocksPerSector(sector); uint8_t start = FirstBlockOfSector(sector); @@ -4426,25 +4407,48 @@ static int CmdHF14AMfCWipe(const char *cmd) { } static int CmdHF14AMfCSetBlk(const char *Cmd) { - uint8_t block[16] = {0x00}; - uint8_t blockNo = 0; + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf csetblk", + "Set block data on a magic gen1a card", + "hf mf csetblk --blk 1 -d 000102030405060708090a0b0c0d0e0f" + ); + void *argtable[] = { + arg_param_begin, + arg_int1("b", "blk", "", "block number"), + arg_str0("d", "data", "", "bytes to write, 16 hex bytes"), + arg_lit0("w", "wipe", "wipes card with backdoor cmd before writing`"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int b = arg_get_int_def(ctx, 1, -1); + + uint8_t data[MFBLOCK_SIZE] = {0x00}; + int datalen = 0; + CLIGetHexWithReturn(ctx, 2, data, &datalen); + + uint8_t wipe_card = arg_get_lit(ctx, 3); + CLIParserFree(ctx); + + if (b < 0 || b >= MIFARE_1K_MAXBLOCK ) { + PrintAndLogEx(FAILED, "target block number out-of-range, got %i", b); + return PM3_EINVARG; + } + + if (datalen != MFBLOCK_SIZE) { + PrintAndLogEx(FAILED, "expected 16 bytes data, got %i", datalen); + return PM3_EINVARG; + } + uint8_t params = MAGIC_SINGLE; - int res; - char ctmp = tolower(param_getchar(Cmd, 0)); - - if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_csetblk(); - - blockNo = param_get8(Cmd, 0); - - if (param_gethex(Cmd, 1, block, 32)) return usage_hf14_csetblk(); - - ctmp = tolower(param_getchar(Cmd, 2)); - if (ctmp == 'w') + if (wipe_card) { params |= MAGIC_WIPE; + } - PrintAndLogEx(NORMAL, "--block number:%2d data:%s", blockNo, sprint_hex(block, 16)); + PrintAndLogEx(INFO, "Writing block number:%2d data:%s", b, sprint_hex_inrow(data, sizeof(data))); - res = mfCSetBlock(blockNo, block, NULL, params); + int res = mfCSetBlock(b, data, NULL, params); if (res) { PrintAndLogEx(ERR, "Can't write block. error=%d", res); return PM3_ESOFT; @@ -4648,9 +4652,7 @@ static int CmdHF14AMfCGetBlk(const char *Cmd) { } uint8_t sector = GetSectorFromBlockNo(blockno); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); - PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); + mf_print_sector_hdr(sector); mf_print_block(blockno, data); if (verbose) { @@ -4684,10 +4686,7 @@ static int CmdHF14AMfCGetSc(const char *Cmd) { } uint8_t sector = (uint8_t)s; - - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, " # | data - sector %02d / 0x%02X | ascii", sector, sector); - PrintAndLogEx(INFO, "----+-------------------------------------------------+-----------------"); + mf_print_sector_hdr(sector); uint8_t blocks = 4; uint8_t start = sector * 4; From 33c758421c25792bd912218c6aa186a2baa71c1b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 11 Apr 2021 13:14:49 +0200 Subject: [PATCH 220/373] text --- doc/cliparser_todo.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index c8e72098e..f93a30fab 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -23,7 +23,6 @@ hf mf rdsc hf mf restore hf mf setmod hf mf wrbl -hf mf csetblk hf mf gen3uid hf mf gen3blk hf mf gen3freeze From 0ac28addcb5b4b30f41ecc3c2f42156c9ce6d5c2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 11 Apr 2021 13:58:04 +0200 Subject: [PATCH 221/373] remove one test command --- armsrc/mifarecmd.c | 18 ++--- client/src/cmdhfmf.c | 171 +++++++++++++++++++++-------------------- doc/cliparser_todo.txt | 3 - doc/commands.md | 1 - 4 files changed, 95 insertions(+), 98 deletions(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index b35a4d6e3..4330f2c4f 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -2485,8 +2485,7 @@ void MifareGen3UID(uint8_t uidlen, uint8_t *uid) { clear_trace(); set_tracing(true); - if (!iso14443a_select_card(old_uid, card_info, NULL, true, 0, true)) { - if (DBGLEVEL >= DBG_ERROR) Dbprintf("Card not selected"); + if (iso14443a_select_card(old_uid, card_info, NULL, true, 0, true) == false) { retval = PM3_ESOFT; goto OUT; } @@ -2521,8 +2520,7 @@ void MifareGen3Blk(uint8_t block_len, uint8_t *block) { clear_trace(); set_tracing(true); - if (!iso14443a_select_card(uid, card_info, NULL, true, 0, true)) { - if (DBGLEVEL >= DBG_ERROR) Dbprintf("Card not selected"); + if (iso14443a_select_card(uid, card_info, NULL, true, 0, true) == false) { retval = PM3_ESOFT; goto OUT; } @@ -2558,7 +2556,6 @@ void MifareGen3Blk(uint8_t block_len, uint8_t *block) { if (doReselect) { if (!iso14443a_select_card(uid, NULL, NULL, true, 0, true)) { - if (DBGLEVEL >= DBG_ERROR) Dbprintf("Card not selected"); retval = PM3_ESOFT; goto OUT; } @@ -2575,16 +2572,15 @@ OUT: } void MifareGen3Freez(void) { - int retval = PM3_SUCCESS; - uint8_t freeze_cmd[7] = { 0x90, 0xfd, 0x11, 0x11, 0x00, 0xe7, 0x91 }; - uint8_t *uid = BigBuf_malloc(10); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); set_tracing(true); - if (!iso14443a_select_card(uid, NULL, NULL, true, 0, true)) { - if (DBGLEVEL >= DBG_ERROR) Dbprintf("Card not selected"); + int retval = PM3_SUCCESS; + uint8_t freeze_cmd[7] = { 0x90, 0xfd, 0x11, 0x11, 0x00, 0xe7, 0x91 }; + uint8_t *uid = BigBuf_malloc(10); + + if (iso14443a_select_card(uid, NULL, NULL, true, 0, true) == false) { retval = PM3_ESOFT; goto OUT; } diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 3ccec1a10..bd17fec59 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -188,48 +188,6 @@ static int usage_hf14_decryptbytes(void) { return PM3_SUCCESS; } -static int usage_hf14_gen3uid(void) { - PrintAndLogEx(NORMAL, "Set UID for magic GEN 3 card without manufacturer block changing"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf gen3uid [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " UID 8/14 hex symbols"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf gen3uid 01020304")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf gen3uid 01020304050607")); - return PM3_SUCCESS; -} -static int usage_hf14_gen3block(void) { - PrintAndLogEx(NORMAL, "Overwrite full manufacturer block for magic GEN 3 card"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf gen3blk [h] [block data (up to 32 hex symbols)]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " [block] manufacturer block data up to 32 hex symbols to write"); - PrintAndLogEx(NORMAL, " - If block data not specified, it prints current"); - PrintAndLogEx(NORMAL, " data without changes"); - PrintAndLogEx(NORMAL, " - You can specify part of manufacturer block as"); - PrintAndLogEx(NORMAL, " 4/7-bytes for UID change only for example"); - PrintAndLogEx(NORMAL, " NOTE: BCC, SAK, ATQA will be calculated automatically"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf gen3blk 01020304FFFFFFFF0102030405060708")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf gen3blk 01020304")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf gen3blk 01020304050607")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf gen3blk")); - return PM3_SUCCESS; -} -static int usage_hf14_gen3freeze(void) { - PrintAndLogEx(NORMAL, "Perma lock further UID changes. No more UID changes available after operation completed"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf gen3freeze [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " confirm UID locks operation"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf gen3freeze y")); - return PM3_SUCCESS; -} int mfc_ev1_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, int signature_len) { @@ -5079,6 +5037,7 @@ static int CmdHf14AMfNack(const char *Cmd) { return PM3_SUCCESS; } +/* static int CmdHF14AMfice(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf ice", @@ -5180,6 +5139,7 @@ out: SendCommandMIX(CMD_HF_MIFARE_ACQ_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, 4, NULL, 0); return PM3_SUCCESS; } +*/ static int CmdHF14AMfAuth4(const char *Cmd) { uint8_t keyn[20] = {0}; @@ -5592,65 +5552,110 @@ static int CmdHF14AMfList(const char *Cmd) { } static int CmdHf14AGen3UID(const char *Cmd) { - uint8_t uid[7] = {0x00}; - uint8_t oldUid[10] = {0x00}; - uint8_t uidlen; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf gen3uid", + "Set UID for magic Gen3 card _without_ changes to manufacturer block 0", + "hf mf gen3uid --uid 01020304 --> set 4 byte uid\n" + "hf mf gen3uid --uid 01020304050607 --> set 7 byte uid" + ); + void *argtable[] = { + arg_param_begin, + arg_str0("u", "uid", "", "UID 4/7 hex bytes"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + uint8_t uid[7] = {0}; + int uidlen = 0; + CLIGetHexWithReturn(ctx, 1, uid, &uidlen); + CLIParserFree(ctx); - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_hf14_gen3uid(); + // sanity checks + if (uidlen != 4 && uidlen != 7) { + PrintAndLogEx(FAILED, "UID must be 4 or 7 hex bytes. Got %d", uidlen); + return PM3_EINVARG; + } - if (param_gethex(Cmd, 0, uid, 8)) - if (param_gethex(Cmd, 0, uid, 14)) - return usage_hf14_gen3uid(); - else - uidlen = 7; - else - uidlen = 4; + uint8_t old_uid[10] = {0}; - int res = mfGen3UID(uid, uidlen, oldUid); - if (res) { - PrintAndLogEx(ERR, "Can't set UID. Error=%d", res); + int res = mfGen3UID(uid, uidlen, old_uid); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Can't set UID"); + PrintAndLogEx(HINT, "Are you sure your card is a Gen3 ?"); return PM3_ESOFT; } - PrintAndLogEx(SUCCESS, "Old UID : %s", sprint_hex(oldUid, uidlen)); - PrintAndLogEx(SUCCESS, "New UID : %s", sprint_hex(uid, uidlen)); + PrintAndLogEx(SUCCESS, "Old UID... %s", sprint_hex(old_uid, uidlen)); + PrintAndLogEx(SUCCESS, "New UID... %s", sprint_hex(uid, uidlen)); return PM3_SUCCESS; } static int CmdHf14AGen3Block(const char *Cmd) { - uint8_t block[16] = {0x00}; - int blocklen = 0; - uint8_t newBlock[16] = {0x00}; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf gen3blk", + "Overwrite full manufacturer block for magic Gen3 card\n" + " - You can specify part of manufacturer block as\n" + " 4/7-bytes for UID change only\n" + "\n" + "NOTE: BCC, SAK, ATQA will be calculated automatically" + , + "hf mf gen3blk --> print current data\n" + "hf mf gen3blk -d 01020304 --> set 4 byte uid\n" + "hf mf gen3blk -d 01020304050607 --> set 7 byte uid \n" + "hf mf gen3blk -d 01020304FFFFFFFF0102030405060708" - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_hf14_gen3block(); + ); + void *argtable[] = { + arg_param_begin, + arg_str0("d", "data", "", "manufacturer block data up to 16 hex bytes"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + uint8_t data[MFBLOCK_SIZE] = {0x00}; + int datalen = 0; + CLIGetHexWithReturn(ctx, 1, data, &datalen); + CLIParserFree(ctx); - if (ctmp != '\0' && param_gethex_to_eol(Cmd, 0, block, sizeof(block), &blocklen)) - return usage_hf14_gen3block(); - - int res = mfGen3Block(block, blocklen, newBlock); + uint8_t new_block[MFBLOCK_SIZE] = {0x00}; + int res = mfGen3Block(data, datalen, new_block); if (res) { - PrintAndLogEx(ERR, "Can't change manufacturer block data. Error=%d", res); + PrintAndLogEx(ERR, "Can't change manufacturer block data. error %d", res); return PM3_ESOFT; } - PrintAndLogEx(SUCCESS, "Current Block : %s", sprint_hex(newBlock, 16)); + PrintAndLogEx(SUCCESS, "Current block... %s", sprint_hex_inrow(new_block, sizeof(new_block))); return PM3_SUCCESS; } static int CmdHf14AGen3Freeze(const char *Cmd) { - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_hf14_gen3freeze(); - if (ctmp != 'y') return usage_hf14_gen3freeze(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf gen3freeze", + "Perma lock further UID changes. No more UID changes available after operation completed\n" + "\nNote: operation is " _RED_("! irreversible !"), + + "hf mf gen3freeze -y" + ); + void *argtable[] = { + arg_param_begin, + arg_lit1("y", "yes", "confirm UID lock operation"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + bool confirm = arg_get_lit(ctx, 1); + CLIParserFree(ctx); + if (confirm == false) { + PrintAndLogEx(INFO, "please confirm that you want to perma lock the card"); + return PM3_SUCCESS; + } int res = mfGen3Freeze(); - if (res) { - PrintAndLogEx(ERR, "Can't lock UID changes. Error=%d", res); - return PM3_ESOFT; + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Can't lock UID changes. error %d", res); + } else { + PrintAndLogEx(SUCCESS, "MFC Gen3 UID card is now perma-locked"); } - PrintAndLogEx(SUCCESS, "MFC Gen3 UID permalocked"); - return PM3_SUCCESS; + return res; } static void des_decrypt(void *out, const void *in, const void *key) { @@ -6038,12 +6043,12 @@ static command_t CommandTable[] = { {"cview", CmdHF14AMfCView, IfPm3Iso14443a, "View card"}, {"cwipe", CmdHF14AMfCWipe, IfPm3Iso14443a, "Wipe card to default UID/Sectors/Keys"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen3") " -----------------------"}, - {"gen3uid", CmdHf14AGen3UID, IfPm3Iso14443a, "Set UID without manufacturer block"}, - {"gen3blk", CmdHf14AGen3Block, IfPm3Iso14443a, "Overwrite full manufacturer block"}, - {"gen3freeze", CmdHf14AGen3Freeze, IfPm3Iso14443a, "Perma lock further UID changes"}, + {"gen3uid", CmdHf14AGen3UID, IfPm3Iso14443a, "Set UID without changing manufacturer block"}, + {"gen3blk", CmdHf14AGen3Block, IfPm3Iso14443a, "Overwrite manufacturer block"}, + {"gen3freeze", CmdHf14AGen3Freeze, IfPm3Iso14443a, "Perma lock UID changes. irreversible"}, - {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("i") " -----------------------"}, - {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"}, +// {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("i") " -----------------------"}, +// {"ice", CmdHF14AMfice, IfPm3Iso14443a, "collect MIFARE Classic nonces to file"}, {NULL, NULL, NULL, NULL} }; diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index f93a30fab..db27145ff 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -23,9 +23,6 @@ hf mf rdsc hf mf restore hf mf setmod hf mf wrbl -hf mf gen3uid -hf mf gen3blk -hf mf gen3freeze lf hitag reader lf hitag writer lf hitag dump diff --git a/doc/commands.md b/doc/commands.md index 04546c2e9..8b257b3d2 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -427,7 +427,6 @@ Check column "offline" for their availability. |`hf mf gen3uid `|N |`Set UID without manufacturer block` |`hf mf gen3blk `|N |`Overwrite full manufacturer block` |`hf mf gen3freeze `|N |`Perma lock further UID changes` -|`hf mf ice `|N |`collect MIFARE Classic nonces to file` ### hf mfp From 55e1b95f21a74d9a887a7d439005e5026908ba8d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 11 Apr 2021 17:54:17 +0200 Subject: [PATCH 222/373] hf mf setmod - now uses cliparser --- client/src/cmdhfmf.c | 73 +++++++++++++++++++++++++----------------- doc/cliparser_todo.txt | 2 -- doc/commands.md | 6 ++-- 3 files changed, 46 insertions(+), 35 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index bd17fec59..eee416b45 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -524,7 +524,7 @@ static int CmdHF14AMfRdBl(const char *Cmd) { arg_int1(NULL, "blk", "", "block number"), arg_lit0("a", NULL, "input key type is key A (def)"), arg_lit0("b", NULL, "input key type is key B"), - arg_str0("k", "key", "", "key specified as 6 hex bytes"), + arg_str0("k", "key", "", "key, 6 hex bytes"), arg_lit0("v", "verbose", "verbose output"), arg_param_end }; @@ -569,9 +569,9 @@ static int CmdHF14AMfRdBl(const char *Cmd) { static int CmdHF14AMfRdSc(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mf rdbl", + CLIParserInit(&ctx, "hf mf rdsc", "Read MIFARE Classic sector", - "hf mf rdbl -s 0 -k FFFFFFFFFFFF\n" + "hf mf rdsc -s 0 -k FFFFFFFFFFFF\n" ); void *argtable[] = { arg_param_begin, @@ -4975,43 +4975,56 @@ static int CmdHf14AMfDecryptBytes(const char *Cmd) { } static int CmdHf14AMfSetMod(const char *Cmd) { - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - uint8_t mod = 2; - char ctmp = param_getchar(Cmd, 0); - if (ctmp == '0') { - mod = 0; - } else if (ctmp == '1') { - mod = 1; - } - int gethexfail = param_gethex(Cmd, 1, key, 12); - if (mod == 2 || gethexfail) { - PrintAndLogEx(NORMAL, "Sets the load modulation strength of a MIFARE Classic EV1 card."); - PrintAndLogEx(NORMAL, "Usage: hf mf setmod <0|1> "); - PrintAndLogEx(NORMAL, " 0 = normal modulation"); - PrintAndLogEx(NORMAL, " 1 = strong modulation (default)"); - return PM3_ESOFT; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf setmod", + "Sets the load modulation strength of a MIFARE Classic EV1 card", + "hf mf setmod -k ffffffffffff -0" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0("0", NULL, "normal modulation"), + arg_lit0("1", NULL, "strong modulation (def)"), + arg_str0("k", "key", "", "key A, Sector 0, 6 hex bytes"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + bool m0 = arg_get_lit(ctx, 1); + bool m1 = arg_get_lit(ctx, 2); + + int keylen = 0; + uint8_t key[6] = {0}; + CLIGetHexWithReturn(ctx, 3, key, &keylen); + CLIParserFree(ctx); + + if (m0 + m1 > 1) { + PrintAndLogEx(WARNING, "please select one modulation"); + return PM3_EINVARG; } - uint8_t data[7]; - data[0] = mod; + uint8_t data[7] = {0}; memcpy(data + 1, key, 6); + if (m1) { + data[0] = 1; + } else { + data[0] = 0; + } + clearCommandBuffer(); SendCommandNG(CMD_HF_MIFARE_SETMOD, data, sizeof(data)); - PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_HF_MIFARE_SETMOD, &resp, 1500)) { - - if (resp.status == PM3_SUCCESS) - PrintAndLogEx(SUCCESS, "Success"); - else - PrintAndLogEx(FAILED, "Failed"); - - } else { + if (WaitForResponseTimeout(CMD_HF_MIFARE_SETMOD, &resp, 1500) == false) { PrintAndLogEx(WARNING, "Command execute timeout"); + return PM3_ETIMEOUT; } - return PM3_SUCCESS; + + if (resp.status == PM3_SUCCESS) + PrintAndLogEx(SUCCESS, "Change ( " _GREEN_("ok") " )"); + else + PrintAndLogEx(FAILED, "Change (" _GREEN_("fail") " )"); + + return resp.status; } // MIFARE NACK bug detection diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index db27145ff..83fbf87c3 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -19,9 +19,7 @@ hf felica resetmode hf mf hardnested hf mf autopwn hf mf decrypt -hf mf rdsc hf mf restore -hf mf setmod hf mf wrbl lf hitag reader lf hitag writer diff --git a/doc/commands.md b/doc/commands.md index 8b257b3d2..d67b43086 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -424,9 +424,9 @@ Check column "offline" for their availability. |`hf mf csetuid `|N |`Set UID on card` |`hf mf cview `|N |`View card` |`hf mf cwipe `|N |`Wipe card to default UID/Sectors/Keys` -|`hf mf gen3uid `|N |`Set UID without manufacturer block` -|`hf mf gen3blk `|N |`Overwrite full manufacturer block` -|`hf mf gen3freeze `|N |`Perma lock further UID changes` +|`hf mf gen3uid `|N |`Set UID without changing manufacturer block` +|`hf mf gen3blk `|N |`Overwrite manufacturer block` +|`hf mf gen3freeze `|N |`Perma lock UID changes. irreversible` ### hf mfp From 96f8cad9a523e0c0928fe70ea384d5d345652bd1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 11 Apr 2021 18:18:13 +0200 Subject: [PATCH 223/373] hf mf decrypt - now use cliparser --- client/src/cmdhfmf.c | 84 ++++++++++++++++++---------------- client/src/mifare/mifarehost.c | 5 +- doc/cliparser_todo.txt | 1 - 3 files changed, 47 insertions(+), 43 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index eee416b45..4a78ce118 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -173,21 +173,6 @@ static int usage_hf14_restore(void) { PrintAndLogEx(NORMAL, _YELLOW_(" hf mf restore 4") " -- read the UID from tag with 4K memory first, then restore from hf-mf--key.bin and and hf-mf--dump.bin"); return PM3_SUCCESS; } -static int usage_hf14_decryptbytes(void) { - PrintAndLogEx(NORMAL, "Decrypt Crypto-1 encrypted bytes given some known state of crypto. See tracelog to gather needed values\n"); - PrintAndLogEx(NORMAL, "Usage: hf mf decrypt [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " tag nonce"); - PrintAndLogEx(NORMAL, " encrypted reader response"); - PrintAndLogEx(NORMAL, " encrypted tag response"); - PrintAndLogEx(NORMAL, " encrypted data, taken directly after at_enc and forward"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf decrypt b830049b 9248314a 9280e203 41e586f9")); - PrintAndLogEx(NORMAL, "\n this sample decrypts 41e586f9 -> 3003999a Annotated: 30 03 [99 9a] read block 3 [crc]"); - return PM3_SUCCESS; -} - int mfc_ev1_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, int signature_len) { @@ -4375,7 +4360,7 @@ static int CmdHF14AMfCSetBlk(const char *Cmd) { arg_param_begin, arg_int1("b", "blk", "", "block number"), arg_str0("d", "data", "", "bytes to write, 16 hex bytes"), - arg_lit0("w", "wipe", "wipes card with backdoor cmd before writing`"), + arg_lit0("w", "wipe", "wipes card with backdoor cmd before writing"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -4943,35 +4928,54 @@ static int CmdHF14AMfCView(const char *Cmd) { //needs nt, ar, at, Data to decrypt static int CmdHf14AMfDecryptBytes(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf decrypt", + "Decrypt Crypto-1 encrypted bytes given some known state of crypto. See tracelog to gather needed values", + "hf mf decrypt --nt b830049b --ar 9248314a --at 9280e203 -d 41e586f9\n" + " -> 41e586f9 becomes 3003999a\n" + " -> which annotates 30 03 [99 9a] read block 3 [crc]" + ); + void *argtable[] = { + arg_param_begin, + arg_str1(NULL, "nt", "", "tag nonce"), + arg_str1(NULL, "ar", "", "ar_enc, encrypted reader response"), + arg_str1(NULL, "at", "", "at_enc, encrypted tag response"), + arg_str1("d", "data", "", "encrypted data, taken directly after at_enc and forward"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); - char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_decryptbytes(); - - uint32_t nt = param_get32ex(Cmd, 0, 0, 16); - uint32_t ar_enc = param_get32ex(Cmd, 1, 0, 16); - uint32_t at_enc = param_get32ex(Cmd, 2, 0, 16); - - int len = param_getlength(Cmd, 3); - if (len & 1) { - PrintAndLogEx(WARNING, "Uneven hex string length. LEN=%d", len); - return PM3_ESOFT; + uint32_t nt = 0; + int res = arg_get_u32_hexstr_def(ctx, 1, 0, &nt); + if (res != 1) { + PrintAndLogEx(WARNING, "check `nt` parameter"); + return PM3_EINVARG; } - PrintAndLogEx(NORMAL, "nt\t%08X", nt); - PrintAndLogEx(NORMAL, "ar enc\t%08X", ar_enc); - PrintAndLogEx(NORMAL, "at enc\t%08X", at_enc); - - uint8_t *data = calloc(len, sizeof(uint8_t)); - if (!data) { - PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); - return PM3_EMALLOC; + uint32_t ar_enc = 0; + res = arg_get_u32_hexstr_def(ctx, 2, 0, &ar_enc); + if (res != 1) { + PrintAndLogEx(WARNING, "check `ar` parameter"); + return PM3_EINVARG; } - param_gethex_ex(Cmd, 3, data, &len); - len >>= 1; - tryDecryptWord(nt, ar_enc, at_enc, data, len); - free(data); - return PM3_SUCCESS; + uint32_t at_enc = 0; + res = arg_get_u32_hexstr_def(ctx, 3, 0, &at_enc); + if (res != 1) { + PrintAndLogEx(WARNING, "check `at` parameter"); + return PM3_EINVARG; + } + + int datalen = 0; + uint8_t data[512] = {0x00}; + CLIGetHexWithReturn(ctx, 4, data, &datalen); + CLIParserFree(ctx); + + PrintAndLogEx(INFO, "nt....... %08X", nt); + PrintAndLogEx(INFO, "ar enc... %08X", ar_enc); + PrintAndLogEx(INFO, "at enc... %08X", at_enc); + + return tryDecryptWord(nt, ar_enc, at_enc, data, datalen); } static int CmdHf14AMfSetMod(const char *Cmd) { diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index c87e96442..d068aaac0 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -1060,13 +1060,14 @@ void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool i } int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len) { - PrintAndLogEx(SUCCESS, "\nencrypted data: [%s]", sprint_hex(data, len)); + PrintAndLogEx(SUCCESS, "encrypted data... %s", sprint_hex(data, len)); struct Crypto1State *s; uint32_t ks2 = ar_enc ^ prng_successor(nt, 64); uint32_t ks3 = at_enc ^ prng_successor(nt, 96); s = lfsr_recovery64(ks2, ks3); mf_crypto1_decrypt(s, data, len, false); - PrintAndLogEx(SUCCESS, "decrypted data: [%s]", sprint_hex(data, len)); + PrintAndLogEx(SUCCESS, "decrypted data... " _YELLOW_("%s"), sprint_hex(data, len)); + PrintAndLogEx(NORMAL, ""); crypto1_destroy(s); return PM3_SUCCESS; } diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 83fbf87c3..77e7d2d32 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -18,7 +18,6 @@ hf felica rqspecver hf felica resetmode hf mf hardnested hf mf autopwn -hf mf decrypt hf mf restore hf mf wrbl lf hitag reader From e5a9e8812a7234b9c40e152b58384a3d1d79ef7e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 11 Apr 2021 19:11:11 +0200 Subject: [PATCH 224/373] hf mf wrbl - now uses cliparser --- client/src/cmdhfmf.c | 90 ++++++++++++++++++++++++++---------------- doc/cliparser_todo.txt | 1 - 2 files changed, 56 insertions(+), 35 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 4a78ce118..bd8b087b6 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -444,56 +444,78 @@ static int CmdHF14AMfDarkside(const char *Cmd) { } static int CmdHF14AMfWrBl(const char *Cmd) { - uint8_t blockNo = 0; - uint8_t keyType = 0; - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - char cmdp = 0x00; - if (strlen(Cmd) < 3) { - PrintAndLogEx(NORMAL, "Usage: hf mf wrbl "); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf wrbl 1 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F"); - return PM3_SUCCESS; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf wrbl", + "Write MIFARE Classic block", + "hf mf wrbl --blk 1 -k FFFFFFFFFFFF -d 000102030405060708090a0b0c0d0e0f" + ); + void *argtable[] = { + arg_param_begin, + arg_int1(NULL, "blk", "", "block number"), + arg_lit0("a", NULL, "input key type is key A (def)"), + arg_lit0("b", NULL, "input key type is key B"), + arg_str0("k", "key", "", "key, 6 hex bytes"), + arg_str0("d", "data", "", "bytes to write, 16 hex bytes"), + + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int b = arg_get_int_def(ctx, 1, 0); + + uint8_t keytype = MF_KEY_A; + if (arg_get_lit(ctx, 2) && arg_get_lit(ctx, 3)) { + CLIParserFree(ctx); + PrintAndLogEx(WARNING, "Input key type must be A or B"); + return PM3_EINVARG; + } else if (arg_get_lit(ctx, 3)) { + keytype = MF_KEY_B;; } - blockNo = param_get8(Cmd, 0); - cmdp = tolower(param_getchar(Cmd, 1)); - if (cmdp == 0x00) { - PrintAndLogEx(NORMAL, "Key type must be A or B"); + int keylen = 0; + uint8_t key[6] = {0}; + CLIGetHexWithReturn(ctx, 4, key, &keylen); + + uint8_t block[MFBLOCK_SIZE] = {0x00}; + int blen = 0; + CLIGetHexWithReturn(ctx, 5, block, &blen); + CLIParserFree(ctx); + + if (blen != MFBLOCK_SIZE) { + PrintAndLogEx(WARNING, "block data must include 16 HEX bytes. Got %i", blen); return PM3_EINVARG; } - if (cmdp != 'a') - keyType = 1; - - if (param_gethex(Cmd, 2, key, 12)) { - PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); + if (b > 255) { return PM3_EINVARG; } + uint8_t blockno = (uint8_t)b; - if (param_gethex(Cmd, 3, bldata, 32)) { - PrintAndLogEx(NORMAL, "Block data must include 32 HEX symbols"); - return PM3_EINVARG; - } - - PrintAndLogEx(NORMAL, "--block no %d, key %c - %s", blockNo, keyType ? 'B' : 'A', sprint_hex(key, 6)); - PrintAndLogEx(NORMAL, "--data: %s", sprint_hex(bldata, 16)); + PrintAndLogEx(INFO, "--block no %d, key %c - %s", blockno, keytype ? 'B' : 'A', sprint_hex_inrow(key, sizeof(key))); + PrintAndLogEx(INFO, "--data: %s", sprint_hex(block, sizeof(block))); uint8_t data[26]; - memcpy(data, key, 6); - memcpy(data + 10, bldata, 16); + memcpy(data, key, sizeof(key)); + memcpy(data + 10, block, sizeof(block)); clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFARE_WRITEBL, blockNo, keyType, 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_MIFARE_WRITEBL, blockno, keytype, 0, data, sizeof(data)); PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - uint8_t isOK = resp.oldarg[0] & 0xff; - PrintAndLogEx(NORMAL, "isOk:%02x", isOK); - } else { - PrintAndLogEx(NORMAL, "Command execute timeout"); + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) { + PrintAndLogEx(FAILED, "Command execute timeout"); + return PM3_ETIMEOUT; } + uint8_t isok = resp.oldarg[0] & 0xff; + if (isok) { + PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )"); + PrintAndLogEx(HINT, "try `" _YELLOW_("hf mf rdbl") "` to verify"); + } else { + PrintAndLogEx(FAILED, "Write ( " _RED_("fail") " )"); + // suggest the opposite keytype than what was used. + PrintAndLogEx(HINT, "Maybe access rights? Try specify keytype " _YELLOW_("%c") " instead", (keytype == 0) ? 'B' : 'A' ); + } return PM3_SUCCESS; } diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 77e7d2d32..4f0adf791 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -19,7 +19,6 @@ hf felica resetmode hf mf hardnested hf mf autopwn hf mf restore -hf mf wrbl lf hitag reader lf hitag writer lf hitag dump From f07426db439c18265642d97954aa4354334798fc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 11 Apr 2021 21:19:14 +0200 Subject: [PATCH 225/373] hf mf restore - now uses cliparser --- client/src/cmdhfmf.c | 377 +++++++++++++++++++++-------------------- doc/cliparser_todo.txt | 1 - 2 files changed, 192 insertions(+), 186 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index bd8b087b6..100f03da4 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -43,21 +43,6 @@ static int CmdHelp(const char *Cmd); -/* - * static int usage_hf14_sniff(void) { - PrintAndLogEx(NORMAL, "It continuously gets data from the field and saves it to: log, emulator, emulator file."); - PrintAndLogEx(NORMAL, "Usage: hf mf sniff [h] [l] [d] [f]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " l save encrypted sequence to logfile `uid.log`"); - PrintAndLogEx(NORMAL, " d decrypt sequence and put it to log file `uid.log`"); -// PrintAndLogEx(NORMAL, " n/a e decrypt sequence, collect read and write commands and save the result of the sequence to emulator memory"); - PrintAndLogEx(NORMAL, " f decrypt sequence, collect read and write commands and save the result of the sequence to emulator dump file `uid.eml`"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf sniff l d f")); - return PM3_SUCCESS; -} -*/ static int usage_hf14_hardnested(void) { PrintAndLogEx(NORMAL, "Usage:"); PrintAndLogEx(NORMAL, " hf mf hardnested "); @@ -95,7 +80,6 @@ static int usage_hf14_hardnested(void) { PrintAndLogEx(NORMAL, _YELLOW_(" hf mf hardnested 0 A A0A1A2A3A4A5 4 A FFFFFFFFFFFF")); return PM3_SUCCESS; } - static int usage_hf14_autopwn(void) { PrintAndLogEx(NORMAL, "Usage:"); PrintAndLogEx(NORMAL, " hf mf autopwn [k] "); @@ -157,22 +141,6 @@ static int usage_hf14_keybrute(void) { return 0; } */ -static int usage_hf14_restore(void) { - PrintAndLogEx(NORMAL, "Usage: hf mf restore [card memory] u k f [w]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (MIFARE Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); - PrintAndLogEx(NORMAL, " u : uid, try to restore from hf-mf--key.bin and hf-mf--dump.bin"); - PrintAndLogEx(NORMAL, " k : key filename, specific the full filename of key file"); - PrintAndLogEx(NORMAL, " f : data filename, specific the full filename of data file"); - PrintAndLogEx(NORMAL, " w : use specified keyfile to authenticate with"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf restore") " -- read the UID from tag first, then restore from hf-mf--key.bin and and hf-mf--dump.bin"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf restore 1 u 12345678") " -- restore from hf-mf-12345678-key.bin and hf-mf-12345678-dump.bin"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf restore 1 u 12345678 k dumpkey.bin") " -- restore from dumpkey.bin and hf-mf-12345678-dump.bin"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf restore 4") " -- read the UID from tag with 4K memory first, then restore from hf-mf--key.bin and and hf-mf--dump.bin"); - return PM3_SUCCESS; -} int mfc_ev1_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, int signature_len) { @@ -718,15 +686,6 @@ static int CmdHF14AMfDump(const char *Cmd) { uint64_t t1 = msclock(); - uint8_t sectorNo, blockNo; - uint8_t keyA[40][6]; - uint8_t keyB[40][6]; - uint8_t rights[40][4]; - uint8_t carddata[256][16]; - - FILE *f; - PacketResponseNG resp; - // validations if ((m0 + m1 + m2 + m4) > 1) { PrintAndLogEx(WARNING, "Only specify one MIFARE Type"); @@ -750,6 +709,15 @@ static int CmdHF14AMfDump(const char *Cmd) { return PM3_EINVARG; } + uint8_t sectorNo, blockNo; + uint8_t keyA[40][6]; + uint8_t keyB[40][6]; + uint8_t rights[40][4]; + uint8_t carddata[256][16]; + + FILE *f; + PacketResponseNG resp; + char *fptr; if (keyFilename[0] == 0x00) { @@ -933,174 +901,238 @@ static int CmdHF14AMfDump(const char *Cmd) { } static int CmdHF14AMfRestore(const char *Cmd) { - uint8_t sectorNo, blockNo; - uint8_t keyType = 0; - uint8_t key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - uint8_t bldata[16] = {0x00}; + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf restore", + "Restore MIFARE Classic binary file to tag.\n" + "\n" + "The key file and data file will program the card sector trailers.\n" + "By default we authenticate to card with key B 0xFFFFFFFFFFFF.\n" + "\n" + "`--uid` param is used for filename templates `hf-mf--dump.bin` and `hf-mf--key.bin.\n" + " If not specified, it will read the card uid instead.\n" + " `-w` param you can indicate that the key file should be used for authentication instead.\n" + " if so we also try both B/A keys", + "hf mf restore\n" + "hf mf restore --1k --uid 04010203\n" + "hf mf restore --1k --uid 04010203 -k hf-mf-AABBCCDD-key.bin\n" + "hf mf restore --4k" + ); + + void *argtable[] = { + arg_param_begin, + arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"), + arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (def)"), + arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"), + arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"), + arg_str0("u", "uid", "", "uid, 6 hex bytes"), + arg_str0("f", "file", "", "data filename"), + arg_str0("k", "kfn", "", "key filename"), + arg_lit0(NULL, "ka", "use specified keyfile to authenticate"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool m0 = arg_get_lit(ctx, 1); + bool m1 = arg_get_lit(ctx, 2); + bool m2 = arg_get_lit(ctx, 3); + bool m4 = arg_get_lit(ctx, 4); + + int uidlen = 0; + char uid[14] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)uid, sizeof(uid), &uidlen); + + int datafnlen = 0; + char datafilename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)datafilename, FILE_PATH_SIZE, &datafnlen); + + int keyfnlen = 0; + char keyfilename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 7), (uint8_t *)keyfilename, FILE_PATH_SIZE, &keyfnlen); + + bool use_keyfile_for_auth = arg_get_lit(ctx, 8); + CLIParserFree(ctx); + + // validations + if ((m0 + m1 + m2 + m4) > 1) { + PrintAndLogEx(WARNING, "Only specify one MIFARE Type"); + return PM3_EINVARG; + } else if ((m0 + m1 + m2 + m4) == 0) { + m1 = true; + } + + uint8_t sectors = MIFARE_1K_MAXSECTOR; + + if (m0) { + sectors = MIFARE_MINI_MAXSECTOR; + } else if (m1) { + sectors = MIFARE_1K_MAXSECTOR; + } else if (m2) { + sectors = MIFARE_2K_MAXSECTOR; + } else if (m4) { + sectors = MIFARE_4K_MAXSECTOR; + } else { + PrintAndLogEx(WARNING, "Please specify a MIFARE Type"); + return PM3_EINVARG; + } + + // if user specified UID, use it in file templates + if (uidlen) { + + if (keyfnlen == 0) { + snprintf(keyfilename, FILE_PATH_SIZE, "hf-mf-%s-key.bin", uid); + keyfnlen = strlen(keyfilename); + } + + if (datafnlen == 0) { + snprintf(datafilename, FILE_PATH_SIZE, "hf-mf-%s-dump.bin", uid); + datafnlen = strlen(datafilename); + } + } + + // try reading card uid and create filename + if (keyfnlen == 0) { + char *fptr = GenerateFilename("hf-mf-", "-key.bin"); + if (fptr == NULL) + return PM3_ESOFT; + + strcpy(keyfilename, fptr); + free(fptr); + } + + FILE *f; + if ((f = fopen(keyfilename, "rb")) == NULL) { + PrintAndLogEx(WARNING, "Could not find file " _YELLOW_("%s"), keyfilename); + return PM3_EFILE; + } + + // key arrays uint8_t keyA[40][6]; uint8_t keyB[40][6]; - uint8_t numSectors = 16; - uint8_t cmdp = 0; - char keyFilename[FILE_PATH_SIZE] = ""; - char dataFilename[FILE_PATH_SIZE] = ""; - char szTemp[FILE_PATH_SIZE - 20] = ""; - char *fptr; - FILE *fdump, *fkeys; - - bool use_keyfile_for_auth = false; - while (param_getchar(Cmd, cmdp) != 0x00) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf14_restore(); - case 'u': - param_getstr(Cmd, cmdp + 1, szTemp, FILE_PATH_SIZE - 20); - if (keyFilename[0] == 0x00) - snprintf(keyFilename, FILE_PATH_SIZE, "hf-mf-%s-key.bin", szTemp); - if (dataFilename[0] == 0x00) - snprintf(dataFilename, FILE_PATH_SIZE, "hf-mf-%s-dump.bin", szTemp); - cmdp += 2; - break; - case 'k': - param_getstr(Cmd, cmdp + 1, keyFilename, FILE_PATH_SIZE); - cmdp += 2; - break; - case 'f': - param_getstr(Cmd, cmdp + 1, dataFilename, FILE_PATH_SIZE); - cmdp += 2; - break; - case 'w': - use_keyfile_for_auth = true; - cmdp++; - break; - default: - if (cmdp == 0) { - numSectors = NumOfSectors(param_getchar(Cmd, cmdp)); - if (numSectors == 0) return usage_hf14_restore(); - cmdp++; - } else { - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - return usage_hf14_restore(); - } - } - } - - if (keyFilename[0] == 0x00) { - fptr = GenerateFilename("hf-mf-", "-key.bin"); - if (fptr == NULL) - return 1; - - strcpy(keyFilename, fptr); - free(fptr); - } - - if ((fkeys = fopen(keyFilename, "rb")) == NULL) { - PrintAndLogEx(WARNING, "Could not find file " _YELLOW_("%s"), keyFilename); - return 1; - } + // read key file size_t bytes_read; - for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { - bytes_read = fread(keyA[sectorNo], 1, 6, fkeys); + for (uint8_t s = 0; s < sectors; s++) { + bytes_read = fread(keyA[s], 1, 6, f); if (bytes_read != 6) { - PrintAndLogEx(ERR, "File reading error " _YELLOW_("%s"), keyFilename); - fclose(fkeys); - return 2; + PrintAndLogEx(ERR, "File reading error " _YELLOW_("%s"), keyfilename); + fclose(f); + return PM3_EFILE; } } - for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { - bytes_read = fread(keyB[sectorNo], 1, 6, fkeys); + for (uint8_t s = 0; s < sectors; s++) { + bytes_read = fread(keyB[s], 1, 6, f); if (bytes_read != 6) { - PrintAndLogEx(ERR, "File reading error " _YELLOW_("%s"), keyFilename); - fclose(fkeys); - return 2; + PrintAndLogEx(ERR, "File reading error " _YELLOW_("%s"), keyfilename); + fclose(f); + return PM3_EFILE; } } + fclose(f); + f = NULL; - fclose(fkeys); - - if (dataFilename[0] == 0x00) { - fptr = GenerateFilename("hf-mf-", "-dump.bin"); + // try reading card uid and create filename + if (datafnlen == 0) { + char *fptr = GenerateFilename("hf-mf-", "-dump.bin"); if (fptr == NULL) - return 1; + return PM3_ESOFT; - strcpy(dataFilename, fptr); + strcpy(datafilename, fptr); free(fptr); } - if ((fdump = fopen(dataFilename, "rb")) == NULL) { - PrintAndLogEx(WARNING, "Could not find file " _YELLOW_("%s"), dataFilename); - return 1; + // read dump file + if ((f = fopen(datafilename, "rb")) == NULL) { + PrintAndLogEx(WARNING, "Could not find file " _YELLOW_("%s"), datafilename); + return PM3_EINVARG; } - PrintAndLogEx(INFO, "Restoring " _YELLOW_("%s")" to card", dataFilename); - for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { - for (blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) { + // default authentication key + uint8_t default_key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + PrintAndLogEx(INFO, "Restoring " _YELLOW_("%s")" to card", datafilename); + + for (uint8_t s = 0; s < sectors; s++) { + for (uint8_t b = 0; b < NumBlocksPerSector(s); b++) { + uint8_t data[26]; - bytes_read = fread(bldata, 1, 16, fdump); - if (bytes_read != 16) { - PrintAndLogEx(ERR, "File reading error " _YELLOW_("%s"), dataFilename); - fclose(fdump); - fdump = NULL; - return 2; + uint8_t bldata[MFBLOCK_SIZE] = {0x00}; + + bytes_read = fread(bldata, 1, MFBLOCK_SIZE, f); + if (bytes_read != sizeof(bldata)) { + PrintAndLogEx(ERR, "File reading error " _YELLOW_("%s"), datafilename); + fclose(f); + f = NULL; + return PM3_EFILE; } if (use_keyfile_for_auth == false) { - if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer - bldata[0] = (keyA[sectorNo][0]); - bldata[1] = (keyA[sectorNo][1]); - bldata[2] = (keyA[sectorNo][2]); - bldata[3] = (keyA[sectorNo][3]); - bldata[4] = (keyA[sectorNo][4]); - bldata[5] = (keyA[sectorNo][5]); - bldata[10] = (keyB[sectorNo][0]); - bldata[11] = (keyB[sectorNo][1]); - bldata[12] = (keyB[sectorNo][2]); - bldata[13] = (keyB[sectorNo][3]); - bldata[14] = (keyB[sectorNo][4]); - bldata[15] = (keyB[sectorNo][5]); + + // sector trailer + if (b == NumBlocksPerSector(s) - 1) { + bldata[0] = (keyA[s][0]); + bldata[1] = (keyA[s][1]); + bldata[2] = (keyA[s][2]); + bldata[3] = (keyA[s][3]); + bldata[4] = (keyA[s][4]); + bldata[5] = (keyA[s][5]); + bldata[10] = (keyB[s][0]); + bldata[11] = (keyB[s][1]); + bldata[12] = (keyB[s][2]); + bldata[13] = (keyB[s][3]); + bldata[14] = (keyB[s][4]); + bldata[15] = (keyB[s][5]); } } - memcpy(data + 10, bldata, 16); - + memcpy(data + 10, bldata, sizeof(bldata)); if (use_keyfile_for_auth) { - for (uint8_t kt = 0; kt < 2; kt++) { + for (int8_t kt = MF_KEY_B; kt > -1; kt--) { + //for (uint8_t kt = MF_KEY_A; kt <= MF_KEY_B; kt++) { - if (kt == 0) - memcpy(data, keyA[sectorNo], 6); + if (kt == MF_KEY_A) + memcpy(data, keyA[s], 6); else - memcpy(data, keyB[sectorNo], 6); + memcpy(data, keyB[s], 6); - PrintAndLogEx(NORMAL, "Writing to block %3d: %s", FirstBlockOfSector(sectorNo) + blockNo, sprint_hex(bldata, 16)); + PrintAndLogEx(INFO, "block %3d: %s", FirstBlockOfSector(s) + b, sprint_hex(bldata, sizeof(bldata))); clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFARE_WRITEBL, FirstBlockOfSector(sectorNo) + blockNo, kt, 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_MIFARE_WRITEBL, FirstBlockOfSector(s) + b, kt, 0, data, sizeof(data)); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { uint8_t isOK = resp.oldarg[0] & 0xff; if (isOK == 0) { - PrintAndLogEx(FAILED, "isOk: %02x", isOK); + if (b == 0) { + PrintAndLogEx(INFO, "Writing to manufacture block w key %c ( " _RED_("fail") " )", (kt == MF_KEY_A) ? 'A' : 'B'); + } else { + PrintAndLogEx(FAILED, "Write to block %u w key %c ( " _RED_("fail") " ) ", b, (kt == MF_KEY_A) ? 'A' : 'B'); + } } else { + // if success, skip to next block break; } } else { PrintAndLogEx(WARNING, "Command execute timeout"); } } - } else { - memcpy(data, key, 6); - PrintAndLogEx(NORMAL, "Writing to block %3d: %s", FirstBlockOfSector(sectorNo) + blockNo, sprint_hex(bldata, 16)); + memcpy(data, default_key, 6); + PrintAndLogEx(INFO, "block %3d: %s", FirstBlockOfSector(s) + b, sprint_hex(bldata, sizeof(bldata))); clearCommandBuffer(); - SendCommandMIX(CMD_HF_MIFARE_WRITEBL, FirstBlockOfSector(sectorNo) + blockNo, keyType, 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_MIFARE_WRITEBL, FirstBlockOfSector(s) + b, MF_KEY_B, 0, data, sizeof(data)); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { uint8_t isOK = resp.oldarg[0] & 0xff; if (isOK == 0) { - PrintAndLogEx(FAILED, "isOk: %02x", isOK); + if (b == 0) { + PrintAndLogEx(INFO, "Writing to manufacture block w key B ( " _RED_("fail") " )"); + } else { + PrintAndLogEx(FAILED, "Write to block %u w key B ( " _RED_("fail") " )", b); + } } } else { PrintAndLogEx(WARNING, "Command execute timeout"); @@ -1108,7 +1140,7 @@ static int CmdHF14AMfRestore(const char *Cmd) { } } } - fclose(fdump); + fclose(f); PrintAndLogEx(INFO, "Done!"); return PM3_SUCCESS; } @@ -2609,29 +2641,6 @@ all_found: return PM3_SUCCESS; } -/* -static int randInRange(int min, int max) { - return min + (int)(rand() / (double)(RAND_MAX) * (max - min + 1)); -} -*/ - -//Fisher–Yates shuffle -/* -static void shuffle(uint8_t *array, uint16_t len) { - uint8_t tmp[6]; - uint16_t x; - time_t t; - srand((unsigned) time(&t)); - while (len) { - x = randInRange(0, (len -= 6)) | 0; // 0 = i < n - x %= 6; - memcpy(tmp, array + x, 6); - memcpy(array + x, array + len, 6); - memcpy(array + len, tmp, 6); - } -} -*/ - static int CmdHF14AMfChk_fast(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf fchk", @@ -5933,7 +5942,7 @@ static int CmdHF14AMfWipe(const char *Cmd) { else memcpy(data, keyB + (s * 6), 6); - PrintAndLogEx(INFO, "Writing to block %3d: %s", FirstBlockOfSector(s) + b, sprint_hex(data + 10, MFBLOCK_SIZE)); + PrintAndLogEx(INFO, "block %3d: %s", FirstBlockOfSector(s) + b, sprint_hex(data + 10, MFBLOCK_SIZE)); clearCommandBuffer(); SendCommandMIX(CMD_HF_MIFARE_WRITEBL, FirstBlockOfSector(s) + b, kt, 0, data, sizeof(data)); PacketResponseNG resp; @@ -6059,8 +6068,6 @@ static command_t CommandTable[] = { {"view", CmdHF14AMfView, AlwaysAvailable, "Display content from tag dump file"}, {"wipe", CmdHF14AMfWipe, IfPm3Iso14443a, "Wipe card to zeros and default keys/acc"}, {"wrbl", CmdHF14AMfWrBl, IfPm3Iso14443a, "Write MIFARE Classic block"}, - -// {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"}, {"sim", CmdHF14AMfSim, IfPm3Iso14443a, "Simulate MIFARE card"}, {"ecfill", CmdHF14AMfECFill, IfPm3Iso14443a, "Fill emulator memory with help of keys from emulator"}, diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 4f0adf791..55b00cc75 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -18,7 +18,6 @@ hf felica rqspecver hf felica resetmode hf mf hardnested hf mf autopwn -hf mf restore lf hitag reader lf hitag writer lf hitag dump From 199e344260df8d75bca6edc13c55903f12e9246d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 11 Apr 2021 21:35:45 +0200 Subject: [PATCH 226/373] use defines instead --- client/src/cmdhfmf.c | 106 +++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 54 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 100f03da4..deec0cf6d 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -460,7 +460,7 @@ static int CmdHF14AMfWrBl(const char *Cmd) { } uint8_t blockno = (uint8_t)b; - PrintAndLogEx(INFO, "--block no %d, key %c - %s", blockno, keytype ? 'B' : 'A', sprint_hex_inrow(key, sizeof(key))); + PrintAndLogEx(INFO, "--block no %d, key %c - %s", blockno, (keytype == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(key, sizeof(key))); PrintAndLogEx(INFO, "--data: %s", sprint_hex(block, sizeof(block))); uint8_t data[26]; @@ -482,7 +482,7 @@ static int CmdHF14AMfWrBl(const char *Cmd) { } else { PrintAndLogEx(FAILED, "Write ( " _RED_("fail") " )"); // suggest the opposite keytype than what was used. - PrintAndLogEx(HINT, "Maybe access rights? Try specify keytype " _YELLOW_("%c") " instead", (keytype == 0) ? 'B' : 'A' ); + PrintAndLogEx(HINT, "Maybe access rights? Try specify keytype " _YELLOW_("%c") " instead", (keytype == MF_KEY_A) ? 'B' : 'A' ); } return PM3_SUCCESS; } @@ -506,13 +506,13 @@ static int CmdHF14AMfRdBl(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, false); int b = arg_get_int_def(ctx, 1, 0); - uint8_t keytype = 0; + uint8_t keytype = MF_KEY_A; if (arg_get_lit(ctx, 2) && arg_get_lit(ctx, 3)) { CLIParserFree(ctx); PrintAndLogEx(WARNING, "Input key type must be A or B"); return PM3_EINVARG; } else if (arg_get_lit(ctx, 3)) { - keytype = 1; + keytype = MF_KEY_B; } int keylen = 0; @@ -558,13 +558,13 @@ static int CmdHF14AMfRdSc(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); - uint8_t keytype = 0; + uint8_t keytype = MF_KEY_A; if (arg_get_lit(ctx, 1) && arg_get_lit(ctx, 2)) { CLIParserFree(ctx); PrintAndLogEx(WARNING, "Input key type must be A or B"); return PM3_EINVARG; } else if (arg_get_lit(ctx, 2)) { - keytype = 1; + keytype = MF_KEY_B; } int keylen = 0; @@ -612,7 +612,7 @@ static int FastDumpWithEcFill(uint8_t numsectors) { mfc_eload_t payload; payload.sectorcnt = numsectors; - payload.keytype = 0; + payload.keytype = MF_KEY_A; // ecfill key A clearCommandBuffer(); @@ -628,7 +628,7 @@ static int FastDumpWithEcFill(uint8_t numsectors) { PrintAndLogEx(INFO, "fast dump reported back failure w KEY A, swapping to KEY B"); // ecfill key B - payload.keytype = 1; + payload.keytype = MF_KEY_B; clearCommandBuffer(); SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload)); @@ -770,7 +770,7 @@ static int CmdHF14AMfDump(const char *Cmd) { fflush(stdout); payload.blockno = FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1; - payload.keytype = 0; + payload.keytype = MF_KEY_A; memcpy(payload.key, keyA[sectorNo], sizeof(payload.key)); clearCommandBuffer(); @@ -809,7 +809,7 @@ static int CmdHF14AMfDump(const char *Cmd) { if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer. At least the Access Conditions can always be read with key A. payload.blockno = FirstBlockOfSector(sectorNo) + blockNo; - payload.keytype = 0; + payload.keytype = MF_KEY_A; memcpy(payload.key, keyA[sectorNo], sizeof(payload.key)); clearCommandBuffer(); @@ -833,7 +833,7 @@ static int CmdHF14AMfDump(const char *Cmd) { } else { // key A would work payload.blockno = FirstBlockOfSector(sectorNo) + blockNo; - payload.keytype = 0; + payload.keytype = MF_KEY_A; memcpy(payload.key, keyA[sectorNo], sizeof(payload.key)); clearCommandBuffer(); @@ -1090,7 +1090,6 @@ static int CmdHF14AMfRestore(const char *Cmd) { if (use_keyfile_for_auth) { for (int8_t kt = MF_KEY_B; kt > -1; kt--) { - //for (uint8_t kt = MF_KEY_A; kt <= MF_KEY_B; kt++) { if (kt == MF_KEY_A) memcpy(data, keyA[s], 6); @@ -1186,26 +1185,26 @@ static int CmdHF14AMfNested(const char *Cmd) { uint8_t blockNo = arg_get_u32_def(ctx, 6, 0); - uint8_t keyType = 0; + uint8_t keyType = MF_KEY_A; if (arg_get_lit(ctx, 7) && arg_get_lit(ctx, 8)) { CLIParserFree(ctx); PrintAndLogEx(WARNING, "Input key type must be A or B"); return PM3_EINVARG; } else if (arg_get_lit(ctx, 8)) { - keyType = 1; + keyType = MF_KEY_B; } uint8_t trgBlockNo = arg_get_u32_def(ctx, 9, 0); - uint8_t trgKeyType = 0; + uint8_t trgKeyType = MF_KEY_A; if (arg_get_lit(ctx, 10) && arg_get_lit(ctx, 11)) { CLIParserFree(ctx); PrintAndLogEx(WARNING, "Target key type must be A or B"); return PM3_EINVARG; } else if (arg_get_lit(ctx, 11)) { - trgKeyType = 1; + trgKeyType = MF_KEY_B; } bool transferToEml = arg_get_lit(ctx, 12); @@ -1289,7 +1288,7 @@ static int CmdHF14AMfNested(const char *Cmd) { } mfEmlGetMem(keyBlock, sectortrailer, 1); - if (!trgKeyType) + if (trgKeyType == MF_KEY_A) num_to_bytes(key64, 6, keyBlock); else num_to_bytes(key64, 6, &keyBlock[10]); @@ -1334,7 +1333,7 @@ static int CmdHF14AMfNested(const char *Cmd) { // nested sectors bool calibrate = true; - for (trgKeyType = 0; trgKeyType < 2; ++trgKeyType) { + for (trgKeyType = MF_KEY_A; trgKeyType <= MF_KEY_B; ++trgKeyType) { for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; ++sectorNo) { for (int i = 0; i < MIFARE_SECTOR_RETRY; i++) { @@ -1387,7 +1386,7 @@ static int CmdHF14AMfNested(const char *Cmd) { mf_readblock_t payload; payload.blockno = sectrail; - payload.keytype = 0; + payload.keytype = MF_KEY_A; num_to_bytes(e_sector[i].Key[0], 6, payload.key); // KEY A @@ -1491,14 +1490,14 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { uint8_t blockNo = arg_get_u32_def(ctx, 6, 0); - uint8_t keyType = 0; + uint8_t keyType = MF_KEY_A; if (arg_get_lit(ctx, 7) && arg_get_lit(ctx, 8)) { CLIParserFree(ctx); PrintAndLogEx(WARNING, "Input key type must be A or B"); return PM3_EINVARG; } else if (arg_get_lit(ctx, 8)) { - keyType = 1; + keyType = MF_KEY_B; } bool transferToEml = arg_get_lit(ctx, 9); @@ -1533,7 +1532,7 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { sector_t *e_sector = NULL; - uint8_t trgKeyType = 0; + uint8_t trgKeyType = MF_KEY_A; uint8_t keyBlock[(ARRAYLEN(g_mifare_default_keys) + 1) * 6]; uint64_t key64 = 0; @@ -1585,7 +1584,7 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { PrintAndLogEx(SUCCESS, "enter static nested key recovery"); // nested sectors - for (trgKeyType = 0; trgKeyType < 2; ++trgKeyType) { + for (trgKeyType = MF_KEY_A; trgKeyType <= MF_KEY_B; ++trgKeyType) { for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; ++sectorNo) { for (int i = 0; i < 1; i++) { @@ -1633,7 +1632,7 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { mf_readblock_t payload; payload.blockno = sectrail; - payload.keytype = 0; + payload.keytype = MF_KEY_A; num_to_bytes(e_sector[i].Key[0], 6, payload.key); // KEY A @@ -1703,9 +1702,9 @@ jumptoend: static int CmdHF14AMfNestedHard(const char *Cmd) { uint8_t blockNo = 0; - uint8_t keyType = 0; + uint8_t keyType = MF_KEY_A; uint8_t trgBlockNo = 0; - uint8_t trgKeyType = 0; + uint8_t trgKeyType = MF_KEY_A; uint8_t key[6] = {0, 0, 0, 0, 0, 0}; uint8_t trgkey[6] = {0, 0, 0, 0, 0, 0}; uint8_t cmdp = 0; @@ -1758,7 +1757,7 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { } if (ctmp != 'a') { - keyType = 1; + keyType = MF_KEY_B; } if (param_gethex(Cmd, cmdp + 2, key, 12)) { @@ -1779,7 +1778,7 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { return 1; } if (ctmp != 'a') { - trgKeyType = 1; + trgKeyType = MF_KEY_B; } cmdp += 5; } @@ -1864,14 +1863,14 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { uint64_t key64 = 0; // check if we can authenticate to sector if (mfCheckKeys(blockNo, keyType, true, 1, key, &key64) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "Key is wrong. Can't authenticate to block: %3d key type: %c", blockNo, keyType ? 'B' : 'A'); + PrintAndLogEx(WARNING, "Key is wrong. Can't authenticate to block: %3d key type: %c", blockNo, (keyType == MF_KEY_B) ? 'B' : 'A'); return 3; } } PrintAndLogEx(INFO, "Target block no:%3d, target key type:%c, known target key: 0x%02x%02x%02x%02x%02x%02x%s", trgBlockNo, - trgKeyType ? 'B' : 'A', + (trgKeyType == MF_KEY_B)? 'B' : 'A', trgkey[0], trgkey[1], trgkey[2], trgkey[3], trgkey[4], trgkey[5], know_target_key ? "" : " (not set)" ); @@ -1906,7 +1905,7 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { static int CmdHF14AMfAutoPWN(const char *Cmd) { // Nested and Hardnested parameter uint8_t blockNo = 0; - uint8_t keyType = 0; + uint8_t keyType = MF_KEY_A; uint8_t key[6] = {0}; uint64_t key64 = 0; bool calibrate = true; @@ -1988,7 +1987,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { } if (ctmp != 'a') { - keyType = 1; + keyType = MF_KEY_B; } // Get the known block key @@ -2074,7 +2073,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { PrintAndLogEx(INFO, " card sectors .. " _YELLOW_("%d"), sectors_cnt); PrintAndLogEx(INFO, " key supplied .. " _YELLOW_("%s"), know_target_key ? "True" : "False"); PrintAndLogEx(INFO, " known sector .. " _YELLOW_("%d"), blockNo); - PrintAndLogEx(INFO, " keytype ....... " _YELLOW_("%c"), keyType ? 'B' : 'A'); + PrintAndLogEx(INFO, " keytype ....... " _YELLOW_("%c"), (keyType == MF_KEY_B) ? 'B' : 'A'); PrintAndLogEx(INFO, " known key ..... " _YELLOW_("%s"), sprint_hex(key, sizeof(key))); if (has_staticnonce == NONCE_STATIC) @@ -2104,7 +2103,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { if (mfCheckKeys(FirstBlockOfSector(blockNo), keyType, true, 1, key, &key64) == PM3_SUCCESS) { PrintAndLogEx(INFO, "target sector:%3u key type: %c -- using valid key [ " _GREEN_("%s") "] (used for nested / hardnested attack)", blockNo, - keyType ? 'B' : 'A', + (keyType == MF_KEY_B) ? 'B' : 'A', sprint_hex(key, sizeof(key)) ); @@ -2117,7 +2116,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { know_target_key = false; PrintAndLogEx(FAILED, "Key is wrong. Can't authenticate to sector:"_RED_("%3d") " key type: "_RED_("%c") " key: " _RED_("%s"), blockNo, - keyType ? 'B' : 'A', + (keyType == MF_KEY_B) ? 'B' : 'A', sprint_hex(key, sizeof(key)) ); PrintAndLogEx(WARNING, "falling back to dictionary"); @@ -2125,7 +2124,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { // Check if the user supplied key is used by other sectors for (int i = 0; i < sectors_cnt; i++) { - for (int j = 0; j < 2; j++) { + for (int j = MF_KEY_A; j <= MF_KEY_B; j++) { if (e_sector[i].foundKey[j] == 0) { if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, key, &key64) == PM3_SUCCESS) { e_sector[i].Key[j] = bytes_to_num(key, 6); @@ -2251,7 +2250,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { // Analyse the dictionary attack for (int i = 0; i < sectors_cnt; i++) { - for (int j = 0; j < 2; j++) { + for (int j = MF_KEY_A; j <= MF_KEY_B; j++) { if (e_sector[i].foundKey[j] == 1) { e_sector[i].foundKey[j] = 'D'; num_to_bytes(e_sector[i].Key[j], 6, tmp_key); @@ -2315,7 +2314,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { e_sector[blockNo].foundKey[keyType] = 'S'; PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%012" PRIx64) " ] (used for nested / hardnested attack)", blockNo, - keyType ? 'B' : 'A', + (keyType == MF_KEY_B) ? 'B' : 'A', key64 ); } else { @@ -2378,7 +2377,7 @@ noValidKeyFound: mf_readblock_t payload; payload.blockno = sectrail; - payload.keytype = 0; + payload.keytype = MF_KEY_A; num_to_bytes(e_sector[current_sector_i].Key[0], 6, payload.key); // KEY A @@ -2974,9 +2973,9 @@ static int CmdHF14AMfChk(const char *Cmd) { if ((arg_get_lit(ctx, 3) && arg_get_lit(ctx, 4)) || arg_get_lit(ctx, 5)) { keyType = 2; } else if (arg_get_lit(ctx, 3)) { - keyType = 0; + keyType = MF_KEY_A; } else if (arg_get_lit(ctx, 4)) { - keyType = 1; + keyType = MF_KEY_B; } bool m0 = arg_get_lit(ctx, 6); @@ -2994,7 +2993,6 @@ static int CmdHF14AMfChk(const char *Cmd) { CLIParserFree(ctx); //validations - if ((m0 + m1 + m2 + m4) > 1) { PrintAndLogEx(WARNING, "Only specify one MIFARE Type"); return PM3_EINVARG; @@ -3136,7 +3134,7 @@ static int CmdHF14AMfChk(const char *Cmd) { return PM3_EMALLOC; } - uint8_t trgKeyType = 0; + uint8_t trgKeyType = MF_KEY_A; uint16_t max_keys = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt; PrintAndLogEx(INFO, "Start check for keys..."); @@ -3188,7 +3186,7 @@ static int CmdHF14AMfChk(const char *Cmd) { PrintAndLogEx(INFO, "\ntime in checkkeys " _YELLOW_("%.0f") " seconds\n", (float)t1 / 1000.0); // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? - if (keyType != 1) { + if (keyType != MF_KEY_B) { PrintAndLogEx(INFO, "testing to read key B..."); // loop sectors but block is used as to keep track of from which blocks to test @@ -3205,7 +3203,7 @@ static int CmdHF14AMfChk(const char *Cmd) { mf_readblock_t payload; payload.blockno = sectrail; - payload.keytype = 0; + payload.keytype = MF_KEY_A; // Use key A num_to_bytes(e_sector[i].Key[0], 6, payload.key); @@ -3312,7 +3310,7 @@ void readerAttack(sector_t *k_sector, uint8_t k_sectorsCount, nonces_t data, boo uint8_t keytype = data.keytype; PrintAndLogEx(INFO, "Reader is trying authenticate with: Key %s, sector %02d: [%012" PRIx64 "]" - , keytype ? "B" : "A" + , (keytype == MF_KEY_B) ? "B" : "A" , sector , key ); @@ -3526,7 +3524,7 @@ static int CmdHF14AMfSim(const char *Cmd) { /* static int CmdHF14AMfKeyBrute(const char *Cmd) { - uint8_t blockNo = 0, keytype = 0; + uint8_t blockNo = 0, keytype = MF_KEY_A; uint8_t key[6] = {0, 0, 0, 0, 0, 0}; uint64_t foundkey = 0; @@ -3538,7 +3536,7 @@ static int CmdHF14AMfKeyBrute(const char *Cmd) { // keytype cmdp = tolower(param_getchar(Cmd, 1)); - if (cmdp == 'b') keytype = 1; + if (cmdp == 'b') keytype = MF_KEY_B; // key if (param_gethex(Cmd, 2, key, 12)) return usage_hf14_keybrute(); @@ -4099,13 +4097,13 @@ static int CmdHF14AMfECFill(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - uint8_t keytype = 0; + uint8_t keytype = MF_KEY_A; if (arg_get_lit(ctx, 1) && arg_get_lit(ctx, 2)) { CLIParserFree(ctx); PrintAndLogEx(WARNING, "Input key type must be A or B"); return PM3_EINVARG; } else if (arg_get_lit(ctx, 2)) { - keytype = 1; + keytype = MF_KEY_B; } bool m0 = arg_get_lit(ctx, 3); @@ -5121,9 +5119,9 @@ static int CmdHF14AMfice(const char *Cmd) { } uint8_t blockNo = 0; - uint8_t keyType = 0; + uint8_t keyType = MF_KEY_A; uint8_t trgBlockNo = 0; - uint8_t trgKeyType = 1; + uint8_t trgKeyType = MF_KEY_B; bool slow = false; bool initialize = true; bool acquisition_completed = false; @@ -5935,9 +5933,9 @@ static int CmdHF14AMfWipe(const char *Cmd) { } // try both A/B keys, start with B key first - for (int8_t kt = 1; kt > -1; kt--) { + for (int8_t kt = MF_KEY_B; kt > -1; kt--) { - if (kt == 0) + if (kt == MF_KEY_A) memcpy(data, keyA + (s * 6), 6); else memcpy(data, keyB + (s * 6), 6); From e2ed63d96bd5581ca25fd5cd2ff1be16f016ee8f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 12 Apr 2021 08:16:11 +0200 Subject: [PATCH 227/373] hf mf hardnested - now uses cliparser --- .../deps/hardnested/hardnested_bruteforce.c | 4 +- client/src/cmdhfmf.c | 363 ++++++++---------- doc/cliparser_todo.txt | 1 - 3 files changed, 168 insertions(+), 200 deletions(-) diff --git a/client/deps/hardnested/hardnested_bruteforce.c b/client/deps/hardnested/hardnested_bruteforce.c index a589040ac..84f34e808 100644 --- a/client/deps/hardnested/hardnested_bruteforce.c +++ b/client/deps/hardnested/hardnested_bruteforce.c @@ -164,7 +164,7 @@ crack_states_thread(void *x) { statelist_t *bucket = buckets[current_bucket]; if (bucket) { #if defined (DEBUG_BRUTE_FORCE) - PrintAndLogEx(INFO, "Thread %u starts working on bucket %u\n", thread_id, current_bucket); + PrintAndLogEx(INFO, "Thread " _YELLOW_("%u") " starts working on bucket " _YELLOW_("%u") "\n", thread_id, current_bucket); #endif const uint64_t key = crack_states_bitsliced(thread_arg->cuid, thread_arg->best_first_bytes, bucket, &keys_found, &num_keys_tested, nonces_to_bruteforce, bf_test_nonce_2nd_byte, thread_arg->nonces); if (key != -1) { @@ -174,7 +174,7 @@ crack_states_thread(void *x) { char progress_text[80]; char keystr[19]; sprintf(keystr, "%012" PRIx64 " ", key); - sprintf(progress_text, "Brute force phase completed. Key found: " _YELLOW_("%s"), keystr); + sprintf(progress_text, "Brute force phase completed. Key found: " _GREEN_("%s"), keystr); hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, 0.0, 0); break; } else if (keys_found) { diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index deec0cf6d..210964417 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -43,43 +43,6 @@ static int CmdHelp(const char *Cmd); -static int usage_hf14_hardnested(void) { - PrintAndLogEx(NORMAL, "Usage:"); - PrintAndLogEx(NORMAL, " hf mf hardnested "); - PrintAndLogEx(NORMAL, " [known target key (12 hex symbols)] [w] [s]"); - PrintAndLogEx(NORMAL, " or hf mf hardnested r [known target key]"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " w acquire nonces and UID, and write them to binary file with default name hf-mf--nonces.bin"); - PrintAndLogEx(NORMAL, " s slower acquisition (required by some non standard cards)"); - PrintAndLogEx(NORMAL, " r read hf-mf--nonces.bin if tag present, otherwise read nonces.bin, then start attack"); - PrintAndLogEx(NORMAL, " u read/write hf-mf--nonces.bin instead of default name"); - PrintAndLogEx(NORMAL, " f read/write instead of default name"); - PrintAndLogEx(NORMAL, " t tests?"); - PrintAndLogEx(NORMAL, " i set type of SIMD instructions. Without this flag programs autodetect it."); -#if defined(COMPILER_HAS_SIMD_AVX512) - PrintAndLogEx(NORMAL, " i 5 = AVX512"); -#endif -#if defined(COMPILER_HAS_SIMD) - PrintAndLogEx(NORMAL, " i 2 = AVX2"); - PrintAndLogEx(NORMAL, " i a = AVX"); - PrintAndLogEx(NORMAL, " i s = SSE2"); - PrintAndLogEx(NORMAL, " i m = MMX"); -#endif - PrintAndLogEx(NORMAL, " i n = none (use CPU regular instruction set)"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf hardnested 0 A FFFFFFFFFFFF 4 A")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf hardnested 0 A FFFFFFFFFFFF 4 A w")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf hardnested 0 A FFFFFFFFFFFF 4 A f nonces.bin w s")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf hardnested r")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf hardnested r a0a1a2a3a4a5")); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Add the known target key to check if it is present in the remaining key space:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf hardnested 0 A A0A1A2A3A4A5 4 A FFFFFFFFFFFF")); - return PM3_SUCCESS; -} static int usage_hf14_autopwn(void) { PrintAndLogEx(NORMAL, "Usage:"); PrintAndLogEx(NORMAL, " hf mf autopwn [k] "); @@ -1148,11 +1111,11 @@ static int CmdHF14AMfNested(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf nested", "Execute Nested attack against MIFARE Classic card for key recovery", - "hf mf nested --single --blk 0 -a FFFFFFFFFFFF --tblk 4 --tkeya --> Single sector key recovery. Use block 0 Key A to find block 4 Key A\n" - "hf mf nested --mini --blk 0 -a -k FFFFFFFFFFFF --> Key recovery against MIFARE Mini\n" - "hf mf nested --1k --blk 0 -a -k FFFFFFFFFFFF --> Key recovery against MIFARE Classic 1k\n" - "hf mf nested --2k --blk 0 -a -k FFFFFFFFFFFF --> Key recovery against MIFARE 2k\n" - "hf mf nested --4k --blk 0 -a -k FFFFFFFFFFFF --> Key recovery against MIFARE 4k"); + "hf mf nested --single --blk 0 -a FFFFFFFFFFFF --tblk 4 --ta --> Single sector key recovery. Use block 0 Key A to find block 4 Key A\n" + "hf mf nested --mini --blk 0 -a -k FFFFFFFFFFFF --> Key recovery against MIFARE Mini\n" + "hf mf nested --1k --blk 0 -a -k FFFFFFFFFFFF --> Key recovery against MIFARE Classic 1k\n" + "hf mf nested --2k --blk 0 -a -k FFFFFFFFFFFF --> Key recovery against MIFARE 2k\n" + "hf mf nested --4k --blk 0 -a -k FFFFFFFFFFFF --> Key recovery against MIFARE 4k"); void *argtable[] = { arg_param_begin, @@ -1165,8 +1128,8 @@ static int CmdHF14AMfNested(const char *Cmd) { arg_lit0("a", NULL, "Input key specified is A key (default)"), arg_lit0("b", NULL, "Input key specified is B key"), arg_int0(NULL, "tblk", "", "Target block number"), - arg_lit0(NULL, "tkeya", "Target A key (default)"), - arg_lit0(NULL, "tkeyb", "Target B key"), + arg_lit0(NULL, "ta", "Target A key (default)"), + arg_lit0(NULL, "tb", "Target B key"), arg_lit0(NULL, "emu", "Fill simulator keys from found keys"), arg_lit0(NULL, "dump", "Dump found keys to file"), arg_lit0(NULL, "single", "Single sector (defaults to All)"), @@ -1701,157 +1664,163 @@ jumptoend: } static int CmdHF14AMfNestedHard(const char *Cmd) { - uint8_t blockNo = 0; - uint8_t keyType = MF_KEY_A; - uint8_t trgBlockNo = 0; - uint8_t trgKeyType = MF_KEY_A; - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - uint8_t trgkey[6] = {0, 0, 0, 0, 0, 0}; - uint8_t cmdp = 0; - char filename[FILE_PATH_SIZE] = {0}; - char szTemp[FILE_PATH_SIZE - 20]; - char ctmp; - bool know_target_key = false; - bool nonce_file_read = false; - bool nonce_file_write = false; - bool slow = false; - int tests = 0; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf hardnested", + "Nested attack for hardened MIFARE Classic cards.\n" + "`--i` set type of SIMD instructions. Without this flag programs autodetect it.\n" + " or \n" + " hf mf hardnested -r --tk [known target key]\n" + "Add the known target key to check if it is present in the remaining key space\n" + " hf mf hardnested --blk 0 -a -k A0A1A2A3A4A5 --tblk 4 --ta --tk FFFFFFFFFFFF\n" + , + "hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 4 --ta\n" + "hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 4 --ta -w\n" + "hf mf hardnested --blk 0 -a -k FFFFFFFFFFFF --tblk 4 --ta -f nonces.bin -w -s\n" + "hf mf hardnested -r\n" + "hf mf hardnested -r --tk a0a1a2a3a4a5\n" + "hf mf hardnested -t --tk a0a1a2a3a4a5\n" + "hf mf hardnested --blk 0 -a -k a0a1a2a3a4a5 --tblk 4 --ta --tk FFFFFFFFFFFF" + ); - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf14_hardnested(); - case 'r': { - char *fptr = GenerateFilename("hf-mf-", "-nonces.bin"); - if (fptr == NULL) - strncpy(filename, "nonces.bin", FILE_PATH_SIZE - 1); - else - strncpy(filename, fptr, FILE_PATH_SIZE - 1); + void *argtable[] = { + arg_param_begin, + arg_str0("k", "key", "", "Key, 12 hex bytes"), // 1 + arg_int0(NULL, "blk", "", "Input block number"), // 2 + arg_lit0("a", NULL, "Input key A (def)"), // 3 + arg_lit0("b", NULL, "Input key B"), + arg_int0(NULL, "tblk", "", "Target block number"), + arg_lit0(NULL, "ta", "Target key A"), + arg_lit0(NULL, "tb", "Target key B"), + arg_str0(NULL, "tk", "", "Target key, 12 hex bytes"), // 8 + arg_str0("u", "uid", "", "R/W `hf-mf--nonces.bin` instead of default name"), + arg_str0("f", "file", "", "R/W instead of default name"), + arg_lit0("r", "read", "Read `hf-mf--nonces.bin` if tag present, otherwise `nonces.bin`, and start attack"), + arg_lit0("s", "slow", "Slower acquisition (required by some non standard cards)"), + arg_lit0("t", "tests", "Run tests"), + arg_lit0("w", "wr", "Acquire nonces and UID, and write them to file `hf-mf--nonces.bin`"), - free(fptr); - nonce_file_read = true; - if (!param_gethex(Cmd, cmdp + 1, trgkey, 12)) { - know_target_key = true; - } - cmdp++; - break; - } - case 't': - tests = param_get32ex(Cmd, cmdp + 1, 100, 10); - if (!param_gethex(Cmd, cmdp + 2, trgkey, 12)) { - know_target_key = true; - } - cmdp += 2; - break; - default: - if (param_getchar(Cmd, cmdp) == 0x00) { - PrintAndLogEx(WARNING, "Block number is missing"); - return usage_hf14_hardnested(); - } - - blockNo = param_get8(Cmd, cmdp); - ctmp = tolower(param_getchar(Cmd, cmdp + 1)); - if (ctmp != 'a' && ctmp != 'b') { - PrintAndLogEx(WARNING, "Key type must be A or B"); - return 1; - } - - if (ctmp != 'a') { - keyType = MF_KEY_B; - } - - if (param_gethex(Cmd, cmdp + 2, key, 12)) { - PrintAndLogEx(WARNING, "Key must include 12 HEX symbols"); - return 1; - } - - if (param_getchar(Cmd, cmdp + 3) == 0x00) { - PrintAndLogEx(WARNING, "Target block number is missing"); - return 1; - } - - trgBlockNo = param_get8(Cmd, cmdp + 3); - - ctmp = tolower(param_getchar(Cmd, cmdp + 4)); - if (ctmp != 'a' && ctmp != 'b') { - PrintAndLogEx(WARNING, "Target key type must be A or B"); - return 1; - } - if (ctmp != 'a') { - trgKeyType = MF_KEY_B; - } - cmdp += 5; - } - if (!param_gethex(Cmd, cmdp, trgkey, 12)) { - know_target_key = true; - cmdp++; - } - - while ((ctmp = param_getchar(Cmd, cmdp))) { - switch (tolower(ctmp)) { - case 's': - slow = true; - break; - case 'w': { - nonce_file_write = true; - char *fptr = GenerateFilename("hf-mf-", "-nonces.bin"); - if (fptr == NULL) - return 1; - strncpy(filename, fptr, FILE_PATH_SIZE - 1); - free(fptr); - break; - } - case 'u': - param_getstr(Cmd, cmdp + 1, szTemp, FILE_PATH_SIZE - 20); - snprintf(filename, FILE_PATH_SIZE, "hf-mf-%s-nonces.bin", szTemp); - cmdp++; - break; - case 'f': - param_getstr(Cmd, cmdp + 1, szTemp, FILE_PATH_SIZE - 20); - strncpy(filename, szTemp, FILE_PATH_SIZE - 20); - cmdp++; - break; - case 'i': - SetSIMDInstr(SIMD_AUTO); - ctmp = tolower(param_getchar(Cmd, cmdp + 1)); - switch (ctmp) { -#if defined(COMPILER_HAS_SIMD_AVX512) - case '5': - SetSIMDInstr(SIMD_AVX512); - break; -#endif + arg_lit0(NULL, "in", "None (use CPU regular instruction set)"), #if defined(COMPILER_HAS_SIMD) - case '2': - SetSIMDInstr(SIMD_AVX2); - break; - case 'a': - SetSIMDInstr(SIMD_AVX); - break; - case 's': - SetSIMDInstr(SIMD_SSE2); - break; - case 'm': - SetSIMDInstr(SIMD_MMX); - break; + arg_lit0(NULL, "im", "MMX"), + arg_lit0(NULL, "is", "SSE2"), + arg_lit0(NULL, "ia", "AVX"), + arg_lit0(NULL, "i2", "AVX2"), #endif - case 'n': - SetSIMDInstr(SIMD_NONE); - break; - default: - PrintAndLogEx(WARNING, "Unknown SIMD type. %c", ctmp); - return 1; - } - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", ctmp); - usage_hf14_hardnested(); - return 1; - } - cmdp++; +#if defined(COMPILER_HAS_SIMD_AVX512) + arg_lit0(NULL, "i5", "AVX512"), +#endif + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + int keylen = 0; + uint8_t key[6] = {0}; + CLIGetHexWithReturn(ctx, 1, key, &keylen); + + uint8_t blockno = arg_get_u32_def(ctx, 2, 0); + + uint8_t keytype = MF_KEY_A; + if (arg_get_lit(ctx, 3) && arg_get_lit(ctx, 4)) { + CLIParserFree(ctx); + PrintAndLogEx(WARNING, "Input key type must be A or B"); + return PM3_EINVARG; + } else if (arg_get_lit(ctx, 4)) { + keytype = MF_KEY_B; } - if (!know_target_key && nonce_file_read == false) { + uint8_t trg_blockno = arg_get_u32_def(ctx, 5, 0); + + uint8_t trg_keytype = MF_KEY_A; + if (arg_get_lit(ctx, 6) && arg_get_lit(ctx, 7)) { + CLIParserFree(ctx); + PrintAndLogEx(WARNING, "Input key type must be A or B"); + return PM3_EINVARG; + } else if (arg_get_lit(ctx, 7)) { + trg_keytype = MF_KEY_B; + } + + int trg_keylen = 0; + uint8_t trg_key[6] = {0}; + CLIGetHexWithReturn(ctx, 8, trg_key, &trg_keylen); + + int uidlen = 0; + char uid[14] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 9), (uint8_t *)uid, sizeof(uid), &uidlen); + + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 10), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + + bool nonce_file_read = arg_get_lit(ctx, 11); + bool slow = arg_get_lit(ctx, 12); + bool tests = arg_get_lit(ctx, 13); + bool nonce_file_write = arg_get_lit(ctx, 14); + + bool in = arg_get_lit(ctx, 15); + bool im = false; + bool is = false; + bool ia = false; + bool i2 = false; + bool i5 = false; + +#if defined(COMPILER_HAS_SIMD) + im = arg_get_lit(ctx, 16); + is = arg_get_lit(ctx, 17); + ia = arg_get_lit(ctx, 18); + i2 = arg_get_lit(ctx, 19); +#endif +#if defined(COMPILER_HAS_SIMD_AVX512) + i5 = arg_get_lit(ctx, 20); +#endif + CLIParserFree(ctx); + + // set SIM instructions + SetSIMDInstr(SIMD_AUTO); + +#if defined(COMPILER_HAS_SIMD_AVX512) + if (i5) + SetSIMDInstr(SIMD_AVX512); +#endif + +#if defined(COMPILER_HAS_SIMD) + if (i2) + SetSIMDInstr(SIMD_AVX2); + if (ia) + SetSIMDInstr(SIMD_AVX); + if (is) + SetSIMDInstr(SIMD_SSE2); + if (im) + SetSIMDInstr(SIMD_MMX); +#endif + if (in) + SetSIMDInstr(SIMD_NONE); + + + bool know_target_key = (trg_keylen); + + if (nonce_file_read) { + char *fptr = GenerateFilename("hf-mf-", "-nonces.bin"); + if (fptr == NULL) + strncpy(filename, "nonces.bin", FILE_PATH_SIZE - 1); + else + strncpy(filename, fptr, FILE_PATH_SIZE - 1); + free(fptr); + } + + if (nonce_file_write) { + char *fptr = GenerateFilename("hf-mf-", "-nonces.bin"); + if (fptr == NULL) + return 1; + strncpy(filename, fptr, FILE_PATH_SIZE - 1); + free(fptr); + } + + if (uidlen) { + snprintf(filename, FILE_PATH_SIZE, "hf-mf-%s-nonces.bin", uid); + } + + if (know_target_key == false && nonce_file_read == false) { // check if tag doesn't have static nonce if (detect_classic_static_nonce() == NONCE_STATIC) { @@ -1862,25 +1831,25 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { uint64_t key64 = 0; // check if we can authenticate to sector - if (mfCheckKeys(blockNo, keyType, true, 1, key, &key64) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "Key is wrong. Can't authenticate to block: %3d key type: %c", blockNo, (keyType == MF_KEY_B) ? 'B' : 'A'); - return 3; + if (mfCheckKeys(blockno, keytype, true, 1, key, &key64) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "Key is wrong. Can't authenticate to block: %3d key type: %c", blockno, (keytype == MF_KEY_B) ? 'B' : 'A'); + return PM3_EWRONGANSWER; } } - PrintAndLogEx(INFO, "Target block no:%3d, target key type:%c, known target key: 0x%02x%02x%02x%02x%02x%02x%s", - trgBlockNo, - (trgKeyType == MF_KEY_B)? 'B' : 'A', - trgkey[0], trgkey[1], trgkey[2], trgkey[3], trgkey[4], trgkey[5], + PrintAndLogEx(INFO, "Target block no " _YELLOW_("%3d") ", target key type: " _YELLOW_("%c") ", known target key: " _YELLOW_("%02x%02x%02x%02x%02x%02x%s"), + trg_blockno, + (trg_keytype == MF_KEY_B)? 'B' : 'A', + trg_key[0], trg_key[1], trg_key[2], trg_key[3], trg_key[4], trg_key[5], know_target_key ? "" : " (not set)" ); - PrintAndLogEx(INFO, "File action: %s, Slow: %s, Tests: %d ", + PrintAndLogEx(INFO, "File action: " _YELLOW_("%s") ", Slow: " _YELLOW_("%s") ", Tests: " _YELLOW_("%d"), nonce_file_write ? "write" : nonce_file_read ? "read" : "none", slow ? "Yes" : "No", tests); uint64_t foundkey = 0; - int16_t isOK = mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType, know_target_key ? trgkey : NULL, nonce_file_read, nonce_file_write, slow, tests, &foundkey, filename); + int16_t isOK = mfnestedhard(blockno, keytype, key, trg_blockno, trg_keytype, know_target_key ? trg_key : NULL, nonce_file_read, nonce_file_write, slow, tests, &foundkey, filename); if ((tests == 0) && IfPm3Iso14443a()) { DropField(); diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 55b00cc75..dfb321a00 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -16,7 +16,6 @@ hf felica auth1 hf felica auth2 hf felica rqspecver hf felica resetmode -hf mf hardnested hf mf autopwn lf hitag reader lf hitag writer From b59e469d47f44232f12f30409a2b839dbbde58e9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 12 Apr 2021 10:02:47 +0200 Subject: [PATCH 228/373] hf mf autopwn - now use cliparser --- client/src/cmdhfmf.c | 512 +++++++++++++++++++---------------------- doc/cliparser_todo.txt | 1 - 2 files changed, 236 insertions(+), 277 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 210964417..13dcf5557 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -43,48 +43,6 @@ static int CmdHelp(const char *Cmd); -static int usage_hf14_autopwn(void) { - PrintAndLogEx(NORMAL, "Usage:"); - PrintAndLogEx(NORMAL, " hf mf autopwn [k] "); - PrintAndLogEx(NORMAL, " [* ] [f [.dic]] [s] [i ] [l] [v]"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Description:"); - PrintAndLogEx(NORMAL, " This command automates the key recovery process on MIFARE Classic cards."); - PrintAndLogEx(NORMAL, " It uses the darkside, nested, hardnested and staticnested to recover keys."); - PrintAndLogEx(NORMAL, " If all keys are found, try dumping card content."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " k known key is supplied"); - PrintAndLogEx(NORMAL, " f [.dic] key dictionary file"); - PrintAndLogEx(NORMAL, " s slower acquisition for hardnested (required by some non standard cards)"); - PrintAndLogEx(NORMAL, " v verbose output (statistics)"); - PrintAndLogEx(NORMAL, " l legacy mode (use the slow 'mf chk' for the key enumeration)"); - PrintAndLogEx(NORMAL, " * all sectors based on card memory"); - PrintAndLogEx(NORMAL, " * 0 = MINI(320 bytes)"); - PrintAndLogEx(NORMAL, " * 1 = 1k (default)"); - PrintAndLogEx(NORMAL, " * 2 = 2k"); - PrintAndLogEx(NORMAL, " * 4 = 4k"); - PrintAndLogEx(NORMAL, " i set type of SIMD instructions for hardnested. Default: autodetection."); -#if defined(COMPILER_HAS_SIMD_AVX512) - PrintAndLogEx(NORMAL, " i 5 = AVX512"); -#endif -#if defined(COMPILER_HAS_SIMD) - PrintAndLogEx(NORMAL, " i 2 = AVX2"); - PrintAndLogEx(NORMAL, " i a = AVX"); - PrintAndLogEx(NORMAL, " i s = SSE2"); -#endif - PrintAndLogEx(NORMAL, " i m = MMX"); - PrintAndLogEx(NORMAL, " i n = none (use CPU regular instruction set)"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf autopwn")" -- target MIFARE Classic card with default keys"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf autopwn * 1 f mfc_default_keys")" -- target MIFARE Classic card (size 1k) with default dictionary"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf autopwn k 0 A FFFFFFFFFFFF")" -- target MIFARE Classic card with Sector0 typeA with known key 'FFFFFFFFFFFF'"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf autopwn k 0 A FFFFFFFFFFFF * 1 f mfc_default_keys")" -- this command combines the two above (reduce the need for nested / hardnested attacks, by using a dictionary)"); - return PM3_SUCCESS; -} - /* static int usage_hf14_keybrute(void) { PrintAndLogEx(NORMAL, "J_Run's 2nd phase of multiple sector nested authentication key recovery"); @@ -222,21 +180,6 @@ static void decode_print_st(uint16_t blockno, uint8_t *data) { } } -static uint16_t NumOfBlocks(char card) { - switch (card) { - case '0' : - return MIFARE_MINI_MAXBLOCK; - case '1' : - return MIFARE_1K_MAXBLOCK; - case '2' : - return MIFARE_2K_MAXBLOCK; - case '4' : - return MIFARE_4K_MAXBLOCK; - default : - return 0; - } -} - static uint8_t NumOfSectors(char card) { switch (card) { case '0' : @@ -1758,20 +1701,14 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { bool nonce_file_write = arg_get_lit(ctx, 14); bool in = arg_get_lit(ctx, 15); - bool im = false; - bool is = false; - bool ia = false; - bool i2 = false; - bool i5 = false; - #if defined(COMPILER_HAS_SIMD) - im = arg_get_lit(ctx, 16); - is = arg_get_lit(ctx, 17); - ia = arg_get_lit(ctx, 18); - i2 = arg_get_lit(ctx, 19); + bool im = arg_get_lit(ctx, 16); + bool is = arg_get_lit(ctx, 17); + bool ia = arg_get_lit(ctx, 18); + bool i2 = arg_get_lit(ctx, 19); #endif #if defined(COMPILER_HAS_SIMD_AVX512) - i5 = arg_get_lit(ctx, 20); + bool i5 = arg_get_lit(ctx, 20); #endif CLIParserFree(ctx); @@ -1872,149 +1809,173 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { } static int CmdHF14AMfAutoPWN(const char *Cmd) { - // Nested and Hardnested parameter - uint8_t blockNo = 0; - uint8_t keyType = MF_KEY_A; + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mf autopwn", + "This command automates the key recovery process on MIFARE Classic cards.\n" + "It uses the fchk, chk, darkside, nested, hardnested and staticnested to recover keys.\n" + "If all keys are found, it try dumping card content both to file and emulator memory.", + "hf mf autopwn\n" + "hf mf autopwn -s 0 -a -k FFFFFFFFFFFF --> target MFC 1K card, Sector 0 with known key A 'FFFFFFFFFFFF'\n" + "hf mf autopwn --1k -f mfc_default_keys --> target MFC 1K card, default dictionary\n" + "hf mf autopwn --1k -s 0 -a -k FFFFFFFFFFFF -f mfc_default_keys --> combo of the two above samples" + ); + + void *argtable[] = { + arg_param_begin, + arg_str0("k", "key", "", "Known key, 12 hex bytes"), + arg_int0("s", "sector", "", "Input sector number"), + arg_lit0("a", NULL, "Input key A (def)"), + arg_lit0("b", NULL, "Input key B"), + arg_str0("f", "file", "", "filename of dictionary"), + arg_lit0("s", "slow", "Slower acquisition (required by some non standard cards)"), + arg_lit0("l", "legacy", "legacy mode (use the slow `hf mf chk`)"), + arg_lit0("v", "verbose", "verbose output (statistics)"), + + arg_lit0(NULL, "mini", "MIFARE Classic Mini / S20"), + arg_lit0(NULL, "1k", "MIFARE Classic 1k / S50 (default)"), + arg_lit0(NULL, "2k", "MIFARE Classic/Plus 2k"), + arg_lit0(NULL, "4k", "MIFARE Classic 4k / S70"), + + arg_lit0(NULL, "in", "None (use CPU regular instruction set)"), +#if defined(COMPILER_HAS_SIMD) + arg_lit0(NULL, "im", "MMX"), + arg_lit0(NULL, "is", "SSE2"), + arg_lit0(NULL, "ia", "AVX"), + arg_lit0(NULL, "i2", "AVX2"), +#endif +#if defined(COMPILER_HAS_SIMD_AVX512) + arg_lit0(NULL, "i5", "AVX512"), +#endif + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int keylen = 0; uint8_t key[6] = {0}; + int32_t res = CLIParamHexToBuf(arg_get_str(ctx, 1), key, sizeof(key), &keylen); + if (res) { + CLIParserFree(ctx); + PrintAndLogEx(FAILED, "Error parsing key bytes"); + return PM3_EINVARG; + } + + bool know_target_key = (keylen == 6); + + uint8_t sectorno = arg_get_u32_def(ctx, 2, 0); + + uint8_t keytype = MF_KEY_A; + if (arg_get_lit(ctx, 3) && arg_get_lit(ctx, 4)) { + CLIParserFree(ctx); + PrintAndLogEx(WARNING, "Input key type must be A or B"); + return PM3_EINVARG; + } else if (arg_get_lit(ctx, 4)) { + keytype = MF_KEY_B; + } + + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + bool has_filename = (fnlen > 0); + + bool slow = arg_get_lit(ctx, 6); + bool legacy_mfchk = arg_get_lit(ctx, 7); + bool verbose = arg_get_lit(ctx, 8); + + bool m0 = arg_get_lit(ctx, 9); + bool m1 = arg_get_lit(ctx, 10); + bool m2 = arg_get_lit(ctx, 11); + bool m4 = arg_get_lit(ctx, 12); + + bool in = arg_get_lit(ctx, 13); +#if defined(COMPILER_HAS_SIMD) + bool im = arg_get_lit(ctx, 14); + bool is = arg_get_lit(ctx, 15); + bool ia = arg_get_lit(ctx, 16); + bool i2 = arg_get_lit(ctx, 17); +#endif +#if defined(COMPILER_HAS_SIMD_AVX512) + bool i5 = arg_get_lit(ctx, 18); +#endif + CLIParserFree(ctx); + + //validations + if ((m0 + m1 + m2 + m4) > 1) { + PrintAndLogEx(WARNING, "Only specify one MIFARE Type"); + return PM3_EINVARG; + } else if ((m0 + m1 + m2 + m4) == 0) { + m1 = true; + } + + uint8_t sector_cnt = MIFARE_1K_MAXSECTOR; + uint16_t block_cnt = MIFARE_1K_MAXBLOCK; + + if (m0) { + sector_cnt = MIFARE_MINI_MAXSECTOR; + block_cnt = MIFARE_MINI_MAXBLOCK; + } else if (m1) { + sector_cnt = MIFARE_1K_MAXSECTOR; + block_cnt = MIFARE_1K_MAXBLOCK; + } else if (m2) { + sector_cnt = MIFARE_2K_MAXSECTOR; + block_cnt = MIFARE_2K_MAXBLOCK; + } else if (m4) { + sector_cnt = MIFARE_4K_MAXSECTOR; + block_cnt = MIFARE_4K_MAXBLOCK; + } else { + PrintAndLogEx(WARNING, "Please specify a MIFARE Type"); + return PM3_EINVARG; + } + + + // set SIM instructions + SetSIMDInstr(SIMD_AUTO); + +#if defined(COMPILER_HAS_SIMD_AVX512) + if (i5) + SetSIMDInstr(SIMD_AVX512); +#endif + +#if defined(COMPILER_HAS_SIMD) + if (i2) + SetSIMDInstr(SIMD_AVX2); + if (ia) + SetSIMDInstr(SIMD_AVX); + if (is) + SetSIMDInstr(SIMD_SSE2); + if (im) + SetSIMDInstr(SIMD_MMX); +#endif + if (in) + SetSIMDInstr(SIMD_NONE); + + + // Nested and Hardnested parameter uint64_t key64 = 0; bool calibrate = true; // Attack key storage variables uint8_t *keyBlock = NULL; uint32_t key_cnt = 0; sector_t *e_sector; - uint8_t sectors_cnt = MIFARE_1K_MAXSECTOR; - int block_cnt = MIFARE_1K_MAXBLOCK; uint8_t tmp_key[6] = {0}; - bool know_target_key = false; - // For the timer - uint64_t t1; - // Parameters and dictionary file - char filename[FILE_PATH_SIZE] = {0}; - uint8_t cmdp = 0; - char ctmp; + // Nested and Hardnested returned status uint64_t foundkey = 0; int isOK = 0; int current_sector_i = 0, current_key_type_i = 0; // Dumping and transfere to simulater memory uint8_t block[16] = {0x00}; - uint8_t *dump; int bytes; // Settings - bool slow = false; - bool legacy_mfchk = false; int prng_type = PM3_EUNDEF; int has_staticnonce; - bool verbose = false; - bool has_filename = false; - bool errors = false; uint8_t num_found_keys = 0; - // Parse the options given by the user - while ((ctmp = param_getchar(Cmd, cmdp)) && !errors) { - switch (tolower(ctmp)) { - case 'h': - return usage_hf14_autopwn(); - case 'f': - if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { - PrintAndLogEx(FAILED, "Filename too long"); - errors = true; - } else { - has_filename = true; - } - cmdp += 2; - break; - case 'l': - legacy_mfchk = true; - cmdp++; - break; - case 'v': - verbose = true; - cmdp++; - break; - case '*': - // Get the number of sectors - sectors_cnt = NumOfSectors(param_getchar(Cmd, cmdp + 1)); - block_cnt = NumOfBlocks(param_getchar(Cmd, cmdp + 1)); - cmdp += 2; - break; - case 'k': - // Get the known block number - if (param_getchar(Cmd, cmdp + 1) == 0x00) { - errors = true; - break; - } - - blockNo = param_get8(Cmd, cmdp + 1); - - // Get the knonwn block type - ctmp = tolower(param_getchar(Cmd, cmdp + 2)); - if (ctmp != 'a' && ctmp != 'b') { - PrintAndLogEx(WARNING, "Key type must be A or B"); - errors = true; - break; - } - - if (ctmp != 'a') { - keyType = MF_KEY_B; - } - - // Get the known block key - if (param_gethex(Cmd, cmdp + 3, key, 12)) { - PrintAndLogEx(WARNING, "Key must include 12 HEX symbols"); - errors = true; - } - know_target_key = true; - cmdp += 3; - case 's': - slow = true; - cmdp++; - break; - case 'i': - SetSIMDInstr(SIMD_AUTO); - ctmp = tolower(param_getchar(Cmd, cmdp + 1)); - switch (ctmp) { -#if defined(COMPILER_HAS_SIMD_AVX512) - case '5': - SetSIMDInstr(SIMD_AVX512); - break; -#endif -#if defined(COMPILER_HAS_SIMD) - case '2': - SetSIMDInstr(SIMD_AVX2); - break; - case 'a': - SetSIMDInstr(SIMD_AVX); - break; - case 's': - SetSIMDInstr(SIMD_SSE2); - break; - case 'm': - SetSIMDInstr(SIMD_MMX); - break; -#endif - case 'n': - SetSIMDInstr(SIMD_NONE); - break; - default: - PrintAndLogEx(WARNING, "Unknown SIMD type. %c", ctmp); - return PM3_EINVARG; - } - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", ctmp); - return usage_hf14_autopwn(); - } - } - - if (errors) { - return usage_hf14_autopwn(); - } +// ------------------------------ // create/initialize key storage structure - int32_t res = initSectorTable(&e_sector, sectors_cnt); - if (res != sectors_cnt) { + res = initSectorTable(&e_sector, sector_cnt); + if (res != sector_cnt) { free(e_sector); return PM3_EMALLOC; } @@ -2039,10 +2000,10 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { // print parameters if (verbose) { PrintAndLogEx(INFO, "======================= " _YELLOW_("SETTINGS") " ======================="); - PrintAndLogEx(INFO, " card sectors .. " _YELLOW_("%d"), sectors_cnt); + PrintAndLogEx(INFO, " card sectors .. " _YELLOW_("%d"), sector_cnt); PrintAndLogEx(INFO, " key supplied .. " _YELLOW_("%s"), know_target_key ? "True" : "False"); - PrintAndLogEx(INFO, " known sector .. " _YELLOW_("%d"), blockNo); - PrintAndLogEx(INFO, " keytype ....... " _YELLOW_("%c"), (keyType == MF_KEY_B) ? 'B' : 'A'); + PrintAndLogEx(INFO, " known sector .. " _YELLOW_("%d"), sectorno); + PrintAndLogEx(INFO, " keytype ....... " _YELLOW_("%c"), (keytype == MF_KEY_B) ? 'B' : 'A'); PrintAndLogEx(INFO, " known key ..... " _YELLOW_("%s"), sprint_hex(key, sizeof(key))); if (has_staticnonce == NONCE_STATIC) @@ -2059,7 +2020,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { } // Start the timer - t1 = msclock(); + uint64_t t1 = msclock(); // check the user supplied key if (know_target_key == false) { @@ -2069,30 +2030,30 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { PrintAndLogEx(INFO, "======================= " _YELLOW_("START KNOWN KEY ATTACK") " ======================="); } - if (mfCheckKeys(FirstBlockOfSector(blockNo), keyType, true, 1, key, &key64) == PM3_SUCCESS) { - PrintAndLogEx(INFO, "target sector:%3u key type: %c -- using valid key [ " _GREEN_("%s") "] (used for nested / hardnested attack)", - blockNo, - (keyType == MF_KEY_B) ? 'B' : 'A', + if (mfCheckKeys(FirstBlockOfSector(sectorno), keytype, true, 1, key, &key64) == PM3_SUCCESS) { + PrintAndLogEx(INFO, "target sector %3u key type %c -- using valid key [ " _GREEN_("%s") "] (used for nested / hardnested attack)", + sectorno, + (keytype == MF_KEY_B) ? 'B' : 'A', sprint_hex(key, sizeof(key)) ); // Store the key for the nested / hardnested attack (if supplied by the user) - e_sector[blockNo].Key[keyType] = key64; - e_sector[blockNo].foundKey[keyType] = 'U'; + e_sector[sectorno].Key[keytype] = key64; + e_sector[sectorno].foundKey[keytype] = 'U'; ++num_found_keys; } else { know_target_key = false; - PrintAndLogEx(FAILED, "Key is wrong. Can't authenticate to sector:"_RED_("%3d") " key type: "_RED_("%c") " key: " _RED_("%s"), - blockNo, - (keyType == MF_KEY_B) ? 'B' : 'A', + PrintAndLogEx(FAILED, "Key is wrong. Can't authenticate to sector"_RED_("%3d") " key type "_RED_("%c") " key " _RED_("%s"), + sectorno, + (keytype == MF_KEY_B) ? 'B' : 'A', sprint_hex(key, sizeof(key)) ); PrintAndLogEx(WARNING, "falling back to dictionary"); } // Check if the user supplied key is used by other sectors - for (int i = 0; i < sectors_cnt; i++) { + for (int i = 0; i < sector_cnt; i++) { for (int j = MF_KEY_A; j <= MF_KEY_B; j++) { if (e_sector[i].foundKey[j] == 0) { if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, key, &key64) == PM3_SUCCESS) { @@ -2103,18 +2064,18 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { if (know_target_key == false) { num_to_bytes(e_sector[i].Key[j], 6, key); know_target_key = true; - blockNo = i; - keyType = j; - PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%s") "] (used for nested / hardnested attack)", + sectorno = i; + keytype = j; + PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ] (used for nested / hardnested attack)", i, - j ? 'B' : 'A', - sprint_hex(key, sizeof(key)) + (j == MF_KEY_B) ? 'B' : 'A', + sprint_hex_inrow(key, sizeof(key)) ); } else { - PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%s") "]", + PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]", i, - j ? 'B' : 'A', - sprint_hex(key, sizeof(key)) + (j == MF_KEY_B) ? 'B' : 'A', + sprint_hex_inrow(key, sizeof(key)) ); } ++num_found_keys; @@ -2123,7 +2084,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { } } - if (num_found_keys == sectors_cnt * 2) { + if (num_found_keys == sector_cnt * 2) { goto all_found; } } @@ -2162,7 +2123,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { if (legacy_mfchk) { PrintAndLogEx(INFO, "." NOLF); // Check all the sectors - for (int i = 0; i < sectors_cnt; i++) { + for (int i = 0; i < sector_cnt; i++) { for (int j = 0; j < 2; j++) { // Check if the key is known if (e_sector[i].foundKey[j] == 0) { @@ -2202,7 +2163,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { if (size == key_cnt - i) lastChunk = true; - res = mfCheckKeys_fast(sectors_cnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector, false); + res = mfCheckKeys_fast(sector_cnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector, false); if (firstChunk) firstChunk = false; // all keys, aborted @@ -2218,7 +2179,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { } // Analyse the dictionary attack - for (int i = 0; i < sectors_cnt; i++) { + for (int i = 0; i < sector_cnt; i++) { for (int j = MF_KEY_A; j <= MF_KEY_B; j++) { if (e_sector[i].foundKey[j] == 1) { e_sector[i].foundKey[j] = 'D'; @@ -2228,18 +2189,18 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { if (know_target_key == false) { num_to_bytes(e_sector[i].Key[j], 6, key); know_target_key = true; - blockNo = i; - keyType = j; - PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%s") "] (used for nested / hardnested attack)", + sectorno = i; + keytype = j; + PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ] (used for nested / hardnested attack)", i, - j ? 'B' : 'A', - sprint_hex(tmp_key, sizeof(tmp_key)) + (j == MF_KEY_B) ? 'B' : 'A', + sprint_hex_inrow(tmp_key, sizeof(tmp_key)) ); } else { - PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%s") "]", + PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]", i, - j ? 'B' : 'A', - sprint_hex(tmp_key, sizeof(tmp_key)) + (j == MF_KEY_B)? 'B' : 'A', + sprint_hex_inrow(tmp_key, sizeof(tmp_key)) ); } } @@ -2253,7 +2214,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { if (verbose) { PrintAndLogEx(INFO, "======================= " _YELLOW_("START DARKSIDE ATTACK") " ======================="); } - isOK = mfDarkside(FirstBlockOfSector(blockNo), keyType + 0x60, &key64); + isOK = mfDarkside(FirstBlockOfSector(sectorno), keytype + 0x60, &key64); switch (isOK) { case -1 : @@ -2273,17 +2234,17 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { PrintAndLogEx(WARNING, "\nAborted via keyboard."); goto noValidKeyFound; default : - PrintAndLogEx(SUCCESS, "\nFound valid key: [ " _GREEN_("%012" PRIx64) " ]\n", key64); + PrintAndLogEx(SUCCESS, "\nFound valid key [ " _GREEN_("%012" PRIx64) " ]\n", key64); break; } // Store the keys num_to_bytes(key64, 6, key); - e_sector[blockNo].Key[keyType] = key64; - e_sector[blockNo].foundKey[keyType] = 'S'; - PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%012" PRIx64) " ] (used for nested / hardnested attack)", - blockNo, - (keyType == MF_KEY_B) ? 'B' : 'A', + e_sector[sectorno].Key[keytype] = key64; + e_sector[sectorno].foundKey[keytype] = 'S'; + PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%012" PRIx64) " ] (used for nested / hardnested attack)", + sectorno, + (keytype == MF_KEY_B) ? 'B' : 'A', key64 ); } else { @@ -2302,7 +2263,7 @@ noValidKeyFound: bool nested_failed = false; // Iterate over each sector and key(A/B) - for (current_sector_i = 0; current_sector_i < sectors_cnt; current_sector_i++) { + for (current_sector_i = 0; current_sector_i < sector_cnt; current_sector_i++) { for (current_key_type_i = 0; current_key_type_i < 2; current_key_type_i++) { // If the key is already known, just skip it @@ -2310,10 +2271,10 @@ noValidKeyFound: // Try the found keys are reused if (bytes_to_num(tmp_key, 6) != 0) { - // The fast check --> mfCheckKeys_fast(sectors_cnt, true, true, 2, 1, tmp_key, e_sector, false); + // The fast check --> mfCheckKeys_fast(sector_cnt, true, true, 2, 1, tmp_key, e_sector, false); // Returns false keys, so we just stick to the slower mfchk. - for (int i = 0; i < sectors_cnt; i++) { - for (int j = 0; j < 2; j++) { + for (int i = 0; i < sector_cnt; i++) { + for (int j = MF_KEY_A; j <= MF_KEY_B; j++) { // Check if the sector key is already broken if (e_sector[i].foundKey[j]) continue; @@ -2322,10 +2283,10 @@ noValidKeyFound: if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, tmp_key, &key64) == PM3_SUCCESS) { e_sector[i].Key[j] = bytes_to_num(tmp_key, 6); e_sector[i].foundKey[j] = 'R'; - PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%s") "]", + PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]", i, - j ? 'B' : 'A', - sprint_hex(tmp_key, sizeof(tmp_key)) + (j == MF_KEY_B) ? 'B' : 'A', + sprint_hex_inrow(tmp_key, sizeof(tmp_key)) ); } } @@ -2334,13 +2295,13 @@ noValidKeyFound: // Clear the last found key num_to_bytes(0, 6, tmp_key); - if (current_key_type_i == 1) { + if (current_key_type_i == MF_KEY_B) { if (e_sector[current_sector_i].foundKey[0] && !e_sector[current_sector_i].foundKey[1]) { if (verbose) { PrintAndLogEx(INFO, "======================= " _YELLOW_("START READ B KEY ATTACK") " ======================="); - PrintAndLogEx(INFO, "reading B key: sector: %3d key type: %c", + PrintAndLogEx(INFO, "reading B key of sector %3d with key type %c", current_sector_i, - current_key_type_i ? 'B' : 'A'); + (current_key_type_i == MF_KEY_B) ? 'B' : 'A'); } uint8_t sectrail = (FirstBlockOfSector(current_sector_i) + NumBlocksPerSector(current_sector_i) - 1); @@ -2364,16 +2325,16 @@ noValidKeyFound: e_sector[current_sector_i].foundKey[current_key_type_i] = 'A'; e_sector[current_sector_i].Key[current_key_type_i] = key64; num_to_bytes(key64, 6, tmp_key); - PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%s") "]", + PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]", current_sector_i, - current_key_type_i ? 'B' : 'A', - sprint_hex(tmp_key, sizeof(tmp_key)) + (current_key_type_i == MF_KEY_B) ? 'B' : 'A', + sprint_hex_inrow(tmp_key, sizeof(tmp_key)) ); } else { if (verbose) { PrintAndLogEx(WARNING, "unknown B key: sector: %3d key type: %c", current_sector_i, - current_key_type_i ? 'B' : 'A' + (current_key_type_i == MF_KEY_B) ? 'B' : 'A' ); PrintAndLogEx(INFO, " -- reading the B key was not possible, maybe due to access rights?"); @@ -2394,12 +2355,12 @@ skipReadBKey: uint8_t retries = 0; if (verbose) { PrintAndLogEx(INFO, "======================= " _YELLOW_("START NESTED ATTACK") " ======================="); - PrintAndLogEx(INFO, "sector no: %3d, target key type: %c", + PrintAndLogEx(INFO, "sector no %3d, target key type %c", current_sector_i, - current_key_type_i ? 'B' : 'A'); + (current_key_type_i == MF_KEY_B) ? 'B' : 'A'); } tryNested: - isOK = mfnested(FirstBlockOfSector(blockNo), keyType, key, FirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key, calibrate); + isOK = mfnested(FirstBlockOfSector(sectorno), keytype, key, FirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key, calibrate); switch (isOK) { case PM3_ETIMEOUT: { @@ -2451,22 +2412,22 @@ tryNested: tryHardnested: // If the nested attack fails then we try the hardnested attack if (verbose) { PrintAndLogEx(INFO, "======================= " _YELLOW_("START HARDNESTED ATTACK") " ======================="); - PrintAndLogEx(INFO, "sector no: %3d, target key type: %c, Slow: %s", + PrintAndLogEx(INFO, "sector no %3d, target key type %c, Slow %s", current_sector_i, - current_key_type_i ? 'B' : 'A', + (current_key_type_i == MF_KEY_B) ? 'B' : 'A', slow ? "Yes" : "No"); } - isOK = mfnestedhard(FirstBlockOfSector(blockNo), keyType, key, FirstBlockOfSector(current_sector_i), current_key_type_i, NULL, false, false, slow, 0, &foundkey, NULL); + isOK = mfnestedhard(FirstBlockOfSector(sectorno), keytype, key, FirstBlockOfSector(current_sector_i), current_key_type_i, NULL, false, false, slow, 0, &foundkey, NULL); DropField(); if (isOK) { switch (isOK) { case 1: { - PrintAndLogEx(ERR, "\nError: No response from Proxmark3."); + PrintAndLogEx(ERR, "\nError: No response from Proxmark3"); break; } case 2: { - PrintAndLogEx(NORMAL, "\nButton pressed. Aborted."); + PrintAndLogEx(NORMAL, "\nButton pressed, user aborted"); break; } default: { @@ -2488,22 +2449,22 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack tryStaticnested: if (verbose) { PrintAndLogEx(INFO, "======================= " _YELLOW_("START STATIC NESTED ATTACK") " ======================="); - PrintAndLogEx(INFO, "sector no: %3d, target key type: %c", + PrintAndLogEx(INFO, "sector no %3d, target key type %c", current_sector_i, - current_key_type_i ? 'B' : 'A'); + (current_key_type_i == MF_KEY_B) ? 'B' : 'A'); } - isOK = mfStaticNested(blockNo, keyType, key, FirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key); + isOK = mfStaticNested(sectorno, keytype, key, FirstBlockOfSector(current_sector_i), current_key_type_i, tmp_key); DropField(); switch (isOK) { case PM3_ETIMEOUT: { - PrintAndLogEx(ERR, "\nError: No response from Proxmark3."); + PrintAndLogEx(ERR, "\nError: No response from Proxmark3"); free(e_sector); free(fptr); return PM3_ESOFT; } case PM3_EOPABORTED: { - PrintAndLogEx(WARNING, "\nButton pressed. Aborted."); + PrintAndLogEx(WARNING, "\nButton pressed, user aborted"); free(e_sector); free(fptr); return PM3_EOPABORTED; @@ -2521,10 +2482,10 @@ tryStaticnested: // Check if the key was found if (e_sector[current_sector_i].foundKey[current_key_type_i]) { - PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _GREEN_("%s") "]", + PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]", current_sector_i, - current_key_type_i ? 'B' : 'A', - sprint_hex(tmp_key, sizeof(tmp_key)) + (current_key_type_i == MF_KEY_B) ? 'B' : 'A', + sprint_hex_inrow(tmp_key, sizeof(tmp_key)) ); } } @@ -2538,12 +2499,12 @@ all_found: PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, _GREEN_("found keys:")); - printKeyTable(sectors_cnt, e_sector); + printKeyTable(sector_cnt, e_sector); // Dump the keys PrintAndLogEx(NORMAL, ""); - if (createMfcKeyDump(fptr, sectors_cnt, e_sector) != PM3_SUCCESS) { + if (createMfcKeyDump(fptr, sector_cnt, e_sector) != PM3_SUCCESS) { PrintAndLogEx(ERR, "Failed to save keys to file"); } @@ -2553,7 +2514,7 @@ all_found: PrintAndLogEx(SUCCESS, "transferring keys to simulator memory (Cmd Error: 04 can occur)"); - for (current_sector_i = 0; current_sector_i < sectors_cnt; current_sector_i++) { + for (current_sector_i = 0; current_sector_i < sector_cnt; current_sector_i++) { mfEmlGetMem(block, current_sector_i, 1); if (e_sector[current_sector_i].foundKey[0]) num_to_bytes(e_sector[current_sector_i].Key[0], 6, block); @@ -2564,17 +2525,16 @@ all_found: } // use ecfill trick - FastDumpWithEcFill(sectors_cnt); + FastDumpWithEcFill(sector_cnt); bytes = block_cnt * MFBLOCK_SIZE; - dump = calloc(bytes, sizeof(uint8_t)); - if (!dump) { + uint8_t *dump = calloc(bytes, sizeof(uint8_t)); + if (dump == NULL) { PrintAndLogEx(ERR, "Fail, cannot allocate memory"); free(e_sector); free(fptr); return PM3_EMALLOC; } - memset(dump, 0, bytes); PrintAndLogEx(INFO, "downloading the card content from emulator memory"); if (!GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false)) { @@ -2585,15 +2545,16 @@ all_found: return PM3_ETIMEOUT; } - char *fnameptr = GenerateFilename("hf-mf-", "-dump"); - if (fnameptr == NULL) { + free(fptr); + fptr = GenerateFilename("hf-mf-", "-dump"); + if (fptr == NULL) { free(dump); free(e_sector); free(fptr); return PM3_ESOFT; } - strcpy(filename, fnameptr); - free(fnameptr); + strcpy(filename, fptr); + free(fptr); saveFile(filename, ".bin", dump, bytes); saveFileEML(filename, dump, bytes, MFBLOCK_SIZE); @@ -2605,7 +2566,6 @@ all_found: free(dump); free(e_sector); - free(fptr); return PM3_SUCCESS; } @@ -2632,7 +2592,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { arg_lit0(NULL, "emu", "Fill simulator keys from found keys"), arg_lit0(NULL, "dump", "Dump found keys to binary file"), arg_lit0(NULL, "mem", "Use dictionary from flashmemory"), - arg_str0("f", "file", "", "filename of dictionary"), + arg_str0("f", "file", "", "filename of dictionary"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -2863,8 +2823,8 @@ out: conn.block_after_ACK = true; uint8_t block[16] = {0x00}; for (i = 0; i < sectorsCnt; ++i) { - uint8_t blockno = FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1; - mfEmlGetMem(block, blockno, 1); + uint8_t b = FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1; + mfEmlGetMem(block, b, 1); if (e_sector[i].foundKey[0]) num_to_bytes(e_sector[i].Key[0], 6, block); @@ -2876,7 +2836,7 @@ out: // Disable fast mode on last packet conn.block_after_ACK = false; } - mfEmlSetMem(block, blockno, 1); + mfEmlSetMem(block, b, 1); } PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory"); diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index dfb321a00..0d9f82af7 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -16,7 +16,6 @@ hf felica auth1 hf felica auth2 hf felica rqspecver hf felica resetmode -hf mf autopwn lf hitag reader lf hitag writer lf hitag dump From 8bee66c32a84cfeabc5af48a7afeecdeb8f94663 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 12 Apr 2021 13:18:25 +0200 Subject: [PATCH 229/373] lf hitag reader - now uses cliparser --- client/src/cmdlfhitag.c | 176 +++++++++++++++++++++++++--------------- doc/cliparser_todo.txt | 1 - 2 files changed, 111 insertions(+), 66 deletions(-) diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index c03a9ca89..44f7ac5b1 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -49,9 +49,7 @@ static const char *getHitagTypeStr(uint32_t uid) { static size_t nbytes(size_t nbits) { return (nbits / 8) + ((nbits % 8) > 0); } -*/ -/* static int usage_hitag_dump(void) { PrintAndLogEx(NORMAL, "Usage: lf hitag dump [h] p f "); PrintAndLogEx(NORMAL, "Options:"); @@ -65,24 +63,6 @@ static int usage_hitag_dump(void) { return PM3_SUCCESS; } */ -static int usage_hitag_reader(void) { - PrintAndLogEx(NORMAL, "Hitag reader functions"); - PrintAndLogEx(NORMAL, "Usage: lf hitag reader [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " HitagS (0*)"); - PrintAndLogEx(NORMAL, " 01 Read all pages, challenge mode"); - PrintAndLogEx(NORMAL, " 02 Read all pages, crypto mode. Set key=0 for no auth"); - PrintAndLogEx(NORMAL, " Hitag1 (1*)"); - PrintAndLogEx(NORMAL, " Not implemented"); - PrintAndLogEx(NORMAL, " Hitag2 (2*)"); - PrintAndLogEx(NORMAL, " 21 Read all pages, password mode. Default: " _YELLOW_("4D494B52") " (\"MIKR\")"); - PrintAndLogEx(NORMAL, " 22 Read all pages, challenge mode"); - PrintAndLogEx(NORMAL, " 23 Read all pages, crypto mode. Key format: ISK high + ISK low. Default: " _YELLOW_("4F4E4D494B52") " (\"ONMIKR\")"); - PrintAndLogEx(NORMAL, " 25 Test recorded authentications"); - PrintAndLogEx(NORMAL, " 26 Just read UID"); - return PM3_SUCCESS; -} static int usage_hitag_writer(void) { PrintAndLogEx(NORMAL, "Hitag writer functions"); PrintAndLogEx(NORMAL, "Usage: lf hitag write [h] "); @@ -558,57 +538,123 @@ static int CmdLFHitagInfo(const char *Cmd) { // static int CmdLFHitagReader(const char *Cmd) { - uint16_t cmd = CMD_LF_HITAG_READER; - hitag_data htd; - hitag_function htf = param_get32ex(Cmd, 0, 0, 10); + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf hitag reader", + "Act like a Hitag Reader", + "Hitag S\n" + " lf hitag reader --01 --nr 01020304 --ar 11223344\n" + " lf hitag reader --02 -k 4F4E4D494B52\n" + "Hitag 2\n" + " lf hitag reader --21 -k 4D494B52\n" + " lf hitag reader --22 --nr 01020304 --ar 11223344\n" + " lf hitag reader --23 -k 4F4E4D494B52\n" + " lf hitag reader --26\n" + ); - switch (htf) { - case RHTSF_CHALLENGE: { - cmd = CMD_LF_HITAGS_READ; - num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd.auth.NrAr); - num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd.auth.NrAr + 4); - break; - } - case RHTSF_KEY: { - cmd = CMD_LF_HITAGS_READ; - num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd.crypto.key); - break; - } - case RHT2F_PASSWORD: { - num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd.pwd.password); - break; - } - case RHT2F_AUTHENTICATE: { - num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd.auth.NrAr); - num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd.auth.NrAr + 4); - break; - } - case RHT2F_CRYPTO: { - num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd.crypto.key); - break; - } - case RHT2F_TEST_AUTH_ATTEMPTS: { - // No additional parameters needed - break; - } - case RHT2F_UID_ONLY: { - // No additional parameters needed - break; - } - default: - case RHT1F_PLAIN: - case RHT1F_AUTHENTICATE: - case WHTSF_CHALLENGE: - case WHTSF_KEY: - case WHT2F_PASSWORD: - case WHT2F_CRYPTO: - return usage_hitag_reader(); + void *argtable[] = { + arg_param_begin, + arg_lit0(NULL, "01", "HitagS, read all pages, challenge mode"), + arg_lit0(NULL, "02", "HitagS, read all pages, crypto mode. Set key=0 for no auth"), + arg_lit0(NULL, "21", "Hitag2, read all pages, password mode. def 4D494B52 (MIKR)"), + arg_lit0(NULL, "22", "Hitag2, read all pages, challenge mode"), + arg_lit0(NULL, "23", "Hitag2, read all pages, crypto mode. Key format: ISK high + ISK low. def 4F4E4D494B52 (ONMIKR)"), + arg_lit0(NULL, "25", "Hitag2, test recorded authentications (replay?)"), + arg_lit0(NULL, "26", "Hitag2, read UID"), + arg_str0("k","key", "", "4 or 6 hex bytes"), + arg_str0(NULL,"nr", "", "nonce reader, 4 hex bytes"), + arg_str0(NULL,"ar", "", "answer reader, 4 hex bytes"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + // Hitag S + bool s01 = arg_get_lit(ctx, 1); + bool s02 = arg_get_lit(ctx, 2); + + // Hitag 2 + bool h21 = arg_get_lit(ctx, 3); + bool h22 = arg_get_lit(ctx, 4); + bool h23 = arg_get_lit(ctx, 5); + bool h25 = arg_get_lit(ctx, 6); + bool h26 = arg_get_lit(ctx, 7); + + uint8_t key[6]; + int keylen = 0; + CLIParamHexToBuf(arg_get_str(ctx, 8), key, sizeof(key), &keylen); + + uint8_t nr[4]; + int nlen = 0; + CLIParamHexToBuf(arg_get_str(ctx, 9), nr, sizeof(nr), &nlen); + + uint8_t ar[4]; + int alen = 0; + CLIParamHexToBuf(arg_get_str(ctx, 10), ar, sizeof(ar), &alen); + CLIParserFree(ctx); + + + // sanity checks + if (keylen != 0 && keylen != 6) { + PrintAndLogEx(WARNING, "Wrong KEY len expected 0 or 6, got %d", keylen); + return PM3_EINVARG; } + if (nlen != 0 && nlen != 4) { + PrintAndLogEx(WARNING, "Wrong NR len expected 0 or 4, got %d", nlen); + return PM3_EINVARG; + } + + if (alen != 0 && alen != 4) { + PrintAndLogEx(WARNING, "Wrong AR len expected 0 or 4, got %d", alen); + return PM3_EINVARG; + } + + uint8_t foo = (s01 + s02 + h21 + h22 + h23 + h25 + h26); + if (foo > 1) { + PrintAndLogEx(WARNING, "Only specify one HITAG reader call"); + return PM3_EINVARG; + } else if (foo == 0) { + PrintAndLogEx(WARNING, "Specify one HITAG reader call"); + return PM3_EINVARG; + } + + hitag_function htf; + hitag_data htd; + uint16_t cmd = CMD_LF_HITAG_READER; + if (s01) { + cmd = CMD_LF_HITAGS_READ; + htf = RHTSF_CHALLENGE; + memcpy(htd.auth.NrAr, nr, sizeof(nr)); + memcpy(htd.auth.NrAr + 4, ar, sizeof(ar)); + } + if (s02){ + cmd = CMD_LF_HITAGS_READ; + htf = RHTSF_KEY; + memcpy(htd.crypto.key, key, sizeof(key)); + } + if (h21) { + htf = RHT2F_PASSWORD; + memcpy(htd.pwd.password, key, 4); + } + if (h22) { + htf = RHT2F_AUTHENTICATE; + memcpy(htd.auth.NrAr, nr, sizeof(nr)); + memcpy(htd.auth.NrAr + 4, ar, sizeof(ar)); + } + if (h23) { + htf = RHT2F_CRYPTO; + memcpy(htd.crypto.key, key, sizeof(key)); + } + if (h25) { + htf = RHT2F_TEST_AUTH_ATTEMPTS; + } + if (h26) { + htf = RHT2F_UID_ONLY; + } + clearCommandBuffer(); SendCommandMIX(cmd, htf, 0, 0, &htd, sizeof(htd)); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); return PM3_ETIMEOUT; } diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 0d9f82af7..8d27f7717 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -16,6 +16,5 @@ hf felica auth1 hf felica auth2 hf felica rqspecver hf felica resetmode -lf hitag reader lf hitag writer lf hitag dump From 5ddedf17dd5e32ee7460fb28503d667a55bb5597 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 12 Apr 2021 16:17:37 +0200 Subject: [PATCH 230/373] lf hitag writer - now uses cliparser --- client/src/cmdlfhitag.c | 196 +++++++++++++++++++++++----------------- doc/cliparser_todo.txt | 1 - doc/commands.md | 4 +- 3 files changed, 116 insertions(+), 85 deletions(-) diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index 44f7ac5b1..a3faf9025 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -63,22 +63,6 @@ static int usage_hitag_dump(void) { return PM3_SUCCESS; } */ -static int usage_hitag_writer(void) { - PrintAndLogEx(NORMAL, "Hitag writer functions"); - PrintAndLogEx(NORMAL, "Usage: lf hitag write [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " HitagS (0*)"); - PrintAndLogEx(NORMAL, " 03 Write page, challenge mode"); - PrintAndLogEx(NORMAL, " 04 Write page, crypto mode. Set key=0 for no auth"); - PrintAndLogEx(NORMAL, " Hitag1 (1*)"); - PrintAndLogEx(NORMAL, " Not implemented"); - PrintAndLogEx(NORMAL, " Hitag2 (2*)"); - PrintAndLogEx(NORMAL, " 24 Write page, crypto mode. Key format: ISK high + ISK low."); - PrintAndLogEx(NORMAL, " Default: 4F4E4D494B52 (\"ONMIKR\"). Set key=0 for no auth"); - PrintAndLogEx(NORMAL, " 27 Write page, password mode. Default: 4D494B52 (\"MIKR\")"); - return PM3_SUCCESS; -} static int CmdLFHitagList(const char *Cmd) { char args[128] = {0}; @@ -542,11 +526,11 @@ static int CmdLFHitagReader(const char *Cmd) { CLIParserInit(&ctx, "lf hitag reader", "Act like a Hitag Reader", "Hitag S\n" - " lf hitag reader --01 --nr 01020304 --ar 11223344\n" + " lf hitag reader --01 --nrar 0102030411223344\n" " lf hitag reader --02 -k 4F4E4D494B52\n" "Hitag 2\n" " lf hitag reader --21 -k 4D494B52\n" - " lf hitag reader --22 --nr 01020304 --ar 11223344\n" + " lf hitag reader --22 --nrar 0102030411223344\n" " lf hitag reader --23 -k 4F4E4D494B52\n" " lf hitag reader --26\n" ); @@ -557,12 +541,11 @@ static int CmdLFHitagReader(const char *Cmd) { arg_lit0(NULL, "02", "HitagS, read all pages, crypto mode. Set key=0 for no auth"), arg_lit0(NULL, "21", "Hitag2, read all pages, password mode. def 4D494B52 (MIKR)"), arg_lit0(NULL, "22", "Hitag2, read all pages, challenge mode"), - arg_lit0(NULL, "23", "Hitag2, read all pages, crypto mode. Key format: ISK high + ISK low. def 4F4E4D494B52 (ONMIKR)"), + arg_lit0(NULL, "23", "Hitag2, read all pages, crypto mode. Key ISK high + ISK low. def 4F4E4D494B52 (ONMIKR)"), arg_lit0(NULL, "25", "Hitag2, test recorded authentications (replay?)"), arg_lit0(NULL, "26", "Hitag2, read UID"), - arg_str0("k","key", "", "4 or 6 hex bytes"), - arg_str0(NULL,"nr", "", "nonce reader, 4 hex bytes"), - arg_str0(NULL,"ar", "", "answer reader, 4 hex bytes"), + arg_str0("k","key", "", "key, 4 or 6 hex bytes"), + arg_str0(NULL,"nrar", "", "nonce / answer reader, 8 hex bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -582,38 +565,28 @@ static int CmdLFHitagReader(const char *Cmd) { int keylen = 0; CLIParamHexToBuf(arg_get_str(ctx, 8), key, sizeof(key), &keylen); - uint8_t nr[4]; - int nlen = 0; - CLIParamHexToBuf(arg_get_str(ctx, 9), nr, sizeof(nr), &nlen); - - uint8_t ar[4]; - int alen = 0; - CLIParamHexToBuf(arg_get_str(ctx, 10), ar, sizeof(ar), &alen); + uint8_t nrar[8]; + int nalen = 0; + CLIParamHexToBuf(arg_get_str(ctx, 9), nrar, sizeof(nrar), &nalen); CLIParserFree(ctx); - // sanity checks if (keylen != 0 && keylen != 6) { - PrintAndLogEx(WARNING, "Wrong KEY len expected 0 or 6, got %d", keylen); + PrintAndLogEx(WARNING, "Wrong KEY len expected 0 or 6, got %d", keylen); return PM3_EINVARG; } - if (nlen != 0 && nlen != 4) { - PrintAndLogEx(WARNING, "Wrong NR len expected 0 or 4, got %d", nlen); - return PM3_EINVARG; - } - - if (alen != 0 && alen != 4) { - PrintAndLogEx(WARNING, "Wrong AR len expected 0 or 4, got %d", alen); + if (nalen != 0 && nalen != 8) { + PrintAndLogEx(WARNING, "Wrong NR/AR len expected 0 or 8, got %d", nalen); return PM3_EINVARG; } uint8_t foo = (s01 + s02 + h21 + h22 + h23 + h25 + h26); if (foo > 1) { - PrintAndLogEx(WARNING, "Only specify one HITAG reader call"); + PrintAndLogEx(WARNING, "Only specify one HITAG reader cmd"); return PM3_EINVARG; } else if (foo == 0) { - PrintAndLogEx(WARNING, "Specify one HITAG reader call"); + PrintAndLogEx(WARNING, "Specify one HITAG reader cms"); return PM3_EINVARG; } @@ -623,8 +596,7 @@ static int CmdLFHitagReader(const char *Cmd) { if (s01) { cmd = CMD_LF_HITAGS_READ; htf = RHTSF_CHALLENGE; - memcpy(htd.auth.NrAr, nr, sizeof(nr)); - memcpy(htd.auth.NrAr + 4, ar, sizeof(ar)); + memcpy(htd.auth.NrAr, nrar, sizeof(nrar)); } if (s02){ cmd = CMD_LF_HITAGS_READ; @@ -637,8 +609,7 @@ static int CmdLFHitagReader(const char *Cmd) { } if (h22) { htf = RHT2F_AUTHENTICATE; - memcpy(htd.auth.NrAr, nr, sizeof(nr)); - memcpy(htd.auth.NrAr + 4, ar, sizeof(ar)); + memcpy(htd.auth.NrAr, nrar, sizeof(nrar)); } if (h23) { htf = RHT2F_CRYPTO; @@ -722,47 +693,108 @@ static int CmdLFHitagCheckChallenges(const char *Cmd) { } static int CmdLFHitagWriter(const char *Cmd) { - hitag_data htd; - hitag_function htf = param_get32ex(Cmd, 0, 0, 10); + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf hitag writer", + "Act like a Hitag writer" + "In password mode the default key is 4D494B52 (MIKR)\n" + "In crypto mode the default key is 4F4E4D494B52 (ONMIKR) format: ISK high + ISK low.", + "Hitag S\n" + " lf hitag reader --03 --nrar 0102030411223344 -p 3 -d 01020304\n" + " lf hitag reader --04 -k 4F4E4D494B52 -p 3 -d 01020304\n" + "Hitag 2\n" + " lf hitag reader --24 -k 4F4E4D494B52 -p 3 -d 01020304\n" + " lf hitag reader --27 -k 4D494B52 -p 3 -d 01020304\n" + ); - uint32_t arg2 = 0; - switch (htf) { - case WHTSF_CHALLENGE: { - num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 8, htd.auth.NrAr); - arg2 = param_get32ex(Cmd, 2, 0, 10); - num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd.auth.data); - break; - } - case WHTSF_KEY: - case WHT2F_CRYPTO: { - num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd.crypto.key); - arg2 = param_get32ex(Cmd, 2, 0, 10); - num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd.crypto.data); - break; - } - case WHT2F_PASSWORD: { - num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 4, htd.pwd.password); - arg2 = param_get32ex(Cmd, 2, 0, 10); - num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd.crypto.data); - break; - } - default: - case RHT1F_PLAIN: - case RHT1F_AUTHENTICATE: - case RHTSF_CHALLENGE: - case RHTSF_KEY: - case RHT2F_PASSWORD: - case RHT2F_AUTHENTICATE: - case RHT2F_CRYPTO: - case RHT2F_TEST_AUTH_ATTEMPTS: - case RHT2F_UID_ONLY: - return usage_hitag_writer(); + void *argtable[] = { + arg_param_begin, + arg_lit0(NULL, "03", "HitagS, write page, challenge mode"), + arg_lit0(NULL, "04", "HitagS, write page, crypto mode. Set key=0 for no auth"), + arg_lit0(NULL, "24", "Hitag2, write page, crypto mode."), + arg_lit0(NULL, "27", "Hitag2, write page, password mode"), + arg_int1("p", "page", "", "page address to write to"), + arg_str0("d", "data", "", "data, 4 hex bytes"), + arg_str0("k","key", "", "key, 4 or 6 hex bytes"), + arg_str0(NULL,"nrar", "", "nonce / answer reader, 8 hex bytes"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + // Hitag S + bool s03 = arg_get_lit(ctx, 1); + bool s04 = arg_get_lit(ctx, 2); + + // Hitag 2 + bool h24 = arg_get_lit(ctx, 3); + bool h27 = arg_get_lit(ctx, 4); + + uint32_t page = arg_get_u32_def(ctx, 5, 0); + + uint8_t data[4]; + int dlen = 0; + CLIParamHexToBuf(arg_get_str(ctx, 6), data, sizeof(data), &dlen); + + uint8_t key[6]; + int keylen = 0; + CLIParamHexToBuf(arg_get_str(ctx, 7), key, sizeof(key), &keylen); + + uint8_t nrar[8]; + int nalen = 0; + CLIParamHexToBuf(arg_get_str(ctx, 8), nrar, sizeof(nrar), &nalen); + CLIParserFree(ctx); + + // sanity checks + if (dlen != sizeof(data)) { + PrintAndLogEx(WARNING, "Wrong DATA len expected 4, got %d", dlen); + return PM3_EINVARG; + } + + if (keylen != 0 && keylen != 6 && keylen != 4) { + PrintAndLogEx(WARNING, "Wrong KEY len expected 0, 4 or 6, got %d", keylen); + return PM3_EINVARG; + } + + if (nalen != 0 && nalen != 8) { + PrintAndLogEx(WARNING, "Wrong NR/AR len expected 0 or 8, got %d", nalen); + return PM3_EINVARG; + } + + uint8_t foo = (s03 + s04 + h24 + h27); + if (foo > 1) { + PrintAndLogEx(WARNING, "Only specify one HITAG write cmd"); + return PM3_EINVARG; + } else if (foo == 0) { + PrintAndLogEx(WARNING, "Specify one HITAG write cmd"); + return PM3_EINVARG; + } + + hitag_function htf; + hitag_data htd; + if (s03) { + htf = WHTSF_CHALLENGE; + memcpy(htd.auth.NrAr, nrar, sizeof(nrar)); + memcpy(htd.auth.data, data, sizeof(data)); + } + if (s04){ + htf = WHTSF_KEY; + memcpy(htd.crypto.key, key, sizeof(key)); + memcpy(htd.crypto.data, data, sizeof(data)); + } + if (h24) { + htf = WHT2F_CRYPTO; + memcpy(htd.pwd.password, key, 4); + memcpy(htd.crypto.data, data, sizeof(data)); + } + if (h27) { + htf = WHT2F_PASSWORD; + memcpy(htd.pwd.password, key, 4); + memcpy(htd.crypto.data, data, sizeof(data)); } clearCommandBuffer(); - SendCommandMIX(CMD_LF_HITAGS_WRITE, htf, 0, arg2, &htd, sizeof(htd)); + SendCommandMIX(CMD_LF_HITAGS_WRITE, htf, 0, page, &htd, sizeof(htd)); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 4000) == false) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); return PM3_ETIMEOUT; } @@ -861,10 +893,10 @@ static command_t CommandTable[] = { {"eload", CmdLFHitagEload, IfPm3Hitag, "Load Hitag dump file into emulator memory"}, {"list", CmdLFHitagList, IfPm3Hitag, "List Hitag trace history"}, {"info", CmdLFHitagInfo, IfPm3Hitag, "Tag information"}, - {"reader", CmdLFHitagReader, IfPm3Hitag, "Act like a Hitag Reader"}, + {"reader", CmdLFHitagReader, IfPm3Hitag, "Act like a Hitag reader"}, {"sim", CmdLFHitagSim, IfPm3Hitag, "Simulate Hitag transponder"}, {"sniff", CmdLFHitagSniff, IfPm3Hitag, "Eavesdrop Hitag communication"}, - {"writer", CmdLFHitagWriter, IfPm3Hitag, "Act like a Hitag Writer"}, + {"writer", CmdLFHitagWriter, IfPm3Hitag, "Act like a Hitag writer"}, {"dump", CmdLFHitag2Dump, IfPm3Hitag, "Dump Hitag2 tag"}, {"cc", CmdLFHitagCheckChallenges, IfPm3Hitag, "Test all challenges"}, { NULL, NULL, 0, NULL } diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 8d27f7717..750aca4bf 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -16,5 +16,4 @@ hf felica auth1 hf felica auth2 hf felica rqspecver hf felica resetmode -lf hitag writer lf hitag dump diff --git a/doc/commands.md b/doc/commands.md index d67b43086..fffeade87 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -789,10 +789,10 @@ Check column "offline" for their availability. |`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` +|`lf hitag reader `|N |`Act like a Hitag reader` |`lf hitag sim `|N |`Simulate Hitag transponder` |`lf hitag sniff `|N |`Eavesdrop Hitag communication` -|`lf hitag writer `|N |`Act like a Hitag Writer` +|`lf hitag writer `|N |`Act like a Hitag writer` |`lf hitag dump `|N |`Dump Hitag2 tag` |`lf hitag cc `|N |`Test all challenges` From 0290efb25e838dbabbfdc2130a9be7273e5dd5c4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 12 Apr 2021 16:18:24 +0200 Subject: [PATCH 231/373] hf mf hardnest - init all values (Thanks @doegox) --- client/src/cmdhfmfhard.c | 43 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfmfhard.c b/client/src/cmdhfmfhard.c index fc9e00476..1ced5e1a9 100644 --- a/client/src/cmdhfmfhard.c +++ b/client/src/cmdhfmfhard.c @@ -2176,6 +2176,46 @@ static void set_test_state(uint8_t byte) { crypto1_destroy(pcs); } +static void init_it_all(void) { + memset(nonces, 0, sizeof(nonces)); + maximum_states = 0; + best_first_byte_smallest_bitarray = 0; + first_byte_Sum = 0; + first_byte_num = 0; + write_stats = false; + all_bitflips_bitarray[0] = NULL; + all_bitflips_bitarray[1] = NULL; + num_all_bitflips_bitarray[0] = 0; + num_all_bitflips_bitarray[1] = 0; + all_bitflips_bitarray_dirty[0] = false; + all_bitflips_bitarray_dirty[1] = false; + last_sample_clock = 0; + sample_period = 0; + num_keys_tested = 0; + candidates = NULL; + num_acquired_nonces = 0; + start_time = 0; + num_effective_bitflips[0] = 0; + num_effective_bitflips[1] = 0; + num_all_effective_bitflips = 0; + num_1st_byte_effective_bitflips = 0; + hardnested_stage = CHECK_1ST_BYTES; + known_target_key = 0; + test_state[0] = 0; + test_state[1] = 0; + brute_force_per_second=0; + init_book_of_work(); + real_sum_a8 = 0; + + memset(effective_bitflip, 0, sizeof(effective_bitflip)); + memset(all_effective_bitflip, 0, sizeof(all_effective_bitflip)); + memset(bitflip_bitarrays, 0, sizeof(bitflip_bitarrays)); + memset(count_bitflip_bitarrays, 0, sizeof(count_bitflip_bitarrays)); + memset(part_sum_a0_bitarrays, 0, sizeof(part_sum_a0_bitarrays)); + memset(part_sum_a8_bitarrays, 0, sizeof(part_sum_a8_bitarrays)); + memset(sum_a0_bitarrays, 0, sizeof(sum_a0_bitarrays)); +} + int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests, uint64_t *foundkey, char *filename) { char progress_text[80]; char instr_set[12] = {0}; @@ -2183,8 +2223,9 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc get_SIMD_instruction_set(instr_set); PrintAndLogEx(SUCCESS, "Using %s SIMD core.", instr_set); + // initialize static arrays memset(part_sum_count, 0, sizeof(part_sum_count)); - real_sum_a8 = 0; + init_it_all(); srand((unsigned) time(NULL)); brute_force_per_second = brute_force_benchmark(); From b7b42ebd3909e69b037fe1bc872b904fc67cc6e1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 12 Apr 2021 16:47:54 +0200 Subject: [PATCH 232/373] lf hitag dump - now supports cliparser. Command is still not implemented --- client/src/cmdlfhitag.c | 65 ++++++++++++++++++++++++++--------------- doc/cliparser_todo.txt | 1 - 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index a3faf9025..912ea4665 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -49,19 +49,6 @@ static const char *getHitagTypeStr(uint32_t uid) { static size_t nbytes(size_t nbits) { return (nbits / 8) + ((nbits % 8) > 0); } - -static int usage_hitag_dump(void) { - PrintAndLogEx(NORMAL, "Usage: lf hitag dump [h] p f "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); -// PrintAndLogEx(NORMAL, " p password"); -// PrintAndLogEx(NORMAL, " f data filename, if no given, UID will be used as filename"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf hitag dump f mydump"); - PrintAndLogEx(NORMAL, " lf hitag dump p 4D494B52 f mydump"); - return PM3_SUCCESS; -} */ static int CmdLFHitagList(const char *Cmd) { @@ -807,25 +794,57 @@ static int CmdLFHitagWriter(const char *Cmd) { } static int CmdLFHitag2Dump(const char *Cmd) { - PrintAndLogEx(INFO, "Dumping of tag memory"); - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return 0; // usage_hitag_dump(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf hitag dump", + "Read all card memory and save to file" + "In password mode the default key is 4D494B52 (MIKR)\n" + "In crypto mode the default key is 4F4E4D494B52 (ONMIKR) format: ISK high + ISK low.", + "lf hitag dump -k 4F4E4D494B52\n" + "lf hitag dump -k 4D494B52\n" + ); - PacketResponseNG resp; + void *argtable[] = { + arg_param_begin, + arg_str0("f", "file", "", "file name"), + arg_str0("k","key", "", "key, 4 or 6 hex bytes"), + arg_str0(NULL,"nrar", "", "nonce / answer reader, 8 hex bytes"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + uint8_t filename[FILE_PATH_SIZE] = {0}; + int fnlen = 0; + CLIParamHexToBuf(arg_get_str(ctx, 1), filename, sizeof(filename), &fnlen); + uint8_t key[6]; + int keylen = 0; + CLIParamHexToBuf(arg_get_str(ctx, 2), key, sizeof(key), &keylen); + + uint8_t nrar[8]; + int nalen = 0; + CLIParamHexToBuf(arg_get_str(ctx, 3), nrar, sizeof(nrar), &nalen); + CLIParserFree(ctx); + + + PrintAndLogEx(WARNING, "to be implememted..."); + +/* PrintAndLogEx(SUCCESS, "Dumping tag memory..."); - uint8_t *data = resp.data.asBytes; - char filename[FILE_PATH_SIZE]; - char *fnameptr = filename; - fnameptr += sprintf(fnameptr, "lf-hitag-"); - FillFileNameByUID(fnameptr, data, "-dump", 4); + clearCommandBuffer(); + //SendCommandNG(CMD_LF_HITAG_DUMP, &htd, sizeof(htd)); + PacketResponseNG resp; + uint8_t *data = resp.data.asBytes; + if (fnlen < 1) { + char *fptr = filename; + fptr += sprintf(fptr, "lf-hitag-"); + FillFileNameByUID(fptr, data, "-dump", 4); + } saveFile(filename, ".bin", data, 48); saveFileEML(filename, data, 48, 4); saveFileJSON(filename, jsfHitag, data, 48, NULL); - +*/ return PM3_SUCCESS; } diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 750aca4bf..fac683247 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -16,4 +16,3 @@ hf felica auth1 hf felica auth2 hf felica rqspecver hf felica resetmode -lf hitag dump From 6da7fcd510f30ef73fcbd092d58d2ec5a6fa744a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 12 Apr 2021 18:39:15 +0200 Subject: [PATCH 233/373] coverity fixes --- client/src/cmdhfmf.c | 8 ++++++- client/src/cmdlfhitag.c | 48 +++++++++++++++++++++++++++++++++-------- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 13dcf5557..a6136ff25 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -3776,6 +3776,7 @@ int CmdHF14AMfELoad(const char *Cmd) { } case DICTIONARY: { PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); + free(data); return PM3_EINVARG; } } @@ -4447,6 +4448,7 @@ static int CmdHF14AMfCLoad(const char *Cmd) { } case DICTIONARY: { PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); + free(data); return PM3_EINVARG; } } @@ -4886,7 +4888,7 @@ static int CmdHF14AMfCView(const char *Cmd) { //needs nt, ar, at, Data to decrypt static int CmdHf14AMfDecryptBytes(const char *Cmd) { - CLIParserContext *ctx; + CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf decrypt", "Decrypt Crypto-1 encrypted bytes given some known state of crypto. See tracelog to gather needed values", "hf mf decrypt --nt b830049b --ar 9248314a --at 9280e203 -d 41e586f9\n" @@ -4906,6 +4908,7 @@ static int CmdHf14AMfDecryptBytes(const char *Cmd) { uint32_t nt = 0; int res = arg_get_u32_hexstr_def(ctx, 1, 0, &nt); if (res != 1) { + CLIParserFree(ctx); PrintAndLogEx(WARNING, "check `nt` parameter"); return PM3_EINVARG; } @@ -4913,6 +4916,7 @@ static int CmdHf14AMfDecryptBytes(const char *Cmd) { uint32_t ar_enc = 0; res = arg_get_u32_hexstr_def(ctx, 2, 0, &ar_enc); if (res != 1) { + CLIParserFree(ctx); PrintAndLogEx(WARNING, "check `ar` parameter"); return PM3_EINVARG; } @@ -4920,6 +4924,7 @@ static int CmdHf14AMfDecryptBytes(const char *Cmd) { uint32_t at_enc = 0; res = arg_get_u32_hexstr_def(ctx, 3, 0, &at_enc); if (res != 1) { + CLIParserFree(ctx); PrintAndLogEx(WARNING, "check `at` parameter"); return PM3_EINVARG; } @@ -5939,6 +5944,7 @@ static int CmdHF14AMfView(const char *Cmd) { } case DICTIONARY: { PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); + free(dump); return PM3_EINVARG; } } diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index 912ea4665..af984ce61 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -550,12 +550,19 @@ static int CmdLFHitagReader(const char *Cmd) { uint8_t key[6]; int keylen = 0; - CLIParamHexToBuf(arg_get_str(ctx, 8), key, sizeof(key), &keylen); + int res = CLIParamHexToBuf(arg_get_str(ctx, 8), key, sizeof(key), &keylen); + if (res != 0) { + CLIParserFree(ctx); + return PM3_EINVARG; + } uint8_t nrar[8]; int nalen = 0; - CLIParamHexToBuf(arg_get_str(ctx, 9), nrar, sizeof(nrar), &nalen); + res = CLIParamHexToBuf(arg_get_str(ctx, 9), nrar, sizeof(nrar), &nalen); CLIParserFree(ctx); + if (res != 0) { + return PM3_EINVARG; + } // sanity checks if (keylen != 0 && keylen != 6) { @@ -719,17 +726,30 @@ static int CmdLFHitagWriter(const char *Cmd) { uint8_t data[4]; int dlen = 0; - CLIParamHexToBuf(arg_get_str(ctx, 6), data, sizeof(data), &dlen); + int res = CLIParamHexToBuf(arg_get_str(ctx, 6), data, sizeof(data), &dlen); + if (res != 0) { + CLIParserFree(ctx); + return PM3_EINVARG; + } uint8_t key[6]; int keylen = 0; - CLIParamHexToBuf(arg_get_str(ctx, 7), key, sizeof(key), &keylen); + res = CLIParamHexToBuf(arg_get_str(ctx, 7), key, sizeof(key), &keylen); + if (res != 0) { + CLIParserFree(ctx); + return PM3_EINVARG; + } uint8_t nrar[8]; int nalen = 0; - CLIParamHexToBuf(arg_get_str(ctx, 8), nrar, sizeof(nrar), &nalen); + res = CLIParamHexToBuf(arg_get_str(ctx, 8), nrar, sizeof(nrar), &nalen); + CLIParserFree(ctx); + if (res != 0) { + return PM3_EINVARG; + } + // sanity checks if (dlen != sizeof(data)) { PrintAndLogEx(WARNING, "Wrong DATA len expected 4, got %d", dlen); @@ -814,17 +834,27 @@ static int CmdLFHitag2Dump(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, false); uint8_t filename[FILE_PATH_SIZE] = {0}; int fnlen = 0; - CLIParamHexToBuf(arg_get_str(ctx, 1), filename, sizeof(filename), &fnlen); + int res = CLIParamHexToBuf(arg_get_str(ctx, 1), filename, sizeof(filename), &fnlen); + if (res != 0) { + CLIParserFree(ctx); + return PM3_EINVARG; + } uint8_t key[6]; int keylen = 0; - CLIParamHexToBuf(arg_get_str(ctx, 2), key, sizeof(key), &keylen); + res = CLIParamHexToBuf(arg_get_str(ctx, 2), key, sizeof(key), &keylen); + if (res != 0) { + CLIParserFree(ctx); + return PM3_EINVARG; + } uint8_t nrar[8]; int nalen = 0; - CLIParamHexToBuf(arg_get_str(ctx, 3), nrar, sizeof(nrar), &nalen); + res = CLIParamHexToBuf(arg_get_str(ctx, 3), nrar, sizeof(nrar), &nalen); CLIParserFree(ctx); - + if (res != 0) { + return PM3_EINVARG; + } PrintAndLogEx(WARNING, "to be implememted..."); From 4f3991a10ce31b147a603ef615e50190f9a0f023 Mon Sep 17 00:00:00 2001 From: dandri <8928881+dandri@users.noreply.github.com> Date: Mon, 12 Apr 2021 17:57:06 +0000 Subject: [PATCH 234/373] 3-keys-added --- client/dictionaries/mfc_default_keys.dic | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index a0c8b9943..d22d2e7c2 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -1367,4 +1367,8 @@ F678905568C3 2E71D3BD262A 540D5E6355CC D1417E431949 -4BF6DE347FB6 \ No newline at end of file +4BF6DE347FB6 +# +3a471b2192bf +a297ceb7d34b +ae76242931f1 From 37751e1b2b5dbd6241d9f2bdddf837a797635d4a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 12 Apr 2021 21:30:53 +0200 Subject: [PATCH 235/373] hf felica resetmode - now uses cliparser --- client/src/cmdhffelica.c | 251 ++++++++++++++++++++------------------- 1 file changed, 132 insertions(+), 119 deletions(-) diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 8cf536e49..d1255cd0b 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -33,75 +33,87 @@ static void set_last_known_card(felica_card_select_t card) { last_known_card = card; } - static void print_status_flag1_interpretation(void) { PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "Status Flag1:"); - PrintAndLogEx(INFO, " - 00h : Indicates the successful completion of a command."); - PrintAndLogEx(INFO, " - FFh : If an error occurs during the processing of a command that includes no list in the command packet, or if " - "an error occurs independently of any list, the card returns a response by setting FFh to Status Flag1."); - PrintAndLogEx(INFO, " - XXh : If an error occurs while processing a command that includes Service Code List or Block List " - "in the command packet, the card returns a response by setting a number in the list to Status Flag1, " - "indicating the location of the error."); + PrintAndLogEx(INFO, _CYAN_("Status Flag 1")); + PrintAndLogEx(INFO, "----+--------------------------------------------------------------------------------------------------------------------"); + PrintAndLogEx(INFO, " 00 | Indicates the successful completion of a command."); + PrintAndLogEx(INFO, " FF | If an error occurs during the processing of a command that includes no list in the command packet, \n" + " | or if an error occurs independently of any list, the card returns a response by setting FFh to Status Flag1."); + PrintAndLogEx(INFO, " XX | If an error occurs while processing a command that includes Service Code List or Block List \n" + " | in the command packet, the card returns a response by setting a number in the list to Status Flag1,\n" + " | indicating the location of the error."); + PrintAndLogEx(INFO, "----+--------------------------------------------------------------------------------------------------------------------"); } static void print_status_flag2_interpration(void) { - PrintAndLogEx(INFO, "\nStatus Flag2:"); - PrintAndLogEx(INFO, " - 00h : Indicates the successful completion of a command."); - PrintAndLogEx(INFO, " - 01h : The calculated result is either less than zero when the purse data is decremented, or exceeds 4" - "Bytes when the purse data is incremented."); - PrintAndLogEx(INFO, " - 02h : The specified data exceeds the value of cashback data at cashback of purse."); - PrintAndLogEx(INFO, " - 70h : Memory error (fatal error)."); - PrintAndLogEx(INFO, " - 71h : The number of memory rewrites exceeds the upper limit (this is only a warning; data writing is " - "performed as normal). The maximum number of rewrites can differ, depending on the product being used."); - PrintAndLogEx(INFO, " In addition, Status Flag1 is either 00h or FFh depending on the product being used."); - PrintAndLogEx(INFO, " - A1h : Illegal Number of Service: Number of Service or Number of Node specified by the command falls outside the range of the prescribed value."); - PrintAndLogEx(INFO, " - A2h : Illegal command packet (specified Number of Block): Number of Block specified by the command falls outside the range of the prescribed values for the product."); - PrintAndLogEx(INFO, " - A3h : Illegal Block List (specified order of Service): Service Code List Order specified by Block List Element falls outside the Number of Service specified by the " - "command (or the Number of Service specified at the times of mutual authentication)."); - PrintAndLogEx(INFO, " - A4h : Illegal Service type: Area Attribute specified by the command or Service Attribute of Service Code is incorrect."); - PrintAndLogEx(INFO, " - A5h : Access is not allowed: Area or Service specified by the command cannot be accessed. " - "The parameter specified by the command does not satisfy the conditions for success."); - PrintAndLogEx(INFO, " - A6h : Illegal Service Code List: Target to be accessed, identified by Service Code List Order, specified by Block " - "List Element does not exist. Or, Node specified by Node Code List does not exist."); - PrintAndLogEx(INFO, " - A7h : Illegal Block List (Access Mode): Access Mode specified by Block List Element is incorrect."); - PrintAndLogEx(INFO, " - A8h : Illegal Block Number Block Number (access to the specified data is inhibited): specified by Block List Element exceeds the number of Blocks assigned to Service."); - PrintAndLogEx(INFO, " - A9h : Data write failure: This is the error that occurs in issuance commands."); - PrintAndLogEx(INFO, " - AAh : Key-change failure: Key change failed."); - PrintAndLogEx(INFO, " - ABh : Illegal Package Parity or illegal Package MAC: This is the error that occurs in issuance commands."); - PrintAndLogEx(INFO, " - ACh : Illegal parameter: This is the error that occurs in issuance commands."); - PrintAndLogEx(INFO, " - ADh : Service exists already: This is the error that occurs in issuance commands."); - PrintAndLogEx(INFO, " - AEh : Illegal System Code: This is the error that occurs in issuance commands."); - PrintAndLogEx(INFO, " - AFh : Too many simultaneous cyclic write operations: Number of simultaneous write Blocks specified by the command to Cyclic Service " - "exceeds the number of Blocks assigned to Service."); - PrintAndLogEx(INFO, " - C0h : Illegal Package Identifier: This is the error that occurs in issuance commands."); - PrintAndLogEx(INFO, " - C1h : Discrepancy of parameters inside and outside Package: This is the error that occurs in issuance commands."); - PrintAndLogEx(INFO, " - C2h : Command is disabled already: This is the error that occurs in issuance commands."); + PrintAndLogEx(INFO, _CYAN_("Status Flag 2")); + PrintAndLogEx(INFO, "----+--------------------------------------------------------------------------------------------------------------------"); + PrintAndLogEx(INFO, " 00 | Indicates the successful completion of a command."); + PrintAndLogEx(INFO, " 01 | The calculated result is either less than zero when the purse data is decremented, or exceeds 4\n" + " | Bytes when the purse data is incremented."); + PrintAndLogEx(INFO, " 02 | The specified data exceeds the value of cashback data at cashback of purse."); + PrintAndLogEx(INFO, " 70 | Memory error (fatal error)."); + PrintAndLogEx(INFO, " 71 | The number of memory rewrites exceeds the upper limit (this is only a warning; data writing is performed as normal).\n" + " | The maximum number of rewrites can differ, depending on the product being used.\n" + " | In addition, Status Flag1 is either 00h or FFh depending on the product being used."); + + PrintAndLogEx(INFO, " A1 | Illegal Number of Service| Number of Service or Number of Node specified by the command \n" + " | falls outside the range of the prescribed value."); + PrintAndLogEx(INFO, " A2 | Illegal command packet (specified Number of Block) : Number of Block specified by the \n" + " | command falls outside the range of the prescribed values for the product."); + PrintAndLogEx(INFO, " A3 | Illegal Block List (specified order of Service) : Service Code List Order specified by \n" + " | Block List Element falls outside the Number of Service specified by the command \n" + " | (or the Number of Service specified at the times of mutual authentication)."); + PrintAndLogEx(INFO, " A4 | Illegal Service type : Area Attribute specified by the command or Service Attribute of Service Code is incorrect."); + PrintAndLogEx(INFO, " A5 | Access is not allowed : Area or Service specified by the command cannot be accessed.\n" + " | The parameter specified by the command does not satisfy the conditions for success."); + PrintAndLogEx(INFO, " A6 | Illegal Service Code List : Target to be accessed, identified by Service Code List Order, specified by Block\n" + " | List Element does not exist. Or, Node specified by Node Code List does not exist."); + PrintAndLogEx(INFO, " A7 | Illegal Block List (Access Mode) : Access Mode specified by Block List Element is incorrect."); + PrintAndLogEx(INFO, " A8 | Illegal Block Number Block Number (access to the specified data is inhibited) :\n" + " | specified by Block List Element exceeds the number of Blocks assigned to Service."); + PrintAndLogEx(INFO, " A9 | Data write failure : This is the error that occurs in issuance commands."); + PrintAndLogEx(INFO, " AA | Key-change failure : Key change failed."); + PrintAndLogEx(INFO, " AB | Illegal Package Parity or illegal Package MAC : This is the error that occurs in issuance commands."); + PrintAndLogEx(INFO, " AC | Illegal parameter : This is the error that occurs in issuance commands."); + PrintAndLogEx(INFO, " AD | Service exists already : This is the error that occurs in issuance commands."); + PrintAndLogEx(INFO, " AE | Illegal System Code : This is the error that occurs in issuance commands."); + PrintAndLogEx(INFO, " AF | Too many simultaneous cyclic write operations : Number of simultaneous write Blocks\n" + " | specified by the command to Cyclic Service exceeds the number of Blocks assigned to Service."); + PrintAndLogEx(INFO, " C0 | Illegal Package Identifier : This is the error that occurs in issuance commands."); + PrintAndLogEx(INFO, " C1 | Discrepancy of parameters inside and outside Package : This is the error that occurs in issuance commands."); + PrintAndLogEx(INFO, " C2 | Command is disabled already : This is the error that occurs in issuance commands."); + PrintAndLogEx(INFO, "----+--------------------------------------------------------------------------------------------------------------------"); + PrintAndLogEx(NORMAL, ""); } static void print_block_list_element_constraints(void) { - PrintAndLogEx(INFO, " - Each Block List Element shall satisfy the following conditions:"); - PrintAndLogEx(INFO, " - The value of Service Code List Order shall not exceed Number of Service."); - PrintAndLogEx(INFO, " - Access Mode shall be 000b."); - PrintAndLogEx(INFO, " - The target specified by Service Code shall not be Area or System."); - PrintAndLogEx(INFO, " - Service specified in Service Code List shall exist in System."); - PrintAndLogEx(INFO, " - Service Attribute of Service specified in Service Code List shall be authentication-not-required Service."); - PrintAndLogEx(INFO, " - Block Number shall be in the range of the number of Blocks assigned to the specified Service."); + PrintAndLogEx(INFO, " - Each Block List Element shall satisfy the following conditions:"); + PrintAndLogEx(INFO, " - The value of Service Code List Order shall not exceed Number of Service."); + PrintAndLogEx(INFO, " - Access Mode shall be 000b."); + PrintAndLogEx(INFO, " - The target specified by Service Code shall not be Area or System."); + PrintAndLogEx(INFO, " - Service specified in Service Code List shall exist in System."); + PrintAndLogEx(INFO, " - Service Attribute of Service specified in Service Code List shall be authentication-not-required Service."); + PrintAndLogEx(INFO, " - Block Number shall be in the range of the number of Blocks assigned to the specified Service."); } static void print_number_of_service_constraints(void) { - PrintAndLogEx(INFO, " - Number of Service: shall be a positive integer in the range of 1 to 16, inclusive."); + PrintAndLogEx(INFO, " - Number of Service: shall be a positive integer in the range of 1 to 16, inclusive."); } static void print_number_of_block_constraints(void) { - PrintAndLogEx(INFO, " - Number of Block: shall be less than or equal to the maximum number of Blocks that can be read simultaneously. \n" - "The maximum number of Blocks that can be read simultaneously can differ, depending on the product being used. Use as default 01"); + PrintAndLogEx(INFO, " - Number of Block: shall be less than or equal to the maximum number of Blocks that can be read simultaneously.\n" + " The maximum number of Blocks that can be read simultaneously can differ, depending on the product being used.\n" + " Use as default 01"); } static void print_service_code_list_constraints(void) { - PrintAndLogEx(INFO, " - Service Code List: For Service Code List, only Service Code existing in the product shall be specified:"); - PrintAndLogEx(INFO, " - Even when Service Code exists in the product, Service Code not referenced from Block List shall not be specified to Service Code List."); - PrintAndLogEx(INFO, " - For existence or nonexistence of Service in a product, please check using the Request Service (or Request Service v2) command."); + PrintAndLogEx(INFO, " - Service Code List: For Service Code List, only Service Code existing in the product shall be specified:"); + PrintAndLogEx(INFO, " - Even when Service Code exists in the product, Service Code not referenced from Block List shall not \n" + " be specified to Service Code List."); + PrintAndLogEx(INFO, " - For existence or nonexistence of Service in a product, please check using the Request Service \n" + " (or Request Service v2) command."); } /* @@ -119,8 +131,6 @@ static int usage_hf_felica_sim(void) { } */ - - static int usage_hf_felica_request_response(void) { PrintAndLogEx(NORMAL, "\nInfo: Use this command to verify the existence of a card and its Mode."); PrintAndLogEx(NORMAL, " - Current Mode of the card is returned."); @@ -185,21 +195,6 @@ static int usage_hf_felica_request_system_code(void) { return PM3_SUCCESS; } -static int usage_hf_felica_reset_mode(void) { - PrintAndLogEx(NORMAL, "\nInfo: Use this command to reset Mode to Mode 0."); - print_status_flag1_interpretation(); - print_status_flag2_interpration(); - PrintAndLogEx(NORMAL, "\nUsage: hf felica resetmode [-h][-i][-r]"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); - PrintAndLogEx(NORMAL, " -r <0A0B hex> set custom reserve to use"); - PrintAndLogEx(NORMAL, "\nExamples: "); - PrintAndLogEx(NORMAL, " hf felica resetmode "); - PrintAndLogEx(NORMAL, " hf felica resetmode -r 0001"); - PrintAndLogEx(NORMAL, " hf felica resetmode -i 11100910C11BC407\n\n"); - return PM3_SUCCESS; -} - static int usage_hf_felica_request_specification_version(void) { PrintAndLogEx(NORMAL, "\nInfo: Use this command to acquire the version of card OS."); PrintAndLogEx(NORMAL, " - Response:"); @@ -366,7 +361,9 @@ int read_felica_uid(bool loop, bool verbose) { felica_card_select_t card; memcpy(&card, (felica_card_select_t *)resp.data.asBytes, sizeof(felica_card_select_t)); - PrintAndLogEx(NORMAL, ""); + if (loop == false) { + PrintAndLogEx(NORMAL, ""); + } PrintAndLogEx(SUCCESS, "IDm: " _GREEN_("%s"), sprint_hex_inrow(card.IDm, sizeof(card.IDm))); set_last_known_card(card); } @@ -581,12 +578,12 @@ int send_rd_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool ver * @return */ static bool check_last_idm(uint8_t *data, uint16_t datalen) { - if (!add_last_IDm(2, data)) { - PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!"); - return 0; + if (add_last_IDm(2, data) == false) { + PrintAndLogEx(WARNING, "No last known card! Use `" _YELLOW_("hf felica reader") "` first or set a custom IDm"); + return false; } else { - PrintAndLogEx(INFO, "Used last known IDm. %s", sprint_hex(data, datalen)); - return 1; + PrintAndLogEx(INFO, "Using last known IDm... " _GREEN_("%s"), sprint_hex_inrow(data, datalen)); + return true; } } @@ -1208,69 +1205,85 @@ static int CmdHFFelicaRequestSpecificationVersion(const char *Cmd) { * @return client result code. */ static int CmdHFFelicaResetMode(const char *Cmd) { - uint8_t data[PM3_CMD_DATA_SIZE]; - bool custom_IDm = false; - bool custom_reserve = false; - strip_cmds(Cmd); - uint16_t datalen = 12; // Length (1), Command ID (1), IDm (8), Reserved (2) - uint8_t paramCount = 0; - uint8_t flags = 0; - int i = 0; - while (Cmd[i] != '\0') { - if (Cmd[i] == '-') { - switch (tolower(Cmd[i + 1])) { - case 'h': - return usage_hf_felica_reset_mode(); - case 'i': - paramCount++; - custom_IDm = true; - if (!add_param(Cmd, paramCount, data, 2, 16)) { - return PM3_EINVARG; - } - paramCount++; - i += 16; - break; - case 'r': - paramCount++; - custom_reserve = true; - if (!add_param(Cmd, paramCount, data, 10, 4)) { - return PM3_EINVARG; - } - paramCount++; - i += 4; - break; - default: - return usage_hf_felica_reset_mode(); - } - } - i++; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica resetmode", + "Use this command to reset Mode to Mode 0.", + "hf felica resetmode\n" + "hf felica resetmode -r 0001\n" + "hf felica resetmode -i 11100910C11BC407 \n" + ); + void *argtable[] = { + arg_param_begin, + arg_str0("i", NULL, "", "set custom IDm"), + arg_str0("r", NULL, "", "set custom reserve"), + arg_lit0("v", "verbose", "verbose helptext"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + uint8_t idm[8] = {0}; + int ilen = 0; + int res = CLIParamHexToBuf(arg_get_str(ctx, 1), idm, sizeof(idm), &ilen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; } + + uint8_t reserved[2] = {0,0}; + int rlen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 2), reserved, sizeof(reserved), &rlen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + bool verbose = arg_get_lit(ctx, 3); + if (verbose) { + print_status_flag1_interpretation(); + print_status_flag2_interpration(); + } + CLIParserFree(ctx); + + uint8_t data[PM3_CMD_DATA_SIZE]; data[0] = 0x0C; // Static length data[1] = 0x3E; // Command ID - if (!custom_reserve) { + + bool custom_IDm = false; + + if (ilen) { + custom_IDm = true; + memcpy(data + 2, idm, 8); + } + if (rlen) { + memcpy(data + 10, reserved, 2); + } else { data[10] = 0x00; // Reserved Value data[11] = 0x00; // Reserved Value } - if (!custom_IDm && !check_last_idm(data, datalen)) { + + uint16_t datalen = 12; // Length (1), Command ID (1), IDm (8), Reserved (2) + if (custom_IDm == false && !check_last_idm(data, datalen)) { return PM3_EINVARG; } + AddCrc(data, datalen); datalen += 2; - flags |= FELICA_APPEND_CRC; - flags |= FELICA_RAW; + uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW); + clear_and_send_command(flags, datalen, data, 0); + PacketResponseNG resp; - if (!waitCmdFelica(0, &resp, 1)) { + if (waitCmdFelica(0, &resp, 1) == false) { PrintAndLogEx(ERR, "\nGot no response from card"); return PM3_ERFTRANS; } else { felica_status_response_t reset_mode_response; memcpy(&reset_mode_response, (felica_status_response_t *)resp.data.asBytes, sizeof(felica_status_response_t)); if (reset_mode_response.frame_response.IDm[0] != 0) { - PrintAndLogEx(SUCCESS, "\nGot Request Response:"); - PrintAndLogEx(SUCCESS, "\nIDm: %s", sprint_hex(reset_mode_response.frame_response.IDm, sizeof(reset_mode_response.frame_response.IDm))); + PrintAndLogEx(SUCCESS, "Got Request Response:"); + PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(reset_mode_response.frame_response.IDm, sizeof(reset_mode_response.frame_response.IDm))); PrintAndLogEx(SUCCESS, "Status Flag1: %s", sprint_hex(reset_mode_response.status_flags.status_flag1, sizeof(reset_mode_response.status_flags.status_flag1))); - PrintAndLogEx(SUCCESS, "Status Flag2: %s\n", sprint_hex(reset_mode_response.status_flags.status_flag2, sizeof(reset_mode_response.status_flags.status_flag2))); + PrintAndLogEx(SUCCESS, "Status Flag2: %s", sprint_hex(reset_mode_response.status_flags.status_flag2, sizeof(reset_mode_response.status_flags.status_flag2))); } } return PM3_SUCCESS; From cf0ffb778dbaecfebd88062bde96bf07fb02c0d3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 12 Apr 2021 21:42:49 +0200 Subject: [PATCH 236/373] hf felica rqservice - now uses cliparser --- client/src/cmdhffelica.c | 82 +++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index d1255cd0b..a449e3828 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -1262,7 +1262,7 @@ static int CmdHFFelicaResetMode(const char *Cmd) { } uint16_t datalen = 12; // Length (1), Command ID (1), IDm (8), Reserved (2) - if (custom_IDm == false && !check_last_idm(data, datalen)) { + if (custom_IDm == false && check_last_idm(data, datalen) == false) { return PM3_EINVARG; } @@ -1378,7 +1378,7 @@ static int CmdHFFelicaRequestService(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_lit0("a", "all", "auto node number mode, iterates through all possible nodes 1 < n < 32"), + arg_lit0("a", "all", "auto node number mode, iterates through all nodes 1 < n < 32"), arg_str0("n", "node", "", "Number of Node"), arg_str0("c", "code", "", "Node Code List (little endian)"), arg_str0("i", "idm", "", "use custom IDm"), @@ -1387,50 +1387,52 @@ static int CmdHFFelicaRequestService(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, true); bool all_nodes = arg_get_lit(ctx, 1); -// int dlen = 0; -// int res = 0; + uint8_t node[1] = {0}; + int nlen = 0; + int res = CLIParamHexToBuf(arg_get_str(ctx, 2), node, sizeof(node), &nlen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + uint8_t code[2] = {0,0}; + int clen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 3), code, sizeof(code), &clen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint8_t idm[8] = {0}; + int ilen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 4), idm, sizeof(idm), &ilen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } CLIParserFree(ctx); uint8_t data[PM3_CMD_DATA_SIZE]; bool custom_IDm = false; - uint16_t datalen = 13; // length (1) + CMD (1) + IDm(8) + Node Number (1) + Node Code List (2) - /* - case 'i': + if (ilen) { + custom_IDm = true; + memcpy(data + 2, idm, 8); + } - custom_IDm = true; - if (!add_param(Cmd, paramCount, data, 2, 16)) { - return PM3_EINVARG; - } - - - if (!all_nodes) { - // Node Number - if (param_getlength(Cmd, paramCount) == 2) { - - if (param_gethex(Cmd, paramCount++, data + 10, 2) == 1) { - PrintAndLogEx(ERR, "Failed param key"); - return PM3_EINVARG; - } - - } else { - PrintAndLogEx(ERR, "Incorrect Node number length!"); - return PM3_EINVARG; - } + if (all_nodes == false) { + // Node Number + if (nlen == 1) { + memcpy(data + 10, node, sizeof(node)); } - if (param_getlength(Cmd, paramCount) == 4) { - - if (param_gethex(Cmd, paramCount++, data + 11, 4) == 1) { - PrintAndLogEx(ERR, "Failed param key"); - return PM3_EINVARG; - } - } else { - PrintAndLogEx(ERR, "Incorrect parameter length!"); - return PM3_EINVARG; + // code + if (clen == 2) { + memcpy(data + 11, code, sizeof(code)); } - */ + } + + uint8_t datalen = 13; // length (1) + CMD (1) + IDm(8) + Node Number (1) + Node Code List (2) uint8_t flags = FELICA_APPEND_CRC; if (custom_IDm) { @@ -1440,20 +1442,22 @@ static int CmdHFFelicaRequestService(const char *Cmd) { if (datalen > 0) { flags |= FELICA_RAW; } - -// Todo activate once datalen isn't hardcoded anymore... - if (!custom_IDm && !check_last_idm(data, datalen)) { + // Todo activate once datalen isn't hardcoded anymore... + if (custom_IDm == false && check_last_idm(data, datalen) == false) { return PM3_EINVARG; } data[0] = (datalen & 0xFF); data[1] = 0x02; // Service Request Command ID if (all_nodes) { + + // send 32 calls for (uint8_t i = 1; i < 32; i++) { data[10] = i; AddCrc(data, datalen); send_request_service(flags, datalen + 2, data, 1); } + } else { AddCrc(data, datalen); send_request_service(flags, datalen + 2, data, 1); From 935ba8289ac08fcf1cce213891efe1e5f8ce2dd2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 12 Apr 2021 22:10:38 +0200 Subject: [PATCH 237/373] hf felica rqsyscode, rqspecver - now uses cliparser --- client/src/cmdhffelica.c | 311 ++++++++++++++++++++------------------- doc/cliparser_todo.txt | 3 - 2 files changed, 157 insertions(+), 157 deletions(-) diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index a449e3828..7a63408b6 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -183,40 +183,6 @@ static int usage_hf_felica_write_without_encryption(void) { return PM3_SUCCESS; } -static int usage_hf_felica_request_system_code(void) { - PrintAndLogEx(NORMAL, "\nInfo: Use this command to acquire System Code registered to the card."); - PrintAndLogEx(NORMAL, " - If a card is divided into more than one System, this command acquires System Code of each System existing in the card."); - PrintAndLogEx(NORMAL, "\nUsage: hf felica rqsyscode [-h] [-i]"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); - PrintAndLogEx(NORMAL, "\nExamples: "); - PrintAndLogEx(NORMAL, " hf felica rqsyscode "); - PrintAndLogEx(NORMAL, " hf felica rqsyscode -i 11100910C11BC407\n\n"); - return PM3_SUCCESS; -} - -static int usage_hf_felica_request_specification_version(void) { - PrintAndLogEx(NORMAL, "\nInfo: Use this command to acquire the version of card OS."); - PrintAndLogEx(NORMAL, " - Response:"); - PrintAndLogEx(NORMAL, " - Format Version: Fixed value 00h. Provided only if Status Flag1 = 00h."); - PrintAndLogEx(NORMAL, " - Basic Version: Each value of version is expressed in BCD notation . Provided only if Status Flag1 = 00h."); - PrintAndLogEx(NORMAL, " - Number of Option: value = 0: AES card, value = 1: AES/DES card. Provided only if Status Flag1 = 00h."); - PrintAndLogEx(NORMAL, " - Option Version List: Provided only if Status Flag1 = 00h."); - PrintAndLogEx(NORMAL, " - For AES card: not added."); - PrintAndLogEx(NORMAL, " - For AES/DES card: DES option version is added - BCD notation ."); - print_status_flag1_interpretation(); - print_status_flag2_interpration(); - PrintAndLogEx(NORMAL, "\nUsage: hf felica rqspecver [-h][-i][-r]"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); - PrintAndLogEx(NORMAL, " -r <0A0B hex> set custom reserve to use"); - PrintAndLogEx(NORMAL, "\nExamples: "); - PrintAndLogEx(NORMAL, " hf felica rqspecver "); - PrintAndLogEx(NORMAL, " hf felica rqspecver -r 0001"); - PrintAndLogEx(NORMAL, " hf felica rqspecver -i 11100910C11BC407\n\n"); - return PM3_SUCCESS; -} - static int usage_hf_felica_authentication1(void) { PrintAndLogEx(NORMAL, "\nInfo: Initiate mutual authentication. This command must always be executed before Authentication2 command" ", and mutual authentication is achieve only after Authentication2 command has succeeded."); @@ -319,9 +285,8 @@ static bool add_last_IDm(uint8_t position, uint8_t *data) { if (last_known_card.IDm[0] != 0 && last_known_card.IDm[1] != 0) { memcpy(data + position, last_known_card.IDm, sizeof(last_known_card.IDm)); return true; - } else { - return false; - } + } + return false; } static int CmdHFFelicaList(const char *Cmd) { @@ -581,10 +546,10 @@ static bool check_last_idm(uint8_t *data, uint16_t datalen) { if (add_last_IDm(2, data) == false) { PrintAndLogEx(WARNING, "No last known card! Use `" _YELLOW_("hf felica reader") "` first or set a custom IDm"); return false; - } else { - PrintAndLogEx(INFO, "Using last known IDm... " _GREEN_("%s"), sprint_hex_inrow(data, datalen)); - return true; } + + PrintAndLogEx(INFO, "Using last known IDm... " _GREEN_("%s"), sprint_hex_inrow(data, datalen)); + return true; } /** @@ -599,13 +564,13 @@ static bool check_last_idm(uint8_t *data, uint16_t datalen) { static int send_wr_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_status_response_t *wr_noCry_resp) { clear_and_send_command(flags, datalen, data, verbose); PacketResponseNG resp; - if (!waitCmdFelica(0, &resp, verbose)) { - PrintAndLogEx(ERR, "\nGot no response from card"); + if (waitCmdFelica(0, &resp, verbose) == false) { + PrintAndLogEx(ERR, "Got no response from card"); return PM3_ERFTRANS; - } else { - memcpy(wr_noCry_resp, (felica_status_response_t *)resp.data.asBytes, sizeof(felica_status_response_t)); - return PM3_SUCCESS; - } + } + + memcpy(wr_noCry_resp, (felica_status_response_t *)resp.data.asBytes, sizeof(felica_status_response_t)); + return PM3_SUCCESS; } /** @@ -1118,79 +1083,108 @@ static int CmdHFFelicaRequestResponse(const char *Cmd) { * @return client result code. */ static int CmdHFFelicaRequestSpecificationVersion(const char *Cmd) { - uint8_t data[PM3_CMD_DATA_SIZE]; - bool custom_IDm = false; - bool custom_reserve = false; - strip_cmds(Cmd); - uint16_t datalen = 12; // Length (1), Command ID (1), IDm (8), Reserved (2) - uint8_t paramCount = 0; - uint8_t flags = 0; - int i = 0; - while (Cmd[i] != '\0') { - if (Cmd[i] == '-') { - switch (tolower(Cmd[i + 1])) { - case 'h': - return usage_hf_felica_request_specification_version(); - case 'i': - paramCount++; - custom_IDm = true; - if (!add_param(Cmd, paramCount, data, 2, 16)) { - return PM3_EINVARG; - } - paramCount++; - i += 16; - break; - case 'r': - paramCount++; - custom_reserve = true; - if (!add_param(Cmd, paramCount, data, 10, 4)) { - return PM3_EINVARG; - } - paramCount++; - i += 4; - break; - default: - return usage_hf_felica_request_specification_version(); - } - } - i++; + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica rqspecver", + "Use this command to acquire the version of card OS.\n" + "Response:\n" + " - Format version: Fixed value 00h. Provided only if Status Flag1 = 00h\n" + " - Basic version: Each value of version is expressed in BCD notation. Provided only if Status Flag1 = 00h\n" + " - Number of Option: value = 0: AES card, value = 1: AES/DES card. Provided only if Status Flag1 = 00h\n" + " - Option version list: Provided only if Status Flag1 = 00h\n" + " - AES card: not added\n" + " - AES/DES card: DES option version is added - BCD notation", + + "hf felica rqspecver\n" + "hf felica rqspecver -r 0001\n" + "hf felica rqspecver -i 11100910C11BC407 \n" + ); + void *argtable[] = { + arg_param_begin, + arg_str0("i", NULL, "", "set custom IDm"), + arg_str0("r", NULL, "", "set custom reserve"), + arg_lit0("v", "verbose", "verbose helptext"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + uint8_t idm[8] = {0}; + int ilen = 0; + int res = CLIParamHexToBuf(arg_get_str(ctx, 1), idm, sizeof(idm), &ilen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; } + + uint8_t reserved[2] = {0,0}; + int rlen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 2), reserved, sizeof(reserved), &rlen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + bool verbose = arg_get_lit(ctx, 3); + if (verbose) { + print_status_flag1_interpretation(); + print_status_flag2_interpration(); + } + CLIParserFree(ctx); + + uint8_t data[PM3_CMD_DATA_SIZE]; data[0] = 0x0C; // Static length data[1] = 0x3C; // Command ID - if (!custom_reserve) { + + bool custom_IDm = false; + + // add custom idm + if (ilen) { + custom_IDm = true; + memcpy(data + 2, idm, sizeof(idm)); + } + + // add custom reserved + if (rlen ) { + memcpy(data +10, reserved, sizeof(reserved)); + } else { data[10] = 0x00; // Reserved Value data[11] = 0x00; // Reserved Value } - if (!custom_IDm && !check_last_idm(data, datalen)) { + + uint16_t datalen = 12; // Length (1), Command ID (1), IDm (8), Reserved (2) + if (custom_IDm == false && check_last_idm(data, datalen) == false) { return PM3_EINVARG; } + AddCrc(data, datalen); datalen += 2; - flags |= FELICA_APPEND_CRC; - flags |= FELICA_RAW; - clear_and_send_command(flags, datalen, data, 0); - PacketResponseNG resp; - if (!waitCmdFelica(0, &resp, 1)) { - PrintAndLogEx(ERR, "\nGot no response from card"); - return PM3_ERFTRANS; - } else { - felica_request_spec_response_t spec_response; - memcpy(&spec_response, (felica_request_spec_response_t *)resp.data.asBytes, sizeof(felica_request_spec_response_t)); + uint8_t flags = (FELICA_APPEND_CRC |FELICA_RAW); - if (spec_response.frame_response.IDm[0] != 0) { - PrintAndLogEx(SUCCESS, "\nGot Request Response:"); - PrintAndLogEx(SUCCESS, "\nIDm: %s", sprint_hex(spec_response.frame_response.IDm, sizeof(spec_response.frame_response.IDm))); - PrintAndLogEx(SUCCESS, "Status Flag1: %s", sprint_hex(spec_response.status_flags.status_flag1, sizeof(spec_response.status_flags.status_flag1))); - PrintAndLogEx(SUCCESS, "Status Flag2: %s", sprint_hex(spec_response.status_flags.status_flag2, sizeof(spec_response.status_flags.status_flag2))); - if (spec_response.status_flags.status_flag1[0] == 0x00) { - PrintAndLogEx(SUCCESS, "Format Version: %s", sprint_hex(spec_response.format_version, sizeof(spec_response.format_version))); - PrintAndLogEx(SUCCESS, "Basic Version: %s", sprint_hex(spec_response.basic_version, sizeof(spec_response.basic_version))); - PrintAndLogEx(SUCCESS, "Number of Option: %s", sprint_hex(spec_response.number_of_option, sizeof(spec_response.number_of_option))); - if (spec_response.number_of_option[0] == 0x01) { - PrintAndLogEx(SUCCESS, "Option Version List:"); - for (i = 0; i < spec_response.number_of_option[0]; i++) { - PrintAndLogEx(SUCCESS, " - %s", sprint_hex(spec_response.option_version_list + i * 2, sizeof(uint8_t) * 2)); - } + clear_and_send_command(flags, datalen, data, 0); + + PacketResponseNG resp; + if (waitCmdFelica(0, &resp, 1) == false) { + PrintAndLogEx(FAILED, "Got no response from card"); + return PM3_ERFTRANS; + } + + felica_request_spec_response_t spec_response; + memcpy(&spec_response, (felica_request_spec_response_t *)resp.data.asBytes, sizeof(felica_request_spec_response_t)); + + if (spec_response.frame_response.IDm[0] != 0) { + PrintAndLogEx(SUCCESS, "Got Request Response"); + PrintAndLogEx(SUCCESS, "IDm............ %s", sprint_hex(spec_response.frame_response.IDm, sizeof(spec_response.frame_response.IDm))); + PrintAndLogEx(SUCCESS, "Status Flag1... %s", sprint_hex(spec_response.status_flags.status_flag1, sizeof(spec_response.status_flags.status_flag1))); + PrintAndLogEx(SUCCESS, "Status Flag2... %s", sprint_hex(spec_response.status_flags.status_flag2, sizeof(spec_response.status_flags.status_flag2))); + + if (spec_response.status_flags.status_flag1[0] == 0) { + PrintAndLogEx(SUCCESS, "Format Version..... %s", sprint_hex(spec_response.format_version, sizeof(spec_response.format_version))); + PrintAndLogEx(SUCCESS, "Basic Version...... %s", sprint_hex(spec_response.basic_version, sizeof(spec_response.basic_version))); + PrintAndLogEx(SUCCESS, "Number of Option... %s", sprint_hex(spec_response.number_of_option, sizeof(spec_response.number_of_option))); + if (spec_response.number_of_option[0] == 1) { + PrintAndLogEx(SUCCESS, "Option Version List..."); + for (int i = 0; i < spec_response.number_of_option[0]; i++) { + PrintAndLogEx(SUCCESS, " - %s", sprint_hex(spec_response.option_version_list + i * 2, 2)); } } } @@ -1274,17 +1268,17 @@ static int CmdHFFelicaResetMode(const char *Cmd) { PacketResponseNG resp; if (waitCmdFelica(0, &resp, 1) == false) { - PrintAndLogEx(ERR, "\nGot no response from card"); + PrintAndLogEx(ERR, "Got no response from card"); return PM3_ERFTRANS; - } else { - felica_status_response_t reset_mode_response; - memcpy(&reset_mode_response, (felica_status_response_t *)resp.data.asBytes, sizeof(felica_status_response_t)); - if (reset_mode_response.frame_response.IDm[0] != 0) { - PrintAndLogEx(SUCCESS, "Got Request Response:"); - PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(reset_mode_response.frame_response.IDm, sizeof(reset_mode_response.frame_response.IDm))); - PrintAndLogEx(SUCCESS, "Status Flag1: %s", sprint_hex(reset_mode_response.status_flags.status_flag1, sizeof(reset_mode_response.status_flags.status_flag1))); - PrintAndLogEx(SUCCESS, "Status Flag2: %s", sprint_hex(reset_mode_response.status_flags.status_flag2, sizeof(reset_mode_response.status_flags.status_flag2))); - } + } + + felica_status_response_t reset_mode_response; + memcpy(&reset_mode_response, (felica_status_response_t *)resp.data.asBytes, sizeof(felica_status_response_t)); + if (reset_mode_response.frame_response.IDm[0] != 0) { + PrintAndLogEx(SUCCESS, "Request Response"); + PrintAndLogEx(SUCCESS, "IDm............ %s", sprint_hex(reset_mode_response.frame_response.IDm, sizeof(reset_mode_response.frame_response.IDm))); + PrintAndLogEx(SUCCESS, "Status Flag1... %s", sprint_hex(reset_mode_response.status_flags.status_flag1, sizeof(reset_mode_response.status_flags.status_flag1))); + PrintAndLogEx(SUCCESS, "Status Flag2... %s", sprint_hex(reset_mode_response.status_flags.status_flag2, sizeof(reset_mode_response.status_flags.status_flag2))); } return PM3_SUCCESS; } @@ -1295,42 +1289,51 @@ static int CmdHFFelicaResetMode(const char *Cmd) { * @return client result code. */ static int CmdHFFelicaRequestSystemCode(const char *Cmd) { - uint8_t data[PM3_CMD_DATA_SIZE]; - bool custom_IDm = false; - strip_cmds(Cmd); - uint16_t datalen = 10; // Length (1), Command ID (1), IDm (8) - uint8_t paramCount = 0; - uint8_t flags = 0; - int i = 0; - while (Cmd[i] != '\0') { - if (Cmd[i] == '-') { - switch (tolower(Cmd[i + 1])) { - case 'h': - return usage_hf_felica_request_system_code(); - case 'i': - paramCount++; - custom_IDm = true; - if (!add_param(Cmd, paramCount, data, 2, 16)) { - return PM3_EINVARG; - } - paramCount++; - i += 16; - break; - default: - return usage_hf_felica_request_system_code(); - } - } - i++; - } - data[0] = 0x0A; // Static length - data[1] = 0x0C; // Command ID - if (!custom_IDm && !check_last_idm(data, datalen)) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica rqsyscode", + "Use this command to acquire System Code registered to the card." + " - if a card is divided into more than one System, \n" + " this command acquires System Code of each System existing in the card.", + "hf felica rqsyscode\n" + "hf felica rqsyscode -i 11100910C11BC407 \n" + ); + void *argtable[] = { + arg_param_begin, + arg_str0("i", NULL, "", "set custom IDm"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + uint8_t idm[8] = {0}; + int ilen = 0; + int res = CLIParamHexToBuf(arg_get_str(ctx, 1), idm, sizeof(idm), &ilen); + if (res) { + CLIParserFree(ctx); return PM3_EINVARG; } + CLIParserFree(ctx); + + + uint8_t data[PM3_CMD_DATA_SIZE]; + data[0] = 0x0A; // Static length + data[1] = 0x0C; // Command ID + + bool custom_IDm = false; + if (ilen) { + custom_IDm = true; + memcpy(data + 2, idm, sizeof(idm)); + } + + uint16_t datalen = 10; // Length (1), Command ID (1), IDm (8) + if (custom_IDm == false && check_last_idm(data, datalen) == false) { + return PM3_EINVARG; + } + AddCrc(data, datalen); datalen += 2; - flags |= FELICA_APPEND_CRC; - flags |= FELICA_RAW; + uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW); + clear_and_send_command(flags, datalen, data, 0); PacketResponseNG resp; @@ -1343,13 +1346,13 @@ static int CmdHFFelicaRequestSystemCode(const char *Cmd) { memcpy(&rq_syscode_response, (felica_syscode_response_t *)resp.data.asBytes, sizeof(felica_syscode_response_t)); if (rq_syscode_response.frame_response.IDm[0] != 0) { - PrintAndLogEx(SUCCESS, "\nGot Request Response:"); - PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(rq_syscode_response.frame_response.IDm, sizeof(rq_syscode_response.frame_response.IDm))); + PrintAndLogEx(SUCCESS, "Request Response"); + PrintAndLogEx(SUCCESS, "IDm... %s", sprint_hex(rq_syscode_response.frame_response.IDm, sizeof(rq_syscode_response.frame_response.IDm))); PrintAndLogEx(SUCCESS, " - Number of Systems: %s", sprint_hex(rq_syscode_response.number_of_systems, sizeof(rq_syscode_response.number_of_systems))); PrintAndLogEx(SUCCESS, " - System Codes: enumerated in ascending order starting from System 0."); - for (i = 0; i < rq_syscode_response.number_of_systems[0]; i++) { - PrintAndLogEx(SUCCESS, " - %s", sprint_hex(rq_syscode_response.system_code_list + i * 2, sizeof(uint8_t) * 2)); + for (int i = 0; i < rq_syscode_response.number_of_systems[0]; i++) { + PrintAndLogEx(SUCCESS, " - %s", sprint_hex(rq_syscode_response.system_code_list + i * 2, 2)); } } diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index fac683247..d5c841d93 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -11,8 +11,5 @@ hf felica rdunencrypted hf felica wrunencrypted hf felica rqresponse hf felica scsvcode -hf felica rqsyscode hf felica auth1 hf felica auth2 -hf felica rqspecver -hf felica resetmode From 4d2f8a3bd5edab7817cdff2fe0059a7861476449 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 12 Apr 2021 22:49:19 +0200 Subject: [PATCH 238/373] hf felica rqresponse - now uses cliparser --- client/src/cmdhffelica.c | 97 +++++++++++++++++++--------------------- doc/cliparser_todo.txt | 1 - 2 files changed, 47 insertions(+), 51 deletions(-) diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 7a63408b6..090b7359c 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -131,16 +131,6 @@ static int usage_hf_felica_sim(void) { } */ -static int usage_hf_felica_request_response(void) { - PrintAndLogEx(NORMAL, "\nInfo: Use this command to verify the existence of a card and its Mode."); - PrintAndLogEx(NORMAL, " - Current Mode of the card is returned."); - PrintAndLogEx(NORMAL, "\nUsage: hf felica rqresponse [-h]"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); - PrintAndLogEx(NORMAL, " hf felica rqresponse -i 01100910c11bc407"); - return PM3_SUCCESS; -} - static int usage_hf_felica_read_without_encryption(void) { PrintAndLogEx(NORMAL, "\nInfo: Use this command to read Block Data from authentication-not-required Service."); PrintAndLogEx(NORMAL, " - Mode shall be Mode0."); @@ -1023,60 +1013,68 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { * @return client result code. */ static int CmdHFFelicaRequestResponse(const char *Cmd) { - uint8_t data[PM3_CMD_DATA_SIZE]; - bool custom_IDm = false; - strip_cmds(Cmd); - uint16_t datalen = 10; // Length (1), Command ID (1), IDm (8) - uint8_t paramCount = 0; - uint8_t flags = 0; - int i = 0; - while (Cmd[i] != '\0') { - if (Cmd[i] == '-') { - switch (tolower(Cmd[i + 1])) { - case 'h': - return usage_hf_felica_request_response(); - case 'i': - paramCount++; - custom_IDm = true; - if (!add_param(Cmd, paramCount, data, 2, 16)) { - return PM3_EINVARG; - } - paramCount++; - i += 16; - break; - default: - return usage_hf_felica_request_response(); - } - } - i++; + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica rqresponse", + "Use this command to verify the existence of a card and its Mode.\n" + " - current mode of the card is returned", + "hf felica rqresponse -i 11100910C11BC407\n" + ); + void *argtable[] = { + arg_param_begin, + arg_str0("i", NULL, "", "set custom IDm"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + uint8_t idm[8] = {0}; + int ilen = 0; + int res = CLIParamHexToBuf(arg_get_str(ctx, 1), idm, sizeof(idm), &ilen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; } + + CLIParserFree(ctx); + + uint8_t data[PM3_CMD_DATA_SIZE]; data[0] = 0x0A; // Static length data[1] = 0x04; // Command ID + + bool custom_IDm = false; + if (ilen) { + custom_IDm = true; + memcpy(data + 2, idm, sizeof(idm)); + } + + uint8_t datalen = 10; // Length (1), Command ID (1), IDm (8) if (!custom_IDm && !check_last_idm(data, datalen)) { return PM3_EINVARG; } + AddCrc(data, datalen); datalen += 2; - flags |= FELICA_APPEND_CRC; - flags |= FELICA_RAW; + + uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW); clear_and_send_command(flags, datalen, data, 0); + PacketResponseNG resp; - if (!waitCmdFelica(0, &resp, 1)) { - PrintAndLogEx(ERR, "\nGot no response from card"); + if (waitCmdFelica(0, &resp, 1) == false) { + PrintAndLogEx(ERR, "Got no response from card"); return PM3_ERFTRANS; - } else { - felica_request_request_response_t rq_response; - memcpy(&rq_response, (felica_request_request_response_t *)resp.data.asBytes, sizeof(felica_request_request_response_t)); - if (rq_response.frame_response.IDm[0] != 0) { - PrintAndLogEx(SUCCESS, "\nGot Request Response:"); - PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(rq_response.frame_response.IDm, sizeof(rq_response.frame_response.IDm))); - PrintAndLogEx(SUCCESS, " -Mode: %s\n\n", sprint_hex(rq_response.mode, sizeof(rq_response.mode))); - } } + + felica_request_request_response_t rq_response; + memcpy(&rq_response, (felica_request_request_response_t *)resp.data.asBytes, sizeof(felica_request_request_response_t)); + if (rq_response.frame_response.IDm[0] != 0) { + PrintAndLogEx(SUCCESS, "Request Response"); + PrintAndLogEx(SUCCESS, "IDm...... %s", sprint_hex(rq_response.frame_response.IDm, sizeof(rq_response.frame_response.IDm))); + PrintAndLogEx(SUCCESS, " Mode... %s", sprint_hex(rq_response.mode, sizeof(rq_response.mode))); + } + return PM3_SUCCESS; } - /** * Command parser for rqspecver * @param Cmd input data of the user. @@ -1192,7 +1190,6 @@ static int CmdHFFelicaRequestSpecificationVersion(const char *Cmd) { return PM3_SUCCESS; } - /** * Command parser for resetmode * @param Cmd input data of the user. diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index d5c841d93..c1a82050c 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -9,7 +9,6 @@ hf 15 writeafi hf 15 writedsfid hf felica rdunencrypted hf felica wrunencrypted -hf felica rqresponse hf felica scsvcode hf felica auth1 hf felica auth2 From 6eb02c5f8e12d37dac5ee26135c6392b6618fa35 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 13 Apr 2021 08:17:11 +0200 Subject: [PATCH 239/373] cppchecker fixes --- armsrc/desfire_crypto.c | 4 ++-- armsrc/iclass.c | 6 +++--- armsrc/lfops.c | 2 +- armsrc/mifaredesfire.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/armsrc/desfire_crypto.c b/armsrc/desfire_crypto.c index d414835c0..782466be2 100644 --- a/armsrc/desfire_crypto.c +++ b/armsrc/desfire_crypto.c @@ -430,7 +430,7 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes, break; // Append MAC size_t bla = maced_data_length(DESFIRE(tag)->session_key, *nbytes - offset) + offset; - bla++; + (void)bla++; memcpy(res + *nbytes, mac, 4); @@ -443,7 +443,7 @@ void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes, if (append_mac) { size_t len = maced_data_length(key, *nbytes); - ++len; + (void)++len; memcpy(res, data, *nbytes); memcpy(res + *nbytes, DESFIRE(tag)->cmac, CMAC_LENGTH); *nbytes += CMAC_LENGTH; diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 856db35f7..c1b80639b 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -860,7 +860,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) { } else if (cmd == ICLASS_CMD_DETECT) { // 0x0F // not supported yet, ignore - } else if (cmd == 0x26 && len == 5) { +// } else if (cmd == 0x26 && len == 5) { // standard ISO15693 INVENTORY command. Ignore. } else { // Never seen this command before @@ -1021,7 +1021,7 @@ int do_iclass_simulation_nonsec(void) { bool button_pressed = false; uint8_t cmd, options, block; - int len = 0; + int len; bool exit_loop = false; while (exit_loop == false) { @@ -1213,7 +1213,7 @@ int do_iclass_simulation_nonsec(void) { goto send; // } else if(cmd == ICLASS_CMD_DETECT) { // 0x0F - } else if (cmd == 0x26 && len == 5) { +// } else if (cmd == 0x26 && len == 5) { // standard ISO15693 INVENTORY command. Ignore. } else { // Never seen this command before diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 1cfb68326..b03ee9f43 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -2107,7 +2107,7 @@ void T55xx_ChkPwds(uint8_t flags) { #endif - uint64_t curr = 0, prev = 0; + uint64_t curr, prev = 0; int32_t idx = -1; for (uint32_t i = 0; i < pwd_count; i++) { diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index b6ca949c6..b22f4db09 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -271,7 +271,7 @@ void MifareDES_Auth1(uint8_t *datain) { memcpy(keybytes, PICC_MASTER_KEY8, 8); } else if (payload->algo == MFDES_ALGO_AES || payload->algo == MFDES_ALGO_3DES) { memcpy(keybytes, PICC_MASTER_KEY16, 16); - } else if (payload->algo == MFDES_ALGO_3DES) { + } else if (payload->algo == MFDES_ALGO_3K3DES) { memcpy(keybytes, PICC_MASTER_KEY24, 24); } } else { From 536ddd17fde580f98bb30c277d87653e77ac7acc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 13 Apr 2021 10:02:48 +0200 Subject: [PATCH 240/373] cppchecker fixes --- client/src/cmdhficlass.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index cd7e5b62e..cedcdc36e 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -255,11 +255,10 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke iclass_last_known_card.conf.app_limit = 0x16; tot_bytes = (app1_limit + 1) * 8; - uint8_t *p; - p = realloc(data, tot_bytes); + uint8_t *p = realloc(data, tot_bytes); if (p == NULL) { PrintAndLogEx(FAILED, "failed to allocate memory"); - free(data); + //free(data); return PM3_EMALLOC; } data = p; @@ -1155,7 +1154,6 @@ static int CmdHFiClassDecrypt(const char *Cmd) { bool verbose = arg_get_lit(clictx, 4); CLIParserFree(clictx); - uint8_t dec_data[8] = {0}; bool use_sc = false; if (have_key == false) { use_sc = IsCardHelperPresent(verbose); @@ -1181,6 +1179,8 @@ static int CmdHFiClassDecrypt(const char *Cmd) { mbedtls_des3_context ctx; mbedtls_des3_set2key_dec(&ctx, key); + uint8_t dec_data[8] = {0}; + if (have_data) { if (use_sc) { @@ -3735,9 +3735,9 @@ static int CmdHFiClassConfigCard(const char *Cmd) { int ccidx = arg_get_int_def(ctx, 1, -1); int kidx = arg_get_int_def(ctx, 2, -1); - bool generate = arg_get_lit(ctx, 3); - bool load = arg_get_lit(ctx, 4); - bool print = arg_get_lit(ctx, 5); + bool do_generate = arg_get_lit(ctx, 3); + bool do_load = arg_get_lit(ctx, 4); + bool do_print = arg_get_lit(ctx, 5); CLIParserFree(ctx); bool got_kr = false; @@ -3753,13 +3753,13 @@ static int CmdHFiClassConfigCard(const char *Cmd) { } } - if (load) { + if (do_load) { if (load_config_cards() != PM3_SUCCESS) { PrintAndLogEx(INFO, "failed to load, check your cardhelper"); } } - if (print) { + if (do_print) { print_config_cards(); } @@ -3768,7 +3768,7 @@ static int CmdHFiClassConfigCard(const char *Cmd) { print_config_card(item); } - if (generate) { + if (do_generate) { const iclass_config_card_item_t *item = get_config_card_item(ccidx); if (strstr(item->desc, "Keyroll") != NULL) { if (got_kr == false) { From 66a9490fe7061d678003a3609f5c8d81ad61de49 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 13 Apr 2021 11:05:39 +0200 Subject: [PATCH 241/373] lf t55xx restore - now support bin/eml/json formats --- client/src/cmdlft55xx.c | 202 ++++++++++++++++++++-------------------- 1 file changed, 103 insertions(+), 99 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 99db98058..63ff9c46f 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -2302,13 +2302,13 @@ static int CmdT55xxDump(const char *Cmd) { static int CmdT55xxRestore(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf t55xx restore", - "This command restores T55xx card page 0/1 n blocks", + "Restore T55xx card page 0/1 n blocks from (bin/eml/json) dump file", "lf t55xx restore -f lf-t55xx-00148040-dump.bin" ); void *argtable[] = { arg_param_begin, - arg_str0("f", "filename", "", "filename of the dump file (bin|eml)"), + arg_str0("f", "file", "", "filename of dump file"), arg_str0("p", "pwd", "", "password if target card has password set (4 hex bytes)"), arg_param_end }; @@ -2336,94 +2336,104 @@ static int CmdT55xxRestore(const char *Cmd) { return PM3_EINVARG; } - char ext[FILE_PATH_SIZE] = {0}; - uint32_t data[12] = {0}; - size_t datalen = 0; + size_t dlen = 0; + uint8_t *dump = calloc(T55x7_BLOCK_COUNT * 4, sizeof(uint8_t)); + if (dump == NULL) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); + return PM3_EMALLOC; + } - 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) { - filename[fnlen - 4] = 0x00; - retval = loadFile(filename, ".bin", data, sizeof(data), &datalen); - - } else if (memcmp(ext, ".eml", 4) == 0) { - filename[fnlen - 4] = 0x00; - datalen = 12; - retval = loadFileEML(filename, (uint8_t *)data, &datalen); - - } else { - PrintAndLogEx(WARNING, "\nWarning: invalid dump filename "_YELLOW_("%s")" to restore!\n", filename); + DumpFileType_t dftype = getfiletype(filename); + switch (dftype) { + case BIN: { + res = loadFile_safe(filename, ".bin", (void **)&dump, &dlen); + break; + } + case EML: { + res = loadFileEML_safe(filename, (void **)&dump, &dlen); + break; + } + case JSON: { + res = loadFileJSON(filename, dump, T55x7_BLOCK_COUNT * 4, &dlen, NULL); + break; + } + case DICTIONARY: { + PrintAndLogEx(ERR, "Error: Only BIN/EML/JSON formats allowed"); + free(dump); + return PM3_EINVARG; } } - if (retval != PM3_SUCCESS) { - return retval; + //sanity checks of file processing + if (res != PM3_SUCCESS) { + return res; } - if (datalen == T55x7_BLOCK_COUNT * 4) { - // 12 blocks * 4 bytes per block + if (dlen != T55x7_BLOCK_COUNT * 4) { + free(dump); + PrintAndLogEx(FAILED, "wrong length of dump file. Expected 48 bytes, got %zu", dlen); + return PM3_EFILE; + } - // this fct creats strings to call "lf t55 write" command. - // - // - uint8_t downlink_mode; - char wcmd[100]; - char pwdopt [14] = {0}; // p XXXXXXXX + // 12 blocks * 4 bytes per block + // this part creates strings to call "lf t55 write" command. + PrintAndLogEx(INFO, "Starting to write..."); - if (usepwd) - snprintf(pwdopt, sizeof(pwdopt), "-p %08X", password); + uint8_t downlink_mode; + char wcmd[100]; + char pwdopt [14] = {0}; // p XXXXXXXX - uint8_t idx; - // Restore endien for writing to card - for (idx = 0; idx < 12; idx++) { - data[idx] = BSWAP_32(data[idx]); - } + if (usepwd) + snprintf(pwdopt, sizeof(pwdopt), "-p %08X", password); - // 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; + uint32_t *data = (uint32_t*) dump; + uint8_t idx; + // Restore endien for writing to card + for (idx = 0; idx < 12; idx++) { + data[idx] = BSWAP_32(data[idx]); + } - // write out blocks 1-7 page 0 - for (idx = 1; idx <= 7; idx++) { - snprintf(wcmd, sizeof(wcmd), "-b %d -d %08X %s", idx, data[idx], pwdopt); + // 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; - if (CmdT55xxWriteBlock(wcmd) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "Warning: error writing blk %d", idx); - } - } + // write out blocks 1-7 page 0 + for (idx = 1; idx <= 7; idx++) { + snprintf(wcmd, sizeof(wcmd), "-b %d -d %08X %s", idx, data[idx], pwdopt); - // 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(wcmd, sizeof(wcmd), "-b %d --pg1 -d %08X %s", idx - 8, data[idx], pwdopt); - - if (CmdT55xxWriteBlock(wcmd) != 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(wcmd, sizeof(wcmd), "-b 0 -d %08X %s", data[0], pwdopt); if (CmdT55xxWriteBlock(wcmd) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "Warning: error writing blk 0"); + 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(wcmd, sizeof(wcmd), "-b %d --pg1 -d %08X %s", idx - 8, data[idx], pwdopt); + + if (CmdT55xxWriteBlock(wcmd) != 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(wcmd, sizeof(wcmd), "-b 0 -d %08X %s", data[0], pwdopt); + if (CmdT55xxWriteBlock(wcmd) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "Warning: error writing blk 0"); + } + PrintAndLogEx(INFO, "Done!"); return PM3_SUCCESS; } /* @@ -2546,7 +2556,7 @@ char *GetBitRateStr(uint32_t id, bool xmode) { char *retStr = buf; if (xmode) { //xmode bitrate calc is same as em4x05 calc - snprintf(retStr, sizeof(buf), "%u - RF/%d", id, EM4x05_GET_BITRATE(id)); + snprintf(retStr, sizeof(buf), "%u - RF/%u", id, EM4x05_GET_BITRATE(id)); } else { switch (id) { case 0: @@ -3012,7 +3022,7 @@ static int CmdT55xxChkPwds(const char *Cmd) { void *argtable[4 + 6] = { arg_param_begin, arg_lit0("m", "fm", "use dictionary from flash memory (RDV4)"), - arg_str0("f", "file", "", "file name"), + arg_str0("f", "file", "", "file name"), arg_str0(NULL, "em", "", "EM4100 ID (5 hex bytes)"), }; uint8_t idx = 4; @@ -3937,6 +3947,15 @@ static int CmdT55xxSniff(const char *Cmd) { int opt_width0 = arg_get_int_def(ctx, 4, -1); CLIParserFree(ctx); + if (opt_width0 == 0) { + PrintAndLogEx(ERR, "Must call with --zero larger than 0"); + return PM3_EINVARG; + } + if ((opt_width0 == 0) || (opt_width1 == 0)) { + PrintAndLogEx(ERR, "Must call with --one larger than 0"); + return PM3_EINVARG; + } + if (opt_width0 > 0 && opt_width1 == -1) { PrintAndLogEx(ERR, _RED_("Missing sample width for ONE")); return PM3_EINVARG; @@ -3947,15 +3966,6 @@ static int CmdT55xxSniff(const char *Cmd) { return PM3_EINVARG; } - if (opt_width0 == 0) { - PrintAndLogEx(ERR, "Must call with --zero larger than 0"); - return PM3_EINVARG; - } - if ((opt_width0 == 0) || (opt_width1 == 0)) { - PrintAndLogEx(ERR, "Must call with --one larger than 0"); - return PM3_EINVARG; - } - uint8_t width1 = 0; uint8_t width0 = 0; @@ -3993,18 +4003,13 @@ static int CmdT55xxSniff(const char *Cmd) { 00 01 10 11 */ - bool have_data = false; uint8_t page, blockAddr; - uint16_t dataLen = 0; size_t idx = 0; uint32_t usedPassword, blockData; - int pulseSamples = 0; - int pulseIdx = 0; - int minWidth = 1000; - int maxWidth = 0; - char modeText [100]; - char pwdText [100]; - char dataText [100]; + int pulseSamples = 0, pulseIdx = 0; + char modeText[100]; + char pwdText[100]; + char dataText[100]; int pulseBuffer[80] = { 0 }; // max should be 73 +/- - Holds Pulse widths char data[80]; // linked to pulseBuffer. - Holds 0/1 from pulse widths @@ -4024,11 +4029,11 @@ static int CmdT55xxSniff(const char *Cmd) { // loop though sample buffer while (idx < GraphTraceLen) { - minWidth = 1000; - maxWidth = 0; - dataLen = 0; + int minWidth = 1000; + int maxWidth = 0; + uint16_t dataLen = 0; data[0] = 0; - have_data = false; + bool have_data = false; sprintf(modeText, "Default"); sprintf(pwdText, " "); sprintf(dataText, " "); @@ -4110,7 +4115,6 @@ static int CmdT55xxSniff(const char *Cmd) { // printf ("Fixed | Data end of 80 samples | offset : %llu - datalen %-2d - data : %s --- - Bit 0 width : %d\n",idx,dataLen,data,pulseBuffer[0]); if (data[0] == '0') { // should never get here.. - dataLen = 0; data[0] = 0; } else { From 506d660c293001d4eddd2263929253110071df1d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 13 Apr 2021 11:08:03 +0200 Subject: [PATCH 242/373] cppchecker fixes --- client/src/cmdlft55xx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 63ff9c46f..0f93615aa 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -506,8 +506,9 @@ static int CmdT55xxSetConfig(const char *Cmd) { } // validate user specified bitrate - uint8_t rates[9] = {8, 16, 32, 40, 50, 64, 100, 128, 0}; + if (bitrate != -1) { + uint8_t rates[9] = {8, 16, 32, 40, 50, 64, 100, 128, 0}; uint8_t i = 0; for (; i < ARRAYLEN(rates); i++) { if (rates[i] == bitrate) { @@ -921,10 +922,7 @@ 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; - - bool try_with_pwd = false; bool found = false; - bool usewake = false; // Setup the 90ms time value to sleep for after the wake, to allow delay init to complete (~70ms) struct timespec sleepperiod; @@ -943,6 +941,8 @@ static int CmdT55xxDetect(const char *Cmd) { char wakecmd[20] = { 0x00 }; sprintf(wakecmd, "-p %08" PRIx64, password); + bool usewake = false; + bool try_with_pwd = false; // do ... while not found and not yet tried with wake (for AOR or Init Delay) do { // do ... while to check without password then loop back if password supplied From 30ea41efc8f6f10c74600694d73a783e1c791215 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 13 Apr 2021 15:30:12 +0200 Subject: [PATCH 243/373] hf felica scsvcode, rdunencrypted - now uses cliparser --- client/src/cmdhffelica.c | 228 +++++++++++++++++++++++---------------- 1 file changed, 136 insertions(+), 92 deletions(-) diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 090b7359c..e560c8d1f 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -131,29 +131,6 @@ static int usage_hf_felica_sim(void) { } */ -static int usage_hf_felica_read_without_encryption(void) { - PrintAndLogEx(NORMAL, "\nInfo: Use this command to read Block Data from authentication-not-required Service."); - PrintAndLogEx(NORMAL, " - Mode shall be Mode0."); - print_number_of_service_constraints(); - print_number_of_block_constraints(); - print_service_code_list_constraints(); - print_block_list_element_constraints(); - PrintAndLogEx(NORMAL, " - Successful read: Card responses the block data"); - PrintAndLogEx(NORMAL, " - Unsuccessful read: Card responses with Status Flag1 and Flag2"); - print_status_flag1_interpretation(); - print_status_flag2_interpration(); - PrintAndLogEx(NORMAL, "\nUsage: hf felica rdunencrypted [-h] <01 Number of Service hex> <0A0B Service Code List (Little Endian) hex> <01 Number of Block hex> <0A0B Block List Element hex>"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); - PrintAndLogEx(NORMAL, " -b get all Block List Elements starting from 00 to FF - stops when a block return an error status flags"); - PrintAndLogEx(NORMAL, " -l use 3-byte block list element block number"); - PrintAndLogEx(NORMAL, "\nExamples: "); - PrintAndLogEx(NORMAL, " hf felica rdunencrypted 01 8B00 01 8000"); - PrintAndLogEx(NORMAL, " hf felica rdunencrypted -i 01100910c11bc407 01 8B00 01 8000"); - PrintAndLogEx(NORMAL, " hf felica rdunencrypted -b 01 4B18 01 8000\n\n"); - return PM3_SUCCESS; -} - static int usage_hf_felica_write_without_encryption(void) { PrintAndLogEx(NORMAL, "\nInfo: Use this command to write Block Data to authentication-not-required Service."); PrintAndLogEx(NORMAL, " - Mode shall be Mode0."); @@ -471,11 +448,11 @@ static void print_rd_noEncrpytion_response(felica_read_without_encryption_respon temp = sprint_hex(rd_noCry_resp->block_element_number, sizeof(rd_noCry_resp->block_element_number)); strncpy(bl_element_number, temp, sizeof(bl_element_number) - 1); - PrintAndLogEx(INFO, "\t%s\t| %s ", bl_element_number, bl_data); + PrintAndLogEx(INFO, " %s | %s ", bl_element_number, bl_data); } else { - PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex_inrow(rd_noCry_resp->frame_response.IDm, sizeof(rd_noCry_resp->frame_response.IDm))); - PrintAndLogEx(SUCCESS, " Status flag 1: %s", sprint_hex(rd_noCry_resp->status_flags.status_flag1, sizeof(rd_noCry_resp->status_flags.status_flag1))); - PrintAndLogEx(SUCCESS, " Status flag 2: %s", sprint_hex(rd_noCry_resp->status_flags.status_flag1, sizeof(rd_noCry_resp->status_flags.status_flag1))); + PrintAndLogEx(SUCCESS, "IDm... %s", sprint_hex_inrow(rd_noCry_resp->frame_response.IDm, sizeof(rd_noCry_resp->frame_response.IDm))); + PrintAndLogEx(SUCCESS, " Status flag 1... %s", sprint_hex(rd_noCry_resp->status_flags.status_flag1, sizeof(rd_noCry_resp->status_flags.status_flag1))); + PrintAndLogEx(SUCCESS, " Status flag 2... %s", sprint_hex(rd_noCry_resp->status_flags.status_flag1, sizeof(rd_noCry_resp->status_flags.status_flag1))); } } @@ -914,80 +891,139 @@ static int CmdHFFelicaWriteWithoutEncryption(const char *Cmd) { * @return client result code. */ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { - if (strlen(Cmd) < 4) - return usage_hf_felica_read_without_encryption(); - uint8_t data[PM3_CMD_DATA_SIZE]; - bool custom_IDm = false; - strip_cmds(Cmd); - uint16_t datalen = 16; // Length (1), Command ID (1), IDm (8), Number of Service (1), Service Code List(2), Number of Block(1), Block List(3) - uint8_t paramCount = 0; - uint8_t flags = 0; - uint8_t all_block_list_elements = false; - uint8_t long_block_numbers = false; - int i = 0; - while (Cmd[i] != '\0') { - if (Cmd[i] == '-') { - switch (tolower(Cmd[i + 1])) { - case 'h': - return usage_hf_felica_read_without_encryption(); - case 'i': - paramCount++; - custom_IDm = true; - if (!add_param(Cmd, paramCount, data, 2, 16)) { - return PM3_EINVARG; - } - paramCount++; - i += 16; - break; - case 'b': - paramCount++; - all_block_list_elements = true; - break; - case 'l': - paramCount++; - long_block_numbers = true; - break; - default: - return usage_hf_felica_read_without_encryption(); - } - } - i++; - } - data[0] = 0x10; // Static length - data[1] = 0x06; // Command ID - if (!custom_IDm && !check_last_idm(data, datalen)) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica rdunencrypted", + "Use this command to read block data from authentication-not-required Service.\n\n" + " - Mode shall be Mode0.\n" + " - Successful == block data\n" + " - Unsuccessful == Status Flag1 and Flag2", + "hf felica rdunencrypted --sn 01 --scl 8B00 --bn 01 --ble 8000\n" + "hf felica rdunencrypted --sn 01 --scl 4B18 --bn 01 --ble 8000 -b\n" + "hf felica rdunencrypted -i 01100910c11bc407 --sn 01 --scl 8B00 --bn 01 --ble 8000\n" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0("b", NULL, "get all block list elements 00 -> FF"), + arg_str0("i", NULL, "", "set custom IDm"), + arg_lit0("l", "long", "use 3 byte block list element block number"), + arg_str0(NULL, "sn", "", "number of service"), + arg_str0(NULL, "scl", "", "service code list"), + arg_str0(NULL, "bn", "", "number of block"), + arg_str0(NULL, "ble", "", "block list element (def 2|3 bytes)"), + arg_lit0("v", "verbose", "verbose helptext"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool all_block_list_elements = arg_get_lit(ctx, 1); + + uint8_t idm[8] = {0}; + int ilen = 0; + int res = CLIParamHexToBuf(arg_get_str(ctx, 2), idm, sizeof(idm), &ilen); + if (res) { + CLIParserFree(ctx); return PM3_EINVARG; } - // Number of Service 2, Service Code List 4, Number of Block 2, Block List Element 4 - uint8_t lengths[] = {2, 4, 2, 4}; - uint8_t dataPositions[] = {10, 11, 13, 14}; - if (long_block_numbers) { - datalen += 1; - lengths[3] = 6; - } - for (i = 0; i < 4; i++) { - if (add_param(Cmd, paramCount, data, dataPositions[i], lengths[i])) { - paramCount++; - } else { - return PM3_EINVARG; - } + + uint8_t long_block_numbers = arg_get_lit(ctx, 3); + + uint8_t sn[1] = {0}; + int snlen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 4), sn, sizeof(sn), &snlen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; } - flags |= FELICA_APPEND_CRC; - flags |= FELICA_RAW; + uint8_t scl[2] = {0}; + int scllen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 5), scl, sizeof(scl), &scllen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint8_t bn[1] = {0}; + int bnlen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 6), bn, sizeof(bn), &bnlen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint8_t ble[3] = {0}; + int blelen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 7), ble, sizeof(ble), &blelen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + bool verbose = arg_get_lit(ctx, 8); + CLIParserFree(ctx); + if (verbose) { + print_number_of_service_constraints(); + print_number_of_block_constraints(); + print_service_code_list_constraints(); + print_block_list_element_constraints(); + print_status_flag1_interpretation(); + print_status_flag2_interpration(); + return PM3_SUCCESS; + } + + uint8_t data[PM3_CMD_DATA_SIZE]; + data[0] = 0x10; // Static length + data[1] = 0x06; // Command ID + + bool custom_IDm = false; + if (ilen) { + custom_IDm = true; + memcpy(data + 2, idm, sizeof(idm)); + } + + uint16_t datalen = 16; // Length (1), Command ID (1), IDm (8), Number of Service (1), Service Code List(2), Number of Block(1), Block List(3) + if (custom_IDm == false && check_last_idm(data, datalen) == false) { + return PM3_EINVARG; + } + + if (long_block_numbers) { + datalen++; + } + + // Number of Service 1, Service Code List 2, Number of Block 1, Block List Element 2|3 + if (snlen) { + data[10] = sn[0]; + } + if (scllen) { + data[11] = scl[0]; + data[12] = scl[1]; + } + if (bnlen) { + data[13] = bn[0]; + } + if (blelen) + memcpy(data + 14, ble, blelen); + + uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW); + + PrintAndLogEx(INFO, "block | data "); + PrintAndLogEx(INFO, "------+----------------------------------------"); + + // main loop block reads if (all_block_list_elements) { - uint16_t last_block_number = 0xFF; + + uint16_t last_blockno = 0xFF; if (long_block_numbers) { - last_block_number = 0xFFFF; + last_blockno = 0xFFFF; } - PrintAndLogEx(INFO, "Block Nr.\t| Data "); - for (i = 0x00; i < last_block_number; i++) { + + for (uint16_t i = 0x00; i < last_blockno; i++) { data[15] = i; AddCrc(data, datalen); datalen += 2; felica_read_without_encryption_response_t rd_noCry_resp; if ((send_rd_unencrypted(flags, datalen, data, 0, &rd_noCry_resp) == PM3_SUCCESS)) { - if (rd_noCry_resp.status_flags.status_flag1[0] == 00 && rd_noCry_resp.status_flags.status_flag2[0] == 00) { + if (rd_noCry_resp.status_flags.status_flag1[0] == 0 && rd_noCry_resp.status_flags.status_flag2[0] == 0) { print_rd_noEncrpytion_response(&rd_noCry_resp); } } else { @@ -1000,7 +1036,6 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { datalen += 2; felica_read_without_encryption_response_t rd_noCry_resp; if (send_rd_unencrypted(flags, datalen, data, 1, &rd_noCry_resp) == PM3_SUCCESS) { - PrintAndLogEx(INFO, "Block Nr.\t| Data "); print_rd_noEncrpytion_response(&rd_noCry_resp); } } @@ -1467,8 +1502,17 @@ static int CmdHFFelicaRequestService(const char *Cmd) { } static int CmdHFFelicaNotImplementedYet(const char *Cmd) { - PrintAndLogEx(INFO, "Feature not implemented yet."); - PrintAndLogEx(INFO, "Feel free to contribute!"); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica scsvcode", + "Feature not implemented yet. Feel free to contribute!", + "hf felica scsvcode" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + CLIParserFree(ctx); return PM3_SUCCESS; } From e7e43d11d0193688b8cec7d57047ad8625144e19 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 13 Apr 2021 16:08:58 +0200 Subject: [PATCH 244/373] hf felica rdbl, wrbl, now uses cliparser. Renamed them, and hf felica raw got a bugfix to read raw bytes correct --- client/src/cmdhffelica.c | 282 ++++++++++++++++++++++++++------------- doc/cliparser_todo.txt | 3 - doc/commands.md | 4 +- 3 files changed, 188 insertions(+), 101 deletions(-) diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index e560c8d1f..76bd98365 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -131,25 +131,6 @@ static int usage_hf_felica_sim(void) { } */ -static int usage_hf_felica_write_without_encryption(void) { - PrintAndLogEx(NORMAL, "\nInfo: Use this command to write Block Data to authentication-not-required Service."); - PrintAndLogEx(NORMAL, " - Mode shall be Mode0."); - print_number_of_service_constraints(); - print_number_of_block_constraints(); - print_service_code_list_constraints(); - print_block_list_element_constraints(); - PrintAndLogEx(NORMAL, " - Un-/Successful read: Card responses with Status Flag1 and Flag2"); - print_status_flag1_interpretation(); - print_status_flag2_interpration(); - PrintAndLogEx(NORMAL, "\nUsage: hf felica wrunencrypted [-h][-i] <01 Number of Service hex> <0A0B Service Code List (Little Endian) hex> <01 Number of Block hex> <0A0B Block List Element hex> <0A0B0C0D0E0F... Data hex (16-Byte)>"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use\n"); - PrintAndLogEx(NORMAL, "\nExamples: "); - PrintAndLogEx(NORMAL, " hf felica wrunencrypted 01 CB10 01 8001 0102030405060708090A0B0C0D0E0F10"); - PrintAndLogEx(NORMAL, " hf felica wrunencrypted -i 11100910C11BC407 01 CB10 01 8001 0102030405060708090A0B0C0D0E0F10\n\n"); - return PM3_SUCCESS; -} - static int usage_hf_felica_authentication1(void) { PrintAndLogEx(NORMAL, "\nInfo: Initiate mutual authentication. This command must always be executed before Authentication2 command" ", and mutual authentication is achieve only after Authentication2 command has succeeded."); @@ -202,7 +183,6 @@ static int usage_hf_felica_authentication2(void) { return PM3_SUCCESS; } - /** * Wait for response from pm3 or timeout. * Checks if receveid bytes have a valid CRC. @@ -212,23 +192,23 @@ static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp, bool verbose) if (WaitForResponseTimeout(CMD_ACK, resp, 2000)) { uint16_t len = iSelect ? (resp->oldarg[1] & 0xffff) : (resp->oldarg[0] & 0xffff); if (verbose) { - PrintAndLogEx(SUCCESS, "Client Received %i octets", len); + PrintAndLogEx(SUCCESS, "client received %i octets", len); if (len == 0 || len == 1) { PrintAndLogEx(ERR, "Could not receive data correctly!"); return false; } PrintAndLogEx(SUCCESS, "%s", sprint_hex(resp->data.asBytes, len)); if (!check_crc(CRC_FELICA, resp->data.asBytes + 2, len - 2)) { - PrintAndLogEx(WARNING, "Wrong or no CRC bytes"); + PrintAndLogEx(WARNING, "wrong or no CRC bytes"); } if (resp->data.asBytes[0] != 0xB2 && resp->data.asBytes[1] != 0x4D) { - PrintAndLogEx(ERR, "Received incorrect Frame Format!"); + PrintAndLogEx(ERR, "received incorrect frame format!"); return false; } } return true; } else { - PrintAndLogEx(WARNING, "Timeout while waiting for reply."); + PrintAndLogEx(WARNING, "timeout while waiting for reply."); } return false; } @@ -434,7 +414,7 @@ static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_ * Prints read-without-encryption response. * @param rd_noCry_resp Response frame. */ -static void print_rd_noEncrpytion_response(felica_read_without_encryption_response_t *rd_noCry_resp) { +static void print_rd_plain_response(felica_read_without_encryption_response_t *rd_noCry_resp) { if (rd_noCry_resp->status_flags.status_flag1[0] == 00 && rd_noCry_resp->status_flags.status_flag2[0] == 00) { @@ -471,10 +451,10 @@ int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool ve memcpy(&r, (felica_request_service_response_t *)resp.data.asBytes, sizeof(felica_request_service_response_t)); if (r.frame_response.IDm[0] != 0) { - PrintAndLogEx(SUCCESS, "\nGot Service Response:"); - PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex_inrow(r.frame_response.IDm, sizeof(r.frame_response.IDm))); - PrintAndLogEx(SUCCESS, " Node number: %s", sprint_hex(r.node_number, sizeof(r.node_number))); - PrintAndLogEx(SUCCESS, " Node key version list: %s\n", sprint_hex(r.node_key_versions, sizeof(r.node_key_versions))); + PrintAndLogEx(SUCCESS, "Service Response:"); + PrintAndLogEx(SUCCESS, "IDm... %s", sprint_hex_inrow(r.frame_response.IDm, sizeof(r.frame_response.IDm))); + PrintAndLogEx(SUCCESS, " Node number............. %s", sprint_hex(r.node_number, sizeof(r.node_number))); + PrintAndLogEx(SUCCESS, " Node key version list... %s\n", sprint_hex(r.node_key_versions, sizeof(r.node_key_versions))); } return PM3_SUCCESS; } @@ -490,11 +470,11 @@ int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool ve * @param rd_noCry_resp frame in which the response will be saved. * @return success if response was received. */ -int send_rd_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp) { +int send_rd_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp) { clear_and_send_command(flags, datalen, data, verbose); PacketResponseNG resp; if (!waitCmdFelica(0, &resp, verbose)) { - PrintAndLogEx(ERR, "\nGot no response from card"); + PrintAndLogEx(ERR, "No response from card"); return PM3_ERFTRANS; } else { memcpy(rd_noCry_resp, (felica_read_without_encryption_response_t *)resp.data.asBytes, sizeof(felica_read_without_encryption_response_t)); @@ -528,11 +508,11 @@ static bool check_last_idm(uint8_t *data, uint16_t datalen) { * @param wr_noCry_resp frame in which the response will be saved. * @return success if response was received. */ -static int send_wr_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_status_response_t *wr_noCry_resp) { +static int send_wr_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_status_response_t *wr_noCry_resp) { clear_and_send_command(flags, datalen, data, verbose); PacketResponseNG resp; if (waitCmdFelica(0, &resp, verbose) == false) { - PrintAndLogEx(ERR, "Got no response from card"); + PrintAndLogEx(ERR, "no response from card"); return PM3_ERFTRANS; } @@ -564,6 +544,8 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { PrintAndLogEx(INFO, "INCOMPLETE / EXPERIMENTAL COMMAND!!!"); uint8_t data[PM3_CMD_DATA_SIZE]; + memset(data, 0 , sizeof(data)); + bool custom_IDm = false; strip_cmds(Cmd); uint16_t datalen = 24; // Length (1), Command ID (1), IDm (8), Number of Area (1), Area Code List (2), Number of Service (1), Service Code List (2), M1c (8) @@ -711,6 +693,8 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { PrintAndLogEx(INFO, "INCOMPLETE / EXPERIMENTAL COMMAND!!!"); PrintAndLogEx(INFO, "EXPERIMENTAL COMMAND - M2c/P2c will be not checked"); uint8_t data[PM3_CMD_DATA_SIZE]; + memset(data, 0 , sizeof(data)); + bool custom_IDm = false; strip_cmds(Cmd); uint16_t datalen = 18; // Length (1), Command ID (1), IDm (8), M4c (8) @@ -822,66 +806,162 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { * @param Cmd input data of the user. * @return client result code. */ -static int CmdHFFelicaWriteWithoutEncryption(const char *Cmd) { - if (strlen(Cmd) < 5) - return usage_hf_felica_write_without_encryption(); - uint8_t data[PM3_CMD_DATA_SIZE]; - bool custom_IDm = false; - strip_cmds(Cmd); - uint16_t datalen = 32; // Length (1), Command ID (1), IDm (8), Number of Service (1), Service Code List(2), Number of Block(1), Block List(3), Block Data(16) - uint8_t paramCount = 0; - uint8_t flags = 0; - int i = 0; - while (Cmd[i] != '\0') { - if (Cmd[i] == '-') { - switch (tolower(Cmd[i + 1])) { - case 'h': - return usage_hf_felica_write_without_encryption(); - case 'i': - paramCount++; - custom_IDm = true; - if (!add_param(Cmd, paramCount, data, 2, 16)) { - return PM3_EINVARG; - } - paramCount++; - i += 16; - break; - default: - return usage_hf_felica_write_without_encryption(); - } - } - i++; - } - data[0] = 0x20; // Static length - data[1] = 0x08; // Command ID - if (!custom_IDm && !check_last_idm(data, datalen)) { +static int CmdHFFelicaWritePlain(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica wrbl", + "Use this command to write block data to authentication-not-required Service.\n\n" + " - Mode shall be Mode0.\n" + " - Un-/Ssuccessful == Status Flag1 and Flag2", + "hf felica wrbl --sn 01 --scl CB10 --bn 01 --ble 8001 -d 0102030405060708090A0B0C0D0E0F10\n" + "hf felica wrbl -i 01100910c11bc407 --sn 01 --scl CB10 --bn 01 --ble 8001 -d 0102030405060708090A0B0C0D0E0F10\n" + ); + void *argtable[] = { + arg_param_begin, + arg_str0("d", "data", "", "data, 16 hex bytes"), + arg_str0("i", NULL, "", "set custom IDm"), + arg_str0(NULL, "sn", "", "number of service"), + arg_str0(NULL, "scl", "", "service code list"), + arg_str0(NULL, "bn", "", "number of block"), + arg_str0(NULL, "ble", "", "block list element (def 2|3 bytes)"), + arg_lit0("v", "verbose", "verbose helptext"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + uint8_t userdata[16] = {0}; + int udlen = 0; + int res = CLIParamHexToBuf(arg_get_str(ctx, 1), userdata, sizeof(userdata), &udlen); + if (res) { + CLIParserFree(ctx); return PM3_EINVARG; } - // Number of Service 2, Service Code List 4, Number of Block 2, Block List Element 4, Data 16 - uint8_t lengths[] = {2, 4, 2, 4, 32}; - uint8_t dataPositions[] = {10, 11, 13, 14, 16}; - for (i = 0; i < 5; i++) { - if (add_param(Cmd, paramCount, data, dataPositions[i], lengths[i])) { - paramCount++; - } else { - return PM3_EINVARG; - } + + uint8_t idm[8] = {0}; + int ilen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 2), idm, sizeof(idm), &ilen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; } - flags |= FELICA_APPEND_CRC; - flags |= FELICA_RAW; + + uint8_t sn[1] = {0}; + int snlen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 3), sn, sizeof(sn), &snlen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint8_t scl[2] = {0}; + int scllen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 4), scl, sizeof(scl), &scllen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint8_t bn[1] = {0}; + int bnlen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 5), bn, sizeof(bn), &bnlen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint8_t ble[3] = {0}; + int blelen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 6), ble, sizeof(ble), &blelen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + bool verbose = arg_get_lit(ctx, 7); + CLIParserFree(ctx); + + if (verbose) { + print_number_of_service_constraints(); + print_number_of_block_constraints(); + print_service_code_list_constraints(); + print_block_list_element_constraints(); + print_status_flag1_interpretation(); + print_status_flag2_interpration(); + return PM3_SUCCESS; + } + + uint8_t data[PM3_CMD_DATA_SIZE]; + memset(data, 0 , sizeof(data)); + data[0] = 0x20; // Static length + data[1] = 0x08; // Command ID + + bool custom_IDm = false; + if (ilen) { + custom_IDm = true; + memcpy(data + 2, idm, sizeof(idm)); + } + + // Length (1) + // Command ID (1) + // IDm (8) + // Number of Service (1) + // Service Code List(2) + // Number of Block(1) + // Block List(3) + // Block Data(16) + + uint16_t datalen = 32; // Length (1), Command ID (1), IDm (8), Number of Service (1), Service Code List(2), Number of Block(1), Block List(3), Block Data(16) + if (custom_IDm == false && check_last_idm(data, datalen) == false) { + return PM3_EINVARG; + } + + if (blelen == 3) { + datalen++; + } + + // Number of Service 1, Service Code List 2, Number of Block 1, Block List Element 2, Data 16 + + // Service Number 1 byte + if (snlen) { + data[10] = sn[0]; + } + // Service Code List 2 bytes + if (scllen) { + data[11] = scl[0]; + data[12] = scl[1]; + } + + // Block number 1 byte + if (bnlen) { + data[13] = bn[0]; + } + + // Block List Element 2|3 bytes + if (blelen) { + memcpy(data + 14, ble, blelen); + } + + // data to be written, 16 bytes + if (udlen) { + memcpy(data + 14 + blelen, userdata, sizeof(userdata)); + } + + uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW); AddCrc(data, datalen); datalen += 2; + felica_status_response_t wr_noCry_resp; - if (send_wr_unencrypted(flags, datalen, data, 1, &wr_noCry_resp) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "\nIDm: %s", sprint_hex(wr_noCry_resp.frame_response.IDm, sizeof(wr_noCry_resp.frame_response.IDm))); - PrintAndLogEx(SUCCESS, "Status Flag1: %s", sprint_hex(wr_noCry_resp.status_flags.status_flag1, sizeof(wr_noCry_resp.status_flags.status_flag1))); - PrintAndLogEx(SUCCESS, "Status Flag2: %s\n", sprint_hex(wr_noCry_resp.status_flags.status_flag2, sizeof(wr_noCry_resp.status_flags.status_flag2))); + if (send_wr_plain(flags, datalen, data, 1, &wr_noCry_resp) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "IDm............ %s", sprint_hex(wr_noCry_resp.frame_response.IDm, sizeof(wr_noCry_resp.frame_response.IDm))); + PrintAndLogEx(SUCCESS, "Status Flag1... %s", sprint_hex(wr_noCry_resp.status_flags.status_flag1, sizeof(wr_noCry_resp.status_flags.status_flag1))); + PrintAndLogEx(SUCCESS, "Status Flag2... %s\n", sprint_hex(wr_noCry_resp.status_flags.status_flag2, sizeof(wr_noCry_resp.status_flags.status_flag2))); if (wr_noCry_resp.status_flags.status_flag1[0] == 0x00 && wr_noCry_resp.status_flags.status_flag2[0] == 0x00) { - PrintAndLogEx(SUCCESS, "Writing data successful!\n"); + PrintAndLogEx(SUCCESS, "Writing data successful!"); } else { - PrintAndLogEx(ERR, "Something went wrong! Check status flags.\n"); + PrintAndLogEx(FAILED, "Something went wrong! Check status flags."); } } + return PM3_SUCCESS; } @@ -890,16 +970,16 @@ static int CmdHFFelicaWriteWithoutEncryption(const char *Cmd) { * @param Cmd input data of the user. * @return client result code. */ -static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { +static int CmdHFFelicaReadPlain(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "hf felica rdunencrypted", + CLIParserInit(&ctx, "hf felica rdbl", "Use this command to read block data from authentication-not-required Service.\n\n" " - Mode shall be Mode0.\n" " - Successful == block data\n" " - Unsuccessful == Status Flag1 and Flag2", - "hf felica rdunencrypted --sn 01 --scl 8B00 --bn 01 --ble 8000\n" - "hf felica rdunencrypted --sn 01 --scl 4B18 --bn 01 --ble 8000 -b\n" - "hf felica rdunencrypted -i 01100910c11bc407 --sn 01 --scl 8B00 --bn 01 --ble 8000\n" + "hf felica rdbl --sn 01 --scl 8B00 --bn 01 --ble 8000\n" + "hf felica rdbl --sn 01 --scl 4B18 --bn 01 --ble 8000 -b\n" + "hf felica rdbl -i 01100910c11bc407 --sn 01 --scl 8B00 --bn 01 --ble 8000\n" ); void *argtable[] = { arg_param_begin, @@ -972,6 +1052,7 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { } uint8_t data[PM3_CMD_DATA_SIZE]; + memset(data, 0 , sizeof(data)); data[0] = 0x10; // Static length data[1] = 0x06; // Command ID @@ -1022,9 +1103,9 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { AddCrc(data, datalen); datalen += 2; felica_read_without_encryption_response_t rd_noCry_resp; - if ((send_rd_unencrypted(flags, datalen, data, 0, &rd_noCry_resp) == PM3_SUCCESS)) { + if ((send_rd_plain(flags, datalen, data, 0, &rd_noCry_resp) == PM3_SUCCESS)) { if (rd_noCry_resp.status_flags.status_flag1[0] == 0 && rd_noCry_resp.status_flags.status_flag2[0] == 0) { - print_rd_noEncrpytion_response(&rd_noCry_resp); + print_rd_plain_response(&rd_noCry_resp); } } else { break; @@ -1035,8 +1116,8 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { AddCrc(data, datalen); datalen += 2; felica_read_without_encryption_response_t rd_noCry_resp; - if (send_rd_unencrypted(flags, datalen, data, 1, &rd_noCry_resp) == PM3_SUCCESS) { - print_rd_noEncrpytion_response(&rd_noCry_resp); + if (send_rd_plain(flags, datalen, data, 1, &rd_noCry_resp) == PM3_SUCCESS) { + print_rd_plain_response(&rd_noCry_resp); } } return PM3_SUCCESS; @@ -1073,6 +1154,7 @@ static int CmdHFFelicaRequestResponse(const char *Cmd) { CLIParserFree(ctx); uint8_t data[PM3_CMD_DATA_SIZE]; + memset(data, 0 , sizeof(data)); data[0] = 0x0A; // Static length data[1] = 0x04; // Command ID @@ -1165,6 +1247,7 @@ static int CmdHFFelicaRequestSpecificationVersion(const char *Cmd) { CLIParserFree(ctx); uint8_t data[PM3_CMD_DATA_SIZE]; + memset(data, 0 , sizeof(data)); data[0] = 0x0C; // Static length data[1] = 0x3C; // Command ID @@ -1271,6 +1354,7 @@ static int CmdHFFelicaResetMode(const char *Cmd) { CLIParserFree(ctx); uint8_t data[PM3_CMD_DATA_SIZE]; + memset(data, 0 , sizeof(data)); data[0] = 0x0C; // Static length data[1] = 0x3E; // Command ID @@ -1348,6 +1432,7 @@ static int CmdHFFelicaRequestSystemCode(const char *Cmd) { uint8_t data[PM3_CMD_DATA_SIZE]; + memset(data, 0 , sizeof(data)); data[0] = 0x0A; // Static length data[1] = 0x0C; // Command ID @@ -1448,6 +1533,8 @@ static int CmdHFFelicaRequestService(const char *Cmd) { CLIParserFree(ctx); uint8_t data[PM3_CMD_DATA_SIZE]; + memset(data, 0 , sizeof(data)); + bool custom_IDm = false; if (ilen) { @@ -1879,7 +1966,8 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf felica raw ", "Send raw hex data to tag", - "hf felica raw -s 20" + "hf felica raw -cs 20\n" + "hf felica raw -cs 2008" ); void *argtable[] = { @@ -1904,7 +1992,9 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { int datalen = 0; uint8_t data[PM3_CMD_DATA_SIZE]; - CLIGetHexWithReturn(ctx, 6, data, &datalen); + memset(data, 0 , sizeof(data)); + + CLIGetHexWithReturn(ctx, 7, data, &datalen); CLIParserFree(ctx); if (crc) { @@ -1961,8 +2051,8 @@ static command_t CommandTable[] = { {"info", CmdHFFelicaInfo, IfPm3Felica, "Tag information"}, {"sniff", CmdHFFelicaSniff, IfPm3Felica, "Sniff ISO 18092/FeliCa traffic"}, {"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"}, - {"rdunencrypted", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from authentication-not-required Service."}, - {"wrunencrypted", CmdHFFelicaWriteWithoutEncryption, IfPm3Felica, "write Block Data to an authentication-not-required Service."}, + {"rdbl", CmdHFFelicaReadPlain, IfPm3Felica, "read block data from authentication-not-required Service."}, + {"wrbl", CmdHFFelicaWritePlain, IfPm3Felica, "write block data to an authentication-not-required Service."}, {"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("FeliCa Standard") " -----------------------"}, //{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, {"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."}, diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index c1a82050c..8af74face 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -7,8 +7,5 @@ hf 15 restore hf 15 wrbl hf 15 writeafi hf 15 writedsfid -hf felica rdunencrypted -hf felica wrunencrypted -hf felica scsvcode hf felica auth1 hf felica auth2 diff --git a/doc/commands.md b/doc/commands.md index fffeade87..a44840d61 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -266,8 +266,8 @@ Check column "offline" for their availability. |`hf felica info `|N |`Tag information` |`hf felica sniff `|N |`Sniff ISO 18092/FeliCa traffic` |`hf felica raw `|N |`Send raw hex data to tag` -|`hf felica rdunencrypted`|N |`read Block Data from authentication-not-required Service.` -|`hf felica wrunencrypted`|N |`write Block Data to an authentication-not-required Service.` +|`hf felica rdbl `|N |`read block data from authentication-not-required Service.` +|`hf felica wrbl `|N |`write block data to an authentication-not-required Service.` |`hf felica rqservice `|N |`verify the existence of Area and Service, and to acquire Key Version.` |`hf felica rqresponse `|N |`verify the existence of a card and its Mode.` |`hf felica scsvcode `|N |`acquire Area Code and Service Code.` From 967cab7b58838ee1cc15176dfc59cde16737c258 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 13 Apr 2021 17:02:06 +0200 Subject: [PATCH 245/373] update the header file --- client/src/cmdhffelica.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhffelica.h b/client/src/cmdhffelica.h index 271a0d448..63f738a2d 100644 --- a/client/src/cmdhffelica.h +++ b/client/src/cmdhffelica.h @@ -17,6 +17,6 @@ int CmdHFFelica(const char *Cmd); int read_felica_uid(bool loop, bool verbose); int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose); -int send_rd_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp); +int send_rd_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool verbose, felica_read_without_encryption_response_t *rd_noCry_resp); #endif From 831f664a4c4c74e51b2bce2dbd44fa058be438fd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 13 Apr 2021 17:45:36 +0200 Subject: [PATCH 246/373] coverity fix CID 319217 --- client/src/cmdlft55xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 0f93615aa..b8f162896 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -2366,6 +2366,7 @@ static int CmdT55xxRestore(const char *Cmd) { //sanity checks of file processing if (res != PM3_SUCCESS) { + free(dump); return res; } From 02f8993837e4da6a8a64380c74936bec6c842c27 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 13 Apr 2021 21:06:21 +0200 Subject: [PATCH 247/373] make clear Ryscorp Pm3 Pro isn't supported --- README.md | 3 ++- doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8dd1ccf5e..09cb8667d 100644 --- a/README.md +++ b/README.md @@ -49,11 +49,12 @@ In order to build this repo for generic Proxmark3 platforms we urge you to read With generic Proxmark3 platforms we mean: - RDV1, RDV2, RDV3 easy - Proxmark Evolution (needs extra care) - - Ryscorp green PCB version, Pm3 Pro - Radiowar black PCB version - VX - numerous Chinese adapted versions of the RDV3 easy (kkmoon, pisworks etc) +> ⚠ **Note**: *Ryscorp green PCB version, Pm3 Pro* has different and unknown hardware components and therefore is not supported. + > ⚠ **Note**: About flash memory size of other Proxmark3 platforms. You need to keep a eye on how large your ARM chip built-in flash memory is. With 512kb you are fine but if its 256kb you need to compile this repo with even less functionality. When running the `./pm3-flash-all` you can see which size your device have if you have the bootloader from this repo installed. Otherwise you will find the size reported in the start message when running the Proxmark3 client `./pm3`. ## What has changed? diff --git a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md index 8f49e0b15..211761b18 100644 --- a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md +++ b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md @@ -54,7 +54,7 @@ Known issues: * 256kb Arm chip devices: The compiled firmware image from this repo may/will be too large for your device. * PM3 Evo: it has a different led/button pin assignment. It tends to be messed up. -* Proxmark Pro: it has different fpga and unknown pin assignments. Will most certainly mess up +* Proxmark Pro: it has different fpga and unknown pin assignments. Unsupported. ## PLATFORM_EXTRAS From 59bdb6df19a28632a1056fa63f65c0b1788f0efa Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 13 Apr 2021 21:22:33 +0200 Subject: [PATCH 248/373] typos & minor changes --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 09cb8667d..16b228b41 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ With generic Proxmark3 platforms we mean: - VX - numerous Chinese adapted versions of the RDV3 easy (kkmoon, pisworks etc) -> ⚠ **Note**: *Ryscorp green PCB version, Pm3 Pro* has different and unknown hardware components and therefore is not supported. +> ⚠ **Note**: *Ryscorp green PCB version, Pm3 Pro* has different fpga and unknown pin assignments and therefore is not supported. > ⚠ **Note**: About flash memory size of other Proxmark3 platforms. You need to keep a eye on how large your ARM chip built-in flash memory is. With 512kb you are fine but if its 256kb you need to compile this repo with even less functionality. When running the `./pm3-flash-all` you can see which size your device have if you have the bootloader from this repo installed. Otherwise you will find the size reported in the start message when running the Proxmark3 client `./pm3`. @@ -62,25 +62,25 @@ With generic Proxmark3 platforms we mean: Proxmark3 RDV4 hardware modifications: * added flash memory 256kb * added smart card module - * added FPC connector + * added FPC connector for peripherals such as Bluetooth+battery addon * improved antennas * swappable * LF Q factor switch - * LF 125/134 freqency switch + * LF 125/134 frequency switch * tiny PCB form factor * ABS case This repo vs official Proxmark3 repo: -see the [Changelog file](CHANGELOG.md) which we try to keep updated. In short this repo gives you an complete different user experience when it comes to Proxmark3. +see the [Changelog file](CHANGELOG.md) which we try to keep updated. In short this repo gives you a completely different user experience when it comes to Proxmark3. * richer CLI with use of colors / emojis * help text system implemented everywhere * hints system * user preference settings - * extensive testing with continues built systems and static analyse tools like - * [coverity scan](https://scan.coverity.com/projects/proxmark3-rrg-iceman-repo/) - * cppchecker - * CLANG - * auto detection of serial ports and seamless intergration with bluetooth addon + * extensive testing with continuous integration build systems on Linux, OSX and Windows, and regular usage of static analysis tools like + * [Coverity Scan](https://scan.coverity.com/projects/proxmark3-rrg-iceman-repo/) + * Cppcheck + * GCC and Clang aggressive enforcement of diagnostic flags + * auto detection of serial ports and seamless integration with Bluetooth addon * reconnect to device @@ -108,7 +108,7 @@ This repo compiles nicely on ## Precompiled binaries -We don't maintain any precompiled binaries in this repo. There is community effort over at the Proxmark3 forum where package maintainer [@gator96100](https://github.com/gator96100) has set up a AWS bucket with precompiled Proxspace (Mingw) binaries which is recompiled every night and with that also up-to-date. We link to these files here as to make it easier for users. If you are having troubles with these files, we suggest to read the [homepage of his proxmark builds](https://www.proxmarkbuilds.org/) or read the [sticky thread at forum](http://www.proxmark.org/forum/viewtopic.php?pid=24763#p24763) +We don't maintain any precompiled binaries in this repo. There is community effort over at the Proxmark3 forum where package maintainer [@gator96100](https://github.com/gator96100) has set up a AWS bucket with precompiled Proxspace (Mingw) binaries which are recompiled every night and with that also up-to-date. We link to these files here as to make it easier for users. If you are having troubles with these files, we suggest to read the [homepage of his proxmark builds](https://www.proxmarkbuilds.org/) or read the [sticky thread at forum](http://www.proxmark.org/forum/viewtopic.php?pid=24763#p24763) ### Proxmark3 RDV4 devices - [Precompiled builds for RDV40 dedicated x64](https://www.proxmarkbuilds.org/#rdv40-64/) From 7a47c02eebdafd1382435b3dc2802196d94951df Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 13 Apr 2021 21:26:00 +0200 Subject: [PATCH 249/373] more typos --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 16b228b41..c1b735240 100644 --- a/README.md +++ b/README.md @@ -98,8 +98,8 @@ The [public roadmap](https://github.com/RfidResearchGroup/proxmark3/wiki/Public- This repo compiles nicely on - WSL1 on Windows 10 - Proxspace v3.9 [release v3.9](https://github.com/Gator96100/ProxSpace/releases) - - Windows/mingw environment - - Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, Nethunter, Archlinux, Fedora, Debian, Rasbian + - Windows/MinGW environment + - Ubuntu, ParrotOS, Gentoo, Pentoo, Kali, NetHunter, Arch Linux, Fedora, Debian, Raspbian - Android / Termux - Mac OS X / Homebrew / Apple Silicon M1 - Docker container @@ -108,7 +108,7 @@ This repo compiles nicely on ## Precompiled binaries -We don't maintain any precompiled binaries in this repo. There is community effort over at the Proxmark3 forum where package maintainer [@gator96100](https://github.com/gator96100) has set up a AWS bucket with precompiled Proxspace (Mingw) binaries which are recompiled every night and with that also up-to-date. We link to these files here as to make it easier for users. If you are having troubles with these files, we suggest to read the [homepage of his proxmark builds](https://www.proxmarkbuilds.org/) or read the [sticky thread at forum](http://www.proxmark.org/forum/viewtopic.php?pid=24763#p24763) +We don't maintain any precompiled binaries in this repo. There is community effort over at the Proxmark3 forum where package maintainer [@gator96100](https://github.com/gator96100) has set up a AWS bucket with precompiled Proxspace (MinGW) binaries which are recompiled every night and with that also up-to-date. We link to these files here as to make it easier for users. If you are having troubles with these files, we suggest to read the [homepage of his proxmark builds](https://www.proxmarkbuilds.org/) or read the [sticky thread at forum](http://www.proxmark.org/forum/viewtopic.php?pid=24763#p24763) ### Proxmark3 RDV4 devices - [Precompiled builds for RDV40 dedicated x64](https://www.proxmarkbuilds.org/#rdv40-64/) @@ -118,7 +118,7 @@ We don't maintain any precompiled binaries in this repo. There is community effo - [Precompiled builds for RRG / Iceman repository x64](https://www.proxmarkbuilds.org/#rrg_other-64/) -## Offical channels +## Official channels Where do you find the community? - [RFID Hacking community discord server](https://discord.gg/QfPvGFRQxH) - [Proxmark3 IRC channel](http://webchat.freenode.net/?channels=#proxmark3) @@ -139,7 +139,7 @@ The official PM3-GUI from Gaucho will not work. Not to mention is quite old and - [Proxmark3 Universal GUI](https://github.com/burma69/PM3UniversalGUI) will work more or less. -- [Proxmark3 GUI crosscompiled](https://github.com/wh201906/Proxmark3GUI/) which is recently updated and claims to support latest source of this repo. +- [Proxmark3 GUI cross-compiled](https://github.com/wh201906/Proxmark3GUI/) which is recently updated and claims to support latest source of this repo. # Donations From cf672afe3f18ad620c5d6935bfd6ccee892224d0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 13 Apr 2021 21:52:48 +0200 Subject: [PATCH 250/373] reworked the support device section --- README.md | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c1b735240..d464b48d0 100644 --- a/README.md +++ b/README.md @@ -46,16 +46,33 @@ See the instruction links in the tables above to build, flash and run for your P ## Generic Proxmark3 platforms In order to build this repo for generic Proxmark3 platforms we urge you to read [Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md) -With generic Proxmark3 platforms we mean: +We define generic Proxmark3 platforms as following devices. + +**Supported** - RDV1, RDV2, RDV3 easy - - Proxmark Evolution (needs extra care) + - Ryscorp green PCB version - Radiowar black PCB version - - VX - numerous Chinese adapted versions of the RDV3 easy (kkmoon, pisworks etc) -> ⚠ **Note**: *Ryscorp green PCB version, Pm3 Pro* has different fpga and unknown pin assignments and therefore is not supported. +**Not supported** + - ⚠ Proxmark Evolution (EVO) + - **Note**: unknown pin assignments. + - ⚠ Ryscorp Proxmark3 Pro + - **Note**: device has different fpga and unknown pin assignments. + +**Unknown support status** + - ⚠ VX + +**256kb flash memory size of generic Proxmark3 platforms** + +> ⚠ **Note**: +> You need to keep a eye on how large your ARM chip built-in flash memory is. +> With 512kb you are fine but if its 256kb you need to compile this repo with even less functionality. +> When running the `./pm3-flash-all` you can see which size your device have if you have the bootloader from this repo installed. +> Otherwise you will find the size reported in the start message when running the Proxmark3 client `./pm3`. +> +> [OBS! Read the 256kb flash memory advisory](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md#256kb-versions) -> ⚠ **Note**: About flash memory size of other Proxmark3 platforms. You need to keep a eye on how large your ARM chip built-in flash memory is. With 512kb you are fine but if its 256kb you need to compile this repo with even less functionality. When running the `./pm3-flash-all` you can see which size your device have if you have the bootloader from this repo installed. Otherwise you will find the size reported in the start message when running the Proxmark3 client `./pm3`. ## What has changed? From fc61561e97263f4b64a7bf3441b1a8084ee2f0f5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 14 Apr 2021 08:15:14 +0200 Subject: [PATCH 251/373] hf felica auth1, auth2 - now use cliparser. --- client/src/cmdhffelica.c | 585 ++++++++++++++++++++++----------------- doc/cliparser_todo.txt | 2 - 2 files changed, 324 insertions(+), 263 deletions(-) diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 76bd98365..7a576c946 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -131,55 +131,40 @@ static int usage_hf_felica_sim(void) { } */ -static int usage_hf_felica_authentication1(void) { - PrintAndLogEx(NORMAL, "\nInfo: Initiate mutual authentication. This command must always be executed before Authentication2 command" - ", and mutual authentication is achieve only after Authentication2 command has succeeded."); - PrintAndLogEx(NORMAL, " - Auth1 Parameters:"); - PrintAndLogEx(NORMAL, " - Number of Areas n: 1-byte (1 <= n <= 8)"); - PrintAndLogEx(NORMAL, " - Area Code List: 2n byte"); - PrintAndLogEx(NORMAL, " - Number of Services m: 1-byte (1 <= n <= 8)"); - PrintAndLogEx(NORMAL, " - Service Code List: 2n byte"); - PrintAndLogEx(NORMAL, " - 3DES-Key: 128-bit master secret used for the encryption"); - PrintAndLogEx(NORMAL, " - M1c: Encrypted random number - challenge for tag authentication (8-byte)"); - PrintAndLogEx(NORMAL, " - Response:"); - PrintAndLogEx(NORMAL, " - Response Code: 11h 1-byte"); - PrintAndLogEx(NORMAL, " - Manufacture ID(IDm): 8-byte"); - PrintAndLogEx(NORMAL, " - M2c: 8-byte"); - PrintAndLogEx(NORMAL, " - M3c: 8-byte"); - PrintAndLogEx(NORMAL, " - Success: Card Mode switches to Mode1. You can check this with the request response command."); - PrintAndLogEx(NORMAL, " - Unsuccessful: Card should not respond at all."); - - PrintAndLogEx(NORMAL, "\nUsage: hf felica auth1 [-h][-i] <01 Number of Areas hex> <0A0B... Area Code List hex> <01 Number of Services hex> <0A0B... Service Code List hex> <0x0102030405060809... 3DES-key hex (16-byte)>"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); - PrintAndLogEx(NORMAL, "\nExamples: "); - PrintAndLogEx(NORMAL, " hf felica auth1 01 0000 01 8B00 AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB "); - PrintAndLogEx(NORMAL, " hf felica auth1 01 0000 01 8B00 AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAA "); - PrintAndLogEx(NORMAL, " hf felica auth1 -i 11100910C11BC407 01 0000 01 8B00 AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n\n"); +static int print_authentication1(void) { + PrintAndLogEx(INFO, "Initiate mutual authentication. This command must always be executed before Auth2 command"); + PrintAndLogEx(INFO, "and mutual authentication is achieve only after Auth2 command has succeeded."); + PrintAndLogEx(INFO, " - Auth1 Parameters:"); + PrintAndLogEx(INFO, " - Number of Areas n: 1-byte (1 <= n <= 8)"); + PrintAndLogEx(INFO, " - Area Code List: 2n byte"); + PrintAndLogEx(INFO, " - Number of Services m: 1-byte (1 <= n <= 8)"); + PrintAndLogEx(INFO, " - Service Code List: 2n byte"); + PrintAndLogEx(INFO, " - 3DES-Key: 128-bit master secret used for the encryption"); + PrintAndLogEx(INFO, " - M1c: Encrypted random number - challenge for tag authentication (8-byte)"); + PrintAndLogEx(INFO, " - Response:"); + PrintAndLogEx(INFO, " - Response Code: 11h 1-byte"); + PrintAndLogEx(INFO, " - Manufacture ID(IDm): 8-byte"); + PrintAndLogEx(INFO, " - M2c: 8-byte"); + PrintAndLogEx(INFO, " - M3c: 8-byte"); + PrintAndLogEx(INFO, " - Success: Card Mode switches to Mode1. You can check this with the request response command."); + PrintAndLogEx(INFO, " - Unsuccessful: Card should not respond at all."); return PM3_SUCCESS; } -static int usage_hf_felica_authentication2(void) { - PrintAndLogEx(NORMAL, "\nInfo: Complete mutual authentication. This command can only be executed subsquent to Authentication1" - " command."); - PrintAndLogEx(NORMAL, " - Auth2 Parameters:"); - PrintAndLogEx(NORMAL, " - Manufacturer IDm: (8-byte)"); - PrintAndLogEx(NORMAL, " - M3c: card challenge (8-byte)"); - PrintAndLogEx(NORMAL, " - 3DES Key: key used for decryption of M3c (16-byte)"); - PrintAndLogEx(NORMAL, " - Response (encrypted):"); - PrintAndLogEx(NORMAL, " - Response Code: 13h (1-byte)"); - PrintAndLogEx(NORMAL, " - IDtc: (8-byte)"); - PrintAndLogEx(NORMAL, " - IDi (encrypted): (8-byte)"); - PrintAndLogEx(NORMAL, " - PMi (encrypted): (8-byte)"); - PrintAndLogEx(NORMAL, " - Success: Card switches to mode2 and sends response frame."); - PrintAndLogEx(NORMAL, " - Unsuccessful: Card should not respond at all."); - PrintAndLogEx(NORMAL, "\nUsage: hf felica auth2 [-h][-i] <0102030405060708 M3c hex> <0x0102030405060809... 3DES-key hex (16-byte)>"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); - PrintAndLogEx(NORMAL, "\nExamples: "); - PrintAndLogEx(NORMAL, " hf felica auth2 0102030405060708 AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB"); - PrintAndLogEx(NORMAL, " hf felica auth2 -i 11100910C11BC407 0102030405060708 AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n\n"); - +static int print_authentication2(void) { + PrintAndLogEx(INFO, "Complete mutual authentication."); + PrintAndLogEx(INFO, "This command can only be executed subsquent to Auth1 command."); + PrintAndLogEx(INFO, " - Auth2 Parameters:"); + PrintAndLogEx(INFO, " - Manufacturer IDm: (8-byte)"); + PrintAndLogEx(INFO, " - M3c: card challenge (8-byte)"); + PrintAndLogEx(INFO, " - 3DES Key: key used for decryption of M3c (16-byte)"); + PrintAndLogEx(INFO, " - Response (encrypted):"); + PrintAndLogEx(INFO, " - Response Code: 13h (1-byte)"); + PrintAndLogEx(INFO, " - IDtc: (8-byte)"); + PrintAndLogEx(INFO, " - IDi (encrypted): (8-byte)"); + PrintAndLogEx(INFO, " - PMi (encrypted): (8-byte)"); + PrintAndLogEx(INFO, " - Success: Card switches to mode2 and sends response frame."); + PrintAndLogEx(INFO, " - Unsuccessful: Card should not respond at all."); return PM3_SUCCESS; } @@ -213,14 +198,6 @@ static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp, bool verbose) return false; } -/* - * Counts and sets the number of parameters. - */ -static void strip_cmds(const char *Cmd) { - while (*Cmd == ' ' || *Cmd == '\t') { - Cmd++; - } -} /** * Adds the last known IDm (8-Byte) to the data frame. @@ -386,30 +363,6 @@ static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *dat SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); } -/** - * Adds a parameter to the frame and checks if the parameter has the specific length. - * @param Cmd User input with the parameter. - * @param paramCount number of the parameter within the user input. - * @param data frame in which the data is stored. - * @param dataPosition position within frame where the data will be stored. - * @param length which the parameter should have and will be tested against. - * @return true if parameters was added. - */ -static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_t dataPosition, uint8_t length) { - if (param_getlength(Cmd, paramCount) == length) { - - if (param_gethex(Cmd, paramCount, data + dataPosition, length) == 1) - return false; - else - return true; - - } else { - PrintAndLogEx(ERR, "Param %s", Cmd); - PrintAndLogEx(ERR, "Incorrect Parameter length! Param %i should be %i", paramCount, length); - return false; - } -} - /** * Prints read-without-encryption response. * @param rd_noCry_resp Response frame. @@ -538,145 +491,212 @@ static void reverse_3des_key(uint8_t *master_key, int length, uint8_t *reverse_m * @return client result code. */ static int CmdHFFelicaAuthentication1(const char *Cmd) { - if (strlen(Cmd) < 4) { - return usage_hf_felica_authentication1(); - } + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica auth1", + "Initiate mutual authentication. This command must always be executed before Auth2 command\n" + "and mutual authentication is achieve only after Auth2 command has succeeded.\n" + _RED_("INCOMPLETE / EXPERIMENTAL COMMAND!!!"), + "hf felica auth1 --an 01 --acl 0000 --sn 01 --scl 8B00 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n" + "hf felica auth1 --an 01 --acl 0000 --sn 01 --scl 8B00 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAA\n" + "hf felica auth1 -i 11100910C11BC407 --an 01 --acl 0000 --sn 01 ..scl 8B00 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n" + ); + void *argtable[] = { + arg_param_begin, + arg_str0(NULL, "an", "", "number of areas, 1 byte"), + arg_str0(NULL, "acl", "", "area code list, 2 bytes"), + arg_str0("i", NULL, "", "set custom IDm"), + arg_str0(NULL, "sn", "", "number of service, 1 byte"), + arg_str0(NULL, "scl", "", "service code list, 2 bytes"), + arg_str0("k", "key", "", "3des key, 16 bytes"), + arg_lit0("v", "verbose", "verbose helptext"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); - PrintAndLogEx(INFO, "INCOMPLETE / EXPERIMENTAL COMMAND!!!"); - uint8_t data[PM3_CMD_DATA_SIZE]; - memset(data, 0 , sizeof(data)); - - bool custom_IDm = false; - strip_cmds(Cmd); - uint16_t datalen = 24; // Length (1), Command ID (1), IDm (8), Number of Area (1), Area Code List (2), Number of Service (1), Service Code List (2), M1c (8) - uint8_t paramCount = 0; - uint8_t flags = 0; - int i = 0; - while (Cmd[i] != '\0') { - if (Cmd[i] == '-') { - switch (tolower(Cmd[i + 1])) { - case 'h': - return usage_hf_felica_authentication1(); - case 'i': - paramCount++; - custom_IDm = true; - if (!add_param(Cmd, paramCount, data, 2, 16)) { - return PM3_EINVARG; - } - paramCount++; - i += 16; - break; - default: - return usage_hf_felica_authentication1(); - } - } - i++; - } - data[0] = (datalen & 0xFF); - data[1] = 0x10; // Command ID - if (!custom_IDm && !check_last_idm(data, datalen)) { + uint8_t an[1] = {0}; + int anlen = 0; + int res = CLIParamHexToBuf(arg_get_str(ctx, 1), an, sizeof(an), &anlen); + if (res) { + CLIParserFree(ctx); return PM3_EINVARG; } - // Number of Area (1), Area Code List (2), Number of Service (1), Service Code List (2), M1c (8) - uint8_t lengths[] = {2, 4, 2, 4}; - uint8_t dataPositions[] = {10, 11, 13, 14}; - for (i = 0; i < 4; i++) { - if (add_param(Cmd, paramCount, data, dataPositions[i], lengths[i])) { - paramCount++; - } else { - return PM3_EINVARG; - } + + uint8_t acl[2] = {0}; + int acllen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 2), acl, sizeof(acl), &acllen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint8_t idm[8] = {0}; + int ilen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 3), idm, sizeof(idm), &ilen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint8_t sn[1] = {0}; + int snlen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 4), sn, sizeof(sn), &snlen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint8_t scl[2] = {0}; + int scllen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 5), scl, sizeof(scl), &scllen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint8_t key[24] = {0}; + int keylen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 6), key, sizeof(key), &keylen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + bool verbose = arg_get_lit(ctx, 7); + CLIParserFree(ctx); + if (verbose) { + print_authentication1(); + return PM3_SUCCESS; + } + + uint8_t data[PM3_CMD_DATA_SIZE]; + memset(data, 0 , sizeof(data)); + data[0] = 0x0C; // Static length + data[1] = 0x3E; // Command ID + + bool custom_IDm = false; + + if (ilen) { + custom_IDm = true; + memcpy(data + 2, idm, 8); + } + + // Length (1), + // Command ID (1), + // IDm (8), + // Number of Area (1), + // Area Code List (2), + // Number of Service (1), + // Service Code List (2), + // M1c (16) + uint16_t datalen = 32; + data[0] = (datalen & 0xFF); + data[1] = 0x10; // Command ID + + if (custom_IDm == false && check_last_idm(data, datalen) == false) { + return PM3_EINVARG; + } + + if (anlen) { + data[10] = an[0]; + } + if (acllen) { + data[11] = acl[0]; + data[12] = acl[1]; + } + if (snlen) { + data[13] = sn[0]; + } + if (scllen) { + data[14] = scl[0]; + data[15] = scl[1]; + } + if (keylen) { + memcpy(data + 16, key, keylen); } // READER CHALLENGE - (RANDOM To Encrypt = Rac) - unsigned char input[8]; - input[0] = 0x1; - input[1] = 0x2; - input[2] = 0x3; - input[3] = 0x4; - input[4] = 0x5; - input[5] = 0x6; - input[6] = 0x7; - input[7] = 0x8; - PrintAndLogEx(INFO, "Reader challenge (unencrypted): %s", sprint_hex(input, 8)); - unsigned char output[8]; + uint8_t nonce[8] = {1,2,3,4,5,6,7,8}; + PrintAndLogEx(INFO, "Reader challenge (unencrypted): %s", sprint_hex(nonce, 8)); + // Create M1c Challenge with 3DES (3 Keys = 24, 2 Keys = 16) - uint8_t master_key[PM3_CMD_DATA_SIZE]; + uint8_t master_key[24]; mbedtls_des3_context des3_ctx; mbedtls_des3_init(&des3_ctx); - if (param_getlength(Cmd, paramCount) == 48) { - if (param_gethex(Cmd, paramCount, master_key, 48) == 1) { - PrintAndLogEx(ERR, "Failed param key"); - return PM3_EINVARG; - } - mbedtls_des3_set3key_enc(&des3_ctx, master_key); - PrintAndLogEx(INFO, "3DES Master Secret: %s", sprint_hex(master_key, 24)); - } else if (param_getlength(Cmd, paramCount) == 32) { - if (param_gethex(Cmd, paramCount, master_key, 32) == 1) { - PrintAndLogEx(ERR, "Failed param key"); - return PM3_EINVARG; - } + if (keylen == 24) { + + mbedtls_des3_set3key_enc(&des3_ctx, master_key); + PrintAndLogEx(INFO, "3DES Master Secret: %s", sprint_hex(master_key, keylen)); + + } else if (keylen == 16) { // Assumption: Master secret split in half for Kac, Kbc mbedtls_des3_set2key_enc(&des3_ctx, master_key); - PrintAndLogEx(INFO, "3DES Master Secret: %s", sprint_hex(master_key, 16)); + PrintAndLogEx(INFO, "3DES Master Secret: %s", sprint_hex(master_key, keylen)); } else { PrintAndLogEx(ERR, "Invalid key length"); + mbedtls_des3_free(&des3_ctx); return PM3_EINVARG; } - mbedtls_des3_crypt_ecb(&des3_ctx, input, output); - PrintAndLogEx(INFO, "3DES ENCRYPTED M1c: %s", sprint_hex(output, 8)); + uint8_t output[8]; + mbedtls_des3_crypt_ecb(&des3_ctx, nonce, output); + mbedtls_des3_free(&des3_ctx); + + PrintAndLogEx(INFO, "3DES ENCRYPTED M1c: %s", sprint_hex(output, sizeof(output))); + // Add M1c Challenge to frame - int frame_position = 16; - for (i = 0; i < 8; i++) { - data[frame_position++] = output[i]; - } + memcpy(data + 16, output, sizeof(output)); AddCrc(data, datalen); datalen += 2; - flags |= FELICA_APPEND_CRC; - flags |= FELICA_RAW; + uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW); - PrintAndLogEx(INFO, "Client Send AUTH1 Frame: %s", sprint_hex(data, datalen)); + PrintAndLogEx(INFO, "Client send AUTH1 frame: %s", sprint_hex(data, datalen)); clear_and_send_command(flags, datalen, data, 0); PacketResponseNG resp; - if (!waitCmdFelica(0, &resp, 1)) { - PrintAndLogEx(ERR, "\nGot no Response from card"); + if (waitCmdFelica(0, &resp, 1) == false) { + PrintAndLogEx(ERR, "no response from card"); return PM3_ERFTRANS; - } else { - felica_auth1_response_t auth1_response; - memcpy(&auth1_response, (felica_auth1_response_t *)resp.data.asBytes, sizeof(felica_auth1_response_t)); - if (auth1_response.frame_response.IDm[0] != 0) { - PrintAndLogEx(SUCCESS, "\nGot auth1 response:"); - PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(auth1_response.frame_response.IDm, sizeof(auth1_response.frame_response.IDm))); - PrintAndLogEx(SUCCESS, "M2C: %s", sprint_hex(auth1_response.m2c, sizeof(auth1_response.m2c))); - PrintAndLogEx(SUCCESS, "M3C: %s", sprint_hex(auth1_response.m3c, sizeof(auth1_response.m3c))); - // Assumption: Key swap method used - uint8_t reverse_master_key[PM3_CMD_DATA_SIZE]; - reverse_3des_key(master_key, 16, reverse_master_key); - mbedtls_des3_set2key_dec(&des3_ctx, reverse_master_key); - bool isKeyCorrect = false; - unsigned char p2c[8]; - mbedtls_des3_crypt_ecb(&des3_ctx, auth1_response.m2c, p2c); - for (i = 0; i < 8; i++) { - if (p2c[i] != input[i]) { - isKeyCorrect = false; - break; - } else { - isKeyCorrect = true; - } - } - if (isKeyCorrect) { - PrintAndLogEx(SUCCESS, "\nAuth1 done with correct key material! Use Auth2 now with M3C and same key"); + } + + felica_auth1_response_t auth1_response; + memcpy(&auth1_response, (felica_auth1_response_t *)resp.data.asBytes, sizeof(felica_auth1_response_t)); + + if (auth1_response.frame_response.IDm[0]) { + PrintAndLogEx(SUCCESS, "Auth1 response:"); + PrintAndLogEx(SUCCESS, "IDm... %s", sprint_hex(auth1_response.frame_response.IDm, sizeof(auth1_response.frame_response.IDm))); + PrintAndLogEx(SUCCESS, "M2C... %s", sprint_hex(auth1_response.m2c, sizeof(auth1_response.m2c))); + PrintAndLogEx(SUCCESS, "M3C... %s", sprint_hex(auth1_response.m3c, sizeof(auth1_response.m3c))); + + // Assumption: Key swap method used + uint8_t rev_master_key[PM3_CMD_DATA_SIZE]; + reverse_3des_key(master_key, 16, rev_master_key); + mbedtls_des3_set2key_dec(&des3_ctx, rev_master_key); + + bool is_key_correct = false; + unsigned char p2c[8]; + mbedtls_des3_crypt_ecb(&des3_ctx, auth1_response.m2c, p2c); + + for (uint8_t i = 0; i < 8; i++) { + if (p2c[i] != nonce[i]) { + is_key_correct = false; + break; } else { - PrintAndLogEx(INFO, "3DES secret (swapped decryption): %s", sprint_hex(reverse_master_key, 16)); - PrintAndLogEx(INFO, "P2c: %s", sprint_hex(p2c, 8)); - PrintAndLogEx(ERR, "Can't decrypt M2C with master secret (P1c != P2c)! Probably wrong keys or wrong decryption method"); + is_key_correct = true; } } + + if (is_key_correct) { + PrintAndLogEx(SUCCESS, "Auth1 done with correct key material!"); + PrintAndLogEx(SUCCESS, "Use Auth2 now with M3C and same key"); + } else { + PrintAndLogEx(INFO, "3DES secret (swapped decryption): %s", sprint_hex(rev_master_key, 16)); + PrintAndLogEx(INFO, "P2c: %s", sprint_hex(p2c, 8)); + PrintAndLogEx(ERR, "Can't decrypt M2C with master secret (P1c != P2c)!"); + PrintAndLogEx(ERR, "Probably wrong keys or wrong decryption method"); + } } return PM3_SUCCESS; } @@ -687,115 +707,158 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { * @return client result code. */ static int CmdHFFelicaAuthentication2(const char *Cmd) { - if (strlen(Cmd) < 2) { - return usage_hf_felica_authentication2(); + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf felica auth2", + "Complete mutual authentication. This command can only be executed subsquent to Auth1\n" + _RED_("INCOMPLETE / EXPERIMENTAL COMMAND!!!\n") + _RED_("EXPERIMENTAL COMMAND - M2c/P2c will be not checked"), + "hf felica auth2 --cc 0102030405060708 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n" + "hf felica auth2 -i 11100910C11BC407 --cc 0102030405060708 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n" + ); + void *argtable[] = { + arg_param_begin, + arg_str0("i", NULL, "", "set custom IDm"), + arg_str0("c", "cc", "", "M3c card challenge, 8 bytes"), + arg_str0("k", "key", "", "3des M3c decryption key, 16 bytes"), + arg_lit0("v", "verbose", "verbose helptext"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + uint8_t idm[8] = {0}; + int ilen = 0; + int res = CLIParamHexToBuf(arg_get_str(ctx, 1), idm, sizeof(idm), &ilen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; } - PrintAndLogEx(INFO, "INCOMPLETE / EXPERIMENTAL COMMAND!!!"); - PrintAndLogEx(INFO, "EXPERIMENTAL COMMAND - M2c/P2c will be not checked"); + + uint8_t cc[1] = {0}; + int cclen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 2), cc, sizeof(cc), &cclen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint8_t key[16] = {0}; + int keylen = 0; + res = CLIParamHexToBuf(arg_get_str(ctx, 3), key, sizeof(key), &keylen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + bool verbose = arg_get_lit(ctx, 4); + CLIParserFree(ctx); + if (verbose) { + print_authentication2(); + return PM3_SUCCESS; + } + uint8_t data[PM3_CMD_DATA_SIZE]; memset(data, 0 , sizeof(data)); bool custom_IDm = false; - strip_cmds(Cmd); + + if (ilen) { + custom_IDm = true; + memcpy(data + 2, idm, 8); + } + uint16_t datalen = 18; // Length (1), Command ID (1), IDm (8), M4c (8) - uint8_t paramCount = 0; - uint8_t flags = 0; - int i = 0; - while (Cmd[i] != '\0') { - if (Cmd[i] == '-') { - switch (tolower(Cmd[i + 1])) { - case 'h': - return usage_hf_felica_authentication2(); - case 'i': - paramCount++; - custom_IDm = true; - if (!add_param(Cmd, paramCount, data, 2, 16)) { - return PM3_EINVARG; - } - paramCount++; - i += 16; - break; - default: - return usage_hf_felica_authentication1(); - } - } - i++; - } - data[0] = (datalen & 0xFF); - data[1] = 0x12; // Command ID - if (!custom_IDm && !check_last_idm(data, datalen)) { + + if (custom_IDm == false && check_last_idm(data, datalen) == false) { return PM3_EINVARG; } - // M3c (8) - unsigned char m3c[8]; - if (add_param(Cmd, paramCount, m3c, 0, 16)) { - paramCount++; - } else { + if (cclen) { + memcpy(data + 16, cc, cclen); + } + + if (keylen) { + memcpy(data + 16, key, keylen); + } + + + if (custom_IDm == false && check_last_idm(data, datalen) == false) { return PM3_EINVARG; } - // Create M4c challenge response with 3DES - uint8_t master_key[PM3_CMD_DATA_SIZE]; - uint8_t reverse_master_key[PM3_CMD_DATA_SIZE]; - mbedtls_des3_context des3_ctx; - mbedtls_des3_init(&des3_ctx); - unsigned char p3c[8]; - if (param_getlength(Cmd, paramCount) == 32) { + // M3c (8) == cc +// unsigned char m3c[8]; == cc + + + mbedtls_des3_context des3_ctx_enc; + mbedtls_des3_context des3_ctx_dec; + + mbedtls_des3_init(&des3_ctx_enc); + mbedtls_des3_init(&des3_ctx_dec); + + if (keylen == 16) { + + // set encryption context + mbedtls_des3_set2key_enc(&des3_ctx_enc, key); + + // Create M4c challenge response with 3DES + uint8_t rev_key[16]; + reverse_3des_key(key, sizeof(key), rev_key); + + // set decryption context + mbedtls_des3_set2key_dec(&des3_ctx_dec, rev_key); - if (param_gethex(Cmd, paramCount, master_key, 32) == 1) { - PrintAndLogEx(ERR, "Failed param key"); - return PM3_EINVARG; - } - reverse_3des_key(master_key, 16, reverse_master_key); - mbedtls_des3_set2key_dec(&des3_ctx, reverse_master_key); - mbedtls_des3_set2key_enc(&des3_ctx, master_key); // Assumption: Key swap method used for E2 - PrintAndLogEx(INFO, "3DES Master Secret (encryption): %s", sprint_hex(master_key, 16)); - PrintAndLogEx(INFO, "3DES Master Secret (decryption): %s", sprint_hex(reverse_master_key, 16)); + PrintAndLogEx(INFO, "3DES Master Secret (encryption)... %s", sprint_hex_inrow(key, sizeof(key))); + PrintAndLogEx(INFO, "3DES Master Secret (decryption)... %s", sprint_hex_inrow(rev_key, sizeof(rev_key))); } else { PrintAndLogEx(ERR, "Invalid key length"); + mbedtls_des3_free(&des3_ctx_enc); + mbedtls_des3_free(&des3_ctx_dec); return PM3_EINVARG; } + // Decrypt m3c with reverse_master_key - mbedtls_des3_crypt_ecb(&des3_ctx, m3c, p3c); - PrintAndLogEx(INFO, "3DES decrypted M3c = P3c: %s", sprint_hex(p3c, 8)); + unsigned char p3c[8]; + mbedtls_des3_crypt_ecb(&des3_ctx_dec, cc, p3c); + PrintAndLogEx(INFO, "3DES decrypted M3c = P3c... %s", sprint_hex_inrow(p3c, sizeof(p3c))); + // Encrypt p3c with master_key unsigned char m4c[8]; - mbedtls_des3_crypt_ecb(&des3_ctx, p3c, m4c); - PrintAndLogEx(INFO, "3DES encrypted M4c: %s", sprint_hex(m4c, 8)); + mbedtls_des3_crypt_ecb(&des3_ctx_enc, p3c, m4c); + PrintAndLogEx(INFO, "3DES encrypted M4c......... %s", sprint_hex_inrow(m4c, sizeof(m4c))); + + // free contexts + mbedtls_des3_free(&des3_ctx_enc); + mbedtls_des3_free(&des3_ctx_dec); // Add M4c Challenge to frame - int frame_position = 10; - for (i = 0; i < 8; i++) { - data[frame_position++] = m4c[i]; - } + memcpy(data + 10, m4c, sizeof(m4c)); AddCrc(data, datalen); datalen += 2; - flags |= FELICA_APPEND_CRC; - flags |= FELICA_RAW; + uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW); PrintAndLogEx(INFO, "Client Send AUTH2 Frame: %s", sprint_hex(data, datalen)); clear_and_send_command(flags, datalen, data, 0); PacketResponseNG resp; - if (!waitCmdFelica(0, &resp, 1)) { - PrintAndLogEx(ERR, "\nGot no response from card"); + if (waitCmdFelica(0, &resp, 1) == false) { + PrintAndLogEx(ERR, "no response from card"); return PM3_ERFTRANS; + } + + felica_auth2_response_t auth2_response; + memcpy(&auth2_response, (felica_auth2_response_t *)resp.data.asBytes, sizeof(felica_auth2_response_t)); + if (auth2_response.code[0] != 0x12) { + PrintAndLogEx(SUCCESS, "Auth2 response:"); + PrintAndLogEx(SUCCESS, "IDtc.............. %s", sprint_hex(auth2_response.IDtc, sizeof(auth2_response.IDtc))); + PrintAndLogEx(SUCCESS, "IDi (encrypted)... %s", sprint_hex(auth2_response.IDi, sizeof(auth2_response.IDi))); + PrintAndLogEx(SUCCESS, "PMi (encrypted)... %s", sprint_hex(auth2_response.PMi, sizeof(auth2_response.PMi))); } else { - felica_auth2_response_t auth2_response; - memcpy(&auth2_response, (felica_auth2_response_t *)resp.data.asBytes, sizeof(felica_auth2_response_t)); - if (auth2_response.code[0] != 0x12) { - PrintAndLogEx(SUCCESS, "\nGot auth2 response:"); - PrintAndLogEx(SUCCESS, "IDtc: %s", sprint_hex(auth2_response.IDtc, sizeof(auth2_response.IDtc))); - PrintAndLogEx(SUCCESS, "IDi (encrypted): %s", sprint_hex(auth2_response.IDi, sizeof(auth2_response.IDi))); - PrintAndLogEx(SUCCESS, "PMi (encrypted): %s", sprint_hex(auth2_response.PMi, sizeof(auth2_response.PMi))); - } else { - PrintAndLogEx(ERR, "\nGot wrong frame format."); - } + PrintAndLogEx(ERR, "Got wrong frame format"); } return PM3_SUCCESS; } diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 8af74face..1fc5b5db4 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -7,5 +7,3 @@ hf 15 restore hf 15 wrbl hf 15 writeafi hf 15 writedsfid -hf felica auth1 -hf felica auth2 From eb4181d8beb7abb4e61054e2c71067e63560b082 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 14 Apr 2021 08:15:30 +0200 Subject: [PATCH 252/373] reenabled felica in hf search --- client/src/cmdhf.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index 7f53fea57..5183ee739 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -127,6 +127,15 @@ int CmdHFSearch(const char *Cmd) { } } + PROMPT_CLEARLINE; + PrintAndLogEx(INPLACE, " Searching for FeliCa tag..."); + if (IfPm3Felica()) { + if (read_felica_uid(false, false) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO18092 / FeliCa tag") " found\n"); + res = PM3_SUCCESS; + } + } + // 14b is the longest test (put last) PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, " Searching for ISO14443-B tag..."); @@ -139,22 +148,13 @@ int CmdHFSearch(const char *Cmd) { /* PROMPT_CLEARLINE; - PrintAndLogEx(INPLACE, " Searching for FeliCa tag..."); - if (IfPm3Felica()) { - if (read_felica_uid(false, false) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO18092 / FeliCa tag") " found\n"); + PrintAndLogEx(INPLACE, " Searching for CryptoRF tag..."); + if (IfPm3Iso14443b()) { + if (readHFCryptoRF(false, false) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("CryptoRF tag") " found\n"); res = PM3_SUCCESS; } } - - PROMPT_CLEARLINE; - PrintAndLogEx(INPLACE, " Searching for CryptoRF tag..."); - if (IfPm3Iso14443b()) { - if (readHFCryptoRF(false, false) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("CryptoRF tag") " found\n"); - res = PM3_SUCCESS; - } - } */ PROMPT_CLEARLINE; From 8f4a89fb205f87278719bf9ef722bf4bc02584aa Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 14 Apr 2021 08:15:59 +0200 Subject: [PATCH 253/373] text --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1823134ee..b51667f04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Change `lf t55xx restore` - now also support JSON (@iceman1001) + - Change `hf mf csetuid` - adapted to accept 7byte uids. ~untested~ (@iceman1001) + - Added `hf mf view/eload/cload` - now accepts bin/eml/json (@iceman1001) + - Added `hf mf eload/cload' - now accepts bin/eml/json (@iceman1001) - Fix RESTORE mis-annotation (@VortixDev) - Changed `smart raw` - now uses NG (@iceman1001) - Added `hf iclass configcard` - now can download / generate config card dumps with a cardhelper [WIP] (@iceman1001) From b9661f7794b06a7df0bd441ae52c98ff521da010 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 14 Apr 2021 09:08:00 +0200 Subject: [PATCH 254/373] text --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d464b48d0..8f0b682ae 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,19 @@ see the [Changelog file](CHANGELOG.md) which we try to keep updated. In short th * Cppcheck * GCC and Clang aggressive enforcement of diagnostic flags * auto detection of serial ports and seamless integration with Bluetooth addon - * reconnect to device + * reconnect to device from inside client + * the most comprehensive compiled known keys dictionaries + * Slimed down usb communications with NG-frames + * the most compiled public known key recovery software + * the fastest implementations of said software + * support multiple fileformats for dump files (BIN/EML/JSON) + * interoperability of said fileformats with libnfc, MFC tool app etc + * Supports more RFID based protocols than ever + * Easy install for package maintainers, distro maintainers + * More documentation + + +All of this and more is what makes this repo different from any other Proxmark3 firmware / client software. It is truely bleeding edge in that sense of available functionality and experience with it. With all extensive testing its also quite more stable than any other Proxmark3 repo. ## Development From a9885214461e033d50c399f75cdcd41ec17f42d7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 14 Apr 2021 09:08:57 +0200 Subject: [PATCH 255/373] text --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8f0b682ae..515c2cbff 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,7 @@ see the [Changelog file](CHANGELOG.md) which we try to keep updated. In short th * GCC and Clang aggressive enforcement of diagnostic flags * auto detection of serial ports and seamless integration with Bluetooth addon * reconnect to device from inside client + * Supports tearoff attacks * the most comprehensive compiled known keys dictionaries * Slimed down usb communications with NG-frames * the most compiled public known key recovery software @@ -109,6 +110,7 @@ see the [Changelog file](CHANGELOG.md) which we try to keep updated. In short th * Easy install for package maintainers, distro maintainers * More documentation + All of this and more is what makes this repo different from any other Proxmark3 firmware / client software. It is truely bleeding edge in that sense of available functionality and experience with it. With all extensive testing its also quite more stable than any other Proxmark3 repo. From 1ec1bda141b7079993b48b0e76483b4690c18837 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 14 Apr 2021 14:24:50 +0200 Subject: [PATCH 256/373] fix lf search --- client/src/cmdlfhitag.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index af984ce61..a23c8450d 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -693,11 +693,11 @@ static int CmdLFHitagWriter(const char *Cmd) { "In password mode the default key is 4D494B52 (MIKR)\n" "In crypto mode the default key is 4F4E4D494B52 (ONMIKR) format: ISK high + ISK low.", "Hitag S\n" - " lf hitag reader --03 --nrar 0102030411223344 -p 3 -d 01020304\n" - " lf hitag reader --04 -k 4F4E4D494B52 -p 3 -d 01020304\n" + " lf hitag writer --03 --nrar 0102030411223344 -p 3 -d 01020304\n" + " lf hitag writer --04 -k 4F4E4D494B52 -p 3 -d 01020304\n" "Hitag 2\n" - " lf hitag reader --24 -k 4F4E4D494B52 -p 3 -d 01020304\n" - " lf hitag reader --27 -k 4D494B52 -p 3 -d 01020304\n" + " lf hitag writer --24 -k 4F4E4D494B52 -p 3 -d 01020304\n" + " lf hitag writer --27 -k 4D494B52 -p 3 -d 01020304\n" ); void *argtable[] = { @@ -709,7 +709,7 @@ static int CmdLFHitagWriter(const char *Cmd) { arg_int1("p", "page", "", "page address to write to"), arg_str0("d", "data", "", "data, 4 hex bytes"), arg_str0("k","key", "", "key, 4 or 6 hex bytes"), - arg_str0(NULL,"nrar", "", "nonce / answer reader, 8 hex bytes"), + arg_str0(NULL,"nrar", "", "nonce / answer writer, 8 hex bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -963,5 +963,5 @@ int CmdLFHitag(const char *Cmd) { } int readHitagUid(void) { - return (CmdLFHitagReader("26") == PM3_SUCCESS); + return (CmdLFHitagReader("--26") == PM3_SUCCESS); } From ab3032c628a2468f888694f2202f22fb8cd8e368 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 10:39:56 +0200 Subject: [PATCH 257/373] hf 15 writeafi, writedsfi - now support cliparser --- client/src/cmdhf15.c | 282 ++++++++++++++++++++++++++++--------------- 1 file changed, 186 insertions(+), 96 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 9ac4385d1..efe541567 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -228,24 +228,6 @@ static int usage_15_info(void) { return PM3_SUCCESS; } -static int usage_15_writeafi(void) { - PrintAndLogEx(NORMAL, "Usage: hf 15 writeafi \n" - "\tuid (either): \n" - "\t <8B hex> full UID eg E011223344556677\n" - "\t u unaddressed mode\n" - "\t * scan for tag\n" - "\t AFI number 0-255"); - return PM3_SUCCESS; -} -static int usage_15_writedsfid(void) { - PrintAndLogEx(NORMAL, "Usage: hf 15 writedsfid \n" - "\tuid (either): \n" - "\t <8B hex> full UID eg E011223344556677\n" - "\t u unaddressed mode\n" - "\t * scan for tag\n" - "\t DSFID number 0-255"); - return PM3_SUCCESS; -} static int usage_15_dump(void) { PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-15693 tag and save it to file\n" "\n" @@ -515,7 +497,7 @@ static const char *TagErrorStr(uint8_t error) { // fast method to just read the UID of a tag (collision detection not supported) // *buf should be large enough to fit the 64bit uid // returns 1 if succeeded -static bool getUID(bool loop, uint8_t *buf) { +static int getUID(bool loop, uint8_t *buf) { uint8_t data[5]; data[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; @@ -528,7 +510,9 @@ static bool getUID(bool loop, uint8_t *buf) { uint8_t fast = 1; uint8_t reply = 1; - while (kbd_enter_pressed() == false) { + int res = PM3_SUCCESS; + + do { clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO15693_COMMAND, sizeof(data), fast, reply, data, sizeof(data)); PacketResponseNG resp; @@ -547,29 +531,55 @@ static bool getUID(bool loop, uint8_t *buf) { PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("%s"), getTagInfo_15(buf)); if (loop == false) { - return true; + res = PM3_SUCCESS; + break; } } } - if (loop == false) { - break; - } - } + } while (loop && kbd_enter_pressed() == false); DropField(); - return false; + return res; } // used with 'hf search' bool readHF15Uid(bool loop, bool verbose) { uint8_t uid[8] = {0}; - if (getUID(loop, uid) == false) { - if (verbose) PrintAndLogEx(WARNING, "No tag found"); + if (getUID(loop, uid) != PM3_SUCCESS) { + if (verbose) PrintAndLogEx(WARNING, "no tag found"); return false; } return true; } +// adds 6 +static uint8_t arg_add_default(void *at[]) { + at[0] = arg_param_begin; + at[1] = arg_str0("u", "uid", "", "full UID, 8 bytes"); + at[2] = arg_lit0(NULL, "ua", "unaddressed mode"); + at[3] = arg_lit0("*", NULL, "scan for tag"); + at[4] = arg_lit0("2", NULL, "use slower '1 out of 256' mode"); + at[5] = arg_lit0("o", "opt", "set OPTION Flag (needed for TI)"); + return 6; +} +static uint16_t arg_get_raw_flag(uint8_t uidlen, bool unaddressed, bool scan, bool add_option ) { + uint16_t flags = 0; + if (unaddressed) { + // unaddressed mode may not be supported by all vendors + flags |= (ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY); + } + if (uidlen == 8) { + flags |= (ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS); + } + if (scan) { + flags |= (ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS); + } + if (add_option) { + flags |= (ISO15_REQ_OPTION); + } + return flags; +} + /** * parses common HF 15 CMD parameters and prepares some data structures * Parameters: @@ -618,8 +628,8 @@ static bool prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t req[tmpreqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; req[tmpreqlen++] = iso15cmd; - if (getUID(false, uid) == false) { - PrintAndLogEx(WARNING, "No tag found"); + if (getUID(false, uid) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "no tag found"); return false; } memcpy(&req[tmpreqlen], uid, sizeof(uid)); @@ -637,7 +647,7 @@ static bool prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t PrintAndLogEx(SUCCESS, "Using UID " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); memcpy(&req[tmpreqlen], uid, sizeof(uid)); - tmpreqlen += sizeof(uid); + tmpreqlen += sizeof(uid); break; } // skip to next space @@ -1083,20 +1093,21 @@ static int CmdHF15Reader(const char *Cmd) { CLIParserInit(&ctx, "hf 15 reader", "Act as a ISO15693 reader. Look for ISO15693 tags until Enter or the pm3 button is pressed\n", "hf 15 reader\n" - "hf 15 reader -1"); + "hf 15 reader -@ -> Continuous mode"); void *argtable[] = { arg_param_begin, - arg_lit0("1", "one", "read once"), + arg_lit0("@", NULL, "continuous reader mode"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - bool read_once = arg_get_lit(ctx, 1); + bool cm = arg_get_lit(ctx, 1); CLIParserFree(ctx); - PrintAndLogEx(INFO, "Starting ISO15 reader mode"); - PrintAndLogEx(INFO, "press " _YELLOW_("`enter`") " to cancel"); - readHF15Uid(!read_once, true); + if (cm) { + PrintAndLogEx(INFO, "press " _GREEN_("`Enter`") " to exit"); + } + readHF15Uid(cm, true); return PM3_SUCCESS; } @@ -1193,40 +1204,79 @@ static int CmdHF15FindAfi(const char *Cmd) { // Writes the AFI (Application Family Identifier) of a card static int CmdHF15WriteAfi(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 writeafi", + "Write AFI on card", + "hf 15 writeafi -* --afi 12\n" + "hf 15 writeafi -u E011223344556677 --afi 12" + ); - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 3 || cmdp == 'h') return usage_15_writeafi(); + void *argtable[6+2] = {}; + uint8_t arglen = arg_add_default(argtable); + argtable[arglen++] = arg_int1(NULL, "afi", "", "AFI number (0-255)"); + argtable[arglen++] = arg_param_end; + + CLIExecWithReturn(ctx, Cmd, argtable, false); + + uint8_t uid[8]; + int uidlen = 0; + CLIGetHexWithReturn(ctx, 1, uid, &uidlen); + bool unaddressed = arg_get_lit(ctx, 2); + bool scan = arg_get_lit(ctx, 3); + int fast = (arg_get_lit(ctx, 4) == false); + bool add_option = arg_get_lit(ctx, 5); + + int afi = arg_get_int_def(ctx, 6, 0); + CLIParserFree(ctx); + + // sanity checks + if ((scan + unaddressed + uidlen) > 1) { + PrintAndLogEx(WARNING, "Select only one option /scan/unaddress/uid"); + return PM3_EINVARG; + } + + // request to be sent to device/card + uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option); + uint8_t req[PM3_CMD_DATA_SIZE] = {flags, ISO15_CMD_WRITEAFI}; + uint16_t reqlen = 2; + + if (unaddressed == false) { + if (scan) { + if (getUID(false, uid) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "no tag found"); + return PM3_EINVARG; + } else { + uidlen = 8; + } + } + + if (uidlen == 8) { + // add UID (scan, uid) + memcpy(req + reqlen, uid, sizeof(uid)); + reqlen += sizeof(uid); + } + PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); + } + + // enforce, since we are writing + req[0] |= ISO15_REQ_OPTION; + + req[reqlen++] = (uint8_t)afi; + + AddCrc15(req, reqlen); + reqlen += 2; // arg: len, speed, recv? // arg0 (datalen, cmd len? .arg0 == crc?) // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 ) // arg2 (recv == 1 == expect a response) - uint8_t req[PM3_CMD_DATA_SIZE] = {0}; - uint16_t reqlen = 0; - uint8_t fast = 1; - uint8_t reply = 1; - - char cmdbuf[100] = {0}; - char *cmd = cmdbuf; - strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); - - if (!prepareHF15Cmd(&cmd, &reqlen, &fast, req, ISO15_CMD_WRITEAFI)) - return PM3_SUCCESS; - - req[0] |= ISO15_REQ_OPTION; // Since we are writing - - int afinum = strtol(cmd, NULL, 0); - - req[reqlen++] = (uint8_t)afinum; - - AddCrc15(req, reqlen); - reqlen += 2; + uint8_t read_respone = 1; PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO15693_COMMAND, reqlen, fast, reply, req, reqlen); + SendCommandMIX(CMD_HF_ISO15693_COMMAND, reqlen, fast, read_respone, req, reqlen); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { PrintAndLogEx(ERR, "iso15693 timeout"); DropField(); return PM3_ETIMEOUT; @@ -1246,48 +1296,88 @@ static int CmdHF15WriteAfi(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "Wrote AFI 0x%02X", afinum); + PrintAndLogEx(SUCCESS, "Wrote AFI 0x%02X", afi); return PM3_SUCCESS; } // Writes the DSFID (Data Storage Format Identifier) of a card static int CmdHF15WriteDsfid(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 writedsfi", + "Write DSFID on card", + "hf 15 writedsfi -* --dsfid 12\n" + "hf 15 writedsfi -u E011223344556677 --dsfid 12" + ); + + void *argtable[6+2] = {}; + uint8_t arglen = arg_add_default(argtable); + argtable[arglen++] = arg_int1(NULL, "dsfid", "", "DSFID number (0-255)"); + argtable[arglen++] = arg_param_end; + + CLIExecWithReturn(ctx, Cmd, argtable, false); + + uint8_t uid[8]; + int uidlen = 0; + CLIGetHexWithReturn(ctx, 1, uid, &uidlen); + bool unaddressed = arg_get_lit(ctx, 2); + bool scan = arg_get_lit(ctx, 3); + int fast = (arg_get_lit(ctx, 4) == false); + bool add_option = arg_get_lit(ctx, 5); + + int dsfid = arg_get_int_def(ctx, 6, 0); + CLIParserFree(ctx); + + // sanity checks + if ((scan + unaddressed + uidlen) > 1) { + PrintAndLogEx(WARNING, "Select only one option /scan/unaddress/uid"); + return PM3_EINVARG; + } + + // request to be sent to device/card + uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option); + uint8_t req[PM3_CMD_DATA_SIZE] = {flags, ISO15_CMD_WRITEDSFID}; + uint16_t reqlen = 2; + + if (unaddressed == false) { + if (scan) { + if (getUID(false, uid) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "no tag found"); + return PM3_EINVARG; + } else { + uidlen = 8; + } + } + + if (uidlen == 8) { + // add UID (scan, uid) + memcpy(req + reqlen, uid, sizeof(uid)); + reqlen += sizeof(uid); + } + PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); + } + + // enforce, since we are writing + req[0] |= ISO15_REQ_OPTION; + + // dsfid + req[reqlen++] = (uint8_t)dsfid; + + AddCrc15(req, reqlen); + reqlen += 2; - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 3 || cmdp == 'h') return usage_15_writedsfid(); // arg: len, speed, recv? // arg0 (datalen, cmd len? .arg0 == crc?) // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 ) // arg2 (recv == 1 == expect a response) - uint8_t req[PM3_CMD_DATA_SIZE] = {0}; - uint16_t reqlen = 0; - uint8_t fast = 1; - uint8_t reply = 1; - int dsfidnum; + uint8_t read_respone = 1; - char cmdbuf[100] = {0}; - char *cmd = cmdbuf; - strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); - - if (prepareHF15Cmd(&cmd, &reqlen, &fast, req, ISO15_CMD_WRITEDSFID) == false) - return PM3_SUCCESS; - - req[0] |= ISO15_REQ_OPTION; // Since we are writing - - dsfidnum = strtol(cmd, NULL, 0); - - req[reqlen++] = (uint8_t)dsfidnum; - - AddCrc15(req, reqlen); - reqlen += 2; - - // PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(req, reqlen) ); + PrintAndLogEx(DEBUG, "cmd %s", sprint_hex(req, reqlen) ); PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO15693_COMMAND, reqlen, fast, reply, req, reqlen); + SendCommandMIX(CMD_HF_ISO15693_COMMAND, reqlen, fast, read_respone, req, reqlen); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { PrintAndLogEx(ERR, "iso15693 timeout"); DropField(); return PM3_ETIMEOUT; @@ -1307,7 +1397,7 @@ static int CmdHF15WriteDsfid(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "Wrote DSFID 0x%02X", dsfidnum); + PrintAndLogEx(SUCCESS, "Wrote DSFID 0x%02X", dsfid); return PM3_SUCCESS; } @@ -1340,8 +1430,8 @@ static int CmdHF15Dump(const char *Cmd) { //Validations if (errors) return usage_15_dump(); - if (getUID(false, uid) == false) { - PrintAndLogEx(WARNING, "No tag found."); + if (getUID(false, uid) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "no tag found"); return PM3_ESOFT; } @@ -1848,7 +1938,7 @@ static int CmdHF15Restore(const char *Cmd) { } uint8_t uid[8] = {0x00}; - if (getUID(false, uid) == false) { + if (getUID(false, uid) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "no tag found"); return PM3_ESOFT; } @@ -1950,8 +2040,8 @@ static int CmdHF15CSetUID(const char *Cmd) { PrintAndLogEx(INFO, "getting current card details..."); uint8_t carduid[8] = {0x00}; - if (getUID(false, carduid) == false) { - PrintAndLogEx(FAILED, "can't read card UID"); + if (getUID(false, carduid) != PM3_SUCCESS) { + PrintAndLogEx(FAILED, "no tag found"); return PM3_ESOFT; } @@ -1968,8 +2058,8 @@ static int CmdHF15CSetUID(const char *Cmd) { PrintAndLogEx(INFO, "getting updated card details..."); - if (getUID(false, carduid) == false) { - PrintAndLogEx(FAILED, "can't read card UID"); + if (getUID(false, carduid) != PM3_SUCCESS) { + PrintAndLogEx(FAILED, "no tag found"); return PM3_ESOFT; } From 9396aa4bf6aa1217ac86efe4dec2d15792d9d8a9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 10:40:23 +0200 Subject: [PATCH 258/373] text --- client/src/cmdhf14a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 095bd5a44..c6283e794 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -412,7 +412,7 @@ static int CmdHF14AReader(const char *Cmd) { arg_lit0("s", "silent", "silent (no messages)"), arg_lit0(NULL, "drop", "just drop the signal field"), arg_lit0(NULL, "skip", "ISO14443-3 select only (skip RATS)"), - arg_lit0("@", NULL, "optional - continuous reader mode"), + arg_lit0("@", NULL, "continuous reader mode"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); From d20a5f49dd652a95168d5000c6f796b56cf5a094 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 10:41:11 +0200 Subject: [PATCH 259/373] text --- doc/cliparser_todo.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 1fc5b5db4..12ad2bef1 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -5,5 +5,4 @@ hf 15 rdbl hf 15 readmulti hf 15 restore hf 15 wrbl -hf 15 writeafi hf 15 writedsfid From d5aee1bd00c2833f812fd04bc692dcac16ab8f91 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 10:42:47 +0200 Subject: [PATCH 260/373] text --- client/src/cmdhf15.c | 6 +++--- doc/cliparser_todo.txt | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index efe541567..778d828a7 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1303,10 +1303,10 @@ static int CmdHF15WriteAfi(const char *Cmd) { // Writes the DSFID (Data Storage Format Identifier) of a card static int CmdHF15WriteDsfid(const char *Cmd) { CLIParserContext *ctx; - CLIParserInit(&ctx, "hf 15 writedsfi", + CLIParserInit(&ctx, "hf 15 writedsfid", "Write DSFID on card", - "hf 15 writedsfi -* --dsfid 12\n" - "hf 15 writedsfi -u E011223344556677 --dsfid 12" + "hf 15 writedsfid -* --dsfid 12\n" + "hf 15 writedsfid -u E011223344556677 --dsfid 12" ); void *argtable[6+2] = {}; diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 12ad2bef1..ec2f4bc34 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -5,4 +5,3 @@ hf 15 rdbl hf 15 readmulti hf 15 restore hf 15 wrbl -hf 15 writedsfid From f76f98b3182278f19bf67c22dd52c103a2c78bf1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 10:54:40 +0200 Subject: [PATCH 261/373] hf 15 rdbl - now uses cliparser --- client/src/cmdhf15.c | 106 +++++++++++++++++++++++++---------------- doc/cliparser_todo.txt | 1 - 2 files changed, 66 insertions(+), 41 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 778d828a7..a6fe8af87 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -267,17 +267,6 @@ static int usage_15_raw(void) { PrintAndLogOptions(options, 4, 3); return PM3_SUCCESS; } -static int usage_15_read(void) { - PrintAndLogEx(NORMAL, "Usage: hf 15 rdbl [options] \n" - "Options:\n" - "\t-2 use slower '1 out of 256' mode\n" - "\tuid (either): \n" - "\t <8B hex> full UID eg E011223344556677\n" - "\t u unaddressed mode\n" - "\t * scan for tag\n" - "\t page number 0-255"); - return PM3_SUCCESS; -} static int usage_15_write(void) { PrintAndLogEx(NORMAL, "Usage: hf 15 wrbl [options] \n" "Options:\n" @@ -1723,42 +1712,79 @@ static int CmdHF15Readmulti(const char *Cmd) { * Commandline handling: HF15 CMD READ * Reads a single Block */ -static int CmdHF15Read(const char *Cmd) { +static int CmdHF15Readblock(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 3 || cmdp == 'h') return usage_15_read(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 rdbl", + "Read page on ISO15693 card", + "hf 15 rdbl -* -b 12\n" + "hf 15 rdbl -u E011223344556677 -b 12" + ); + + void *argtable[6+2] = {}; + uint8_t arglen = arg_add_default(argtable); + argtable[arglen++] = arg_int1("b", "blk", "", "page number (0-255)"); + argtable[arglen++] = arg_param_end; + + CLIExecWithReturn(ctx, Cmd, argtable, false); + + uint8_t uid[8]; + int uidlen = 0; + CLIGetHexWithReturn(ctx, 1, uid, &uidlen); + bool unaddressed = arg_get_lit(ctx, 2); + bool scan = arg_get_lit(ctx, 3); + int fast = (arg_get_lit(ctx, 4) == false); + bool add_option = arg_get_lit(ctx, 5); + + int block = arg_get_int_def(ctx, 6, 0); + CLIParserFree(ctx); + + // sanity checks + if ((scan + unaddressed + uidlen) > 1) { + PrintAndLogEx(WARNING, "Select only one option /scan/unaddress/uid"); + return PM3_EINVARG; + } + + // request to be sent to device/card + uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option); + uint8_t req[PM3_CMD_DATA_SIZE] = {flags, ISO15_CMD_READ}; + uint16_t reqlen = 2; + + if (unaddressed == false) { + if (scan) { + if (getUID(false, uid) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "no tag found"); + return PM3_EINVARG; + } else { + uidlen = 8; + } + } + + if (uidlen == 8) { + // add UID (scan, uid) + memcpy(req + reqlen, uid, sizeof(uid)); + reqlen += sizeof(uid); + } + PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); + } + // add OPTION flag, in order to get lock-info + req[0] |= ISO15_REQ_OPTION; + + req[reqlen++] = (uint8_t)block; + + AddCrc15(req, reqlen); + reqlen += 2; // arg: len, speed, recv? // arg0 (datalen, cmd len? .arg0 == crc?) // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 ) // arg2 (recv == 1 == expect a response) - uint8_t req[PM3_CMD_DATA_SIZE] = {0}; - uint16_t reqlen = 0; - uint8_t fast = 1; - uint8_t reply = 1; - int blocknum; - char cmdbuf[100] = {0}; - char *cmd = cmdbuf; - strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); - - if (prepareHF15Cmd(&cmd, &reqlen, &fast, req, ISO15_CMD_READ) == false) - return PM3_SUCCESS; - - // add OPTION flag, in order to get lock-info - req[0] |= ISO15_REQ_OPTION; - - blocknum = strtol(cmd, NULL, 0); - - req[reqlen++] = (uint8_t)blocknum; - - AddCrc15(req, reqlen); - reqlen += 2; - + uint8_t read_respone = 1; PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO15693_COMMAND, reqlen, fast, reply, req, reqlen); + SendCommandMIX(CMD_HF_ISO15693_COMMAND, reqlen, fast, read_respone, req, reqlen); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { PrintAndLogEx(ERR, "iso15693 timeout"); DropField(); return PM3_ETIMEOUT; @@ -1789,7 +1815,7 @@ static int CmdHF15Read(const char *Cmd) { // print response PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "block #%3d |lck| ascii", blocknum); + PrintAndLogEx(INFO, " #%3d |lck| ascii", block); PrintAndLogEx(INFO, "------------+---+------"); PrintAndLogEx(INFO, "%s| %d | %s", sprint_hex(data + 2, status - 4), data[1], sprint_ascii(data + 2, status - 4)); PrintAndLogEx(NORMAL, ""); @@ -2089,7 +2115,7 @@ static command_t CommandTable[] = { {"info", CmdHF15Info, IfPm3Iso15693, "Tag information"}, {"sniff", CmdHF15Sniff, IfPm3Iso15693, "Sniff ISO15693 traffic"}, {"raw", CmdHF15Raw, IfPm3Iso15693, "Send raw hex data to tag"}, - {"rdbl", CmdHF15Read, IfPm3Iso15693, "Read a block"}, + {"rdbl", CmdHF15Readblock, IfPm3Iso15693, "Read a block"}, {"reader", CmdHF15Reader, IfPm3Iso15693, "Act like an ISO15693 reader"}, {"readmulti", CmdHF15Readmulti, IfPm3Iso15693, "Reads multiple Blocks"}, {"restore", CmdHF15Restore, IfPm3Iso15693, "Restore from file to all memory pages of an ISO15693 tag"}, diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index ec2f4bc34..91fdea6c4 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -1,7 +1,6 @@ hf 15 dump hf 15 info hf 15 raw -hf 15 rdbl hf 15 readmulti hf 15 restore hf 15 wrbl From 93474264569e378fb7a3e55a4b2f8a1230eaccfc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 11:05:57 +0200 Subject: [PATCH 262/373] hf 15 rdmulti - now uses cliparser --- client/src/cmdhf15.c | 109 +++++++++++++++++++++++++---------------- doc/cliparser_todo.txt | 1 - doc/commands.md | 2 +- 3 files changed, 68 insertions(+), 44 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index a6fe8af87..e3382ba7a 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -280,18 +280,6 @@ static int usage_15_write(void) { "\t data to be written eg AA BB CC DD"); return PM3_SUCCESS; } -static int usage_15_readmulti(void) { - PrintAndLogEx(NORMAL, "Usage: hf 15 readmulti [options] \n" - "Options:\n" - "\t-2 use slower '1 out of 256' mode\n" - "\tuid (either): \n" - "\t <8B hex> full UID eg E011223344556677\n" - "\t u unaddressed mode\n" - "\t * scan for tag\n" - "\t 0-255, page number to start\n" - "\t 1-6, number of pages"); - return PM3_SUCCESS; -} static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) { @@ -1619,47 +1607,86 @@ static int CmdHF15Raw(const char *Cmd) { */ static int CmdHF15Readmulti(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 3 || cmdp == 'h') return usage_15_readmulti(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 rdmulti", + "Read multiple pages on a ISO15693 card", + "hf 15 rdmulti -* -b 1 --cnt 6 -> read 6 blocks\n" + "hf 15 rdmulti -u E011223344556677 -b 12 --cnt 3 -> read three blocks" + ); - uint8_t req[PM3_CMD_DATA_SIZE] = {0}; - uint16_t reqlen = 0; - uint8_t fast = 1; - uint8_t reply = 1; + void *argtable[6+3] = {}; + uint8_t arglen = arg_add_default(argtable); + argtable[arglen++] = arg_int1("b", NULL, "", "first page number (0-255)"); + argtable[arglen++] = arg_int1(NULL, "cnt", "", "number of pages (1-6)"); + argtable[arglen++] = arg_param_end; - char cmdbuf[100] = {0}; - char *cmd = cmdbuf; - strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); + CLIExecWithReturn(ctx, Cmd, argtable, false); - if (!prepareHF15Cmd(&cmd, &reqlen, &fast, req, ISO15_CMD_READMULTI)) - return PM3_SUCCESS; + uint8_t uid[8]; + int uidlen = 0; + CLIGetHexWithReturn(ctx, 1, uid, &uidlen); + bool unaddressed = arg_get_lit(ctx, 2); + bool scan = arg_get_lit(ctx, 3); + int fast = (arg_get_lit(ctx, 4) == false); + bool add_option = arg_get_lit(ctx, 5); - // add OPTION flag, in order to get lock-info - req[0] |= ISO15_REQ_OPTION; + int block = arg_get_int_def(ctx, 6, 0); + int blockcnt = arg_get_int_def(ctx, 7, 0); - // decimal - uint8_t pagenum = param_get8ex(cmd, 0, 0, 10); - uint8_t pagecount = param_get8ex(cmd, 1, 0, 10); + CLIParserFree(ctx); - if (pagecount > 6) { - PrintAndLogEx(WARNING, "Page count must be 6 or less (%d)", pagecount); + // sanity checks + if (blockcnt > 6) { + PrintAndLogEx(WARNING, "Page count must be 6 or less (%d)", blockcnt); return PM3_EINVARG; } + if ((scan + unaddressed + uidlen) > 1) { + PrintAndLogEx(WARNING, "Select only one option /scan/unaddress/uid"); + return PM3_EINVARG; + } + + // request to be sent to device/card + uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option); + uint8_t req[PM3_CMD_DATA_SIZE] = {flags, ISO15_CMD_READMULTI}; + uint16_t reqlen = 2; + + if (unaddressed == false) { + if (scan) { + if (getUID(false, uid) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "no tag found"); + return PM3_EINVARG; + } else { + uidlen = 8; + } + } + + if (uidlen == 8) { + // add UID (scan, uid) + memcpy(req + reqlen, uid, sizeof(uid)); + reqlen += sizeof(uid); + } + PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); + } + // add OPTION flag, in order to get lock-info + req[0] |= ISO15_REQ_OPTION; + // 0 means 1 page, // 1 means 2 pages, ... - if (pagecount > 0) pagecount--; + if (blockcnt > 0) blockcnt--; + + req[reqlen++] = block; + req[reqlen++] = blockcnt; - req[reqlen++] = pagenum; - req[reqlen++] = pagecount; AddCrc15(req, reqlen); reqlen += 2; + uint8_t read_respone = 1; PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO15693_COMMAND, reqlen, fast, reply, req, reqlen); + SendCommandMIX(CMD_HF_ISO15693_COMMAND, reqlen, fast, read_respone, req, reqlen); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { PrintAndLogEx(FAILED, "iso15693 card timeout"); DropField(); return PM3_ETIMEOUT; @@ -1691,12 +1718,11 @@ static int CmdHF15Readmulti(const char *Cmd) { // skip status byte int start = 1; - int stop = (pagecount + 1) * 5; - int currblock = pagenum; - + int stop = (blockcnt + 1) * 5; + int currblock = block; PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "block# | data |lck| ascii"); + PrintAndLogEx(INFO, " # | data |lck| ascii"); PrintAndLogEx(INFO, "---------+--------------+---+----------"); for (int i = start; i < stop; i += 5) { @@ -1713,8 +1739,7 @@ static int CmdHF15Readmulti(const char *Cmd) { * Reads a single Block */ static int CmdHF15Readblock(const char *Cmd) { - - CLIParserContext *ctx; + CLIParserContext *ctx; CLIParserInit(&ctx, "hf 15 rdbl", "Read page on ISO15693 card", "hf 15 rdbl -* -b 12\n" @@ -2116,8 +2141,8 @@ static command_t CommandTable[] = { {"sniff", CmdHF15Sniff, IfPm3Iso15693, "Sniff ISO15693 traffic"}, {"raw", CmdHF15Raw, IfPm3Iso15693, "Send raw hex data to tag"}, {"rdbl", CmdHF15Readblock, IfPm3Iso15693, "Read a block"}, + {"rdmulti", CmdHF15Readmulti, IfPm3Iso15693, "Reads multiple blocks"}, {"reader", CmdHF15Reader, IfPm3Iso15693, "Act like an ISO15693 reader"}, - {"readmulti", CmdHF15Readmulti, IfPm3Iso15693, "Reads multiple Blocks"}, {"restore", CmdHF15Restore, IfPm3Iso15693, "Restore from file to all memory pages of an ISO15693 tag"}, {"samples", CmdHF15Samples, IfPm3Iso15693, "Acquire Samples as Reader (enables carrier, sends inquiry)"}, {"sim", CmdHF15Sim, IfPm3Iso15693, "Fake an ISO15693 tag"}, diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 91fdea6c4..3d72aa92b 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -1,6 +1,5 @@ hf 15 dump hf 15 info hf 15 raw -hf 15 readmulti hf 15 restore hf 15 wrbl diff --git a/doc/commands.md b/doc/commands.md index a44840d61..9f25525a4 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -219,8 +219,8 @@ Check column "offline" for their availability. |`hf 15 sniff `|N |`Sniff ISO15693 traffic` |`hf 15 raw `|N |`Send raw hex data to tag` |`hf 15 rdbl `|N |`Read a block` +|`hf 15 rdmulti `|N |`Reads multiple blocks` |`hf 15 reader `|N |`Act like an ISO15693 reader` -|`hf 15 readmulti `|N |`Reads multiple Blocks` |`hf 15 restore `|N |`Restore from file to all memory pages of an ISO15693 tag` |`hf 15 samples `|N |`Acquire Samples as Reader (enables carrier, sends inquiry)` |`hf 15 sim `|N |`Fake an ISO15693 tag` From 0f9365d2ddcaff6cdfca76679abd2c82dcc7d8e4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 11:16:23 +0200 Subject: [PATCH 263/373] hf 15 rdmulti - now colors lockbyte if set --- client/src/cmdhf15.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index e3382ba7a..0e8f68394 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1726,10 +1726,15 @@ static int CmdHF15Readmulti(const char *Cmd) { PrintAndLogEx(INFO, "---------+--------------+---+----------"); for (int i = start; i < stop; i += 5) { - PrintAndLogEx(INFO, "%3d/0x%02X | %s | %d | %s", currblock, currblock, sprint_hex(data + i + 1, 4), data[i], sprint_ascii(data + i + 1, 4)); + char lck[16] = {0}; + if (data[i]) { + sprintf(lck, _RED_("%d"), data[i]); + } else { + sprintf(lck, "%d", data[i]); + } + PrintAndLogEx(INFO, "%3d/0x%02X | %s | %s | %s", currblock, currblock, sprint_hex(data + i + 1, 4), lck, sprint_ascii(data + i + 1, 4)); currblock++; } - PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } @@ -1839,10 +1844,16 @@ static int CmdHF15Readblock(const char *Cmd) { } // print response + char lck[16] = {0}; + if (data[1]) { + sprintf(lck, _RED_("%d"), data[1]); + } else { + sprintf(lck, "%d", data[1]); + } PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, " #%3d |lck| ascii", block); PrintAndLogEx(INFO, "------------+---+------"); - PrintAndLogEx(INFO, "%s| %d | %s", sprint_hex(data + 2, status - 4), data[1], sprint_ascii(data + 2, status - 4)); + PrintAndLogEx(INFO, "%s| %s | %s", sprint_hex(data + 2, status - 4), lck, sprint_ascii(data + 2, status - 4)); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } From 3e1a1abbbbee920749154cf8df368b7cb5aa0816 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 12:15:44 +0200 Subject: [PATCH 264/373] hf 15 info - now uses cliparser --- client/src/cmdhf15.c | 100 ++++++++++++++++++++++++----------------- doc/cliparser_todo.txt | 1 - 2 files changed, 60 insertions(+), 41 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 0e8f68394..f659c09fc 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -211,23 +211,6 @@ const productName_t uidmapping[] = { static int CmdHF15Help(const char *Cmd); -static int usage_15_info(void) { - PrintAndLogEx(NORMAL, "Uses the optional command 'get_systeminfo' 0x2B to try and extract information\n" - "command may fail, depending on tag.\n" - "defaults to '1 out of 4' mode\n" - "\n" - "Usage: hf 15 info [options] \n" - "Options:\n" - "\t-2 use slower '1 out of 256' mode\n" - "\tuid (either): \n" - "\t <8B hex> full UID eg E011223344556677\n" - "\t u unaddressed mode\n" - "\t * scan for tag\n" - "Examples:\n" - _YELLOW_("\thf 15 info u")); - return PM3_SUCCESS; -} - static int usage_15_dump(void) { PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-15693 tag and save it to file\n" "\n" @@ -948,29 +931,70 @@ static int NxpSysInfo(uint8_t *uid) { */ static int CmdHF15Info(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_info(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 info", + "Uses the optional command `get_systeminfo` 0x2B to try and extract information", + "hf 15 info\n" + "hf 15 info -*\n" + "hf 15 info -u E011223344556677" + ); - PacketResponseNG resp; - uint8_t req[PM3_CMD_DATA_SIZE] = {0}; - uint16_t reqlen; - uint8_t fast = 1; - uint8_t reply = 1; - uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + void *argtable[6+1] = {}; + uint8_t arglen = arg_add_default(argtable); + argtable[arglen++] = arg_param_end; - char cmdbuf[100] = {0}; - char *cmd = cmdbuf; - strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); + CLIExecWithReturn(ctx, Cmd, argtable, true); + + uint8_t uid[8]; + int uidlen = 0; + CLIGetHexWithReturn(ctx, 1, uid, &uidlen); + bool unaddressed = arg_get_lit(ctx, 2); + bool scan = arg_get_lit(ctx, 3); + int fast = (arg_get_lit(ctx, 4) == false); + bool add_option = arg_get_lit(ctx, 5); + + CLIParserFree(ctx); + + // sanity checks + if ((scan + unaddressed + uidlen) > 1) { + PrintAndLogEx(WARNING, "Select only one option /scan/unaddress/uid"); + return PM3_EINVARG; + } + + // default fallback to scan for tag. + if (unaddressed == false && uidlen != 8) { + scan = true; + } + + // request to be sent to device/card + uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option); + uint8_t req[PM3_CMD_DATA_SIZE] = {flags, ISO15_CMD_SYSINFO}; + uint16_t reqlen = 2; + + if (scan) { + if (getUID(false, uid) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "no tag found"); + return PM3_EINVARG; + } + uidlen = 8; + } + + if (uidlen == 8) { + // add UID (scan, uid) + memcpy(req + reqlen, uid, sizeof(uid)); + reqlen += sizeof(uid); + } + PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); - if (prepareHF15Cmd(&cmd, &reqlen, &fast, req, ISO15_CMD_SYSINFO) == false) - return PM3_SUCCESS; AddCrc15(req, reqlen); reqlen += 2; + uint8_t read_response = 1; + PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO15693_COMMAND, reqlen, fast, reply, req, reqlen); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + SendCommandMIX(CMD_HF_ISO15693_COMMAND, reqlen, fast, read_response, req, reqlen); + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { PrintAndLogEx(WARNING, "iso15693 timeout"); DropField(); return PM3_ETIMEOUT; @@ -1222,9 +1246,8 @@ static int CmdHF15WriteAfi(const char *Cmd) { if (getUID(false, uid) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "no tag found"); return PM3_EINVARG; - } else { - uidlen = 8; } + uidlen = 8; } if (uidlen == 8) { @@ -1320,9 +1343,8 @@ static int CmdHF15WriteDsfid(const char *Cmd) { if (getUID(false, uid) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "no tag found"); return PM3_EINVARG; - } else { - uidlen = 8; } + uidlen = 8; } if (uidlen == 8) { @@ -1656,9 +1678,8 @@ static int CmdHF15Readmulti(const char *Cmd) { if (getUID(false, uid) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "no tag found"); return PM3_EINVARG; - } else { - uidlen = 8; } + uidlen = 8; } if (uidlen == 8) { @@ -1785,9 +1806,8 @@ static int CmdHF15Readblock(const char *Cmd) { if (getUID(false, uid) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "no tag found"); return PM3_EINVARG; - } else { - uidlen = 8; } + uidlen = 8; } if (uidlen == 8) { diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 3d72aa92b..051df2e51 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -1,5 +1,4 @@ hf 15 dump -hf 15 info hf 15 raw hf 15 restore hf 15 wrbl From d33ba25d3fbfd4ae422a9f90613f7eb7c929df46 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 12:31:16 +0200 Subject: [PATCH 265/373] hf 15 wrbl - now uses cliparser --- client/src/cmdhf15.c | 193 ++++++++++++++--------------------------- doc/cliparser_todo.txt | 1 - 2 files changed, 65 insertions(+), 129 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index f659c09fc..9288b3141 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -250,19 +250,6 @@ static int usage_15_raw(void) { PrintAndLogOptions(options, 4, 3); return PM3_SUCCESS; } -static int usage_15_write(void) { - PrintAndLogEx(NORMAL, "Usage: hf 15 wrbl [options] \n" - "Options:\n" - "\t-2 use slower '1 out of 256' mode\n" - "\t-o set OPTION Flag (needed for TI)\n" - "\tuid (either): \n" - "\t <8B hex> full UID eg E011223344556677\n" - "\t u unaddressed mode\n" - "\t * scan for tag\n" - "\t page number 0-255\n" - "\t data to be written eg AA BB CC DD"); - return PM3_SUCCESS; -} static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) { @@ -540,85 +527,6 @@ static uint16_t arg_get_raw_flag(uint8_t uidlen, bool unaddressed, bool scan, bo return flags; } -/** - * parses common HF 15 CMD parameters and prepares some data structures - * Parameters: - * **cmd command line - */ -static bool prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t *req, uint8_t iso15cmd) { // reqlen arg0 - - if (*cmd == NULL || strlen(*cmd) == 0) - return false; - - int temp; - uint8_t uid[8] = {0x00}; - uint32_t tmpreqlen = 0; - - // strip - while (**cmd == ' ' || **cmd == '\t')(*cmd)++; - - if (strstr(*cmd, "-2") == *cmd) { - *arg1 = 0; // use 1of256 - (*cmd) += 2; - } - - // strip - while (**cmd == ' ' || **cmd == '\t')(*cmd)++; - - if (strstr(*cmd, "-o") == *cmd) { - req[tmpreqlen] = ISO15_REQ_OPTION; - (*cmd) += 2; - } - - // strip - while (**cmd == ' ' || **cmd == '\t')(*cmd)++; - - char c = tolower(**cmd); - switch (c) { - case 0: - PrintAndLogEx(WARNING, "missing addr"); - return false; - case 'u': - // unaddressed mode may not be supported by all vendors - req[tmpreqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY; - req[tmpreqlen++] = iso15cmd; - break; - case '*': - // we scan for the UID ourself - req[tmpreqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; - req[tmpreqlen++] = iso15cmd; - - if (getUID(false, uid) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "no tag found"); - return false; - } - memcpy(&req[tmpreqlen], uid, sizeof(uid)); - PrintAndLogEx(SUCCESS, "Detected UID " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); - tmpreqlen += sizeof(uid); - break; - default: - req[tmpreqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; - req[tmpreqlen++] = iso15cmd; - // parse UID - for (int i = 0; i < 8 && (*cmd)[i * 2] && (*cmd)[i * 2 + 1]; i++) { - sscanf((char[]) {(*cmd)[i * 2], (*cmd)[i * 2 + 1], 0}, "%X", &temp); - uid[7 - i] = temp & 0xff; - } - - PrintAndLogEx(SUCCESS, "Using UID " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); - memcpy(&req[tmpreqlen], uid, sizeof(uid)); - tmpreqlen += sizeof(uid); - break; - } - // skip to next space - while (**cmd != '\0' && **cmd != ' ' && **cmd != '\t')(*cmd)++; - // skip over the space - while (**cmd != '\0' && (**cmd == ' ' || **cmd == '\t'))(*cmd)++; - - *reqlen = tmpreqlen; - return true; -} - // Mode 3 static int CmdHF15Demod(const char *Cmd) { @@ -1883,54 +1791,83 @@ static int CmdHF15Readblock(const char *Cmd) { * Writes a single Block - might run into timeout, even when successful */ static int CmdHF15Write(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 wrbl", + "Write block on ISO15693 card", + "hf 15 wrbl -* -b 12 -d AABBCCDD\n" + "hf 15 wrbl -u E011223344556677 -b 12 -d AABBCCDD" + ); - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 3 || cmdp == 'h') return usage_15_write(); + void *argtable[6+3] = {}; + uint8_t arglen = arg_add_default(argtable); + argtable[arglen++] = arg_int1("b", "blk", "", "page number (0-255)"); + argtable[arglen++] = arg_str1("d", "data", "", "data, 4 bytes"); + argtable[arglen++] = arg_param_end; + CLIExecWithReturn(ctx, Cmd, argtable, false); - uint8_t req[PM3_CMD_DATA_SIZE] = {0}; - uint16_t reqlen = 0; - uint8_t fast = 1; - uint8_t reply = 1; - int pagenum, temp; + uint8_t uid[8]; + int uidlen = 0; + CLIGetHexWithReturn(ctx, 1, uid, &uidlen); + bool unaddressed = arg_get_lit(ctx, 2); + bool scan = arg_get_lit(ctx, 3); + int fast = (arg_get_lit(ctx, 4) == false); + bool add_option = arg_get_lit(ctx, 5); - char cmdbuf[100] = {0}; - char *cmd = cmdbuf; - char *cmd2; + int block = arg_get_int_def(ctx, 6, 0); + uint8_t d[4]; + int dlen = 0; + CLIGetHexWithReturn(ctx, 7, d, &dlen); - strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); + CLIParserFree(ctx); - if (prepareHF15Cmd(&cmd, &reqlen, &fast, req, ISO15_CMD_WRITE) == false) - return PM3_SUCCESS; - - // *cmd -> page num ; *cmd2 -> data - cmd2 = cmd; - while (*cmd2 != ' ' && *cmd2 != '\t' && *cmd2) cmd2++; - *cmd2 = 0; - cmd2++; - - pagenum = strtol(cmd, NULL, 0); - - req[reqlen++] = (uint8_t)pagenum; - - while (cmd2[0] && cmd2[1]) { // hexdata, read by 2 hexchars - if (*cmd2 == ' ') { - cmd2++; - continue; - } - sscanf((char[]) {cmd2[0], cmd2[1], 0}, "%X", &temp); - req[reqlen++] = temp & 0xff; - cmd2 += 2; + // sanity checks + if ((scan + unaddressed + uidlen) > 1) { + PrintAndLogEx(WARNING, "Select only one option /scan/unaddress/uid"); + return PM3_EINVARG; } + + if (dlen != 4) { + PrintAndLogEx(WARNING, "expected data, 4 bytes, got %d", dlen); + return PM3_EINVARG; + } + + // request to be sent to device/card + uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option); + uint8_t req[PM3_CMD_DATA_SIZE] = {flags, ISO15_CMD_WRITE}; + uint16_t reqlen = 2; + + if (unaddressed == false) { + if (scan) { + if (getUID(false, uid) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "no tag found"); + return PM3_EINVARG; + } + uidlen = 8; + } + + if (uidlen == 8) { + // add UID (scan, uid) + memcpy(req + reqlen, uid, sizeof(uid)); + reqlen += sizeof(uid); + } + PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); + } + + req[reqlen++] = (uint8_t)block; + memcpy(req + reqlen, d, sizeof(d)); + reqlen += sizeof(d); + AddCrc15(req, reqlen); reqlen += 2; - PrintAndLogEx(INFO, "iso15693 writing to page %02d (0x%02X) | data [ %s ] ", pagenum, pagenum, sprint_hex(req, reqlen)); + PrintAndLogEx(INFO, "iso15693 writing to page %02d (0x%02X) | data [ %s ] ", block, block, sprint_hex(req, reqlen)); + uint8_t read_response = 1; PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO15693_COMMAND, reqlen, fast, reply, req, reqlen); + SendCommandMIX(CMD_HF_ISO15693_COMMAND, reqlen, fast, read_response, req, reqlen); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { PrintAndLogEx(FAILED, "iso15693 card timeout, data may be written anyway"); DropField(); return PM3_ETIMEOUT; @@ -1960,7 +1897,7 @@ static int CmdHF15Write(const char *Cmd) { return PM3_EWRONGANSWER; } - PrintAndLogEx(SUCCESS, "Write " _GREEN_("OK")); + PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )"); return PM3_SUCCESS; } diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 051df2e51..a9b58a74a 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -1,4 +1,3 @@ hf 15 dump hf 15 raw hf 15 restore -hf 15 wrbl From 49630f0a7f882d6479d1ce5254c867b85a07ab66 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 12:52:47 +0200 Subject: [PATCH 266/373] hf 15 dump - now uses cliparser --- client/src/cmdhf15.c | 177 ++++++++++++++++++++++++----------------- doc/cliparser_todo.txt | 1 - doc/commands.md | 24 +++--- 3 files changed, 114 insertions(+), 88 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 9288b3141..14af6bdab 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -211,19 +211,6 @@ const productName_t uidmapping[] = { static int CmdHF15Help(const char *Cmd); -static int usage_15_dump(void) { - PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-15693 tag and save it to file\n" - "\n" - "Usage: hf 15 dump [h] \n" - "Options:\n" - "\th this help\n" - "\tf filename, if no UID will be used as filename\n" - "\n" - "Example:\n" - _YELLOW_("\thf 15 dump f\n") - _YELLOW_("\thf 15 dump f mydump")); - return PM3_SUCCESS; -} static int usage_15_restore(void) { const char *options[][2] = { {"h", "this help"}, @@ -532,7 +519,7 @@ static int CmdHF15Demod(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf 15 demod", - "Tries to demodulate / decode ISO15693, from downloaded samples.\n" + "Tries to demodulate / decode ISO-15693, from downloaded samples.\n" "Gather samples with 'hf 15 samples' / 'hf 15 sniff'", "hf 15 demod\n"); @@ -1000,7 +987,7 @@ static int CmdHF15Sniff(const char *Cmd) { static int CmdHF15Reader(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf 15 reader", - "Act as a ISO15693 reader. Look for ISO15693 tags until Enter or the pm3 button is pressed\n", + "Act as a ISO-15693 reader. Look for ISO-15693 tags until Enter or the pm3 button is pressed\n", "hf 15 reader\n" "hf 15 reader -@ -> Continuous mode"); @@ -1026,7 +1013,7 @@ static int CmdHF15Sim(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf 15 sim", - "Simulate a ISO15693 tag\n", + "Simulate a ISO-15693 tag\n", "hf 15 sim -u E011223344556677"); void *argtable[] = { @@ -1065,7 +1052,7 @@ static int CmdHF15Sim(const char *Cmd) { static int CmdHF15FindAfi(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf 15 findafi", - "This command attempts to brute force AFI of an ISO15693 tag\n" + "This command attempts to brute force AFI of an ISO-15693 tag\n" "Estimated execution time is around 2 minutes", "hf 15 findafi"); @@ -1311,71 +1298,92 @@ static int CmdHF15WriteDsfid(const char *Cmd) { // Reads all memory pages // need to write to file static int CmdHF15Dump(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 dump", + "This command dumps the contents of a ISO-15693 tag and save it to file", + "hf 15 dump\n" + "hf 15 dump -*\n" + "hf 15 dump -u E011223344556677 -f hf-15-my-dump.bin" + ); - uint8_t fileNameLen = 0; + void *argtable[6+2] = {}; + uint8_t arglen = arg_add_default(argtable); + argtable[arglen++] = arg_str0("f", "file", "", "filename of dump"), + argtable[arglen++] = arg_param_end; + + CLIExecWithReturn(ctx, Cmd, argtable, true); + + uint8_t uid[8]; + int uidlen = 0; + CLIGetHexWithReturn(ctx, 1, uid, &uidlen); + bool unaddressed = arg_get_lit(ctx, 2); + bool scan = arg_get_lit(ctx, 3); + int fast = (arg_get_lit(ctx, 4) == false); + bool add_option = arg_get_lit(ctx, 5); + + int fnlen = 0; char filename[FILE_PATH_SIZE] = {0}; - char *fptr = filename; - bool errors = false; - uint8_t cmdp = 0; - uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_15_dump(); - case 'f': - fileNameLen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; - } + CLIParserFree(ctx); + + // sanity checks + if ((scan + unaddressed + uidlen) > 1) { + PrintAndLogEx(WARNING, "Select only one option /scan/unaddress/uid"); + return PM3_EINVARG; } - //Validations - if (errors) return usage_15_dump(); - - if (getUID(false, uid) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "no tag found"); - return PM3_ESOFT; + // default fallback to scan for tag. + // overriding unaddress parameter :) + if (uidlen != 8) { + scan = true; } - if (fileNameLen < 1) { - PrintAndLogEx(INFO, "Using UID as filename"); - fptr += sprintf(fptr, "hf-15-"); - FillFileNameByUID(fptr, SwapEndian64(uid, sizeof(uid), 8), "-dump", sizeof(uid)); + // request to be sent to device/card + uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option); + uint8_t req[13] = {flags, ISO15_CMD_READ}; + uint16_t reqlen = 2; + + if (scan) { + if (getUID(false, uid) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "no tag found"); + return PM3_EINVARG; + } + uidlen = 8; } + + if (uidlen == 8) { + // add UID (scan, uid) + memcpy(req + reqlen, uid, sizeof(uid)); + reqlen += sizeof(uid); + } + PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); + // detect blocksize from card :) PrintAndLogEx(SUCCESS, "Reading memory from tag UID " _YELLOW_("%s"), iso15693_sprintUID(NULL, uid)); int blocknum = 0; - uint8_t *recv = NULL; - // memory. t15memory_t mem[256]; uint8_t data[256 * 4] = {0}; memset(data, 0, sizeof(data)); - PacketResponseNG resp; - uint8_t req[13]; - req[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; - req[1] = ISO15_CMD_READ; - - // copy uid to read command - memcpy(req + 2, uid, sizeof(uid)); - PrintAndLogEx(INFO, "." NOLF); for (int retry = 0; retry < 5; retry++) { req[10] = blocknum; AddCrc15(req, 11); + // arg: len, speed, recv? + // arg0 (datalen, cmd len? .arg0 == crc?) + // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 ) + // arg2 (recv == 1 == expect a response) + uint8_t read_respone = 1; + PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO15693_COMMAND, sizeof(req), 1, 1, req, sizeof(req)); + SendCommandMIX(CMD_HF_ISO15693_COMMAND, sizeof(req), fast, read_respone, req, sizeof(req)); if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { @@ -1389,7 +1397,7 @@ static int CmdHF15Dump(const char *Cmd) { continue; } - recv = resp.data.asBytes; + uint8_t *recv = resp.data.asBytes; if (CheckCrc15(recv, len) == false) { PrintAndLogEx(NORMAL, ""); @@ -1421,10 +1429,30 @@ static int CmdHF15Dump(const char *Cmd) { PrintAndLogEx(INFO, "block# | data |lck| ascii"); PrintAndLogEx(INFO, "---------+--------------+---+----------"); for (int i = 0; i < blocknum; i++) { - PrintAndLogEx(INFO, "%3d/0x%02X | %s | %d | %s", i, i, sprint_hex(mem[i].block, 4), mem[i].lock, sprint_ascii(mem[i].block, 4)); + char lck[16] = {0}; + if (mem[i].lock) { + sprintf(lck, _RED_("%d"), mem[i].lock); + } else { + sprintf(lck, "%d", mem[i].lock); + } + PrintAndLogEx(INFO, "%3d/0x%02X | %s | %s | %s" + , i + , i + , sprint_hex(mem[i].block, 4) + , lck + , sprint_ascii(mem[i].block, 4) + ); } PrintAndLogEx(NORMAL, ""); + // user supplied filename ? + if (strlen(filename) < 1) { + char *fptr = filename; + PrintAndLogEx(INFO, "Using UID as filename"); + fptr += snprintf(fptr, sizeof(filename), "hf-15-"); + FillFileNameByUID(fptr, SwapEndian64(uid, sizeof(uid), 8), "-dump", sizeof(uid)); + } + size_t datalen = blocknum * 4; saveFile(filename, ".bin", data, datalen); saveFileEML(filename, data, datalen, 4); @@ -1536,10 +1564,9 @@ static int CmdHF15Raw(const char *Cmd) { * Read multiple blocks at once (not all tags support this) */ static int CmdHF15Readmulti(const char *Cmd) { - - CLIParserContext *ctx; + CLIParserContext *ctx; CLIParserInit(&ctx, "hf 15 rdmulti", - "Read multiple pages on a ISO15693 card", + "Read multiple pages on a ISO-15693 tag ", "hf 15 rdmulti -* -b 1 --cnt 6 -> read 6 blocks\n" "hf 15 rdmulti -u E011223344556677 -b 12 --cnt 3 -> read three blocks" ); @@ -1675,7 +1702,7 @@ static int CmdHF15Readmulti(const char *Cmd) { static int CmdHF15Readblock(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf 15 rdbl", - "Read page on ISO15693 card", + "Read page on ISO-15693 tag", "hf 15 rdbl -* -b 12\n" "hf 15 rdbl -u E011223344556677 -b 12" ); @@ -1793,7 +1820,7 @@ static int CmdHF15Readblock(const char *Cmd) { static int CmdHF15Write(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf 15 wrbl", - "Write block on ISO15693 card", + "Write block on ISO-15693 tag", "hf 15 wrbl -* -b 12 -d AABBCCDD\n" "hf 15 wrbl -u E011223344556677 -b 12 -d AABBCCDD" ); @@ -2102,25 +2129,25 @@ static int CmdHF15CSetUID(const char *Cmd) { static command_t CommandTable[] = { {"-----------", CmdHF15Help, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, {"help", CmdHF15Help, AlwaysAvailable, "This help"}, - {"list", CmdHF15List, AlwaysAvailable, "List ISO15693 history"}, - {"demod", CmdHF15Demod, AlwaysAvailable, "Demodulate ISO15693 from tag"}, - {"dump", CmdHF15Dump, IfPm3Iso15693, "Read all memory pages of an ISO15693 tag, save to file"}, + {"list", CmdHF15List, AlwaysAvailable, "List ISO-15693 history"}, + {"demod", CmdHF15Demod, AlwaysAvailable, "Demodulate ISO-15693 from tag"}, + {"dump", CmdHF15Dump, IfPm3Iso15693, "Read all memory pages of an ISO-15693 tag, save to file"}, {"info", CmdHF15Info, IfPm3Iso15693, "Tag information"}, - {"sniff", CmdHF15Sniff, IfPm3Iso15693, "Sniff ISO15693 traffic"}, + {"sniff", CmdHF15Sniff, IfPm3Iso15693, "Sniff ISO-15693 traffic"}, {"raw", CmdHF15Raw, IfPm3Iso15693, "Send raw hex data to tag"}, {"rdbl", CmdHF15Readblock, IfPm3Iso15693, "Read a block"}, {"rdmulti", CmdHF15Readmulti, IfPm3Iso15693, "Reads multiple blocks"}, - {"reader", CmdHF15Reader, IfPm3Iso15693, "Act like an ISO15693 reader"}, - {"restore", CmdHF15Restore, IfPm3Iso15693, "Restore from file to all memory pages of an ISO15693 tag"}, - {"samples", CmdHF15Samples, IfPm3Iso15693, "Acquire Samples as Reader (enables carrier, sends inquiry)"}, - {"sim", CmdHF15Sim, IfPm3Iso15693, "Fake an ISO15693 tag"}, + {"reader", CmdHF15Reader, IfPm3Iso15693, "Act like an ISO-15693 reader"}, + {"restore", CmdHF15Restore, IfPm3Iso15693, "Restore from file to all memory pages of an ISO-15693 tag"}, + {"samples", CmdHF15Samples, IfPm3Iso15693, "Acquire samples as reader (enables carrier, sends inquiry)"}, + {"sim", CmdHF15Sim, IfPm3Iso15693, "Fake an ISO-15693 tag"}, {"wrbl", CmdHF15Write, IfPm3Iso15693, "Write a block"}, {"-----------", CmdHF15Help, IfPm3Iso15693, "----------------------- " _CYAN_("afi") " -----------------------"}, - {"findafi", CmdHF15FindAfi, IfPm3Iso15693, "Brute force AFI of an ISO15693 tag"}, - {"writeafi", CmdHF15WriteAfi, IfPm3Iso15693, "Writes the AFI on an ISO15693 tag"}, - {"writedsfid", CmdHF15WriteDsfid, IfPm3Iso15693, "Writes the DSFID on an ISO15693 tag"}, + {"findafi", CmdHF15FindAfi, IfPm3Iso15693, "Brute force AFI of an ISO-15693 tag"}, + {"writeafi", CmdHF15WriteAfi, IfPm3Iso15693, "Writes the AFI on an ISO-15693 tag"}, + {"writedsfid", CmdHF15WriteDsfid, IfPm3Iso15693, "Writes the DSFID on an ISO-15693 tag"}, {"-----------", CmdHF15Help, IfPm3Iso15693, "----------------------- " _CYAN_("magic") " -----------------------"}, - {"csetuid", CmdHF15CSetUID, IfPm3Iso15693, "Set UID for magic Chinese card"}, + {"csetuid", CmdHF15CSetUID, IfPm3Iso15693, "Set UID for magic card"}, {NULL, NULL, NULL, NULL} }; diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index a9b58a74a..7d39047c4 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -1,3 +1,2 @@ -hf 15 dump hf 15 raw hf 15 restore diff --git a/doc/commands.md b/doc/commands.md index 9f25525a4..f4fb8c813 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -212,23 +212,23 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`hf 15 help `|Y |`This help` -|`hf 15 list `|Y |`List ISO15693 history` -|`hf 15 demod `|Y |`Demodulate ISO15693 from tag` -|`hf 15 dump `|N |`Read all memory pages of an ISO15693 tag, save to file` +|`hf 15 list `|Y |`List ISO-15693 history` +|`hf 15 demod `|Y |`Demodulate ISO-15693 from tag` +|`hf 15 dump `|N |`Read all memory pages of an ISO-15693 tag, save to file` |`hf 15 info `|N |`Tag information` -|`hf 15 sniff `|N |`Sniff ISO15693 traffic` +|`hf 15 sniff `|N |`Sniff ISO-15693 traffic` |`hf 15 raw `|N |`Send raw hex data to tag` |`hf 15 rdbl `|N |`Read a block` |`hf 15 rdmulti `|N |`Reads multiple blocks` -|`hf 15 reader `|N |`Act like an ISO15693 reader` -|`hf 15 restore `|N |`Restore from file to all memory pages of an ISO15693 tag` -|`hf 15 samples `|N |`Acquire Samples as Reader (enables carrier, sends inquiry)` -|`hf 15 sim `|N |`Fake an ISO15693 tag` +|`hf 15 reader `|N |`Act like an ISO-15693 reader` +|`hf 15 restore `|N |`Restore from file to all memory pages of an ISO-15693 tag` +|`hf 15 samples `|N |`Acquire samples as reader (enables carrier, sends inquiry)` +|`hf 15 sim `|N |`Fake an ISO-15693 tag` |`hf 15 wrbl `|N |`Write a block` -|`hf 15 findafi `|N |`Brute force AFI of an ISO15693 tag` -|`hf 15 writeafi `|N |`Writes the AFI on an ISO15693 tag` -|`hf 15 writedsfid `|N |`Writes the DSFID on an ISO15693 tag` -|`hf 15 csetuid `|N |`Set UID for magic Chinese card` +|`hf 15 findafi `|N |`Brute force AFI of an ISO-15693 tag` +|`hf 15 writeafi `|N |`Writes the AFI on an ISO-15693 tag` +|`hf 15 writedsfid `|N |`Writes the DSFID on an ISO-15693 tag` +|`hf 15 csetuid `|N |`Set UID for magic card` ### hf epa From 966875ce6f7cc1db301fa30edeef2446da4fe6c9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Apr 2021 18:05:08 +0300 Subject: [PATCH 267/373] add tokenization tags for apple/google pay --- client/src/emv/emv_tags.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/emv/emv_tags.c b/client/src/emv/emv_tags.c index 6499bcd8e..5bdecc665 100644 --- a/client/src/emv/emv_tags.c +++ b/client/src/emv/emv_tags.c @@ -261,6 +261,7 @@ static const struct emv_tag emv_tags[] = { { 0x9f16, "Merchant Identifier", EMV_TAG_STRING, NULL }, { 0x9f17, "Personal Identification Number (PIN) Try Counter", EMV_TAG_GENERIC, NULL }, { 0x9f18, "Issuer Script Identifier", EMV_TAG_GENERIC, NULL }, + { 0x9f19, "Token Requestor ID", EMV_TAG_GENERIC, NULL }, { 0x9f1a, "Terminal Country Code", EMV_TAG_GENERIC, NULL }, { 0x9f1b, "Terminal Floor Limit", EMV_TAG_GENERIC, NULL }, { 0x9f1c, "Terminal Identification", EMV_TAG_STRING, NULL }, @@ -272,6 +273,7 @@ static const struct emv_tag emv_tags[] = { { 0x9f22, "Certification Authority Public Key Index - Terminal", EMV_TAG_GENERIC, NULL }, { 0x9f23, "Upper Consecutive Offline Limit", EMV_TAG_GENERIC, NULL }, { 0x9f24, "Payment Account Reference (PAR)", EMV_TAG_GENERIC, NULL }, + { 0x9f25, "Last 4 Digits of PAN", EMV_TAG_GENERIC, NULL }, { 0x9f26, "Application Cryptogram", EMV_TAG_GENERIC, NULL }, { 0x9f27, "Cryptogram Information Data", EMV_TAG_CID, NULL }, { 0x9f2a, "Kernel Identifier", EMV_TAG_GENERIC, NULL }, From 7a04b06f52e47e56bccf8a2713c802d410c7e093 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 17:37:35 +0200 Subject: [PATCH 268/373] hf 15 restore - now uses cliparser --- client/src/cmdhf15.c | 274 ++++++++++++++++++++++------------------- doc/cliparser_todo.txt | 1 - 2 files changed, 148 insertions(+), 127 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 14af6bdab..f69542ea3 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -210,21 +210,6 @@ const productName_t uidmapping[] = { }; static int CmdHF15Help(const char *Cmd); - -static int usage_15_restore(void) { - const char *options[][2] = { - {"h", "this help"}, - {"-2", "use slower '1 out of 256' mode"}, - {"-o", "set OPTION Flag (needed for TI)"}, - {"a", "use addressed mode"}, - {"r ", "numbers of retries on error, default is 3"}, - {"f ", "load "}, - {"b ", "block size, default is 4"} - }; - PrintAndLogEx(NORMAL, "Usage: hf 15 restore [-2] [-o] [h] [r ] [u ] [f ] [b ]"); - PrintAndLogOptions(options, 7, 3); - return PM3_SUCCESS; -} static int usage_15_raw(void) { const char *options[][2] = { {"-r", "do not read response" }, @@ -1133,7 +1118,7 @@ static int CmdHF15WriteAfi(const char *Cmd) { // request to be sent to device/card uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option); - uint8_t req[PM3_CMD_DATA_SIZE] = {flags, ISO15_CMD_WRITEAFI}; + uint8_t req[16] = {flags, ISO15_CMD_WRITEAFI}; uint16_t reqlen = 2; if (unaddressed == false) { @@ -1230,7 +1215,9 @@ static int CmdHF15WriteDsfid(const char *Cmd) { // request to be sent to device/card uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option); - uint8_t req[PM3_CMD_DATA_SIZE] = {flags, ISO15_CMD_WRITEDSFID}; + uint8_t req[16] = {flags, ISO15_CMD_WRITEDSFID}; + // enforce, since we are writing + req[0] |= ISO15_REQ_OPTION; uint16_t reqlen = 2; if (unaddressed == false) { @@ -1250,9 +1237,6 @@ static int CmdHF15WriteDsfid(const char *Cmd) { PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); } - // enforce, since we are writing - req[0] |= ISO15_REQ_OPTION; - // dsfid req[reqlen++] = (uint8_t)dsfid; @@ -1813,6 +1797,48 @@ static int CmdHF15Readblock(const char *Cmd) { return PM3_SUCCESS; } +static int hf_15_write_blk(bool verbose, bool fast, uint8_t *req, uint8_t reqlen) { + + uint8_t read_response = 1; + clearCommandBuffer(); + SendCommandMIX(CMD_HF_ISO15693_COMMAND, reqlen, fast, read_response, req, reqlen); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { + PrintAndLogEx(FAILED, "iso15693 card timeout, data may be written anyway"); + DropField(); + return PM3_ETIMEOUT; + } + + DropField(); + int status = resp.oldarg[0]; + if (status == PM3_ETEAROFF) { + return status; + } + + if (status < 2) { + if (verbose) { + PrintAndLogEx(FAILED, "iso15693 command failed"); + } + return PM3_EWRONGANSWER; + } + + uint8_t *recv = resp.data.asBytes; + if (CheckCrc15(recv, status) == false) { + if (verbose) { + PrintAndLogEx(FAILED, "crc (" _RED_("fail") ")"); + } + return PM3_ESOFT; + } + + if ((recv[0] & ISO15_RES_ERROR) == ISO15_RES_ERROR) { + if (verbose) { + PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + } + return PM3_EWRONGANSWER; + } + return PM3_SUCCESS; +} + /** * Commandline handling: HF15 CMD WRITE * Writes a single Block - might run into timeout, even when successful @@ -1825,10 +1851,11 @@ static int CmdHF15Write(const char *Cmd) { "hf 15 wrbl -u E011223344556677 -b 12 -d AABBCCDD" ); - void *argtable[6+3] = {}; + void *argtable[6+4] = {}; uint8_t arglen = arg_add_default(argtable); argtable[arglen++] = arg_int1("b", "blk", "", "page number (0-255)"); argtable[arglen++] = arg_str1("d", "data", "", "data, 4 bytes"); + argtable[arglen++] = arg_lit0("v", "verbose", "verbose output"); argtable[arglen++] = arg_param_end; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -1845,6 +1872,7 @@ static int CmdHF15Write(const char *Cmd) { int dlen = 0; CLIGetHexWithReturn(ctx, 7, d, &dlen); + bool verbose = arg_get_lit(ctx, 8); CLIParserFree(ctx); // sanity checks @@ -1858,9 +1886,18 @@ static int CmdHF15Write(const char *Cmd) { return PM3_EINVARG; } + // default fallback to scan for tag. + // overriding unaddress parameter :) + if (uidlen != 8) { + scan = true; + } + // request to be sent to device/card uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option); - uint8_t req[PM3_CMD_DATA_SIZE] = {flags, ISO15_CMD_WRITE}; + uint8_t req[17] = {flags, ISO15_CMD_WRITE}; + + // enforce, since we are writing + req[0] |= ISO15_REQ_OPTION; uint16_t reqlen = 2; if (unaddressed == false) { @@ -1880,6 +1917,7 @@ static int CmdHF15Write(const char *Cmd) { PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); } + req[reqlen++] = (uint8_t)block; memcpy(req + reqlen, d, sizeof(d)); reqlen += sizeof(d); @@ -1889,106 +1927,92 @@ static int CmdHF15Write(const char *Cmd) { PrintAndLogEx(INFO, "iso15693 writing to page %02d (0x%02X) | data [ %s ] ", block, block, sprint_hex(req, reqlen)); - uint8_t read_response = 1; - PacketResponseNG resp; - clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO15693_COMMAND, reqlen, fast, read_response, req, reqlen); + int res = hf_15_write_blk(verbose, fast, req, reqlen); + if (res == PM3_SUCCESS) + PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )"); + else + PrintAndLogEx(FAILED, "Write ( " _RED_("fail") " )"); - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { - PrintAndLogEx(FAILED, "iso15693 card timeout, data may be written anyway"); - DropField(); - return PM3_ETIMEOUT; - } - - DropField(); - - int status = resp.oldarg[0]; - if (status == PM3_ETEAROFF) { - return status; - } - - if (status < 2) { - PrintAndLogEx(FAILED, "iso15693 command failed"); - return PM3_EWRONGANSWER; - } - - uint8_t *data = resp.data.asBytes; - - if (CheckCrc15(data, status) == false) { - PrintAndLogEx(FAILED, "crc (" _RED_("fail") ")"); - return PM3_ESOFT; - } - - if ((data[0] & ISO15_RES_ERROR) == ISO15_RES_ERROR) { - PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", data[0], TagErrorStr(data[0])); - return PM3_EWRONGANSWER; - } - - PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )"); return PM3_SUCCESS; } static int CmdHF15Restore(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 restore", + "This command restore the contents of a dump file onto a ISO-15693 tag", + "hf 15 restore\n" + "hf 15 restore -*\n" + "hf 15 restore -u E011223344556677 -f hf-15-my-dump.bin" + ); - char newPrefix[60] = {0x00}; - char filename[FILE_PATH_SIZE] = {0x00}; - size_t blocksize = 4; - uint8_t cmdp = 0, retries = 3; - bool addressed_mode = false; + void *argtable[6+5] = {}; + uint8_t arglen = arg_add_default(argtable); + argtable[arglen++] = arg_str0("f", "file", "", "filename of dump"), + argtable[arglen++] = arg_int0("r", "retry", "", "number of retries (def 3)"), + argtable[arglen++] = arg_int0(NULL, "bs", "", "block size (def 4)"), + argtable[arglen++] = arg_lit0("v", "verbose", "verbose output"); + argtable[arglen++] = arg_param_end; + CLIExecWithReturn(ctx, Cmd, argtable, true); - while (param_getchar(Cmd, cmdp) != 0x00) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case '-': { - char param[3] = ""; - param_getstr(Cmd, cmdp, param, sizeof(param)); - switch (param[1]) { - case '2': - case 'o': - sprintf(newPrefix, " %s", param); - break; - default: - PrintAndLogEx(WARNING, "11 unknown parameter " _YELLOW_("'%s'"), param); - return usage_15_restore(); - } - break; - } - case 'f': - param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); - cmdp++; - break; - case 'r': - retries = param_get8ex(Cmd, cmdp + 1, 3, 10); - cmdp++; - break; - case 'b': - blocksize = param_get8ex(Cmd, cmdp + 1, 4, 10); - cmdp++; - break; - case 'a': - addressed_mode = true; - break; - case 'h': - return usage_15_restore(); - default: - PrintAndLogEx(WARNING, "unknown parameter " _YELLOW_("'%c'"), param_getchar(Cmd, cmdp)); - return usage_15_restore(); - } - cmdp++; + uint8_t uid[8]; + int uidlen = 0; + CLIGetHexWithReturn(ctx, 1, uid, &uidlen); + bool unaddressed = arg_get_lit(ctx, 2); + bool scan = arg_get_lit(ctx, 3); + int fast = (arg_get_lit(ctx, 4) == false); + bool add_option = arg_get_lit(ctx, 5); + + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); + int retries = arg_get_int_def(ctx, 7, 3); + int blocksize = arg_get_int_def(ctx, 8, 4); + bool verbose = arg_get_lit(ctx, 9); + CLIParserFree(ctx); + + // sanity checks + if ((scan + unaddressed + uidlen) > 1) { + PrintAndLogEx(WARNING, "Select only one option /scan/unaddress/uid"); + return PM3_EINVARG; } - - PrintAndLogEx(INFO, "blocksize: %zu", blocksize); - - if (!strlen(filename)) { + if (fnlen == 0) { PrintAndLogEx(WARNING, "please provide a filename"); - return usage_15_restore(); + return PM3_EINVARG; } - uint8_t uid[8] = {0x00}; - if (getUID(false, uid) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "no tag found"); - return PM3_ESOFT; + // default fallback to scan for tag. + // overriding unaddress parameter :) + if (uidlen != 8) { + scan = true; } + // request to be sent to device/card + uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option); + uint8_t req[17] = {flags, ISO15_CMD_WRITE}; + // enforce, since we are writing + req[0] |= ISO15_REQ_OPTION; + uint16_t reqlen = 2; + + if (unaddressed == false) { + if (scan) { + if (getUID(false, uid) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "no tag found"); + return PM3_EINVARG; + } + uidlen = 8; + } + + if (uidlen == 8) { + // add UID (scan, uid) + memcpy(req + reqlen, uid, sizeof(uid)); + reqlen += sizeof(uid); + } + PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); + } else { + PrintAndLogEx(SUCCESS, "Using unaddressed mode"); + } + PrintAndLogEx(INFO, "Using block size... %zu", blocksize); + size_t datalen = 0; uint8_t *data = NULL; if (loadFile_safe(filename, ".bin", (void **)&data, &datalen) != PM3_SUCCESS) { @@ -2003,37 +2027,33 @@ static int CmdHF15Restore(const char *Cmd) { } PrintAndLogEx(INFO, "restoring data blocks"); + PrintAndLogEx(INFO, "." NOLF); + fflush(stdout); int retval = PM3_SUCCESS; size_t bytes = 0; uint16_t i = 0; while (bytes < datalen) { + req[reqlen + 1] = i; + // copy over the data to the request + memcpy(req + reqlen + 1, data + bytes, blocksize); + AddCrc15(req, reqlen + 1 + blocksize); + uint8_t tried = 0; - char hex[40] = {0x00}; - char tmpCmd[200] = {0x00}; - - if (addressed_mode) { - char uidhex[17] = {0x00}; - hex_to_buffer((uint8_t *)uidhex, uid, sizeof(uid), sizeof(uidhex) - 1, 0, false, true); - hex_to_buffer((uint8_t *)hex, data + bytes, blocksize, sizeof(hex) - 1, 0, false, true); - snprintf(tmpCmd, sizeof(tmpCmd), "%s %s %u %s", newPrefix, uidhex, i, hex); - } else { - hex_to_buffer((uint8_t *)hex, data + bytes, blocksize, sizeof(hex) - 1, 0, false, true); - snprintf(tmpCmd, sizeof(tmpCmd), "%s u %u %s", newPrefix, i, hex); - } - - PrintAndLogEx(DEBUG, "hf 15 write %s", tmpCmd); - for (tried = 0; tried < retries; tried++) { - retval = CmdHF15Write(tmpCmd); - if (retval == false) { + + retval = hf_15_write_blk(verbose, fast, req, (reqlen + 1 + blocksize + 2)); + if (retval == PM3_SUCCESS) { + PrintAndLogEx(NORMAL, "." NOLF); + fflush(stdout); break; } } if (tried >= retries) { free(data); + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(FAILED, "restore failed. Too many retries."); return retval; } @@ -2041,6 +2061,8 @@ static int CmdHF15Restore(const char *Cmd) { i++; } free(data); + + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "done"); PrintAndLogEx(HINT, "try `" _YELLOW_("hf 15 dump") "` to read your card to verify"); return PM3_SUCCESS; diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt index 7d39047c4..18ff88d0d 100644 --- a/doc/cliparser_todo.txt +++ b/doc/cliparser_todo.txt @@ -1,2 +1 @@ hf 15 raw -hf 15 restore From f5147cb5cf44e024693f656d8d37b5c2eee53af7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 18:11:22 +0200 Subject: [PATCH 269/373] hf 15 raw - now uses cliparser --- client/src/cmdhf15.c | 107 +++++++++++++++-------------------------- doc/cliparser_todo.txt | 1 - 2 files changed, 38 insertions(+), 70 deletions(-) delete mode 100644 doc/cliparser_todo.txt diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index f69542ea3..e7be38aa1 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -210,18 +210,6 @@ const productName_t uidmapping[] = { }; static int CmdHF15Help(const char *Cmd); -static int usage_15_raw(void) { - const char *options[][2] = { - {"-r", "do not read response" }, - {"-2", "use slower '1 out of 256' mode" }, - {"-c", "calculate and append CRC" }, - {"-k", "keep signal field ON after receive" }, - {"", "Tip: turn on debugging for verbose output"}, - }; - PrintAndLogEx(NORMAL, "Usage: hf 15 raw [-r] [-2] [-k] [-c] <0A 0B 0C ... hex>\n"); - PrintAndLogOptions(options, 4, 3); - return PM3_SUCCESS; -} static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) { @@ -1455,71 +1443,46 @@ static int CmdHF15List(const char *Cmd) { } static int CmdHF15Raw(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 raw", + "Sends raw bytes over ISO-15693 to card", + "hf 15 raw -c -d 260100 --> add crc\n" + "hf 15 raw -krc -d 260100 --> add crc, keep field on, skip response" + ); - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 3 || cmdp == 'h') return usage_15_raw(); - - int reply = 1, fast = 1, i = 0; - bool crc = false, keep_field_on = false; - char buf[5] = ""; - uint8_t data[100]; - uint32_t datalen = 0, temp; - - // strip - while (*Cmd == ' ' || *Cmd == '\t') Cmd++; - - while (Cmd[i] != '\0') { - if (Cmd[i] == ' ' || Cmd[i] == '\t') { i++; continue; } - if (Cmd[i] == '-') { - switch (tolower(Cmd[i + 1])) { - case 'r': - reply = 0; - break; - case '2': - fast = 0; - break; - case 'c': - crc = true; - break; - case 'k': - keep_field_on = true; - break; - default: - PrintAndLogEx(WARNING, "Invalid option"); - return PM3_EINVARG; - } - i += 2; - continue; - } - if ((Cmd[i] >= '0' && Cmd[i] <= '9') || - (Cmd[i] >= 'a' && Cmd[i] <= 'f') || - (Cmd[i] >= 'A' && Cmd[i] <= 'F')) { - buf[strlen(buf) + 1] = 0; - buf[strlen(buf)] = Cmd[i]; - i++; - - if (strlen(buf) >= 2) { - sscanf(buf, "%x", &temp); - data[datalen] = (uint8_t)(temp & 0xff); - datalen++; - *buf = 0; - } - continue; - } - PrintAndLogEx(WARNING, "Invalid char on input"); - return PM3_EINVARG; - } + void *argtable[] = { + arg_param_begin, + arg_lit0("2", NULL, "use slower '1 out of 256' mode"), + arg_lit0("c", "crc", "calculate and append CRC"), + arg_lit0("k", NULL, "keep signal field ON after receive"), + arg_lit0("r", NULL, "do not read response"), + arg_strx1("d", "data", "", "raw bytes to send"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + int fast = (arg_get_lit(ctx, 1) == false); + bool crc = arg_get_lit(ctx, 2); + bool keep_field_on = arg_get_lit(ctx, 3); + bool read_respone = (arg_get_lit(ctx, 4) == false); + int datalen = 0; + uint8_t data[300]; + CLIGetHexWithReturn(ctx, 5, data, &datalen); + CLIParserFree(ctx); if (crc) { AddCrc15(data, datalen); datalen += 2; } + // arg: len, speed, recv? + // arg0 (datalen, cmd len? .arg0 == crc?) + // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 ) + // arg2 (recv == 1 == expect a response) PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO15693_COMMAND, datalen, fast, reply, data, datalen); + SendCommandMIX(CMD_HF_ISO15693_COMMAND, datalen, fast, read_respone, data, datalen); - if (reply) { + if (read_respone) { if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { int len = resp.oldarg[0]; if (len == PM3_ETEAROFF) { @@ -1537,9 +1500,9 @@ static int CmdHF15Raw(const char *Cmd) { } } - if (keep_field_on == false) + if (keep_field_on == false) { DropField(); - + } return PM3_SUCCESS; } @@ -1715,6 +1678,12 @@ static int CmdHF15Readblock(const char *Cmd) { return PM3_EINVARG; } + // default fallback to scan for tag. + // overriding unaddress parameter :) + if (uidlen != 8) { + scan = true; + } + // request to be sent to device/card uint16_t flags = arg_get_raw_flag(uidlen, unaddressed, scan, add_option); uint8_t req[PM3_CMD_DATA_SIZE] = {flags, ISO15_CMD_READ}; diff --git a/doc/cliparser_todo.txt b/doc/cliparser_todo.txt deleted file mode 100644 index 18ff88d0d..000000000 --- a/doc/cliparser_todo.txt +++ /dev/null @@ -1 +0,0 @@ -hf 15 raw From 8587b93e0d7fdb4f5e329762c2d5a95696ca7236 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 18:11:44 +0200 Subject: [PATCH 270/373] text --- client/src/cmdhf14a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index c6283e794..e382a5714 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -1198,7 +1198,7 @@ static int CmdHF14ACmdRaw(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf 14a raw", - "Sends an raw bytes over ISO14443a. With option to use TOPAZ 14a mode.", + "Sends raw bytes over ISO14443a. With option to use TOPAZ 14a mode.", "hf 14a raw -sc 3000 -> select, crc, where 3000 == 'read block 00'\n" "hf 14a raw -ak -b 7 40 -> send 7 bit byte 0x40\n" ); From 097d24347f9eb5dfda67f54cf651e6d36da4889c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 18:13:33 +0200 Subject: [PATCH 271/373] remove unused command in Makefile --- Makefile | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Makefile b/Makefile index b2dcba430..77b7b9741 100644 --- a/Makefile +++ b/Makefile @@ -249,14 +249,6 @@ endif # easy printing of MAKE VARIABLES print-%: ; @echo $* = $($*) -cliparser: - # Get list of all commands - cat doc/commands.md | grep -e ^\|\` | cut -f 2 -d "\`" | grep -v 'help\|list\|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 - grep -xvf cliparser_done.tmp cliparser_all_commands.tmp > ./doc/cliparser_todo.txt - style: # Make sure astyle is installed @which astyle >/dev/null || ( echo "Please install 'astyle' package first" ; exit 1 ) From 46bf5297633d0b3964db75cf161c65a8b64f64ba Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 18:27:24 +0200 Subject: [PATCH 272/373] change 'hf 15 restore' now supports EML/JSON --- CHANGELOG.md | 2 ++ client/src/cmdhf15.c | 34 +++++++++++++++++++++++++++++++--- client/src/fileutils.c | 4 ++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b51667f04..5c9b851a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Change `hf 15 restore` - now also support EML/JSON (@iceman1001) + - Change - all commands now use cliparser (@iceman1001) - Change `lf t55xx restore` - now also support JSON (@iceman1001) - Change `hf mf csetuid` - adapted to accept 7byte uids. ~untested~ (@iceman1001) - Added `hf mf view/eload/cload` - now accepts bin/eml/json (@iceman1001) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index e7be38aa1..9b1f9be52 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1982,10 +1982,38 @@ static int CmdHF15Restore(const char *Cmd) { } PrintAndLogEx(INFO, "Using block size... %zu", blocksize); + // 4bytes * 256 blocks. Should be enough.. + uint8_t *data = calloc(4 * 256, sizeof(uint8_t)); + if (data == NULL) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); + return PM3_EMALLOC; + } + size_t datalen = 0; - uint8_t *data = NULL; - if (loadFile_safe(filename, ".bin", (void **)&data, &datalen) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "could not find file " _YELLOW_("%s"), filename); + int res = PM3_SUCCESS; + DumpFileType_t dftype = getfiletype(filename); + switch (dftype) { + case BIN: { + res = loadFile_safe(filename, ".bin", (void **)&data, &datalen); + break; + } + case EML: { + res = loadFileEML_safe(filename, (void **)&data, &datalen); + break; + } + case JSON: { + res = loadFileJSON(filename, data, 256 * 4, &datalen, NULL); + break; + } + case DICTIONARY: { + PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); + free(data); + return PM3_EINVARG; + } + } + + if (res != PM3_SUCCESS) { + free(data); return PM3_EFILE; } diff --git a/client/src/fileutils.c b/client/src/fileutils.c index 24538497e..45185ea71 100644 --- a/client/src/fileutils.c +++ b/client/src/fileutils.c @@ -1210,6 +1210,10 @@ int loadFileJSONex(const char *preferredName, void *data, size_t maxdatalen, siz *datalen = sptr; } + if (!strcmp(ctype, "15693")) { + JsonLoadBufAsHex(root, "$.raw", udata, maxdatalen, datalen); + } + out: if (callback != NULL) { From e1a7b61b1ffd5339d79761ad9b9670e37c076219 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Apr 2021 19:51:24 +0300 Subject: [PATCH 273/373] show some general crypto description --- client/src/emv/cmdemv.c | 21 +++++++++++++++++++-- client/src/emv/emv_tags.c | 14 +++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/client/src/emv/cmdemv.c b/client/src/emv/cmdemv.c index 83f268f57..fd02528a6 100644 --- a/client/src/emv/cmdemv.c +++ b/client/src/emv/cmdemv.c @@ -1076,13 +1076,30 @@ static int CmdEMVExec(const char *Cmd) { PrintAndLogEx(NORMAL, "AC: %s", sprint_hex(AC->value, AC->len)); if (IAD) { PrintAndLogEx(NORMAL, "IAD: %s", sprint_hex(IAD->value, IAD->len)); - - if (IAD->len >= IAD->value[0] + 1) { + + // https://mst-company.ru/blog/ekvajring-emv-tranzaktsiya-emv-transaction-flow-chast-4-pdol-i-beskontaktnye-karty-osobennosti-qvsdc-i-quics + if (IAD->value[0] == 0x1f) { + PrintAndLogEx(NORMAL, "\tKey index: 0x%02x", IAD->value[2]); + PrintAndLogEx(NORMAL, "\tCrypto ver: 0x%02x(%03d)", IAD->value[1], IAD->value[1]); + PrintAndLogEx(NORMAL, "\tCVR: %s", sprint_hex(&IAD->value[3], 5)); + struct tlvdb *cvr = tlvdb_fixed(0x20, 5, &IAD->value[3]); + TLVPrintFromTLVLev(cvr, 1); + PrintAndLogEx(NORMAL, "\tIDD option id: 0x%02x", IAD->value[8]); + PrintAndLogEx(NORMAL, "\tIDD: %s", sprint_hex(&IAD->value[9], 23)); + } else if (IAD->len >= IAD->value[0] + 1) { PrintAndLogEx(NORMAL, "\tKey index: 0x%02x", IAD->value[1]); PrintAndLogEx(NORMAL, "\tCrypto ver: 0x%02x(%03d)", IAD->value[2], IAD->value[2]); PrintAndLogEx(NORMAL, "\tCVR: %s", sprint_hex(&IAD->value[3], IAD->value[0] - 2)); struct tlvdb *cvr = tlvdb_fixed(0x20, IAD->value[0] - 2, &IAD->value[3]); TLVPrintFromTLVLev(cvr, 1); + if (IAD->len >= 8) { + int iddLen = IAD->value[7]; + PrintAndLogEx(NORMAL, "\tIDD length: %d", iddLen); + if (iddLen >= 1) + PrintAndLogEx(NORMAL, "\tIDD option id: 0x%02x", IAD->value[8]); + if (iddLen >= 2) + PrintAndLogEx(NORMAL, "\tIDD: %s", sprint_hex(&IAD->value[9], iddLen - 1)); + } } } else { PrintAndLogEx(WARNING, "WARNING: IAD not found."); diff --git a/client/src/emv/emv_tags.c b/client/src/emv/emv_tags.c index 5bdecc665..acafa18d3 100644 --- a/client/src/emv/emv_tags.c +++ b/client/src/emv/emv_tags.c @@ -557,7 +557,7 @@ static void emv_tag_dump_cvr(const struct tlv *tlv, const struct emv_tag *tag, i return; } - if (tlv->len != tlv->value[0] + 1) { + if (tlv->len != 5 && tlv->len != tlv->value[0] + 1) { PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); PrintAndLogEx(NORMAL, " INVALID length!"); return; @@ -581,6 +581,14 @@ static void emv_tag_dump_cvr(const struct tlv *tlv, const struct emv_tag *tag, i PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); PrintAndLogEx(NORMAL, " PIN try: %x", tlv->value[2] >> 4); } + if (tlv->len >= 3 && (tlv->value[2] & 0x40)) { + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " PIN try exceeded"); + } + if (tlv->len >= 4 && (tlv->value[3] >> 4)) { + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " Issuer script counter: %x", tlv->value[3] >> 4); + } if (tlv->len >= 4 && (tlv->value[3] & 0x0F)) { PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); PrintAndLogEx(NORMAL, " Issuer discretionary bits: %x", tlv->value[3] & 0x0F); @@ -589,6 +597,10 @@ static void emv_tag_dump_cvr(const struct tlv *tlv, const struct emv_tag *tag, i PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); PrintAndLogEx(NORMAL, " Successfully processed issuer script commands: %x", tlv->value[4] >> 4); } + if (tlv->len >= 5 && (tlv->value[4] & 0x02)) { + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " CDCVM OK"); + } // mask 0F 0F F0 0F uint8_t data[20] = {0}; From f4f602324dbe9697eac6a41206cbbe186435e644 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Apr 2021 19:53:52 +0300 Subject: [PATCH 274/373] add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c9b851a2..ef3269c33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Change emv commands now works with tokenized cards (@merlokk) - Change `hf 15 restore` - now also support EML/JSON (@iceman1001) - Change - all commands now use cliparser (@iceman1001) - Change `lf t55xx restore` - now also support JSON (@iceman1001) From b627934fb42871c1e7aa9265e169af2c6a02f6d6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Apr 2021 19:56:20 +0300 Subject: [PATCH 275/373] fix tabs --- client/src/emv/cmdemv.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/client/src/emv/cmdemv.c b/client/src/emv/cmdemv.c index fd02528a6..9a1c4aa76 100644 --- a/client/src/emv/cmdemv.c +++ b/client/src/emv/cmdemv.c @@ -1079,26 +1079,26 @@ static int CmdEMVExec(const char *Cmd) { // https://mst-company.ru/blog/ekvajring-emv-tranzaktsiya-emv-transaction-flow-chast-4-pdol-i-beskontaktnye-karty-osobennosti-qvsdc-i-quics if (IAD->value[0] == 0x1f) { - PrintAndLogEx(NORMAL, "\tKey index: 0x%02x", IAD->value[2]); - PrintAndLogEx(NORMAL, "\tCrypto ver: 0x%02x(%03d)", IAD->value[1], IAD->value[1]); - PrintAndLogEx(NORMAL, "\tCVR: %s", sprint_hex(&IAD->value[3], 5)); + PrintAndLogEx(NORMAL, " Key index: 0x%02x", IAD->value[2]); + PrintAndLogEx(NORMAL, " Crypto ver: 0x%02x(%03d)", IAD->value[1], IAD->value[1]); + PrintAndLogEx(NORMAL, " CVR: %s", sprint_hex(&IAD->value[3], 5)); struct tlvdb *cvr = tlvdb_fixed(0x20, 5, &IAD->value[3]); TLVPrintFromTLVLev(cvr, 1); - PrintAndLogEx(NORMAL, "\tIDD option id: 0x%02x", IAD->value[8]); - PrintAndLogEx(NORMAL, "\tIDD: %s", sprint_hex(&IAD->value[9], 23)); + PrintAndLogEx(NORMAL, " IDD option id: 0x%02x", IAD->value[8]); + PrintAndLogEx(NORMAL, " IDD: %s", sprint_hex(&IAD->value[9], 23)); } else if (IAD->len >= IAD->value[0] + 1) { - PrintAndLogEx(NORMAL, "\tKey index: 0x%02x", IAD->value[1]); - PrintAndLogEx(NORMAL, "\tCrypto ver: 0x%02x(%03d)", IAD->value[2], IAD->value[2]); - PrintAndLogEx(NORMAL, "\tCVR: %s", sprint_hex(&IAD->value[3], IAD->value[0] - 2)); + PrintAndLogEx(NORMAL, " Key index: 0x%02x", IAD->value[1]); + PrintAndLogEx(NORMAL, " Crypto ver: 0x%02x(%03d)", IAD->value[2], IAD->value[2]); + PrintAndLogEx(NORMAL, " CVR: %s", sprint_hex(&IAD->value[3], IAD->value[0] - 2)); struct tlvdb *cvr = tlvdb_fixed(0x20, IAD->value[0] - 2, &IAD->value[3]); TLVPrintFromTLVLev(cvr, 1); if (IAD->len >= 8) { int iddLen = IAD->value[7]; - PrintAndLogEx(NORMAL, "\tIDD length: %d", iddLen); + PrintAndLogEx(NORMAL, " IDD length: %d", iddLen); if (iddLen >= 1) - PrintAndLogEx(NORMAL, "\tIDD option id: 0x%02x", IAD->value[8]); + PrintAndLogEx(NORMAL, " IDD option id: 0x%02x", IAD->value[8]); if (iddLen >= 2) - PrintAndLogEx(NORMAL, "\tIDD: %s", sprint_hex(&IAD->value[9], iddLen - 1)); + PrintAndLogEx(NORMAL, " IDD: %s", sprint_hex(&IAD->value[9], iddLen - 1)); } } } else { From 9eccb07106691eb74a546c18040dd1689d96becc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 19:16:15 +0200 Subject: [PATCH 276/373] text --- doc/cheatsheet.md | 169 +++++++++++++++++++++++++++------------------- 1 file changed, 100 insertions(+), 69 deletions(-) diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index 7816c1140..ebd2898af 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -205,7 +205,7 @@ pm3 --> hf iclass dump --ki 7 --elite Verify custom iCLASS key ``` -Options +options --- -f, --file Dictionary file with default iclass keys --csn Specify CSN as 8 bytes (16 hex symbols) @@ -222,7 +222,7 @@ pm3 --> hf iclass lookup --csn 010a0ffff7ff12e0 --epurse feffffffffffffff --macs Check for default keys ``` -Options +options --- -k, --key Key specified as 12 hex symbols --blk Input block number @@ -257,9 +257,10 @@ Options pm3 --> hf mf fchk --1k --mem ``` -Dump MIFARE card contents +Dump MIFARE Classic card contents ``` -options: +Options: +--- -f, --file filename of dump -k, --keys filename of keys --mini MIFARE Classic Mini / S20 @@ -267,52 +268,66 @@ options: --2k MIFARE Classic/Plus 2k --4k MIFARE Classic 4k / S70 -examples/notes: - hf mf dump --mini -> MIFARE Mini - hf mf dump --1k -> MIFARE Classic 1k - hf mf dump --2k -> MIFARE 2k - hf mf dump --4k -> MIFARE 4k - hf mf dump -f hf-mf-066C8B78-key-5.bin -> MIFARE 1k with keys from specified file - pm3 --> hf mf dump pm3 --> hf mf dump --1k -k hf-mf-A29558E4-key.bin -f hf-mf-A29558E4-dump.bin ``` -Convert .bin to .eml +Write to MIFARE Classic block ``` -Options +Options: --- --i dump-file (input). If omitted, 'dumpdata.bin' is used --o output file, if omitted, .eml is use + --blk block number +-a input key type is key A (def) +-b input key type is key B +-k, --key key, 6 hex bytes +-d, --data bytes to write, 16 hex bytes -pm3 --> script run data_mf_bin2eml -i dumpdata.bin -o hf-mf-myfile.bin +pm3 --> hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d d3a2859f6b880400c801002000000016 ``` -Write to MIFARE block +Run autopwn, to extract all keys and backup a MIFARE Classic tag ``` -Options ---- - - -pm3 --> hf mf wrbl 0 A FFFFFFFFFFFF d3a2859f6b880400c801002000000016 -``` - -Run autopwn, to backup a MIFARE tag -``` -Options ---- +Options: +--- +-k, --key Known key, 12 hex bytes +-s, --sector Input sector number +-a Input key A (def) +-b Input key B +-f, --file filename of dictionary +-s, --slow Slower acquisition (required by some non standard cards) +-l, --legacy legacy mode (use the slow `hf mf chk`) +-v, --verbose verbose output (statistics) + --mini MIFARE Classic Mini / S20 + --1k MIFARE Classic 1k / S50 (default) + --2k MIFARE Classic/Plus 2k + --4k MIFARE Classic 4k / S70 pm3 --> hf mf autopwn + +// target MFC 1K card, Sector 0 with known key A 'FFFFFFFFFFFF' +pm3 --> hf mf autopwn -s 0 -a -k FFFFFFFFFFFF + +// target MFC 1K card, default dictionary +pm3 --> hf mf autopwn --1k -f mfc_default_keys ``` Run hardnested attack ``` Options --- - [known target key (12 hex symbols)] [w] [s] -w : Acquire nonces and write them to binary file nonces.bin +-k, --key Key, 12 hex bytes + --blk Input block number +-a Input key A (def) +-b Input key B + --tblk Target block number + --ta Target key A + --tb Target key B + --tk Target key, 12 hex bytes +-f, --file R/W instead of default name +-s, --slow Slower acquisition (required by some non standard cards) +-w, --wr Acquire nonces and UID, and write them to file `hf-mf--nonces.bin` -pm3 --> hf mf hardnested 0 A 8829da9daf76 0 A w +pm3 --> hf mf hardnested --blk 0 -a -k 8829da9daf76 --tblk 4 --ta -w ``` Load MIFARE Classic dump file into emulator memory for simulation @@ -503,19 +518,20 @@ Act as Hitag reader ``` Options --- -HitagS: -01 : Read all pages, challenge mode -02 : Read all pages, crypto mode. Set key=0 for no auth + --01 HitagS, read all pages, challenge mode + --02 HitagS, read all pages, crypto mode. Set key=0 for no auth -Hitag2: -21 : Read all pages, password mode. Default: 4D494B52 ("MIKR") -22 : Read all pages, challenge mode -23 : Read all pages, crypto mode. Key format: ISK high + ISK low. Default: 4F4E4D494B52 ("ONMIKR") -25 : Test recorded authentications -26 : Just read UID - -pm3 --> lf hitag 26 -pm3 --> lf hitag 21 4D494B52 + --21 Hitag2, read all pages, password mode. def 4D494B52 (MIKR) + --22 Hitag2, read all pages, challenge mode + --23 Hitag2, read all pages, crypto mode. Key ISK high + ISK low. def 4F4E4D494B52 (ONMIKR) + --25 Hitag2, test recorded authentications (replay?) + --26 Hitag2, read UID +-k, --key key, 4 or 6 hex bytes + --nrar nonce / answer reader, 8 hex bytes + +pm3 --> lf hitag --26 +pm3 --> lf hitag --21 -k 4D494B52 +pm3 --> lf hitag reader --23 -k 4F4E4D494B52 ``` Sniff Hitag traffic @@ -524,30 +540,32 @@ pm3 --> lf hitag sniff pm3 --> lf hitag list ``` -Simulate Hitag +Simulate Hitag2 ``` -pm3 --> lf hitag sim c378181c_a8f7.ht2 +pm3 --> lf hitag sim -2 ``` Write to Hitag block ``` Options --- -HitagS: -03 : Write page, challenge mode -04 : Write page, crypto mode. Set key=0 for no auth + --03 HitagS, write page, challenge mode + --04 HitagS, write page, crypto mode. Set key=0 for no auth -Hitag2: -24 : Write page, crypto mode. Key format: ISK high + ISK low. -27 : Write page, password mode. Default: 4D494B52 ("MIKR") + --24 Hitag2, write page, crypto mode. + --27 Hitag2, write page, password mode +-p, --page page address to write to +-d, --data data, 4 hex bytes +-k, --key key, 4 or 6 hex bytes + --nrar nonce / answer writer, 8 hex bytes -pm3 --> lf hitag writer 24 499602D2 1 00000000 +pm3 --> lf hitag writer --24 -k 499602D2 -p 1 -d 00000000 ``` Simulate Hitag2 sequence ``` -pm3 --> lf hitag reader 21 56713368 -pm3 --> lf hitag sim c378181c_a8f7.ht2 +pm3 --> lf hitag reader --21 -k 56713368 +pm3 --> lf hitag sim -2 ``` ## T55XX @@ -562,7 +580,19 @@ Configure modulation ``` Options --- - : Set modulation + --FSK set demodulation FSK + --FSK1 set demodulation FSK 1 + --FSK1A set demodulation FSK 1a (inv) + --FSK2 set demodulation FSK 2 + --FSK2A set demodulation FSK 2a (inv) + --ASK set demodulation ASK + --PSK1 set demodulation PSK 1 + --PSK2 set demodulation PSK 2 + --PSK3 set demodulation PSK 3 + --NRZ set demodulation NRZ + --BI set demodulation Biphase + --BIA set demodulation Diphase (inverted biphase) + EM is ASK HID Prox is FSK Indala is PSK @@ -574,18 +604,19 @@ Set timings to default ``` Options --- --p : persist to flash memory (RDV4) --z : Set default t55x7 timings (use `-p` to save if required) -pm3 --> lf t55xx deviceconfig -z -p +-p, --persist persist to flash memory (RDV4) +-z Set default t55x7 timings (use `-p` to save if required) +pm3 --> lf t55xx deviceconfig -zp ``` Write to T55xx block ``` -b : block number to write. Between 0-7 -d : 4 bytes of data to write (8 hex characters) +-b, --blk <0-7> block number to write +-d, --data data to write (4 hex bytes) +-p, --pwd password (4 hex bytes) -pm3 --> lf t55xx wr -b 0 -d 00081040 +pm3 --> lf t55xx write -b 0 -d 00081040 ``` Wipe a T55xx tag and set defaults @@ -631,8 +662,8 @@ Convert .bin to .eml ``` Options --- --i Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used --o Specifies the output file. If omitted, .eml is used +-i Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used +-o Specifies the output file. If omitted, .eml is used pm3 --> script run data_mf_bin2eml -i xxxxxxxxxxxxxx.bin ``` @@ -641,8 +672,8 @@ Convert .eml to .bin ``` Options --- --i Specifies the dump-file (input). If omitted, 'dumpdata.eml' is used --o Specifies the output file. If omitted, .bin is used +-i Specifies the dump-file (input). If omitted, 'dumpdata.eml' is used +-o Specifies the output file. If omitted, .bin is used pm3 --> script run data_mf_eml2bin -i myfile.eml -o myfile.bin ``` @@ -651,10 +682,10 @@ Format Mifare card ``` Options --- --k The current six byte key with write access --n The new key that will be written to the card --a The new access bytes that will be written to the card --x Execute the commands as well +-k The current six byte key with write access +-n The new key that will be written to the card +-a The new access bytes that will be written to the card +-x Execute the commands as well pm3 --> script run hf_mf_format -k FFFFFFFFFFFF -n FFFFFFFFFFFF -x ``` From 4f3447a4abaee5b2e17512ff3e1ce8fe683d2c1d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 19:34:42 +0200 Subject: [PATCH 277/373] text --- client/src/cmdhfmfu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 6fe59084d..d78750fab 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -2796,7 +2796,7 @@ static int CmdHF14AMfUCSetUid(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("uk", "uid", "", "new uid (7 bytes)"), + arg_str0("u", "uid", "", "new uid (7 bytes)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); From fde48cd916ab6b5988f21ef3fe9da484d2e8c3da Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 19:44:30 +0200 Subject: [PATCH 278/373] text --- doc/colors_notes.md | 6 +++++- doc/magic_cards_notes.md | 16 ++++++++-------- doc/trace_notes.md | 8 ++++---- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/doc/colors_notes.md b/doc/colors_notes.md index 74d0cbb92..38a3e9ede 100644 --- a/doc/colors_notes.md +++ b/doc/colors_notes.md @@ -4,7 +4,7 @@ ## Table of Contents * [style/color](#style_color) * [Proxspace](#proxspace) - * [](#) + * [help texts](#help-texts) The client should autodetect color support when starting. @@ -48,3 +48,7 @@ Most commands doesn't use a header yet. We added it to make it standout (ie: yel ^[Top](#top) Proxspace has support for colors. + +## Help texts +^[Top](#top) +The help text uses a hard coded template deep inside the cliparser.c file. \ No newline at end of file diff --git a/doc/magic_cards_notes.md b/doc/magic_cards_notes.md index 0a73a83b8..45a225d99 100644 --- a/doc/magic_cards_notes.md +++ b/doc/magic_cards_notes.md @@ -329,7 +329,7 @@ Android compatible ### Proxmark3 commands ``` -hf mf wrbl 0 A FFFFFFFFFFFF 11223344440804006263646566676869 +hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 11223344440804006263646566676869 ``` When "soft-bricked" (by writing invalid data in block0), these ones may help: @@ -342,8 +342,8 @@ e.g. for 4b UID: ``` hf 14a config --atqa force --bcc ignore --cl2 skip --rats skip -hf mf wrbl 0 A FFFFFFFFFFFF 11223344440804006263646566676869 # for 1k -hf mf wrbl 0 A FFFFFFFFFFFF 11223344441802006263646566676869 # for 4k +hf mf wrbl --blk 0 -k FFFFFFFFFFFF -k 11223344440804006263646566676869 # for 1k +hf mf wrbl --blk 0 -k FFFFFFFFFFFF -k 11223344441802006263646566676869 # for 4k hf 14a config --std hf 14a reader ``` @@ -352,8 +352,8 @@ e.g. for 7b UID: ``` hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip --rats skip -hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566084400626364656667 # for 1k -hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566184200626364656667 # for 4k +hf mf wrbl --blk 0 -k FFFFFFFFFFFF -k 04112233445566084400626364656667 # for 1k +hf mf wrbl --blk 0 -k FFFFFFFFFFFF -k 04112233445566184200626364656667 # for 4k hf 14a config --std hf 14a reader ``` @@ -585,7 +585,7 @@ Issue three regular MFU write commands in a row to write first three blocks. ### Proxmark3 commands ``` -hf mfu setuid +hf mfu setuid -h ``` Equivalent: don't use `hf mfu wrbl` as you need to write three blocks in a row, but do, with proper BCCx: @@ -605,7 +605,7 @@ hf 14a config -h E.g.: ``` hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip --rats skip -hf mfu setuid 04112233445566 +hf mfu setuid --uid 04112233445566 hf 14a config --std hf 14a reader ``` @@ -825,7 +825,7 @@ It accepts longer UID but that doesn't affect BCC/ATQA/SAK The same effect (with better ATQA!) can be obtained with a MFC Gen1A that uses SAK defined in block0: ``` -hf mf csetblk 0 1122334444204403A1A2A3A4A5A6A7A8 +hf mf csetblk --blk 0 -d 1122334444204403A1A2A3A4A5A6A7A8 hf 14a info [+] UID: 11 22 33 44 [+] ATQA: 03 44 diff --git a/doc/trace_notes.md b/doc/trace_notes.md index 515255053..6f89cffbc 100644 --- a/doc/trace_notes.md +++ b/doc/trace_notes.md @@ -26,10 +26,10 @@ The unit for this time information depends on the protocol in use: * Reader Mode: Timings are in ticks (1us == 1.5ticks) * Tag Mode: Timings are in sub carrier periods (1/212 kHz == 4.7us) * Hitag1 / Hitag2 / HitagS: Elementary Time Unit (ETU) is 8µs -* iClass, ISO15693, ISO18092 and FeliCa have no accurate timing information at the moment +* iCLASS, ISO15693, ISO18092 and FeliCa have no accurate timing information at the moment * For others timing is not available -By specifying the option ```f``` (e.g. ```trace list 14a f```) the frame delay times are shown. (So you don't have to do the math by your own). +By specifying the option ```f``` (e.g. ```trace list -t 14a -f```) the frame delay times are shown. (So you don't have to do the math by your own). ### Sources ^[Top](#top) @@ -88,14 +88,14 @@ To get a more detailed explanation of the transmitted data for ISO14443A traces To do so -* use `trace list 14a x` +* use `trace list -t 14a -x` * copy the output (starting with the timestamp) into a textfile * run `text2pcap -t "%S." -l 264 -n ` * now open your pcapng file in Wireshark or read it with the CLI version `tshark` An example frame -with `trace list 14a`: +with `trace list -t 14a`: ``` 19072 | 29536 | Rdr |93 70 88 04 cf ff bc 7f bb | ok | SELECT_UID From d1fe746ebf59192baddd705a5faab1328b03ea7e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 21:43:48 +0200 Subject: [PATCH 279/373] felica - select tag , only loop 10 tens --- armsrc/felica.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/felica.c b/armsrc/felica.c index a00378881..55995cbb1 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -208,9 +208,9 @@ static uint8_t felica_select_card(felica_card_select_t *card) { // 0x00 = timeslot // 0x09 0x21 = crc static uint8_t poll[10] = {0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x21}; - int len = 20; + int len = 10; - // We try 20 times, or if answer was received. + // We try 10 times, or if answer was received. do { // end-of-reception response packet data, wait approx. 501μs // end-of-transmission command packet data, wait approx. 197μs From 786858aa6ce7d52655496ec388889d02d4f7e0d8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 21:51:47 +0200 Subject: [PATCH 280/373] =?UTF-8?q?fix=20=C2=B4hf=20search'=20/=20=C2=B4hf?= =?UTF-8?q?=2015=20reader=C2=B4=20looping=20gave=20false=20result?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/cmdhf15.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 9b1f9be52..cf083332c 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -417,7 +417,7 @@ static int getUID(bool loop, uint8_t *buf) { uint8_t fast = 1; uint8_t reply = 1; - int res = PM3_SUCCESS; + int res = PM3_ESOFT; do { clearCommandBuffer(); @@ -437,11 +437,12 @@ static int getUID(bool loop, uint8_t *buf) { PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), iso15693_sprintUID(NULL, buf)); PrintAndLogEx(SUCCESS, "TYPE: " _YELLOW_("%s"), getTagInfo_15(buf)); + res = PM3_SUCCESS; + if (loop == false) { - res = PM3_SUCCESS; break; } - } + } } } while (loop && kbd_enter_pressed() == false); From 9c358961620bd2036e992510ea890f93bc35efd8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 22:06:17 +0200 Subject: [PATCH 281/373] hf 14b reader - now supports continuous mode --- client/src/cmdhf14b.c | 50 +++++++++++++++++++++++++++---------------- client/src/cmdhf14b.h | 2 +- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index 244d88f83..ebce7126a 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -1047,13 +1047,20 @@ static int CmdHF14BReader(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_lit0("v", "verbose", "verbose"), + arg_lit0("s", "silent", "silent (no messages)"), + arg_lit0("@", NULL, "optional - continuous reader mode"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - bool verbose = arg_get_lit(ctx, 1); + bool verbose = (arg_get_lit(ctx, 1) == false); + bool cm = arg_get_lit(ctx, 2); CLIParserFree(ctx); - return readHF14B(verbose); + + if (cm) { + PrintAndLogEx(INFO, "Press " _GREEN_("") " to exit"); + } + + return readHF14B(cm, verbose); } // Read SRI512|SRIX4K block @@ -1965,25 +1972,30 @@ int infoHF14B(bool verbose, bool do_aid_search) { } // get and print general info about all known 14b chips -int readHF14B(bool verbose) { +int readHF14B(bool loop, bool verbose) { - // try std 14b (atqb) - if (HF14B_std_reader(verbose)) - return 1; + do { + // try std 14b (atqb) + if (HF14B_std_reader(verbose)) + return PM3_SUCCESS; - // try ST Microelectronics 14b - if (HF14B_st_reader(verbose)) - return 1; + // try ST Microelectronics 14b + if (HF14B_st_reader(verbose)) + return PM3_SUCCESS; - // try ASK CT 14b - if (HF14B_ask_ct_reader(verbose)) - return 1; + // try ASK CT 14b + if (HF14B_ask_ct_reader(verbose)) + return PM3_SUCCESS; - // try unknown 14b read commands (to be identified later) - // could be read of calypso, CEPAS, moneo, or pico pass. - if (HF14B_other_reader(verbose)) - return 1; + // try unknown 14b read commands (to be identified later) + // could be read of calypso, CEPAS, moneo, or pico pass. + if (HF14B_other_reader(verbose)) + return PM3_SUCCESS; - if (verbose) PrintAndLogEx(FAILED, "no 14443-B tag found"); - return 0; + } while (loop && kbd_enter_pressed() == false); + + if (verbose) { + PrintAndLogEx(FAILED, "no ISO 14443-B tag found"); + } + return PM3_EOPABORTED; } diff --git a/client/src/cmdhf14b.h b/client/src/cmdhf14b.h index bd97bbf5c..ca05bc02e 100644 --- a/client/src/cmdhf14b.h +++ b/client/src/cmdhf14b.h @@ -18,5 +18,5 @@ int CmdHF14B(const char *Cmd); int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field, bool leave_signal_on, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, int user_timeout); int infoHF14B(bool verbose, bool do_aid_search); -int readHF14B(bool verbose); +int readHF14B(bool loop, bool verbose); #endif From 92bb8d38bc506c470d58696235bcc6131fd22d31 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 22:24:20 +0200 Subject: [PATCH 282/373] adapting text --- tools/pm3_amii_bin2eml.pl | 2 +- tools/pm3_mf7b_wipe.py | 29 +++++++++++++---------------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/tools/pm3_amii_bin2eml.pl b/tools/pm3_amii_bin2eml.pl index f15b0de75..380d0035b 100755 --- a/tools/pm3_amii_bin2eml.pl +++ b/tools/pm3_amii_bin2eml.pl @@ -684,7 +684,7 @@ print STDERR "\n"; $uid = uc $uid; #print STDERR "amiitool -d -k ../client/amiitool/key_retail.bin -i $input -o $input.decrypted\n"; $input =~ s/\....$//; -print STDERR "hf mf eload u $input\n"; +print STDERR "hf mfu eload --u $input\n"; print STDERR "hf 14a sim -t 7 -u $uid\n"; diff --git a/tools/pm3_mf7b_wipe.py b/tools/pm3_mf7b_wipe.py index 1bc0db4b9..d4ba6f197 100755 --- a/tools/pm3_mf7b_wipe.py +++ b/tools/pm3_mf7b_wipe.py @@ -27,11 +27,11 @@ # # Get first line from EML file (block0) and write it down using command # -# Place it here -# | -# | -# v -# hf mf wrbl 0 B FFFFFFFFFFFF 046E46AAA53480084400120111003113 +# Place it here +# | +# | +# v +# hf mf wrbl --blk 0 -b -k FFFFFFFFFFFF -d 046E46AAA53480084400120111003113 # # Now restore all the data using built-in restore command # @@ -73,15 +73,12 @@ # # - - - import subprocess # EML data var te get keys of EML_FILE_DATA = """PLACE RAW hf-mf-CARD_UID-dump.eml FILE CONTENT OF CURRENTLY LOADED CARD HERE""" # Change your device name here if it differs from the default Proxmark3 RDV4.0 -PROXMARK_BIN_EXEC_STRING = 'proxmark3 -c "%s" /dev/tty.usbmodemiceman1' +PROXMARK_BIN_EXEC_STRING = './pm3 -c "%s"' # Constants DEFAULT_ACCESS_BLOCK = "FFFFFFFFFFFFFF078000FFFFFFFFFFFF" F12_KEY = "FFFFFFFFFFFF" @@ -95,7 +92,7 @@ def exec_proxmark_cmd(command, retry = 2, input=""): proxmark_reply = rst.stdout.decode("utf-8") proxmark_status = proxmark_reply.splitlines()[-1:][0].strip() - if proxmark_status == "isOk:01": + if proxmark_status == "ok": return True, "Success: " + proxmark_status retry_c += 1 return False, "Error: %s , status %s" % (proxmark_reply.splitlines()[-2:][0], proxmark_status) @@ -128,19 +125,19 @@ for sector in sector_array: key_B = sector[3][-12:] for _block in range(0,4): if sector_array.index(sector) == 0 and block == 0: - write_status, verbose = exec_proxmark_cmd("hf mf wrbl %s B %s %s" % (block, key_B, sector[0])) + write_status, verbose = exec_proxmark_cmd("hf mf wrbl --blk %s -b -k %s -d %s" % (block, key_B, sector[0])) if not write_status: - write_status, verbose = exec_proxmark_cmd("hf mf wrbl %s A %s %s" % (block, key_A, sector[0])) + write_status, verbose = exec_proxmark_cmd("hf mf wrbl --blk %s -a -k %s -d %s" % (block, key_A, sector[0])) if not write_status: - write_status, verbose = exec_proxmark_cmd("hf mf wrbl %s A %s %s" % (block, F12_KEY, sector[0])) + write_status, verbose = exec_proxmark_cmd("hf mf wrbl --blk %s -a -k %s -d %s" % (block, F12_KEY, sector[0])) block_success[block] = verbose elif _block == 3: - write_status, verbose = exec_proxmark_cmd("hf mf wrbl %s B %s %s" % (block, key_B, DEFAULT_ACCESS_BLOCK)) + write_status, verbose = exec_proxmark_cmd("hf mf wrbl --blk %s -b -k %s -d %s" % (block, key_B, DEFAULT_ACCESS_BLOCK)) if not write_status: - write_status, verbose = exec_proxmark_cmd("hf mf wrbl %s A %s %s" % (block, key_A, DEFAULT_ACCESS_BLOCK)) + write_status, verbose = exec_proxmark_cmd("hf mf wrbl --blk %s -a -k %s -d %s" % (block, key_A, DEFAULT_ACCESS_BLOCK)) if not write_status: - write_status, verbose = exec_proxmark_cmd("hf mf wrbl %s A %s %s" % (block, F12_KEY, DEFAULT_ACCESS_BLOCK)) + write_status, verbose = exec_proxmark_cmd("hf mf wrbl --blk %s -a -k %s -d %s" % (block, F12_KEY, DEFAULT_ACCESS_BLOCK)) block_success[block] = verbose _block += 1 From 0a57b3dc0f583f6641fc61ee957afdeb99a7ced7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 22:31:46 +0200 Subject: [PATCH 283/373] text --- doc/cheatsheet.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index ebd2898af..ae41a4745 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -356,7 +356,7 @@ pm3 --> hf mf sim -u 353c2aa6 Simulate MIFARE Sequence ``` -pm3 --> hf mf fchk -1k -f mfc_default_keys.dic +pm3 --> hf mf fchk --1k -f mfc_default_keys.dic pm3 --> hf mf dump pm3 --> hf mf eload -f hf-mf--dump.bin pm3 --> hf mf sim -u 353c2aa6 @@ -366,7 +366,7 @@ Clone MIFARE 1K Sequence ``` pm3 --> hf mf fchk --1k -f mfc_default_keys.dic pm3 --> hf mf dump -pm3 --> hf mf restore 1 u 4A6CE843 k hf-mf-A29558E4-key.bin f hf-mf-A29558E4-dump.bin +pm3 --> hf mf restore --1k --uid 4A6CE843 -k hf-mf-A29558E4-key.bin -f hf-mf-A29558E4-dump.bin ``` Read MIFARE Ultralight EV1 From 52c7b9072ebc11796d086e45a6c25dba4335326e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 22:32:58 +0200 Subject: [PATCH 284/373] text --- doc/magic_cards_notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/magic_cards_notes.md b/doc/magic_cards_notes.md index 45a225d99..dc3a5f564 100644 --- a/doc/magic_cards_notes.md +++ b/doc/magic_cards_notes.md @@ -79,7 +79,7 @@ UID 4b: (actually NUID as there are no more "unique" IDs on 4b) ``` -Computing BCC on UID 11223344: `hf analyse lcr 11223344` = `44` +Computing BCC on UID 11223344: `hf analyse lcr -d 11223344` = `44` UID 7b: From dea87b8c48780f43e8ceca0ae6b718a9f20e9310 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 22:34:31 +0200 Subject: [PATCH 285/373] text --- armsrc/iclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/iclass.c b/armsrc/iclass.c index c1b80639b..5006436c1 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -678,7 +678,7 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) { if (_mac[0] != receivedCmd[5] || _mac[1] != receivedCmd[6] || _mac[2] != receivedCmd[7] || _mac[3] != receivedCmd[8]) { Dbprintf("reader auth " _RED_("failed")); - Dbprintf("hf iclass lookup u %02x%02x%02x%02x%02x%02x%02x%02x p %02x%02x%02x%02x%02x%02x%02x%02x m %02x%02x%02x%02x%02x%02x%02x%02x f iclass_default_keys.dic", + Dbprintf("hf iclass lookup --csn %02x%02x%02x%02x%02x%02x%02x%02x --epurse %02x%02x%02x%02x%02x%02x%02x%02x --macs %02x%02x%02x%02x%02x%02x%02x%02x f iclass_default_keys.dic", csn_data[0], csn_data[1], csn_data[2], csn_data[3], csn_data[4], csn_data[5], csn_data[6], csn_data[7], card_challenge_data[0], card_challenge_data[1], card_challenge_data[2], card_challenge_data[3], card_challenge_data[4], card_challenge_data[5], card_challenge_data[6], card_challenge_data[7], From 62697ca46019b8f974ce0422c4460fdf7936e8d7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 22:41:47 +0200 Subject: [PATCH 286/373] text --- client/src/cmdhf14a.c | 2 +- client/src/cmdhfmf.c | 4 ++-- include/mifare.h | 2 +- tools/pm3_amii_bin2eml.pl | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index e382a5714..b729049d9 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -627,7 +627,7 @@ int CmdHF14ASim(const char *Cmd) { arg_int1("t", "type", "<1-10> ", "Simulation type to use"), arg_str0("u", "uid", "", "4, 7 or 10 byte UID"), arg_int0("n", "num", "", "Exit simulation after blocks have been read by reader. 0 = infinite"), - arg_lit0(NULL, "nr", "Performs the 'reader attack', nr/ar attack against a reader"), + arg_lit0("x", NULL, "Performs the 'reader attack', nr/ar attack against a reader"), arg_lit0(NULL, "sk", "Fill simulator keys from found keys"), arg_lit0("v", "verbose", "verbose output"), arg_param_end diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index a6136ff25..f122e58e3 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -3267,7 +3267,7 @@ void readerAttack(sector_t *k_sector, uint8_t k_sectorsCount, nonces_t data, boo static int CmdHF14AMfSim(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf sim", - "Simulate MIFARE card", + "Simulate MIFARE Classic card", "hf mf sim --mini --> MIFARE Mini\n" "hf mf sim --1k --> MIFARE Classic 1k (default)\n" "hf mf sim --1k -u 0a0a0a0a --> MIFARE Classic 1k with 4b UID\n" @@ -3287,7 +3287,7 @@ static int CmdHF14AMfSim(const char *Cmd) { arg_str0(NULL, "sak", "", "Provide explicit SAK (1 bytes, overrides option t)"), arg_int0("n", "num", " ", "Automatically exit simulation after blocks have been read by reader. 0 = infinite"), arg_lit0("i", "interactive", "Console will not be returned until simulation finishes or is aborted"), - arg_lit0(NULL, "crack", "Performs the 'reader attack', nr/ar attack against a reader"), + arg_lit0("x", NULL, "Performs the 'reader attack', nr/ar attack against a reader"), arg_lit0("e", "emukeys", "Fill simulator keys from found keys"), arg_lit0("v", "verbose", "verbose output"), arg_param_end diff --git a/include/mifare.h b/include/mifare.h index d31368102..e38c7eb45 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -101,7 +101,7 @@ typedef enum { } mifare_des_kdf_algo_t; //----------------------------------------------------------------------------- -// "hf 14a sim x", "hf mf sim x" attacks +// "hf 14a sim -x", "hf mf sim -x" attacks //----------------------------------------------------------------------------- typedef struct { uint32_t cuid; diff --git a/tools/pm3_amii_bin2eml.pl b/tools/pm3_amii_bin2eml.pl index 380d0035b..83e9f195f 100755 --- a/tools/pm3_amii_bin2eml.pl +++ b/tools/pm3_amii_bin2eml.pl @@ -6,7 +6,7 @@ # # -samy kamkar 05/28/2017 # -# hf mf eload u FILENAME_MINUS_EML +# hf mf eload --ul FILENAME_MINUS_EML # hf 14a sim -t 7 -u UID # perl -lne 'chomp; s/\s+(\S+)$//;$f=$1;if($f=~s/-(\S+)//){$g=hex($1);}else{$g=hex($f)}$f=hex($f); for$m($f..$g){print "0x" . substr(unpack("H4",pack("n",$m)),1) ." => \"$_\","}' /tmp/game >> game2 From 4e417fe0374df90b801b9662dc577bfd2b4607d0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 22:49:39 +0200 Subject: [PATCH 287/373] fix commands --- client/luascripts/hf_mf_gen3_writer.lua | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/client/luascripts/hf_mf_gen3_writer.lua b/client/luascripts/hf_mf_gen3_writer.lua index 1257f3413..a70a5c23d 100644 --- a/client/luascripts/hf_mf_gen3_writer.lua +++ b/client/luascripts/hf_mf_gen3_writer.lua @@ -30,7 +30,7 @@ local read14a = require('read14a') -- copyright = 'RRG Team' author = 'Winds' -version = 'v1.0.0' +version = 'v1.0.1' desc = [[ This script gives you an easy way to write your *.eml dumps into normal MIFARE Classic and Magic Gen3 cards. @@ -46,11 +46,6 @@ desc = [[ 5. Erase all data at the card and set the FF FF FF FF FF FF keys, and Access Conditions to 78778800. Script works in a wizard styled way. - - Author Youtube channel: https://yev.ooo/ - - Many Thanks, - Best Regards ]] example = [[ 1. script run mfc_gen3_writer @@ -80,8 +75,8 @@ local default_key_type = '01' --KeyA: 00, KeyB: 01 local default_key_blk = 'FFFFFFFFFFFF7C378800FFFFFFFFFFFF' -- Writing blocks local piswords_uid_lock = 'hf 14a raw -s -c -t 2000 90fd111100' local piswords_uid_change = 'hf 14a raw -s -c -t 2000 90f0cccc10' -local cmd_wrbl_a = 'hf mf wrbl %d A %s %s' -- Writing blocks by A key -local cmd_wrbl_b = 'hf mf wrbl %d B %s %s' -- Writing blocks by B key +local cmd_wrbl_a = 'hf mf wrbl --blk %d -a -k %s -d %s' -- Writing blocks by A key +local cmd_wrbl_b = 'hf mf wrbl --blk %d -b -k %s -d %s' -- Writing blocks by B key -- --- ------------------------------- From 34544e238e61e3dd0314a333ff38360584fff59f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 22:58:16 +0200 Subject: [PATCH 288/373] text --- client/luascripts/hf_legic_buffer2card.lua | 8 +++++--- client/luascripts/hf_mf_magicrevive.lua | 4 ++-- client/luascripts/hf_mf_tnp3_clone.lua | 10 +++++----- client/luascripts/mfc_hammerlite.lua | 6 +++--- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/client/luascripts/hf_legic_buffer2card.lua b/client/luascripts/hf_legic_buffer2card.lua index eac8f1ed2..83fa6c12b 100644 --- a/client/luascripts/hf_legic_buffer2card.lua +++ b/client/luascripts/hf_legic_buffer2card.lua @@ -5,10 +5,12 @@ local ansicolors = require('ansicolors') copyright = '' author = 'Mosci' -version = 'v1.0.2' +version = 'v1.0.3' desc = [[ -This is a script which writes value 0x01 to bytes from position 0x07 until 0xFF on a Legic Prime Tag (MIM256 or MIM1024) -- (created with 'hf legic save my_dump.hex') -- +This is a script which writes value 0x01 to bytes from +position 0x07 until 0xFF on a Legic Prime Tag (MIM256 or MIM1024) +-- (created with 'hf legic dump -f my_dump.hex') -- ]] example = [[ script run hf_legic_buffer2card @@ -53,7 +55,7 @@ function main() local cmd = '' local i for i = 7, 255 do - cmd = ('hf legic write o %02x d 01'):format(i) + cmd = ('hf legic wrbl -o %02x -d 01'):format(i) print(cmd) core.clearCommandBuffer() core.console(cmd) diff --git a/client/luascripts/hf_mf_magicrevive.lua b/client/luascripts/hf_mf_magicrevive.lua index 9354b0f96..b50422123 100644 --- a/client/luascripts/hf_mf_magicrevive.lua +++ b/client/luascripts/hf_mf_magicrevive.lua @@ -3,7 +3,7 @@ local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.2' +version = 'v1.0.3' desc = [[ This is a script that tries to bring back a chinese magic card (1k generation1) from the dead when it's block 0 has been written with bad values. @@ -84,7 +84,7 @@ local function cmdRestoreST() local arr = {} for i = 0, 15 do local blk = 3 + (4*i) - arr[i] = 'hf mf csetbl '..blk..' FFFFFFFFFFFFFF078000FFFFFFFFFFFF' + arr[i] = 'hf mf csetbl --blk '..blk..' -d FFFFFFFFFFFFFF078000FFFFFFFFFFFF' end return arr end diff --git a/client/luascripts/hf_mf_tnp3_clone.lua b/client/luascripts/hf_mf_tnp3_clone.lua index 490c49242..22c626e80 100644 --- a/client/luascripts/hf_mf_tnp3_clone.lua +++ b/client/luascripts/hf_mf_tnp3_clone.lua @@ -13,7 +13,7 @@ local band = bit32.band copyright = '' author = "Iceman" -version = 'v1.0.2' +version = 'v1.0.3' desc = [[ This script will try to make a barebones clone of a tnp3 tag on to a magic generation1 card. ]] @@ -160,7 +160,7 @@ local function main(args) core.clearCommandBuffer() -- wipe card. - local cmd = (csetuid..'%s %s %s w'):format(card.uid, atqa, sak) + local cmd = (csetuid..' -u %s -a %s -s %s -w'):format(card.uid, atqa, sak) core.console(cmd) core.clearCommandBuffer() @@ -169,7 +169,7 @@ local function main(args) local calc = utils.Crc16(b0..b1) local calcEndian = bor(rsh(calc,8), lsh(band(calc, 0xff), 8)) - local cmd = (cset..'1 %s%04x'):format( b1, calcEndian) + local cmd = (cset..'--blk 1 -d %s%04x'):format( b1, calcEndian) core.console(cmd) core.clearCommandBuffer() @@ -178,14 +178,14 @@ local function main(args) pos = (math.floor( blockNo / 4 ) * 12)+1 key = akeys:sub(pos, pos + 11 ) if blockNo%4 == 3 then - cmd = ('%s %d %s%s'):format(cset,blockNo,key,AccAndKeyB) + cmd = ('%s --blk %d -d %s%s'):format(cset,blockNo,key,AccAndKeyB) core.console(cmd) end end core.clearCommandBuffer() -- Set sector trailer S0, since it has different access rights - cmd = ('%s 3 %s0f0f0f69000000000000'):format(cset, keyA) + cmd = ('%s --blk 3 -d %s0f0f0f69000000000000'):format(cset, keyA) core.console(cmd) core.clearCommandBuffer() end diff --git a/client/luascripts/mfc_hammerlite.lua b/client/luascripts/mfc_hammerlite.lua index c2f34f04c..10a528a3d 100644 --- a/client/luascripts/mfc_hammerlite.lua +++ b/client/luascripts/mfc_hammerlite.lua @@ -5,7 +5,7 @@ local ansicolors = require('ansicolors') copyright = 'Copyright 2020 A. Ozkal, released under GPLv2+.' author = 'Ave' -version = 'v0.1.1' +version = 'v0.1.2' desc = [[ This script writes a bunch of random blocks to a Mifare Classic card ]] @@ -70,8 +70,8 @@ function main(args) do if ((a + 1) % 4 ~= 0) and a ~= 0 then -- :) data = randhex(32) - -- core.console('hf mf rdbl '..a..' A FFFFFFFFFFFF') - core.console('hf mf wrbl '..a..' A '..key..' '..data) + -- core.console('hf mf rdbl --blk '..a..' -k FFFFFFFFFFFF') + core.console('hf mf wrbl --blk '..a..' -k '..key..' -d '..data) end end end From 771ac8d239ae4e7e03f8f830eb14c0a13833d3f5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 23:00:43 +0200 Subject: [PATCH 289/373] text --- client/src/cmdhf14a.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index b729049d9..abac9e999 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -218,23 +218,23 @@ static int hf_14a_config_example(void) { PrintAndLogEx(NORMAL, "\nExamples to revive Gen2/DirectWrite magic cards failing at anticollision:"); PrintAndLogEx(NORMAL, _CYAN_(" MFC 1k 4b UID")":"); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 skip --rats skip")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 11223344440804006263646566676869")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 11223344440804006263646566676869")); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std")); PrintAndLogEx(NORMAL, _CYAN_(" MFC 4k 4b UID")":"); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 skip --rats skip")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 11223344441802006263646566676869")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 11223344441802006263646566676869")); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std")); PrintAndLogEx(NORMAL, _CYAN_(" MFC 1k 7b UID")":"); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip --rats skip")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566084400626364656667")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 04112233445566084400626364656667")); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std")); PrintAndLogEx(NORMAL, _CYAN_(" MFC 4k 7b UID")":"); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa forcce --bcc ignore --cl2 force --cl3 skip --rats skip")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl 0 A FFFFFFFFFFFF 04112233445566184200626364656667")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 04112233445566184200626364656667")); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std")); PrintAndLogEx(NORMAL, _CYAN_(" MFUL ")"/" _CYAN_(" MFUL EV1 ")"/" _CYAN_(" MFULC")":"); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip -rats skip")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu setuid 04112233445566")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu setuid --uid 04112233445566")); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std")); return PM3_SUCCESS; } From 876de0d95473ec06c125ffaa7d594aed0e7d4c00 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 23:26:31 +0200 Subject: [PATCH 290/373] rework helptexts and params --- client/src/cmdhfmfp.c | 217 +++++++++++++++++++++--------------------- 1 file changed, 110 insertions(+), 107 deletions(-) diff --git a/client/src/cmdhfmfp.c b/client/src/cmdhfmfp.c index 33991bb27..8b01f1aff 100644 --- a/client/src/cmdhfmfp.c +++ b/client/src/cmdhfmfp.c @@ -446,28 +446,29 @@ static int CmdHFMFPInfo(const char *Cmd) { } static int CmdHFMFPWritePerso(const char *Cmd) { - uint8_t keyNum[64] = {0}; - int keyNumLen = 0; - uint8_t key[64] = {0}; - int keyLen = 0; - CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfp wrp", "Executes Write Perso command. Can be used in SL0 mode only.", - "hf mfp wrp 4000 000102030405060708090a0b0c0d0e0f -> write key (00..0f) to key number 4000 \n" - "hf mfp wrp 4000 -> write default key(0xff..0xff) to key number 4000"); + "hf mfp wrp --ki 4000 --key 000102030405060708090a0b0c0d0e0f -> write key (00..0f) to key number 4000 \n" + "hf mfp wrp --ki 4000 -> write default key(0xff..0xff) to key number 4000"); void *argtable[] = { arg_param_begin, - arg_lit0("v", "verbose", "show internal data."), - arg_str1(NULL, NULL, "", NULL), - arg_strx0(NULL, NULL, "", NULL), + arg_lit0("v", "verbose", "show internal data."), + arg_str1("i", "ki", "", " key number, 2 hex bytes"), + arg_strx0(NULL, "key", "", " key, 16 hex bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - + bool verbose = arg_get_lit(ctx, 1); + + uint8_t keyNum[64] = {0}; + int keyNumLen = 0; CLIGetHexWithReturn(ctx, 2, keyNum, &keyNumLen); + + uint8_t key[64] = {0}; + int keyLen = 0; CLIGetHexWithReturn(ctx, 3, key, &keyLen); CLIParserFree(ctx); @@ -480,11 +481,11 @@ static int CmdHFMFPWritePerso(const char *Cmd) { if (keyNumLen != 2) { PrintAndLogEx(ERR, "Key number length must be 2 bytes instead of: %d", keyNumLen); - return 1; + return PM3_EINVARG; } if (keyLen != 16) { PrintAndLogEx(ERR, "Key length must be 16 bytes instead of: %d", keyLen); - return 1; + return PM3_EINVARG; } uint8_t data[250] = {0}; @@ -498,60 +499,61 @@ static int CmdHFMFPWritePerso(const char *Cmd) { if (datalen != 3) { PrintAndLogEx(ERR, "Command must return 3 bytes instead of: %d", datalen); - return 1; + return PM3_ESOFT; } if (data[0] != 0x90) { PrintAndLogEx(ERR, "Command error: %02x %s", data[0], mfpGetErrorDescription(data[0])); - return 1; + return PM3_ESOFT; } - PrintAndLogEx(INFO, "Write OK."); + PrintAndLogEx(INFO, "Write (" _GREEN_("ok") " )"); return PM3_SUCCESS; } static int CmdHFMFPInitPerso(const char *Cmd) { - int res; - uint8_t key[256] = {0}; - int keyLen = 0; - uint8_t keyNum[2] = {0}; - uint8_t data[250] = {0}; - int datalen = 0; - CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfp initp", "Executes Write Perso command for all card's keys. Can be used in SL0 mode only.", - "hf mfp initp 000102030405060708090a0b0c0d0e0f -> fill all the keys with key (00..0f)\n" + "hf mfp initp --key 000102030405060708090a0b0c0d0e0f -> fill all the keys with key (00..0f)\n" "hf mfp initp -vv -> fill all the keys with default key(0xff..0xff) and show all the data exchange"); void *argtable[] = { arg_param_begin, arg_litn("v", "verbose", 0, 2, "show internal data."), - arg_strx0(NULL, NULL, "", NULL), + arg_strx0("k", "key", "", "key, 16 hex bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); bool verbose = arg_get_lit(ctx, 1); bool verbose2 = arg_get_lit(ctx, 1) > 1; + + uint8_t key[256] = {0}; + int keyLen = 0; CLIGetHexWithReturn(ctx, 2, key, &keyLen); CLIParserFree(ctx); if (keyLen && keyLen != 16) { PrintAndLogEx(ERR, "Key length must be 16 bytes instead of: %d", keyLen); - return 1; + return PM3_EINVARG; } if (!keyLen) memmove(key, DefaultKey, 16); + uint8_t keyNum[2] = {0}; + uint8_t data[250] = {0}; + int datalen = 0; + int res; + mfpSetVerboseMode(verbose2); for (uint16_t sn = 0x4000; sn < 0x4050; sn++) { keyNum[0] = sn >> 8; keyNum[1] = sn & 0xff; res = MFPWritePerso(keyNum, key, (sn == 0x4000), true, data, sizeof(data), &datalen); if (!res && (datalen == 3) && data[0] == 0x09) { - PrintAndLogEx(INFO, "2k card detected."); + PrintAndLogEx(INFO, "2K card detected."); break; } if (res || (datalen != 3) || data[0] != 0x90) { @@ -574,14 +576,12 @@ static int CmdHFMFPInitPerso(const char *Cmd) { } } } - DropField(); if (res) return res; - PrintAndLogEx(INFO, "Done."); - + PrintAndLogEx(INFO, "Done!"); return PM3_SUCCESS; } @@ -589,17 +589,19 @@ static int CmdHFMFPCommitPerso(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfp commitp", "Executes Commit Perso command. Can be used in SL0 mode only.", - "hf mfp commitp"); + "hf mfp commitp\n" + // "hf mfp commitp --sl 1" + ); void *argtable[] = { arg_param_begin, arg_lit0("v", "verbose", "show internal data."), - arg_int0(NULL, NULL, "SL mode", NULL), +// arg_int0(NULL, "sl", "", "SL mode"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - bool verbose = arg_get_lit(ctx, 1); +// int slmode = arg_get_int(ctx, 2); CLIParserFree(ctx); mfpSetVerboseMode(verbose); @@ -615,15 +617,14 @@ static int CmdHFMFPCommitPerso(const char *Cmd) { if (datalen != 3) { PrintAndLogEx(ERR, "Command must return 3 bytes instead of: %d", datalen); - return 1; + return PM3_EINVARG; } if (data[0] != 0x90) { PrintAndLogEx(ERR, "Command error: %02x %s", data[0], mfpGetErrorDescription(data[0])); - return 1; + return PM3_EINVARG; } - PrintAndLogEx(INFO, "Switch level OK."); - + PrintAndLogEx(INFO, "Switch level ( " _GREEN_("ok") " )"); return PM3_SUCCESS; } @@ -636,14 +637,14 @@ static int CmdHFMFPAuth(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfp auth", "Executes AES authentication command for Mifare Plus card", - "hf mfp auth 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n" - "hf mfp auth 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -v -> executes authentication and shows all the system data"); + "hf mfp auth --ki 4000 --key 000102030405060708090a0b0c0d0e0f -> executes authentication\n" + "hf mfp auth --ki 9003 --key FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -v -> executes authentication and shows all the system data"); void *argtable[] = { arg_param_begin, arg_lit0("v", "verbose", "show internal data."), - arg_str1(NULL, NULL, "", NULL), - arg_str1(NULL, NULL, "", NULL), + arg_str1(NULL, "ki", "", "key number, 2 hex bytes"), + arg_str1(NULL, "key", "", "key, 16 hex bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -654,37 +655,33 @@ static int CmdHFMFPAuth(const char *Cmd) { CLIParserFree(ctx); if (keynlen != 2) { - PrintAndLogEx(ERR, "ERROR: must be 2 bytes long instead of: %d", keynlen); - return 1; + PrintAndLogEx(ERR, "ERROR: must be 2 bytes long instead of: %d", keynlen); + return PM3_EINVARG; } if (keylen != 16) { - PrintAndLogEx(ERR, "ERROR: must be 16 bytes long instead of: %d", keylen); - return 1; + PrintAndLogEx(ERR, "ERROR: must be 16 bytes long instead of: %d", keylen); + return PM3_EINVARG; } return MifareAuth4(NULL, keyn, key, true, false, true, verbose, false); } static int CmdHFMFPRdbl(const char *Cmd) { - uint8_t keyn[2] = {0}; - uint8_t key[250] = {0}; - int keylen = 0; - CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfp rdbl", - "Reads several blocks from Mifare Plus card.", - "hf mfp rdbl 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read block 0 data\n" - "hf mfp rdbl 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data"); + "Reads several blocks from Mifare Plus card", + "hf mfp rdbl --blk 0 --key 000102030405060708090a0b0c0d0e0f -> executes authentication and read block 0 data\n" + "hf mfp rdbl --blk 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF"); void *argtable[] = { arg_param_begin, - arg_lit0("v", "verbose", "show internal data."), - arg_int0("n", "count", "blocks count (by default 1).", NULL), - arg_lit0("b", "keyb", "use key B (by default keyA)."), - arg_lit0("p", "plain", "plain communication mode between reader and card."), - arg_int1(NULL, NULL, "", NULL), - arg_str0(NULL, NULL, "", NULL), + arg_lit0("v", "verbose", "show internal data"), + arg_int0("n", "count", "","blocks count (by default 1)"), + arg_lit0("b", "keyb", "use key B (by default keyA)"), + arg_lit0("p", "plain", "plain communication mode between reader and card"), + arg_int1(NULL, "blk", "", "block number (0..255)"), + arg_str0(NULL, "key", "", "Key, 16 hex bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -694,6 +691,10 @@ static int CmdHFMFPRdbl(const char *Cmd) { bool keyB = arg_get_lit(ctx, 3); int plain = arg_get_lit(ctx, 4); uint32_t blockn = arg_get_int(ctx, 5); + + uint8_t keyn[2] = {0}; + uint8_t key[250] = {0}; + int keylen = 0; CLIGetHexWithReturn(ctx, 6, key, &keylen); CLIParserFree(ctx); @@ -705,19 +706,19 @@ static int CmdHFMFPRdbl(const char *Cmd) { } if (blockn > 255) { - PrintAndLogEx(ERR, " must be in range [0..255] instead of: %d", blockn); - return 1; + PrintAndLogEx(ERR, " must be in range [0..255] instead of: %d", blockn); + return PM3_EINVARG; } if (keylen != 16) { - PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); - return 1; + PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); + return PM3_EINVARG; } // 3 blocks - wo iso14443-4 chaining if (blocksCount > 3) { PrintAndLogEx(ERR, "blocks count must be less than 3 instead of: %d", blocksCount); - return 1; + return PM3_EINVARG; } if (blocksCount > 1 && mfIsSectorTrailer(blockn)) { @@ -749,12 +750,12 @@ static int CmdHFMFPRdbl(const char *Cmd) { if (datalen && data[0] != 0x90) { PrintAndLogEx(ERR, "Card read error: %02x %s", data[0], mfpGetErrorDescription(data[0])); - return 6; + return PM3_ESOFT; } if (datalen != 1 + blocksCount * 16 + 8 + 2) { PrintAndLogEx(ERR, "Error return length:%d", datalen); - return 5; + return PM3_ESOFT; } int indx = blockn; @@ -776,27 +777,23 @@ static int CmdHFMFPRdbl(const char *Cmd) { PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[blocksCount * 16 + 1], 8)); } - return 0; + return PM3_SUCCESS; } static int CmdHFMFPRdsc(const char *Cmd) { - uint8_t keyn[2] = {0}; - uint8_t key[250] = {0}; - int keylen = 0; - CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfp rdsc", - "Reads one sector from Mifare Plus card.", - "hf mfp rdsc 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read sector 0 data\n" - "hf mfp rdsc 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data"); + "Reads one sector from Mifare Plus card", + "hf mfp rdsc --sn 0 --key 000102030405060708090a0b0c0d0e0f -> executes authentication and read sector 0 data\n" + "hf mfp rdsc --sn 1 -v -> executes authentication and shows sector 1 data with default key"); void *argtable[] = { arg_param_begin, - arg_lit0("v", "verbose", "show internal data."), - arg_lit0("b", "keyb", "use key B (by default keyA)."), - arg_lit0("p", "plain", "plain communication mode between reader and card."), - arg_int1(NULL, NULL, "", NULL), - arg_str0(NULL, NULL, "", NULL), + arg_lit0("v", "verbose", "show internal data."), + arg_lit0("b", "keyb", "use key B (by default keyA)."), + arg_lit0("p", "plain", "plain communication mode between reader and card."), + arg_int1(NULL, "sn", "", "sector number (0..255)"), + arg_str0("k", "key", "", "key, 16 hex bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -805,6 +802,9 @@ static int CmdHFMFPRdsc(const char *Cmd) { bool keyB = arg_get_lit(ctx, 2); bool plain = arg_get_lit(ctx, 3); uint32_t sectorNum = arg_get_int(ctx, 4); + uint8_t keyn[2] = {0}; + uint8_t key[250] = {0}; + int keylen = 0; CLIGetHexWithReturn(ctx, 5, key, &keylen); CLIParserFree(ctx); @@ -816,13 +816,13 @@ static int CmdHFMFPRdsc(const char *Cmd) { } if (sectorNum > 39) { - PrintAndLogEx(ERR, " must be in range [0..39] instead of: %d", sectorNum); - return 1; + PrintAndLogEx(ERR, " must be in range [0..39] instead of: %d", sectorNum); + return PM3_EINVARG; } if (keylen != 16) { - PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); - return 1; + PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); + return PM3_EINVARG; } uint16_t uKeyNum = 0x4000 + sectorNum * 2 + (keyB ? 1 : 0); @@ -852,12 +852,12 @@ static int CmdHFMFPRdsc(const char *Cmd) { if (datalen && data[0] != 0x90) { PrintAndLogEx(ERR, "Card read error: %02x %s", data[0], mfpGetErrorDescription(data[0])); DropField(); - return 6; + return PM3_ESOFT; } if (datalen != 1 + 16 + 8 + 2) { PrintAndLogEx(ERR, "Error return length:%d", datalen); DropField(); - return 5; + return PM3_ESOFT; } PrintAndLogEx(INFO, "data[%03d]: %s", n, sprint_hex(&data[1], 16)); @@ -877,25 +877,20 @@ static int CmdHFMFPRdsc(const char *Cmd) { } static int CmdHFMFPWrbl(const char *Cmd) { - uint8_t keyn[2] = {0}; - uint8_t key[250] = {0}; - int keylen = 0; - uint8_t datain[250] = {0}; - int datainlen = 0; - CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfp wrbl", - "Writes one block to Mifare Plus card.", - "hf mfp wrbl 1 ff0000000000000000000000000000ff 000102030405060708090a0b0c0d0e0f -> writes block 1 data\n" - "hf mfp wrbl 2 ff0000000000000000000000000000ff -v -> writes block 2 data with default key 0xFF..0xFF and some additional data"); + "Writes one block to Mifare Plus card", + "hf mfp wrbl --blk 1 -d ff0000000000000000000000000000ff --key 000102030405060708090a0b0c0d0e0f -> writes block 1 data\n" + "hf mfp wrbl --blk 2 -d ff0000000000000000000000000000ff -v -> writes block 2 data with default key 0xFF..0xFF" + ); void *argtable[] = { arg_param_begin, - arg_lit0("v", "verbose", "show internal data."), - arg_lit0("b", "keyb", "use key B (by default keyA)."), - arg_int1(NULL, NULL, "", NULL), - arg_str1(NULL, NULL, "", NULL), - arg_str0(NULL, NULL, "", NULL), + arg_lit0("v", "verbose", "show internal data."), + arg_lit0("b", "keyb", "use key B (by default keyA)."), + arg_int1(NULL, "blk", "", "block number (0..255)"), + arg_str1("d", "data", "", "data, 16 hex bytes"), + arg_str0("k", "key", "", "key, 16 hex bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -903,10 +898,18 @@ static int CmdHFMFPWrbl(const char *Cmd) { bool verbose = arg_get_lit(ctx, 1); bool keyB = arg_get_lit(ctx, 2); uint32_t blockNum = arg_get_int(ctx, 3); + + uint8_t datain[250] = {0}; + int datainlen = 0; CLIGetHexWithReturn(ctx, 4, datain, &datainlen); + + uint8_t key[250] = {0}; + int keylen = 0; CLIGetHexWithReturn(ctx, 5, key, &keylen); CLIParserFree(ctx); + uint8_t keyn[2] = {0}; + mfpSetVerboseMode(verbose); if (!keylen) { @@ -915,18 +918,18 @@ static int CmdHFMFPWrbl(const char *Cmd) { } if (blockNum > 255) { - PrintAndLogEx(ERR, " must be in range [0..255] instead of: %d", blockNum); - return 1; + PrintAndLogEx(ERR, " must be in range [0..255] instead of: %d", blockNum); + return PM3_EINVARG; } if (keylen != 16) { - PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); - return 1; + PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); + return PM3_EINVARG; } if (datainlen != 16) { - PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", datainlen); - return 1; + PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", datainlen); + return PM3_EINVARG; } uint8_t sectorNum = mfSectorNum(blockNum & 0xff); @@ -956,13 +959,13 @@ static int CmdHFMFPWrbl(const char *Cmd) { if (datalen != 3 && (datalen != 3 + 8)) { PrintAndLogEx(ERR, "Error return length:%d", datalen); DropField(); - return 5; + return PM3_ESOFT; } if (datalen && data[0] != 0x90) { PrintAndLogEx(ERR, "Card write error: %02x %s", data[0], mfpGetErrorDescription(data[0])); DropField(); - return 6; + return PM3_ESOFT; } if (memcmp(&data[1], mac, 8)) { @@ -975,7 +978,7 @@ static int CmdHFMFPWrbl(const char *Cmd) { } DropField(); - PrintAndLogEx(INFO, "Write OK."); + PrintAndLogEx(INFO, "Write ( " _GREEN_("ok") " )"); return PM3_SUCCESS; } From 53b42d0069712fe47f9e1729020e6e80d74a3a02 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 15 Apr 2021 23:39:33 +0200 Subject: [PATCH 291/373] adapt text --- client/src/cmdhffido.c | 70 ++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/client/src/cmdhffido.c b/client/src/cmdhffido.c index d3ea8e1cb..d0be26cfd 100644 --- a/client/src/cmdhffido.c +++ b/client/src/cmdhffido.c @@ -176,10 +176,12 @@ static int cmd_hf_fido_register(const char *cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf fido reg", - "Initiate a U2F token registration. Needs two 32-byte hash numbers. \nchallenge parameter (32b) and application parameter (32b).", - "hf fido reg -> execute command with 2 parameters, filled 0x00\n" - "hf fido reg 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters\n" - "hf fido reg -p s0 s1 -> execute command with plain parameters"); + "Initiate a U2F token registration. Needs two 32-byte hash numbers.\n" + "challenge parameter (32b) and application parameter (32b).", + "hf fido reg -> execute command with 2 parameters, filled 0x00\n" + "hf fido reg -p s0 s1 -> execute command with plain parameters\n" + "hf fido reg --cp 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f --ap 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f\n" + ); void *argtable[] = { arg_param_begin, @@ -188,8 +190,8 @@ static int cmd_hf_fido_register(const char *cmd) { arg_lit0("p", "plain", "send plain ASCII to challenge and application parameters instead of HEX"), arg_lit0("t", "tlv", "Show DER certificate contents in TLV representation"), arg_str0("j", "json", "fido.json", "JSON input / output file name for parameters."), - arg_str0(NULL, NULL, "", NULL), - arg_str0(NULL, NULL, "", NULL), + arg_str0(NULL, "cp", "", "challenge parameter (32 bytes hex / 1..16 chars)"), + arg_str0(NULL, "ap", "", "application parameter (32 bytes hex / 1..16 chars)"), arg_param_end }; CLIExecWithReturn(ctx, cmd, argtable, true); @@ -418,10 +420,13 @@ static int cmd_hf_fido_authenticate(const char *cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf fido auth", - "Initiate a U2F token authentication. Needs key handle and two 32-byte hash numbers. \nkey handle(var 0..255), challenge parameter (32b) and application parameter (32b).", - "hf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n" - "hf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f " - "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters"); + "Initiate a U2F token authentication. Needs key handle and two 32-byte hash numbers.\n" + "key handle(var 0..255), challenge parameter (32b) and application parameter (32b)", + "hf fido auth --kh 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n" + "hf fido auth \n" + "--kh 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f\n" + "--cp 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f \n" + "--ap 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters"); void *argtable[] = { arg_param_begin, @@ -432,10 +437,10 @@ static int cmd_hf_fido_authenticate(const char *cmd) { arg_lit0("u", "user", "mode: enforce-user-presence-and-sign"), arg_lit0("c", "check", "mode: check-only"), arg_str0("j", "json", "fido.json", "JSON input / output file name for parameters."), - arg_str0("k", "key", "public key to verify signature", NULL), - arg_str0(NULL, NULL, "", NULL), - arg_str0(NULL, NULL, "", NULL), - arg_str0(NULL, NULL, "", NULL), + arg_str0("k", "key", "", "public key to verify signature"), + arg_str0(NULL, "kh", "", "key handle (var 0..255b)"), + arg_str0(NULL, "cp", "", "challenge parameter (32 bytes hex / 1..16 chars)"), + arg_str0(NULL, "ap", "", "application parameter (32 bytes hex / 1..16 chars)"), arg_param_end }; CLIExecWithReturn(ctx, cmd, argtable, true); @@ -684,17 +689,19 @@ static int cmd_hf_fido_2make_credential(const char *cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf fido make", - "Execute a FIDO2 Make Credential command. Needs json file with parameters. Sample file `fido2.json` in `resources/`.", - "hf fido make -> execute command with default parameters file `fido2.json`\n" - "hf fido make test.json -> execute command with parameters file `text.json`"); + "Execute a FIDO2 Make Credential command. Needs json file with parameters.\n" + "Sample file `fido2.json` in `client/resources/`.", + "hf fido make -> default parameters file `fido2.json`\n" + "hf fido make -f test.json -> use parameters file `text.json`" + ); void *argtable[] = { arg_param_begin, - arg_lit0("a", "apdu", "show APDU reqests and responses"), - arg_litn("v", "verbose", 0, 2, "show technical data. vv - show full certificates data"), - arg_lit0("t", "tlv", "Show DER certificate contents in TLV representation"), - arg_lit0("c", "cbor", "show CBOR decoded data"), - arg_str0(NULL, NULL, "", "JSON input / output file name for parameters. Default `fido2.json`"), + arg_lit0("a", "apdu", "show APDU reqests and responses"), + arg_litn("v", "verbose", 0, 2, "show technical data. vv - show full certificates data"), + arg_lit0("t", "tlv", "Show DER certificate contents in TLV representation"), + arg_lit0("c", "cbor", "show CBOR decoded data"), + arg_str0("f", "file", "", "parameter JSON file name. (def `fido2.json`)"), arg_param_end }; CLIExecWithReturn(ctx, cmd, argtable, true); @@ -810,17 +817,20 @@ static int cmd_hf_fido_2get_assertion(const char *cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf fido assert", - "Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file `fido2.json` in `resources/`.", - "hf fido assert -> execute command with default parameters file `fido2.json`\n" - "hf fido assert test.json -l -> execute command with parameters file `text.json` and add to request CredentialId"); + "Execute a FIDO2 Get Assertion command. Needs json file with parameters.\n" + "Sample file `fido2.json` in `client/resources/`.\n" + "- Needs if `rk` option is `false` (authenticator doesn't store credential to its memory)" + , + "hf fido assert -> default parameters file `fido2.json`\n" + "hf fido assert -f test.json -l -> use parameters file `text.json` and add to request CredentialId"); void *argtable[] = { arg_param_begin, - arg_lit0("a", "apdu", "show APDU reqests and responses"), - arg_litn("v", "verbose", 0, 2, "show technical data. vv - show full certificates data"), - arg_lit0("c", "cbor", "show CBOR decoded data"), - arg_lit0("l", "list", "add CredentialId from json to allowList. Needs if `rk` option is `false` (authenticator doesn't store credential to its memory)"), - arg_str0(NULL, NULL, "", "JSON input / output file name for parameters. Default `fido2.json`"), + arg_lit0("a", "apdu", "show APDU reqests and responses"), + arg_litn("v", "verbose", 0, 2, "show technical data. vv - show full certificates data"), + arg_lit0("c", "cbor", "show CBOR decoded data"), + arg_lit0("l", "list", "add CredentialId from json to allowList."), + arg_str0("f", "file", "", "parameter JSON file name. (def `fido2.json`)"), arg_param_end }; CLIExecWithReturn(ctx, cmd, argtable, true); From e426699c5d3889a75a06a1e882edad79bf9c4cab Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 00:00:02 +0200 Subject: [PATCH 292/373] forgotten --- client/src/cmdhf.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index 5183ee739..a4c5b2544 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -86,7 +86,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, " Searching for ISO14443-A tag..."); if (IfPm3Iso14443a()) { if (infoHF14A(false, false, false) > 0) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-A tag") " found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 14443-A tag") " found\n"); res = PM3_SUCCESS; } } @@ -95,7 +95,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, " Searching for ISO15693 tag..."); if (IfPm3Iso15693()) { if (readHF15Uid(false, false)) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO15693 tag") " found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 15693 tag") " found\n"); res = PM3_SUCCESS; } } @@ -131,7 +131,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, " Searching for FeliCa tag..."); if (IfPm3Felica()) { if (read_felica_uid(false, false) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO18092 / FeliCa tag") " found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 18092 / FeliCa tag") " found\n"); res = PM3_SUCCESS; } } @@ -140,8 +140,8 @@ int CmdHFSearch(const char *Cmd) { PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, " Searching for ISO14443-B tag..."); if (IfPm3Iso14443b()) { - if (readHF14B(false) == 1) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-B tag") " found\n"); + if (readHF14B(false, false) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 14443-B tag") " found\n"); res = PM3_SUCCESS; } } From a9c75a400fb23897c309952117c207863058bf8e Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 16 Apr 2021 00:07:30 +0200 Subject: [PATCH 293/373] typo --- doc/magic_cards_notes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/magic_cards_notes.md b/doc/magic_cards_notes.md index dc3a5f564..9982efbe0 100644 --- a/doc/magic_cards_notes.md +++ b/doc/magic_cards_notes.md @@ -195,7 +195,7 @@ hf mf csetuid -u 11223344 -a 0044 -s 18 ``` ``` -script run run hf_mf_magicrevive +script run hf_mf_magicrevive ``` To execute commands manually: @@ -538,7 +538,7 @@ When "soft-bricked" (by writing invalid data in block0), these ones may help: ``` hf 14a config -h -script run run hf_mf_magicrevive -u +script run hf_mf_magicrevive -u ``` ## MIFARE Ultralight DirectWrite From 046f8f50ead658ffaa114ce91a247b68f337274d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 16 Apr 2021 00:09:11 +0200 Subject: [PATCH 294/373] typo --- client/src/cmdhf14b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index ebce7126a..45777fdce 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -263,7 +263,7 @@ static int CmdHF14BSniff(const char *Cmd) { WaitForResponse(CMD_HF_ISO14443B_SNIFF, &resp); PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 14b list") "` to view captured tracelog"); - PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save h") "` to save tracelog for later analysing"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -h") "` to save tracelog for later analysing"); return PM3_SUCCESS; } From f63125386bb7dfe3c9ca1e92bcbb3e82ff0bbd7b Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 16 Apr 2021 00:13:36 +0200 Subject: [PATCH 295/373] typos --- armsrc/Standalone/hf_14asniff.c | 4 ++-- client/src/cmdhf15.c | 2 +- client/src/cmdhffelica.c | 2 +- doc/magic_cards_notes.md | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/armsrc/Standalone/hf_14asniff.c b/armsrc/Standalone/hf_14asniff.c index 56a7c0cab..cd4c10c97 100644 --- a/armsrc/Standalone/hf_14asniff.c +++ b/armsrc/Standalone/hf_14asniff.c @@ -37,8 +37,8 @@ * 2. trace load trace.trc * Loads trace data from a file into PC-side buffers. * - * 3. For ISO14a: trace list 14a 1 - * For MIFARE Classic: trace list mf 1 + * 3. For ISO14a: trace list -t 14a -1 + * For MIFARE Classic: trace list -t mf -1 * * Lists trace data from buffer without requesting it from PM3. * diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index cf083332c..6c3a854fb 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -954,7 +954,7 @@ static int CmdHF15Sniff(const char *Cmd) { WaitForResponse(CMD_HF_ISO15693_SNIFF, &resp); PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 15 list") "` to view captured tracelog"); - PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save h") "` to save tracelog for later analysing"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -h") "` to save tracelog for later analysing"); return PM3_SUCCESS; } diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 7a576c946..d2ce89fa6 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -1935,7 +1935,7 @@ static int CmdHFFelicaDumpLite(const char *Cmd) { iceman 2021, Why does this command say it dumps a FeliCa lite card and then tries to print a trace?!? - Is this a trace list or a feclia dump cmd? + Is this a trace list or a FeliCa dump cmd? */ diff --git a/doc/magic_cards_notes.md b/doc/magic_cards_notes.md index 9982efbe0..8e1edbaac 100644 --- a/doc/magic_cards_notes.md +++ b/doc/magic_cards_notes.md @@ -499,9 +499,9 @@ BCC1 Int LCK0 LCK1 UID is made of SN0..SN6 bytes -Computing BCC0 on UID 04112233445566: `analyse lcr 88041122` = `bf` +Computing BCC0 on UID 04112233445566: `analyse lcr -d 88041122` = `bf` -Computing BCC1 on UID 04112233445566: `analyse lcr 33445566` = `44` +Computing BCC1 on UID 04112233445566: `analyse lcr -d 33445566` = `44` Int is internal, typically 0x48 From 568d7cc1d4e03f7a830bc215dd406b5310ce50aa Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 00:13:44 +0200 Subject: [PATCH 296/373] this script suffers much. its not designed to use --paramss in the calls to the pm3 client --- client/luascripts/multi_bruteforce.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/luascripts/multi_bruteforce.lua b/client/luascripts/multi_bruteforce.lua index e9b320058..a2723a44c 100644 --- a/client/luascripts/multi_bruteforce.lua +++ b/client/luascripts/multi_bruteforce.lua @@ -3,7 +3,7 @@ local ansicolors = require('ansicolors') copyright = '' author = 'Kenzy Carey' -version = 'v1.0.2' +version = 'v1.0.3' desc = [[ .-----------------------------------------------------------------. @@ -193,7 +193,7 @@ local function main(args) rfidtagname = 'Noralsy' facilityrequired = 0 elseif rfidtag == 'presco' then - consolecommand = 'lf presco sim d' + consolecommand = 'lf presco sim -d' rfidtagname = 'Presco' facilityrequired = 0 elseif rfidtag == 'visa2000' then @@ -201,7 +201,7 @@ local function main(args) rfidtagname = 'Visa2000' facilityrequired = 0 elseif rfidtag == '14a' then - consolecommand = 'hf 14a sim' + consolecommand = 'hf 14a sim -t' if facility == '1' then rfidtagname = 'MIFARE Classic' -- Here we use the -f option to read the 14a type instead of the facility code elseif facility == '2' then rfidtagname = 'MIFARE Ultralight' elseif facility == '3' then rfidtagname = 'MIFARE Desfire' From 83339d0a45455ffcc84e1d2a097cbeb35d64bed6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 00:15:43 +0200 Subject: [PATCH 297/373] text --- client/cmdscripts/test_psk_clone.cmd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdscripts/test_psk_clone.cmd b/client/cmdscripts/test_psk_clone.cmd index 784fecd1e..834106f91 100644 --- a/client/cmdscripts/test_psk_clone.cmd +++ b/client/cmdscripts/test_psk_clone.cmd @@ -2,13 +2,13 @@ clear rem Test of Motorola clone & read lf t55xx wipe -lf motorola clone a0000000a0002021 +lf motorola clone --raw a0000000a0002021 lf motorola read lf search rem Test of Nexwatch clone & read lf t55xx wipe -lf nexwatch clone c 1337 m 1 n +lf nexwatch clone --cn 1337 -m 1 -n lf nexwatch read lf search From 741cdfc383a762257370090ea7842c7aab03598f Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 16 Apr 2021 00:21:22 +0200 Subject: [PATCH 298/373] typos --- armsrc/hitag2.c | 2 +- doc/cloner_notes.md | 2 +- tools/hitag2crack/README.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 07feb80e0..72211b037 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1897,7 +1897,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false); -// TODO when using cumulative time for command_start, pm3 doesn't reply anymore, e.g. on lf hitag read 23 4F4E4D494B52 +// TODO when using cumulative time for command_start, pm3 doesn't reply anymore, e.g. on lf hitag reader --23 -k 4F4E4D494B52 // Use delta time? // command_start = response_start + response_duration; command_start = 0; diff --git a/doc/cloner_notes.md b/doc/cloner_notes.md index 77edc244b..78f7b360e 100644 --- a/doc/cloner_notes.md +++ b/doc/cloner_notes.md @@ -79,4 +79,4 @@ 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. -As normal, the cloner may write data past the end of the 40K sample buffer. So using the `lf config s ` then re-run the sniff to see if there is more data. \ No newline at end of file +As normal, the cloner may write data past the end of the 40K sample buffer. So using the `lf config -s ` then re-run the sniff to see if there is more data. \ No newline at end of file diff --git a/tools/hitag2crack/README.md b/tools/hitag2crack/README.md index 2d38de395..72fd6baa6 100644 --- a/tools/hitag2crack/README.md +++ b/tools/hitag2crack/README.md @@ -167,7 +167,7 @@ response pairs for the same tag UID. **TODO** will be ht2 sim or sniff with actual tag ? ``` -pm3 --> lf hitag sniff l +pm3 --> lf hitag sniff ``` It creates a file `Hitag2____collection.txt`. @@ -184,7 +184,7 @@ Attack 4 requires the same information as attack 3, but only 16-32 encrypted nonce and challenge response pairs are required. ``` -pm3 --> lf hitag sniff l +pm3 --> lf hitag sniff ``` It creates a file `Hitag2____collection.txt`. From c2a6d6fc42d71ecf01f66ceda16cc234bf2c2a21 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 00:23:17 +0200 Subject: [PATCH 299/373] text --- client/luascripts/hf_mf_dump-luxeo.lua | 9 +++++---- client/luascripts/hf_mf_mini_dumpdecrypt.lua | 6 +++--- client/luascripts/hf_mf_tnp3_dump.lua | 6 +++--- client/luascripts/hf_mf_tnp3_sim.lua | 4 ++-- client/luascripts/hf_ntag-3d.lua | 14 +++++++------- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/client/luascripts/hf_mf_dump-luxeo.lua b/client/luascripts/hf_mf_dump-luxeo.lua index 70f1b42e0..8659dcd9b 100644 --- a/client/luascripts/hf_mf_dump-luxeo.lua +++ b/client/luascripts/hf_mf_dump-luxeo.lua @@ -12,9 +12,10 @@ local ansicolors = require('ansicolors') copyright = '' author = '0xdrrb' -version = 'v0.1.1' +version = 'v0.1.2' desc = [[ -This is a script that tries to dump and decrypt the data of a specific type of Mifare laundromat token. OBS! Tag must be on the antenna. +This is a script that tries to dump and decrypt the data of a specific type of Mifare laundromat token. +OBS! Tag must be on the antenna. ]] example = [[ script run hf_mf_dump-luxeo @@ -69,9 +70,9 @@ end local function setdevicedebug( status ) local c = 'hw dbg ' if status then - c = c..'1' + c = c..'-1' else - c = c..'0' + c = c..'-0' end core.console(c) end diff --git a/client/luascripts/hf_mf_mini_dumpdecrypt.lua b/client/luascripts/hf_mf_mini_dumpdecrypt.lua index ec6006ed2..c75b92304 100644 --- a/client/luascripts/hf_mf_mini_dumpdecrypt.lua +++ b/client/luascripts/hf_mf_mini_dumpdecrypt.lua @@ -10,7 +10,7 @@ local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.2' +version = 'v1.0.3' desc = [[ This is a script to dump and decrypt the data of a specific type of Mifare Mini token. The dump is decrypted. If a raw dump is wanted, use the -r parameter @@ -557,9 +557,9 @@ end local function setdevicedebug( status ) local c = 'hw dbg ' if status then - c = c..'1' + c = c..'-1' else - c = c..'0' + c = c..'-0' end core.console(c) end diff --git a/client/luascripts/hf_mf_tnp3_dump.lua b/client/luascripts/hf_mf_tnp3_dump.lua index 54a19da82..8e6a6bfb3 100644 --- a/client/luascripts/hf_mf_tnp3_dump.lua +++ b/client/luascripts/hf_mf_tnp3_dump.lua @@ -10,7 +10,7 @@ local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.2' +version = 'v1.0.3' desc = [[ This script will try to dump the contents of a Mifare TNP3xxx card. It will need a valid KeyA in order to find the other keys and decode the card. @@ -112,7 +112,7 @@ local function main(args) local keyA, cmd, err local useNested = false local usePreCalc = false - local cmdReadBlockString = 'hf mf rdbl %d A %s' + local cmdReadBlockString = 'hf mf rdbl --blk %d -k %s' local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S"); -- Arguments for the script @@ -131,7 +131,7 @@ local function main(args) end -- Turn off Debug - local cmdSetDbgOff = "hw dbg 0" + local cmdSetDbgOff = "hw dbg -0" core.console( cmdSetDbgOff) utils.Sleep(0.5) diff --git a/client/luascripts/hf_mf_tnp3_sim.lua b/client/luascripts/hf_mf_tnp3_sim.lua index 33f82b2d4..2351bf1d5 100644 --- a/client/luascripts/hf_mf_tnp3_sim.lua +++ b/client/luascripts/hf_mf_tnp3_sim.lua @@ -10,7 +10,7 @@ local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.2' +version = 'v1.0.3' desc = [[ This script will try to load a binary datadump of a Mifare TNP3xxx card. It will try to validate all checksums and view some information stored in the dump @@ -372,7 +372,7 @@ local function main(args) end -- Turn off Debug - local cmdSetDbgOff = 'hw dbg 0' + local cmdSetDbgOff = 'hw dbg -0' core.console( cmdSetDbgOff) utils.Sleep(0.5) diff --git a/client/luascripts/hf_ntag-3d.lua b/client/luascripts/hf_ntag-3d.lua index e46705bd1..1ee21fe37 100644 --- a/client/luascripts/hf_ntag-3d.lua +++ b/client/luascripts/hf_ntag-3d.lua @@ -5,7 +5,7 @@ local ansicolors = require('ansicolors') copyright = 'Copyright (c) 2017 IceSQL AB. All rights reserved.' author = "Christian Herrmann" -version = 'v1.0.5' +version = 'v1.0.6' desc = [[ This script writes a empty template for 3D printing system onto a empty NTAG213 or MAGIC NTAG21* @@ -189,25 +189,25 @@ end local function write_tag(uid, t) print('Writing to tag') - core.console('hw dbg 0') + core.console('hw dbg -0') utils.Sleep(0.5) local cmd = '' local pwd, pack = core.keygen_algo_d(uid) for i= 8, 23 do - cmd = ('hf mfu wrbl b %02d d %s k %08X'):format(i, t[i], pwd) + cmd = ('hf mfu wrbl --blk %02d -d %s -k %08X'):format(i, t[i], pwd) core.console(cmd) end --cfg1 - core.console(('hf mfu wrbl b 42 d %s k %08X'):format(t[42], pwd)) + core.console(('hf mfu wrbl --blk 42 -d %s -k %08X'):format(t[42], pwd)) --cfg0 - core.console(('hf mfu wrbl b 41 d %s k %08X'):format(t[41], pwd)) + core.console(('hf mfu wrbl --blk 41 -d %s -k %08X'):format(t[41], pwd)) --dynamic - core.console(('hf mfu wrbl b 40 d %s k %08X'):format(t[40], pwd)) + core.console(('hf mfu wrbl --blk 40 -d %s -k %08X'):format(t[40], pwd)) - core.console('hw dbg 1') + core.console('hw dbg -1') utils.Sleep(0.5) print('Done') end From 9ebdce957604adbb7ec24d7240695a1ac7a22f66 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 16 Apr 2021 00:30:52 +0200 Subject: [PATCH 300/373] fix hardnested test in pm3_tests --- tools/pm3_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pm3_tests.sh b/tools/pm3_tests.sh index da5ea56a5..572bbc10a 100755 --- a/tools/pm3_tests.sh +++ b/tools/pm3_tests.sh @@ -460,7 +460,7 @@ while true; do echo -e "\n${C_BLUE}Testing HF:${C_NC}" if ! CheckExecute "hf mf offline text" "$CLIENTBIN -c 'hf mf'" "at_enc"; then break; fi - if ! CheckExecute slow retry ignore "hf mf hardnested long test" "$CLIENTBIN -c 'hf mf hardnested t 1 000000000000'" "found:"; then break; fi + if ! CheckExecute slow retry ignore "hf mf hardnested long test" "$CLIENTBIN -c 'hf mf hardnested -t --tk 000000000000'" "found:"; then break; fi if ! CheckExecute slow "hf iclass long test" "$CLIENTBIN -c 'hf iclass loclass --long'" "verified (ok)"; then break; fi if ! CheckExecute slow "emv long test" "$CLIENTBIN -c 'emv test -l'" "Test(s) \[ ok"; then break; fi if ! $SLOWTESTS; then From 4c8aada66b9c0225506a6f327b7313c839350c07 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 00:44:50 +0200 Subject: [PATCH 301/373] text and rework --- client/src/cmdhfmf.c | 115 +++++++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 54 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index f122e58e3..a616de444 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -50,15 +50,13 @@ static int usage_hf14_keybrute(void) { PrintAndLogEx(NORMAL, "First 2 bytes of key will be bruteforced"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " ---[ This attack is obsolete, try hardnested instead ]---"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf keybrute [h] "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " target block number"); PrintAndLogEx(NORMAL, " target key type"); PrintAndLogEx(NORMAL, " candidate key from mf_nonce_brute tool"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf mf keybrute 1 A 000011223344")); + PrintAndLogEx(NORMAL, _YELLOW_(" hf mf keybrute --blk 1 -k 000011223344")); return 0; } */ @@ -3841,7 +3839,7 @@ int CmdHF14AMfELoad(const char *Cmd) { PrintAndLogEx(NORMAL, "\n"); if (block_width == 4) { - PrintAndLogEx(HINT, "You are ready to simulate. See " _YELLOW_("`hf mfu sim h`")); + PrintAndLogEx(HINT, "You are ready to simulate. See " _YELLOW_("`hf mfu sim -h`")); // MFU / NTAG if ((cnt != block_cnt)) { PrintAndLogEx(WARNING, "Warning, Ultralight/Ntag file content, Loaded %d blocks of expected %d blocks into emulator memory", cnt, block_cnt); @@ -5432,74 +5430,79 @@ static int CmdHFMFNDEF(const char *Cmd) { } static int CmdHFMFPersonalize(const char *cmd) { - CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf personalize", - "Personalize the UID of a MIFARE Classic EV1 card. This is only possible if it is a 7Byte UID card and if it is not already personalized.", - "hf mf personalize UIDF0 -> double size UID according to ISO/IEC14443-3\n" - "hf mf personalize UIDF1 -> double size UID according to ISO/IEC14443-3, optional usage of selection process shortcut\n" - "hf mf personalize UIDF2 -> single size random ID according to ISO/IEC14443-3\n" - "hf mf personalize UIDF3 -> single size NUID according to ISO/IEC14443-3\n" - "hf mf personalize -t B -k B0B1B2B3B4B5 UIDF3 -> use key B = 0xB0B1B2B3B4B5 instead of default key A"); + "Personalize the UID of a MIFARE Classic EV1 card. This is only possible \n" + "if it is a 7Byte UID card and if it is not already personalized.", + "hf mf personalize -f0 -> double size UID\n" + "hf mf personalize -f1 -> double size UID, optional usage of selection process shortcut\n" + "hf mf personalize -f2 -> single size random ID\n" + "hf mf personalize -f3 -> single size NUID\n" + "hf mf personalize -b -k B0B1B2B3B4B5 -f3 -> use key B = 0xB0B1B2B3B4B5" + ); void *argtable[] = { arg_param_begin, - arg_str0("t", "keytype", "", "key type (A or B) to authenticate sector 0 (default: A)"), - arg_str0("k", "key", "", "key to authenticate sector 0 (default: FFFFFFFFFFFF)"), - arg_str1(NULL, NULL, "", "Personalization Option"), + arg_lit0("a", NULL, "use key A to authenticate sector 0 (def)"), + arg_lit0("b", NULL, "use key B to authenticate sector 0"), + arg_str0("k", "key", "", "key (def FFFFFFFFFFFF)"), + arg_lit0(NULL, "f0", "UIDFO, double size UID"), + arg_lit0(NULL, "f1", "UIDF1, double size UID, optional usage of selection process shortcut"), + arg_lit0(NULL, "f2", "UIDF2, single size random ID"), + arg_lit0(NULL, "f3", "UIDF3, single size NUID"), arg_param_end }; CLIExecWithReturn(ctx, cmd, argtable, true); - char keytypestr[2] = "a"; - uint8_t keytype = 0x00; - int keytypestr_len; - int res = CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)keytypestr, 1, &keytypestr_len); - str_lower(keytypestr); + bool use_a = arg_get_lit(ctx, 1); + bool use_b = arg_get_lit(ctx, 2); - if (res || (keytypestr[0] != 'a' && keytypestr[0] != 'b')) { - PrintAndLogEx(ERR, "ERROR: not a valid key type. Key type must be A or B"); + if (use_a + use_b > 1) { + PrintAndLogEx(ERR, "error, use only one key type"); CLIParserFree(ctx); return PM3_EINVARG; } - if (keytypestr[0] == 'b') { - keytype = 0x01; + + uint8_t keytype = 0; + if (use_b) { + keytype = 1; } uint8_t key[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; int key_len; - res = CLIParamHexToBuf(arg_get_str(ctx, 2), key, 6, &key_len); - if (res || (!res && key_len > 0 && key_len != 6)) { + int res = CLIParamHexToBuf(arg_get_str(ctx, 3), key, 6, &key_len); + if (res || (!res && key_len && key_len != 6)) { PrintAndLogEx(ERR, "ERROR: not a valid key. Key must be 12 hex digits"); CLIParserFree(ctx); return PM3_EINVARG; } - char pers_optionstr[6]; - int opt_len; - uint8_t pers_option; - res = CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)pers_optionstr, 5, &opt_len); - str_lower(pers_optionstr); - - if (res || (!res && opt_len > 0 && opt_len != 5) - || (strncmp(pers_optionstr, "uidf0", 5) && strncmp(pers_optionstr, "uidf1", 5) && strncmp(pers_optionstr, "uidf2", 5) && strncmp(pers_optionstr, "uidf3", 5))) { - PrintAndLogEx(ERR, "ERROR: invalid personalization option. Must be one of UIDF0, UIDF1, UIDF2, or UIDF3"); - CLIParserFree(ctx); - return PM3_EINVARG; - } - if (!strncmp(pers_optionstr, "uidf0", 5)) { - pers_option = MIFARE_EV1_UIDF0; - } else if (!strncmp(pers_optionstr, "uidf1", 5)) { - pers_option = MIFARE_EV1_UIDF1; - } else if (!strncmp(pers_optionstr, "uidf2", 5)) { - pers_option = MIFARE_EV1_UIDF2; - } else { - pers_option = MIFARE_EV1_UIDF3; - } - + bool f0 = arg_get_lit(ctx, 4); + bool f1 = arg_get_lit(ctx, 5); + bool f2 = arg_get_lit(ctx, 6); + bool f3 = arg_get_lit(ctx, 7); CLIParserFree(ctx); - clearCommandBuffer(); + uint8_t tmp = f0 + f1 + f2 + f3; + if (tmp > 1) { + PrintAndLogEx(WARNING, "select only one key type"); + return PM3_EINVARG; + } + if (tmp == 0) { + PrintAndLogEx(WARNING, "select one key type"); + return PM3_EINVARG; + } + + uint8_t pers_option = MIFARE_EV1_UIDF3; + if (f0) { + pers_option = MIFARE_EV1_UIDF0; + } else if (f1) { + pers_option = MIFARE_EV1_UIDF1; + } else if (f2) { + pers_option = MIFARE_EV1_UIDF2; + } + + CLIParserFree(ctx); struct { uint8_t keytype; @@ -5508,16 +5511,20 @@ static int CmdHFMFPersonalize(const char *cmd) { } PACKED payload; payload.keytype = keytype; payload.pers_option = pers_option; + memcpy(payload.key, key, sizeof(payload.key)); - memcpy(payload.key, key, 6); - + clearCommandBuffer(); SendCommandNG(CMD_HF_MIFARE_PERSONALIZE_UID, (uint8_t *)&payload, sizeof(payload)); - PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_HF_MIFARE_PERSONALIZE_UID, &resp, 2500)) return PM3_ETIMEOUT; - - PrintAndLogEx(SUCCESS, "Personalization %s", resp.status == PM3_SUCCESS ? "SUCCEEDED" : "FAILED"); + if (WaitForResponseTimeout(CMD_HF_MIFARE_PERSONALIZE_UID, &resp, 2500) == false) { + return PM3_ETIMEOUT; + } + if ( resp.status == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "Personalization ( %s )", _GREEN_("ok")); + } else { + PrintAndLogEx(FAILED, "Personalization ( %s )", _RED_("fail")); + } return PM3_SUCCESS; } From 4814b67e1775fc8720fecfd49618074e624b4221 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 16 Apr 2021 00:47:53 +0200 Subject: [PATCH 302/373] change pm3_tests mf_nonce_brute test --- tools/pm3_tests.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/pm3_tests.sh b/tools/pm3_tests.sh index 572bbc10a..0cd468f9a 100755 --- a/tools/pm3_tests.sh +++ b/tools/pm3_tests.sh @@ -263,7 +263,8 @@ while true; do if $TESTALL || $TESTMFNONCEBRUTE; then echo -e "\n${C_BLUE}Testing mf_nonce_brute:${C_NC} ${MFNONCEBRUTEBIN:=./tools/mf_nonce_brute/mf_nonce_brute}" if ! CheckFileExist "mf_nonce_brute exists" "$MFNONCEBRUTEBIN"; then break; fi - if ! CheckExecute slow "mf_nonce_brute test" "$MFNONCEBRUTEBIN 9c599b32 5a920d85 1011 98d76b77 d6c6e870 0000 ca7e0b63 0111 3e709c8a" "Key.*: \[ffffffffffff\]"; then break; fi +# if ! CheckExecute slow "mf_nonce_brute test" "$MFNONCEBRUTEBIN 9c599b32 5a920d85 1011 98d76b77 d6c6e870 0000 ca7e0b63 0111 3e709c8a" "Key found \[.*ffffffffffff.*\]"; then break; fi + if ! CheckExecute slow "mf_nonce_brute test" "$MFNONCEBRUTEBIN 96519578 d7e3c6ac 0011 cd311951 9da49e49 0010 2bb22e00 0100 a4f7f398" "Key found \[.*3b7e4fd575ad.*\]"; then break; fi fi # hitag2crack not yet part of "all" # if $TESTALL || $TESTHITAG2CRACK; then From ad7a0ccf1f1e81fb24380a9f12b5dc3b42de21f3 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 16 Apr 2021 00:58:07 +0200 Subject: [PATCH 303/373] typos --- armsrc/Standalone/hf_14asniff.c | 2 +- armsrc/Standalone/hf_legic.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/Standalone/hf_14asniff.c b/armsrc/Standalone/hf_14asniff.c index cd4c10c97..16d351ef0 100644 --- a/armsrc/Standalone/hf_14asniff.c +++ b/armsrc/Standalone/hf_14asniff.c @@ -31,7 +31,7 @@ * * To retrieve trace data from flash: * - * 1. mem spiffs dump o hf_14asniff.trc f trace.trc + * 1. mem spiffs dump -s hf_14asniff.trc -d trace.trc * Copies trace data file from flash to your PC. * * 2. trace load trace.trc diff --git a/armsrc/Standalone/hf_legic.c b/armsrc/Standalone/hf_legic.c index 40174ce87..aa694b029 100644 --- a/armsrc/Standalone/hf_legic.c +++ b/armsrc/Standalone/hf_legic.c @@ -30,7 +30,7 @@ * * To retrieve dump files from flash: * - * 1. mem spiffs dump o hf-legic-XXYYZZWW-dump.bin f hf-legic-XXYYZZWW-dump.bin + * 1. mem spiffs dump -s hf-legic-XXYYZZWW-dump.bin -d hf-legic-XXYYZZWW-dump.bin * Copies log file from flash to your client. * * From 25521f131f5fdd9f5831396f6cffec9a394a4a38 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 16 Apr 2021 01:02:12 +0200 Subject: [PATCH 304/373] typos --- doc/uart_notes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/uart_notes.md b/doc/uart_notes.md index d34ed1a6d..9e71c3dbf 100644 --- a/doc/uart_notes.md +++ b/doc/uart_notes.md @@ -34,7 +34,7 @@ This USART can be reached from the host client (if connected via USB-CDC) throug * `usart config`, to configure the baudrate and the parity of the Proxmark3 USART * `usart txrx/tx/rx/txhex/rxhex` to transmit and receive bytes -So, `usart config` changes the Proxmark3 USART baudrate and parity, while e.g. `usart txrx d AT+Px` and `usart txrx d AT+BAUDx` changes the BT add-on parity and baudrate. +So, `usart config` changes the Proxmark3 USART baudrate and parity, while e.g. `usart txrx -d "AT+Px"` and `usart txrx -d "AT+BAUDx"` changes the BT add-on parity and baudrate. And for things to work fine, both sets have to match! Internally, the desired baudrate is converted to UART settings: a BRGR and a FP. The resulting baudrate will be close to but not always equal to the desired baudrate. Serial ports typically have some error tolerance in the actual baudrates. Theoretically < 2.5% on each side (so 5% in total), < 2% to be on the safe side. In the current firmware configuration, the Proxmark3 can provide any baudrate up to 2Mbauds with an error of max 2%, and selected baudrates up to 6Mbauds (tested with a FTDI C232HM DDHSL-0 cable). @@ -51,7 +51,7 @@ Some specific commands are available when you add `BTADDON` to `PLATFORM_EXTRAS` `usart btfactory` changes several times the Proxmark3 USART baudrate and parity till it matches the BT add-on settings, then changes the baudrate and parity of the add-on to a default value, then changes the Proxmark USART to the same default values, so everything should be back in order. (`btfactory` does more but we're only interested in baudrate in this discussion) -Manual configuration is also possible with `usart txrx d AT+Px` and `usart txrx d AT+BAUDx`. +Manual configuration is also possible with `usart txrx -d "AT+Px"` and `usart txrx -d "AT+BAUDx"`. ### BT add-on connected mode From 8f3f868e81483b5aecc6c59033da27bd5e8f1e08 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 01:03:34 +0200 Subject: [PATCH 305/373] text --- client/luascripts/lf_em_tearoff_protect.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/luascripts/lf_em_tearoff_protect.lua b/client/luascripts/lf_em_tearoff_protect.lua index 8d18ec5da..ed2dcf5f1 100644 --- a/client/luascripts/lf_em_tearoff_protect.lua +++ b/client/luascripts/lf_em_tearoff_protect.lua @@ -6,7 +6,7 @@ author = [[ 'Author Iceman CoAuthor Doegox ]] -version = 'v1.0.1' +version = 'v1.0.2' desc = [[ This is scripts loops though a tear attack and reads expected value. ]] @@ -37,7 +37,7 @@ arguments = [[ ]] local set_tearoff_delay = 'hw tearoff --on --delay %d' -local wr_template = 'lf em 4x05_write %s %s %s' +local wr_template = 'lf em 4x05 write --po -d %s -p %s' --- -- This is only meant to be used when errors occur @@ -71,7 +71,7 @@ end local function reset(wr_value, password) print('[=] '..ansicolors.red..'resetting the active lock block'..ansicolors.reset) - core.console(wr_template:format(99, wr_value, password)) + core.console(wr_template:format(wr_value, password)) end local function main(args) @@ -201,7 +201,7 @@ local function main(args) local c = set_tearoff_delay:format(sd) core.console(c); - c = wr_template:format(99, wr_value, password) + c = wr_template:format(wr_value, password) core.console(c) word14, err14 = core.em4x05_read(14, password) From 086cea765f29da687f329eb20e10f01210314811 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 01:08:25 +0200 Subject: [PATCH 306/373] text --- client/luascripts/hf_mf_format.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/luascripts/hf_mf_format.lua b/client/luascripts/hf_mf_format.lua index 7aed6b757..155a586ec 100644 --- a/client/luascripts/hf_mf_format.lua +++ b/client/luascripts/hf_mf_format.lua @@ -7,9 +7,9 @@ local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.2' +version = 'v1.0.3' desc = [[ -This script will generate 'hf mf wrbl' commands for each block to format a Mifare card. +This script will generate 'hf mf wrbl' commands for each block to format a Mifare Classic card. Alla datablocks gets 0x00 As default the script sets the keys A/B to 0xFFFFFFFFFFFF @@ -41,7 +41,7 @@ arguments = [[ local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds local DEBUG = true -- the debug flag -local CmdString = 'hf mf wrbl %d B %s %s' +local CmdString = 'hf mf wrbl --blk %d -b -k %s -d %s' local numBlocks = 64 local numSectors = 16 --- @@ -89,7 +89,7 @@ local function ExitMsg(msg) end -- -- Read information from a card -function GetCardInfo() +local function GetCardInfo() result, err = lib14a.read(false, true) if not result then print(err) @@ -200,9 +200,9 @@ local function main(args) local reminder = (block+1) % 4 local cmd if reminder == 0 then - cmd = CmdString:format(block, OldKey , EMPTY_SECTORTRAIL) + cmd = CmdString:format(block, OldKey, EMPTY_SECTORTRAIL) else - cmd = CmdString:format(block, OldKey , EMPTY_BL) + cmd = CmdString:format(block, OldKey, EMPTY_BL) end if block ~= 0 then From 5654e29908d923c0011dce41218a6552f8d75a59 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 01:11:35 +0200 Subject: [PATCH 307/373] text --- armsrc/hitagS.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 022730075..7d396196e 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -1542,7 +1542,7 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) { //check for valid input if (page == 0) { Dbprintf( - "usage: lf hitag writer [03 | 04] [CHALLENGE | KEY] [page] [byte0] [byte1] [byte2] [byte3]"); + "usage: lf hitag writer [--03 | --04] [--nrar CHALLENGE | -k KEY] [-p page] -d [4 hex bytes]"); bStop = !false; } From f1cf01f7572090c230808423f1d4b444141f0bca Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 01:15:14 +0200 Subject: [PATCH 308/373] test --- client/luascripts/tests/data_tracetest.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/luascripts/tests/data_tracetest.lua b/client/luascripts/tests/data_tracetest.lua index 5773e0bcf..34341518d 100644 --- a/client/luascripts/tests/data_tracetest.lua +++ b/client/luascripts/tests/data_tracetest.lua @@ -7,7 +7,7 @@ local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.4' +version = 'v1.0.5' desc = [[ This script will load several traces files in current working directory/traces/ folder and do "data load" @@ -115,7 +115,7 @@ local function main(args) io.write('Starting to test traces > ') for _,file in pairs(files) do - local x = 'data load '..file + local x = 'data load -f '..file dbg(x) core.console(x) From 9410cc410fb56e6c3e3f3232fa1e1489f3f5e56b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 01:19:11 +0200 Subject: [PATCH 309/373] text --- armsrc/appmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index dfbec3780..f5e9ba489 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -195,7 +195,7 @@ static void MeasureAntennaTuning(void) { payload.v_lf134 = adcval; // voltage at 134kHz if (i == sc->divisor) - payload.v_lfconf = adcval; // voltage at `lf config q` + payload.v_lfconf = adcval; // voltage at `lf config --divisor` payload.results[i] = adcval >> 9; // scale int to fit in byte for graphing purposes From 4f21963b07f976d8db734895c6b064940a44d75e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 01:29:47 +0200 Subject: [PATCH 310/373] text --- client/src/emv/cmdemv.c | 81 +++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/client/src/emv/cmdemv.c b/client/src/emv/cmdemv.c index 9a1c4aa76..3ef602d16 100644 --- a/client/src/emv/cmdemv.c +++ b/client/src/emv/cmdemv.c @@ -59,10 +59,10 @@ static void ParamLoadDefaults(struct tlvdb *tlvRoot) { static void PrintChannel(EMVCommandChannel channel) { switch (channel) { case ECC_CONTACTLESS: - PrintAndLogEx(INFO, "Selected channel : " _GREEN_("CONTACTLESS (T=CL)")); + PrintAndLogEx(INFO, "Selected channel... " _GREEN_("CONTACTLESS (T=CL)")); break; case ECC_CONTACT: - PrintAndLogEx(INFO, "Selected channel : " _GREEN_("CONTACT")); + PrintAndLogEx(INFO, "Selected channel... " _GREEN_("CONTACT")); break; } } @@ -74,7 +74,8 @@ static int CmdEMVSelect(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "emv select", "Executes select applet command", - "Usage:\n\temv select -s a00000000101 -> select card, select applet\n\temv select -st a00000000101 -> select card, select applet, show result in TLV\n"); + "emv select -s a00000000101 -> select card, select applet\n" + "emv select -st a00000000101 -> select card, select applet, show result in TLV\n"); void *argtable[] = { arg_param_begin, @@ -123,8 +124,9 @@ static int CmdEMVSearch(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "emv search", - "Tries to select all applets from applet list:\n", - "Usage:\n\temv search -s -> select card and search\n\temv search -st -> select card, search and show result in TLV\n"); + "Tries to select all applets from applet list\n", + "emv search -s -> select card and search\n" + "emv search -st -> select card, search and show result in TLV\n"); void *argtable[] = { arg_param_begin, @@ -174,7 +176,8 @@ static int CmdEMVPPSE(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "emv pse", "Executes PSE/PPSE select command. It returns list of applet on the card:\n", - "Usage:\n\temv pse -s1 -> select, get pse\n\temv pse -st2 -> select, get ppse, show result in TLV\n"); + "emv pse -s1 -> select, get pse\n" + "emv pse -st2 -> select, get ppse, show result in TLV\n"); void *argtable[] = { arg_param_begin, @@ -230,10 +233,11 @@ static int CmdEMVGPO(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "emv gpo", - "Executes Get Processing Options command. It returns data in TLV format (0x77 - format2) or plain format (0x80 - format1).\nNeeds a EMV applet to be selected.", - "Usage:\n\temv gpo -k -> execute GPO\n" - "\temv gpo -t 01020304 -> execute GPO with 4-byte PDOL data, show result in TLV\n" - "\temv gpo -pmt 9F 37 04 -> load params from file, make PDOL data from PDOL, execute GPO with PDOL, show result in TLV\n"); + "Executes Get Processing Options command. It returns data in TLV format (0x77 - format2)\n" + "or plain format (0x80 - format1). Needs a EMV applet to be selected.", + "emv gpo -k -> execute GPO\n" + "emv gpo -t 01020304 -> execute GPO with 4-byte PDOL data, show result in TLV\n" + "emv gpo -pmt 9F 37 04 -> load params from file, make PDOL data from PDOL, execute GPO with PDOL, show result in TLV\n"); void *argtable[] = { arg_param_begin, @@ -339,8 +343,10 @@ static int CmdEMVReadRecord(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "emv readrec", - "Executes Read Record command. It returns data in TLV format.\nNeeds a bank applet to be selected and sometimes needs GPO to be executed.", - "Usage:\n\temv readrec -k 0101 -> read file SFI=01, SFIrec=01\n\temv readrec -kt 0201-> read file 0201 and show result in TLV\n"); + "Executes Read Record command. It returns data in TLV format.\n" + "Needs a bank applet to be selected and sometimes needs GPO to be executed.", + "emv readrec -k 0101 -> read file SFI=01, SFIrec=01\n" + "emv readrec -kt 0201 -> read file 0201 and show result in TLV\n"); void *argtable[] = { arg_param_begin, @@ -395,11 +401,12 @@ static int CmdEMVAC(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "emv genac", - "Generate Application Cryptogram command. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.", - "Usage:\n\temv genac -k 0102 -> generate AC with 2-byte CDOLdata and keep field ON after command\n" - "\temv genac -t 01020304 -> generate AC with 4-byte CDOL data, show result in TLV\n" - "\temv genac -Daac 01020304 -> generate AC with 4-byte CDOL data and terminal decision 'declined'\n" - "\temv genac -pmt 9F 37 04 -> load params from file, make CDOL data from CDOL, generate AC with CDOL, show result in TLV"); + "Generate Application Cryptogram command. It returns data in TLV format.\n" + "Needs a EMV applet to be selected and GPO to be executed.", + "emv genac -k 0102 -> generate AC with 2-byte CDOLdata and keep field ON after command\n" + "emv genac -t 01020304 -> generate AC with 4-byte CDOL data, show result in TLV\n" + "emv genac -Daac 01020304 -> generate AC with 4-byte CDOL data and terminal decision 'declined'\n" + "emv genac -pmt 9F 37 04 -> load params from file, make CDOL data from CDOL, generate AC with CDOL, show result in TLV"); void *argtable[] = { arg_param_begin, @@ -518,8 +525,10 @@ static int CmdEMVGenerateChallenge(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "emv challenge", - "Executes Generate Challenge command. It returns 4 or 8-byte random number from card.\nNeeds a EMV applet to be selected and GPO to be executed.", - "Usage:\n\temv challenge -> get challenge\n\temv challenge -k -> get challenge, keep fileld ON\n"); + "Executes Generate Challenge command. It returns 4 or 8-byte random number from card.\n" + "Needs a EMV applet to be selected and GPO to be executed.", + "emv challenge -> get challenge\n" + "emv challenge -k -> get challenge, keep fileld ON\n"); void *argtable[] = { arg_param_begin, @@ -569,10 +578,9 @@ static int CmdEMVInternalAuthenticate(const char *Cmd) { "Generate Internal Authenticate command. Usually needs 4-byte random number. It returns data in TLV format .\n" "Needs a EMV applet to be selected and GPO to be executed.", - "Usage:\n" - "\temv intauth -k 01020304 -> execute Internal Authenticate with 4-byte DDOLdata and keep field ON after command\n" - "\temv intauth -t 01020304 -> execute Internal Authenticate with 4-byte DDOL data, show result in TLV\n" - "\temv intauth -pmt 9F 37 04 -> load params from file, make DDOL data from DDOL, Internal Authenticate with DDOL, show result in TLV"); + "emv intauth -k 01020304 -> execute Internal Authenticate with 4-byte DDOLdata and keep field ON after command\n" + "emv intauth -t 01020304 -> execute Internal Authenticate with 4-byte DDOL data, show result in TLV\n" + "emv intauth -pmt 9F 37 04 -> load params from file, make DDOL data from DDOL, Internal Authenticate with DDOL, show result in TLV"); void *argtable[] = { arg_param_begin, @@ -798,9 +806,8 @@ static int CmdEMVExec(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "emv exec", "Executes EMV contactless transaction", - "Usage:\n" - "\temv exec -sat -> select card, execute MSD transaction, show APDU and TLV\n" - "\temv exec -satc -> select card, execute CDA transaction, show APDU and TLV\n"); + "emv exec -sat -> select card, execute MSD transaction, show APDU and TLV\n" + "emv exec -satc -> select card, execute CDA transaction, show APDU and TLV\n"); void *argtable[] = { arg_param_begin, @@ -1410,10 +1417,11 @@ static int CmdEMVScan(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "emv scan", - "Scan EMV card and save it contents to a file.", - "It executes EMV contactless transaction and saves result to a file which can be used for emulation\n" - "Usage:\n\temv scan -at -> scan MSD transaction mode and show APDU and TLV\n" - "\temv scan -c -> scan CDA transaction mode\n"); + "Scan EMV card and save it contents to a file.\n" + "It executes EMV contactless transaction and saves result to a file which can be used for emulation\n", + "emv scan -at -> scan MSD transaction mode and show APDU and TLV\n" + "emv scan -c -> scan CDA transaction mode\n" + ); void *argtable[] = { arg_param_begin, @@ -1808,12 +1816,14 @@ static int CmdEMVTest(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "emv test", "Executes tests\n", - "Usage:\n\temv test [l]\n"); + "emv test -i\n" + "emv test --long" + ); void *argtable[] = { arg_param_begin, - arg_lit0("iI", "ignore", "ignore timing tests for VM"), - arg_lit0("lL", "long", "run long tests too"), + arg_lit0("i", "ignore", "ignore timing tests for VM"), + arg_lit0("l", "long", "run long tests too"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -1838,9 +1848,8 @@ static int CmdEMVRoca(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "emv roca", "Tries to extract public keys and run the ROCA test against them.\n", - "Usage:\n" - "\temv roca -w -> select --CONTACT-- card and run test\n" - "\temv roca -> select --CONTACTLESS-- card and run test\n" + "emv roca -w -> select --CONTACT-- card and run test\n" + "emv roca -> select --CONTACTLESS-- card and run test\n" ); void *argtable[] = { From dda7ddb64a410582c89a2edf332f627b47d4400b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 01:32:55 +0200 Subject: [PATCH 311/373] text --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef3269c33..4d26b8f41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,13 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Change `hf 14b reader` - now supports continous mode (@iceman1001) + - Fix `hf search` - now doesn't false identify ISO15693 (@iceman1001) - Change emv commands now works with tokenized cards (@merlokk) - Change `hf 15 restore` - now also support EML/JSON (@iceman1001) - Change - all commands now use cliparser (@iceman1001) - Change `lf t55xx restore` - now also support JSON (@iceman1001) - - Change `hf mf csetuid` - adapted to accept 7byte uids. ~untested~ (@iceman1001) + - Change `hf mf csetuid` - adapted to accept 7byte uids ~untested~ (@iceman1001) - Added `hf mf view/eload/cload` - now accepts bin/eml/json (@iceman1001) - Added `hf mf eload/cload' - now accepts bin/eml/json (@iceman1001) - Fix RESTORE mis-annotation (@VortixDev) From e62dfa3bcd1bc409cff69674fa78a1844a34ab09 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 16 Apr 2021 01:53:07 +0200 Subject: [PATCH 312/373] typos --- armsrc/BigBuf.c | 2 +- client/lualibs/read15.lua | 2 +- doc/new_frame_format.md | 12 ++++++------ include/pm3_cmd.h | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index 95a19dbb7..b4dd2bc05 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -206,7 +206,7 @@ uint32_t BigBuf_get_traceLen(void) { /** This is a function to store traces. All protocols can use this generic tracer-function. The traces produced by calling this function can be fetched on the client-side - by 'hf list raw', alternatively 'hf list ' for protocol-specific + by 'hf list -t raw', alternatively 'hf list -t ' for protocol-specific annotation of commands/responses. **/ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag) { diff --git a/client/lualibs/read15.lua b/client/lualibs/read15.lua index 5d7400e2d..feb35d3eb 100644 --- a/client/lualibs/read15.lua +++ b/client/lualibs/read15.lua @@ -72,7 +72,7 @@ local function read15693(slow, dont_readresponse) We start by trying this command: MANDATORY (present in ALL iso15693 tags) command (the example below is sent to a tag different from the above one): - pm3> hf 15 info u + pm3> hf 15 info --ua UID=E007C1A257394244 Tag Info: Texas Instrument; Tag-it HF-I Standard; 8x32bit pm3> diff --git a/doc/new_frame_format.md b/doc/new_frame_format.md index 102ef9c18..c5e7d542d 100644 --- a/doc/new_frame_format.md +++ b/doc/new_frame_format.md @@ -288,10 +288,10 @@ USART_BAUD_RATE defined there Receiving from USART need more than 30ms as we used on USB else we get errors about partial packet reception - FTDI 9600 hw status ⇒ we need 20ms - FTDI 115200 hw status ⇒ we need 50ms - FTDI 460800 hw status ⇒ we need 30ms - BT 115200 hf mf fchk 1 dic ⇒ we need 140ms + FTDI 9600 hw status ⇒ we need 20ms + FTDI 115200 hw status ⇒ we need 50ms + FTDI 460800 hw status ⇒ we need 30ms + BT 115200 hf mf fchk --1k -f file.dic ⇒ we need 140ms # define UART_FPC_CLIENT_RX_TIMEOUT_MS 170 # define UART_USB_CLIENT_RX_TIMEOUT_MS 20 @@ -307,7 +307,7 @@ it's reduced to UART_USB_CLIENT_RX_TIMEOUT_MS. Add automatically some communication delay in the `WaitForResponseTimeout` & `dl_it` timeouts. Only when using FPC, timeout = 2* empirically measured delay (FTDI cable). -Empirically measured delay (FTDI cable) with "hw ping 512" : +Empirically measured delay (FTDI cable) with "hw ping -l 512" : usb ⇒ 6.. 32ms 460800 ⇒ 40.. 70ms @@ -453,7 +453,7 @@ On linux UART (FTDI) CMD_PING reply_ng(CMD_PING, PM3_SUCCESS, packet->data.asBytes, packet->length); <-12=504d33620080000009016233 <- NG -`hw ping 512` (NG) +`hw ping -l 512` (NG) CmdPing SendCommandNG(CMD_PING, data, len); ->522=504d336100820901000102030405060708090a0b0c0d0e0f1011121314151617 -> NG diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 8459bdd22..5cee586d2 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -860,10 +860,10 @@ typedef struct { // Receiving from USART need more than 30ms as we used on USB // else we get errors about partial packet reception -// FTDI 9600 hw status -> we need 20ms -// FTDI 115200 hw status -> we need 50ms -// FTDI 460800 hw status -> we need 30ms -// BT 115200 hf mf fchk 1 dic -> we need 140ms +// FTDI 9600 hw status -> we need 20ms +// FTDI 115200 hw status -> we need 50ms +// FTDI 460800 hw status -> we need 30ms +// BT 115200 hf mf fchk --1k -f file.dic -> we need 140ms // all zero's configure: no timeout for read/write used. // took settings from libnfc/buses/uart.c From 72e5b9e80d84d58646f24e9b7f7f5e4f1482c72e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 08:09:11 +0200 Subject: [PATCH 313/373] text --- client/src/cmdlfindala.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/cmdlfindala.c b/client/src/cmdlfindala.c index b2719ba1e..8f811045c 100644 --- a/client/src/cmdlfindala.c +++ b/client/src/cmdlfindala.c @@ -238,7 +238,7 @@ int demodIndalaEx(int clk, int invert, int maxErr, bool verbose) { } int demodIndala(bool verbose) { - return demodIndalaEx(32, 0, 100, verbose); + return demodIndalaEx(0, 0, 100, verbose); } static int CmdIndalaDemod(const char *Cmd) { @@ -587,10 +587,10 @@ static int CmdIndalaSim(const char *Cmd) { // indala PSK // It has to send either 64bits (8bytes) or 224bits (28bytes). Zero padding needed if not. - // lf simpsk 1 c 32 r 2 d 0102030405060708 + // lf simpsk -1 -c 32 --fc 2 -d 0102030405060708 PrintAndLogEx(SUCCESS, "Simulating " _YELLOW_("%s") " Indala raw " _YELLOW_("%s") - , (is_long_uid) ? "224b" : "64b" + , (is_long_uid) ? "224 bit" : "64 bit" , sprint_hex_inrow(raw, raw_len) ); PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation or run another command"); From dff76e81ca3de90322e7c27aaf0822858aa681cb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 08:43:20 +0200 Subject: [PATCH 314/373] fix coverity CID 226452, 319217 --- client/src/cmdhf15.c | 4 ++-- client/src/cmdlft55xx.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 6c3a854fb..d788dc52b 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1981,7 +1981,7 @@ static int CmdHF15Restore(const char *Cmd) { } else { PrintAndLogEx(SUCCESS, "Using unaddressed mode"); } - PrintAndLogEx(INFO, "Using block size... %zu", blocksize); + PrintAndLogEx(INFO, "Using block size... %d", blocksize); // 4bytes * 256 blocks. Should be enough.. uint8_t *data = calloc(4 * 256, sizeof(uint8_t)); @@ -2019,7 +2019,7 @@ static int CmdHF15Restore(const char *Cmd) { } if ((datalen % blocksize) != 0) { - PrintAndLogEx(WARNING, "datalen %zu isn't dividable with blocksize %zu", datalen, blocksize); + PrintAndLogEx(WARNING, "datalen %zu isn't dividable with blocksize %d", datalen, blocksize); free(data); return PM3_ESOFT; } diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index b8f162896..37ab2a8b9 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -2434,6 +2434,7 @@ static int CmdT55xxRestore(const char *Cmd) { if (CmdT55xxWriteBlock(wcmd) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Warning: error writing blk 0"); } + free(dump); PrintAndLogEx(INFO, "Done!"); return PM3_SUCCESS; } From cf8f0f0b6ae64d863ff2d6b1bf1b014b2e2f72d4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 12:53:44 +0200 Subject: [PATCH 315/373] hf iclass eload/view/decrypt - now suports BIN/EML/JSON formats --- client/src/cmdhficlass.c | 230 +++++++++++++++++++++++++-------------- 1 file changed, 150 insertions(+), 80 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index cedcdc36e..e1640f84b 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -526,7 +526,7 @@ static int CmdHFiClassSniff(const char *Cmd) { CLIParserInit(&ctx, "hf iclass sniff", "Sniff the communication reader and tag", "hf iclass sniff\n" - "hf iclass sniff -j -> jam e-purse updates\n" + "hf iclass sniff -j --> jam e-purse updates\n" ); void *argtable[] = { @@ -566,12 +566,11 @@ static int CmdHFiClassSim(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf iclass sim", "Simulate a iCLASS legacy/standard tag", - "hf iclass sim -t 0 --csn 031FEC8AF7FF12E0 -> simulate with specficied CSN\n" - "hf iclass sim -t 1 -> simulate with default CSN\n" - "hf iclass sim -t 2 -> execute loclass attack online part\n" - "hf iclass eload -f hf-iclass-AA162D30F8FF12F1-dump.bin -> simulate full iCLASS 2k tag\n" - "hf iclass sim -t 3 -> simulate full iCLASS 2k tag\n" - "hf iclass sim -t 4 -> Reader-attack, adapted for KeyRoll mode, gather reader responses to extract elite key"); + "hf iclass sim -t 0 --csn 031FEC8AF7FF12E0 --> simulate with specficied CSN\n" + "hf iclass sim -t 1 --> simulate with default CSN\n" + "hf iclass sim -t 2 --> execute loclass attack online part\n" + "hf iclass sim -t 3 --> simulate full iCLASS 2k tag\n" + "hf iclass sim -t 4 --> Reader-attack, adapted for KeyRoll mode, gather reader responses to extract elite key"); void *argtable[] = { arg_param_begin, @@ -857,14 +856,14 @@ static int CmdHFiClassReader(const char *Cmd) { static int CmdHFiClassELoad(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf iclass eload", - "Loads iCLASS tag dump into emulator memory on device", - "hf iclass eload -f hf-iclass-AA162D30F8FF12F1-dump.bin\n"); + "Load emulator memory with data from (bin/eml/json) iCLASS dump file", + "hf iclass eload -f hf-iclass-AA162D30F8FF12F1-dump.bin\n" + "hf iclass eload -f hf-iclass-AA162D30F8FF12F1-dump.eml\n" + ); void *argtable[] = { arg_param_begin, - arg_str1("f", "file", "", "filename of dump"), - arg_lit0(NULL, "json", "load JSON type dump"), - arg_lit0(NULL, "eml", "load EML type dump"), + arg_str1("f", "file", "", "filename of dump (bin/eml/json)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -879,32 +878,17 @@ static int CmdHFiClassELoad(const char *Cmd) { return PM3_EINVARG; } - DumpFileType_t dftype = BIN; - - bool use_json = arg_get_lit(ctx, 2); - bool use_eml = arg_get_lit(ctx, 3); CLIParserFree(ctx); - if (use_json && use_eml) { - PrintAndLogEx(ERR, "Error: can't specify both JSON & EML"); - return PM3_EINVARG; - } - - if (use_json) { - dftype = JSON; - } else if (use_eml) { - dftype = EML; - } - size_t bytes_read = 2048; uint8_t *dump = calloc(2048, sizeof(uint8_t)); - if (!dump) { + if (dump == NULL) { PrintAndLogEx(ERR, "error, cannot allocate memory "); return PM3_EMALLOC; } int res = 0; - + DumpFileType_t dftype = getfiletype(filename); switch (dftype) { case BIN: { res = loadFile_safe(filename, ".bin", (void **)&dump, &bytes_read); @@ -975,7 +959,7 @@ static int CmdHFiClassESave(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "filename of dumpfile"), + arg_str0("f", "file", "", "filename of dump file"), arg_int0("s", "size", "<256|2048>", "number of bytes to save (default 256)"), arg_param_end }; @@ -1088,15 +1072,18 @@ static int CmdHFiClassDecrypt(const char *Cmd) { "This is a naive implementation, it tries to decrypt every block after block 6.\n" "Correct behaviour would be to decrypt only the application areas where the key is valid,\n" "which is defined by the configuration block.\n" - "OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside\n" - "in the resources directory. The file should be 16 bytes binary data", + "\nOBS!\n" + "In order to use this function, the file `iclass_decryptionkey.bin` must reside\n" + "in the resources directory. The file should be 16 bytes binary data\n" + "or...\n" + "make sure your cardhelper is placed in the sim module", "hf iclass decrypt -f hf-iclass-AA162D30F8FF12F1-dump.bin\n" "hf iclass decrypt -f hf-iclass-AA162D30F8FF12F1-dump.bin -k 000102030405060708090a0b0c0d0e0f\n" "hf iclass decrypt -d 1122334455667788 -k 000102030405060708090a0b0c0d0e0f"); void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "filename of dumpfile"), + arg_str0("f", "file", "", "filename of dump file (bin/eml/json)"), arg_str0("d", "data", "", "3DES encrypted data"), arg_str0("k", "key", "", "3DES transport key"), arg_lit0("v", "verbose", "verbose output"), @@ -1108,33 +1095,12 @@ static int CmdHFiClassDecrypt(const char *Cmd) { char filename[FILE_PATH_SIZE] = {0}; CLIParamStrToBuf(arg_get_str(clictx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - size_t decryptedlen = 0; - uint8_t *decrypted = NULL; - bool have_file = false; - - if (fnlen > 0) { - if (loadFile_safe(filename, "", (void **)&decrypted, &decryptedlen) != PM3_SUCCESS) { - CLIParserFree(clictx); - return PM3_EINVARG; - } - have_file = true; - } - int enc_data_len = 0; uint8_t enc_data[8] = {0}; bool have_data = false; CLIGetHexWithReturn(clictx, 2, enc_data, &enc_data_len); - if (enc_data_len > 0) { - if (enc_data_len != 8) { - PrintAndLogEx(ERR, "Data must be 8 hex bytes (16 HEX symbols)"); - CLIParserFree(clictx); - return PM3_EINVARG; - } - have_data = true; - } - int key_len = 0; uint8_t key[16] = {0}; uint8_t *keyptr = NULL; @@ -1142,24 +1108,74 @@ static int CmdHFiClassDecrypt(const char *Cmd) { CLIGetHexWithReturn(clictx, 3, key, &key_len); + bool verbose = arg_get_lit(clictx, 4); + CLIParserFree(clictx); + + // sanity checks + if (enc_data_len > 0) { + if (enc_data_len != 8) { + PrintAndLogEx(ERR, "Data must be 8 hex bytes (16 HEX symbols)"); + return PM3_EINVARG; + } + have_data = true; + } + if (key_len > 0) { if (key_len != 16) { PrintAndLogEx(ERR, "Transport key must be 16 hex bytes (32 HEX characters)"); - CLIParserFree(clictx); return PM3_EINVARG; } have_key = true; } - bool verbose = arg_get_lit(clictx, 4); - CLIParserFree(clictx); + size_t decryptedlen = 2048; + uint8_t *decrypted = calloc(2048, sizeof(uint8_t)); + bool have_file = false; + if (decrypted == NULL) { + PrintAndLogEx(ERR, "error, cannot allocate memory "); + return PM3_EMALLOC; + } + int res = PM3_SUCCESS; + + // if user supplied dump file, time to load it + if (fnlen > 0) { + + DumpFileType_t dftype = getfiletype(filename); + switch (dftype) { + case BIN: { + res = loadFile_safe(filename, ".bin", (void **)&decrypted, &decryptedlen); + break; + } + case EML: { + res = loadFileEML_safe(filename, (void **)&decrypted, &decryptedlen); + break; + } + case JSON: { + res = loadFileJSON(filename, decrypted, 2048, &decryptedlen, NULL); + break; + } + case DICTIONARY: { + PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); + return PM3_EINVARG; + } + } + + if (res != PM3_SUCCESS) { + free(decrypted); + return PM3_EFILE; + } + + have_file = true; + } + + // load transport key bool use_sc = false; if (have_key == false) { use_sc = IsCardHelperPresent(verbose); if (use_sc == false) { size_t keylen = 0; - int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&keyptr, &keylen); + res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&keyptr, &keylen); if (res != PM3_SUCCESS) { PrintAndLogEx(INFO, "Couldn't find any decryption methods"); return PM3_EINVARG; @@ -1181,6 +1197,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { uint8_t dec_data[8] = {0}; + // decrypt user supplied data if (have_data) { if (use_sc) { @@ -1191,6 +1208,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { PrintAndLogEx(SUCCESS, "Data: %s", sprint_hex(dec_data, sizeof(dec_data))); } + // decrypt dump file data if (have_file) { picopass_hdr_t *hdr = (picopass_hdr_t *)decrypted; @@ -1455,7 +1473,7 @@ static int CmdHFiClassDump(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "filename to save dump to"), + arg_str0("f", "file", "", "save filename"), arg_str0("k", "key", "", "debit key or NR/MAC for replay as 8 hex bytes"), arg_int0(NULL, "ki", "", "debit key index to select key from memory 'hf iclass managekeys'"), arg_str0(NULL, "credit", "", "credit key as 8 hex bytes"), @@ -1927,7 +1945,7 @@ static int CmdHFiClassRestore(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str1("f", "file", "", "specify a filename to restore"), + arg_str1("f", "file", "", "specify a filename to restore (bin/eml/json)"), arg_str0("k", "key", "", "Access key as 8 hex bytes"), arg_int0(NULL, "ki", "", "Key index to select key from memory 'hf iclass managekeys'"), arg_int1(NULL, "first", "", "The first block number to restore"), @@ -2005,10 +2023,36 @@ static int CmdHFiClassRestore(const char *Cmd) { return PM3_EINVARG; } - uint8_t *dump = NULL; - size_t bytes_read = 0; - if (loadFile_safe(filename, "", (void **)&dump, &bytes_read) != PM3_SUCCESS) { - PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); + size_t bytes_read = 2048; + uint8_t *dump = calloc(2048, sizeof(uint8_t)); + if (dump == NULL) { + PrintAndLogEx(ERR, "error, cannot allocate memory "); + return PM3_EMALLOC; + } + + int res = PM3_SUCCESS; + DumpFileType_t dftype = getfiletype(filename); + switch (dftype) { + case BIN: { + res = loadFile_safe(filename, ".bin", (void **)&dump, &bytes_read); + break; + } + case EML: { + res = loadFileEML_safe(filename, (void **)&dump, &bytes_read); + break; + } + case JSON: { + res = loadFileJSON(filename, dump, 2048, &bytes_read, NULL); + break; + } + case DICTIONARY: { + PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); + return PM3_EINVARG; + } + } + + if (res != PM3_SUCCESS) { + free(dump); return PM3_EFILE; } @@ -2305,9 +2349,9 @@ static int CmdHFiClass_loclass(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "filename of Bruteforce iclass dumpfile"), - arg_lit0(NULL, "test", "Perform self-test"), - arg_lit0(NULL, "long", "Perform self-test, including long ones"), + arg_str0("f", "file", "", "filename with nr/mac data from `hf iclass sim -t 2` "), + arg_lit0(NULL, "test", "Perform self-test"), + arg_lit0(NULL, "long", "Perform self-test, including long ones"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -2456,13 +2500,13 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e static int CmdHFiClassView(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf iclass view", - "Print a iCLASS tag dump file", + "Print a iCLASS tag dump file (bin/eml/json)", "hf iclass view -f hf-iclass-AA162D30F8FF12F1-dump.bin\n" "hf iclass view --first 1 -f hf-iclass-AA162D30F8FF12F1-dump.bin\n"); void *argtable[] = { arg_param_begin, - arg_str1("f", "file", "", "filename of dump"), + arg_str1("f", "file", "", "filename of dump (bin/eml/json)"), arg_int0(NULL, "first", "", "Begin printing from this block (default block 6)"), arg_int0(NULL, "last", "", "End printing at this block (default 0, ALL)"), arg_lit0("v", "verbose", "verbose output"), @@ -2480,10 +2524,36 @@ static int CmdHFiClassView(const char *Cmd) { CLIParserFree(ctx); - uint8_t *dump = NULL; - size_t bytes_read = 0; - if (loadFile_safe(filename, "", (void **)&dump, &bytes_read) != PM3_SUCCESS) { - PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); + size_t bytes_read = 2048; + uint8_t *dump = calloc(2048, sizeof(uint8_t)); + if (dump == NULL) { + PrintAndLogEx(ERR, "error, cannot allocate memory "); + return PM3_EMALLOC; + } + + int res = 0; + DumpFileType_t dftype = getfiletype(filename); + switch (dftype) { + case BIN: { + res = loadFile_safe(filename, ".bin", (void **)&dump, &bytes_read); + break; + } + case EML: { + res = loadFileEML_safe(filename, (void **)&dump, &bytes_read); + break; + } + case JSON: { + res = loadFileJSON(filename, dump, 2048, &bytes_read, NULL); + break; + } + case DICTIONARY: { + PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); + return PM3_EINVARG; + } + } + + if (res != PM3_SUCCESS) { + free(dump); return PM3_EFILE; } @@ -2726,14 +2796,14 @@ static int CmdHFiClassManageKeys(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf iclass managekeys", "Manage iCLASS Keys in client memory", - "hf iclass managekeys --ki 0 -k 1122334455667788 -> set key 1122334455667788 at index 0\n" - "hf iclass managekeys -f mykeys.bin --save -> save key file\n" - "hf iclass managekeys -f mykeys.bin --load -> load key file\n" - "hf iclass managekeys -p -> print keys"); + "hf iclass managekeys --ki 0 -k 1122334455667788 --> set key 1122334455667788 at index 0\n" + "hf iclass managekeys -f mykeys.bin --save --> save key file\n" + "hf iclass managekeys -f mykeys.bin --load --> load key file\n" + "hf iclass managekeys -p --> print keys"); void *argtable[] = { arg_param_begin, - arg_str0("f", "file", "", "Specify a filename to use with load or save operations"), + arg_str0("f", "file", "", "Specify a filename for load / save operations"), arg_str0("k", "key", "", "Access key as 8 hex bytes"), arg_int0(NULL, "ki", "", "Specify key index to set key in memory"), arg_lit0(NULL, "save", "Save keys in memory to file specified by filename"), @@ -2947,7 +3017,7 @@ static int CmdHFiClassCheckKeys(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str1("f", "file", "", "Dictionary file with default iclass keys"), + arg_str1("f", "file", "", "Dictionary file with default iclass keys"), arg_lit0(NULL, "credit", "key is assumed to be the credit key"), arg_lit0(NULL, "elite", "elite computations applied to key"), arg_lit0(NULL, "raw", "no computations applied to key (raw)"), @@ -3133,7 +3203,7 @@ static int CmdHFiClassLookUp(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str1("f", "file", "", "Dictionary file with default iclass keys"), + arg_str1("f", "file", "", "Dictionary file with default iclass keys"), arg_str1(NULL, "csn", "", "Specify CSN as 8 hex bytes"), arg_str1(NULL, "epurse", "", "Specify ePurse as 8 hex bytes"), arg_str1(NULL, "macs", "", "MACs"), From 201797ef81872bbd5a24d716bcdba6f283b4e349 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 13:09:21 +0200 Subject: [PATCH 316/373] more SANITIZE --- .vscode/tasks.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 67f0f235e..0bbc07ac9 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -36,7 +36,7 @@ { "label": "client: Debug: make", "type": "shell", - "command": "make client -j DEBUG=1", + "command": "make client -j DEBUG=1 SANITIZE=1", "problemMatcher": [ "$gcc" ], @@ -45,7 +45,7 @@ { "label": "client: Debug: clean & make", "type": "shell", - "command": "make client/clean && make client -j DEBUG=1", + "command": "make client/clean && make client -j DEBUG=1 SANITIZE=1", "problemMatcher": [ "$gcc" ], From 8497b3e3f6951f2e44030a21a32307c1358867f7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 13:20:20 +0200 Subject: [PATCH 317/373] fix data dec --- client/src/cmddata.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 63d65fa25..870157514 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1035,12 +1035,12 @@ static int CmdDecimate(const char *Cmd) { CLIParserInit(&ctx, "data decimate", "Performs decimation, by reducing samples N times in the grapbuf. Good for PSK\n", "data decimate\n" - "data decimate 4" + "data decimate -n 4" ); void *argtable[] = { arg_param_begin, - arg_int0(NULL, NULL, "", "factor to reduce sample set (default 2)"), + arg_int0("n", NULL, "", "factor to reduce sample set (default 2)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -1067,12 +1067,12 @@ static int CmdUndecimate(const char *Cmd) { CLIParserInit(&ctx, "data undecimate", "Performs un-decimation, by repeating each sample N times in the graphbuf", "data undecimate\n" - "data undecimate 4\n" + "data undecimate -n 4\n" ); void *argtable[] = { arg_param_begin, - arg_int0(NULL, NULL, "", "factor to repeat each sample (default 2)"), + arg_int0("n", NULL, "", "factor to repeat each sample (default 2)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); From 5775a283e918256d9651c482e4c02d590e8dc2ad Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 17:04:21 +0200 Subject: [PATCH 318/373] fix coverity CID 319296 --- client/src/cmdhficlass.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index e1640f84b..56f581664 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -903,6 +903,7 @@ static int CmdHFiClassELoad(const char *Cmd) { break; } case DICTIONARY: { + free(dump); PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); return PM3_EINVARG; } @@ -1156,6 +1157,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { break; } case DICTIONARY: { + free(decrypted); PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); return PM3_EINVARG; } @@ -2046,7 +2048,8 @@ static int CmdHFiClassRestore(const char *Cmd) { break; } case DICTIONARY: { - PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); + free(dump); + PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); return PM3_EINVARG; } } @@ -2547,6 +2550,7 @@ static int CmdHFiClassView(const char *Cmd) { break; } case DICTIONARY: { + free(dump); PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); return PM3_EINVARG; } From d2646122e7c928248b86b140b165ef79954d140e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 17:10:08 +0200 Subject: [PATCH 319/373] style --- client/luascripts/hf_legic_buffer2card.lua | 4 +- client/luascripts/hf_mf_dump-luxeo.lua | 2 +- client/src/cmddata.c | 268 ++++++++++----------- client/src/cmdhf14b.c | 4 +- client/src/cmdhf15.c | 92 +++---- client/src/cmdhffelica.c | 142 +++++------ client/src/cmdhffido.c | 4 +- client/src/cmdhfmf.c | 150 ++++++------ client/src/cmdhfmfhard.c | 2 +- client/src/cmdhfmfp.c | 16 +- client/src/cmdlfhitag.c | 56 ++--- client/src/cmdlft55xx.c | 4 +- client/src/cmdwiegand.c | 2 +- client/src/emv/cmdemv.c | 6 +- client/src/mifare/mifare4.c | 32 +-- tools/mf_nonce_brute/mf_nonce_brute.c | 24 +- 16 files changed, 404 insertions(+), 404 deletions(-) diff --git a/client/luascripts/hf_legic_buffer2card.lua b/client/luascripts/hf_legic_buffer2card.lua index 83fa6c12b..b6eee9f86 100644 --- a/client/luascripts/hf_legic_buffer2card.lua +++ b/client/luascripts/hf_legic_buffer2card.lua @@ -8,8 +8,8 @@ author = 'Mosci' version = 'v1.0.3' desc = [[ -This is a script which writes value 0x01 to bytes from -position 0x07 until 0xFF on a Legic Prime Tag (MIM256 or MIM1024) +This is a script which writes value 0x01 to bytes from +position 0x07 until 0xFF on a Legic Prime Tag (MIM256 or MIM1024) -- (created with 'hf legic dump -f my_dump.hex') -- ]] example = [[ diff --git a/client/luascripts/hf_mf_dump-luxeo.lua b/client/luascripts/hf_mf_dump-luxeo.lua index 8659dcd9b..2b2c5d9c7 100644 --- a/client/luascripts/hf_mf_dump-luxeo.lua +++ b/client/luascripts/hf_mf_dump-luxeo.lua @@ -14,7 +14,7 @@ copyright = '' author = '0xdrrb' version = 'v0.1.2' desc = [[ -This is a script that tries to dump and decrypt the data of a specific type of Mifare laundromat token. +This is a script that tries to dump and decrypt the data of a specific type of Mifare laundromat token. OBS! Tag must be on the antenna. ]] example = [[ diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 870157514..cf426b50f 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- // Copyright (C) 2010 iZsh -// modified Marshmellow, +// modified Marshmellow, // modified Iceman 2019, 2020, 2021 // // This code is licensed to you under the terms of the GNU GPL, version 2 or, @@ -309,9 +309,9 @@ void save_restoreDB(uint8_t saveOpt) { static int CmdSetDebugMode(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data setdebugmode", - "Set debugging level on client side", - "data setdebugmode" - ); + "Set debugging level on client side", + "data setdebugmode" + ); void *argtable[] = { arg_param_begin, arg_lit0("0", NULL, "no debug messages"), @@ -326,7 +326,7 @@ static int CmdSetDebugMode(const char *Cmd) { bool dg_2 = arg_get_lit(ctx, 3); CLIParserFree(ctx); - if (dg_0 + dg_1 + dg_2 > 1 ) { + if (dg_0 + dg_1 + dg_2 > 1) { PrintAndLogEx(INFO, "Select only one option"); return PM3_EINVARG; } @@ -339,7 +339,7 @@ static int CmdSetDebugMode(const char *Cmd) { if (dg_2) g_debugMode = 2; - switch(g_debugMode) { + switch (g_debugMode) { case 0: PrintAndLogEx(INFO, "client debug level... %u ( no debug messages )", g_debugMode); break; @@ -428,15 +428,15 @@ int printDemodBuff(uint8_t offset, bool strip_leading, bool invert, bool print_h int CmdPrintDemodBuff(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data print", - "Print the data in the DemodBuffer as hex or binary.\n" - "Defaults to binary output", - "data print" - ); + "Print the data in the DemodBuffer as hex or binary.\n" + "Defaults to binary output", + "data print" + ); void *argtable[] = { arg_param_begin, arg_lit0("i", "inv", "invert Demodbuffer before printing"), // arg_int0("l","len", "", "length to print in # of bits or hex characters respectively"), - arg_int0("o","offset", "", "offset in # of bits"), + arg_int0("o", "offset", "", "offset in # of bits"), arg_lit0("s", "strip", "strip leading zeroes, i.e. set offset to first bit equal to one"), arg_lit0("x", "hex", "output in hex (omit for binary output)"), arg_param_end @@ -458,11 +458,11 @@ int CmdPrintDemodBuff(const char *Cmd) { int CmdGetBitStream(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data getbitstream", - "Convert GraphBuffer's value accordingly\n" - " - larger or equal to ONE becomes ONE\n" - " - less than ONE becomes ZERO", - "data getbitstream" - ); + "Convert GraphBuffer's value accordingly\n" + " - larger or equal to ONE becomes ONE\n" + " - less than ONE becomes ZERO", + "data getbitstream" + ); void *argtable[] = { arg_param_begin, arg_param_end @@ -482,9 +482,9 @@ static int CmdConvertBitStream(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data convertbitstream", - "Convert GraphBuffer's 0|1 values to 127|-127", - "data convertbitstream" - ); + "Convert GraphBuffer's 0|1 values to 127|-127", + "data convertbitstream" + ); void *argtable[] = { arg_param_begin, arg_param_end @@ -644,11 +644,11 @@ static int Cmdaskmandemod(const char *Cmd) { static int Cmdmandecoderaw(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data manrawdecode", - "Manchester decode binary stream in DemodBuffer\n" - "Converts 10 and 01 and converts to 0 and 1 respectively\n" - " - must have binary sequence in demodbuffer (run `data rawdemod ar` before)", - "data manrawdecode" - ); + "Manchester decode binary stream in DemodBuffer\n" + "Converts 10 and 01 and converts to 0 and 1 respectively\n" + " - must have binary sequence in demodbuffer (run `data rawdemod ar` before)", + "data manrawdecode" + ); void *argtable[] = { arg_param_begin, arg_lit0("i", "inv", "invert output"), @@ -658,7 +658,7 @@ static int Cmdmandecoderaw(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, true); bool invert = arg_get_lit(ctx, 1); int max_err = arg_get_int_def(ctx, 2, 20); - CLIParserFree(ctx); + CLIParserFree(ctx); if (DemodBufferLen == 0) { PrintAndLogEx(WARNING, "DemodBuffer empty, run " _YELLOW_("`data rawdemod ar`")); @@ -726,13 +726,13 @@ static int Cmdmandecoderaw(const char *Cmd) { static int CmdBiphaseDecodeRaw(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data biphaserawdecode", - "Biphase decode binary stream in DemodBuffer\n" - "Converts 10 or 01 -> 1 and 11 or 00 -> 0\n" - " - must have binary sequence in demodbuffer (run `data rawdemod ar` before)\n" - " - invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester", - "data biphaserawdecode --> decode biphase bitstream from the demodbuffer\n" - "data biphaserawdecode -oi --> decode biphase bitstream from the demodbuffer, adjust offset, and invert output" - ); + "Biphase decode binary stream in DemodBuffer\n" + "Converts 10 or 01 -> 1 and 11 or 00 -> 0\n" + " - must have binary sequence in demodbuffer (run `data rawdemod ar` before)\n" + " - invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester", + "data biphaserawdecode --> decode biphase bitstream from the demodbuffer\n" + "data biphaserawdecode -oi --> decode biphase bitstream from the demodbuffer, adjust offset, and invert output" + ); void *argtable[] = { arg_param_begin, arg_lit0("o", "offset", "set to adjust decode start position"), @@ -744,7 +744,7 @@ static int CmdBiphaseDecodeRaw(const char *Cmd) { int offset = arg_get_lit(ctx, 1); bool invert = arg_get_lit(ctx, 2); int max_err = arg_get_int_def(ctx, 3, 20); - CLIParserFree(ctx); + CLIParserFree(ctx); if (DemodBufferLen == 0) { PrintAndLogEx(WARNING, "DemodBuffer empty, run " _YELLOW_("`data rawdemod ar`")); @@ -942,11 +942,11 @@ int AutoCorrelate(const int *in, int *out, size_t len, size_t window, bool SaveG static int CmdAutoCorr(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data autocorr", - "Autocorrelate over window is used to detect repeating sequences.\n" - "We use it as detection of how long in bits a message inside the signal is", - "data autocorr -w 4000\n" - "data autocorr -w 4000 -g" - ); + "Autocorrelate over window is used to detect repeating sequences.\n" + "We use it as detection of how long in bits a message inside the signal is", + "data autocorr -w 4000\n" + "data autocorr -w 4000 -g" + ); void *argtable[] = { arg_param_begin, arg_lit0("g", NULL, "save back to GraphBuffer (overwrite)"), @@ -979,9 +979,9 @@ static int CmdBitsamples(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data bitsamples", - "Get raw samples from device as bitstring", - "data bitsamples" - ); + "Get raw samples from device as bitstring", + "data bitsamples" + ); void *argtable[] = { arg_param_begin, arg_param_end @@ -1013,10 +1013,10 @@ static int CmdBitsamples(const char *Cmd) { static int CmdBuffClear(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data clear", - "This function clears the bigbuff on deviceside\n" - "and graph window", - "data clear" - ); + "This function clears the bigbuff on deviceside\n" + "and graph window", + "data clear" + ); void *argtable[] = { arg_param_begin, arg_param_end @@ -1105,10 +1105,10 @@ static int CmdGraphShiftZero(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data shiftgraphzero", - "Shift 0 for Graphed wave + or - shift value", - "data shiftgraphzero -n 10 --> shift 10 points\n" - "data shiftgraphzero -n -22 --> shift negative 22 points" - ); + "Shift 0 for Graphed wave + or - shift value", + "data shiftgraphzero -n 10 --> shift 10 points\n" + "data shiftgraphzero -n -22 --> shift negative 22 points" + ); void *argtable[] = { arg_param_begin, arg_int1("n", NULL, "", "shift + or -"), @@ -1150,10 +1150,10 @@ static int CmdAskEdgeDetect(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data askedgedetect", - "Adjust Graph for manual ASK demod using the length of sample differences\n" - "to detect the edge of a wave", - "data askedgedetect -t 20" - ); + "Adjust Graph for manual ASK demod using the length of sample differences\n" + "to detect the edge of a wave", + "data askedgedetect -t 20" + ); void *argtable[] = { arg_param_begin, arg_int0("t", "thres", "", "threshold, use 20 - 45 (def 25)"), @@ -1175,12 +1175,12 @@ static int CmdAskEdgeDetect(const char *Cmd) { static int CmdDetectClockRate(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data detectclock", - "Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer", - "data detectclock -A --> detect clock of an ask wave in GraphBuffer\n" - "data detectclock -F --> detect clock of an fsk wave in GraphBuffer\n" - "data detectclock -N --> detect clock of an psk wave in GraphBuffer\n" - "data detectclock -P --> detect clock of an nrz/direct wave in GraphBuffer" - ); + "Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer", + "data detectclock -A --> detect clock of an ask wave in GraphBuffer\n" + "data detectclock -F --> detect clock of an fsk wave in GraphBuffer\n" + "data detectclock -N --> detect clock of an psk wave in GraphBuffer\n" + "data detectclock -P --> detect clock of an nrz/direct wave in GraphBuffer" + ); void *argtable[] = { arg_param_begin, arg_lit0("A", "ASK", "specify ASK modulation clock detection"), @@ -1538,11 +1538,11 @@ void setClockGrid(uint32_t clk, int offset) { int CmdGrid(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data grid", - "This function overlay grid on graph plot window.\n" - "use zero value to turn off either", - "data grid --> turn off\n" - "data grid -x 64 -y 50" - ); + "This function overlay grid on graph plot window.\n" + "use zero value to turn off either", + "data grid --> turn off\n" + "data grid -x 64 -y 50" + ); void *argtable[] = { arg_param_begin, arg_dbl0("x", NULL, "", "plot grid X coord"), @@ -1563,10 +1563,10 @@ int CmdGrid(const char *Cmd) { static int CmdSetGraphMarkers(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data setgraphmarkers", - "Set blue and orange marker in graph window", - "data setgraphmarkers --> turn off\n" - "data setgraphmarkers -a 64 -b 50" - ); + "Set blue and orange marker in graph window", + "data setgraphmarkers --> turn off\n" + "data setgraphmarkers -a 64 -b 50" + ); void *argtable[] = { arg_param_begin, arg_u64_0("a", NULL, "", "orange marker"), @@ -1586,9 +1586,9 @@ static int CmdHexsamples(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data hexsamples", - "Dump big buffer as hex bytes", - "data hexsamples -n 128 --> dumps 128 bytes from offset 0" - ); + "Dump big buffer as hex bytes", + "data hexsamples -n 128 --> dumps 128 bytes from offset 0" + ); void *argtable[] = { arg_param_begin, arg_u64_0("b", "breaks", "", "row break, def 16"), @@ -1603,7 +1603,7 @@ static int CmdHexsamples(const char *Cmd) { CLIParserFree(ctx); // sanity checks - if (requested > pm3_capabilities.bigbuf_size) { + if (requested > pm3_capabilities.bigbuf_size) { requested = pm3_capabilities.bigbuf_size; PrintAndLogEx(INFO, "n is larger than big buffer size, will use %u", requested); } @@ -1611,10 +1611,10 @@ static int CmdHexsamples(const char *Cmd) { uint8_t got[pm3_capabilities.bigbuf_size]; if (offset + requested > sizeof(got)) { PrintAndLogEx(NORMAL, "Tried to read past end of buffer, + > %d" - , requested - , offset - , pm3_capabilities.bigbuf_size - ); + , requested + , offset + , pm3_capabilities.bigbuf_size + ); return PM3_EINVARG; } @@ -1630,9 +1630,9 @@ static int CmdHexsamples(const char *Cmd) { static int CmdHide(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data hide", - "Show graph window", - "data hide" - ); + "Show graph window", + "data hide" + ); void *argtable[] = { arg_param_begin, arg_param_end @@ -1647,9 +1647,9 @@ static int CmdHide(const char *Cmd) { int CmdHpf(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data hpf", - "Remove DC offset from trace. It should centralize around 0", - "data hpf" - ); + "Remove DC offset from trace. It should centralize around 0", + "data hpf" + ); void *argtable[] = { arg_param_begin, arg_param_end @@ -1762,13 +1762,13 @@ static int CmdSamples(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data samples", - "Get raw samples for graph window (GraphBuffer) from device.\n" - "If 0, then get whole big buffer from device.", - "data samples" - ); + "Get raw samples for graph window (GraphBuffer) from device.\n" + "If 0, then get whole big buffer from device.", + "data samples" + ); void *argtable[] = { arg_param_begin, - arg_int0("n","", "", "num of samples (512 - 40000)"), + arg_int0("n", "", "", "num of samples (512 - 40000)"), arg_lit0("v", "verbose", "verbose"), arg_param_end }; @@ -1783,11 +1783,11 @@ int CmdTuneSamples(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data tune", - "Measure tuning of device antenna. Results shown in graph window.\n" - "This command doesn't actively tune your antennas, \n" - "it's only informative by measuring voltage that the antennas will generate", - "data tune" - ); + "Measure tuning of device antenna. Results shown in graph window.\n" + "This command doesn't actively tune your antennas, \n" + "it's only informative by measuring voltage that the antennas will generate", + "data tune" + ); void *argtable[] = { arg_param_begin, arg_param_end @@ -2038,9 +2038,9 @@ static int CmdLoad(const char *Cmd) { int CmdLtrim(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data ltrim", - "Trim samples from left of trace", - "data ltrim -i 300 --> keep 300 - end" - ); + "Trim samples from left of trace", + "data ltrim -i 300 --> keep 300 - end" + ); void *argtable[] = { arg_param_begin, arg_u64_1("i", "idx", "", "from index to beginning trace"), @@ -2070,9 +2070,9 @@ static int CmdRtrim(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data rtrim", - "Trim samples from right of trace", - "data rtrim -i 4000 --> keep 0 - 4000" - ); + "Trim samples from right of trace", + "data rtrim -i 4000 --> keep 0 - 4000" + ); void *argtable[] = { arg_param_begin, arg_u64_1("i", "idx", "", "from index to end trace"), @@ -2098,9 +2098,9 @@ static int CmdMtrim(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data mtrim", - "Trim out samples from the specified start to the specified end point", - "data mtrim -s 1000 -e 2000 --> keep between 1000 and 2000" - ); + "Trim out samples from the specified start to the specified end point", + "data mtrim -s 1000 -e 2000 --> keep between 1000 and 2000" + ); void *argtable[] = { arg_param_begin, arg_u64_1("s", "start", "", "start point"), @@ -2132,9 +2132,9 @@ int CmdNorm(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data norm", - "Normalize max/min to +/-128", - "data norm" - ); + "Normalize max/min to +/-128", + "data norm" + ); void *argtable[] = { arg_param_begin, arg_param_end @@ -2169,10 +2169,10 @@ int CmdNorm(const char *Cmd) { int CmdPlot(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data plot", - "Show graph window \n" - "hit 'h' in window for detail keystroke help available", - "data plot" - ); + "Show graph window \n" + "hit 'h' in window for detail keystroke help available", + "data plot" + ); void *argtable[] = { arg_param_begin, arg_param_end @@ -2280,9 +2280,9 @@ int directionalThreshold(const int *in, int *out, size_t len, int8_t up, int8_t static int CmdDirectionalThreshold(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data dirthreshold", - "Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev.", - "data dirthreshold -u 10 -d -10" - ); + "Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev.", + "data dirthreshold -u 10 -d -10" + ); void *argtable[] = { arg_param_begin, arg_int1("d", "down", "", "threshold down"), @@ -2311,9 +2311,9 @@ static int CmdDirectionalThreshold(const char *Cmd) { static int CmdZerocrossings(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data zerocrossings", - "Count time between zero-crossings", - "data zerocrossings" - ); + "Count time between zero-crossings", + "data zerocrossings" + ); void *argtable[] = { arg_param_begin, arg_param_end @@ -2359,10 +2359,10 @@ static int Cmdbin2hex(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data bin2hex", - "This function converts binary to hexadecimal. It will ignore all\n" - "characters not 1 or 0 but stop reading on whitespace", - "data bin2hex -d 0101111001010" - ); + "This function converts binary to hexadecimal. It will ignore all\n" + "characters not 1 or 0 but stop reading on whitespace", + "data bin2hex -d 0101111001010" + ); void *argtable[] = { arg_param_begin, arg_strx0("d", "data", "", "binary string to convert"), @@ -2378,8 +2378,8 @@ static int Cmdbin2hex(const char *Cmd) { PrintAndLogEx(FAILED, "Error parsing binary string"); return PM3_EINVARG; } - - // Number of digits supplied as argument + + // Number of digits supplied as argument size_t bytelen = (blen + 7) / 8; uint8_t *arr = (uint8_t *) calloc(bytelen, sizeof(uint8_t)); memset(arr, 0, bytelen); @@ -2406,10 +2406,10 @@ static int Cmdbin2hex(const char *Cmd) { static int Cmdhex2bin(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data hex2bin", - "This function converts hexadecimal to binary. It will ignore all\n" - "non-hexadecimal characters but stop reading on whitespace", - "data hex2bin -d 01020304" - ); + "This function converts hexadecimal to binary. It will ignore all\n" + "non-hexadecimal characters but stop reading on whitespace", + "data hex2bin -d 01020304" + ); void *argtable[] = { arg_param_begin, arg_str0("d", "data", "", "bytes to convert"), @@ -2427,11 +2427,11 @@ static int Cmdhex2bin(const char *Cmd) { } for (int i = 0; i < dlen; i++) { - char x = data[i]; - if (isxdigit(x) == false) { - PrintAndLogEx(ERR, "Non hex digit found"); - return PM3_EINVARG; - } + char x = data[i]; + if (isxdigit(x) == false) { + PrintAndLogEx(ERR, "Non hex digit found"); + return PM3_EINVARG; + } } PrintAndLogEx(SUCCESS, "" NOLF); @@ -2598,7 +2598,7 @@ static int FSKToNRZ(int *data, size_t *dataLen, uint8_t clk, uint8_t LowToneFC, } static int CmdFSKToNRZ(const char *Cmd) { - + CLIParserContext *ctx; CLIParserInit(&ctx, "data fsktonrz", "Convert fsk2 to nrz wave for alternate fsk demodulating (for weak fsk)\n" @@ -2632,9 +2632,9 @@ static int CmdDataIIR(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data iir", - "Apply IIR buttersworth filter on plot data", - "data iir -n 2" - ); + "Apply IIR buttersworth filter on plot data", + "data iir -n 2" + ); void *argtable[] = { arg_param_begin, arg_u64_1("n", NULL, "", "factor n"), @@ -2703,7 +2703,7 @@ typedef struct { static int print_modulation(lf_modulation_t b) { PrintAndLogEx(INFO, " Modulation........ " _GREEN_("%s"), GetSelectedModulationStr(b.modulation)); PrintAndLogEx(INFO, " Bit clock......... " _GREEN_("RF/%d"), b.bitrate); - PrintAndLogEx(INFO, " Approx baudrate... " _GREEN_("%.f") "bauds", (125000 / (float)b.bitrate) ); + PrintAndLogEx(INFO, " Approx baudrate... " _GREEN_("%.f") "bauds", (125000 / (float)b.bitrate)); switch (b.modulation) { case DEMOD_PSK1: case DEMOD_PSK2: diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index 45777fdce..22cfaab4d 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -1151,7 +1151,7 @@ static int CmdHF14BWriteSri(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, false); int blockno = arg_get_int_def(ctx, 1, -1); int dlen = 0; - uint8_t data[4] = {0,0,0,0}; + uint8_t data[4] = {0, 0, 0, 0}; int res = CLIParamHexToBuf(arg_get_str(ctx, 2), data, sizeof(data), &dlen); if (res) { CLIParserFree(ctx); @@ -1170,7 +1170,7 @@ static int CmdHF14BWriteSri(const char *Cmd) { if (use_sri512 + use_srix4k > 1) { PrintAndLogEx(FAILED, "Select only one card type"); - return PM3_EINVARG; + return PM3_EINVARG; } if (use_srix4k && blockno > 0x7F) { diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index d788dc52b..ea9ced998 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -442,7 +442,7 @@ static int getUID(bool loop, uint8_t *buf) { if (loop == false) { break; } - } + } } } while (loop && kbd_enter_pressed() == false); @@ -470,7 +470,7 @@ static uint8_t arg_add_default(void *at[]) { at[5] = arg_lit0("o", "opt", "set OPTION Flag (needed for TI)"); return 6; } -static uint16_t arg_get_raw_flag(uint8_t uidlen, bool unaddressed, bool scan, bool add_option ) { +static uint16_t arg_get_raw_flag(uint8_t uidlen, bool unaddressed, bool scan, bool add_option) { uint16_t flags = 0; if (unaddressed) { // unaddressed mode may not be supported by all vendors @@ -800,15 +800,15 @@ static int NxpSysInfo(uint8_t *uid) { */ static int CmdHF15Info(const char *Cmd) { - CLIParserContext *ctx; + CLIParserContext *ctx; CLIParserInit(&ctx, "hf 15 info", "Uses the optional command `get_systeminfo` 0x2B to try and extract information", "hf 15 info\n" "hf 15 info -*\n" "hf 15 info -u E011223344556677" - ); + ); - void *argtable[6+1] = {}; + void *argtable[6 + 1] = {}; uint8_t arglen = arg_add_default(argtable); argtable[arglen++] = arg_param_end; @@ -844,7 +844,7 @@ static int CmdHF15Info(const char *Cmd) { if (getUID(false, uid) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "no tag found"); return PM3_EINVARG; - } + } uidlen = 8; } @@ -853,7 +853,7 @@ static int CmdHF15Info(const char *Cmd) { memcpy(req + reqlen, uid, sizeof(uid)); reqlen += sizeof(uid); } - PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); + PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); AddCrc15(req, reqlen); @@ -1079,9 +1079,9 @@ static int CmdHF15WriteAfi(const char *Cmd) { "Write AFI on card", "hf 15 writeafi -* --afi 12\n" "hf 15 writeafi -u E011223344556677 --afi 12" - ); + ); - void *argtable[6+2] = {}; + void *argtable[6 + 2] = {}; uint8_t arglen = arg_add_default(argtable); argtable[arglen++] = arg_int1(NULL, "afi", "", "AFI number (0-255)"); argtable[arglen++] = arg_param_end; @@ -1124,7 +1124,7 @@ static int CmdHF15WriteAfi(const char *Cmd) { memcpy(req + reqlen, uid, sizeof(uid)); reqlen += sizeof(uid); } - PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); + PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); } // enforce, since we are writing @@ -1176,9 +1176,9 @@ static int CmdHF15WriteDsfid(const char *Cmd) { "Write DSFID on card", "hf 15 writedsfid -* --dsfid 12\n" "hf 15 writedsfid -u E011223344556677 --dsfid 12" - ); + ); - void *argtable[6+2] = {}; + void *argtable[6 + 2] = {}; uint8_t arglen = arg_add_default(argtable); argtable[arglen++] = arg_int1(NULL, "dsfid", "", "DSFID number (0-255)"); argtable[arglen++] = arg_param_end; @@ -1223,7 +1223,7 @@ static int CmdHF15WriteDsfid(const char *Cmd) { memcpy(req + reqlen, uid, sizeof(uid)); reqlen += sizeof(uid); } - PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); + PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); } // dsfid @@ -1239,7 +1239,7 @@ static int CmdHF15WriteDsfid(const char *Cmd) { // arg2 (recv == 1 == expect a response) uint8_t read_respone = 1; - PrintAndLogEx(DEBUG, "cmd %s", sprint_hex(req, reqlen) ); + PrintAndLogEx(DEBUG, "cmd %s", sprint_hex(req, reqlen)); PacketResponseNG resp; clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO15693_COMMAND, reqlen, fast, read_respone, req, reqlen); @@ -1277,12 +1277,12 @@ static int CmdHF15Dump(const char *Cmd) { "hf 15 dump\n" "hf 15 dump -*\n" "hf 15 dump -u E011223344556677 -f hf-15-my-dump.bin" - ); + ); - void *argtable[6+2] = {}; + void *argtable[6 + 2] = {}; uint8_t arglen = arg_add_default(argtable); argtable[arglen++] = arg_str0("f", "file", "", "filename of dump"), - argtable[arglen++] = arg_param_end; + argtable[arglen++] = arg_param_end; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -1321,7 +1321,7 @@ static int CmdHF15Dump(const char *Cmd) { if (getUID(false, uid) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "no tag found"); return PM3_EINVARG; - } + } uidlen = 8; } @@ -1330,7 +1330,7 @@ static int CmdHF15Dump(const char *Cmd) { memcpy(req + reqlen, uid, sizeof(uid)); reqlen += sizeof(uid); } - PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); + PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); // detect blocksize from card :) @@ -1409,12 +1409,12 @@ static int CmdHF15Dump(const char *Cmd) { sprintf(lck, "%d", mem[i].lock); } PrintAndLogEx(INFO, "%3d/0x%02X | %s | %s | %s" - , i - , i - , sprint_hex(mem[i].block, 4) - , lck - , sprint_ascii(mem[i].block, 4) - ); + , i + , i + , sprint_hex(mem[i].block, 4) + , lck + , sprint_ascii(mem[i].block, 4) + ); } PrintAndLogEx(NORMAL, ""); @@ -1449,7 +1449,7 @@ static int CmdHF15Raw(const char *Cmd) { "Sends raw bytes over ISO-15693 to card", "hf 15 raw -c -d 260100 --> add crc\n" "hf 15 raw -krc -d 260100 --> add crc, keep field on, skip response" - ); + ); void *argtable[] = { arg_param_begin, @@ -1517,9 +1517,9 @@ static int CmdHF15Readmulti(const char *Cmd) { "Read multiple pages on a ISO-15693 tag ", "hf 15 rdmulti -* -b 1 --cnt 6 -> read 6 blocks\n" "hf 15 rdmulti -u E011223344556677 -b 12 --cnt 3 -> read three blocks" - ); + ); - void *argtable[6+3] = {}; + void *argtable[6 + 3] = {}; uint8_t arglen = arg_add_default(argtable); argtable[arglen++] = arg_int1("b", NULL, "", "first page number (0-255)"); argtable[arglen++] = arg_int1(NULL, "cnt", "", "number of pages (1-6)"); @@ -1570,7 +1570,7 @@ static int CmdHF15Readmulti(const char *Cmd) { memcpy(req + reqlen, uid, sizeof(uid)); reqlen += sizeof(uid); } - PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); + PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); } // add OPTION flag, in order to get lock-info req[0] |= ISO15_REQ_OPTION; @@ -1653,9 +1653,9 @@ static int CmdHF15Readblock(const char *Cmd) { "Read page on ISO-15693 tag", "hf 15 rdbl -* -b 12\n" "hf 15 rdbl -u E011223344556677 -b 12" - ); + ); - void *argtable[6+2] = {}; + void *argtable[6 + 2] = {}; uint8_t arglen = arg_add_default(argtable); argtable[arglen++] = arg_int1("b", "blk", "", "page number (0-255)"); argtable[arglen++] = arg_param_end; @@ -1679,7 +1679,7 @@ static int CmdHF15Readblock(const char *Cmd) { return PM3_EINVARG; } - // default fallback to scan for tag. + // default fallback to scan for tag. // overriding unaddress parameter :) if (uidlen != 8) { scan = true; @@ -1704,7 +1704,7 @@ static int CmdHF15Readblock(const char *Cmd) { memcpy(req + reqlen, uid, sizeof(uid)); reqlen += sizeof(uid); } - PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); + PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); } // add OPTION flag, in order to get lock-info req[0] |= ISO15_REQ_OPTION; @@ -1819,9 +1819,9 @@ static int CmdHF15Write(const char *Cmd) { "Write block on ISO-15693 tag", "hf 15 wrbl -* -b 12 -d AABBCCDD\n" "hf 15 wrbl -u E011223344556677 -b 12 -d AABBCCDD" - ); + ); - void *argtable[6+4] = {}; + void *argtable[6 + 4] = {}; uint8_t arglen = arg_add_default(argtable); argtable[arglen++] = arg_int1("b", "blk", "", "page number (0-255)"); argtable[arglen++] = arg_str1("d", "data", "", "data, 4 bytes"); @@ -1856,7 +1856,7 @@ static int CmdHF15Write(const char *Cmd) { return PM3_EINVARG; } - // default fallback to scan for tag. + // default fallback to scan for tag. // overriding unaddress parameter :) if (uidlen != 8) { scan = true; @@ -1884,7 +1884,7 @@ static int CmdHF15Write(const char *Cmd) { memcpy(req + reqlen, uid, sizeof(uid)); reqlen += sizeof(uid); } - PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); + PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); } @@ -1913,14 +1913,14 @@ static int CmdHF15Restore(const char *Cmd) { "hf 15 restore\n" "hf 15 restore -*\n" "hf 15 restore -u E011223344556677 -f hf-15-my-dump.bin" - ); + ); - void *argtable[6+5] = {}; + void *argtable[6 + 5] = {}; uint8_t arglen = arg_add_default(argtable); argtable[arglen++] = arg_str0("f", "file", "", "filename of dump"), - argtable[arglen++] = arg_int0("r", "retry", "", "number of retries (def 3)"), - argtable[arglen++] = arg_int0(NULL, "bs", "", "block size (def 4)"), - argtable[arglen++] = arg_lit0("v", "verbose", "verbose output"); + argtable[arglen++] = arg_int0("r", "retry", "", "number of retries (def 3)"), + argtable[arglen++] = arg_int0(NULL, "bs", "", "block size (def 4)"), + argtable[arglen++] = arg_lit0("v", "verbose", "verbose output"); argtable[arglen++] = arg_param_end; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -1950,7 +1950,7 @@ static int CmdHF15Restore(const char *Cmd) { return PM3_EINVARG; } - // default fallback to scan for tag. + // default fallback to scan for tag. // overriding unaddress parameter :) if (uidlen != 8) { scan = true; @@ -1968,7 +1968,7 @@ static int CmdHF15Restore(const char *Cmd) { if (getUID(false, uid) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "no tag found"); return PM3_EINVARG; - } + } uidlen = 8; } @@ -1977,9 +1977,9 @@ static int CmdHF15Restore(const char *Cmd) { memcpy(req + reqlen, uid, sizeof(uid)); reqlen += sizeof(uid); } - PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); + PrintAndLogEx(SUCCESS, "Using UID... " _GREEN_("%s"), iso15693_sprintUID(NULL, uid)); } else { - PrintAndLogEx(SUCCESS, "Using unaddressed mode"); + PrintAndLogEx(SUCCESS, "Using unaddressed mode"); } PrintAndLogEx(INFO, "Using block size... %d", blocksize); diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index d2ce89fa6..7e71fa175 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -39,10 +39,10 @@ static void print_status_flag1_interpretation(void) { PrintAndLogEx(INFO, "----+--------------------------------------------------------------------------------------------------------------------"); PrintAndLogEx(INFO, " 00 | Indicates the successful completion of a command."); PrintAndLogEx(INFO, " FF | If an error occurs during the processing of a command that includes no list in the command packet, \n" - " | or if an error occurs independently of any list, the card returns a response by setting FFh to Status Flag1."); + " | or if an error occurs independently of any list, the card returns a response by setting FFh to Status Flag1."); PrintAndLogEx(INFO, " XX | If an error occurs while processing a command that includes Service Code List or Block List \n" - " | in the command packet, the card returns a response by setting a number in the list to Status Flag1,\n" - " | indicating the location of the error."); + " | in the command packet, the card returns a response by setting a number in the list to Status Flag1,\n" + " | indicating the location of the error."); PrintAndLogEx(INFO, "----+--------------------------------------------------------------------------------------------------------------------"); } @@ -51,28 +51,28 @@ static void print_status_flag2_interpration(void) { PrintAndLogEx(INFO, "----+--------------------------------------------------------------------------------------------------------------------"); PrintAndLogEx(INFO, " 00 | Indicates the successful completion of a command."); PrintAndLogEx(INFO, " 01 | The calculated result is either less than zero when the purse data is decremented, or exceeds 4\n" - " | Bytes when the purse data is incremented."); + " | Bytes when the purse data is incremented."); PrintAndLogEx(INFO, " 02 | The specified data exceeds the value of cashback data at cashback of purse."); PrintAndLogEx(INFO, " 70 | Memory error (fatal error)."); PrintAndLogEx(INFO, " 71 | The number of memory rewrites exceeds the upper limit (this is only a warning; data writing is performed as normal).\n" - " | The maximum number of rewrites can differ, depending on the product being used.\n" - " | In addition, Status Flag1 is either 00h or FFh depending on the product being used."); + " | The maximum number of rewrites can differ, depending on the product being used.\n" + " | In addition, Status Flag1 is either 00h or FFh depending on the product being used."); PrintAndLogEx(INFO, " A1 | Illegal Number of Service| Number of Service or Number of Node specified by the command \n" - " | falls outside the range of the prescribed value."); + " | falls outside the range of the prescribed value."); PrintAndLogEx(INFO, " A2 | Illegal command packet (specified Number of Block) : Number of Block specified by the \n" - " | command falls outside the range of the prescribed values for the product."); + " | command falls outside the range of the prescribed values for the product."); PrintAndLogEx(INFO, " A3 | Illegal Block List (specified order of Service) : Service Code List Order specified by \n" - " | Block List Element falls outside the Number of Service specified by the command \n" - " | (or the Number of Service specified at the times of mutual authentication)."); + " | Block List Element falls outside the Number of Service specified by the command \n" + " | (or the Number of Service specified at the times of mutual authentication)."); PrintAndLogEx(INFO, " A4 | Illegal Service type : Area Attribute specified by the command or Service Attribute of Service Code is incorrect."); PrintAndLogEx(INFO, " A5 | Access is not allowed : Area or Service specified by the command cannot be accessed.\n" - " | The parameter specified by the command does not satisfy the conditions for success."); + " | The parameter specified by the command does not satisfy the conditions for success."); PrintAndLogEx(INFO, " A6 | Illegal Service Code List : Target to be accessed, identified by Service Code List Order, specified by Block\n" - " | List Element does not exist. Or, Node specified by Node Code List does not exist."); + " | List Element does not exist. Or, Node specified by Node Code List does not exist."); PrintAndLogEx(INFO, " A7 | Illegal Block List (Access Mode) : Access Mode specified by Block List Element is incorrect."); PrintAndLogEx(INFO, " A8 | Illegal Block Number Block Number (access to the specified data is inhibited) :\n" - " | specified by Block List Element exceeds the number of Blocks assigned to Service."); + " | specified by Block List Element exceeds the number of Blocks assigned to Service."); PrintAndLogEx(INFO, " A9 | Data write failure : This is the error that occurs in issuance commands."); PrintAndLogEx(INFO, " AA | Key-change failure : Key change failed."); PrintAndLogEx(INFO, " AB | Illegal Package Parity or illegal Package MAC : This is the error that occurs in issuance commands."); @@ -80,7 +80,7 @@ static void print_status_flag2_interpration(void) { PrintAndLogEx(INFO, " AD | Service exists already : This is the error that occurs in issuance commands."); PrintAndLogEx(INFO, " AE | Illegal System Code : This is the error that occurs in issuance commands."); PrintAndLogEx(INFO, " AF | Too many simultaneous cyclic write operations : Number of simultaneous write Blocks\n" - " | specified by the command to Cyclic Service exceeds the number of Blocks assigned to Service."); + " | specified by the command to Cyclic Service exceeds the number of Blocks assigned to Service."); PrintAndLogEx(INFO, " C0 | Illegal Package Identifier : This is the error that occurs in issuance commands."); PrintAndLogEx(INFO, " C1 | Discrepancy of parameters inside and outside Package : This is the error that occurs in issuance commands."); PrintAndLogEx(INFO, " C2 | Command is disabled already : This is the error that occurs in issuance commands."); @@ -111,9 +111,9 @@ static void print_number_of_block_constraints(void) { static void print_service_code_list_constraints(void) { PrintAndLogEx(INFO, " - Service Code List: For Service Code List, only Service Code existing in the product shall be specified:"); PrintAndLogEx(INFO, " - Even when Service Code exists in the product, Service Code not referenced from Block List shall not \n" - " be specified to Service Code List."); + " be specified to Service Code List."); PrintAndLogEx(INFO, " - For existence or nonexistence of Service in a product, please check using the Request Service \n" - " (or Request Service v2) command."); + " (or Request Service v2) command."); } /* @@ -209,7 +209,7 @@ static bool add_last_IDm(uint8_t position, uint8_t *data) { if (last_known_card.IDm[0] != 0 && last_known_card.IDm[1] != 0) { memcpy(data + position, last_known_card.IDm, sizeof(last_known_card.IDm)); return true; - } + } return false; } @@ -447,7 +447,7 @@ static bool check_last_idm(uint8_t *data, uint16_t datalen) { PrintAndLogEx(WARNING, "No last known card! Use `" _YELLOW_("hf felica reader") "` first or set a custom IDm"); return false; } - + PrintAndLogEx(INFO, "Using last known IDm... " _GREEN_("%s"), sprint_hex_inrow(data, datalen)); return true; } @@ -467,7 +467,7 @@ static int send_wr_plain(uint8_t flags, uint16_t datalen, uint8_t *data, bool ve if (waitCmdFelica(0, &resp, verbose) == false) { PrintAndLogEx(ERR, "no response from card"); return PM3_ERFTRANS; - } + } memcpy(wr_noCry_resp, (felica_status_response_t *)resp.data.asBytes, sizeof(felica_status_response_t)); return PM3_SUCCESS; @@ -493,13 +493,13 @@ static void reverse_3des_key(uint8_t *master_key, int length, uint8_t *reverse_m static int CmdHFFelicaAuthentication1(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf felica auth1", - "Initiate mutual authentication. This command must always be executed before Auth2 command\n" - "and mutual authentication is achieve only after Auth2 command has succeeded.\n" - _RED_("INCOMPLETE / EXPERIMENTAL COMMAND!!!"), - "hf felica auth1 --an 01 --acl 0000 --sn 01 --scl 8B00 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n" - "hf felica auth1 --an 01 --acl 0000 --sn 01 --scl 8B00 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAA\n" - "hf felica auth1 -i 11100910C11BC407 --an 01 --acl 0000 --sn 01 ..scl 8B00 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n" - ); + "Initiate mutual authentication. This command must always be executed before Auth2 command\n" + "and mutual authentication is achieve only after Auth2 command has succeeded.\n" + _RED_("INCOMPLETE / EXPERIMENTAL COMMAND!!!"), + "hf felica auth1 --an 01 --acl 0000 --sn 01 --scl 8B00 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n" + "hf felica auth1 --an 01 --acl 0000 --sn 01 --scl 8B00 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAA\n" + "hf felica auth1 -i 11100910C11BC407 --an 01 --acl 0000 --sn 01 ..scl 8B00 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n" + ); void *argtable[] = { arg_param_begin, arg_str0(NULL, "an", "", "number of areas, 1 byte"), @@ -569,7 +569,7 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { } uint8_t data[PM3_CMD_DATA_SIZE]; - memset(data, 0 , sizeof(data)); + memset(data, 0, sizeof(data)); data[0] = 0x0C; // Static length data[1] = 0x3E; // Command ID @@ -580,14 +580,14 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { memcpy(data + 2, idm, 8); } - // Length (1), - // Command ID (1), - // IDm (8), - // Number of Area (1), - // Area Code List (2), - // Number of Service (1), - // Service Code List (2), - // M1c (16) + // Length (1), + // Command ID (1), + // IDm (8), + // Number of Area (1), + // Area Code List (2), + // Number of Service (1), + // Service Code List (2), + // M1c (16) uint16_t datalen = 32; data[0] = (datalen & 0xFF); data[1] = 0x10; // Command ID @@ -597,14 +597,14 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { } if (anlen) { - data[10] = an[0]; + data[10] = an[0]; } if (acllen) { data[11] = acl[0]; data[12] = acl[1]; } if (snlen) { - data[13] = sn[0]; + data[13] = sn[0]; } if (scllen) { data[14] = scl[0]; @@ -615,7 +615,7 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { } // READER CHALLENGE - (RANDOM To Encrypt = Rac) - uint8_t nonce[8] = {1,2,3,4,5,6,7,8}; + uint8_t nonce[8] = {1, 2, 3, 4, 5, 6, 7, 8}; PrintAndLogEx(INFO, "Reader challenge (unencrypted): %s", sprint_hex(nonce, 8)); // Create M1c Challenge with 3DES (3 Keys = 24, 2 Keys = 16) @@ -624,7 +624,7 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { mbedtls_des3_init(&des3_ctx); if (keylen == 24) { - + mbedtls_des3_set3key_enc(&des3_ctx, master_key); PrintAndLogEx(INFO, "3DES Master Secret: %s", sprint_hex(master_key, keylen)); @@ -659,8 +659,8 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { if (waitCmdFelica(0, &resp, 1) == false) { PrintAndLogEx(ERR, "no response from card"); return PM3_ERFTRANS; - } - + } + felica_auth1_response_t auth1_response; memcpy(&auth1_response, (felica_auth1_response_t *)resp.data.asBytes, sizeof(felica_auth1_response_t)); @@ -710,12 +710,12 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf felica auth2", - "Complete mutual authentication. This command can only be executed subsquent to Auth1\n" - _RED_("INCOMPLETE / EXPERIMENTAL COMMAND!!!\n") - _RED_("EXPERIMENTAL COMMAND - M2c/P2c will be not checked"), - "hf felica auth2 --cc 0102030405060708 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n" - "hf felica auth2 -i 11100910C11BC407 --cc 0102030405060708 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n" - ); + "Complete mutual authentication. This command can only be executed subsquent to Auth1\n" + _RED_("INCOMPLETE / EXPERIMENTAL COMMAND!!!\n") + _RED_("EXPERIMENTAL COMMAND - M2c/P2c will be not checked"), + "hf felica auth2 --cc 0102030405060708 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n" + "hf felica auth2 -i 11100910C11BC407 --cc 0102030405060708 --key AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n" + ); void *argtable[] = { arg_param_begin, arg_str0("i", NULL, "", "set custom IDm"), @@ -758,7 +758,7 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { } uint8_t data[PM3_CMD_DATA_SIZE]; - memset(data, 0 , sizeof(data)); + memset(data, 0, sizeof(data)); bool custom_IDm = false; @@ -776,7 +776,7 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { } if (cclen) { - memcpy(data + 16, cc, cclen); + memcpy(data + 16, cc, cclen); } if (keylen) { @@ -791,7 +791,7 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { // M3c (8) == cc // unsigned char m3c[8]; == cc - + mbedtls_des3_context des3_ctx_enc; mbedtls_des3_context des3_ctx_dec; @@ -824,7 +824,7 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { unsigned char p3c[8]; mbedtls_des3_crypt_ecb(&des3_ctx_dec, cc, p3c); PrintAndLogEx(INFO, "3DES decrypted M3c = P3c... %s", sprint_hex_inrow(p3c, sizeof(p3c))); - + // Encrypt p3c with master_key unsigned char m4c[8]; mbedtls_des3_crypt_ecb(&des3_ctx_enc, p3c, m4c); @@ -848,7 +848,7 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { if (waitCmdFelica(0, &resp, 1) == false) { PrintAndLogEx(ERR, "no response from card"); return PM3_ERFTRANS; - } + } felica_auth2_response_t auth2_response; memcpy(&auth2_response, (felica_auth2_response_t *)resp.data.asBytes, sizeof(felica_auth2_response_t)); @@ -954,7 +954,7 @@ static int CmdHFFelicaWritePlain(const char *Cmd) { } uint8_t data[PM3_CMD_DATA_SIZE]; - memset(data, 0 , sizeof(data)); + memset(data, 0, sizeof(data)); data[0] = 0x20; // Static length data[1] = 0x08; // Command ID @@ -1115,7 +1115,7 @@ static int CmdHFFelicaReadPlain(const char *Cmd) { } uint8_t data[PM3_CMD_DATA_SIZE]; - memset(data, 0 , sizeof(data)); + memset(data, 0, sizeof(data)); data[0] = 0x10; // Static length data[1] = 0x06; // Command ID @@ -1152,7 +1152,7 @@ static int CmdHFFelicaReadPlain(const char *Cmd) { PrintAndLogEx(INFO, "block | data "); PrintAndLogEx(INFO, "------+----------------------------------------"); - + // main loop block reads if (all_block_list_elements) { @@ -1217,7 +1217,7 @@ static int CmdHFFelicaRequestResponse(const char *Cmd) { CLIParserFree(ctx); uint8_t data[PM3_CMD_DATA_SIZE]; - memset(data, 0 , sizeof(data)); + memset(data, 0, sizeof(data)); data[0] = 0x0A; // Static length data[1] = 0x04; // Command ID @@ -1294,7 +1294,7 @@ static int CmdHFFelicaRequestSpecificationVersion(const char *Cmd) { return PM3_EINVARG; } - uint8_t reserved[2] = {0,0}; + uint8_t reserved[2] = {0, 0}; int rlen = 0; res = CLIParamHexToBuf(arg_get_str(ctx, 2), reserved, sizeof(reserved), &rlen); if (res) { @@ -1310,7 +1310,7 @@ static int CmdHFFelicaRequestSpecificationVersion(const char *Cmd) { CLIParserFree(ctx); uint8_t data[PM3_CMD_DATA_SIZE]; - memset(data, 0 , sizeof(data)); + memset(data, 0, sizeof(data)); data[0] = 0x0C; // Static length data[1] = 0x3C; // Command ID @@ -1322,9 +1322,9 @@ static int CmdHFFelicaRequestSpecificationVersion(const char *Cmd) { memcpy(data + 2, idm, sizeof(idm)); } - // add custom reserved - if (rlen ) { - memcpy(data +10, reserved, sizeof(reserved)); + // add custom reserved + if (rlen) { + memcpy(data + 10, reserved, sizeof(reserved)); } else { data[10] = 0x00; // Reserved Value data[11] = 0x00; // Reserved Value @@ -1337,7 +1337,7 @@ static int CmdHFFelicaRequestSpecificationVersion(const char *Cmd) { AddCrc(data, datalen); datalen += 2; - uint8_t flags = (FELICA_APPEND_CRC |FELICA_RAW); + uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW); clear_and_send_command(flags, datalen, data, 0); @@ -1346,7 +1346,7 @@ static int CmdHFFelicaRequestSpecificationVersion(const char *Cmd) { PrintAndLogEx(FAILED, "Got no response from card"); return PM3_ERFTRANS; } - + felica_request_spec_response_t spec_response; memcpy(&spec_response, (felica_request_spec_response_t *)resp.data.asBytes, sizeof(felica_request_spec_response_t)); @@ -1401,7 +1401,7 @@ static int CmdHFFelicaResetMode(const char *Cmd) { return PM3_EINVARG; } - uint8_t reserved[2] = {0,0}; + uint8_t reserved[2] = {0, 0}; int rlen = 0; res = CLIParamHexToBuf(arg_get_str(ctx, 2), reserved, sizeof(reserved), &rlen); if (res) { @@ -1417,7 +1417,7 @@ static int CmdHFFelicaResetMode(const char *Cmd) { CLIParserFree(ctx); uint8_t data[PM3_CMD_DATA_SIZE]; - memset(data, 0 , sizeof(data)); + memset(data, 0, sizeof(data)); data[0] = 0x0C; // Static length data[1] = 0x3E; // Command ID @@ -1495,7 +1495,7 @@ static int CmdHFFelicaRequestSystemCode(const char *Cmd) { uint8_t data[PM3_CMD_DATA_SIZE]; - memset(data, 0 , sizeof(data)); + memset(data, 0, sizeof(data)); data[0] = 0x0A; // Static length data[1] = 0x0C; // Command ID @@ -1578,7 +1578,7 @@ static int CmdHFFelicaRequestService(const char *Cmd) { return PM3_EINVARG; } - uint8_t code[2] = {0,0}; + uint8_t code[2] = {0, 0}; int clen = 0; res = CLIParamHexToBuf(arg_get_str(ctx, 3), code, sizeof(code), &clen); if (res) { @@ -1596,7 +1596,7 @@ static int CmdHFFelicaRequestService(const char *Cmd) { CLIParserFree(ctx); uint8_t data[PM3_CMD_DATA_SIZE]; - memset(data, 0 , sizeof(data)); + memset(data, 0, sizeof(data)); bool custom_IDm = false; @@ -1608,10 +1608,10 @@ static int CmdHFFelicaRequestService(const char *Cmd) { if (all_nodes == false) { // Node Number if (nlen == 1) { - memcpy(data + 10, node, sizeof(node)); + memcpy(data + 10, node, sizeof(node)); } - // code + // code if (clen == 2) { memcpy(data + 11, code, sizeof(code)); } @@ -2055,7 +2055,7 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { int datalen = 0; uint8_t data[PM3_CMD_DATA_SIZE]; - memset(data, 0 , sizeof(data)); + memset(data, 0, sizeof(data)); CLIGetHexWithReturn(ctx, 7, data, &datalen); CLIParserFree(ctx); diff --git a/client/src/cmdhffido.c b/client/src/cmdhffido.c index d0be26cfd..9fe85a4c8 100644 --- a/client/src/cmdhffido.c +++ b/client/src/cmdhffido.c @@ -181,7 +181,7 @@ static int cmd_hf_fido_register(const char *cmd) { "hf fido reg -> execute command with 2 parameters, filled 0x00\n" "hf fido reg -p s0 s1 -> execute command with plain parameters\n" "hf fido reg --cp 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f --ap 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f\n" - ); + ); void *argtable[] = { arg_param_begin, @@ -693,7 +693,7 @@ static int cmd_hf_fido_2make_credential(const char *cmd) { "Sample file `fido2.json` in `client/resources/`.", "hf fido make -> default parameters file `fido2.json`\n" "hf fido make -f test.json -> use parameters file `text.json`" - ); + ); void *argtable[] = { arg_param_begin, diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index a616de444..7ca124d45 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -352,7 +352,7 @@ static int CmdHF14AMfWrBl(const char *Cmd) { uint8_t block[MFBLOCK_SIZE] = {0x00}; int blen = 0; CLIGetHexWithReturn(ctx, 5, block, &blen); - CLIParserFree(ctx); + CLIParserFree(ctx); if (blen != MFBLOCK_SIZE) { PrintAndLogEx(WARNING, "block data must include 16 HEX bytes. Got %i", blen); @@ -386,7 +386,7 @@ static int CmdHF14AMfWrBl(const char *Cmd) { } else { PrintAndLogEx(FAILED, "Write ( " _RED_("fail") " )"); // suggest the opposite keytype than what was used. - PrintAndLogEx(HINT, "Maybe access rights? Try specify keytype " _YELLOW_("%c") " instead", (keytype == MF_KEY_A) ? 'B' : 'A' ); + PrintAndLogEx(HINT, "Maybe access rights? Try specify keytype " _YELLOW_("%c") " instead", (keytype == MF_KEY_A) ? 'B' : 'A'); } return PM3_SUCCESS; } @@ -423,7 +423,7 @@ static int CmdHF14AMfRdBl(const char *Cmd) { uint8_t key[6] = {0}; CLIGetHexWithReturn(ctx, 4, key, &keylen); bool verbose = arg_get_lit(ctx, 5); - CLIParserFree(ctx); + CLIParserFree(ctx); if (b > 255) { return PM3_EINVARG; @@ -477,7 +477,7 @@ static int CmdHF14AMfRdSc(const char *Cmd) { int s = arg_get_int_def(ctx, 4, 0); bool verbose = arg_get_lit(ctx, 5); - CLIParserFree(ctx); + CLIParserFree(ctx); if (s > MIFARE_4K_MAXSECTOR) { PrintAndLogEx(WARNING, "Sector number must be less then 40"); @@ -504,7 +504,7 @@ static int CmdHF14AMfRdSc(const char *Cmd) { if (verbose) { decode_print_st(start + blocks - 1, data + ((blocks - 1) * MFBLOCK_SIZE)); - } + } } free(data); PrintAndLogEx(NORMAL, ""); @@ -813,7 +813,7 @@ static int CmdHF14AMfRestore(const char *Cmd) { "The key file and data file will program the card sector trailers.\n" "By default we authenticate to card with key B 0xFFFFFFFFFFFF.\n" "\n" - "`--uid` param is used for filename templates `hf-mf--dump.bin` and `hf-mf--key.bin.\n" + "`--uid` param is used for filename templates `hf-mf--dump.bin` and `hf-mf--key.bin.\n" " If not specified, it will read the card uid instead.\n" " `-w` param you can indicate that the key file should be used for authentication instead.\n" " if so we also try both B/A keys", @@ -821,7 +821,7 @@ static int CmdHF14AMfRestore(const char *Cmd) { "hf mf restore --1k --uid 04010203\n" "hf mf restore --1k --uid 04010203 -k hf-mf-AABBCCDD-key.bin\n" "hf mf restore --4k" - ); + ); void *argtable[] = { arg_param_begin, @@ -952,7 +952,7 @@ static int CmdHF14AMfRestore(const char *Cmd) { return PM3_EINVARG; } - // default authentication key + // default authentication key uint8_t default_key[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; PrintAndLogEx(INFO, "Restoring " _YELLOW_("%s")" to card", datafilename); @@ -974,7 +974,7 @@ static int CmdHF14AMfRestore(const char *Cmd) { if (use_keyfile_for_auth == false) { // sector trailer - if (b == NumBlocksPerSector(s) - 1) { + if (b == NumBlocksPerSector(s) - 1) { bldata[0] = (keyA[s][0]); bldata[1] = (keyA[s][1]); bldata[2] = (keyA[s][2]); @@ -1622,7 +1622,7 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { "hf mf hardnested -r --tk a0a1a2a3a4a5\n" "hf mf hardnested -t --tk a0a1a2a3a4a5\n" "hf mf hardnested --blk 0 -a -k a0a1a2a3a4a5 --tblk 4 --ta --tk FFFFFFFFFFFF" - ); + ); void *argtable[] = { arg_param_begin, @@ -1635,7 +1635,7 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { arg_lit0(NULL, "tb", "Target key B"), arg_str0(NULL, "tk", "", "Target key, 12 hex bytes"), // 8 arg_str0("u", "uid", "", "R/W `hf-mf--nonces.bin` instead of default name"), - arg_str0("f", "file", "", "R/W instead of default name"), + arg_str0("f", "file", "", "R/W instead of default name"), arg_lit0("r", "read", "Read `hf-mf--nonces.bin` if tag present, otherwise `nonces.bin`, and start attack"), arg_lit0("s", "slow", "Slower acquisition (required by some non standard cards)"), arg_lit0("t", "tests", "Run tests"), @@ -1751,7 +1751,7 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { free(fptr); } - if (uidlen) { + if (uidlen) { snprintf(filename, FILE_PATH_SIZE, "hf-mf-%s-nonces.bin", uid); } @@ -1774,7 +1774,7 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { PrintAndLogEx(INFO, "Target block no " _YELLOW_("%3d") ", target key type: " _YELLOW_("%c") ", known target key: " _YELLOW_("%02x%02x%02x%02x%02x%02x%s"), trg_blockno, - (trg_keytype == MF_KEY_B)? 'B' : 'A', + (trg_keytype == MF_KEY_B) ? 'B' : 'A', trg_key[0], trg_key[1], trg_key[2], trg_key[3], trg_key[4], trg_key[5], know_target_key ? "" : " (not set)" ); @@ -1808,7 +1808,7 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { static int CmdHF14AMfAutoPWN(const char *Cmd) { - CLIParserContext *ctx; + CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf autopwn", "This command automates the key recovery process on MIFARE Classic cards.\n" "It uses the fchk, chk, darkside, nested, hardnested and staticnested to recover keys.\n" @@ -1817,7 +1817,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { "hf mf autopwn -s 0 -a -k FFFFFFFFFFFF --> target MFC 1K card, Sector 0 with known key A 'FFFFFFFFFFFF'\n" "hf mf autopwn --1k -f mfc_default_keys --> target MFC 1K card, default dictionary\n" "hf mf autopwn --1k -s 0 -a -k FFFFFFFFFFFF -f mfc_default_keys --> combo of the two above samples" - ); + ); void *argtable[] = { arg_param_begin, @@ -1825,7 +1825,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { arg_int0("s", "sector", "", "Input sector number"), arg_lit0("a", NULL, "Input key A (def)"), arg_lit0("b", NULL, "Input key B"), - arg_str0("f", "file", "", "filename of dictionary"), + arg_str0("f", "file", "", "filename of dictionary"), arg_lit0("s", "slow", "Slower acquisition (required by some non standard cards)"), arg_lit0("l", "legacy", "legacy mode (use the slow `hf mf chk`)"), arg_lit0("v", "verbose", "verbose output (statistics)"), @@ -2197,7 +2197,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { } else { PrintAndLogEx(SUCCESS, "target sector %3u key type %c -- found valid key [ " _GREEN_("%s") " ]", i, - (j == MF_KEY_B)? 'B' : 'A', + (j == MF_KEY_B) ? 'B' : 'A', sprint_hex_inrow(tmp_key, sizeof(tmp_key)) ); } @@ -3560,7 +3560,7 @@ static int CmdHF14AMfEGetBlk(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, false); int b = arg_get_int_def(ctx, 1, 0); bool verbose = arg_get_lit(ctx, 2); - CLIParserFree(ctx); + CLIParserFree(ctx); if (b > 255) { return PM3_EINVARG; @@ -3597,7 +3597,7 @@ static int CmdHF14AMfEGetSc(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, false); int s = arg_get_int_def(ctx, 1, 0); bool verbose = arg_get_lit(ctx, 2); - CLIParserFree(ctx); + CLIParserFree(ctx); if (s > 39) { PrintAndLogEx(WARNING, "Sector number must be less then 40"); @@ -3636,7 +3636,7 @@ static int CmdHF14AMfEClear(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - CLIParserFree(ctx); + CLIParserFree(ctx); clearCommandBuffer(); SendCommandNG(CMD_HF_MIFARE_EML_MEMCLR, NULL, 0); return PM3_SUCCESS; @@ -3662,7 +3662,7 @@ static int CmdHF14AMfESet(const char *Cmd) { uint8_t data[16] = {0x00}; int datalen = 0; int res = CLIParamHexToBuf(arg_get_str(ctx, 2), data, sizeof(data), &datalen); - CLIParserFree(ctx); + CLIParserFree(ctx); if (res) { PrintAndLogEx(FAILED, "Error parsing bytes"); return PM3_EINVARG; @@ -3701,7 +3701,7 @@ int CmdHF14AMfELoad(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); - + int fnlen = 0; char filename[FILE_PATH_SIZE]; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); @@ -3714,7 +3714,7 @@ int CmdHF14AMfELoad(const char *Cmd) { int numblks = arg_get_int_def(ctx, 7, -1); - CLIParserFree(ctx); + CLIParserFree(ctx); // validations if ((m0 + m1 + m2 + m4 + mu) > 1) { @@ -3876,7 +3876,7 @@ static int CmdHF14AMfESave(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - + int fnlen = 0; char filename[FILE_PATH_SIZE]; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); @@ -3885,7 +3885,7 @@ static int CmdHF14AMfESave(const char *Cmd) { bool m1 = arg_get_lit(ctx, 3); bool m2 = arg_get_lit(ctx, 4); bool m4 = arg_get_lit(ctx, 5); - CLIParserFree(ctx); + CLIParserFree(ctx); // validations if ((m0 + m1 + m2 + m4) > 1) { @@ -3895,7 +3895,7 @@ static int CmdHF14AMfESave(const char *Cmd) { m1 = true; } - uint16_t block_cnt = MIFARE_1K_MAXBLOCK; + uint16_t block_cnt = MIFARE_1K_MAXBLOCK; if (m0) { block_cnt = MIFARE_MINI_MAXBLOCK; @@ -3959,7 +3959,7 @@ static int CmdHF14AMfEView(const char *Cmd) { bool m1 = arg_get_lit(ctx, 2); bool m2 = arg_get_lit(ctx, 3); bool m4 = arg_get_lit(ctx, 4); - CLIParserFree(ctx); + CLIParserFree(ctx); // validations if ((m0 + m1 + m2 + m4) > 1) { @@ -4038,7 +4038,7 @@ static int CmdHF14AMfECFill(const char *Cmd) { bool m1 = arg_get_lit(ctx, 4); bool m2 = arg_get_lit(ctx, 5); bool m4 = arg_get_lit(ctx, 6); - CLIParserFree(ctx); + CLIParserFree(ctx); // validations if ((m0 + m1 + m2 + m4) > 1) { @@ -4099,7 +4099,7 @@ static int CmdHF14AMfEKeyPrn(const char *Cmd) { bool m1 = arg_get_lit(ctx, 3); bool m2 = arg_get_lit(ctx, 4); bool m4 = arg_get_lit(ctx, 5); - CLIParserFree(ctx); + CLIParserFree(ctx); // validations if ((m0 + m1 + m2 + m4) > 1) { @@ -4209,7 +4209,7 @@ static int CmdHF14AMfCSetUID(const char *Cmd) { int slen = 0; uint8_t sak[1] = {0x00}; CLIGetHexWithReturn(ctx, 4, sak, &slen); - CLIParserFree(ctx); + CLIParserFree(ctx); // sanity checks if (uidlen != 4 && uidlen != 7) { @@ -4229,14 +4229,14 @@ static int CmdHF14AMfCSetUID(const char *Cmd) { uint8_t verify_uid[7] = {0}; int res = mfCSetUID( - uid, - uidlen, - (alen) ? atqa : NULL, - (slen) ? sak : NULL, - old_uid, - verify_uid, - wipe_card - ); + uid, + uidlen, + (alen) ? atqa : NULL, + (slen) ? sak : NULL, + old_uid, + verify_uid, + wipe_card + ); if (res) { PrintAndLogEx(ERR, "Can't set UID. error %d", res); @@ -4247,9 +4247,9 @@ static int CmdHF14AMfCSetUID(const char *Cmd) { PrintAndLogEx(SUCCESS, "Old UID... %s", sprint_hex(old_uid, uidlen)); PrintAndLogEx(SUCCESS, "New UID... %s ( %s )", - sprint_hex(verify_uid, uidlen), - (res == 0) ? _GREEN_("verified") : _RED_("fail") - ); + sprint_hex(verify_uid, uidlen), + (res == 0) ? _GREEN_("verified") : _RED_("fail") + ); return PM3_SUCCESS; } @@ -4273,11 +4273,11 @@ static int CmdHF14AMfCWipe(const char *cmd) { int uidlen = 0; uint8_t uid[8] = {0x00}; CLIGetHexWithReturn(ctx, 1, uid, &uidlen); - + int alen = 0; uint8_t atqa[2] = {0x00}; CLIGetHexWithReturn(ctx, 2, atqa, &alen); - + int slen = 0; uint8_t sak[1] = {0x00}; CLIGetHexWithReturn(ctx, 3, sak, &slen); @@ -4329,9 +4329,9 @@ static int CmdHF14AMfCSetBlk(const char *Cmd) { CLIGetHexWithReturn(ctx, 2, data, &datalen); uint8_t wipe_card = arg_get_lit(ctx, 3); - CLIParserFree(ctx); + CLIParserFree(ctx); - if (b < 0 || b >= MIFARE_1K_MAXBLOCK ) { + if (b < 0 || b >= MIFARE_1K_MAXBLOCK) { PrintAndLogEx(FAILED, "target block number out-of-range, got %i", b); return PM3_EINVARG; } @@ -4372,13 +4372,13 @@ static int CmdHF14AMfCLoad(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); - + int fnlen = 0; char filename[FILE_PATH_SIZE]; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); bool fill_from_emulator = arg_get_lit(ctx, 2); - CLIParserFree(ctx); + CLIParserFree(ctx); if (fill_from_emulator) { @@ -4458,7 +4458,7 @@ static int CmdHF14AMfCLoad(const char *Cmd) { // 64 or 256blocks. if (bytes_read != (MIFARE_1K_MAXBLOCK * MFBLOCK_SIZE) && - bytes_read != (MIFARE_4K_MAXBLOCK * MFBLOCK_SIZE)) { + bytes_read != (MIFARE_4K_MAXBLOCK * MFBLOCK_SIZE)) { PrintAndLogEx(ERR, "File content error. Read %zu bytes", bytes_read); free(data); return PM3_EFILE; @@ -4508,7 +4508,7 @@ static int CmdHF14AMfCLoad(const char *Cmd) { // confirm number written blocks. Must be 64 or 256 blocks if (blockno != MIFARE_1K_MAXBLOCK) { - if (blockno != MIFARE_4K_MAXBLOCK) { + if (blockno != MIFARE_4K_MAXBLOCK) { PrintAndLogEx(ERR, "File content error. There must be %u blocks", MIFARE_4K_MAXBLOCK); return PM3_EFILE; } @@ -4538,7 +4538,7 @@ static int CmdHF14AMfCGetBlk(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, false); int b = arg_get_int_def(ctx, 1, 0); bool verbose = arg_get_lit(ctx, 2); - CLIParserFree(ctx); + CLIParserFree(ctx); if (b > 255) { return PM3_EINVARG; @@ -4555,7 +4555,7 @@ static int CmdHF14AMfCGetBlk(const char *Cmd) { uint8_t sector = GetSectorFromBlockNo(blockno); mf_print_sector_hdr(sector); mf_print_block(blockno, data); - + if (verbose) { decode_print_st(blockno, data); } else { @@ -4580,7 +4580,7 @@ static int CmdHF14AMfCGetSc(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, false); int s = arg_get_int_def(ctx, 1, 0); bool verbose = arg_get_lit(ctx, 2); - CLIParserFree(ctx); + CLIParserFree(ctx); if (s > 39) { PrintAndLogEx(WARNING, "Sector number must be less then 40"); return PM3_EINVARG; @@ -4636,7 +4636,7 @@ static int CmdHF14AMfCSave(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - + int fnlen = 0; char filename[FILE_PATH_SIZE]; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); @@ -4646,7 +4646,7 @@ static int CmdHF14AMfCSave(const char *Cmd) { bool m2 = arg_get_lit(ctx, 4); bool m4 = arg_get_lit(ctx, 5); bool fill_emulator = arg_get_lit(ctx, 6); - CLIParserFree(ctx); + CLIParserFree(ctx); // validations if ((m0 + m1 + m2 + m4) > 1) { @@ -4791,7 +4791,7 @@ static int CmdHF14AMfCView(const char *Cmd) { bool m1 = arg_get_lit(ctx, 2); bool m2 = arg_get_lit(ctx, 3); bool m4 = arg_get_lit(ctx, 4); - CLIParserFree(ctx); + CLIParserFree(ctx); // validations if ((m0 + m1 + m2 + m4) > 1) { @@ -4906,7 +4906,7 @@ static int CmdHf14AMfDecryptBytes(const char *Cmd) { uint32_t nt = 0; int res = arg_get_u32_hexstr_def(ctx, 1, 0, &nt); if (res != 1) { - CLIParserFree(ctx); + CLIParserFree(ctx); PrintAndLogEx(WARNING, "check `nt` parameter"); return PM3_EINVARG; } @@ -4914,7 +4914,7 @@ static int CmdHf14AMfDecryptBytes(const char *Cmd) { uint32_t ar_enc = 0; res = arg_get_u32_hexstr_def(ctx, 2, 0, &ar_enc); if (res != 1) { - CLIParserFree(ctx); + CLIParserFree(ctx); PrintAndLogEx(WARNING, "check `ar` parameter"); return PM3_EINVARG; } @@ -4922,7 +4922,7 @@ static int CmdHf14AMfDecryptBytes(const char *Cmd) { uint32_t at_enc = 0; res = arg_get_u32_hexstr_def(ctx, 3, 0, &at_enc); if (res != 1) { - CLIParserFree(ctx); + CLIParserFree(ctx); PrintAndLogEx(WARNING, "check `at` parameter"); return PM3_EINVARG; } @@ -4930,7 +4930,7 @@ static int CmdHf14AMfDecryptBytes(const char *Cmd) { int datalen = 0; uint8_t data[512] = {0x00}; CLIGetHexWithReturn(ctx, 4, data, &datalen); - CLIParserFree(ctx); + CLIParserFree(ctx); PrintAndLogEx(INFO, "nt....... %08X", nt); PrintAndLogEx(INFO, "ar enc... %08X", ar_enc); @@ -4955,12 +4955,12 @@ static int CmdHf14AMfSetMod(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, true); bool m0 = arg_get_lit(ctx, 1); - bool m1 = arg_get_lit(ctx, 2); + bool m1 = arg_get_lit(ctx, 2); int keylen = 0; uint8_t key[6] = {0}; CLIGetHexWithReturn(ctx, 3, key, &keylen); - CLIParserFree(ctx); + CLIParserFree(ctx); if (m0 + m1 > 1) { PrintAndLogEx(WARNING, "please select one modulation"); @@ -5006,7 +5006,7 @@ static int CmdHf14AMfNack(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, true); bool verbose = arg_get_lit(ctx, 1); - CLIParserFree(ctx); + CLIParserFree(ctx); if (verbose) PrintAndLogEx(INFO, "Started testing card for NACK bug. Press Enter to abort"); @@ -5439,7 +5439,7 @@ static int CmdHFMFPersonalize(const char *cmd) { "hf mf personalize -f2 -> single size random ID\n" "hf mf personalize -f3 -> single size NUID\n" "hf mf personalize -b -k B0B1B2B3B4B5 -f3 -> use key B = 0xB0B1B2B3B4B5" - ); + ); void *argtable[] = { arg_param_begin, @@ -5449,7 +5449,7 @@ static int CmdHFMFPersonalize(const char *cmd) { arg_lit0(NULL, "f0", "UIDFO, double size UID"), arg_lit0(NULL, "f1", "UIDF1, double size UID, optional usage of selection process shortcut"), arg_lit0(NULL, "f2", "UIDF2, single size random ID"), - arg_lit0(NULL, "f3", "UIDF3, single size NUID"), + arg_lit0(NULL, "f3", "UIDF3, single size NUID"), arg_param_end }; CLIExecWithReturn(ctx, cmd, argtable, true); @@ -5462,7 +5462,7 @@ static int CmdHFMFPersonalize(const char *cmd) { CLIParserFree(ctx); return PM3_EINVARG; } - + uint8_t keytype = 0; if (use_b) { keytype = 1; @@ -5500,7 +5500,7 @@ static int CmdHFMFPersonalize(const char *cmd) { pers_option = MIFARE_EV1_UIDF1; } else if (f2) { pers_option = MIFARE_EV1_UIDF2; - } + } CLIParserFree(ctx); @@ -5520,7 +5520,7 @@ static int CmdHFMFPersonalize(const char *cmd) { return PM3_ETIMEOUT; } - if ( resp.status == PM3_SUCCESS) { + if (resp.status == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "Personalization ( %s )", _GREEN_("ok")); } else { PrintAndLogEx(FAILED, "Personalization ( %s )", _RED_("fail")); @@ -5551,11 +5551,11 @@ static int CmdHf14AGen3UID(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - + uint8_t uid[7] = {0}; int uidlen = 0; CLIGetHexWithReturn(ctx, 1, uid, &uidlen); - CLIParserFree(ctx); + CLIParserFree(ctx); // sanity checks if (uidlen != 4 && uidlen != 7) { @@ -5598,11 +5598,11 @@ static int CmdHf14AGen3Block(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - + uint8_t data[MFBLOCK_SIZE] = {0x00}; int datalen = 0; CLIGetHexWithReturn(ctx, 1, data, &datalen); - CLIParserFree(ctx); + CLIParserFree(ctx); uint8_t new_block[MFBLOCK_SIZE] = {0x00}; int res = mfGen3Block(data, datalen, new_block); @@ -5630,7 +5630,7 @@ static int CmdHf14AGen3Freeze(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, false); bool confirm = arg_get_lit(ctx, 1); - CLIParserFree(ctx); + CLIParserFree(ctx); if (confirm == false) { PrintAndLogEx(INFO, "please confirm that you want to perma lock the card"); return PM3_SUCCESS; @@ -5907,7 +5907,7 @@ out: } static int CmdHF14AMfView(const char *Cmd) { - + CLIParserContext *ctx; CLIParserInit(&ctx, "hf mf view", "Print a MIFARE Classic dump file (bin/eml/json)", @@ -5919,12 +5919,12 @@ static int CmdHF14AMfView(const char *Cmd) { arg_lit0("v", "verbose", "verbose output"), arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, false); + CLIExecWithReturn(ctx, Cmd, argtable, false); int fnlen = 0; char filename[FILE_PATH_SIZE]; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); bool verbose = arg_get_lit(ctx, 2); - CLIParserFree(ctx); + CLIParserFree(ctx); // reserve memory uint8_t *dump = calloc(MFBLOCK_SIZE * MIFARE_4K_MAXBLOCK, sizeof(uint8_t)); diff --git a/client/src/cmdhfmfhard.c b/client/src/cmdhfmfhard.c index 1ced5e1a9..22b659110 100644 --- a/client/src/cmdhfmfhard.c +++ b/client/src/cmdhfmfhard.c @@ -2203,7 +2203,7 @@ static void init_it_all(void) { known_target_key = 0; test_state[0] = 0; test_state[1] = 0; - brute_force_per_second=0; + brute_force_per_second = 0; init_book_of_work(); real_sum_a8 = 0; diff --git a/client/src/cmdhfmfp.c b/client/src/cmdhfmfp.c index 8b01f1aff..02e8dd910 100644 --- a/client/src/cmdhfmfp.c +++ b/client/src/cmdhfmfp.c @@ -460,13 +460,13 @@ static int CmdHFMFPWritePerso(const char *Cmd) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - + bool verbose = arg_get_lit(ctx, 1); uint8_t keyNum[64] = {0}; int keyNumLen = 0; CLIGetHexWithReturn(ctx, 2, keyNum, &keyNumLen); - + uint8_t key[64] = {0}; int keyLen = 0; CLIGetHexWithReturn(ctx, 3, key, &keyLen); @@ -546,7 +546,7 @@ static int CmdHFMFPInitPerso(const char *Cmd) { uint8_t data[250] = {0}; int datalen = 0; int res; - + mfpSetVerboseMode(verbose2); for (uint16_t sn = 0x4000; sn < 0x4050; sn++) { keyNum[0] = sn >> 8; @@ -590,8 +590,8 @@ static int CmdHFMFPCommitPerso(const char *Cmd) { CLIParserInit(&ctx, "hf mfp commitp", "Executes Commit Perso command. Can be used in SL0 mode only.", "hf mfp commitp\n" - // "hf mfp commitp --sl 1" - ); + // "hf mfp commitp --sl 1" + ); void *argtable[] = { arg_param_begin, @@ -601,7 +601,7 @@ static int CmdHFMFPCommitPerso(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, true); bool verbose = arg_get_lit(ctx, 1); -// int slmode = arg_get_int(ctx, 2); +// int slmode = arg_get_int(ctx, 2); CLIParserFree(ctx); mfpSetVerboseMode(verbose); @@ -677,7 +677,7 @@ static int CmdHFMFPRdbl(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_lit0("v", "verbose", "show internal data"), - arg_int0("n", "count", "","blocks count (by default 1)"), + arg_int0("n", "count", "", "blocks count (by default 1)"), arg_lit0("b", "keyb", "use key B (by default keyA)"), arg_lit0("p", "plain", "plain communication mode between reader and card"), arg_int1(NULL, "blk", "", "block number (0..255)"), @@ -882,7 +882,7 @@ static int CmdHFMFPWrbl(const char *Cmd) { "Writes one block to Mifare Plus card", "hf mfp wrbl --blk 1 -d ff0000000000000000000000000000ff --key 000102030405060708090a0b0c0d0e0f -> writes block 1 data\n" "hf mfp wrbl --blk 2 -d ff0000000000000000000000000000ff -v -> writes block 2 data with default key 0xFF..0xFF" - ); + ); void *argtable[] = { arg_param_begin, diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index a23c8450d..509e5218b 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -520,7 +520,7 @@ static int CmdLFHitagReader(const char *Cmd) { " lf hitag reader --22 --nrar 0102030411223344\n" " lf hitag reader --23 -k 4F4E4D494B52\n" " lf hitag reader --26\n" - ); + ); void *argtable[] = { arg_param_begin, @@ -531,8 +531,8 @@ static int CmdLFHitagReader(const char *Cmd) { arg_lit0(NULL, "23", "Hitag2, read all pages, crypto mode. Key ISK high + ISK low. def 4F4E4D494B52 (ONMIKR)"), arg_lit0(NULL, "25", "Hitag2, test recorded authentications (replay?)"), arg_lit0(NULL, "26", "Hitag2, read UID"), - arg_str0("k","key", "", "key, 4 or 6 hex bytes"), - arg_str0(NULL,"nrar", "", "nonce / answer reader, 8 hex bytes"), + arg_str0("k", "key", "", "key, 4 or 6 hex bytes"), + arg_str0(NULL, "nrar", "", "nonce / answer reader, 8 hex bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -592,7 +592,7 @@ static int CmdLFHitagReader(const char *Cmd) { htf = RHTSF_CHALLENGE; memcpy(htd.auth.NrAr, nrar, sizeof(nrar)); } - if (s02){ + if (s02) { cmd = CMD_LF_HITAGS_READ; htf = RHTSF_KEY; memcpy(htd.crypto.key, key, sizeof(key)); @@ -615,7 +615,7 @@ static int CmdLFHitagReader(const char *Cmd) { if (h26) { htf = RHT2F_UID_ONLY; } - + clearCommandBuffer(); SendCommandMIX(cmd, htf, 0, 0, &htd, sizeof(htd)); PacketResponseNG resp; @@ -698,7 +698,7 @@ static int CmdLFHitagWriter(const char *Cmd) { "Hitag 2\n" " lf hitag writer --24 -k 4F4E4D494B52 -p 3 -d 01020304\n" " lf hitag writer --27 -k 4D494B52 -p 3 -d 01020304\n" - ); + ); void *argtable[] = { arg_param_begin, @@ -708,8 +708,8 @@ static int CmdLFHitagWriter(const char *Cmd) { arg_lit0(NULL, "27", "Hitag2, write page, password mode"), arg_int1("p", "page", "", "page address to write to"), arg_str0("d", "data", "", "data, 4 hex bytes"), - arg_str0("k","key", "", "key, 4 or 6 hex bytes"), - arg_str0(NULL,"nrar", "", "nonce / answer writer, 8 hex bytes"), + arg_str0("k", "key", "", "key, 4 or 6 hex bytes"), + arg_str0(NULL, "nrar", "", "nonce / answer writer, 8 hex bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -743,7 +743,7 @@ static int CmdLFHitagWriter(const char *Cmd) { uint8_t nrar[8]; int nalen = 0; res = CLIParamHexToBuf(arg_get_str(ctx, 8), nrar, sizeof(nrar), &nalen); - + CLIParserFree(ctx); if (res != 0) { @@ -782,7 +782,7 @@ static int CmdLFHitagWriter(const char *Cmd) { memcpy(htd.auth.NrAr, nrar, sizeof(nrar)); memcpy(htd.auth.data, data, sizeof(data)); } - if (s04){ + if (s04) { htf = WHTSF_KEY; memcpy(htd.crypto.key, key, sizeof(key)); memcpy(htd.crypto.data, data, sizeof(data)); @@ -822,13 +822,13 @@ static int CmdLFHitag2Dump(const char *Cmd) { "In crypto mode the default key is 4F4E4D494B52 (ONMIKR) format: ISK high + ISK low.", "lf hitag dump -k 4F4E4D494B52\n" "lf hitag dump -k 4D494B52\n" - ); + ); void *argtable[] = { arg_param_begin, arg_str0("f", "file", "", "file name"), - arg_str0("k","key", "", "key, 4 or 6 hex bytes"), - arg_str0(NULL,"nrar", "", "nonce / answer reader, 8 hex bytes"), + arg_str0("k", "key", "", "key, 4 or 6 hex bytes"), + arg_str0(NULL, "nrar", "", "nonce / answer reader, 8 hex bytes"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -858,23 +858,23 @@ static int CmdLFHitag2Dump(const char *Cmd) { PrintAndLogEx(WARNING, "to be implememted..."); -/* - PrintAndLogEx(SUCCESS, "Dumping tag memory..."); + /* + PrintAndLogEx(SUCCESS, "Dumping tag memory..."); - clearCommandBuffer(); - //SendCommandNG(CMD_LF_HITAG_DUMP, &htd, sizeof(htd)); - PacketResponseNG resp; - uint8_t *data = resp.data.asBytes; - if (fnlen < 1) { - char *fptr = filename; - fptr += sprintf(fptr, "lf-hitag-"); - FillFileNameByUID(fptr, data, "-dump", 4); - } + clearCommandBuffer(); + //SendCommandNG(CMD_LF_HITAG_DUMP, &htd, sizeof(htd)); + PacketResponseNG resp; + uint8_t *data = resp.data.asBytes; + if (fnlen < 1) { + char *fptr = filename; + fptr += sprintf(fptr, "lf-hitag-"); + FillFileNameByUID(fptr, data, "-dump", 4); + } - saveFile(filename, ".bin", data, 48); - saveFileEML(filename, data, 48, 4); - saveFileJSON(filename, jsfHitag, data, 48, NULL); -*/ + saveFile(filename, ".bin", data, 48); + saveFileEML(filename, data, 48, 4); + saveFileJSON(filename, jsfHitag, data, 48, NULL); + */ return PM3_SUCCESS; } diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 37ab2a8b9..541bcf379 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -2336,7 +2336,7 @@ static int CmdT55xxRestore(const char *Cmd) { return PM3_EINVARG; } - size_t dlen = 0; + size_t dlen = 0; uint8_t *dump = calloc(T55x7_BLOCK_COUNT * 4, sizeof(uint8_t)); if (dump == NULL) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); @@ -2387,7 +2387,7 @@ static int CmdT55xxRestore(const char *Cmd) { if (usepwd) snprintf(pwdopt, sizeof(pwdopt), "-p %08X", password); - uint32_t *data = (uint32_t*) dump; + uint32_t *data = (uint32_t *) dump; uint8_t idx; // Restore endien for writing to card for (idx = 0; idx < 12; idx++) { diff --git a/client/src/cmdwiegand.c b/client/src/cmdwiegand.c index 690626f93..c0c32abd8 100644 --- a/client/src/cmdwiegand.c +++ b/client/src/cmdwiegand.c @@ -137,7 +137,7 @@ int CmdWiegandDecode(const char *Cmd) { uint32_t top = 0, mid = 0, bot = 0; - if (hlen) { + if (hlen) { res = hexstring_to_u96(&top, &mid, &bot, hex); if (res != hlen) { PrintAndLogEx(ERR, "hex string contains none hex chars"); diff --git a/client/src/emv/cmdemv.c b/client/src/emv/cmdemv.c index 3ef602d16..718fb6bcd 100644 --- a/client/src/emv/cmdemv.c +++ b/client/src/emv/cmdemv.c @@ -1083,7 +1083,7 @@ static int CmdEMVExec(const char *Cmd) { PrintAndLogEx(NORMAL, "AC: %s", sprint_hex(AC->value, AC->len)); if (IAD) { PrintAndLogEx(NORMAL, "IAD: %s", sprint_hex(IAD->value, IAD->len)); - + // https://mst-company.ru/blog/ekvajring-emv-tranzaktsiya-emv-transaction-flow-chast-4-pdol-i-beskontaktnye-karty-osobennosti-qvsdc-i-quics if (IAD->value[0] == 0x1f) { PrintAndLogEx(NORMAL, " Key index: 0x%02x", IAD->value[2]); @@ -1421,7 +1421,7 @@ static int CmdEMVScan(const char *Cmd) { "It executes EMV contactless transaction and saves result to a file which can be used for emulation\n", "emv scan -at -> scan MSD transaction mode and show APDU and TLV\n" "emv scan -c -> scan CDA transaction mode\n" - ); + ); void *argtable[] = { arg_param_begin, @@ -1818,7 +1818,7 @@ static int CmdEMVTest(const char *Cmd) { "Executes tests\n", "emv test -i\n" "emv test --long" - ); + ); void *argtable[] = { arg_param_begin, diff --git a/client/src/mifare/mifare4.c b/client/src/mifare/mifare4.c index 80c0287b9..dcbc9ec6b 100644 --- a/client/src/mifare/mifare4.c +++ b/client/src/mifare/mifare4.c @@ -45,25 +45,25 @@ const char *mfpGetErrorDescription(uint8_t errorCode) { } AccessConditions_t MFAccessConditions[] = { - {0x00, "read AB; write AB; increment AB; decrement transfer restore AB"}, - {0x01, "read AB; decrement transfer restore AB"}, - {0x02, "read AB"}, - {0x03, "read B; write B"}, - {0x04, "read AB; writeB"}, - {0x05, "read B"}, - {0x06, "read AB; write B; increment B; decrement transfer restore AB"}, - {0x07, "none"} + {0x00, "read AB; write AB; increment AB; decrement transfer restore AB"}, + {0x01, "read AB; decrement transfer restore AB"}, + {0x02, "read AB"}, + {0x03, "read B; write B"}, + {0x04, "read AB; writeB"}, + {0x05, "read B"}, + {0x06, "read AB; write B; increment B; decrement transfer restore AB"}, + {0x07, "none"} }; AccessConditions_t MFAccessConditionsTrailer[] = { - {0x00, "read A by A; read ACCESS by A; read B by A; write B by A"}, - {0x01, "write A by A; read ACCESS by A write ACCESS by A; read B by A; write B by A"}, - {0x02, "read ACCESS by A; read B by A"}, - {0x03, "write A by B; read ACCESS by AB; write ACCESS by B; write B by B"}, - {0x04, "write A by B; read ACCESS by AB; write B by B"}, - {0x05, "read ACCESS by AB; write ACCESS by B"}, - {0x06, "read ACCESS by AB"}, - {0x07, "read ACCESS by AB"} + {0x00, "read A by A; read ACCESS by A; read B by A; write B by A"}, + {0x01, "write A by A; read ACCESS by A write ACCESS by A; read B by A; write B by A"}, + {0x02, "read ACCESS by A; read B by A"}, + {0x03, "write A by B; read ACCESS by AB; write ACCESS by B; write B by B"}, + {0x04, "write A by B; read ACCESS by AB; write B by B"}, + {0x05, "read ACCESS by AB; write ACCESS by B"}, + {0x06, "read ACCESS by AB"}, + {0x07, "read ACCESS by AB"} }; const char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data) { diff --git a/tools/mf_nonce_brute/mf_nonce_brute.c b/tools/mf_nonce_brute/mf_nonce_brute.c index 089d9e6ac..e2bdff892 100644 --- a/tools/mf_nonce_brute/mf_nonce_brute.c +++ b/tools/mf_nonce_brute/mf_nonce_brute.c @@ -58,7 +58,7 @@ typedef struct thread_key_args { uint32_t nt_enc; uint32_t nr_enc; uint16_t enc_len; - uint8_t enc[ENC_LEN]; // next encrypted command + a full read/write + uint8_t enc[ENC_LEN]; // next encrypted command + a full read/write } targs_key; //------------------------------------------------------------------ @@ -155,7 +155,7 @@ static int param_gethex_to_eol(const char *line, int paramnum, uint8_t *data, in } 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) { + const size_t min_str_len, const size_t spaces_between, bool uppercase) { if (buf == NULL) return; @@ -444,13 +444,13 @@ static void *brute_thread(void *arguments) { if (args->ev1) { // if it was EV1, we know for sure xxxAAAAAAAA recovery - printf("\nKey candidate [ " _YELLOW_("....%08" PRIx64 )" ]\n\n", key & 0xFFFFFFFF); + printf("\nKey candidate [ " _YELLOW_("....%08" PRIx64)" ]\n\n", key & 0xFFFFFFFF); __sync_fetch_and_add(&global_found_candidate, 1); } else { 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; @@ -493,14 +493,14 @@ static void *brute_key_thread(void *arguments) { // check if cmd exists uint8_t isOK = checkValidCmdByte(dec, args->enc_len); - if (isOK == false) { + 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("dec: %s\n", sprint_hex_inrow_ex(dec, args->enc_len, 0)); printf("\nValid Key found [ " _GREEN_("%012" PRIx64) " ]\n\n", key); pthread_mutex_unlock(&print_lock); __sync_fetch_and_add(&global_found, 1); @@ -547,7 +547,7 @@ int main(int argc, char *argv[]) { sscanf(argv[8], "%x", &at_par_err); int enc_len = 0; - uint8_t enc[ENC_LEN] = {0}; // next encrypted command + a full read/write + 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); @@ -565,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(); @@ -615,11 +615,11 @@ int main(int argc, char *argv[]) { t1 = clock() - t1; printf("execution time %.2f sec\n", (float)t1 / 1000000.0); - + if (!global_found && !global_found_candidate) { printf("\nFailed to find a key\n\n"); goto out; - } + } if (enc_len < 4) { printf("Too few next cmd bytes, skipping phase 2\n"); @@ -635,7 +635,7 @@ int main(int argc, char *argv[]) { 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("next encrypted cmd: %s\n", sprint_hex_inrow_ex(enc, enc_len, 0)); printf("\nlooking for the upper 16 bits of key\n"); fflush(stdout); From d34ae56c113bc25963958b0651e2dab736e5f606 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 17:10:45 +0200 Subject: [PATCH 320/373] style --- client/src/cmdhficlass.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 56f581664..a2130e26f 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -859,7 +859,7 @@ static int CmdHFiClassELoad(const char *Cmd) { "Load emulator memory with data from (bin/eml/json) iCLASS dump file", "hf iclass eload -f hf-iclass-AA162D30F8FF12F1-dump.bin\n" "hf iclass eload -f hf-iclass-AA162D30F8FF12F1-dump.eml\n" - ); + ); void *argtable[] = { arg_param_begin, @@ -2049,7 +2049,7 @@ static int CmdHFiClassRestore(const char *Cmd) { } case DICTIONARY: { free(dump); - PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); + PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); return PM3_EINVARG; } } From 5a847b2629c49d72ea2fa5eb5d1697fdef8095c9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 21:35:14 +0200 Subject: [PATCH 321/373] lf pac demod - now also checks for inverted bitstream --- client/src/cmdlfpac.c | 36 +++++++++++++++++++++++++++++------- client/src/cmdlfpac.h | 2 +- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/client/src/cmdlfpac.c b/client/src/cmdlfpac.c index 5c2ccd98c..f9d6b098c 100644 --- a/client/src/cmdlfpac.c +++ b/client/src/cmdlfpac.c @@ -123,8 +123,9 @@ int demodPac(bool verbose) { PrintAndLogEx(DEBUG, "DEBUG: Error - PAC: NRZ Demod failed"); return PM3_ESOFT; } + bool invert = false; size_t size = DemodBufferLen; - int ans = detectPac(DemodBuffer, &size); + int ans = detectPac(DemodBuffer, &size, &invert); if (ans < 0) { if (ans == -1) PrintAndLogEx(DEBUG, "DEBUG: Error - PAC: too few bits found"); @@ -137,6 +138,12 @@ int demodPac(bool verbose) { return PM3_ESOFT; } + + if (invert) { + for (size_t i = ans; i < ans + 128; i++) { + DemodBuffer[i] ^= 1; + } + } setDemodBuff(DemodBuffer, 128, ans); setClockGrid(g_DemodClock, g_DemodStartIdx + (ans * g_DemodClock)); @@ -394,14 +401,29 @@ int CmdLFPac(const char *Cmd) { } // find PAC preamble in already demoded data -int detectPac(uint8_t *dest, size_t *size) { - if (*size < 128) return -1; //make sure buffer has data +int detectPac(uint8_t *dest, size_t *size, bool *invert) { + // make sure buffer has data + if (*size < 128) + return -1; + size_t startIdx = 0; uint8_t preamble[] = {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) - return -2; //preamble not found - if (*size != 128) return -3; //wrong demoded size - //return start position + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) { + + // preamble not found + uint8_t pre_inv[] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1}; + if (!preambleSearch(dest, pre_inv, sizeof(pre_inv), size, &startIdx)) { + return -2; + } else { + *invert = true; + } + } + + // wrong demoded size + if (*size != 128) + return -3; + + // return start position return (int)startIdx; } diff --git a/client/src/cmdlfpac.h b/client/src/cmdlfpac.h index a2145051b..107280cdf 100644 --- a/client/src/cmdlfpac.h +++ b/client/src/cmdlfpac.h @@ -14,6 +14,6 @@ int CmdLFPac(const char *Cmd); int demodPac(bool verbose); -int detectPac(uint8_t *dest, size_t *size); +int detectPac(uint8_t *dest, size_t *size, bool *invert); #endif From 9c2f9f553095372db4d5aec260a1c5e9be363cef Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 21:35:59 +0200 Subject: [PATCH 322/373] text --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d26b8f41..a8cfccb99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Change `lf pac demod` - now also search for inverted bitstreams (@iceman1001) - Change `hf 14b reader` - now supports continous mode (@iceman1001) - Fix `hf search` - now doesn't false identify ISO15693 (@iceman1001) - Change emv commands now works with tokenized cards (@merlokk) From 8f4ba94a6e78e4c7337fe1842956c549edcd5a2e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 22:14:14 +0200 Subject: [PATCH 323/373] sign-conversion fixes --- armsrc/iso15693.c | 6 +++--- armsrc/iso15693.h | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 9ead4c117..42edf63e9 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -245,7 +245,7 @@ void CodeIso15693AsTag(uint8_t *cmd, size_t len) { ts->buf[++ts->max] = 0x1D; // 00011101 // data - for (int i = 0; i < len; i += 2) { + for (size_t i = 0; i < len; i += 2) { ts->buf[++ts->max] = encode_4bits[cmd[i] & 0xF]; ts->buf[++ts->max] = encode_4bits[cmd[i] >> 4]; ts->buf[++ts->max] = encode_4bits[cmd[i + 1] & 0xF]; @@ -515,7 +515,7 @@ static RAMFUNC int Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *ta tag->shiftReg |= 0x80; tag->bitCount++; if (tag->bitCount == 8) { - tag->output[tag->len] = tag->shiftReg; + tag->output[tag->len] = tag->shiftReg & 0xFF; tag->len++; if (tag->len > tag->max_len) { @@ -540,7 +540,7 @@ static RAMFUNC int Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *ta tag->bitCount++; if (tag->bitCount == 8) { - tag->output[tag->len] = tag->shiftReg; + tag->output[tag->len] = (tag->shiftReg & 0xFF); tag->len++; if (tag->len > tag->max_len) { diff --git a/armsrc/iso15693.h b/armsrc/iso15693.h index 168cee42c..29909dfc2 100644 --- a/armsrc/iso15693.h +++ b/armsrc/iso15693.h @@ -39,7 +39,6 @@ void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg void SimTagIso15693(uint8_t *uid); // simulate an ISO15693 tag - greg void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox -void Iso15693InitReader(void); void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string); From 2d5aaaa3355ca3c85d3d4e7fdd3233af0d9e11f5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 16 Apr 2021 22:30:53 +0200 Subject: [PATCH 324/373] conversion fixes --- armsrc/string.c | 15 ++++++++------- armsrc/string.h | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/armsrc/string.c b/armsrc/string.c index a3b49dcb1..d65cb6839 100644 --- a/armsrc/string.c +++ b/armsrc/string.c @@ -35,7 +35,7 @@ void *memmove(void *dest, const void *src, size_t len) { return dest; } -void *memset(void *dest, int c, int len) { +void *memset(void *dest, uint8_t c, int len) { uint8_t *d = dest; while ((len--) > 0) { *d = c; @@ -70,18 +70,19 @@ int strlen(const char *str) { } char *strncat(char *dest, const char *src, unsigned int n) { - unsigned int dest_len = strlen(dest); + int dest_len = strlen(dest); unsigned int i; for (i = 0 ; i < n && src[i] != '\0' ; i++) dest[dest_len + i] = src[i]; + dest[dest_len + i] = '\0'; return dest; } char *strcat(char *dest, const char *src) { - unsigned int dest_len = strlen(dest); + int dest_len = strlen(dest); unsigned int i; for (i = 0 ; src[i] != '\0' ; i++) @@ -97,7 +98,7 @@ void strreverse(char s[]) { int j = strlen(s) - 1; for (int i = 0; i < j; i++, j--) { - int c = s[i]; + char c = s[i]; s[i] = s[j]; s[j] = c; } @@ -105,11 +106,11 @@ void strreverse(char s[]) { /* itoa: convert n to characters in s */ void itoa(int n, char s[]) { - int i, sign; - + int sign; if ((sign = n) < 0) /* record sign */ n = -n; /* make n positive */ - i = 0; + + int i = 0; do { /* generate digits in reverse order */ s[i++] = n % 10 + '0'; /* get next digit */ } while ((n /= 10) > 0); /* delete it */ diff --git a/armsrc/string.h b/armsrc/string.h index f4d6e3fc1..9232508dd 100644 --- a/armsrc/string.h +++ b/armsrc/string.h @@ -17,7 +17,7 @@ int strlen(const char *str); void *memcpy(void *dest, const void *src, int len); void *memmove(void *dest, const void *src, size_t len); -void *memset(void *dest, int c, int len); +void *memset(void *dest, uint8_t c, int len); int memcmp(const void *av, const void *bv, int len); void memxor(uint8_t *dest, uint8_t *src, size_t len); char *strncat(char *dest, const char *src, unsigned int n); From cd965a6d3425ed21d93cac5520128b1362ac3eb0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Apr 2021 10:38:41 +0200 Subject: [PATCH 325/373] fix coverity CID 93584 --- client/src/cmdhficlass.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index a2130e26f..a75d548eb 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -1180,12 +1180,14 @@ static int CmdHFiClassDecrypt(const char *Cmd) { res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void **)&keyptr, &keylen); if (res != PM3_SUCCESS) { PrintAndLogEx(INFO, "Couldn't find any decryption methods"); + free(decrypted); return PM3_EINVARG; } if (keylen != 16) { PrintAndLogEx(ERR, "Failed to load transport key from file"); free(keyptr); + free(decrypted); return PM3_EINVARG; } memcpy(key, keyptr, sizeof(key)); @@ -1328,7 +1330,6 @@ static int CmdHFiClassDecrypt(const char *Cmd) { } PrintAndLogEx(INFO, "-----------------------------------------------------------------"); - free(decrypted); free(fptr); } From 8ee8bb9098b3594e602ae75b3674e05999fa0008 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Apr 2021 11:42:11 +0200 Subject: [PATCH 326/373] oldstyle definition --- armsrc/hitag2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 72211b037..e64b08338 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1307,7 +1307,7 @@ void SniffHitag2(void) { } // Hitag2 simulation -void SimulateHitag2() { +void SimulateHitag2(void) { BigBuf_free(); BigBuf_Clear_ext(false); From aca545834414b7351207e4487418a6762d19ab36 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Apr 2021 11:44:48 +0200 Subject: [PATCH 327/373] old-style-declaration --- armsrc/iso14443a.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index cd64bae36..8f419aebc 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -682,12 +682,12 @@ void RAMFUNC SniffIso14443a(uint8_t param) { uint32_t rx_samples = 0; // loop and listen - while (!BUTTON_PRESS()) { + while (BUTTON_PRESS() == false) { WDT_HIT(); LED_A_ON(); - int register readBufDataP = data - dma->buf; - int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; + register int readBufDataP = data - dma->buf; + register int dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; if (readBufDataP <= dmaBufDataP) dataLen = dmaBufDataP - readBufDataP; else From 3c160acd8e9de82aacd4fb9737699a9e86fd3237 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Apr 2021 12:57:51 +0200 Subject: [PATCH 328/373] removed old travis stuff --- .travis.yml.old | 64 ------------------------------------------------- 1 file changed, 64 deletions(-) delete mode 100644 .travis.yml.old diff --git a/.travis.yml.old b/.travis.yml.old deleted file mode 100644 index fbf7e1df3..000000000 --- a/.travis.yml.old +++ /dev/null @@ -1,64 +0,0 @@ -# Travis-CI Build for RfidResearchGroup/Proxmark3 -language: c - -#default linux build env is: xenial -compiler: gcc - -os: - - linux - - osx - -dist: bionic - -osx_image: xcode11 - -# move some env variables to homebrew env -env: - global: - - HOMEBREW_TRAVIS_BRANCH=$TRAVIS_BRANCH - - HOMEBREW_TRAVIS_COMMIT=$TRAVIS_COMMIT - jobs: - - TO_TEST=MAKEFILE MAKE_PARAMS='PLATFORM_EXTRAS=' - - TO_TEST=MAKEFILE MAKE_PARAMS='PLATFORM_EXTRAS=BTADDON' - - TO_TEST=CMAKE - -addons: - apt: - packages: - - gcc-arm-none-eabi - - libnewlib-dev - - libbluetooth-dev - - python3-dev - - libbz2-dev - homebrew: - packages: - - readline - - qt5 - - RfidResearchGroup/proxmark3/arm-none-eabi-gcc - taps: RfidResearchGroup/proxmark3 -# update trick to fix https://travis-ci.community/t/macos-build-fails-because-of-homebrew-bundle-unknown-command/7296/14 - update: true - -before_install: - # bug? - # homebrew update replaced python2.7 by python3.7 but - # python3 link failed while python@2 still present, so let's do it again: - if [ "$TRAVIS_OS_NAME" == "osx" ]; then - brew link --overwrite python; - fi - -install: - if ! arm-none-eabi-gcc -v; then - echo "arm-none-eabi-gcc [ERROR]"; - travis_terminate 1; - fi - -script: - - if [ "$TO_TEST" = "MAKEFILE" ]; then - make clean && make V=1 "$MAKE_PARAMS"; - make check; - fi - - if [ "$TO_TEST" = "CMAKE" ]; then - mkdir -p client/build && ( cd client/build && cmake .. && make VERBOSE=1 ); - make client/check CHECKARGS="--clientbin ./client/build/proxmark3"; - fi From dacd63f18eb66715cf011a48129451af221e2c3e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Apr 2021 12:58:34 +0200 Subject: [PATCH 329/373] text --- armsrc/printf.c | 1 - 1 file changed, 1 deletion(-) diff --git a/armsrc/printf.c b/armsrc/printf.c index 2d18a9c53..25d4a4df8 100644 --- a/armsrc/printf.c +++ b/armsrc/printf.c @@ -34,7 +34,6 @@ * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 */ #include "printf.h" - #include "string.h" typedef unsigned char u_char; From 15d14f8259bb53acc8542b430a8c52fffc59d7db Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Apr 2021 13:16:39 +0200 Subject: [PATCH 330/373] clang... --- armsrc/cmd.c | 14 ++++++++------ common/parity.h | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/armsrc/cmd.c b/armsrc/cmd.c index b0dc4aef8..7a94cf536 100644 --- a/armsrc/cmd.c +++ b/armsrc/cmd.c @@ -101,7 +101,9 @@ static int reply_ng_internal(uint16_t cmd, int16_t status, uint8_t *data, size_t // overwrite status txBufferNG.pre.status = PM3_EOVFLOW; } - txBufferNG.pre.length = len; + + // length is only 15bit (32768) + txBufferNG.pre.length = (len & 0x7FFF); // Add the (optional) content to the frame, with a maximum size of PM3_CMD_DATA_SIZE if (data && len) { @@ -115,7 +117,7 @@ static int reply_ng_internal(uint16_t cmd, int16_t status, uint8_t *data, size_t if ((g_reply_via_fpc && g_reply_with_crc_on_fpc) || ((g_reply_via_usb) && g_reply_with_crc_on_usb)) { uint8_t first, second; compute_crc(CRC_14443_A, (uint8_t *)&txBufferNG, sizeof(PacketResponseNGPreamble) + len, &first, &second); - tx_post->crc = (first << 8) + second; + tx_post->crc = ((first << 8) | second); } else { tx_post->crc = RESPONSENG_POSTAMBLE_MAGIC; } @@ -150,7 +152,7 @@ int reply_ng(uint16_t cmd, int16_t status, uint8_t *data, size_t len) { } int reply_mix(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len) { - uint16_t status = PM3_SUCCESS; + int16_t status = PM3_SUCCESS; uint64_t arg[3] = {arg0, arg1, arg2}; if (len > PM3_CMD_DATA_SIZE - sizeof(arg)) { len = PM3_CMD_DATA_SIZE - sizeof(arg); @@ -159,9 +161,9 @@ int reply_mix(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *d uint8_t cmddata[PM3_CMD_DATA_SIZE]; memcpy(cmddata, arg, sizeof(arg)); if (len && data) - memcpy(cmddata + sizeof(arg), data, len); + memcpy(cmddata + sizeof(arg), data, (int)len); - return reply_ng_internal(cmd, status, cmddata, len + sizeof(arg), false); + return reply_ng_internal((cmd & 0xFFFF), status, cmddata, len + sizeof(arg), false); } static int receive_ng_internal(PacketCommandNG *rx, uint32_t read_ng(uint8_t *data, size_t len), bool usb, bool fpc) { @@ -230,7 +232,7 @@ static int receive_ng_internal(PacketCommandNG *rx, uint32_t read_ng(uint8_t *da rx->ng = false; rx->magic = 0; rx->crc = 0; - rx->cmd = rx_old.cmd; + rx->cmd = (rx_old.cmd & 0xFFFF); rx->oldarg[0] = rx_old.arg[0]; rx->oldarg[1] = rx_old.arg[1]; rx->oldarg[2] = rx_old.arg[2]; diff --git a/common/parity.h b/common/parity.h index dad768524..3b829bdb4 100644 --- a/common/parity.h +++ b/common/parity.h @@ -29,7 +29,7 @@ static inline uint8_t evenparity32(uint32_t x) { x ^= x >> 8; return evenparity8(x); #else - return __builtin_parity(x); + return (__builtin_parity(x) & 0xFF); #endif } From be6a9273ec4313df41d3e07699e91ef60a4df98b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Apr 2021 15:17:39 +0200 Subject: [PATCH 331/373] clang fix --- client/src/aidsearch.c | 6 +++--- client/src/aidsearch.h | 2 +- client/src/cmdhf14a.c | 2 +- client/src/cmdhf14b.c | 3 +-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/client/src/aidsearch.c b/client/src/aidsearch.c index 3a9d55ace..795ebed15 100644 --- a/client/src/aidsearch.c +++ b/client/src/aidsearch.c @@ -56,10 +56,10 @@ json_t *AIDSearchInit(bool verbose) { return root; } -json_t *AIDSearchGetElm(json_t *root, int elmindx) { +json_t *AIDSearchGetElm(json_t *root, size_t elmindx) { json_t *data = json_array_get(root, elmindx); if (!json_is_object(data)) { - PrintAndLogEx(ERR, "data [%d] is not an object\n", elmindx); + PrintAndLogEx(ERR, "data [%zu] is not an object\n", elmindx); return NULL; } return data; @@ -121,7 +121,7 @@ int PrintAIDDescription(json_t *xroot, char *aid, bool verbose) { json_t *elm = NULL; uint32_t maxaidlen = 0; - for (uint32_t elmindx = 0; elmindx < json_array_size(root); elmindx++) { + for (size_t elmindx = 0; elmindx < json_array_size(root); elmindx++) { json_t *data = AIDSearchGetElm(root, elmindx); if (data == NULL) continue; diff --git a/client/src/aidsearch.h b/client/src/aidsearch.h index 585e173c6..e3783fd71 100644 --- a/client/src/aidsearch.h +++ b/client/src/aidsearch.h @@ -20,7 +20,7 @@ int PrintAIDDescription(json_t *xroot, char *aid, bool verbose); int PrintAIDDescriptionBuf(json_t *root, uint8_t *aid, size_t aidlen, bool verbose); json_t *AIDSearchInit(bool verbose); -json_t *AIDSearchGetElm(json_t *root, int elmindx); +json_t *AIDSearchGetElm(json_t *root, size_t elmindx); bool AIDGetFromElm(json_t *data, uint8_t *aid, size_t aidmaxlen, int *aidlen); int AIDSearchFree(json_t *root); diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index abac9e999..cc7266db4 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -1989,7 +1989,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { PrintAndLogEx(INFO, "-------------------- " _CYAN_("AID Search") " --------------------"); bool found = false; - int elmindx = 0; + size_t elmindx = 0; json_t *root = AIDSearchInit(verbose); if (root != NULL) { bool ActivateField = true; diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index 22cfaab4d..6ad2f90e3 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -53,7 +53,6 @@ static uint16_t get_sw(uint8_t *d, uint8_t n) { static void hf14b_aid_search(bool verbose) { - int elmindx = 0; json_t *root = AIDSearchInit(verbose); if (root == NULL) { switch_off_field_14b(); @@ -65,7 +64,7 @@ static void hf14b_aid_search(bool verbose) { bool found = false; bool leave_signal_on = true; bool activate_field = true; - for (elmindx = 0; elmindx < json_array_size(root); elmindx++) { + for (size_t elmindx = 0; elmindx < json_array_size(root); elmindx++) { if (kbd_enter_pressed()) { break; From 2b8d5e5c0de8850c6cb3258e8912736b070f5bc8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Apr 2021 15:23:19 +0200 Subject: [PATCH 332/373] clang fixes --- client/src/aidsearch.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/aidsearch.c b/client/src/aidsearch.c index 795ebed15..360353fe0 100644 --- a/client/src/aidsearch.c +++ b/client/src/aidsearch.c @@ -24,7 +24,7 @@ static int openAIDFile(json_t **root, bool verbose) { int retval = PM3_SUCCESS; *root = json_load_file(path, 0, &error); - if (!*root) { + if (!*root) { PrintAndLogEx(ERR, "json (%s) error on line %d: %s", path, error.line, error.text); retval = PM3_ESOFT; goto out; @@ -103,7 +103,7 @@ bool AIDGetFromElm(json_t *data, uint8_t *aid, size_t aidmaxlen, int *aidlen) { if (hexaid == NULL || strlen(hexaid) == 0) return false; - int res = param_gethex_to_eol(hexaid, 0, aid, aidmaxlen, aidlen); + int res = param_gethex_to_eol(hexaid, 0, aid, (int)aidmaxlen, aidlen); if (res) return false; @@ -120,7 +120,7 @@ int PrintAIDDescription(json_t *xroot, char *aid, bool verbose) { goto out; json_t *elm = NULL; - uint32_t maxaidlen = 0; + size_t maxaidlen = 0; for (size_t elmindx = 0; elmindx < json_array_size(root); elmindx++) { json_t *data = AIDSearchGetElm(root, elmindx); if (data == NULL) From a1ddd01906bcc3a5c1eb42636075012f112a637d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Apr 2021 15:28:49 +0200 Subject: [PATCH 333/373] clang --- client/src/cmdanalyse.c | 46 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/client/src/cmdanalyse.c b/client/src/cmdanalyse.c index 9a60bb9bc..a891db02f 100644 --- a/client/src/cmdanalyse.c +++ b/client/src/cmdanalyse.c @@ -32,10 +32,10 @@ static int CmdHelp(const char *Cmd); static uint8_t calculateLRC(uint8_t *bytes, uint8_t len) { - uint8_t LRC = 0; + uint8_t lcr = 0; for (uint8_t i = 0; i < len; i++) - LRC ^= bytes[i]; - return LRC; + lcr ^= bytes[i]; + return lcr; } /* static uint16_t matrixadd ( uint8_t* bytes, uint8_t len){ @@ -56,7 +56,7 @@ static uint16_t shiftadd ( uint8_t* bytes, uint8_t len){ } */ static uint16_t calcSumCrumbAdd(uint8_t *bytes, uint8_t len, uint32_t mask) { - uint16_t sum = 0; + uint32_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum += CRUMB(bytes[i], 0); sum += CRUMB(bytes[i], 2); @@ -64,25 +64,25 @@ static uint16_t calcSumCrumbAdd(uint8_t *bytes, uint8_t len, uint32_t mask) { sum += CRUMB(bytes[i], 6); } sum &= mask; - return sum; + return (sum & 0xFFFF); } static uint16_t calcSumCrumbAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask) { return (~calcSumCrumbAdd(bytes, len, mask) & mask); } static uint16_t calcSumNibbleAdd(uint8_t *bytes, uint8_t len, uint32_t mask) { - uint16_t sum = 0; + uint32_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum += NIBBLE_LOW(bytes[i]); sum += NIBBLE_HIGH(bytes[i]); } sum &= mask; - return sum; + return (sum & 0xFFFF); } static uint16_t calcSumNibbleAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask) { return (~calcSumNibbleAdd(bytes, len, mask) & mask); } static uint16_t calcSumCrumbXor(uint8_t *bytes, uint8_t len, uint32_t mask) { - uint16_t sum = 0; + uint32_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum ^= CRUMB(bytes[i], 0); sum ^= CRUMB(bytes[i], 2); @@ -90,32 +90,32 @@ static uint16_t calcSumCrumbXor(uint8_t *bytes, uint8_t len, uint32_t mask) { sum ^= CRUMB(bytes[i], 6); } sum &= mask; - return sum; + return (sum & 0xFFFF); } static uint16_t calcSumNibbleXor(uint8_t *bytes, uint8_t len, uint32_t mask) { - uint16_t sum = 0; + uint32_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum ^= NIBBLE_LOW(bytes[i]); sum ^= NIBBLE_HIGH(bytes[i]); } sum &= mask; - return sum; + return (sum & 0xFFFF); } static uint16_t calcSumByteXor(uint8_t *bytes, uint8_t len, uint32_t mask) { - uint16_t sum = 0; + uint32_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum ^= bytes[i]; } sum &= mask; - return sum; + return (sum & 0xFFFF); } static uint16_t calcSumByteAdd(uint8_t *bytes, uint8_t len, uint32_t mask) { - uint16_t sum = 0; + uint32_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum += bytes[i]; } sum &= mask; - return sum; + return (sum & 0xFFFF); } // Ones complement static uint16_t calcSumByteAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask) { @@ -123,24 +123,24 @@ static uint16_t calcSumByteAddOnes(uint8_t *bytes, uint8_t len, uint32_t mask) { } static uint16_t calcSumByteSub(uint8_t *bytes, uint8_t len, uint32_t mask) { - uint8_t sum = 0; + uint32_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum -= bytes[i]; } sum &= mask; - return sum; + return (sum & 0xFFFF); } static uint16_t calcSumByteSubOnes(uint8_t *bytes, uint8_t len, uint32_t mask) { return (~calcSumByteSub(bytes, len, mask) & mask); } static uint16_t calcSumNibbleSub(uint8_t *bytes, uint8_t len, uint32_t mask) { - uint8_t sum = 0; + uint32_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum -= NIBBLE_LOW(bytes[i]); sum -= NIBBLE_HIGH(bytes[i]); } sum &= mask; - return sum; + return (sum & 0xFFFF); } static uint16_t calcSumNibbleSubOnes(uint8_t *bytes, uint8_t len, uint32_t mask) { return (~calcSumNibbleSub(bytes, len, mask) & mask); @@ -148,18 +148,18 @@ static uint16_t calcSumNibbleSubOnes(uint8_t *bytes, uint8_t len, uint32_t mask) // BSD shift checksum 8bit version static uint16_t calcBSDchecksum8(uint8_t *bytes, uint8_t len, uint32_t mask) { - uint16_t sum = 0; + uint32_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum = ((sum & 0xFF) >> 1) | ((sum & 0x1) << 7); // rotate accumulator sum += bytes[i]; // add next byte sum &= 0xFF; // } sum &= mask; - return sum; + return (sum & 0xFFFF); } // BSD shift checksum 4bit version static uint16_t calcBSDchecksum4(uint8_t *bytes, uint8_t len, uint32_t mask) { - uint16_t sum = 0; + uint32_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator sum += NIBBLE_HIGH(bytes[i]); // add high nibble @@ -169,7 +169,7 @@ static uint16_t calcBSDchecksum4(uint8_t *bytes, uint8_t len, uint32_t mask) { sum &= 0xF; // } sum &= mask; - return sum; + return (sum & 0xFFFF); } // 0xFF - ( n1 ^ n... ) From 0c78958122fe4e615447b3149c49ae7eb34dcd02 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Apr 2021 15:36:46 +0200 Subject: [PATCH 334/373] clang fix --- client/src/cmdanalyse.c | 62 ++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/client/src/cmdanalyse.c b/client/src/cmdanalyse.c index a891db02f..996c7bfa0 100644 --- a/client/src/cmdanalyse.c +++ b/client/src/cmdanalyse.c @@ -227,7 +227,7 @@ static int CmdAnalyseLfsr(const char *Cmd) { for (uint8_t i = 0x01; i < 0x30; i += 1) { legic_prng_init(iv); legic_prng_forward(i); - uint16_t lfsr = legic_prng_get_bits(12); /* Any nonzero start state will work. */ + uint32_t lfsr = legic_prng_get_bits(12); /* Any nonzero start state will work. */ PrintAndLogEx(INFO, " %02X | %03X | %03X | %03X", i, lfsr, 0x40 ^ lfsr, find ^ lfsr); } PrintAndLogEx(INFO, "----+------+-------+--------------"); @@ -258,7 +258,7 @@ static int CmdAnalyseLCR(const char *Cmd) { return PM3_EINVARG; } - uint8_t finalXor = calculateLRC(data, dlen); + uint8_t finalXor = calculateLRC(data, (uint8_t)dlen); PrintAndLogEx(SUCCESS, "Target [%02X] requires final LRC XOR byte value: " _YELLOW_("0x%02X"), data[dlen - 1], finalXor); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; @@ -288,15 +288,15 @@ static int CmdAnalyseCRC(const char *Cmd) { return PM3_EINVARG; } - PrintAndLogEx(INFO, "\nTests with (%d) | %s", dlen, sprint_hex(data, dlen)); + PrintAndLogEx(INFO, "\nTests with (%d) | %s", dlen, sprint_hex(data, (size_t)dlen)); // 51 f5 7a d6 uint8_t uid[] = {0x51, 0xf5, 0x7a, 0xd6}; //12 34 56 init_table(CRC_LEGIC); - uint8_t legic8 = CRC8Legic(uid, sizeof(uid)); - PrintAndLogEx(INFO, "Legic 16 | %X (EF6F expected) [legic8 = %02x]", crc16_legic(data, dlen, legic8), legic8); + uint8_t legic8 = CRC8Legic(uid, sizeof(uid)) & 0xFF; + PrintAndLogEx(INFO, "Legic 16 | %X (EF6F expected) [legic8 = %02x]", crc16_legic(data, (size_t)dlen, legic8), legic8); init_table(CRC_FELICA); - PrintAndLogEx(INFO, "FeliCa | %X ", crc16_xmodem(data, dlen)); + PrintAndLogEx(INFO, "FeliCa | %X ", crc16_xmodem(data, (size_t)dlen)); PrintAndLogEx(INFO, "\nTests of reflection. Current methods in source code"); PrintAndLogEx(INFO, " reflect(0x3e23L,3) is %04X == 0x3e26", reflect(0x3e23L, 3)); @@ -305,9 +305,9 @@ static int CmdAnalyseCRC(const char *Cmd) { uint8_t b1, b2; // ISO14443 crc B - compute_crc(CRC_14443_B, data, dlen, &b1, &b2); + compute_crc(CRC_14443_B, data, (size_t)dlen, &b1, &b2); uint16_t crcBB_1 = b1 << 8 | b2; - uint16_t bbb = Crc16ex(CRC_14443_B, data, dlen); + uint16_t bbb = Crc16ex(CRC_14443_B, data, (size_t)dlen); PrintAndLogEx(INFO, "ISO14443 crc B | %04x == %04x \n", crcBB_1, bbb); @@ -316,7 +316,7 @@ static int CmdAnalyseCRC(const char *Cmd) { PrintAndLogEx(INFO, "\n\nStandard test with 31 32 33 34 35 36 37 38 39 '123456789'\n\n"); uint8_t dataStr[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39 }; - legic8 = CRC8Legic(dataStr, sizeof(dataStr)); + legic8 = CRC8Legic(dataStr, sizeof(dataStr)) & 0xFF; //these below has been tested OK. PrintAndLogEx(INFO, "Confirmed CRC Implementations"); @@ -340,27 +340,27 @@ static int CmdAnalyseCRC(const char *Cmd) { // ISO14443 crc A compute_crc(CRC_14443_A, dataStr, sizeof(dataStr), &b1, &b2); - uint16_t crcAA = b1 << 8 | b2; + uint16_t crcAA = (uint16_t)(b1 << 8 | b2); PrintAndLogEx(INFO, "ISO14443 crc A | %04x or %04x (BF05 expected)\n", crcAA, Crc16ex(CRC_14443_A, dataStr, sizeof(dataStr))); // ISO14443 crc B compute_crc(CRC_14443_B, dataStr, sizeof(dataStr), &b1, &b2); - uint16_t crcBB = b1 << 8 | b2; + uint16_t crcBB = (uint16_t)(b1 << 8 | b2); PrintAndLogEx(INFO, "ISO14443 crc B | %04x or %04x (906E expected)\n", crcBB, Crc16ex(CRC_14443_B, dataStr, sizeof(dataStr))); // ISO15693 crc (x.25) compute_crc(CRC_15693, dataStr, sizeof(dataStr), &b1, &b2); - uint16_t crcCC = b1 << 8 | b2; + uint16_t crcCC = (uint16_t)(b1 << 8 | b2); PrintAndLogEx(INFO, "ISO15693 crc X25| %04x or %04x (906E expected)\n", crcCC, Crc16ex(CRC_15693, dataStr, sizeof(dataStr))); // ICLASS compute_crc(CRC_ICLASS, dataStr, sizeof(dataStr), &b1, &b2); - uint16_t crcDD = b1 << 8 | b2; + uint16_t crcDD = (uint16_t)(b1 << 8 | b2); PrintAndLogEx(INFO, "ICLASS crc | %04x or %04x\n", crcDD, Crc16ex(CRC_ICLASS, dataStr, sizeof(dataStr))); // FeliCa compute_crc(CRC_FELICA, dataStr, sizeof(dataStr), &b1, &b2); - uint16_t crcEE = b1 << 8 | b2; + uint16_t crcEE = (uint16_t)(b1 << 8 | b2); PrintAndLogEx(INFO, "FeliCa | %04x or %04x (31C3 expected)\n", crcEE, Crc16ex(CRC_FELICA, dataStr, sizeof(dataStr))); @@ -430,7 +430,7 @@ static int CmdAnalyseCHKSUM(const char *Cmd) { continue; mask <<= 4; - mask |= c; + mask |= (uint8_t)c; } } @@ -443,22 +443,22 @@ static int CmdAnalyseCHKSUM(const char *Cmd) { PrintAndLogEx(INFO, "------------------+-------------+------------------+-----------------+------------------+-----------+-------------"); } PrintAndLogEx(INFO, "0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X\n", - calcSumByteAdd(data, dlen, mask) - , calcSumNibbleAdd(data, dlen, mask) - , calcSumCrumbAdd(data, dlen, mask) - , calcSumByteSub(data, dlen, mask) - , calcSumNibbleSub(data, dlen, mask) - , calcSumByteAddOnes(data, dlen, mask) - , calcSumNibbleAddOnes(data, dlen, mask) - , calcSumCrumbAddOnes(data, dlen, mask) - , calcSumByteSubOnes(data, dlen, mask) - , calcSumNibbleSubOnes(data, dlen, mask) - , calcSumByteXor(data, dlen, mask) - , calcSumNibbleXor(data, dlen, mask) - , calcSumCrumbXor(data, dlen, mask) - , calcBSDchecksum8(data, dlen, mask) - , calcBSDchecksum4(data, dlen, mask) - , calcXORchecksum(data, dlen, mask) + calcSumByteAdd(data, (uint8_t)dlen, mask) + , calcSumNibbleAdd(data, (uint8_t)dlen, mask) + , calcSumCrumbAdd(data, (uint8_t)dlen, mask) + , calcSumByteSub(data, (uint8_t)dlen, mask) + , calcSumNibbleSub(data, (uint8_t)dlen, mask) + , calcSumByteAddOnes(data, (uint8_t)dlen, mask) + , calcSumNibbleAddOnes(data, (uint8_t)dlen, mask) + , calcSumCrumbAddOnes(data, (uint8_t)dlen, mask) + , calcSumByteSubOnes(data, (uint8_t)dlen, mask) + , calcSumNibbleSubOnes(data, (uint8_t)dlen, mask) + , calcSumByteXor(data, (uint8_t)dlen, mask) + , calcSumNibbleXor(data, (uint8_t)dlen, mask) + , calcSumCrumbXor(data, (uint8_t)dlen, mask) + , calcBSDchecksum8(data, (uint8_t)dlen, mask) + , calcBSDchecksum4(data, (uint8_t)dlen, mask) + , calcXORchecksum(data, (uint8_t)dlen, mask) ); return PM3_SUCCESS; } From ec9c9a54aba3883c316a2e7f5c5ceae190eb01e3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Apr 2021 15:42:58 +0200 Subject: [PATCH 335/373] clang fix --- client/src/cmdanalyse.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/client/src/cmdanalyse.c b/client/src/cmdanalyse.c index 996c7bfa0..1ddf77350 100644 --- a/client/src/cmdanalyse.c +++ b/client/src/cmdanalyse.c @@ -306,7 +306,7 @@ static int CmdAnalyseCRC(const char *Cmd) { uint8_t b1, b2; // ISO14443 crc B compute_crc(CRC_14443_B, data, (size_t)dlen, &b1, &b2); - uint16_t crcBB_1 = b1 << 8 | b2; + uint16_t crcBB_1 = (uint16_t)(b1 << 8 | b2); uint16_t bbb = Crc16ex(CRC_14443_B, data, (size_t)dlen); PrintAndLogEx(INFO, "ISO14443 crc B | %04x == %04x \n", crcBB_1, bbb); @@ -399,25 +399,25 @@ static int CmdAnalyseCHKSUM(const char *Cmd) { PrintAndLogEx(FAILED, "Error parsing bytes"); return PM3_EINVARG; } - const char *s = arg_get_str(ctx, 2)->sval[0]; + const char *m = arg_get_str(ctx, 2)->sval[0]; bool verbose = arg_get_lit(ctx, 3); CLIParserFree(ctx); - uint32_t mlen = 0; - if (s) - mlen = strlen(s); + size_t mlen = 0; + if (m) + mlen = strlen(m); if (mlen > 8) { PrintAndLogEx(FAILED, "Mask value is max 4 hex bytes"); return PM3_EINVARG; } - uint32_t mask = 0; + uint16_t mask = 0; if (mlen == 0) { mask = 0xFFFF; } else { - for (int i = 0; i < mlen; i++) { - char c = s[i]; + for (size_t i = 0; i < mlen; i++) { + char c = m[i]; // capitalize if (c >= 'a' && c <= 'f') c -= 32; @@ -946,7 +946,7 @@ static int CmdAnalyseDemodBuffer(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, true); const char *s = arg_get_str(ctx, 1)->sval[0]; - int len = MIN(strlen(s), MAX_DEMOD_BUF_LEN); + size_t len = MIN(strlen(s), MAX_DEMOD_BUF_LEN); // add 1 for null terminator. uint8_t *data = calloc(len + 1, sizeof(uint8_t)); @@ -955,7 +955,7 @@ static int CmdAnalyseDemodBuffer(const char *Cmd) { return PM3_EMALLOC; } - for (int i = 0; i <= strlen(s); i++) { + for (size_t i = 0; i <= strlen(s); i++) { char c = s[i]; if (c == '1') DemodBuffer[i] = 1; @@ -1031,7 +1031,7 @@ static int CmdAnalyseFoo(const char *Cmd) { CLIParserFree(ctx); PrintAndLogEx(INFO, "-r"); - PrintAndLogEx(INFO, "Got: %s", sprint_hex_inrow(data, datalen)); + PrintAndLogEx(INFO, "Got: %s", sprint_hex_inrow(data, (size_t)datalen)); PrintAndLogEx(INFO, "Got: %s", data3); ClearGraph(false); From 8046f6862a8cc8b629261cb4d1886b0de3b858db Mon Sep 17 00:00:00 2001 From: Ryan Saridar <8403417+VortixDev@users.noreply.github.com> Date: Sat, 17 Apr 2021 19:08:34 +0100 Subject: [PATCH 336/373] Fix DESFire mis-annotation --- client/src/cmdhflist.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/src/cmdhflist.c b/client/src/cmdhflist.c index baf60406d..be2dfa4eb 100644 --- a/client/src/cmdhflist.c +++ b/client/src/cmdhflist.c @@ -776,6 +776,8 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { pos++; for (uint8_t i = 0; i < 2; i++, pos++) { + bool found_annotation = true; + switch (cmd[pos]) { case MFDES_CREATE_APPLICATION: snprintf(exp, size, "CREATE APPLICATION"); @@ -892,8 +894,13 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { snprintf(exp, size, "READ SIGNATURE"); break; default: + found_annotation = false; break; } + + if (found_annotation) { + break; + } } } else { // anything else From 62776bf64aa37dd0f02fff28a2f826cee5375dea Mon Sep 17 00:00:00 2001 From: Ryan Saridar <8403417+VortixDev@users.noreply.github.com> Date: Sat, 17 Apr 2021 19:09:13 +0100 Subject: [PATCH 337/373] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8cfccb99..9b94013db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fix DESFire mis-annotation (@VortixDev) - Change `lf pac demod` - now also search for inverted bitstreams (@iceman1001) - Change `hf 14b reader` - now supports continous mode (@iceman1001) - Fix `hf search` - now doesn't false identify ISO15693 (@iceman1001) From 3577193303c5c45bb0b38376d04cd605988075ea Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 17 Apr 2021 21:47:29 +0200 Subject: [PATCH 338/373] data raw - now use cliparser --- client/src/cmddata.c | 670 +++++++++++++++++++++++-------------------- 1 file changed, 353 insertions(+), 317 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index cf426b50f..d13363172 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -36,150 +36,7 @@ int g_DemodClock = 0; static int CmdHelp(const char *Cmd); -static int usage_data_rawdemod(void) { - PrintAndLogEx(NORMAL, "Usage: data rawdemod [modulation] |"); - PrintAndLogEx(NORMAL, " [modulation] as 2 char,"); - PrintAndLogEx(NORMAL, " "_YELLOW_("ab")" - ask/biphase"); - PrintAndLogEx(NORMAL, " "_YELLOW_("am")" - ask/manchester"); - PrintAndLogEx(NORMAL, " "_YELLOW_("ar")" - ask/raw"); - PrintAndLogEx(NORMAL, " "_YELLOW_("fs")" - fsk"); - PrintAndLogEx(NORMAL, " "_YELLOW_("nr")" - nrz/direct"); - PrintAndLogEx(NORMAL, " "_YELLOW_("p1")" - psk1"); - PrintAndLogEx(NORMAL, " "_YELLOW_("p2")" - psk2"); - PrintAndLogEx(NORMAL, " as 'h', prints the help for the specific modulation"); - PrintAndLogEx(NORMAL, " see specific modulation help for optional parameters"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " data rawdemod fs h = print help specific to fsk demod"); - PrintAndLogEx(NORMAL, " data rawdemod fs = demod GraphBuffer using: fsk - autodetect"); - PrintAndLogEx(NORMAL, " data rawdemod ab = demod GraphBuffer using: ask/biphase - autodetect"); - PrintAndLogEx(NORMAL, " data rawdemod am = demod GraphBuffer using: ask/manchester - autodetect"); - PrintAndLogEx(NORMAL, " data rawdemod ar = demod GraphBuffer using: ask/raw - autodetect"); - PrintAndLogEx(NORMAL, " data rawdemod nr = demod GraphBuffer using: nrz/direct - autodetect"); - PrintAndLogEx(NORMAL, " data rawdemod p1 = demod GraphBuffer using: psk1 - autodetect"); - PrintAndLogEx(NORMAL, " data rawdemod p2 = demod GraphBuffer using: psk2 - autodetect"); - return PM3_SUCCESS; -} -static int usage_data_rawdemod_am(void) { - PrintAndLogEx(NORMAL, "Usage: data rawdemod am [clock] [maxError] [maxLen] [amplify]"); - PrintAndLogEx(NORMAL, " ['s'] optional, check for Sequence Terminator"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect"); - PrintAndLogEx(NORMAL, " , 1 to invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100"); - PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (512 bits at rf/64)"); - PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " data rawdemod am = demod an ask/manchester tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " data rawdemod am 32 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " data rawdemod am 32 1 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " data rawdemod am 1 = demod an ask/manchester tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " data rawdemod am 64 1 0 = demod an ask/manchester tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - return PM3_SUCCESS; -} -static int usage_data_rawdemod_ab(void) { - PrintAndLogEx(NORMAL, "Usage: data rawdemod ab [offset] [clock] [maxError] [maxLen] "); - PrintAndLogEx(NORMAL, " [offset], offset to begin biphase, default=0"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect"); - PrintAndLogEx(NORMAL, " , 1 to invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100"); - PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (512 bits at rf/64)"); - PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); - PrintAndLogEx(NORMAL, " NOTE: can be entered as second or third argument"); - PrintAndLogEx(NORMAL, " NOTE: can be entered as first, second or last argument"); - PrintAndLogEx(NORMAL, " NOTE: any other arg must have previous args set to work"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " NOTE: --invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " data rawdemod ab = demod an ask/biph tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " data rawdemod ab 0 a = demod an ask/biph tag from GraphBuffer, amplified"); - PrintAndLogEx(NORMAL, " data rawdemod ab 1 32 = demod an ask/biph tag from GraphBuffer using an offset of 1 and a clock of RF/32"); - PrintAndLogEx(NORMAL, " data rawdemod ab 0 32 1 = demod an ask/biph tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " data rawdemod ab 0 1 = demod an ask/biph tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " data rawdemod ab 0 64 1 0 = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - PrintAndLogEx(NORMAL, " data rawdemod ab 0 64 1 0 0 a = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); - return PM3_SUCCESS; -} -static int usage_data_rawdemod_ar(void) { - PrintAndLogEx(NORMAL, "Usage: data rawdemod ar [clock] [maxError] [maxLen] [amplify]"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect"); - PrintAndLogEx(NORMAL, " , 1 to invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100"); - PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (1024 bits at rf/64)"); - PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " data rawdemod ar = demod an ask tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " data rawdemod ar a = demod an ask tag from GraphBuffer, amplified"); - PrintAndLogEx(NORMAL, " data rawdemod ar 32 = demod an ask tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " data rawdemod ar 32 1 = demod an ask tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " data rawdemod ar 1 = demod an ask tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " data rawdemod ar 64 1 0 = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - PrintAndLogEx(NORMAL, " data rawdemod ar 64 1 0 0 a = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); - return PM3_SUCCESS; -} -static int usage_data_rawdemod_fs(void) { - PrintAndLogEx(NORMAL, "Usage: data rawdemod fs [clock] [fchigh] [fclow]"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, omit for autodetect."); - PrintAndLogEx(NORMAL, " , 1 for invert output, can be used even if the clock is omitted"); - PrintAndLogEx(NORMAL, " [fchigh], larger field clock length, omit for autodetect"); - PrintAndLogEx(NORMAL, " [fclow], small field clock length, omit for autodetect"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " data rawdemod fs = demod an fsk tag from GraphBuffer using autodetect"); - PrintAndLogEx(NORMAL, " data rawdemod fs 32 = demod an fsk tag from GraphBuffer using a clock of RF/32, autodetect fc"); - PrintAndLogEx(NORMAL, " data rawdemod fs 1 = demod an fsk tag from GraphBuffer using autodetect, invert output"); - PrintAndLogEx(NORMAL, " data rawdemod fs 32 1 = demod an fsk tag from GraphBuffer using a clock of RF/32, invert output, autodetect fc"); - PrintAndLogEx(NORMAL, " data rawdemod fs 64 0 8 5 = demod an fsk1 RF/64 tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " data rawdemod fs 50 0 10 8 = demod an fsk2 RF/50 tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " data rawdemod fs 50 1 10 8 = demod an fsk2a RF/50 tag from GraphBuffer"); - return PM3_SUCCESS; -} -static int usage_data_rawdemod_nr(void) { - PrintAndLogEx(NORMAL, "Usage: data rawdemod nr [clock] <0|1> [maxError]"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect."); - PrintAndLogEx(NORMAL, " , 1 for invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " data rawdemod nr = demod a nrz/direct tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " data rawdemod nr 32 = demod a nrz/direct tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " data rawdemod nr 32 1 = demod a nrz/direct tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " data rawdemod nr 1 = demod a nrz/direct tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " data rawdemod nr 64 1 0 = demod a nrz/direct tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - return PM3_SUCCESS; -} -static int usage_data_rawdemod_p1(void) { - PrintAndLogEx(NORMAL, "Usage: data rawdemod p1 [clock] <0|1> [maxError]"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect."); - PrintAndLogEx(NORMAL, " , 1 for invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " data rawdemod p1 = demod a psk1 tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " data rawdemod p1 32 = demod a psk1 tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " data rawdemod p1 32 1 = demod a psk1 tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " data rawdemod p1 1 = demod a psk1 tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " data rawdemod p1 64 1 0 = demod a psk1 tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - return PM3_SUCCESS; -} -static int usage_data_rawdemod_p2(void) { - PrintAndLogEx(NORMAL, "Usage: data rawdemod p2 [clock] <0|1> [maxError]"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect."); - PrintAndLogEx(NORMAL, " , 1 for invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " data rawdemod p2 = demod a psk2 tag from GraphBuffer, autodetect clock"); - PrintAndLogEx(NORMAL, " data rawdemod p2 32 = demod a psk2 tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " data rawdemod p2 32 1 = demod a psk2 tag from GraphBuffer using a clock of RF/32 and inverting output"); - PrintAndLogEx(NORMAL, " data rawdemod p2 1 = demod a psk2 tag from GraphBuffer, autodetect clock and invert output"); - PrintAndLogEx(NORMAL, " data rawdemod p2 64 1 0 = demod a psk2 tag from GraphBuffer using a clock of RF/64, inverting output and allowing 0 demod errors"); - return PM3_SUCCESS; -} - -//set the demod buffer with given array of binary (one bit per byte) +//set the demod buffer with given array ofq binary (one bit per byte) //by marshmellow void setDemodBuff(uint8_t *buff, size_t size, size_t start_idx) { if (buff == NULL) return; @@ -506,38 +363,50 @@ static int CmdConvertBitStream(const char *Cmd) { // verbose will print results and demoding messages // emSearch will auto search for EM410x format in bitstream // askType switches decode: ask/raw = 0, ask/manchester = 1 -int ASKDemod_ext(int clk, int invert, int maxErr, size_t maxLen, bool amplify, bool verbose, bool emSearch, uint8_t askType, bool *stCheck) { - PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) clk %i invert %i maxErr %i maxLen %zu amplify %i verbose %i emSearch %i askType %i ", clk, invert, maxErr, maxLen, amplify, verbose, emSearch, askType); +int ASKDemod_ext(int clk, int invert, int maxErr, size_t maxlen, bool amplify, bool verbose, bool emSearch, uint8_t askType, bool *stCheck) { + PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) clk %i invert %i maxErr %i maxLen %zu amplify %i verbose %i emSearch %i askType %i " + , clk + , invert + , maxErr + , maxlen + , amplify + , verbose + , emSearch + , askType + ); uint8_t askamp = 0; - if (!maxLen) maxLen = pm3_capabilities.bigbuf_size; + if (maxlen == 0) + maxlen = pm3_capabilities.bigbuf_size; uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t)); if (bits == NULL) { + PrintAndLogEx(INFO, "failed to allocate memory"); return PM3_EMALLOC; } - size_t BitLen = getFromGraphBuf(bits); + size_t bitlen = getFromGraphBuf(bits); - PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) #samples from graphbuff: %zu", BitLen); + PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) #samples from graphbuff: %zu", bitlen); - if (BitLen < 255) { + if (bitlen < 255) { free(bits); return PM3_ESOFT; } - if (maxLen < BitLen && maxLen != 0) BitLen = maxLen; + if (maxlen < bitlen && maxlen != 0) + bitlen = maxlen; int foundclk = 0; //amplify signal before ST check if (amplify) { - askAmp(bits, BitLen); + askAmp(bits, bitlen); } size_t ststart = 0, stend = 0; // if (*stCheck) - bool st = DetectST(bits, &BitLen, &foundclk, &ststart, &stend); + bool st = DetectST(bits, &bitlen, &foundclk, &ststart, &stend); if (clk == 0) { if (foundclk == 32 || foundclk == 64) { @@ -553,34 +422,54 @@ int ASKDemod_ext(int clk, int invert, int maxErr, size_t maxLen, bool amplify, b PrintAndLogEx(DEBUG, "Found Sequence Terminator - First one is shown by orange / blue graph markers"); } - int startIdx = 0; - int errCnt = askdemod_ext(bits, &BitLen, &clk, &invert, maxErr, askamp, askType, &startIdx); + int start_idx = 0; + int errCnt = askdemod_ext(bits, &bitlen, &clk, &invert, maxErr, askamp, askType, &start_idx); - if (errCnt < 0 || BitLen < 16) { //if fatal error (or -1) - PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) No data found errors:%d, invert:%c, bitlen:%zu, clock:%d", errCnt, (invert) ? 'Y' : 'N', BitLen, clk); + if (errCnt < 0 || bitlen < 16) { //if fatal error (or -1) + PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) No data found errors:%d, %s bitlen:%zu, clock:%d" + , errCnt + , (invert) ? "inverted," : "" + , bitlen + , clk + ); free(bits); return PM3_ESOFT; } if (errCnt > maxErr) { - PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Too many errors found, errors:%d, bits:%zu, clock:%d", errCnt, BitLen, clk); + PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Too many errors found, errors:%d, bits:%zu, clock:%d" + , errCnt + , bitlen + , clk + ); free(bits); return PM3_ESOFT; } - if (verbose) PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Using clock:%d, invert:%d, bits found:%zu, start index %d", clk, invert, BitLen, startIdx); + if (verbose) { + PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) using clock:%d, %sbits found:%zu, start index %d" + , clk + , (invert) ? "inverted, " : "" + , bitlen + , start_idx + ); + } //output - setDemodBuff(bits, BitLen, 0); - setClockGrid(clk, startIdx); + setDemodBuff(bits, bitlen, 0); + setClockGrid(clk, start_idx); if (verbose) { if (errCnt > 0) - PrintAndLogEx(DEBUG, "# Errors during Demoding (shown as 7 in bit stream): %d", errCnt); - if (askType) - PrintAndLogEx(DEBUG, "ASK/Manchester - Clock: %d - Decoded bitstream:", clk); - else - PrintAndLogEx(DEBUG, "ASK/Raw - Clock: %d - Decoded bitstream:", clk); + PrintAndLogEx(DEBUG, "# Errors during demoding (shown as 7 in bit stream): %d", errCnt); + + if (askType) { + PrintAndLogEx(SUCCESS, _YELLOW_("ASK/Manchester") " - clock %d - decoded bitstream", clk); + PrintAndLogEx(INFO,"---------------------------------------------"); + } else { + PrintAndLogEx(SUCCESS, _YELLOW_("ASK/Raw") " - clock %d - decoded bitstream", clk); + PrintAndLogEx(INFO,"--------------------------------------"); + } printDemodBuff(0, false, false, false); } @@ -592,51 +481,46 @@ int ASKDemod_ext(int clk, int invert, int maxErr, size_t maxLen, bool amplify, b free(bits); return PM3_SUCCESS; } -int ASKDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, bool verbose, bool emSearch, uint8_t askType) { + +int ASKDemod(int clk, int invert, int maxErr, size_t maxlen, bool amplify, bool verbose, bool emSearch, uint8_t askType) { bool st = false; - return ASKDemod_ext(clk, invert, maxErr, maxLen, amplify, verbose, emSearch, askType, &st); + return ASKDemod_ext(clk, invert, maxErr, maxlen, amplify, verbose, emSearch, askType, &st); } // takes 5 arguments - clock, invert, maxErr, maxLen as integers and amplify as char == 'a' // attempts to demodulate ask while decoding manchester // prints binary found and saves in graphbuffer for further commands static int Cmdaskmandemod(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "data rawdemod --am", + "ASK/MANCHESTER demodulate the data in the GraphBuffer and output binary", + "data rawdemod --am --> demod a ask/manchester tag, using autodetect\n" + "data rawdemod --am -c 32 --> demod a ask/manchester tag, using a clock of RF/32\n" + "data rawdemod --am -i --> demod a ask/manchester tag, using autodetect, invert output\n" + "data rawdemod --am -c 32 -i --> demod a ask/manchester tag, using a clock of RF/32, invert output\n" + "data rawdemod --am -c 64 -i --max 0 --> demod a ask/manchester tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "amp", "try attempt demod with ask amplification (def no amp)"), + arg_int0("c", "clk", "", "set clock manually (def autodetect)"), + arg_lit0("i","inv", "invert output"), + arg_lit0("s", "st", "check for sequence terminator"), + arg_int0(NULL, "max", "", "maximum allowed errors (def 100)"), + arg_int0(NULL, "samples", "", "maximum samples to read (def 32768) [512 bits at RF/64]"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); - size_t slen = strlen(Cmd); + bool amplify = arg_get_lit(ctx, 1); + uint8_t clk = (uint8_t)arg_get_int_def(ctx, 2, 0) & 0xFF; + bool invert = arg_get_lit(ctx, 3); + bool st = arg_get_lit(ctx, 4); + uint8_t max_err = (uint8_t)arg_get_int_def(ctx, 5, 100) & 0xFF; + size_t max_len = (size_t)arg_get_int_def(ctx, 6, 0) & 0xFF; + CLIParserFree(ctx); - char cmdp = tolower(param_getchar(Cmd, 0)); - if (slen > 45 || cmdp == 'h') return usage_data_rawdemod_am(); - - bool st = false, amplify = false; - int clk = 0, invert = 0, maxErr = 100; - size_t maxLen = 0; - - if (slen) { - - if (Cmd[0] == 's') { - st = true; - Cmd++; - } else if (slen > 1 && Cmd[1] == 's') { - st = true; - Cmd += 2; - } - - char amp = tolower(param_getchar(Cmd, 0)); - sscanf(Cmd, "%i %i %i %zu %c", &clk, &invert, &maxErr, &maxLen, &); - - amplify = (amp == 'a'); - } - - if (clk == 1) { - invert = 1; - clk = 0; - } - - if (invert != 0 && invert != 1) { - PrintAndLogEx(WARNING, "Invalid value for invert: %i", invert); - return PM3_EINVARG; - } - return ASKDemod_ext(clk, invert, maxErr, maxLen, amplify, true, true, 1, &st); + return ASKDemod_ext(clk, invert, max_err, max_len, amplify, true, true, 1, &st); } // manchester decode @@ -822,35 +706,67 @@ int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) { // see ASKbiphaseDemod static int Cmdaskbiphdemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ab(); - int offset = 0, clk = 0, invert = 0, maxErr = 50; - sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr); - return ASKbiphaseDemod(offset, clk, invert, maxErr, true); + CLIParserContext *ctx; + CLIParserInit(&ctx, "data rawdemod --ab", + "ASK/BIPHASE demodulate the data in the GraphBuffer and output binary\n" + "NOTE, `--invert` for Conditional Dephase Encoding (CDP) AKA Differential Manchester\n", + "data rawdemod --ab --> demod a ask/biphase tag, using autodetect\n" + "data rawdemod --ab -c 32 --> demod a ask/biphase tag, using a clock of RF/32\n" + "data rawdemod --ab -i --> demod a ask/biphase tag, using autodetect, invert output\n" + "data rawdemod --ab -c 32 -i --> demod a ask/biphase tag, using a clock of RF/32, invert output\n" + "data rawdemod --ab -c 64 -i --max 0 --> demod a ask/biphase tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" + ); + void *argtable[] = { + arg_param_begin, + arg_int0("c", "clk", "", "set clock manually (def autodetect)"), + arg_lit0("i","inv", "invert output"), + arg_int0("o", "offset", "", "offset to begin biphase (def 0)"), + arg_int0(NULL, "max", "", "maximum allowed errors (def 50)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + uint8_t clk = (uint8_t)arg_get_int_def(ctx, 1, 0) & 0xFF; + bool invert = arg_get_lit(ctx, 2); + int offset = arg_get_int_def(ctx, 3, 0); + uint8_t max_err = (uint8_t)arg_get_int_def(ctx, 4, 50) & 0xFF; + CLIParserFree(ctx); + + return ASKbiphaseDemod(offset, clk, invert, max_err, true); } // see ASKDemod static int Cmdaskrawdemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ar(); - bool st = false; - int clk = 0; - int invert = 0; - int maxErr = 100; - size_t maxLen = 0; - bool amplify = false; - char amp = tolower(param_getchar(Cmd, 0)); - sscanf(Cmd, "%i %i %i %zu %c", &clk, &invert, &maxErr, &maxLen, &); - amplify = amp == 'a'; - if (clk == 1) { - invert = 1; - clk = 0; - } - if (invert != 0 && invert != 1) { - PrintAndLogEx(WARNING, "Invalid value for invert: %i", invert); - return PM3_EINVARG; - } - return ASKDemod_ext(clk, invert, maxErr, maxLen, amplify, true, false, 0, &st); + CLIParserContext *ctx; + CLIParserInit(&ctx, "data rawdemod --ar", + "ASK/RAW demodulate the data in the GraphBuffer and output binary", + "data rawdemod --ar -a --> demod a ask tag, using autodetect, amplified\n" + "data rawdemod --ar -c 32 --> demod a ask tag, using a clock of RF/32\n" + "data rawdemod --ar -i --> demod a ask tag, using autodetect, invert output\n" + "data rawdemod --ar -c 32 -i --> demod a ask tag, using a clock of RF/32, invert output\n" + "data rawdemod --ar -c 64 -i --max 0 --> demod a ask tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "amp", "try attempt demod with ask amplification (def no amp)"), + arg_int0("c", "clk", "", "set clock manually (def autodetect)"), + arg_lit0("i","inv", "invert output"), + arg_lit0("s", "st", "check for sequence terminator"), + arg_int0(NULL, "max", "", "maximum allowed errors (def 100)"), + arg_int0(NULL, "samples", "", "maximum samples to read (def 32768) [512 bits at RF/64]"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool amplify = arg_get_lit(ctx, 1); + uint8_t clk = (uint8_t)arg_get_int_def(ctx, 2, 0) & 0xFF; + bool invert = arg_get_lit(ctx, 3); + bool st = arg_get_lit(ctx, 4); + uint8_t max_err = (uint8_t)arg_get_int_def(ctx, 5, 100) & 0xFF; + size_t max_len = (size_t)arg_get_int_def(ctx, 6, 0) & 0xFF; + CLIParserFree(ctx); + + return ASKDemod_ext(clk, invert, max_err, max_len, amplify, true, false, 0, &st); } int AutoCorrelate(const int *in, int *out, size_t len, size_t window, bool SaveGrph, bool verbose) { @@ -1248,23 +1164,29 @@ static char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert) { // defaults: clock = 50, invert=1, fchigh=10, fclow=8 (RF/10 RF/8 (fsk2a)) int FSKrawDemod(uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, bool verbose) { //raw fsk demod no manchester decoding no start bit finding just get binary from wave - if (getSignalProperties()->isnoise) + if (getSignalProperties()->isnoise) { + if (verbose) { + PrintAndLogEx(INFO, "signal looks like noise"); + } return PM3_ESOFT; + } uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t)); if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); return PM3_EMALLOC; } - size_t BitLen = getFromGraphBuf(bits); - if (BitLen == 0) { + size_t bitlen = getFromGraphBuf(bits); + if (bitlen == 0) { + PrintAndLogEx(DEBUG, "DEBUG: no data in graphbuf"); free(bits); return PM3_ESOFT; } //get field clock lengths if (!fchigh || !fclow) { - uint16_t fcs = countFC(bits, BitLen, true); + uint16_t fcs = countFC(bits, bitlen, true); if (!fcs) { fchigh = 10; fclow = 8; @@ -1276,19 +1198,27 @@ int FSKrawDemod(uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, bo //get bit clock length if (!rfLen) { int firstClockEdge = 0; //todo - align grid on graph with this... - rfLen = detectFSKClk(bits, BitLen, fchigh, fclow, &firstClockEdge); + rfLen = detectFSKClk(bits, bitlen, fchigh, fclow, &firstClockEdge); if (!rfLen) rfLen = 50; } - int startIdx = 0; - int size = fskdemod(bits, BitLen, rfLen, invert, fchigh, fclow, &startIdx); + + int start_idx = 0; + int size = fskdemod(bits, bitlen, rfLen, invert, fchigh, fclow, &start_idx); if (size > 0) { setDemodBuff(bits, size, 0); - setClockGrid(rfLen, startIdx); + setClockGrid(rfLen, start_idx); // Now output the bitstream to the scrollback by line of 16 bits if (verbose || g_debugMode) { - PrintAndLogEx(DEBUG, "DEBUG: (FSKrawDemod) Using Clock:%u, invert:%u, fchigh:%u, fclow:%u", rfLen, invert, fchigh, fclow); - PrintAndLogEx(NORMAL, "%s decoded bitstream:", GetFSKType(fchigh, fclow, invert)); + PrintAndLogEx(DEBUG, "DEBUG: (FSKrawDemod) using clock:%u, %sfc high:%u, fc low:%u" + , rfLen + , (invert) ? "inverted, " : "" + , fchigh + , fclow + ); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, _YELLOW_("%s") " decoded bitstream", GetFSKType(fchigh, fclow, invert)); + PrintAndLogEx(INFO,"-----------------------"); printDemodBuff(0, false, invert, false); } goto out; @@ -1305,33 +1235,48 @@ out: // takes 4 arguments - Clock, invert, fchigh, fclow // defaults: clock = 50, invert=1, fchigh=10, fclow=8 (RF/10 RF/8 (fsk2a)) static int CmdFSKrawdemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 20 || cmdp == 'h') return usage_data_rawdemod_fs(); - uint8_t rfLen, invert, fchigh, fclow; + CLIParserContext *ctx; + CLIParserInit(&ctx, "data rawdemod --fs", + "FSK demodulate the data in the GraphBuffer and output binary", + "data rawdemod --fs --> demod an fsk tag, using autodetect\n" + "data rawdemod --fs -c 32 --> demod an fsk tag, using a clock of RF/32, autodetect fc\n" + "data rawdemod --fs -i --> demod an fsk tag, using autodetect, invert output\n" + "data rawdemod --fs -c 32 -i --> demod an fsk tag, using a clock of RF/32, invert output, autodetect fc\n" + "data rawdemod --fs -c 64 --hi 8 --lo 5 --> demod an fsk1 RF/64 tag\n" + "data rawdemod --fs -c 50 --hi 10 --lo 8 --> demod an fsk2 RF/50 tag\n" + "data rawdemod --fs -c 50 -i --hi 10 --lo 8 --> demod an fsk2a RF/50 tag\n" + ); + void *argtable[] = { + arg_param_begin, + arg_int0("c", "clk", "", "set clock manually (def: autodetect)"), + arg_lit0("i","inv", "invert output"), + arg_int0(NULL, "hi", "", "larger field clock length (def: autodetect)"), + arg_int0(NULL, "lo", "", "small field clock length (def: autodetect)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); - //set defaults - //set options from parameters entered with the command - rfLen = param_get8(Cmd, 0); - invert = param_get8(Cmd, 1); - fchigh = param_get8(Cmd, 2); - fclow = param_get8(Cmd, 3); + uint8_t clk = (uint8_t)arg_get_int_def(ctx, 1, 0) & 0xFF; + bool invert = arg_get_lit(ctx, 2); + uint8_t fchigh = (uint8_t)arg_get_int_def(ctx, 3, 0) & 0xFF; + uint8_t fclow = (uint8_t)arg_get_int_def(ctx, 4, 0) & 0xFF; + CLIParserFree(ctx); - if (strlen(Cmd) > 0 && strlen(Cmd) <= 2) { - if (rfLen == 1) { - invert = 1; //if invert option only is used - rfLen = 0; - } - } - return FSKrawDemod(rfLen, invert, fchigh, fclow, true); + return FSKrawDemod(clk, invert, fchigh, fclow, true); } // attempt to psk1 demod graph buffer int PSKDemod(int clk, int invert, int maxErr, bool verbose) { - if (getSignalProperties()->isnoise) + if (getSignalProperties()->isnoise) { + if (verbose) { + PrintAndLogEx(INFO, "signal looks like noise"); + } return PM3_ESOFT; + } uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t)); if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); return PM3_EMALLOC; } size_t bitlen = getFromGraphBuf(bits); @@ -1372,36 +1317,41 @@ int NRZrawDemod(int clk, int invert, int maxErr, bool verbose) { int errCnt = 0, clkStartIdx = 0; - if (getSignalProperties()->isnoise) + if (getSignalProperties()->isnoise) { + if (verbose) { + PrintAndLogEx(INFO, "signal looks like noise"); + } return PM3_ESOFT; + } uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t)); if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); return PM3_EMALLOC; } - size_t BitLen = getFromGraphBuf(bits); + size_t bitlen = getFromGraphBuf(bits); - if (BitLen == 0) { + if (bitlen == 0) { free(bits); return PM3_ESOFT; } - errCnt = nrzRawDemod(bits, &BitLen, &clk, &invert, &clkStartIdx); + errCnt = nrzRawDemod(bits, &bitlen, &clk, &invert, &clkStartIdx); if (errCnt > maxErr) { - PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Too many errors found, clk: %d, invert: %d, numbits: %zu, errCnt: %d", clk, invert, BitLen, errCnt); + PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Too many errors found, clk: %d, invert: %d, numbits: %zu, errCnt: %d", clk, invert, bitlen, errCnt); free(bits); return PM3_ESOFT; } - if (errCnt < 0 || BitLen < 16) { //throw away static - allow 1 and -1 (in case of threshold command first) - PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) no data found, clk: %d, invert: %d, numbits: %zu, errCnt: %d", clk, invert, BitLen, errCnt); + if (errCnt < 0 || bitlen < 16) { //throw away static - allow 1 and -1 (in case of threshold command first) + PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) no data found, clk: %d, invert: %d, numbits: %zu, errCnt: %d", clk, invert, bitlen, errCnt); free(bits); return PM3_ESOFT; } - if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Tried NRZ Demod using Clock: %d - invert: %d - Bits Found: %zu", clk, invert, BitLen); + if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Tried NRZ Demod using Clock: %d - invert: %d - Bits Found: %zu", clk, invert, bitlen); //prime demod buffer for output - setDemodBuff(bits, BitLen, 0); + setDemodBuff(bits, bitlen, 0); setClockGrid(clk, clkStartIdx); @@ -1417,45 +1367,67 @@ int NRZrawDemod(int clk, int invert, int maxErr, bool verbose) { } static int CmdNRZrawDemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_nr(); - int invert = 0, clk = 0, maxErr = 100; - sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr); - if (clk == 1) { - invert = 1; - clk = 0; - } + CLIParserContext *ctx; + CLIParserInit(&ctx, "data rawdemod --nr", + "NRZ/DIRECT demodulate the data in the GraphBuffer and output binary", + "data rawdemod --nr --> demod a nrz/direct tag, using autodetect\n" + "data rawdemod --nr -c 32 --> demod a nrz/direct tag, using a clock of RF/32\n" + "data rawdemod --nr -i --> demod a nrz/direct tag, using autodetect, invert output\n" + "data rawdemod --nr -c 32 -i --> demod a nrz/direct tag, using a clock of RF/32, invert output\n" + "data rawdemod --nr -c 64 -i --max 0 --> demod a nrz/direct tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" + ); + void *argtable[] = { + arg_param_begin, + arg_int0("c", "clk", "", "set clock manually (def autodetect)"), + arg_lit0("i","inv", "invert output"), + arg_int0(NULL, "max", "", "maximum allowed errors (def 100)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); - if (invert != 0 && invert != 1) { - PrintAndLogEx(WARNING, "(NRZrawDemod) Invalid argument: %s", Cmd); - return PM3_EINVARG; - } - return NRZrawDemod(clk, invert, maxErr, true); + uint8_t clk = (uint8_t)arg_get_int_def(ctx, 1, 0) & 0xFF; + bool invert = arg_get_lit(ctx, 2); + uint8_t max_err = (uint8_t)arg_get_int_def(ctx, 3, 100) & 0xFF; + CLIParserFree(ctx); + + return NRZrawDemod(clk, invert, max_err, true); } // takes 3 arguments - clock, invert, max_err as integers // attempts to demodulate psk only // prints binary found and saves in demodbuffer for further commands int CmdPSK1rawDemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_p1(); - int clk = 0, invert = 0, max_err = 100; - sscanf(Cmd, "%i %i %i", &clk, &invert, &max_err); - if (clk == 1) { - invert = 1; - clk = 0; - } - if (invert != 0 && invert != 1) { - PrintAndLogEx(WARNING, "Invalid value for invert: %i", invert); - return PM3_EINVARG; - } + CLIParserContext *ctx; + CLIParserInit(&ctx, "data rawdemod --p1", + "PSK1 demodulate the data in the GraphBuffer and output binary", + "data rawdemod --p1 --> demod a psk1 tag, using autodetect\n" + "data rawdemod --p1 -c 32 --> demod a psk1 tag, using a clock of RF/32\n" + "data rawdemod --p1 -i --> demod a psk1 tag, using autodetect, invert output\n" + "data rawdemod --p1 -c 32 -i --> demod a psk1 tag, using a clock of RF/32, invert output\n" + "data rawdemod --p1 -c 64 -i --max 0 --> demod a psk1 tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" + ); + void *argtable[] = { + arg_param_begin, + arg_int0("c", "clk", "", "set clock manually (def autodetect)"), + arg_lit0("i","inv", "invert output"), + arg_int0(NULL, "max", "", "maximum allowed errors (def 100)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + uint8_t clk = (uint8_t)arg_get_int_def(ctx, 1, 0) & 0xFF; + bool invert = arg_get_lit(ctx, 2); + uint8_t max_err = (uint8_t)arg_get_int_def(ctx, 3, 100) & 0xFF; + CLIParserFree(ctx); + int ans = PSKDemod(clk, invert, max_err, true); //output if (ans != PM3_SUCCESS) { if (g_debugMode) PrintAndLogEx(ERR, "Error demoding: %d", ans); return PM3_ESOFT; } - PrintAndLogEx(NORMAL, "PSK1 demoded bitstream:"); + PrintAndLogEx(SUCCESS, _YELLOW_("PSK1") " demoded bitstream"); + PrintAndLogEx(INFO, "----------------------"); // Now output the bitstream to the scrollback by line of 16 bits printDemodBuff(0, false, invert, false); return PM3_SUCCESS; @@ -1463,25 +1435,37 @@ int CmdPSK1rawDemod(const char *Cmd) { // takes same args as cmdpsk1rawdemod static int CmdPSK2rawDemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_p2(); - int clk = 0, invert = 0, max_err = 100; - sscanf(Cmd, "%i %i %i", &clk, &invert, &max_err); - if (clk == 1) { - invert = 1; - clk = 0; - } - if (invert != 0 && invert != 1) { - PrintAndLogEx(WARNING, "Invalid value for invert: %i", invert); - return PM3_EINVARG; - } + CLIParserContext *ctx; + CLIParserInit(&ctx, "data rawdemod --p2", + "PSK2 demodulate the data in the GraphBuffer and output binary", + "data rawdemod --p2 --> demod a psk2 tag, using autodetect\n" + "data rawdemod --p2 -c 32 --> demod a psk2 tag, using a clock of RF/32\n" + "data rawdemod --p2 -i --> demod a psk2 tag, using autodetect, invert output\n" + "data rawdemod --p2 -c 32 -i --> demod a psk2 tag, using a clock of RF/32, invert output\n" + "data rawdemod --p2 -c 64 -i --max 0 --> demod a psk2 tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" + ); + void *argtable[] = { + arg_param_begin, + arg_int0("c", "clk", "", "set clock manually (def autodetect)"), + arg_lit0("i","inv", "invert output"), + arg_int0(NULL, "max", "", "maximum allowed errors (def 100)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + uint8_t clk = (uint8_t)arg_get_int_def(ctx, 1, 0) & 0xFF; + bool invert = arg_get_lit(ctx, 2); + uint8_t max_err = (uint8_t)arg_get_int_def(ctx, 3, 100) & 0xFF; + CLIParserFree(ctx); + int ans = PSKDemod(clk, invert, max_err, true); if (ans != PM3_SUCCESS) { if (g_debugMode) PrintAndLogEx(ERR, "Error demoding: %d", ans); return PM3_ESOFT; } psk1TOpsk2(DemodBuffer, DemodBufferLen); - PrintAndLogEx(NORMAL, "PSK2 demoded bitstream:"); + PrintAndLogEx(SUCCESS, _YELLOW_("PSK2") " demoded bitstream"); + PrintAndLogEx(INFO, "----------------------"); // Now output the bitstream to the scrollback by line of 16 bits printDemodBuff(0, false, invert, false); return PM3_SUCCESS; @@ -1489,21 +1473,73 @@ static int CmdPSK2rawDemod(const char *Cmd) { // combines all raw demod functions into one menu command static int CmdRawDemod(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "data rawdemod", + "Demodulate the data in the GraphBuffer and output binary", + "data rawdemod --fs --> demod FSK - autodetect\n" + "data rawdemod --ab --> demod ASK/BIPHASE - autodetect\n" + "data rawdemod --am --> demod ASK/MANCHESTER - autodetect\n" + "data rawdemod --ar --> demod ASK/RAW - autodetect\n" + "data rawdemod --nr --> demod NRZ/DIRECT - autodetect\n" + "data rawdemod --p1 --> demod PSK1 - autodetect\n" + "data rawdemod --p2 --> demod PSK2 - autodetect\n" + ); + void *argtable[] = { + arg_param_begin, + arg_lit0(NULL, "ab", "ASK/Biphase demodulation"), + arg_lit0(NULL, "am", "ASK/Manchester demodulation"), + arg_lit0(NULL, "ar", "ASK/Raw demodulation"), + arg_lit0(NULL, "fs", "FSK demodulation"), + arg_lit0(NULL, "nr", "NRZ/Direct demodulation"), + arg_lit0(NULL, "p1", "PSK 1 demodulation"), + arg_lit0(NULL, "p2", "PSK 2 demodulation"), + arg_strn(NULL, NULL, "", 0, 35, "params for sub command"), + arg_param_end + }; + + // + size_t n = MIN(strlen(Cmd), 4); + char tmp[7]; + memset(tmp, 0, sizeof(tmp)); + strncpy(tmp, Cmd, n); + + CLIExecWithReturn(ctx, tmp, argtable, false); + bool ab = arg_get_lit(ctx, 1); + bool am = arg_get_lit(ctx, 2); + bool ar = arg_get_lit(ctx, 3); + bool fs = arg_get_lit(ctx, 4); + bool nr = arg_get_lit(ctx, 5); + bool p1 = arg_get_lit(ctx, 6); + bool p2 = arg_get_lit(ctx, 7); + CLIParserFree(ctx); + + int foo = (ab + am + ar + fs + nr + p1 + p2); + if ( foo > 1 ) { + PrintAndLogEx(WARNING, "please, select only one modulation"); + return PM3_EINVARG; + } + if ( foo == 0 ) { + PrintAndLogEx(WARNING, "please, select a modulation"); + return PM3_EINVARG; + } + int ans = 0; - - if (strlen(Cmd) > 35 || strlen(Cmd) < 2) - return usage_data_rawdemod(); - - str_lower((char *)Cmd); - - if (str_startswith(Cmd, "fs") || Cmd[0] == 'f') ans = CmdFSKrawdemod(Cmd + 2); - else if (str_startswith(Cmd, "ab")) ans = Cmdaskbiphdemod(Cmd + 2); - else if (str_startswith(Cmd, "am")) ans = Cmdaskmandemod(Cmd + 2); - else if (str_startswith(Cmd, "ar")) ans = Cmdaskrawdemod(Cmd + 2); - else if (str_startswith(Cmd, "nr") || Cmd[0] == 'n') ans = CmdNRZrawDemod(Cmd + 2); - else if (str_startswith(Cmd, "p1")) ans = CmdPSK1rawDemod(Cmd + 2); - else if (str_startswith(Cmd, "p2")) ans = CmdPSK2rawDemod(Cmd + 2); - else PrintAndLogEx(WARNING, "Unknown modulation entered - see help ('h') for parameter structure"); + const char *s = Cmd + n; + if (fs) + ans = CmdFSKrawdemod(s); + else if (ab) + ans = Cmdaskbiphdemod(s); + else if (am) + ans = Cmdaskmandemod(s); + else if (ar) + ans = Cmdaskrawdemod(s); + else if (nr) + ans = CmdNRZrawDemod(s); + else if (p1) + ans = CmdPSK1rawDemod(s); + else if (p2) + ans = CmdPSK2rawDemod(s); return ans; } @@ -1983,7 +2019,7 @@ static int CmdLoad(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_strx0("f", "file", "", "file to load"), + arg_str1("f", "file", "", "file to load"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); From 4c696885e464175729db74fde96c99fdd406e482 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 17 Apr 2021 23:18:13 +0200 Subject: [PATCH 339/373] typos --- client/src/cmddata.c | 8 ++++---- client/src/cmdlf.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index d13363172..3b6a8164a 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -530,7 +530,7 @@ static int Cmdmandecoderaw(const char *Cmd) { CLIParserInit(&ctx, "data manrawdecode", "Manchester decode binary stream in DemodBuffer\n" "Converts 10 and 01 and converts to 0 and 1 respectively\n" - " - must have binary sequence in demodbuffer (run `data rawdemod ar` before)", + " - must have binary sequence in demodbuffer (run `data rawdemod --ar` before)", "data manrawdecode" ); void *argtable[] = { @@ -545,7 +545,7 @@ static int Cmdmandecoderaw(const char *Cmd) { CLIParserFree(ctx); if (DemodBufferLen == 0) { - PrintAndLogEx(WARNING, "DemodBuffer empty, run " _YELLOW_("`data rawdemod ar`")); + PrintAndLogEx(WARNING, "DemodBuffer empty, run " _YELLOW_("`data rawdemod --ar`")); return PM3_ESOFT; } @@ -612,7 +612,7 @@ static int CmdBiphaseDecodeRaw(const char *Cmd) { CLIParserInit(&ctx, "data biphaserawdecode", "Biphase decode binary stream in DemodBuffer\n" "Converts 10 or 01 -> 1 and 11 or 00 -> 0\n" - " - must have binary sequence in demodbuffer (run `data rawdemod ar` before)\n" + " - must have binary sequence in demodbuffer (run `data rawdemod --ar` before)\n" " - invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester", "data biphaserawdecode --> decode biphase bitstream from the demodbuffer\n" "data biphaserawdecode -oi --> decode biphase bitstream from the demodbuffer, adjust offset, and invert output" @@ -631,7 +631,7 @@ static int CmdBiphaseDecodeRaw(const char *Cmd) { CLIParserFree(ctx); if (DemodBufferLen == 0) { - PrintAndLogEx(WARNING, "DemodBuffer empty, run " _YELLOW_("`data rawdemod ar`")); + PrintAndLogEx(WARNING, "DemodBuffer empty, run " _YELLOW_("`data rawdemod --ar`")); return PM3_ESOFT; } diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index c1d0e4bb1..c1875a78a 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -1472,15 +1472,15 @@ int CmdLFfind(const char *Cmd) { bool st = true; if (ASKDemod_ext(0, 0, 0, 0, false, true, false, 1, &st) == PM3_SUCCESS) { PrintAndLogEx(INFO, "Unknown ASK Modulated and Manchester encoded Tag found!"); - PrintAndLogEx(INFO, "if it does not look right it could instead be ASK/Biphase - try " _YELLOW_("'data rawdemod ab'")); + PrintAndLogEx(INFO, "if it does not look right it could instead be ASK/Biphase - try " _YELLOW_("'data rawdemod --ab'")); goto out; } if (CmdPSK1rawDemod("") == PM3_SUCCESS) { PrintAndLogEx(INFO, "Possible unknown PSK1 Modulated Tag found above!"); - PrintAndLogEx(INFO, " Could also be PSK2 - try " _YELLOW_("'data rawdemod p2'")); + PrintAndLogEx(INFO, " Could also be PSK2 - try " _YELLOW_("'data rawdemod --p2'")); PrintAndLogEx(INFO, " Could also be PSK3 - [currently not supported]"); - PrintAndLogEx(INFO, " Could also be NRZ - try " _YELLOW_("'data rawdemod nr")); + PrintAndLogEx(INFO, " Could also be NRZ - try " _YELLOW_("'data rawdemod --nr")); goto out; } From d1507bd4c0f80923fb1aa408702f8dfddec7302a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 18 Apr 2021 09:18:42 +0200 Subject: [PATCH 340/373] fix lua script - hf_mf_autopwn --- client/luascripts/hf_mf_autopwn.lua | 44 +++++++++++++---------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/client/luascripts/hf_mf_autopwn.lua b/client/luascripts/hf_mf_autopwn.lua index 029d16d7a..09df92b9d 100644 --- a/client/luascripts/hf_mf_autopwn.lua +++ b/client/luascripts/hf_mf_autopwn.lua @@ -6,11 +6,13 @@ local ansicolors = require('ansicolors') copyright = '' author = "Martin Holst Swende" -version = 'v1.0.3' +version = 'v1.0.4' desc = [[ This is a script which automates cracking and dumping mifare classic cards. It sets itself into 'listening'-mode, after which it cracks and dumps any mifare classic card that you place by the device. + +Please consider using the native command `hf mf autopwn` ]] example = [[ 1. script run hf_mf_autopwn @@ -84,46 +86,40 @@ local function wait_for_mifare() return nil, 'Aborted by user' end -local function nested(key,sak) - local typ = 1 +local function get_mf_size(sak) + local foo = "--1k" if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k - typ = 4 + foo = "--4k" elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K - typ = 1 + foo = "--1k" elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k - typ = 0 + foo = "--mini" elseif 0x10 == sak then-- "NXP MIFARE Plus 2k" - typ = 2 + foo = "--2k" elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K" - typ = 1 + foo = "--1k" else print("I don't know how many sectors there are on this type of card, defaulting to 16") end - local cmd = string.format('hf mf nested -t %d -b 0 --keya -k %s --dumpkeys', typ, key) + return foo +end + +local function nested(key, sak) + local mfs = get_mf_size(sak) + local cmd = string.format('hf mf nested %s --blk 0 -k %s --dump', mfs, key) core.console(cmd) end -local function dump_tag(uid, numsectors) +local function dump_tag(uid, sak) dbg('dumping tag memory') - local typ = 1 - if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k - typ = 4 - elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K - typ = 1 - elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k - typ = 0 - elseif 0x10 == sak then-- "NXP MIFARE Plus 2k" - typ = 2 - elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K" - typ = 1 - end - + if utils.confirm('Do you wish to create a memory dump of tag?') then local dumpfile = 'hf-mf-'..uid..'-dump' - local dmp = ('hf mf dump -t %s -f %s'):format(typ, dumpfile) + local mfs = get_mf_size(sak) + local dmp = ('hf mf dump %s -f %s'):format(mfs, dumpfile) core.console(dmp) -- Save the global args, those are *our* arguments From 155443754b941f099f7db2347e9b6163f4cf092c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 18 Apr 2021 11:35:38 +0200 Subject: [PATCH 341/373] better detection of empty blocks --- client/src/cmdhficlass.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index a75d548eb..709300cf5 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -43,6 +43,7 @@ static void iclass_set_last_known_card(picopass_hdr_t *card) { } static uint8_t empty[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +static uint8_t zeros[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static int CmdHelp(const char *Cmd); @@ -1273,17 +1274,18 @@ static int CmdHFiClassDecrypt(const char *Cmd) { PrintAndLogEx(NORMAL, ""); // decode block 6 - if (memcmp(decrypted + (8 * 6), empty, 8) != 0) { + bool has_values = (memcmp(decrypted + (8 * 6), empty, 8) != 0) && (memcmp(decrypted + (8 * 6), zeros, 8) != 0); + if (has_values) { if (use_sc) { DecodeBlock6(decrypted + (8 * 6)); } } // decode block 7-8-9 - if (memcmp(decrypted + (8 * 7), empty, 8) != 0) { + has_values = (memcmp(decrypted + (8 * 7), empty, 8) != 0) && (memcmp(decrypted + (8 * 7), zeros, 8) != 0); + if (has_values) { //todo: remove preamble/sentinal - uint32_t top = 0, mid, bot; mid = bytes_to_num(decrypted + (8 * 7), 4); bot = bytes_to_num(decrypted + (8 * 7) + 4, 4); @@ -1305,18 +1307,20 @@ static int CmdHFiClassDecrypt(const char *Cmd) { HIDTryUnpack(&packed, true); } else { - PrintAndLogEx(INFO, "No credential found."); + PrintAndLogEx(INFO, "No credential found"); } // decode block 9 - if (memcmp(decrypted + (8 * 9), empty, 8) != 0) { + has_values = (memcmp(decrypted + (8 * 9), empty, 8) != 0) && (memcmp(decrypted + (8 * 9), zeros, 8) != 0); + if (has_values) { uint8_t usr_blk_len = GetNumberBlocksForUserId(decrypted + (8 * 6)); if (usr_blk_len < 3) { - - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "Block 9 decoder"); if (use_sc) { + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "Block 9 decoder"); + uint8_t pinsize = GetPinSize(decrypted + (8 * 6)); if (pinsize > 0) { From e28f8c5c65ce228a1da9f199b4881ae6bb956d15 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 18 Apr 2021 15:07:56 +0200 Subject: [PATCH 342/373] fix config cards generation and it uploads direct to device. --- client/src/cmdhficlass.c | 75 ++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 709300cf5..d8e0a61f4 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -113,6 +113,28 @@ static inline uint32_t leadingzeros(uint64_t a) { #endif } +static void iclass_upload_emul(uint8_t *d, uint32_t n, uint32_t *bytes_sent) { + // fast push mode + conn.block_after_ACK = true; + + //Send to device + *bytes_sent = 0; + uint32_t bytes_remaining = n; + + while (bytes_remaining > 0) { + uint32_t bytes_in_packet = MIN(PM3_CMD_DATA_SIZE, bytes_remaining); + if (bytes_in_packet == bytes_remaining) { + // Disable fast mode on last packet + conn.block_after_ACK = false; + } + clearCommandBuffer(); + SendCommandOLD(CMD_HF_ICLASS_EML_MEMSET, *bytes_sent, bytes_in_packet, 0, d + *bytes_sent, bytes_in_packet); + bytes_remaining -= bytes_in_packet; + *bytes_sent += bytes_in_packet; + } +} + + const char *card_types[] = { "PicoPass 16K / 16", // 000 "PicoPass 32K with current book 16K / 16", // 001 @@ -199,7 +221,7 @@ static const iclass_config_card_item_t *get_config_card_item(int idx) { static void print_config_cards(void) { if (check_config_card(&iclass_config_types[0])) { PrintAndLogEx(INFO, "---- " _CYAN_("Config cards available") " ------------"); - for (int i = 0; i < ARRAYLEN(iclass_config_types); ++i) { + for (int i = 0; i < ARRAYLEN(iclass_config_types) - 1 ; ++i) { PrintAndLogEx(INFO, "%2d, %s", i, iclass_config_types[i].desc); } PrintAndLogEx(NORMAL, ""); @@ -237,7 +259,13 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke PrintAndLogEx(FAILED, "failed to allocate memory"); return PM3_EMALLOC; } - memset(data, 0xFF, tot_bytes); + + + // calc diversified key for selected card + HFiClassCalcDivKey(iclass_last_known_card.csn, iClass_Key_Table[0], iclass_last_known_card.key_d, false); + + memset(data, 0x00, tot_bytes); + memcpy(data, (uint8_t*)&iclass_last_known_card, sizeof(picopass_hdr_t)); // Keyrolling configuration cards are special. if (strstr(o->desc, "Keyroll") != NULL) { @@ -325,19 +353,14 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke memcpy(data + (6 * 8), o->data, sizeof(o->data)); } - // create filename - char filename[FILE_PATH_SIZE] = {0}; - char *fptr = filename; - fptr += snprintf(fptr, sizeof(filename), "hf-iclass-"); - FillFileNameByUID(fptr, data, "-dump", 8); - - // save dump file - saveFile(filename, ".bin", data, tot_bytes); - saveFileEML(filename, data, tot_bytes, 8); - saveFileJSON(filename, jsfIclass, data, tot_bytes, NULL); - - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass view -f %s.bin") "` to view dump file", filename); + //Send to device + uint32_t bytes_sent = 0; + iclass_upload_emul(data, tot_bytes, &bytes_sent); free(data); + + PrintAndLogEx(SUCCESS, "sent %d bytes of data to device emulator memory", bytes_sent); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass eview") "` to view dump file"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass sim -t 3") "` to start simulating config card"); return PM3_SUCCESS; } @@ -926,26 +949,10 @@ static int CmdHFiClassELoad(const char *Cmd) { print_picopass_header((picopass_hdr_t *) dump); print_picopass_info((picopass_hdr_t *) dump); - // fast push mode - conn.block_after_ACK = true; - //Send to device uint32_t bytes_sent = 0; - uint32_t bytes_remaining = bytes_read; - - while (bytes_remaining > 0) { - uint32_t bytes_in_packet = MIN(PM3_CMD_DATA_SIZE, bytes_remaining); - if (bytes_in_packet == bytes_remaining) { - // Disable fast mode on last packet - conn.block_after_ACK = false; - } - clearCommandBuffer(); - SendCommandOLD(CMD_HF_ICLASS_EML_MEMSET, bytes_sent, bytes_in_packet, 0, dump + bytes_sent, bytes_in_packet); - bytes_remaining -= bytes_in_packet; - bytes_sent += bytes_in_packet; - } + iclass_upload_emul(dump, bytes_read, &bytes_sent); free(dump); - PrintAndLogEx(SUCCESS, "sent %d bytes of data to device emulator memory", bytes_sent); return PM3_SUCCESS; } @@ -1004,7 +1011,7 @@ static int CmdHFiClassESave(const char *Cmd) { saveFileJSON(filename, jsfIclass, dump, bytes, NULL); free(dump); - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass view -f %s.bin") "` to view dump file", filename); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass view -f") "` to view dump file"); return PM3_SUCCESS; } @@ -1807,8 +1814,8 @@ write_dump: saveFileEML(filename, tag_data, bytes_got, 8); saveFileJSON(filename, jsfIclass, tag_data, bytes_got, NULL); - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass decrypt -f %s.bin") "` to decrypt dump file", filename); - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass view -f %s.bin") "` to view dump file", filename); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass decrypt -f") "` to decrypt dump file"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass view -f") "` to view dump file"); PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } From 729fd0439c5de6688db0a367b3f84738b7c5c44c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 18 Apr 2021 16:05:45 +0200 Subject: [PATCH 343/373] text --- client/src/cmdhficlass.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index d8e0a61f4..5108cde5e 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -3797,15 +3797,15 @@ static int CmdHFiClassAutopwn(const char *Cmd) { */ static int CmdHFiClassConfigCard(const char *Cmd) { - CLIParserContext *ctx; CLIParserInit(&ctx, "hf iclass configcard", - "Manage reader configuration card via Cardhelper", - "hf iclass configcard -l --> download config cards\n" - "hf iclass configcard -p --> print config card\n" - "hf iclass configcard --ci 1 --> use config card in slot 1\n" + "Manage reader configuration card via Cardhelper,\n" + "The generated config card will be uploaded to device emulator memory.\n" + "You can start simulating `hf iclass sim -t 3` or use the emul commands", + "hf iclass configcard -l --> download config card settings\n" + "hf iclass configcard -p --> print all config cards\n" + "hf iclass configcard --ci 1 --> view config card setting in slot 1\n" "hf iclass configcard -g --ci 0 --> generate config file from slot 0" - ); void *argtable[] = { From ed78bca62b32345796d33a903e22ff35927cc4dc Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 18 Apr 2021 18:31:51 +0200 Subject: [PATCH 344/373] style --- client/luascripts/hf_mf_autopwn.lua | 2 +- client/src/aidsearch.c | 2 +- client/src/cmddata.c | 210 ++++++++++++++-------------- client/src/cmdhficlass.c | 4 +- client/src/cmdhflist.c | 4 +- client/src/cmdlfpac.c | 4 +- 6 files changed, 113 insertions(+), 113 deletions(-) diff --git a/client/luascripts/hf_mf_autopwn.lua b/client/luascripts/hf_mf_autopwn.lua index 09df92b9d..b5d6f850d 100644 --- a/client/luascripts/hf_mf_autopwn.lua +++ b/client/luascripts/hf_mf_autopwn.lua @@ -113,7 +113,7 @@ end local function dump_tag(uid, sak) dbg('dumping tag memory') - + if utils.confirm('Do you wish to create a memory dump of tag?') then local dumpfile = 'hf-mf-'..uid..'-dump' diff --git a/client/src/aidsearch.c b/client/src/aidsearch.c index 360353fe0..377bc2f9e 100644 --- a/client/src/aidsearch.c +++ b/client/src/aidsearch.c @@ -24,7 +24,7 @@ static int openAIDFile(json_t **root, bool verbose) { int retval = PM3_SUCCESS; *root = json_load_file(path, 0, &error); - if (!*root) { + if (!*root) { PrintAndLogEx(ERR, "json (%s) error on line %d: %s", path, error.line, error.text); retval = PM3_ESOFT; goto out; diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 3b6a8164a..ad67126be 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -365,18 +365,18 @@ static int CmdConvertBitStream(const char *Cmd) { // askType switches decode: ask/raw = 0, ask/manchester = 1 int ASKDemod_ext(int clk, int invert, int maxErr, size_t maxlen, bool amplify, bool verbose, bool emSearch, uint8_t askType, bool *stCheck) { PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) clk %i invert %i maxErr %i maxLen %zu amplify %i verbose %i emSearch %i askType %i " - , clk - , invert - , maxErr - , maxlen - , amplify - , verbose - , emSearch - , askType - ); + , clk + , invert + , maxErr + , maxlen + , amplify + , verbose + , emSearch + , askType + ); uint8_t askamp = 0; - if (maxlen == 0) + if (maxlen == 0) maxlen = pm3_capabilities.bigbuf_size; uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t)); @@ -427,32 +427,32 @@ int ASKDemod_ext(int clk, int invert, int maxErr, size_t maxlen, bool amplify, b if (errCnt < 0 || bitlen < 16) { //if fatal error (or -1) PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) No data found errors:%d, %s bitlen:%zu, clock:%d" - , errCnt - , (invert) ? "inverted," : "" - , bitlen - , clk - ); + , errCnt + , (invert) ? "inverted," : "" + , bitlen + , clk + ); free(bits); return PM3_ESOFT; } if (errCnt > maxErr) { PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Too many errors found, errors:%d, bits:%zu, clock:%d" - , errCnt - , bitlen - , clk - ); + , errCnt + , bitlen + , clk + ); free(bits); return PM3_ESOFT; } if (verbose) { PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) using clock:%d, %sbits found:%zu, start index %d" - , clk - , (invert) ? "inverted, " : "" - , bitlen - , start_idx - ); + , clk + , (invert) ? "inverted, " : "" + , bitlen + , start_idx + ); } //output @@ -465,10 +465,10 @@ int ASKDemod_ext(int clk, int invert, int maxErr, size_t maxlen, bool amplify, b if (askType) { PrintAndLogEx(SUCCESS, _YELLOW_("ASK/Manchester") " - clock %d - decoded bitstream", clk); - PrintAndLogEx(INFO,"---------------------------------------------"); + PrintAndLogEx(INFO, "---------------------------------------------"); } else { PrintAndLogEx(SUCCESS, _YELLOW_("ASK/Raw") " - clock %d - decoded bitstream", clk); - PrintAndLogEx(INFO,"--------------------------------------"); + PrintAndLogEx(INFO, "--------------------------------------"); } printDemodBuff(0, false, false, false); @@ -493,18 +493,18 @@ int ASKDemod(int clk, int invert, int maxErr, size_t maxlen, bool amplify, bool static int Cmdaskmandemod(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data rawdemod --am", - "ASK/MANCHESTER demodulate the data in the GraphBuffer and output binary", - "data rawdemod --am --> demod a ask/manchester tag, using autodetect\n" - "data rawdemod --am -c 32 --> demod a ask/manchester tag, using a clock of RF/32\n" - "data rawdemod --am -i --> demod a ask/manchester tag, using autodetect, invert output\n" - "data rawdemod --am -c 32 -i --> demod a ask/manchester tag, using a clock of RF/32, invert output\n" - "data rawdemod --am -c 64 -i --max 0 --> demod a ask/manchester tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" - ); + "ASK/MANCHESTER demodulate the data in the GraphBuffer and output binary", + "data rawdemod --am --> demod a ask/manchester tag, using autodetect\n" + "data rawdemod --am -c 32 --> demod a ask/manchester tag, using a clock of RF/32\n" + "data rawdemod --am -i --> demod a ask/manchester tag, using autodetect, invert output\n" + "data rawdemod --am -c 32 -i --> demod a ask/manchester tag, using a clock of RF/32, invert output\n" + "data rawdemod --am -c 64 -i --max 0 --> demod a ask/manchester tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" + ); void *argtable[] = { arg_param_begin, arg_lit0("a", "amp", "try attempt demod with ask amplification (def no amp)"), arg_int0("c", "clk", "", "set clock manually (def autodetect)"), - arg_lit0("i","inv", "invert output"), + arg_lit0("i", "inv", "invert output"), arg_lit0("s", "st", "check for sequence terminator"), arg_int0(NULL, "max", "", "maximum allowed errors (def 100)"), arg_int0(NULL, "samples", "", "maximum samples to read (def 32768) [512 bits at RF/64]"), @@ -708,18 +708,18 @@ int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) { static int Cmdaskbiphdemod(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data rawdemod --ab", - "ASK/BIPHASE demodulate the data in the GraphBuffer and output binary\n" - "NOTE, `--invert` for Conditional Dephase Encoding (CDP) AKA Differential Manchester\n", - "data rawdemod --ab --> demod a ask/biphase tag, using autodetect\n" - "data rawdemod --ab -c 32 --> demod a ask/biphase tag, using a clock of RF/32\n" - "data rawdemod --ab -i --> demod a ask/biphase tag, using autodetect, invert output\n" - "data rawdemod --ab -c 32 -i --> demod a ask/biphase tag, using a clock of RF/32, invert output\n" - "data rawdemod --ab -c 64 -i --max 0 --> demod a ask/biphase tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" - ); + "ASK/BIPHASE demodulate the data in the GraphBuffer and output binary\n" + "NOTE, `--invert` for Conditional Dephase Encoding (CDP) AKA Differential Manchester\n", + "data rawdemod --ab --> demod a ask/biphase tag, using autodetect\n" + "data rawdemod --ab -c 32 --> demod a ask/biphase tag, using a clock of RF/32\n" + "data rawdemod --ab -i --> demod a ask/biphase tag, using autodetect, invert output\n" + "data rawdemod --ab -c 32 -i --> demod a ask/biphase tag, using a clock of RF/32, invert output\n" + "data rawdemod --ab -c 64 -i --max 0 --> demod a ask/biphase tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" + ); void *argtable[] = { arg_param_begin, arg_int0("c", "clk", "", "set clock manually (def autodetect)"), - arg_lit0("i","inv", "invert output"), + arg_lit0("i", "inv", "invert output"), arg_int0("o", "offset", "", "offset to begin biphase (def 0)"), arg_int0(NULL, "max", "", "maximum allowed errors (def 50)"), arg_param_end @@ -739,18 +739,18 @@ static int Cmdaskbiphdemod(const char *Cmd) { static int Cmdaskrawdemod(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data rawdemod --ar", - "ASK/RAW demodulate the data in the GraphBuffer and output binary", - "data rawdemod --ar -a --> demod a ask tag, using autodetect, amplified\n" - "data rawdemod --ar -c 32 --> demod a ask tag, using a clock of RF/32\n" - "data rawdemod --ar -i --> demod a ask tag, using autodetect, invert output\n" - "data rawdemod --ar -c 32 -i --> demod a ask tag, using a clock of RF/32, invert output\n" - "data rawdemod --ar -c 64 -i --max 0 --> demod a ask tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" - ); + "ASK/RAW demodulate the data in the GraphBuffer and output binary", + "data rawdemod --ar -a --> demod a ask tag, using autodetect, amplified\n" + "data rawdemod --ar -c 32 --> demod a ask tag, using a clock of RF/32\n" + "data rawdemod --ar -i --> demod a ask tag, using autodetect, invert output\n" + "data rawdemod --ar -c 32 -i --> demod a ask tag, using a clock of RF/32, invert output\n" + "data rawdemod --ar -c 64 -i --max 0 --> demod a ask tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" + ); void *argtable[] = { arg_param_begin, arg_lit0("a", "amp", "try attempt demod with ask amplification (def no amp)"), arg_int0("c", "clk", "", "set clock manually (def autodetect)"), - arg_lit0("i","inv", "invert output"), + arg_lit0("i", "inv", "invert output"), arg_lit0("s", "st", "check for sequence terminator"), arg_int0(NULL, "max", "", "maximum allowed errors (def 100)"), arg_int0(NULL, "samples", "", "maximum samples to read (def 32768) [512 bits at RF/64]"), @@ -1179,7 +1179,7 @@ int FSKrawDemod(uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, bo size_t bitlen = getFromGraphBuf(bits); if (bitlen == 0) { - PrintAndLogEx(DEBUG, "DEBUG: no data in graphbuf"); + PrintAndLogEx(DEBUG, "DEBUG: no data in graphbuf"); free(bits); return PM3_ESOFT; } @@ -1211,14 +1211,14 @@ int FSKrawDemod(uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, bo // Now output the bitstream to the scrollback by line of 16 bits if (verbose || g_debugMode) { PrintAndLogEx(DEBUG, "DEBUG: (FSKrawDemod) using clock:%u, %sfc high:%u, fc low:%u" - , rfLen - , (invert) ? "inverted, " : "" - , fchigh - , fclow - ); + , rfLen + , (invert) ? "inverted, " : "" + , fchigh + , fclow + ); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, _YELLOW_("%s") " decoded bitstream", GetFSKType(fchigh, fclow, invert)); - PrintAndLogEx(INFO,"-----------------------"); + PrintAndLogEx(INFO, "-----------------------"); printDemodBuff(0, false, invert, false); } goto out; @@ -1237,19 +1237,19 @@ out: static int CmdFSKrawdemod(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data rawdemod --fs", - "FSK demodulate the data in the GraphBuffer and output binary", - "data rawdemod --fs --> demod an fsk tag, using autodetect\n" - "data rawdemod --fs -c 32 --> demod an fsk tag, using a clock of RF/32, autodetect fc\n" - "data rawdemod --fs -i --> demod an fsk tag, using autodetect, invert output\n" - "data rawdemod --fs -c 32 -i --> demod an fsk tag, using a clock of RF/32, invert output, autodetect fc\n" - "data rawdemod --fs -c 64 --hi 8 --lo 5 --> demod an fsk1 RF/64 tag\n" - "data rawdemod --fs -c 50 --hi 10 --lo 8 --> demod an fsk2 RF/50 tag\n" - "data rawdemod --fs -c 50 -i --hi 10 --lo 8 --> demod an fsk2a RF/50 tag\n" - ); + "FSK demodulate the data in the GraphBuffer and output binary", + "data rawdemod --fs --> demod an fsk tag, using autodetect\n" + "data rawdemod --fs -c 32 --> demod an fsk tag, using a clock of RF/32, autodetect fc\n" + "data rawdemod --fs -i --> demod an fsk tag, using autodetect, invert output\n" + "data rawdemod --fs -c 32 -i --> demod an fsk tag, using a clock of RF/32, invert output, autodetect fc\n" + "data rawdemod --fs -c 64 --hi 8 --lo 5 --> demod an fsk1 RF/64 tag\n" + "data rawdemod --fs -c 50 --hi 10 --lo 8 --> demod an fsk2 RF/50 tag\n" + "data rawdemod --fs -c 50 -i --hi 10 --lo 8 --> demod an fsk2a RF/50 tag\n" + ); void *argtable[] = { arg_param_begin, arg_int0("c", "clk", "", "set clock manually (def: autodetect)"), - arg_lit0("i","inv", "invert output"), + arg_lit0("i", "inv", "invert output"), arg_int0(NULL, "hi", "", "larger field clock length (def: autodetect)"), arg_int0(NULL, "lo", "", "small field clock length (def: autodetect)"), arg_param_end @@ -1318,7 +1318,7 @@ int NRZrawDemod(int clk, int invert, int maxErr, bool verbose) { int errCnt = 0, clkStartIdx = 0; if (getSignalProperties()->isnoise) { - if (verbose) { + if (verbose) { PrintAndLogEx(INFO, "signal looks like noise"); } return PM3_ESOFT; @@ -1369,17 +1369,17 @@ int NRZrawDemod(int clk, int invert, int maxErr, bool verbose) { static int CmdNRZrawDemod(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data rawdemod --nr", - "NRZ/DIRECT demodulate the data in the GraphBuffer and output binary", - "data rawdemod --nr --> demod a nrz/direct tag, using autodetect\n" - "data rawdemod --nr -c 32 --> demod a nrz/direct tag, using a clock of RF/32\n" - "data rawdemod --nr -i --> demod a nrz/direct tag, using autodetect, invert output\n" - "data rawdemod --nr -c 32 -i --> demod a nrz/direct tag, using a clock of RF/32, invert output\n" - "data rawdemod --nr -c 64 -i --max 0 --> demod a nrz/direct tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" - ); + "NRZ/DIRECT demodulate the data in the GraphBuffer and output binary", + "data rawdemod --nr --> demod a nrz/direct tag, using autodetect\n" + "data rawdemod --nr -c 32 --> demod a nrz/direct tag, using a clock of RF/32\n" + "data rawdemod --nr -i --> demod a nrz/direct tag, using autodetect, invert output\n" + "data rawdemod --nr -c 32 -i --> demod a nrz/direct tag, using a clock of RF/32, invert output\n" + "data rawdemod --nr -c 64 -i --max 0 --> demod a nrz/direct tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" + ); void *argtable[] = { arg_param_begin, arg_int0("c", "clk", "", "set clock manually (def autodetect)"), - arg_lit0("i","inv", "invert output"), + arg_lit0("i", "inv", "invert output"), arg_int0(NULL, "max", "", "maximum allowed errors (def 100)"), arg_param_end }; @@ -1399,17 +1399,17 @@ static int CmdNRZrawDemod(const char *Cmd) { int CmdPSK1rawDemod(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data rawdemod --p1", - "PSK1 demodulate the data in the GraphBuffer and output binary", - "data rawdemod --p1 --> demod a psk1 tag, using autodetect\n" - "data rawdemod --p1 -c 32 --> demod a psk1 tag, using a clock of RF/32\n" - "data rawdemod --p1 -i --> demod a psk1 tag, using autodetect, invert output\n" - "data rawdemod --p1 -c 32 -i --> demod a psk1 tag, using a clock of RF/32, invert output\n" - "data rawdemod --p1 -c 64 -i --max 0 --> demod a psk1 tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" - ); + "PSK1 demodulate the data in the GraphBuffer and output binary", + "data rawdemod --p1 --> demod a psk1 tag, using autodetect\n" + "data rawdemod --p1 -c 32 --> demod a psk1 tag, using a clock of RF/32\n" + "data rawdemod --p1 -i --> demod a psk1 tag, using autodetect, invert output\n" + "data rawdemod --p1 -c 32 -i --> demod a psk1 tag, using a clock of RF/32, invert output\n" + "data rawdemod --p1 -c 64 -i --max 0 --> demod a psk1 tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" + ); void *argtable[] = { arg_param_begin, arg_int0("c", "clk", "", "set clock manually (def autodetect)"), - arg_lit0("i","inv", "invert output"), + arg_lit0("i", "inv", "invert output"), arg_int0(NULL, "max", "", "maximum allowed errors (def 100)"), arg_param_end }; @@ -1437,17 +1437,17 @@ int CmdPSK1rawDemod(const char *Cmd) { static int CmdPSK2rawDemod(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data rawdemod --p2", - "PSK2 demodulate the data in the GraphBuffer and output binary", - "data rawdemod --p2 --> demod a psk2 tag, using autodetect\n" - "data rawdemod --p2 -c 32 --> demod a psk2 tag, using a clock of RF/32\n" - "data rawdemod --p2 -i --> demod a psk2 tag, using autodetect, invert output\n" - "data rawdemod --p2 -c 32 -i --> demod a psk2 tag, using a clock of RF/32, invert output\n" - "data rawdemod --p2 -c 64 -i --max 0 --> demod a psk2 tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" - ); + "PSK2 demodulate the data in the GraphBuffer and output binary", + "data rawdemod --p2 --> demod a psk2 tag, using autodetect\n" + "data rawdemod --p2 -c 32 --> demod a psk2 tag, using a clock of RF/32\n" + "data rawdemod --p2 -i --> demod a psk2 tag, using autodetect, invert output\n" + "data rawdemod --p2 -c 32 -i --> demod a psk2 tag, using a clock of RF/32, invert output\n" + "data rawdemod --p2 -c 64 -i --max 0 --> demod a psk2 tag, using a clock of RF/64, inverting and allowing 0 demod errors\n" + ); void *argtable[] = { arg_param_begin, arg_int0("c", "clk", "", "set clock manually (def autodetect)"), - arg_lit0("i","inv", "invert output"), + arg_lit0("i", "inv", "invert output"), arg_int0(NULL, "max", "", "maximum allowed errors (def 100)"), arg_param_end }; @@ -1476,15 +1476,15 @@ static int CmdRawDemod(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "data rawdemod", - "Demodulate the data in the GraphBuffer and output binary", - "data rawdemod --fs --> demod FSK - autodetect\n" - "data rawdemod --ab --> demod ASK/BIPHASE - autodetect\n" - "data rawdemod --am --> demod ASK/MANCHESTER - autodetect\n" - "data rawdemod --ar --> demod ASK/RAW - autodetect\n" - "data rawdemod --nr --> demod NRZ/DIRECT - autodetect\n" - "data rawdemod --p1 --> demod PSK1 - autodetect\n" - "data rawdemod --p2 --> demod PSK2 - autodetect\n" - ); + "Demodulate the data in the GraphBuffer and output binary", + "data rawdemod --fs --> demod FSK - autodetect\n" + "data rawdemod --ab --> demod ASK/BIPHASE - autodetect\n" + "data rawdemod --am --> demod ASK/MANCHESTER - autodetect\n" + "data rawdemod --ar --> demod ASK/RAW - autodetect\n" + "data rawdemod --nr --> demod NRZ/DIRECT - autodetect\n" + "data rawdemod --p1 --> demod PSK1 - autodetect\n" + "data rawdemod --p2 --> demod PSK2 - autodetect\n" + ); void *argtable[] = { arg_param_begin, arg_lit0(NULL, "ab", "ASK/Biphase demodulation"), @@ -1515,18 +1515,18 @@ static int CmdRawDemod(const char *Cmd) { CLIParserFree(ctx); int foo = (ab + am + ar + fs + nr + p1 + p2); - if ( foo > 1 ) { + if (foo > 1) { PrintAndLogEx(WARNING, "please, select only one modulation"); return PM3_EINVARG; } - if ( foo == 0 ) { + if (foo == 0) { PrintAndLogEx(WARNING, "please, select a modulation"); return PM3_EINVARG; } int ans = 0; const char *s = Cmd + n; - if (fs) + if (fs) ans = CmdFSKrawdemod(s); else if (ab) ans = Cmdaskbiphdemod(s); diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 5108cde5e..d6888cf80 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -114,7 +114,7 @@ static inline uint32_t leadingzeros(uint64_t a) { } static void iclass_upload_emul(uint8_t *d, uint32_t n, uint32_t *bytes_sent) { - // fast push mode + // fast push mode conn.block_after_ACK = true; //Send to device @@ -265,7 +265,7 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke HFiClassCalcDivKey(iclass_last_known_card.csn, iClass_Key_Table[0], iclass_last_known_card.key_d, false); memset(data, 0x00, tot_bytes); - memcpy(data, (uint8_t*)&iclass_last_known_card, sizeof(picopass_hdr_t)); + memcpy(data, (uint8_t *)&iclass_last_known_card, sizeof(picopass_hdr_t)); // Keyrolling configuration cards are special. if (strstr(o->desc, "Keyroll") != NULL) { diff --git a/client/src/cmdhflist.c b/client/src/cmdhflist.c index be2dfa4eb..279d75ecb 100644 --- a/client/src/cmdhflist.c +++ b/client/src/cmdhflist.c @@ -777,7 +777,7 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { for (uint8_t i = 0; i < 2; i++, pos++) { bool found_annotation = true; - + switch (cmd[pos]) { case MFDES_CREATE_APPLICATION: snprintf(exp, size, "CREATE APPLICATION"); @@ -897,7 +897,7 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { found_annotation = false; break; } - + if (found_annotation) { break; } diff --git a/client/src/cmdlfpac.c b/client/src/cmdlfpac.c index f9d6b098c..65a3c04a9 100644 --- a/client/src/cmdlfpac.c +++ b/client/src/cmdlfpac.c @@ -403,7 +403,7 @@ int CmdLFPac(const char *Cmd) { // find PAC preamble in already demoded data int detectPac(uint8_t *dest, size_t *size, bool *invert) { // make sure buffer has data - if (*size < 128) + if (*size < 128) return -1; size_t startIdx = 0; @@ -422,7 +422,7 @@ int detectPac(uint8_t *dest, size_t *size, bool *invert) { // wrong demoded size if (*size != 128) return -3; - + // return start position return (int)startIdx; } From 79bf006419f9edf34c4e387d391760483aa90ec4 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 18 Apr 2021 18:52:48 +0200 Subject: [PATCH 345/373] Makefile: remove ROOT_DIR --- client/Makefile | 6 ++---- tools/fpga_compress/Makefile | 2 -- tools/hitag2crack/Makefile | 3 --- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/client/Makefile b/client/Makefile index ab26f970e..f120efaf3 100644 --- a/client/Makefile +++ b/client/Makefile @@ -4,9 +4,6 @@ # the license. #----------------------------------------------------------------------------- -# Must be called before any Makefile include -ROOT_DIR:=$(dir $(realpath $(lastword $(MAKEFILE_LIST)))) - include ../Makefile.defs INSTALLBIN = proxmark3 @@ -91,6 +88,7 @@ WHEREAMILIBLD = MBEDTLSLIBPATH = ../common/mbedtls MBEDTLSLIBINC = -I$(MBEDTLSLIBPATH) MBEDTLSLIB = $(OBJDIR)/libmbedtls.a +MBEDTLSLIBCLIENTRELPATH = ../../client ######################################################## # optional system libraries to replace local libraries # @@ -737,7 +735,7 @@ endif $(MBEDTLSLIB): .FORCE $(info [*] MAKE $@) - $(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) OBJDIR=$(ROOT_DIR)$(OBJDIR) BINDIR=$(ROOT_DIR)$(OBJDIR) all + $(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) OBJDIR=$(MBEDTLSLIBCLIENTRELPATH)/$(OBJDIR) BINDIR=$(MBEDTLSLIBCLIENTRELPATH)/$(OBJDIR) all $(REVENGLIB): .FORCE $(info [*] MAKE $@) diff --git a/tools/fpga_compress/Makefile b/tools/fpga_compress/Makefile index 4a97776b2..fb2f9d23d 100644 --- a/tools/fpga_compress/Makefile +++ b/tools/fpga_compress/Makefile @@ -12,8 +12,6 @@ MYCFLAGS += -DLZ4_MEMORY_USAGE=20 -Wno-redundant-decls -Wno-old-style-definitio BINS = fpga_compress -ROOT_DIR:=$(dir $(realpath $(lastword $(MAKEFILE_LIST)))) - include ../../Makefile.host fpga_compress: $(OBJDIR)/fpga_compress.o $(MYOBJS) diff --git a/tools/hitag2crack/Makefile b/tools/hitag2crack/Makefile index c3e5cebc1..26f538110 100644 --- a/tools/hitag2crack/Makefile +++ b/tools/hitag2crack/Makefile @@ -1,6 +1,3 @@ -# Must be called before any Makefile include -ROOT_DIR:=$(dir $(realpath $(lastword $(MAKEFILE_LIST)))) - include ../../Makefile.defs all clean install uninstall check: %: crack2/% crack3/% crack4/% crack5/% From 69616114741e9f94d672b9cf0b40d4536046428c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 18 Apr 2021 19:57:50 +0200 Subject: [PATCH 346/373] unified text and loading file now follow new pattern --- client/src/cmdlfem4x05.c | 11 +++--- client/src/cmdlfem4x50.c | 82 +++++++++++++++++++++++++--------------- client/src/cmdlfhid.c | 3 +- client/src/cmdlft55xx.c | 8 ++-- 4 files changed, 61 insertions(+), 43 deletions(-) diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index 917dd21e3..5d0fdb0bf 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -557,12 +557,12 @@ int CmdEM4x05Dump(const char *Cmd) { // Test first if the password is correct status = em4x05_login_ext(pwd); if (status == PM3_SUCCESS) { - PrintAndLogEx(INFO, "Password is " _GREEN_("correct")); + PrintAndLogEx(INFO, "password is " _GREEN_("correct")); } else if (status == PM3_EFAILED) { - PrintAndLogEx(WARNING, "Password is " _RED_("incorrect") ", will try without password"); + PrintAndLogEx(WARNING, "password is " _RED_("incorrect") ", will try without password"); usePwd = false; } else if (status != PM3_EFAILED) { - PrintAndLogEx(WARNING, "Login attempt: No answer from tag"); + PrintAndLogEx(WARNING, "Login attempt: no answer from tag"); return status; } } @@ -705,7 +705,6 @@ int CmdEM4x05Dump(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); saveFileJSON(filename, (card_type == EM_4369 || card_type == EM_4469) ? jsfEM4x69 : jsfEM4x05, (uint8_t *)data, 16 * sizeof(uint32_t), NULL); - saveFileEML(filename, (uint8_t *)data, 16 * sizeof(uint32_t), sizeof(uint32_t)); saveFile(filename, ".bin", data, sizeof(data)); } @@ -1376,7 +1375,7 @@ int CmdEM4x05Chk(const char *Cmd) { return PM3_ESOFT; } - PrintAndLogEx(INFO, "press " _YELLOW_("'enter'") " to cancel the command"); + PrintAndLogEx(INFO, "press " _GREEN_("") " to exit"); for (uint32_t c = 0; c < keycount; ++c) { @@ -1626,7 +1625,7 @@ int CmdEM4x05Unlock(const char *Cmd) { PrintAndLogEx(INFO, "----------------------------------------------------------------------------\n"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "press " _YELLOW_("'enter'") " to cancel the command"); + PrintAndLogEx(INFO, "press " _GREEN_("'") " to exit"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--------------- " _CYAN_("start") " -----------------------\n"); diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index 0b188ec24..36a5c2b28 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -130,29 +130,51 @@ static void print_info_result(uint8_t *data, bool verbose) { static int em4x50_load_file(const char *filename, uint8_t *data, size_t data_len, size_t *bytes_read) { - // read data from dump file; file type is derived from file name extension + uint8_t *dump = calloc(DUMP_FILESIZE, sizeof(uint8_t)); + if (dump == NULL) { + PrintAndLogEx(ERR, "error, cannot allocate memory "); + return PM3_EMALLOC; + } - int res = 0; - uint32_t serial = 0x0, device_id = 0x0; + int res = PM3_SUCCESS; + DumpFileType_t dftype = getfiletype(filename); + switch (dftype) { + case BIN: { + res = loadFile_safe(filename, ".bin", (void **)&dump, bytes_read); + break; + } + case EML: { + res = loadFileEML_safe(filename, (void **)&dump, bytes_read); + break; + } + case JSON: { + res = loadFileJSON(filename, dump, DUMP_FILESIZE, bytes_read, NULL); + break; + } + case DICTIONARY: { + free(dump); + PrintAndLogEx(ERR, "Error: Only BIN/JSON/EML formats allowed"); + return PM3_EINVARG; + } + } - if (str_endswith(filename, ".eml")) - res = loadFileEML(filename, data, bytes_read) != PM3_SUCCESS; - else if (str_endswith(filename, ".json")) - res = loadFileJSON(filename, data, data_len, bytes_read, NULL); - else - res = loadFile(filename, ".bin", data, data_len, bytes_read); - - if ((res != PM3_SUCCESS) && (*bytes_read != DUMP_FILESIZE)) + if ((res != PM3_SUCCESS) && (*bytes_read != DUMP_FILESIZE)) { + free(dump); return PM3_EFILE; + } + + uint32_t serial = 0, device_id = 0; // valid em4x50 data? serial = bytes_to_num(data + 4 * EM4X50_DEVICE_SERIAL, 4); device_id = bytes_to_num(data + 4 * EM4X50_DEVICE_ID, 4); if (serial == device_id) { - PrintAndLogEx(WARNING, "No valid em4x50 data in file %s.", filename); + PrintAndLogEx(WARNING, "No valid EM4x50 data in file %s", filename); return PM3_ENODATA; } + memcpy(data, dump, *bytes_read); + free(dump); return PM3_SUCCESS; } @@ -183,7 +205,7 @@ int CmdEM4x50ELoad(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str1("f", "filename", "", "dump filename"), + arg_str1("f", "filename", "", "dump filename"), arg_param_end }; @@ -426,7 +448,7 @@ int CmdEM4x50Chk(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "filename", "", "dictionary filename"), + arg_str0("f", "filename", "", "dictionary filename"), arg_param_end }; @@ -734,7 +756,7 @@ int CmdEM4x50Dump(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_str0("f", "filename", "", "dump filename (bin/eml/json)"), + arg_str0("f", "filename", "", "dump filename (bin/eml/json)"), arg_str0("p", "pwd", "", "password, 4 hex bytes, lsb"), arg_param_end }; @@ -1034,7 +1056,7 @@ int CmdEM4x50Wipe(const char *Cmd) { int CmdEM4x50Restore(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf em 4x50 restore", - "Restores data from dumpfile onto a Em4x50 tag.\n" + "Restores data from dumpfile (bin/eml/json) onto a EM4x50 tag.\n" "if used with -u, the filetemplate `lf-4x50-UID-dump.bin` is used as filename", "lf em 4x50 restore -u 1b5aff5c -> uses lf-4x50-1B5AFF5C-dump.bin\n" "lf em 4x50 restore -f mydump.eml\n" @@ -1045,7 +1067,7 @@ int CmdEM4x50Restore(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0("u", "uid", "", "uid, 4 hex bytes, msb"), - arg_str0("f", "filename", "", "dump filename (bin/eml/json)"), + arg_str0("f", "filename", "", "dump filename (bin/eml/json)"), arg_str0("p", "pwd", "", "password, 4 hex bytes, lsb"), arg_param_end }; @@ -1128,14 +1150,10 @@ int CmdEM4x50Restore(const char *Cmd) { } int CmdEM4x50Sim(const char *Cmd) { - - int status = PM3_EFAILED; - uint32_t password = 0; - CLIParserContext *ctx; CLIParserInit(&ctx, "lf em 4x50 sim", - "Simulates a EM4x50 tag.\n" - "Upload using `lf em 4x50 eload`", + "Simulates a EM4x50 tag\n" + "First upload to device using `lf em 4x50 eload`", "lf em 4x50 sim" "lf em 4x50 sim -p 27182818 -> uses password for eload data" ); @@ -1152,25 +1170,26 @@ int CmdEM4x50Sim(const char *Cmd) { CLIGetHexWithReturn(ctx, 1, pwd, &pwd_len); CLIParserFree(ctx); + uint32_t password = 0; if (pwd_len) { if (pwd_len != 4) { - PrintAndLogEx(FAILED, "password length must be 4 bytes instead of %d", pwd_len); + PrintAndLogEx(FAILED, "password length must be 4 bytes, got %d", pwd_len); return PM3_EINVARG; } else { password = BYTES2UINT32(pwd); } } - CLIParserFree(ctx); + int status = PM3_EFAILED; PrintAndLogEx(INFO, "Simulating data from emulator memory"); clearCommandBuffer(); SendCommandNG(CMD_LF_EM4X50_SIM, (uint8_t *)&password, sizeof(password)); PacketResponseNG resp; - PrintAndLogEx(INFO, "Press pm3-button to abort simulation"); - bool keypress = kbd_enter_pressed(); - while (keypress == false) { + PrintAndLogEx(INFO, "Press " _GREEN_("") " or pm3-button to abort simulation"); + bool keypress; + do { keypress = kbd_enter_pressed(); if (WaitForResponseTimeout(CMD_LF_EM4X50_SIM, &resp, 1500)) { @@ -1178,16 +1197,17 @@ int CmdEM4x50Sim(const char *Cmd) { break; } - } + } while (keypress == false); + if (keypress) { SendCommandNG(CMD_BREAK_LOOP, NULL, 0); status = PM3_EOPABORTED; } if ((status == PM3_SUCCESS) || (status == PM3_EOPABORTED)) - PrintAndLogEx(INFO, "Done"); + PrintAndLogEx(INFO, "Done!"); else - PrintAndLogEx(FAILED, "No valid em4x50 data in memory"); + PrintAndLogEx(FAILED, "No valid EM4x50 data in memory"); return resp.status; } diff --git a/client/src/cmdlfhid.c b/client/src/cmdlfhid.c index ff3a27fd9..882be2da5 100644 --- a/client/src/cmdlfhid.c +++ b/client/src/cmdlfhid.c @@ -545,8 +545,7 @@ static int CmdHIDBrute(const char *Cmd) { } } PrintAndLogEx(INFO, "Started brute-forcing HID Prox reader"); - PrintAndLogEx(INFO, "Press pm3-button to abort simulation or press " _GREEN_("``") " to exit"); - + PrintAndLogEx(INFO, "Press " _GREEN_("") " or pm3-button to abort simulation"); // copy values to low. cn_low = cn_hi; diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 541bcf379..22847fcf5 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -3086,7 +3086,7 @@ static int CmdT55xxChkPwds(const char *Cmd) { snprintf(filename, sizeof(filename), "t55xx_default_pwds"); } - PrintAndLogEx(INFO, "press " _GREEN_("'enter'") " to cancel the command"); + PrintAndLogEx(INFO, "press " _GREEN_("") " to exit"); PrintAndLogEx(NORMAL, ""); /* // block 7, page1 = false, usepwd = false, override = false, pwd = 00000000 @@ -3182,7 +3182,7 @@ static int CmdT55xxChkPwds(const char *Cmd) { return PM3_ESOFT; } - PrintAndLogEx(INFO, "press " _GREEN_("'enter'") " to cancel the command"); + PrintAndLogEx(INFO, "press " _GREEN_("") " to exit"); for (uint32_t c = 0; c < keycount && found == false; ++c) { @@ -3296,7 +3296,7 @@ static int CmdT55xxBruteForce(const char *Cmd) { return PM3_EINVARG; } - PrintAndLogEx(INFO, "press " _GREEN_("'enter'") " to cancel the command"); + PrintAndLogEx(INFO, "press " _GREEN_("") " to exit"); PrintAndLogEx(INFO, "Search password range [%08X -> %08X]", start_password, end_password); uint64_t t1 = msclock(); @@ -3404,7 +3404,7 @@ static int CmdT55xxRecoverPW(const char *Cmd) { else if (r3) downlink_mode = ref1of4; - PrintAndLogEx(NORMAL, "press " _GREEN_("'enter'") " to cancel the command"); + PrintAndLogEx(INFO, "press " _GREEN_("") " to exit"); int bit = 0; uint32_t curr_password = 0x0; From e7df423e0f177c3f2a9796136cfc366ad3cf96fc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 18 Apr 2021 20:03:23 +0200 Subject: [PATCH 347/373] text --- client/src/cmdlfem4x05.c | 2 +- client/src/cmdlfem4x50.c | 22 +++++++++------------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index 5d0fdb0bf..99ce8a9bf 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -504,7 +504,7 @@ int CmdEM4x05Dump(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0("p", "pwd", "", "password (00000000)"), - arg_str0("f", "file", "", "override filename prefix (optional). Default is based on UID"), + arg_str0("f", "file", "", "override filename prefix (optional). Default is based on UID"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index 36a5c2b28..492cbac77 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -197,15 +197,13 @@ static void em4x50_seteml(uint8_t *src, uint32_t offset, uint32_t numofbytes) { int CmdEM4x50ELoad(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf em 4x50 eload", - "Loads EM4x50 tag dump into emulator memory on device.", + "Loads EM4x50 tag dump (bin/eml/json) into emulator memory on device", "lf em 4x50 eload -f mydump.bin\n" - "lf em 4x50 eload -f mydump.eml\n" - "lf em 4x50 eload -f mydump.json" ); void *argtable[] = { arg_param_begin, - arg_str1("f", "filename", "", "dump filename"), + arg_str1("f", "filename", "", "dump filename (bin/eml/json)"), arg_param_end }; @@ -225,10 +223,10 @@ int CmdEM4x50ELoad(const char *Cmd) { } // upload to emulator memory - PrintAndLogEx(INFO, "Uploading dump " _YELLOW_("%s") " to emulator memory", filename); + PrintAndLogEx(INFO, "Uploading to emulator memory contents of " _YELLOW_("%s"), filename); em4x50_seteml(data, 0, DUMP_FILESIZE); - PrintAndLogEx(INFO, "Done"); + PrintAndLogEx(INFO, "Done!"); return PM3_SUCCESS; } @@ -237,14 +235,12 @@ int CmdEM4x50ESave(const char *Cmd) { CLIParserInit(&ctx, "lf em 4x50 esave", "Saves bin/eml/json dump file of emulator memory.", "lf em 4x50 esave -> use UID as filename\n" - "lf em 4x50 esave -f mydump.bin\n" - "lf em 4x50 esave -f mydump.eml\n" - "lf em 4x50 esave -f mydump.json\n" + "lf em 4x50 esave -f mydump\n" ); void *argtable[] = { arg_param_begin, - arg_str0("f", "filename", "", "data filename"), + arg_str0("f", "filename", "", "data filename"), arg_param_end }; @@ -747,11 +743,11 @@ int CmdEM4x50Reader(const char *Cmd) { int CmdEM4x50Dump(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf em 4x50 dump", - "Reads all blocks/words from EM4x50 tag and saves dump in bin/eml/json format.", + "Reads all blocks/words from EM4x50 tag and saves dump in bin/eml/json format", "lf em 4x50 dump\n" - "lf em 4x50 dump -f mydump.eml\n" + "lf em 4x50 dump -f mydump\n" "lf em 4x50 dump -p 12345678\n" - "lf em 4x50 dump -f mydump.eml -p 12345678" + "lf em 4x50 dump -f mydump -p 12345678" ); void *argtable[] = { From f76528eba4163674b644d90446a11b0e9a7d4fa9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 18 Apr 2021 20:19:49 +0200 Subject: [PATCH 348/373] fix coverity CID 319477 --- client/src/cmdlfem4x50.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index 492cbac77..d25148b0b 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -170,6 +170,7 @@ static int em4x50_load_file(const char *filename, uint8_t *data, size_t data_len device_id = bytes_to_num(data + 4 * EM4X50_DEVICE_ID, 4); if (serial == device_id) { PrintAndLogEx(WARNING, "No valid EM4x50 data in file %s", filename); + free(dump); return PM3_ENODATA; } From 68e870527801a653191ee2ee57f1bb898389c7cb Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 18 Apr 2021 23:23:48 +0200 Subject: [PATCH 349/373] Add option -c to lf search to continue searching after first hit --- CHANGELOG.md | 1 + client/src/cmdlf.c | 291 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 251 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b94013db..e7a2dd375 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Change `lf search` - add option `-c` to continue searching after first hit (@doegox) - Fix DESFire mis-annotation (@VortixDev) - Change `lf pac demod` - now also search for inverted bitstreams (@iceman1001) - Change `hf 14b reader` - now supports continous mode (@iceman1001) diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index c1875a78a..ed1bf0bba 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -1343,14 +1343,16 @@ int CmdLFfind(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_lit0("1", NULL, "Use data from Graphbuffer to search"), - arg_lit0("u", NULL, "Search for unknown tags, if not set, reads only known tags"), + arg_lit0("c", NULL, "Continue searching even after a first hit"), + arg_lit0("u", NULL, "Search for unknown tags. If not set, reads only known tags"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); bool use_gb = arg_get_lit(ctx, 1); - bool search_unk = arg_get_lit(ctx, 2); + bool search_cont = arg_get_lit(ctx, 2); + bool search_unk = arg_get_lit(ctx, 3); CLIParserFree(ctx); - + int found = 0; bool is_online = (session.pm3_present && (use_gb == false)); if (is_online) lf_read(false, 30000); @@ -1367,6 +1369,10 @@ int CmdLFfind(const char *Cmd) { PrintAndLogEx(INFO, "False Positives " _YELLOW_("ARE") " possible"); PrintAndLogEx(INFO, ""); PrintAndLogEx(INFO, "Checking for known tags..."); + if (search_cont) + PrintAndLogEx(INFO, "We'll go over all possible demods"); + else + PrintAndLogEx(INFO, "We'll stop at first hit"); PrintAndLogEx(INFO, ""); // only run these tests if device is online @@ -1375,14 +1381,22 @@ int CmdLFfind(const char *Cmd) { if (IfPm3Hitag()) { if (readHitagUid()) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Hitag") " found!"); - return PM3_SUCCESS; + if (search_cont) { + found++; + } else { + return PM3_SUCCESS; + } } } if (IfPm3EM4x50()) { if (read_em4x50_uid() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM4x50 ID") " found!"); - return PM3_SUCCESS; + if (search_cont) { + found++; + } else { + return PM3_SUCCESS; + } } } @@ -1393,61 +1407,241 @@ int CmdLFfind(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for MOTOROLA tag..."); if (readMotorolaUid()) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Motorola FlexPass ID") " found!"); - return PM3_SUCCESS; + if (search_cont) { + found++; + } else { + return PM3_SUCCESS; + } } PrintAndLogEx(INPLACE, "Searching for COTAG tag..."); if (readCOTAGUid()) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("COTAG ID") " found!"); - return PM3_SUCCESS; + if (search_cont) { + found++; + } else { + return PM3_SUCCESS; + } } PrintAndLogEx(NORMAL, ""); PrintAndLogEx(FAILED, _RED_("No data found!")); PrintAndLogEx(INFO, "Signal looks like noise. Maybe not an LF tag?"); PrintAndLogEx(NORMAL, ""); - return PM3_ESOFT; + if (! search_cont) { + return PM3_ESOFT; + } } } int retval = PM3_SUCCESS; // ask / man - if (demodEM410x(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM410x ID") " found!"); goto out;} - if (demodDestron(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-A FECAVA Destron ID") " found!"); goto out;} // to do before HID - if (demodGallagher(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("GALLAGHER ID") " found!"); goto out;} - if (demodNoralsy(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Noralsy ID") " found!"); goto out;} - if (demodPresco(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Presco ID") " found!"); goto out;} - if (demodSecurakey(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Securakey ID") " found!"); goto out;} - if (demodViking(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Viking ID") " found!"); goto out;} - if (demodVisa2k(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Visa2000 ID") " found!"); goto out;} + if (demodEM410x(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM410x ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodDestron(true) == PM3_SUCCESS) { // to do before HID + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-A FECAVA Destron ID") " found!"); if (! search_cont) goto out; + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodGallagher(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("GALLAGHER ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodNoralsy(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Noralsy ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodPresco(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Presco ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodSecurakey(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Securakey ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodViking(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Viking ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodVisa2k(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Visa2000 ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } // ask / bi - if (demodFDXB(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-B ID") " found!"); goto out;} - if (demodJablotron(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Jablotron ID") " found!"); goto out;} - if (demodGuard(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Guardall G-Prox II ID") " found!"); goto out; } - if (demodNedap(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NEDAP ID") " found!"); goto out;} + if (demodFDXB(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-B ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodJablotron(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Jablotron ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodGuard(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Guardall G-Prox II ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodNedap(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NEDAP ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } // nrz - if (demodPac(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("PAC/Stanley ID") " found!"); goto out;} + if (demodPac(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("PAC/Stanley ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } // fsk - if (demodHID(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("HID Prox ID") " found!"); goto out;} - if (demodAWID(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("AWID ID") " found!"); goto out;} - if (demodIOProx(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("IO Prox ID") " found!"); goto out;} - if (demodPyramid(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Pyramid ID") " found!"); goto out;} - if (demodParadox(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!"); goto out;} + if (demodHID(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("HID Prox ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodAWID(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("AWID ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodIOProx(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("IO Prox ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodPyramid(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Pyramid ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodParadox(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } // psk - if (demodIdteck(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!"); goto out;} - if (demodKeri(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("KERI ID") " found!"); goto out;} - if (demodNexWatch(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NexWatch ID") " found!"); goto out;} - if (demodIndala(true) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Indala ID") " found!"); goto out;} - -// if (demodTI() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Texas Instrument ID") " found!"); goto out;} -// if (demodFermax() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Fermax ID") " found!"); goto out;} - - PrintAndLogEx(FAILED, _RED_("No known 125/134 kHz tags found!")); + if (demodIdteck(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodKeri(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("KERI ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodNexWatch(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NexWatch ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodIndala(true) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Indala ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } +/* + if (demodTI() == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Texas Instrument ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } + if (demodFermax() == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Fermax ID") " found!"); + if (search_cont) { + found++; + } else { + goto out; + } + } +*/ + if (found == 0) { + PrintAndLogEx(FAILED, _RED_("No known 125/134 kHz tags found!")); + } if (search_unk) { //test unknown tag formats (raw mode) @@ -1465,7 +1659,11 @@ int CmdLFfind(const char *Cmd) { if (GetFskClock("", false)) { if (FSKrawDemod(0, 0, 0, 0, true) == PM3_SUCCESS) { PrintAndLogEx(INFO, "Unknown FSK Modulated Tag found!"); - goto out; + if (search_cont) { + found++; + } else { + goto out; + } } } @@ -1473,7 +1671,11 @@ int CmdLFfind(const char *Cmd) { if (ASKDemod_ext(0, 0, 0, 0, false, true, false, 1, &st) == PM3_SUCCESS) { PrintAndLogEx(INFO, "Unknown ASK Modulated and Manchester encoded Tag found!"); PrintAndLogEx(INFO, "if it does not look right it could instead be ASK/Biphase - try " _YELLOW_("'data rawdemod --ab'")); - goto out; + if (search_cont) { + found++; + } else { + goto out; + } } if (CmdPSK1rawDemod("") == PM3_SUCCESS) { @@ -1481,19 +1683,26 @@ int CmdLFfind(const char *Cmd) { PrintAndLogEx(INFO, " Could also be PSK2 - try " _YELLOW_("'data rawdemod --p2'")); PrintAndLogEx(INFO, " Could also be PSK3 - [currently not supported]"); PrintAndLogEx(INFO, " Could also be NRZ - try " _YELLOW_("'data rawdemod --nr")); - goto out; + if (search_cont) { + found++; + } else { + goto out; + } } - PrintAndLogEx(FAILED, _RED_("No data found!")); + if (found == 0) { + PrintAndLogEx(FAILED, _RED_("No data found!")); + } } - retval = PM3_ESOFT; + if (found == 0) { + retval = PM3_ESOFT; + } out: // identify chipset if (CheckChipType(is_online) == false) { PrintAndLogEx(DEBUG, "Automatic chip type detection " _RED_("failed")); - retval = false; } return retval; } From 7e6806444634b520451935df308b02e56b6c6f07 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 19 Apr 2021 00:33:59 +0200 Subject: [PATCH 350/373] Allow to see help offline --- client/src/cmdparser.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/client/src/cmdparser.c b/client/src/cmdparser.c index 279f87664..653aaba55 100644 --- a/client/src/cmdparser.c +++ b/client/src/cmdparser.c @@ -240,10 +240,16 @@ int CmdsParse(const command_t Commands[], const char *Cmd) { if (cmd_name[0] == '#') return PM3_SUCCESS; + // find args, check for -h / --help + int tmplen = len; + while (Cmd[tmplen] == ' ') + ++tmplen; + bool request_help = (strcmp(Cmd+tmplen, "-h") == 0) || (strcmp(Cmd+tmplen, "--help") == 0); + int i = 0; while (Commands[i].Name) { if (0 == strcmp(Commands[i].Name, cmd_name)) { - if (Commands[i].IsAvailable()) { + if (request_help || Commands[i].IsAvailable()) { break; } else { PrintAndLogEx(WARNING, "This command is " _YELLOW_("not available") " in this mode"); From e2cc02af49ba9ebf79b96df0cce007b463147d79 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 19 Apr 2021 01:16:39 +0200 Subject: [PATCH 351/373] Allow to see help from all categories --- client/src/cmdlfem4x50.c | 2 +- client/src/cmdparser.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index d25148b0b..46230bafd 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -1195,7 +1195,7 @@ int CmdEM4x50Sim(const char *Cmd) { } } while (keypress == false); - + if (keypress) { SendCommandNG(CMD_BREAK_LOOP, NULL, 0); status = PM3_EOPABORTED; diff --git a/client/src/cmdparser.c b/client/src/cmdparser.c index 653aaba55..23ca61ba5 100644 --- a/client/src/cmdparser.c +++ b/client/src/cmdparser.c @@ -244,12 +244,14 @@ int CmdsParse(const command_t Commands[], const char *Cmd) { int tmplen = len; while (Cmd[tmplen] == ' ') ++tmplen; - bool request_help = (strcmp(Cmd+tmplen, "-h") == 0) || (strcmp(Cmd+tmplen, "--help") == 0); + bool request_help = (strcmp(Cmd + tmplen, "-h") == 0) || (strcmp(Cmd + tmplen, "--help") == 0); int i = 0; while (Commands[i].Name) { if (0 == strcmp(Commands[i].Name, cmd_name)) { - if (request_help || Commands[i].IsAvailable()) { + if ((Commands[i].Help[0] == '{') || // always allow parsing categories + request_help || // always allow requesting help + Commands[i].IsAvailable()) { break; } else { PrintAndLogEx(WARNING, "This command is " _YELLOW_("not available") " in this mode"); From d2246e66069ed28ac7f3e4efc569c69cf9d0f27a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 19 Apr 2021 01:18:12 +0200 Subject: [PATCH 352/373] remove leftover --- client/src/cmdlf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index ed1bf0bba..a20bbf758 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -1446,7 +1446,7 @@ int CmdLFfind(const char *Cmd) { } } if (demodDestron(true) == PM3_SUCCESS) { // to do before HID - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-A FECAVA Destron ID") " found!"); if (! search_cont) goto out; + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-A FECAVA Destron ID") " found!"); if (search_cont) { found++; } else { @@ -1621,7 +1621,7 @@ int CmdLFfind(const char *Cmd) { goto out; } } -/* + /* if (demodTI() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Texas Instrument ID") " found!"); if (search_cont) { @@ -1638,7 +1638,7 @@ int CmdLFfind(const char *Cmd) { goto out; } } -*/ + */ if (found == 0) { PrintAndLogEx(FAILED, _RED_("No known 125/134 kHz tags found!")); } From 11c7ead732dd9ec84964a190aa2380f0c6227c99 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 19 Apr 2021 01:43:26 +0200 Subject: [PATCH 353/373] Add -h/--help support to last commands --- client/src/cmdlft55xx.c | 12 +++++++++++- client/src/cmdmain.c | 12 +++++++++++- client/src/cmdscript.c | 26 ++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 22847fcf5..1b98cc47d 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -96,7 +96,17 @@ static void arg_add_t55xx_downloadlink(void *at[], uint8_t *idx, uint8_t show, u } static int CmdT55xxCloneHelp(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf t55xx clonehelp", + "Display a list of available commands for cloning specific techs on T5xx tags", + "lf t55xx clonehelp" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); 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")); diff --git a/client/src/cmdmain.c b/client/src/cmdmain.c index 94365e6d5..5c4152604 100644 --- a/client/src/cmdmain.c +++ b/client/src/cmdmain.c @@ -263,7 +263,17 @@ static int CmdMsleep(const char *Cmd) { } static int CmdQuit(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + CLIParserContext *ctx; + CLIParserInit(&ctx, "quit", + "Quit the Proxmark3 client terminal", + "quit" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); return PM3_EFATAL; } diff --git a/client/src/cmdscript.c b/client/src/cmdscript.c index 7c44c8978..cb378c75b 100644 --- a/client/src/cmdscript.c +++ b/client/src/cmdscript.c @@ -30,6 +30,7 @@ #include "proxmark3.h" #include "ui.h" #include "fileutils.h" +#include "cliparser.h" // cliparsing #ifdef HAVE_LUA_SWIG extern int luaopen_pm3(lua_State *L); @@ -198,7 +199,17 @@ static void set_python_paths(void) { * ending with .lua */ static int CmdScriptList(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + CLIParserContext *ctx; + CLIParserInit(&ctx, "script list", + "List available Lua, Cmd and Python scripts", + "script list" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); PrintAndLogEx(NORMAL, "\n" _YELLOW_("[ Lua scripts ]")); int ret = searchAndList(LUA_SCRIPTS_SUBDIR, ".lua"); if (ret != PM3_SUCCESS) @@ -223,7 +234,18 @@ static int CmdScriptList(const char *Cmd) { * @return */ static int CmdScriptRun(const char *Cmd) { - + CLIParserContext *ctx; + CLIParserInit(&ctx, "script run", + "Run a Lua, Cmd or Python script", + "script run my_script.lua --my_script_args" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + // TODO possible to handle it with cliparser? char preferredName[128] = {0}; char arguments[256] = {0}; From 74d121a727ebcfe058acf7e31dcc4df5babe72d6 Mon Sep 17 00:00:00 2001 From: tcprst Date: Sun, 18 Apr 2021 20:12:28 -0400 Subject: [PATCH 354/373] Fix Makefile for QT5 on macOS --- client/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/client/Makefile b/client/Makefile index f120efaf3..a4546cf86 100644 --- a/client/Makefile +++ b/client/Makefile @@ -15,6 +15,7 @@ OBJDIR = obj ifeq ($(platform),Darwin) PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/opt/qt/lib/pkgconfig + PKG_CONFIG_ENV := PKG_CONFIG_PATH=$(BREW_PREFIX)/opt/qt5/lib/pkgconfig endif ################### From 008a0b5ab48f818b4253052a7f9b75a80cd58f08 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 19 Apr 2021 02:54:16 +0200 Subject: [PATCH 355/373] First attempt at dumping all help: proxmark3 --fulltext --- client/src/cmdparser.c | 38 ++++++++++++++++++++++++++++++-------- client/src/cmdparser.h | 2 +- client/src/proxmark3.c | 23 ++++++++++++++++------- 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/client/src/cmdparser.c b/client/src/cmdparser.c index 23ca61ba5..1f5476b48 100644 --- a/client/src/cmdparser.c +++ b/client/src/cmdparser.c @@ -195,12 +195,22 @@ void CmdsHelp(const command_t Commands[]) { int CmdsParse(const command_t Commands[], const char *Cmd) { // Help dump children if (strcmp(Cmd, "XX_internal_command_dump_XX") == 0) { - dumpCommandsRecursive(Commands, 0); + dumpCommandsRecursive(Commands, 0, false); + return PM3_SUCCESS; + } + // Help dump children with help + if (strcmp(Cmd, "XX_internal_command_dump_full_XX") == 0) { + dumpCommandsRecursive(Commands, 0, true); return PM3_SUCCESS; } // Markdown help dump children if (strcmp(Cmd, "XX_internal_command_dump_markdown_XX") == 0) { - dumpCommandsRecursive(Commands, 1); + dumpCommandsRecursive(Commands, 1, false); + return PM3_SUCCESS; + } + // Markdown help dump children with help + if (strcmp(Cmd, "XX_internal_command_dump_markdown_help_XX") == 0) { + dumpCommandsRecursive(Commands, 1, true); return PM3_SUCCESS; } @@ -290,7 +300,7 @@ int CmdsParse(const command_t Commands[], const char *Cmd) { static char pparent[512] = {0}; static char *parent = pparent; -void dumpCommandsRecursive(const command_t cmds[], int markdown) { +void dumpCommandsRecursive(const command_t cmds[], int markdown, bool full_help) { if (cmds[0].Name == NULL) return; int i = 0; @@ -301,7 +311,7 @@ void dumpCommandsRecursive(const command_t cmds[], int markdown) { if (markdown) { PrintAndLogEx(NORMAL, "|%-*s|%-*s|%s", w_cmd, "command", w_off, "offline", "description"); PrintAndLogEx(NORMAL, "|%-*s|%-*s|%s", w_cmd, "-------", w_off, "-------", "-----------"); - } else { + } else if (! full_help) { PrintAndLogEx(NORMAL, "%-*s|%-*s|%s", w_cmd, "command", w_off, "offline", "description"); PrintAndLogEx(NORMAL, "%-*s|%-*s|%s", w_cmd, "-------", w_off, "-------", "-----------"); } @@ -317,8 +327,13 @@ void dumpCommandsRecursive(const command_t cmds[], int markdown) { cmd_offline = "Y"; if (markdown) PrintAndLogEx(NORMAL, "|`%s%-*s`|%-*s|`%s`", parent, w_cmd - (int)strlen(parent) - 2, cmds[i].Name, w_off, cmd_offline, cmds[i].Help); - else + else if (full_help) { + PrintAndLogEx(NORMAL, "---------------------------------------------------------------------------------------"); + PrintAndLogEx(NORMAL, _RED_("%s%-*s\n") "available offline: %s", parent, w_cmd - (int)strlen(parent), cmds[i].Name, cmds[i].IsAvailable()?_GREEN_("yes"):_RED_("no")); + cmds[i].Parse("--help"); + } else { PrintAndLogEx(NORMAL, "%s%-*s|%-*s|%s", parent, w_cmd - (int)strlen(parent), cmds[i].Name, w_off, cmd_offline, cmds[i].Help); + } ++i; } PrintAndLogEx(NORMAL, "\n"); @@ -330,8 +345,12 @@ void dumpCommandsRecursive(const command_t cmds[], int markdown) { if ((cmds[i].Name[0] == '-' || strlen(cmds[i].Name) == 0) && ++i) continue; if (cmds[i].Help[0] != '{' && ++i) continue; - PrintAndLogEx(NORMAL, "### %s%s\n\n %s\n", parent, cmds[i].Name, cmds[i].Help); - + if (full_help) { + PrintAndLogEx(NORMAL, "======================================================================================="); + PrintAndLogEx(NORMAL, _RED_("%s%s\n\n ")_CYAN_("%s\n"), parent, cmds[i].Name, cmds[i].Help); + } else { + PrintAndLogEx(NORMAL, "### %s%s\n\n %s\n", parent, cmds[i].Name, cmds[i].Help); + } char currentparent[512] = {0}; snprintf(currentparent, sizeof currentparent, "%s%s ", parent, cmds[i].Name); char *old_parent = parent; @@ -340,8 +359,11 @@ void dumpCommandsRecursive(const command_t cmds[], int markdown) { // in turn calls the CmdsParse above. if (markdown) cmds[i].Parse("XX_internal_command_dump_markdown_XX"); - else + else if (full_help) { + cmds[i].Parse("XX_internal_command_dump_full_XX"); + } else { cmds[i].Parse("XX_internal_command_dump_XX"); + } parent = old_parent; ++i; diff --git a/client/src/cmdparser.h b/client/src/cmdparser.h index ff59df705..9b0933329 100644 --- a/client/src/cmdparser.h +++ b/client/src/cmdparser.h @@ -54,6 +54,6 @@ void CmdsHelp(const command_t Commands[]); void CmdsLS(const command_t Commands[]); // Parse a command line int CmdsParse(const command_t Commands[], const char *Cmd); -void dumpCommandsRecursive(const command_t cmds[], int markdown); +void dumpCommandsRecursive(const command_t cmds[], int markdown, bool full_help); #endif diff --git a/client/src/proxmark3.c b/client/src/proxmark3.c index 18dcf6bb5..030ed9b56 100644 --- a/client/src/proxmark3.c +++ b/client/src/proxmark3.c @@ -455,14 +455,14 @@ check_script: } #ifndef LIBPM3 -static void dumpAllHelp(int markdown) { +static void dumpAllHelp(int markdown, bool full_help) { session.help_dump_mode = true; PrintAndLogEx(NORMAL, "\n%sProxmark3 command dump%s\n\n", markdown ? "# " : "", markdown ? "" : "\n======================"); PrintAndLogEx(NORMAL, "Some commands are available only if a Proxmark3 is actually connected.%s\n", markdown ? " " : ""); PrintAndLogEx(NORMAL, "Check column \"offline\" for their availability.\n"); PrintAndLogEx(NORMAL, "\n"); command_t *cmds = getTopLevelCommandTable(); - dumpCommandsRecursive(cmds, markdown); + dumpCommandsRecursive(cmds, markdown, full_help); session.help_dump_mode = false; } #endif //LIBPM3 @@ -553,7 +553,7 @@ static void set_my_user_directory(void) { #ifndef LIBPM3 static void show_help(bool showFullHelp, char *exec_name) { - PrintAndLogEx(NORMAL, "\nsyntax: %s [-h|-t|-m]", exec_name); + PrintAndLogEx(NORMAL, "\nsyntax: %s [-h|-t|-m|--fulltext]", exec_name); PrintAndLogEx(NORMAL, " %s [[-p] ] [-b] [-w] [-f] [-c ]|[-l ]|[-s ] [-i] [-d <0|1|2>]", exec_name); PrintAndLogEx(NORMAL, " %s [-p] --flash [--unlock-bootloader] [--image ]+ [-w] [-f] [-d <0|1|2>]", exec_name); @@ -567,8 +567,9 @@ static void show_help(bool showFullHelp, char *exec_name) { PrintAndLogEx(NORMAL, " -f/--flush output will be flushed after every print"); PrintAndLogEx(NORMAL, " -d/--debug <0|1|2> set debugmode"); PrintAndLogEx(NORMAL, "\nOptions in client mode:"); - PrintAndLogEx(NORMAL, " -t/--text dump all interactive command's help at once"); - PrintAndLogEx(NORMAL, " -m/--markdown dump all interactive help at once in markdown syntax"); + PrintAndLogEx(NORMAL, " -t/--text dump all interactive command list at once"); + PrintAndLogEx(NORMAL, " --fulltext dump all interactive command's help at once"); + PrintAndLogEx(NORMAL, " -m/--markdown dump all interactive command list at once in markdown syntax"); PrintAndLogEx(NORMAL, " -b/--baud serial port speed (only needed for physical UART, not for USB-CDC or BT)"); PrintAndLogEx(NORMAL, " -c/--command execute one Proxmark3 command (or several separated by ';')."); PrintAndLogEx(NORMAL, " -l/--lua execute lua script."); @@ -823,14 +824,22 @@ int main(int argc, char *argv[]) { if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--text") == 0) { g_printAndLog = PRINTANDLOG_PRINT; show_help(false, exec_name); - dumpAllHelp(0); + dumpAllHelp(0, false); + return 0; + } + + // dump help + if (strcmp(argv[i], "--fulltext") == 0) { + g_printAndLog = PRINTANDLOG_PRINT; + show_help(false, exec_name); + dumpAllHelp(0, true); return 0; } // dump markup if (strcmp(argv[i], "-m") == 0 || strcmp(argv[i], "--markdown") == 0) { g_printAndLog = PRINTANDLOG_PRINT; - dumpAllHelp(1); + dumpAllHelp(1, false); return 0; } // print client version From baf6ef292ddf60e773a5ab37e38f4de6ae5cb575 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 19 Apr 2021 07:07:40 +0200 Subject: [PATCH 356/373] remove old unused files --- client/src/cmdhfmfdesfire_disabled.c | 246 --------------------------- client/src/cmdhfmfdesfire_disabled.h | 8 - 2 files changed, 254 deletions(-) delete mode 100644 client/src/cmdhfmfdesfire_disabled.c delete mode 100644 client/src/cmdhfmfdesfire_disabled.h diff --git a/client/src/cmdhfmfdesfire_disabled.c b/client/src/cmdhfmfdesfire_disabled.c deleted file mode 100644 index e2de33485..000000000 --- a/client/src/cmdhfmfdesfire_disabled.c +++ /dev/null @@ -1,246 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2014 Andy Davies -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// High frequency MIFARE commands -//----------------------------------------------------------------------------- - -#include "cmdhfmfdesfire_disabled.h" - -#include "cmdparser.h" // command_t - -#include "cmdhfmf.h" -#include "util.h" -#include "des.h" -#include "aes.h" - -static int CmdHelp(const char *Cmd); - -//DESFIRE -// Reader 2 Card : 020A, key (1 byte), CRC1 CRC2 ; auth (020a00) -// Card 2 Reader : 02AF, 8 Bytes(b0), CRC1 CRC2 -// Reader 2 Card : 03AF, 8 Bytes(b1),8 bytes(b2), CRC1 CRC2 -// Card 2 Reader : 0300, 8 bytes(b3), CRC1 CRC2 ; success - -//send 020A00, receive enc(nc) - -//02AE = error -//receive b3=enc(r4) -//r5=dec(b3) -//n'r=rol(r5) -//verify n'r=nr - -static int CmdHF14AMfDESAuth(const char *Cmd) { - - uint8_t blockNo = 0; - //keyNo=0; - uint32_t cuid = 0; - uint8_t reply[16] = {0x00}; - //DES_cblock r1_b1; - uint8_t b1[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t b2[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - DES_cblock nr, b0, r1, r0; - - - uint8_t key[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - //DES_cblock iv={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - DES_key_schedule ks1; - DES_cblock key1; - - if (strlen(Cmd) < 1) { - PrintAndLogEx(NORMAL, "Usage: hf desfire des-auth k "); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf desfire des-auth k 0"); - return 0; - } - - //Change key to user defined one - - memcpy(key1, key, 8); - //memcpy(key2,key+8,8); - DES_set_key((DES_cblock *)key1, &ks1); - //DES_set_key((DES_cblock *)key2,&ks2); - - //Auth1 - SendCommandMIX(CMD_MIFARE_DES_AUTH1, blockNo, 0, 0, NULL, 0); - PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - uint8_t isOK = resp.oldarg[0] & 0xff; - cuid = resp.oldarg[1]; - uint8_t *data = resp.data.asBytes; - - if (isOK) { - PrintAndLogEx(NORMAL, "enc(nc)/b0:%s", sprint_hex(data + 2, 8)); - memcpy(b0, data + 2, 8); - } - } else { - PrintAndLogEx(WARNING, "Command execute timeout"); - } - - //Do crypto magic - DES_random_key(&nr); - //b1=dec(nr) - //r0=dec(b0) - DES_ecb_encrypt(&nr, &b1, &ks1, 0); - DES_ecb_encrypt(&b0, &r0, &ks1, 0); - //PrintAndLogEx(NORMAL, "b1:%s",sprint_hex(b1, 8)); - PrintAndLogEx(NORMAL, "r0:%s", sprint_hex(r0, 8)); - //r1=rol(r0) - memcpy(r1, r0, 8); - rol(r1, 8); - PrintAndLogEx(NORMAL, "r1:%s", sprint_hex(r1, 8)); - for (int i = 0; i < 8; i++) { - b2[i] = (r1[i] ^ b1[i]); - } - DES_ecb_encrypt(&b2, &b2, &ks1, 0); - //PrintAndLogEx(NORMAL, "b1:%s",sprint_hex(b1, 8)); - PrintAndLogEx(NORMAL, "b2:%s", sprint_hex(b2, 8)); - - //Auth2 - memcpy(reply, b1, 8); - memcpy(reply + 8, b2, 8); - SendCommandOLD(CMD_MIFARE_DES_AUTH2, cuid, 0, 0, reply, sizeof(reply)); - - PacketResponseNG respb; - if (WaitForResponseTimeout(CMD_ACK, &respb, 1500)) { - uint8_t isOK = respb.arg[0] & 0xff; - uint8_t *data2 = respb.d.asBytes; - - if (isOK) - PrintAndLogEx(NORMAL, "b3:%s", sprint_hex(data2 + 2, 8)); - - } else { - PrintAndLogEx(WARNING, "Command execute timeout"); - } - return 1; -} - -//EV1 -// Reader 2 Card : 02AA, key (1 byte), CRC1 CRC2 ; auth -// Card 2 Reader : 02AF, 16 Bytes(b0), CRC1 CRC2 -// Reader 2 Card : 03AF, 16 Bytes(b1),16Bytes(b2) CRC1 CRC2 -// Card 2 Reader : 0300, 16 bytes(b3), CRC1 CRC2 ; success -static int CmdHF14AMfAESAuth(const char *Cmd) { - - uint8_t blockNo = 0; - //keyNo=0; - uint32_t cuid = 0; - uint8_t reply[32] = {0x00}; - //DES_cblock r1_b1; - //unsigned char * b1, b2, nr, b0, r0, r1; - - uint8_t b1[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t b2[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t nr[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t b0[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t r0[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t r1[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - // - uint8_t key[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - AES_KEY key_e; - AES_KEY key_d; - - if (strlen(Cmd) < 1) { - PrintAndLogEx(NORMAL, "Usage: hf desfire aes-auth k "); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf desfire aes-auth k 0"); - return 0; - } - - //Change key to user defined one - // - // int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,AES_KEY *key); - //int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,AES_KEY *key); - // - //memcpy(key1,key,16); - //memcpy(key2,key+8,8); - AES_set_encrypt_key(key, 128, &key_e); - AES_set_decrypt_key(key, 128, &key_d); - - //Auth1 - SendCommandMIX(CMD_MIFARE_DES_AUTH1, blockNo, 0, 0, NULL, 0); - PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - uint8_t isOK = resp.oldarg[0] & 0xff; - cuid = resp.oldarg[1]; - uint8_t *data = resp.data.asBytes; - - if (isOK) { - PrintAndLogEx(NORMAL, "enc(nc)/b0:%s", sprint_hex(data + 2, 16)); - memcpy(b0, data + 2, 16); - } - } else { - PrintAndLogEx(WARNING, "Command execute timeout"); - } - // - // void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, - //size_t length, const AES_KEY *key, - //unsigned char *ivec, const int enc); - - //Do crypto magic - //DES_random_key(&nr); - //b1=dec(nr) - //r0=dec(b0) - //AES_cbc_encrypt(&nr,&b1,16,&key,0); - AES_cbc_encrypt(&b0, &r0, 16, &key_d, iv, 0); - //PrintAndLogEx(NORMAL, "b1:%s",sprint_hex(b1, 8)); - PrintAndLogEx(NORMAL, "r0:%s", sprint_hex(r0, 16)); - //r1=rol(r0) - memcpy(r1, r0, 16); - rol(r1, 8); - PrintAndLogEx(NORMAL, "r1:%s", sprint_hex(r1, 16)); - for (int i = 0; i < 16; i++) { - b1[i] = (nr[i] ^ b0[i]); - b2[i] = (r1[i] ^ b1[i]); - } - PrintAndLogEx(NORMAL, "nr:%s", sprint_hex(nr, 16)); - AES_cbc_encrypt(&b1, &b1, 16, &key_e, iv, 1); - AES_cbc_encrypt(&b2, &b2, 16, &key_e, iv, 1); - PrintAndLogEx(NORMAL, "b1:%s", sprint_hex(b1, 16)); - PrintAndLogEx(NORMAL, "b2:%s", sprint_hex(b2, 16)); - - //Auth2 - memcpy(reply, b1, 16); - memcpy(reply + 16, b2, 16); - SendCommandOLD(CMD_MIFARE_DES_AUTH2, cuid, 0, 0, reply, sizeof(reply)); - - PacketResponseNG respb; - if (WaitForResponseTimeout(CMD_ACK, &respb, 1500)) { - uint8_t isOK = respb.arg[0] & 0xff; - uint8_t *data2 = respb.d.asBytes; - - if (isOK) - PrintAndLogEx(NORMAL, "b3:%s", sprint_hex(data2 + 2, 16)); - - } else { - PrintAndLogEx(WARNING, "Command execute timeout"); - } - return 1; -} - - -//------------------------------------ -// Menu Stuff -//------------------------------------ -static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"dbg", CmdHF14AMfDbg, IfPm3Iso14443a, "Set default debug mode"}, - {"des-auth", CmdHF14AMfDESAuth, IfPm3Iso14443a, "Desfire Authentication"}, - {"ev1-auth", CmdHF14AMfAESAuth, IfPm3Iso14443a, "EV1 Authentication"}, - {NULL, NULL, NULL, NULL} -}; - -static int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; -} - -int CmdHFMFDesfire(const char *Cmd) { - // flush - clearCommandBuffer(); - return CmdsParse(CommandTable, Cmd); -} diff --git a/client/src/cmdhfmfdesfire_disabled.h b/client/src/cmdhfmfdesfire_disabled.h deleted file mode 100644 index 1583bc395..000000000 --- a/client/src/cmdhfmfdesfire_disabled.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __MFDESFIRE_AD_H -#define __MFDESFIRE_AD_H - -#include "common.h" - -int CmdHFMFDesfire(const char *Cmd); - -#endif From 979cdc465644affba14cf44145ff99bc6bd03826 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 19 Apr 2021 10:58:54 +0200 Subject: [PATCH 357/373] ignore artifact --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 543624a4f..8ff65578d 100644 --- a/.gitignore +++ b/.gitignore @@ -73,6 +73,7 @@ tools/cryptorf/sm tools/cryptorf/sma tools/cryptorf/sma_multi tools/mf_nonce_brute/mf_nonce_brute +tools/mf_nonce_brute/mf_trace_brute fpga/* !fpga/tests From 4c228b6c64efe7855dfe6648c65f8b796c26b9c9 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 19 Apr 2021 14:22:15 +0200 Subject: [PATCH 358/373] fix handling of trace list -1 with empty trace buffer --- client/src/cmdtrace.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index ba1987502..36314feb9 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -678,8 +678,11 @@ int CmdTraceList(const char *Cmd) { else if (strcmp(type, "cryptorf") == 0) protocol = PROTO_CRYPTORF; else if (strcmp(type, "raw") == 0) protocol = -1; - if (use_buffer == false || (g_traceLen == 0)) { + if (use_buffer == false) { download_trace(); + } else if (g_traceLen == 0) { + PrintAndLogEx(FAILED, "You requested a trace list in offline mode but there is no trace, consider using 'trace load' or removing parameter '1'"); + return PM3_EINVARG; } PrintAndLogEx(SUCCESS, "Recorded activity (trace len = " _YELLOW_("%lu") " bytes)", g_traceLen); From 4dea429157af1b2e1050fff2ba727ba2a5c73a21 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 19 Apr 2021 14:35:09 +0200 Subject: [PATCH 359/373] hf 14a list helptext handling by CmdTraceListAlias, to be generalized if ok --- client/src/cmdhf14a.c | 11 ++++++----- client/src/cmdtrace.c | 31 +++++++++++++++++++++++++++++++ client/src/cmdtrace.h | 1 + 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index cc7266db4..8c09b990c 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -171,12 +171,13 @@ static uint16_t frameLength = 0; uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256}; static int CmdHF14AList(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t 14a"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); + int ret = CmdTraceListAlias(Cmd, "hf 14a list"); + if (ret != PM3_SUCCESS) { + return ret; } + char args[128] = {0}; + snprintf(args, sizeof(args), "-t 14a "); + strncat(args, Cmd, sizeof(args) - strlen(args)); return CmdTraceList(args); } diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index 36314feb9..50f67ff05 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -591,6 +591,37 @@ static int CmdTraceSave(const char *Cmd) { return PM3_SUCCESS; } +int CmdTraceListAlias(const char *Cmd, const char *alias) { + CLIParserContext *ctx; + char example[200] = {0}; + sprintf(example, + "%s -f -> show frame delay times\n" + "%s -1 -> use trace buffer ", + alias, alias); + CLIParserInit(&ctx, alias, + "Alias of `trace list -t` with selected protocol data to annotate trace buffer\n" + "You can load a trace from file (see `trace load -h`) or it be downloaded from device by default\n" + "It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol", + example + ); + + void *argtable[] = { + arg_param_begin, + arg_lit0("1", "buffer", "use data from trace buffer"), + arg_lit0("f", NULL, "show frame delay times"), + arg_lit0("c", NULL, "mark CRC bytes"), + arg_lit0("r", NULL, "show relative times (gap and duration)"), + arg_lit0("u", NULL, "display times in microseconds instead of clock cycles"), + arg_lit0("x", NULL, "show hexdump to convert to pcap(ng)\n" + " or to import into Wireshark using encapsulation type \"ISO 14443\""), + arg_strx0(NULL, "dict", "", "use dictionary keys file"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + return PM3_SUCCESS; +} + int CmdTraceList(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "trace list", diff --git a/client/src/cmdtrace.h b/client/src/cmdtrace.h index acef66884..d4a9cd108 100644 --- a/client/src/cmdtrace.h +++ b/client/src/cmdtrace.h @@ -15,5 +15,6 @@ int CmdTrace(const char *Cmd); int CmdTraceList(const char *Cmd); +int CmdTraceListAlias(const char *Cmd, const char *alias); #endif From 2e925d5da3c83d01039df1065528f2ce19ad0474 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 19 Apr 2021 21:21:47 +0200 Subject: [PATCH 360/373] hf 14a list & CmdTraceListAlias: simplify --- client/src/cmdhf14a.c | 9 +-------- client/src/cmdtrace.c | 29 +++++++++++++++++------------ client/src/cmdtrace.h | 2 +- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 8c09b990c..74fe60281 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -171,14 +171,7 @@ static uint16_t frameLength = 0; uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256}; static int CmdHF14AList(const char *Cmd) { - int ret = CmdTraceListAlias(Cmd, "hf 14a list"); - if (ret != PM3_SUCCESS) { - return ret; - } - char args[128] = {0}; - snprintf(args, sizeof(args), "-t 14a "); - strncat(args, Cmd, sizeof(args) - strlen(args)); - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "hf 14a", "14a"); } int hf14a_getconfig(hf14a_config *config) { diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index 50f67ff05..e3b371c57 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -591,19 +591,22 @@ static int CmdTraceSave(const char *Cmd) { return PM3_SUCCESS; } -int CmdTraceListAlias(const char *Cmd, const char *alias) { +int CmdTraceListAlias(const char *Cmd, const char *alias, const char *protocol) { CLIParserContext *ctx; + char desc[500] = {0}; + snprintf(desc, sizeof(desc) - 1, + "Alias of `trace list -t %s` with selected protocol data to annotate trace buffer\n" + "You can load a trace from file (see `trace load -h`) or it be downloaded from device by default\n" + "It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol", + protocol); char example[200] = {0}; - sprintf(example, - "%s -f -> show frame delay times\n" - "%s -1 -> use trace buffer ", + snprintf(example, sizeof(example) - 1, + "%s list -f -> show frame delay times\n" + "%s list -1 -> use trace buffer ", alias, alias); - CLIParserInit(&ctx, alias, - "Alias of `trace list -t` with selected protocol data to annotate trace buffer\n" - "You can load a trace from file (see `trace load -h`) or it be downloaded from device by default\n" - "It accepts all other arguments of `trace list`. Note that some might not be relevant for this specific protocol", - example - ); + char fullalias[100] = {0}; + snprintf(fullalias, sizeof(fullalias) - 1, "%s list", alias); + CLIParserInit(&ctx, fullalias, desc, example); void *argtable[] = { arg_param_begin, @@ -618,8 +621,10 @@ int CmdTraceListAlias(const char *Cmd, const char *alias) { arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - CLIParserFree(ctx); - return PM3_SUCCESS; + char args[128] = {0}; + snprintf(args, sizeof(args), "-t %s ", protocol); + strncat(args, Cmd, sizeof(args) - strlen(args)); + return CmdTraceList(args); } int CmdTraceList(const char *Cmd) { diff --git a/client/src/cmdtrace.h b/client/src/cmdtrace.h index d4a9cd108..7444fe62e 100644 --- a/client/src/cmdtrace.h +++ b/client/src/cmdtrace.h @@ -15,6 +15,6 @@ int CmdTrace(const char *Cmd); int CmdTraceList(const char *Cmd); -int CmdTraceListAlias(const char *Cmd, const char *alias); +int CmdTraceListAlias(const char *Cmd, const char *alias, const char *protocol); #endif From dc54dd305b35c62fb71f36077e100f84fbb8f4e5 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 19 Apr 2021 21:43:32 +0200 Subject: [PATCH 361/373] Use CmdTraceListAlias everywhere --- client/src/cmdhf.c | 6 +++++- client/src/cmdhf14b.c | 8 +------- client/src/cmdhf15.c | 8 +------- client/src/cmdhfcryptorf.c | 8 +------- client/src/cmdhfemrtd.c | 8 +------- client/src/cmdhffelica.c | 8 +------- client/src/cmdhffido.c | 10 ++-------- client/src/cmdhficlass.c | 8 +------- client/src/cmdhflegic.c | 8 +------- client/src/cmdhflto.c | 8 +------- client/src/cmdhfmf.c | 8 +------- client/src/cmdhfmfdes.c | 8 +------- client/src/cmdhfst.c | 1 + client/src/cmdhfthinfilm.c | 8 +------- client/src/cmdhftopaz.c | 8 +------- client/src/cmdlfhitag.c | 10 ++-------- client/src/cmdsmartcard.c | 10 ++-------- client/src/emv/cmdemv.c | 8 +------- 18 files changed, 25 insertions(+), 116 deletions(-) diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index a4c5b2544..f5ef9f188 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -386,6 +386,10 @@ int CmdHFPlot(const char *Cmd) { return handle_hf_plot(); } +static int CmdHFList(const char *Cmd) { + return CmdTraceListAlias(Cmd, "hf", "raw"); +} + static command_t CommandTable[] = { {"--------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("High Frequency") " -----------------------"}, @@ -411,7 +415,7 @@ static command_t CommandTable[] = { {"waveshare", CmdHFWaveshare, AlwaysAvailable, "{ Waveshare NFC ePaper... }"}, {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"list", CmdTraceList, AlwaysAvailable, "List protocol data in trace buffer"}, + {"list", CmdHFList, AlwaysAvailable, "List protocol data in trace buffer"}, {"plot", CmdHFPlot, IfPm3Hfplot, "Plot signal"}, {"tune", CmdHFTune, IfPm3Present, "Continuously measure HF antenna tuning"}, {"search", CmdHFSearch, AlwaysAvailable, "Search for known HF tags"}, diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index 6ad2f90e3..959dfb489 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -199,13 +199,7 @@ static bool wait_cmd_14b(bool verbose, bool is_select) { } static int CmdHF14BList(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t 14b"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "hf 14b", "14b"); } static int CmdHF14BSim(const char *Cmd) { diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index ea9ced998..30d2db275 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1434,13 +1434,7 @@ static int CmdHF15Dump(const char *Cmd) { } static int CmdHF15List(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t 15"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "hf 15", "15"); } static int CmdHF15Raw(const char *Cmd) { diff --git a/client/src/cmdhfcryptorf.c b/client/src/cmdhfcryptorf.c index 3640b9639..4b1155870 100644 --- a/client/src/cmdhfcryptorf.c +++ b/client/src/cmdhfcryptorf.c @@ -42,13 +42,7 @@ static int switch_off_field_cryptorf(void) { } static int CmdHFCryptoRFList(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t cryptorf"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "hf cryptorf", "cryptorf"); } static int CmdHFCryptoRFSim(const char *Cmd) { diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index caa24b4ac..a61a8e709 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -2259,13 +2259,7 @@ static int cmd_hf_emrtd_info(const char *Cmd) { } static int cmd_hf_emrtd_list(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t 7816"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "hf emrtd", "7816"); } static command_t CommandTable[] = { diff --git a/client/src/cmdhffelica.c b/client/src/cmdhffelica.c index 7e71fa175..04ddd94c9 100644 --- a/client/src/cmdhffelica.c +++ b/client/src/cmdhffelica.c @@ -214,13 +214,7 @@ static bool add_last_IDm(uint8_t position, uint8_t *data) { } static int CmdHFFelicaList(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t felica"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "hf felica", "felica"); } int read_felica_uid(bool loop, bool verbose) { diff --git a/client/src/cmdhffido.c b/client/src/cmdhffido.c index 9fe85a4c8..4a0267fe5 100644 --- a/client/src/cmdhffido.c +++ b/client/src/cmdhffido.c @@ -39,13 +39,7 @@ static int CmdHelp(const char *Cmd); static int cmd_hf_fido_list(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t 14a"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "hf fido", "14a"); } static int cmd_hf_fido_info(const char *Cmd) { @@ -941,7 +935,7 @@ static int cmd_hf_fido_2get_assertion(const char *cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help."}, - {"list", cmd_hf_fido_list, IfPm3Iso14443a, "List ISO 14443A history"}, + {"list", cmd_hf_fido_list, AlwaysAvailable, "List ISO 14443A history"}, {"info", cmd_hf_fido_info, IfPm3Iso14443a, "Info about FIDO tag."}, {"reg", cmd_hf_fido_register, IfPm3Iso14443a, "FIDO U2F Registration Message."}, {"auth", cmd_hf_fido_authenticate, IfPm3Iso14443a, "FIDO U2F Authentication Message."}, diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index d6888cf80..2db1a8072 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -535,13 +535,7 @@ static void print_picopass_header(const picopass_hdr_t *hdr) { } static int CmdHFiClassList(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t iclass"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "hf iclass", "iclass"); } static int CmdHFiClassSniff(const char *Cmd) { diff --git a/client/src/cmdhflegic.c b/client/src/cmdhflegic.c index 083945609..8bab7c120 100644 --- a/client/src/cmdhflegic.c +++ b/client/src/cmdhflegic.c @@ -1164,13 +1164,7 @@ static int CmdLegicWipe(const char *Cmd) { } static int CmdLegicList(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t legic"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "hf legic", "legic"); } static command_t CommandTable[] = { diff --git a/client/src/cmdhflto.c b/client/src/cmdhflto.c index 828a69993..15ddd253f 100644 --- a/client/src/cmdhflto.c +++ b/client/src/cmdhflto.c @@ -172,13 +172,7 @@ int infoLTO(bool verbose) { } static int CmdHfLTOList(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t lto"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "hf lto", "lto"); } static int lto_rdbl(uint8_t blk, uint8_t *block_response, uint8_t *block_cnt_response, bool verbose) { diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 7ca124d45..b7e12d0af 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -5529,13 +5529,7 @@ static int CmdHFMFPersonalize(const char *cmd) { } static int CmdHF14AMfList(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t mf"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "hf mf", "mf"); } static int CmdHf14AGen3UID(const char *Cmd) { diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 3be04b5e3..f1673cfb5 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4803,13 +4803,7 @@ static int CmdHF14aDesChk(const char *Cmd) { } static int CmdHF14ADesList(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t des"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "hf mfdes", "des"); } /* diff --git a/client/src/cmdhfst.c b/client/src/cmdhfst.c index f53ace548..64e244323 100644 --- a/client/src/cmdhfst.c +++ b/client/src/cmdhfst.c @@ -788,6 +788,7 @@ static int cmd_hf_st_pwd(const char *Cmd) { } static int cmd_hf_st_list(const char *Cmd) { + return CmdTraceListAlias(Cmd, "hf st", "7816"); char args[128] = {0}; if (strlen(Cmd) == 0) { snprintf(args, sizeof(args), "-t 7816"); diff --git a/client/src/cmdhfthinfilm.c b/client/src/cmdhfthinfilm.c index 976e1314d..20fe64d84 100644 --- a/client/src/cmdhfthinfilm.c +++ b/client/src/cmdhfthinfilm.c @@ -191,13 +191,7 @@ static int CmdHfThinFilmSim(const char *Cmd) { } static int CmdHfThinFilmList(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t thinfilm"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "hf thinfilm", "thinfilm"); } static command_t CommandTable[] = { diff --git a/client/src/cmdhftopaz.c b/client/src/cmdhftopaz.c index a6564ae17..69f840b19 100644 --- a/client/src/cmdhftopaz.c +++ b/client/src/cmdhftopaz.c @@ -524,13 +524,7 @@ static int CmdHFTopazCmdRaw(const char *Cmd) { } static int CmdHFTopazList(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t topaz"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "hf topaz", "topaz"); } static int CmdHFTopazSniff(const char *Cmd) { diff --git a/client/src/cmdlfhitag.c b/client/src/cmdlfhitag.c index 509e5218b..96daa6390 100644 --- a/client/src/cmdlfhitag.c +++ b/client/src/cmdlfhitag.c @@ -52,13 +52,7 @@ static size_t nbytes(size_t nbits) { */ static int CmdLFHitagList(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t hitag2"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "lf hitag", "hitag2"); /* @@ -940,7 +934,7 @@ void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, bool static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"eload", CmdLFHitagEload, IfPm3Hitag, "Load Hitag dump file into emulator memory"}, - {"list", CmdLFHitagList, IfPm3Hitag, "List Hitag trace history"}, + {"list", CmdLFHitagList, AlwaysAvailable, "List Hitag trace history"}, {"info", CmdLFHitagInfo, IfPm3Hitag, "Tag information"}, {"reader", CmdLFHitagReader, IfPm3Hitag, "Act like a Hitag reader"}, {"sim", CmdLFHitagSim, IfPm3Hitag, "Simulate Hitag transponder"}, diff --git a/client/src/cmdsmartcard.c b/client/src/cmdsmartcard.c index 7c2e615d7..fcd52abf8 100644 --- a/client/src/cmdsmartcard.c +++ b/client/src/cmdsmartcard.c @@ -826,13 +826,7 @@ static int CmdSmartSetClock(const char *Cmd) { } static int CmdSmartList(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t 7816"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "smart", "7816"); } static void smart_brute_prim(void) { @@ -1104,7 +1098,7 @@ static int CmdSmartBruteforceSFI(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"list", CmdSmartList, IfPm3Smartcard, "List ISO 7816 history"}, + {"list", CmdSmartList, AlwaysAvailable, "List ISO 7816 history"}, {"info", CmdSmartInfo, IfPm3Smartcard, "Tag information"}, {"reader", CmdSmartReader, IfPm3Smartcard, "Act like an IS07816 reader"}, {"raw", CmdSmartRaw, IfPm3Smartcard, "Send raw hex data to tag"}, diff --git a/client/src/emv/cmdemv.c b/client/src/emv/cmdemv.c index 718fb6bcd..989acaf6c 100644 --- a/client/src/emv/cmdemv.c +++ b/client/src/emv/cmdemv.c @@ -1803,13 +1803,7 @@ static int CmdEMVScan(const char *Cmd) { } static int CmdEMVList(const char *Cmd) { - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t 7816"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); + return CmdTraceListAlias(Cmd, "emv", "7816"); } static int CmdEMVTest(const char *Cmd) { From 1d69cabd5426233c014457342e907c706c89de55 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 19 Apr 2021 21:56:49 +0200 Subject: [PATCH 362/373] change fido/emrtd/st fct names to match other functions --- client/src/cmdhf.c | 2 +- client/src/cmdhfemrtd.c | 12 ++++++------ client/src/cmdhffido.c | 24 ++++++++++++------------ client/src/cmdhfst.c | 30 +++++++++++++++--------------- client/src/cmdhfst.h | 4 ++-- 5 files changed, 36 insertions(+), 36 deletions(-) diff --git a/client/src/cmdhf.c b/client/src/cmdhf.c index f5ef9f188..0cf9bcc37 100644 --- a/client/src/cmdhf.c +++ b/client/src/cmdhf.c @@ -409,7 +409,7 @@ static command_t CommandTable[] = { {"mfp", CmdHFMFP, AlwaysAvailable, "{ MIFARE Plus RFIDs... }"}, {"mfu", CmdHFMFUltra, AlwaysAvailable, "{ MIFARE Ultralight RFIDs... }"}, {"mfdes", CmdHFMFDes, AlwaysAvailable, "{ MIFARE Desfire RFIDs... }"}, - {"st", CmdHF_ST, AlwaysAvailable, "{ ST Rothult RFIDs... }"}, + {"st", CmdHFST, AlwaysAvailable, "{ ST Rothult RFIDs... }"}, {"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"}, {"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"}, {"waveshare", CmdHFWaveshare, AlwaysAvailable, "{ Waveshare NFC ePaper... }"}, diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index a61a8e709..df4cb7273 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -2075,7 +2075,7 @@ static bool validate_date(uint8_t *data, int datalen) { return !(day <= 0 || day > 31 || month <= 0 || month > 12); } -static int cmd_hf_emrtd_dump(const char *Cmd) { +static int CmdHFeMRTDDump(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf emrtd dump", "Dump all files on an eMRTD", @@ -2167,7 +2167,7 @@ static int cmd_hf_emrtd_dump(const char *Cmd) { return dumpHF_EMRTD((char *)docnum, (char *)dob, (char *)expiry, BAC, (const char *)path); } -static int cmd_hf_emrtd_info(const char *Cmd) { +static int CmdHFeMRTDInfo(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf emrtd info", "Display info about an eMRTD", @@ -2258,15 +2258,15 @@ static int cmd_hf_emrtd_info(const char *Cmd) { } } -static int cmd_hf_emrtd_list(const char *Cmd) { +static int CmdHFeMRTDList(const char *Cmd) { return CmdTraceListAlias(Cmd, "hf emrtd", "7816"); } static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"dump", cmd_hf_emrtd_dump, IfPm3Iso14443, "Dump eMRTD files to binary files"}, - {"info", cmd_hf_emrtd_info, AlwaysAvailable, "Display info about an eMRTD"}, - {"list", cmd_hf_emrtd_list, AlwaysAvailable, "List ISO 14443A/7816 history"}, + {"dump", CmdHFeMRTDDump, IfPm3Iso14443, "Dump eMRTD files to binary files"}, + {"info", CmdHFeMRTDInfo, AlwaysAvailable, "Display info about an eMRTD"}, + {"list", CmdHFeMRTDList, AlwaysAvailable, "List ISO 14443A/7816 history"}, {NULL, NULL, NULL, NULL} }; diff --git a/client/src/cmdhffido.c b/client/src/cmdhffido.c index 4a0267fe5..d6648371d 100644 --- a/client/src/cmdhffido.c +++ b/client/src/cmdhffido.c @@ -38,11 +38,11 @@ static int CmdHelp(const char *Cmd); -static int cmd_hf_fido_list(const char *Cmd) { +static int CmdHFFidoList(const char *Cmd) { return CmdTraceListAlias(Cmd, "hf fido", "14a"); } -static int cmd_hf_fido_info(const char *Cmd) { +static int CmdHFFidoInfo(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf fido info", "Get info from Fido tags", @@ -161,7 +161,7 @@ static json_t *OpenJson(CLIParserContext *ctx, int paramnum, char *fname, void * return root; } -static int cmd_hf_fido_register(const char *cmd) { +static int CmdHFFidoRegister(const char *cmd) { uint8_t data[64] = {0}; int chlen = 0; uint8_t cdata[250] = {0}; @@ -404,7 +404,7 @@ static int cmd_hf_fido_register(const char *cmd) { return PM3_SUCCESS; } -static int cmd_hf_fido_authenticate(const char *cmd) { +static int CmdHFFidoAuthenticate(const char *cmd) { uint8_t data[512] = {0}; uint8_t hdata[250] = {0}; bool public_key_loaded = false; @@ -677,7 +677,7 @@ static int GetExistsFileNameJson(const char *prefixDir, const char *reqestedFile return PM3_SUCCESS; } -static int cmd_hf_fido_2make_credential(const char *cmd) { +static int CmdHFFido2MakeCredential(const char *cmd) { json_error_t error; char fname[FILE_PATH_SIZE] = {0}; @@ -805,7 +805,7 @@ static int cmd_hf_fido_2make_credential(const char *cmd) { return PM3_SUCCESS; } -static int cmd_hf_fido_2get_assertion(const char *cmd) { +static int CmdHFFido2GetAssertion(const char *cmd) { json_error_t error; char fname[FILE_PATH_SIZE] = {0}; @@ -935,12 +935,12 @@ static int cmd_hf_fido_2get_assertion(const char *cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help."}, - {"list", cmd_hf_fido_list, AlwaysAvailable, "List ISO 14443A history"}, - {"info", cmd_hf_fido_info, IfPm3Iso14443a, "Info about FIDO tag."}, - {"reg", cmd_hf_fido_register, IfPm3Iso14443a, "FIDO U2F Registration Message."}, - {"auth", cmd_hf_fido_authenticate, IfPm3Iso14443a, "FIDO U2F Authentication Message."}, - {"make", cmd_hf_fido_2make_credential, IfPm3Iso14443a, "FIDO2 MakeCredential command."}, - {"assert", cmd_hf_fido_2get_assertion, IfPm3Iso14443a, "FIDO2 GetAssertion command."}, + {"list", CmdHFFidoList, AlwaysAvailable, "List ISO 14443A history"}, + {"info", CmdHFFidoInfo, IfPm3Iso14443a, "Info about FIDO tag."}, + {"reg", CmdHFFidoRegister, IfPm3Iso14443a, "FIDO U2F Registration Message."}, + {"auth", CmdHFFidoAuthenticate, IfPm3Iso14443a, "FIDO U2F Authentication Message."}, + {"make", CmdHFFido2MakeCredential, IfPm3Iso14443a, "FIDO2 MakeCredential command."}, + {"assert", CmdHFFido2GetAssertion, IfPm3Iso14443a, "FIDO2 GetAssertion command."}, {NULL, NULL, 0, NULL} }; diff --git a/client/src/cmdhfst.c b/client/src/cmdhfst.c index 64e244323..2c0ffea31 100644 --- a/client/src/cmdhfst.c +++ b/client/src/cmdhfst.c @@ -203,7 +203,7 @@ static uint16_t get_sw(uint8_t *d, uint8_t n) { } // ST rothult -int infoHF_ST(void) { +int infoHFST(void) { bool activate_field = true; bool keep_field_on = true; @@ -317,7 +317,7 @@ int infoHF_ST(void) { } // menu command to get and print all info known about any known ST25TA tag -static int cmd_hf_st_info(const char *Cmd) { +static int CmdHFSTInfo(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf st info", "Get info about ST25TA tag", @@ -330,10 +330,10 @@ static int cmd_hf_st_info(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, true); CLIParserFree(ctx); - return infoHF_ST(); + return infoHFST(); } -static int cmd_hf_st_sim(const char *Cmd) { +static int CmdHFSTSim(const char *Cmd) { int uidlen = 0; uint8_t uid[7] = {0}; @@ -361,7 +361,7 @@ static int cmd_hf_st_sim(const char *Cmd) { return CmdHF14ASim(param); } -static int cmd_hf_st_ndef(const char *Cmd) { +static int CmdHFSTNdef(const char *Cmd) { int pwdlen = 0; uint8_t pwd[16] = {0}; bool with_pwd = false; @@ -489,7 +489,7 @@ static int cmd_hf_st_ndef(const char *Cmd) { return PM3_SUCCESS; } -static int cmd_hf_st_protect(const char *Cmd) { +static int CmdHFSTProtect(const char *Cmd) { int pwdlen = 0; uint8_t pwd[16] = {0}; @@ -644,7 +644,7 @@ static int cmd_hf_st_protect(const char *Cmd) { return PM3_SUCCESS; } -static int cmd_hf_st_pwd(const char *Cmd) { +static int CmdHFSTPwd(const char *Cmd) { int pwdlen = 0; uint8_t pwd[16] = {0}; @@ -787,7 +787,7 @@ static int cmd_hf_st_pwd(const char *Cmd) { return PM3_SUCCESS; } -static int cmd_hf_st_list(const char *Cmd) { +static int CmdHFSTList(const char *Cmd) { return CmdTraceListAlias(Cmd, "hf st", "7816"); char args[128] = {0}; if (strlen(Cmd) == 0) { @@ -800,12 +800,12 @@ static int cmd_hf_st_list(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"info", cmd_hf_st_info, IfPm3Iso14443a, "Tag information"}, - {"list", cmd_hf_st_list, AlwaysAvailable, "List ISO 14443A/7816 history"}, - {"ndef", cmd_hf_st_ndef, AlwaysAvailable, "read NDEF file on tag"}, - {"protect", cmd_hf_st_protect, IfPm3Iso14443a, "change protection on tag"}, - {"pwd", cmd_hf_st_pwd, IfPm3Iso14443a, "change password on tag"}, - {"sim", cmd_hf_st_sim, IfPm3Iso14443a, "Fake ISO 14443A/ST tag"}, + {"info", CmdHFSTInfo, IfPm3Iso14443a, "Tag information"}, + {"list", CmdHFSTList, AlwaysAvailable, "List ISO 14443A/7816 history"}, + {"ndef", CmdHFSTNdef, AlwaysAvailable, "read NDEF file on tag"}, + {"protect", CmdHFSTProtect, IfPm3Iso14443a, "change protection on tag"}, + {"pwd", CmdHFSTPwd, IfPm3Iso14443a, "change password on tag"}, + {"sim", CmdHFSTSim, IfPm3Iso14443a, "Fake ISO 14443A/ST tag"}, {NULL, NULL, NULL, NULL} }; @@ -815,7 +815,7 @@ static int CmdHelp(const char *Cmd) { return PM3_SUCCESS; } -int CmdHF_ST(const char *Cmd) { +int CmdHFST(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandTable, Cmd); } diff --git a/client/src/cmdhfst.h b/client/src/cmdhfst.h index c3772318d..cd73fffd0 100644 --- a/client/src/cmdhfst.h +++ b/client/src/cmdhfst.h @@ -13,7 +13,7 @@ #include "common.h" -int CmdHF_ST(const char *Cmd); +int CmdHFST(const char *Cmd); -int infoHF_ST(void); +int infoHFST(void); #endif From 5604afce7a3d5e116ac0994f7dc2cb1887eb2328 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 19 Apr 2021 22:18:37 +0200 Subject: [PATCH 363/373] trace list - now colors whole reader line output. Also little nasty buff-underflow bug fixed --- CHANGELOG.md | 2 ++ client/src/cmdtrace.c | 84 ++++++++++++++++++++++++++++++------------- 2 files changed, 61 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7a2dd375..327ac9f61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Change `hf 14a/14b/15 list etc alias commands now unified helptext (@doegox) + - Change `trace list` - now colors whole reader line (@iceman1001) - Change `lf search` - add option `-c` to continue searching after first hit (@doegox) - Fix DESFire mis-annotation (@VortixDev) - Change `lf pac demod` - now also search for inverted bitstreams (@iceman1001) diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index e3b371c57..4db44fb16 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -308,9 +308,12 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr } m--; } - line[(data_len - 1) / 16][((data_len - 1) % 16) * 4 + 2] = '('; - line[(data_len - 1) / 16][((data_len - 1) % 16) * 4 + 3] = m + 0x30; - line[(data_len - 1) / 16][((data_len - 1) % 16) * 4 + 4] = ')'; + + if (data_len) { + line[(data_len - 1) / 16][((data_len - 1) % 16) * 4 + 2] = '('; + line[(data_len - 1) / 16][((data_len - 1) % 16) * 4 + 3] = m + 0x30; + line[(data_len - 1) / 16][((data_len - 1) % 16) * 4 + 4] = ')'; + } } } @@ -400,32 +403,63 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr time2 = duration; } - if (use_us) { - PrintAndLogEx(NORMAL, " %10.1f | %10.1f | %s |%-72s | %s| %s", - (float)time1 / 13.56, - (float)time2 / 13.56, - (hdr->isResponse ? "Tag" : _YELLOW_("Rdr")), - line[j], - (j == num_lines - 1) ? crc : " ", - (j == num_lines - 1) ? explanation : "" - ); + if (hdr->isResponse) { + // tag row + if (use_us) { + PrintAndLogEx(NORMAL, " %10.1f | %10.1f | Tag |%-72s | %s| %s", + (float)time1 / 13.56, + (float)time2 / 13.56, + line[j], + (j == num_lines - 1) ? crc : " ", + (j == num_lines - 1) ? explanation : "" + ); + } else { + PrintAndLogEx(NORMAL, " %10u | %10u | Tag |%-72s | %s| %s", + (hdr->timestamp - first_hdr->timestamp), + (end_of_transmission_timestamp - first_hdr->timestamp), + line[j], + (j == num_lines - 1) ? crc : " ", + (j == num_lines - 1) ? explanation : "" + ); + } } else { - PrintAndLogEx(NORMAL, " %10u | %10u | %s |%-72s | %s| %s", - (hdr->timestamp - first_hdr->timestamp), - (end_of_transmission_timestamp - first_hdr->timestamp), - (hdr->isResponse ? "Tag" : _YELLOW_("Rdr")), - line[j], - (j == num_lines - 1) ? crc : " ", - (j == num_lines - 1) ? explanation : "" - ); + // reader row + if (use_us) { + PrintAndLogEx(NORMAL, + _YELLOW_(" %10.1f") " | " _YELLOW_("%10.1f") " | " _YELLOW_("Rdr") " |" _YELLOW_("%-72s")" | " _YELLOW_("%s") "| " _YELLOW_("%s"), + (float)time1 / 13.56, + (float)time2 / 13.56, + line[j], + (j == num_lines - 1) ? crc : " ", + (j == num_lines - 1) ? explanation : "" + ); + } else { + PrintAndLogEx(NORMAL, + _YELLOW_(" %10u") " | " _YELLOW_("%10u") " | " _YELLOW_("Rdr") " |" _YELLOW_("%-72s")" | " _YELLOW_("%s") "| " _YELLOW_("%s"), + (hdr->timestamp - first_hdr->timestamp), + (end_of_transmission_timestamp - first_hdr->timestamp), + line[j], + (j == num_lines - 1) ? crc : " ", + (j == num_lines - 1) ? explanation : "" + ); + } + } } else { - PrintAndLogEx(NORMAL, " | | |%-72s | %s| %s", - line[j], - (j == num_lines - 1) ? crc : " ", - (j == num_lines - 1) ? explanation : "" - ); + if (hdr->isResponse) { + PrintAndLogEx(NORMAL, " | | |%-72s | %s| %s", + line[j], + (j == num_lines - 1) ? crc : " ", + (j == num_lines - 1) ? explanation : "" + ); + } else { + PrintAndLogEx(NORMAL, " | | |" _YELLOW_("%-72s")" | " _YELLOW_("%s") "| " _YELLOW_("%s"), + line[j], + (j == num_lines - 1) ? crc : " ", + (j == num_lines - 1) ? explanation : "" + ); + } } } From 150579f3752b5e806de8dec89f79d07a80ca31da Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 19 Apr 2021 22:47:20 +0200 Subject: [PATCH 364/373] cliparser doesnt liek empty strings, should be NULL instead --- client/src/cmddata.c | 5 +++-- client/src/cmdlfem4x05.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index ad67126be..1e96e92d6 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1800,11 +1800,12 @@ static int CmdSamples(const char *Cmd) { CLIParserInit(&ctx, "data samples", "Get raw samples for graph window (GraphBuffer) from device.\n" "If 0, then get whole big buffer from device.", - "data samples" + "data samples\n" + "data samples -n 10000" ); void *argtable[] = { arg_param_begin, - arg_int0("n", "", "", "num of samples (512 - 40000)"), + arg_int0("n", NULL, "", "num of samples (512 - 40000)"), arg_lit0("v", "verbose", "verbose"), arg_param_end }; diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index 99ce8a9bf..82acb5bb6 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -1428,7 +1428,7 @@ int CmdEM4x05Brute(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_u64_0("s", "start", "", "Start bruteforce enumeration from this password value"), - arg_int0("n", "", "", "Stop after having found n candidates. Default: 0 => infinite"), + arg_int0("n", NULL, "", "Stop after having found n candidates. Default: 0 => infinite"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); From 1871e7b9fbfd4144dc06522fcdd244b3ecea0157 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 19 Apr 2021 22:52:40 +0200 Subject: [PATCH 365/373] lf t55xx resetread - correct cli arguments --- client/src/cmdlft55xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 1b98cc47d..06c4e2e34 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -2839,11 +2839,11 @@ static int CmdResetRead(const char *Cmd) { ); // 1 (help) + 0(one user specified params) + (5 T55XX_DLMODE_SINGLE) - void *argtable[0 + 5] = { + void *argtable[2 + 5] = { arg_param_begin, arg_lit0("1", NULL, "extract using data from graphbuffer"), }; - uint8_t idx = 1; + uint8_t idx = 2; arg_add_t55xx_downloadlink(argtable, &idx, T55XX_DLMODE_SINGLE, config.downlink_mode); CLIExecWithReturn(ctx, Cmd, argtable, true); From c7e47a721d590a5b16bb86bd3c3247be216181c4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 19 Apr 2021 23:00:02 +0200 Subject: [PATCH 366/373] cliparser doesnt like empty strings, --- client/src/cmdhfmfdes.c | 4 ++-- client/src/cmdlfem4x05.c | 2 +- client/src/cmdmain.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index f1673cfb5..ed4947377 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4820,7 +4820,7 @@ static int CmdHF14aDesNDEF(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_litn("v", "verbose", 0, 2, "show technical data"), - arg_str0("", "aid", "", "replace default aid for NDEF"), + arg_str0(NULL, "aid", "", "replace default aid for NDEF"), arg_str0("k", "key", "", "replace default key for NDEF"), arg_param_end }; @@ -4924,7 +4924,7 @@ static int CmdHF14aDesMAD(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_litn("v", "verbose", 0, 2, "show technical data"), - arg_str0("", "aid", "", "replace default aid for MAD"), + arg_str0(NULL, "aid", "", "replace default aid for MAD"), arg_str0("k", "key", "", "replace default key for MAD"), arg_param_end }; diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index 82acb5bb6..f43e163bb 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -1533,7 +1533,7 @@ int CmdEM4x05Unlock(const char *Cmd) { arg_int0("n", NULL, NULL, "steps to skip"), arg_int0("s", "start", "", "start scan from delay (us)"), arg_int0("e", "end", "", "end scan at delay (us)"), - arg_str0("p", "pwd", "", "password (00000000)"), + arg_str0("p", "pwd", "", "password (def 00000000)"), arg_lit0("v", "verbose", "verbose output"), arg_param_end }; diff --git a/client/src/cmdmain.c b/client/src/cmdmain.c index 5c4152604..b31b14836 100644 --- a/client/src/cmdmain.c +++ b/client/src/cmdmain.c @@ -129,7 +129,7 @@ static int CmdAuto(const char *Cmd) { void *argtable[] = { arg_param_begin, - arg_lit0("a", "all", ""), + arg_lit0("c", NULL, "Continue searching even after a first hit"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); From a2fa5cbc44aa49235ff632bd97a8071c08715fd8 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 19 Apr 2021 23:12:27 +0200 Subject: [PATCH 367/373] Add fulltext test --- client/src/proxmark3.c | 1 + tools/pm3_tests.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/client/src/proxmark3.c b/client/src/proxmark3.c index 030ed9b56..b0d5c5188 100644 --- a/client/src/proxmark3.c +++ b/client/src/proxmark3.c @@ -464,6 +464,7 @@ static void dumpAllHelp(int markdown, bool full_help) { command_t *cmds = getTopLevelCommandTable(); dumpCommandsRecursive(cmds, markdown, full_help); session.help_dump_mode = false; + PrintAndLogEx(NORMAL, "Full help dump done."); } #endif //LIBPM3 diff --git a/tools/pm3_tests.sh b/tools/pm3_tests.sh index 0cd468f9a..c3e4afcd1 100755 --- a/tools/pm3_tests.sh +++ b/tools/pm3_tests.sh @@ -338,6 +338,7 @@ while true; do if ! CheckExecute "proxmark help" "$CLIENTBIN -h" "wait"; then break; fi if ! CheckExecute "proxmark help text ISO7816" "$CLIENTBIN -t 2>&1" "ISO7816"; then break; fi if ! CheckExecute "proxmark help text hardnested" "$CLIENTBIN -t 2>&1" "hardnested"; then break; fi + if ! CheckExecute "proxmark full help dump" "$CLIENTBIN --fulltext 2>&1" "Full help dump done"; then break; fi echo -e "\n${C_BLUE}Testing data manipulation:${C_NC}" if ! CheckExecute "reveng readline test" "$CLIENTBIN -c 'reveng -h;reveng -D'" "CRC-64/GO-ISO"; then break; fi From bb9cf8ec40ae0a50a642cfdecbd9963fdb2ef672 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 19 Apr 2021 23:25:13 +0200 Subject: [PATCH 368/373] make sure there is room for null terminator --- client/src/cmdtrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index 4db44fb16..6792e2434 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -657,7 +657,7 @@ int CmdTraceListAlias(const char *Cmd, const char *alias, const char *protocol) CLIExecWithReturn(ctx, Cmd, argtable, true); char args[128] = {0}; snprintf(args, sizeof(args), "-t %s ", protocol); - strncat(args, Cmd, sizeof(args) - strlen(args)); + strncat(args, Cmd, sizeof(args) - strlen(args) - 1); return CmdTraceList(args); } From 99a82cf7d2f87df85a1021ab1601a9853066f153 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 19 Apr 2021 23:31:11 +0200 Subject: [PATCH 369/373] coverity fixes --- client/src/cmdhfst.c | 7 ------- client/src/cmdtrace.c | 2 ++ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/client/src/cmdhfst.c b/client/src/cmdhfst.c index 2c0ffea31..b15c8e8b4 100644 --- a/client/src/cmdhfst.c +++ b/client/src/cmdhfst.c @@ -789,13 +789,6 @@ static int CmdHFSTPwd(const char *Cmd) { static int CmdHFSTList(const char *Cmd) { return CmdTraceListAlias(Cmd, "hf st", "7816"); - char args[128] = {0}; - if (strlen(Cmd) == 0) { - snprintf(args, sizeof(args), "-t 7816"); - } else { - strncpy(args, Cmd, sizeof(args) - 1); - } - return CmdTraceList(args); } static command_t CommandTable[] = { diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index 6792e2434..d70b23080 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -655,6 +655,8 @@ int CmdTraceListAlias(const char *Cmd, const char *alias, const char *protocol) arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + char args[128] = {0}; snprintf(args, sizeof(args), "-t %s ", protocol); strncat(args, Cmd, sizeof(args) - strlen(args) - 1); From 06d61cdb7f4a541baa71850a51dfabdc6c936934 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 20 Apr 2021 01:41:34 +0200 Subject: [PATCH 370/373] fix script run for now, to be seen if we can do better --- client/src/cmdscript.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/client/src/cmdscript.c b/client/src/cmdscript.c index cb378c75b..9c8c794b9 100644 --- a/client/src/cmdscript.c +++ b/client/src/cmdscript.c @@ -237,22 +237,30 @@ static int CmdScriptRun(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "script run", "Run a Lua, Cmd or Python script", - "script run my_script.lua --my_script_args" + "script run my_script.lua -- --my_script_args" ); void *argtable[] = { arg_param_begin, + arg_file1(NULL, NULL, "", "script to run"), + arg_rem("--", "separator for script params"), + arg_strx0(NULL, NULL, "", "params for the script"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - CLIParserFree(ctx); - // TODO possible to handle it with cliparser? + char preferredName[128] = {0}; char arguments[256] = {0}; - int name_len = 0; int arg_len = 0; static uint8_t luascriptfile_idx = 0; - sscanf(Cmd, "%127s%n %255[^\n\r]%n", preferredName, &name_len, arguments, &arg_len); + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)preferredName, sizeof(preferredName), &name_len); +// this one removes all spaces +// CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)arguments, sizeof(arguments), &arg_len); + CLIParserFree(ctx); + sscanf(Cmd + name_len + 1, "-- %255[^\n\r]%n", arguments, &arg_len); + if (arg_len == 0) { + sscanf(Cmd + name_len + 1, "%255[^\n\r]%n", arguments, &arg_len); + } if (strlen(preferredName) == 0) { PrintAndLogEx(FAILED, "no script name provided"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`script list`") " to see available scripts"); From 7fbe4063b2aab6d7ec004cf6419533c7e9b669a3 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 20 Apr 2021 10:24:52 +0200 Subject: [PATCH 371/373] fix for script run & cliparser --- client/deps/cliparser/cliparser.c | 96 ++++++++++++++++--------------- client/deps/cliparser/cliparser.h | 1 + client/src/cmdscript.c | 19 +++--- 3 files changed, 60 insertions(+), 56 deletions(-) diff --git a/client/deps/cliparser/cliparser.c b/client/deps/cliparser/cliparser.c index ff7b71d94..ec9f50e20 100644 --- a/client/deps/cliparser/cliparser.c +++ b/client/deps/cliparser/cliparser.c @@ -47,6 +47,55 @@ int CLIParserInit(CLIParserContext **ctx, const char *vprogramName, const char * return 0; } +void CLIParserPrintHelp(CLIParserContext *ctx) { + if (ctx->programHint) + PrintAndLogEx(NORMAL, "\n"_DescriptionColor_("%s"), ctx->programHint); + + PrintAndLogEx(NORMAL, "\n"_SectionTagColor_("usage:")); + PrintAndLogEx(NORMAL, " "_CommandColor_("%s")NOLF, ctx->programName); + arg_print_syntax(stdout, ctx->argtable, "\n\n"); + + PrintAndLogEx(NORMAL, _SectionTagColor_("options:")); + + arg_print_glossary(stdout, ctx->argtable, " "_ArgColor_("%-30s")" "_ArgHelpColor_("%s")"\n"); + + PrintAndLogEx(NORMAL, ""); + if (ctx->programHelp) { + PrintAndLogEx(NORMAL, _SectionTagColor_("examples/notes:")); + char *buf = NULL; + int idx = 0; + buf = realloc(buf, strlen(ctx->programHelp) + 1); // more then enough as we are splitting + + char *p2; // pointer to split example from comment. + int egWidth = 30; + for (int i = 0; i <= strlen(ctx->programHelp); i++) { // <= so to get string terminator. + buf[idx++] = ctx->programHelp[i]; + if ((ctx->programHelp[i] == '\n') || (ctx->programHelp[i] == 0x00)) { + buf[idx - 1] = 0x00; + p2 = strstr(buf, "->"); // See if the example has a comment. + if (p2 != NULL) { + *(p2 - 1) = 0x00; + + if (strlen(buf) > 28) + egWidth = strlen(buf) + 5; + else + egWidth = 30; + + PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s")" %s", egWidth, buf, p2); + } else { + PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s"), egWidth, buf); + } + idx = 0; + } + } + + PrintAndLogEx(NORMAL, ""); + free(buf); + } + + fflush(stdout); +} + int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargtable[], size_t vargtableLen, bool allowEmptyExec) { int nerrors; @@ -65,52 +114,7 @@ int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargta /* special case: '--help' takes precedence over error reporting */ if ((argc < 2 && !allowEmptyExec) || ((struct arg_lit *)(ctx->argtable)[0])->count > 0) { // help must be the first record - if (ctx->programHint) - PrintAndLogEx(NORMAL, "\n"_DescriptionColor_("%s"), ctx->programHint); - - PrintAndLogEx(NORMAL, "\n"_SectionTagColor_("usage:")); - PrintAndLogEx(NORMAL, " "_CommandColor_("%s")NOLF, ctx->programName); - arg_print_syntax(stdout, ctx->argtable, "\n\n"); - - PrintAndLogEx(NORMAL, _SectionTagColor_("options:")); - - arg_print_glossary(stdout, ctx->argtable, " "_ArgColor_("%-30s")" "_ArgHelpColor_("%s")"\n"); - - PrintAndLogEx(NORMAL, ""); - if (ctx->programHelp) { - PrintAndLogEx(NORMAL, _SectionTagColor_("examples/notes:")); - char *buf = NULL; - int idx = 0; - buf = realloc(buf, strlen(ctx->programHelp) + 1); // more then enough as we are splitting - - char *p2; // pointer to split example from comment. - int egWidth = 30; - for (int i = 0; i <= strlen(ctx->programHelp); i++) { // <= so to get string terminator. - buf[idx++] = ctx->programHelp[i]; - if ((ctx->programHelp[i] == '\n') || (ctx->programHelp[i] == 0x00)) { - buf[idx - 1] = 0x00; - p2 = strstr(buf, "->"); // See if the example has a comment. - if (p2 != NULL) { - *(p2 - 1) = 0x00; - - if (strlen(buf) > 28) - egWidth = strlen(buf) + 5; - else - egWidth = 30; - - PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s")" %s", egWidth, buf, p2); - } else { - PrintAndLogEx(NORMAL, " "_ExampleColor_("%-*s"), egWidth, buf); - } - idx = 0; - } - } - - PrintAndLogEx(NORMAL, ""); - free(buf); - } - - fflush(stdout); + CLIParserPrintHelp(ctx); return 1; } diff --git a/client/deps/cliparser/cliparser.h b/client/deps/cliparser/cliparser.h index 0213d1917..39a5792f8 100644 --- a/client/deps/cliparser/cliparser.h +++ b/client/deps/cliparser/cliparser.h @@ -60,6 +60,7 @@ typedef struct { char buf[1024 + 60]; } CLIParserContext; int CLIParserInit(CLIParserContext **ctx, const char *vprogramName, const char *vprogramHint, const char *vprogramHelp); +void CLIParserPrintHelp(CLIParserContext *ctx); int CLIParserParseString(CLIParserContext *ctx, const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec); int CLIParserParseStringEx(CLIParserContext *ctx, const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData); int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargtable[], size_t vargtableLen, bool allowEmptyExec); diff --git a/client/src/cmdscript.c b/client/src/cmdscript.c index 9c8c794b9..184d9d695 100644 --- a/client/src/cmdscript.c +++ b/client/src/cmdscript.c @@ -237,30 +237,29 @@ static int CmdScriptRun(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "script run", "Run a Lua, Cmd or Python script", - "script run my_script.lua -- --my_script_args" + "script run my_script.lua --my_script_args" ); void *argtable[] = { arg_param_begin, arg_file1(NULL, NULL, "", "script to run"), - arg_rem("--", "separator for script params"), arg_strx0(NULL, NULL, "", "params for the script"), arg_param_end }; - CLIExecWithReturn(ctx, Cmd, argtable, true); char preferredName[128] = {0}; char arguments[256] = {0}; int name_len = 0; int arg_len = 0; static uint8_t luascriptfile_idx = 0; - CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)preferredName, sizeof(preferredName), &name_len); -// this one removes all spaces -// CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)arguments, sizeof(arguments), &arg_len); - CLIParserFree(ctx); - sscanf(Cmd + name_len + 1, "-- %255[^\n\r]%n", arguments, &arg_len); - if (arg_len == 0) { - sscanf(Cmd + name_len + 1, "%255[^\n\r]%n", arguments, &arg_len); + sscanf(Cmd, "%127s%n %255[^\n\r]%n", preferredName, &name_len, arguments, &arg_len); + if ((strcmp(preferredName, "-h") == 0) || (strcmp(preferredName, "--help") == 0)) { + ctx->argtable = argtable; + ctx->argtableLen = arg_getsize(argtable); + CLIParserPrintHelp(ctx); + CLIParserFree(ctx); + return PM3_ESOFT; } + CLIParserFree(ctx); if (strlen(preferredName) == 0) { PrintAndLogEx(FAILED, "no script name provided"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`script list`") " to see available scripts"); From a7ad668f8355cefa1445009e2261af72feec89f7 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 20 Apr 2021 10:50:24 +0200 Subject: [PATCH 372/373] script run help --- client/src/cmdscript.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/client/src/cmdscript.c b/client/src/cmdscript.c index 184d9d695..33e6e602d 100644 --- a/client/src/cmdscript.c +++ b/client/src/cmdscript.c @@ -236,13 +236,16 @@ static int CmdScriptList(const char *Cmd) { static int CmdScriptRun(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "script run", - "Run a Lua, Cmd or Python script", - "script run my_script.lua --my_script_args" + "Run a Lua, Cmd or Python script. " + "If no extension it will search for lua/cmd/py extensions\n" + "Use `script list` to see available scripts", + "script run my_script -h\n" ); + void *argtable[] = { arg_param_begin, - arg_file1(NULL, NULL, "", "script to run"), - arg_strx0(NULL, NULL, "", "params for the script"), + arg_file1(NULL, NULL, "", "name of script to run"), + arg_strx0(NULL, NULL, "", "script parameters"), arg_param_end }; @@ -252,7 +255,9 @@ static int CmdScriptRun(const char *Cmd) { int arg_len = 0; static uint8_t luascriptfile_idx = 0; sscanf(Cmd, "%127s%n %255[^\n\r]%n", preferredName, &name_len, arguments, &arg_len); - if ((strcmp(preferredName, "-h") == 0) || (strcmp(preferredName, "--help") == 0)) { + if ((strlen(preferredName) == 0) || + (strcmp(preferredName, "-h") == 0) || + (strcmp(preferredName, "--help") == 0)) { ctx->argtable = argtable; ctx->argtableLen = arg_getsize(argtable); CLIParserPrintHelp(ctx); @@ -260,11 +265,6 @@ static int CmdScriptRun(const char *Cmd) { return PM3_ESOFT; } CLIParserFree(ctx); - if (strlen(preferredName) == 0) { - PrintAndLogEx(FAILED, "no script name provided"); - PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`script list`") " to see available scripts"); - return PM3_EINVARG; - } char *extension_chk; extension_chk = str_dup(preferredName); str_lower(extension_chk); From 8172c708c3b34ba79b5c96d56e08ad21c466aec8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 20 Apr 2021 11:00:39 +0200 Subject: [PATCH 373/373] cppchecker and some renaming --- client/src/cmdscript.c | 56 ++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/client/src/cmdscript.c b/client/src/cmdscript.c index 33e6e602d..9b5f4e374 100644 --- a/client/src/cmdscript.c +++ b/client/src/cmdscript.c @@ -249,15 +249,20 @@ static int CmdScriptRun(const char *Cmd) { arg_param_end }; - char preferredName[128] = {0}; - char arguments[256] = {0}; - int name_len = 0; + int fnlen = 0; + char filename[128] = {0}; int arg_len = 0; - static uint8_t luascriptfile_idx = 0; - sscanf(Cmd, "%127s%n %255[^\n\r]%n", preferredName, &name_len, arguments, &arg_len); - if ((strlen(preferredName) == 0) || - (strcmp(preferredName, "-h") == 0) || - (strcmp(preferredName, "--help") == 0)) { + char arguments[256] = {0}; + + sscanf(Cmd, "%127s%n %255[^\n\r]%n", filename, &fnlen, arguments, &arg_len); + + // hack + // since we don't want to use "-f" for script filename, + // and be able to send in parameters into script meanwhile + // being able to "-h" here too. + if ((strlen(filename) == 0) || + (strcmp(filename, "-h") == 0) || + (strcmp(filename, "--help") == 0)) { ctx->argtable = argtable; ctx->argtableLen = arg_getsize(argtable); CLIParserPrintHelp(ctx); @@ -265,8 +270,10 @@ static int CmdScriptRun(const char *Cmd) { return PM3_ESOFT; } CLIParserFree(ctx); + + // try to detect a valid script file extention, case-insensitive char *extension_chk; - extension_chk = str_dup(preferredName); + extension_chk = str_dup(filename); str_lower(extension_chk); pm3_scriptfile_t ext = PM3_UNSPECIFIED; @@ -282,8 +289,9 @@ static int CmdScriptRun(const char *Cmd) { #endif free(extension_chk); + static uint8_t luascriptfile_idx = 0; char *script_path = NULL; - if (((ext == PM3_LUA) || (ext == PM3_UNSPECIFIED)) && (searchFile(&script_path, LUA_SCRIPTS_SUBDIR, preferredName, ".lua", true) == PM3_SUCCESS)) { + if (((ext == PM3_LUA) || (ext == PM3_UNSPECIFIED)) && (searchFile(&script_path, LUA_SCRIPTS_SUBDIR, filename, ".lua", true) == PM3_SUCCESS)) { int error; if (luascriptfile_idx == MAX_NESTED_LUASCRIPT) { PrintAndLogEx(ERR, "too many nested scripts, skipping %s\n", script_path); @@ -337,11 +345,11 @@ static int CmdScriptRun(const char *Cmd) { // close the Lua state lua_close(lua_state); luascriptfile_idx--; - PrintAndLogEx(SUCCESS, "\nfinished " _YELLOW_("%s"), preferredName); + PrintAndLogEx(SUCCESS, "\nfinished " _YELLOW_("%s"), filename); return PM3_SUCCESS; } - if (((ext == PM3_CMD) || (ext == PM3_UNSPECIFIED)) && (searchFile(&script_path, CMD_SCRIPTS_SUBDIR, preferredName, ".cmd", true) == PM3_SUCCESS)) { + if (((ext == PM3_CMD) || (ext == PM3_UNSPECIFIED)) && (searchFile(&script_path, CMD_SCRIPTS_SUBDIR, filename, ".cmd", true) == PM3_SUCCESS)) { PrintAndLogEx(SUCCESS, "executing Cmd " _YELLOW_("%s"), script_path); PrintAndLogEx(SUCCESS, "args " _YELLOW_("'%s'"), arguments); @@ -379,14 +387,14 @@ static int CmdScriptRun(const char *Cmd) { #ifdef HAVE_PYTHON - if (((ext == PM3_PY) || (ext == PM3_UNSPECIFIED)) && (searchFile(&script_path, PYTHON_SCRIPTS_SUBDIR, preferredName, ".py", true) == PM3_SUCCESS)) { + if (((ext == PM3_PY) || (ext == PM3_UNSPECIFIED)) && (searchFile(&script_path, PYTHON_SCRIPTS_SUBDIR, filename, ".py", true) == PM3_SUCCESS)) { PrintAndLogEx(SUCCESS, "executing python " _YELLOW_("%s"), script_path); PrintAndLogEx(SUCCESS, "args " _YELLOW_("'%s'"), arguments); - wchar_t *program = Py_DecodeLocale(preferredName, NULL); + wchar_t *program = Py_DecodeLocale(filename, NULL); if (program == NULL) { - PrintAndLogEx(ERR, "could not decode " _YELLOW_("%s"), preferredName); + PrintAndLogEx(ERR, "could not decode " _YELLOW_("%s"), filename); free(script_path); return PM3_ESOFT; } @@ -403,7 +411,7 @@ static int CmdScriptRun(const char *Cmd) { char *argv[128]; int argc = split(arguments, argv); wchar_t *py_args[argc]; - py_args[0] = Py_DecodeLocale(preferredName, NULL); + py_args[0] = Py_DecodeLocale(filename, NULL); for (int i = 0; i < argc; i++) { py_args[i + 1] = Py_DecodeLocale(argv[i], NULL); } @@ -424,15 +432,15 @@ static int CmdScriptRun(const char *Cmd) { free(script_path); return PM3_ESOFT; } - int ret = Pm3PyRun_SimpleFileNoExit(f, preferredName); + int ret = Pm3PyRun_SimpleFileNoExit(f, filename); Py_Finalize(); PyMem_RawFree(program); free(script_path); if (ret) { - PrintAndLogEx(WARNING, "\nfinished " _YELLOW_("%s") " with exception", preferredName); + PrintAndLogEx(WARNING, "\nfinished " _YELLOW_("%s") " with exception", filename); return PM3_ESOFT; } else { - PrintAndLogEx(SUCCESS, "\nfinished " _YELLOW_("%s"), preferredName); + PrintAndLogEx(SUCCESS, "\nfinished " _YELLOW_("%s"), filename); return PM3_SUCCESS; } } @@ -441,17 +449,17 @@ static int CmdScriptRun(const char *Cmd) { // file not found, let's search again to display the error messages int ret = PM3_EUNDEF; if (ext == PM3_LUA) - ret = searchFile(&script_path, LUA_SCRIPTS_SUBDIR, preferredName, ".lua", false); + ret = searchFile(&script_path, LUA_SCRIPTS_SUBDIR, filename, ".lua", false); else if (ext == PM3_CMD) - ret = searchFile(&script_path, CMD_SCRIPTS_SUBDIR, preferredName, ".cmd", false); + ret = searchFile(&script_path, CMD_SCRIPTS_SUBDIR, filename, ".cmd", false); #ifdef HAVE_PYTHON else if (ext == PM3_PY) - ret = searchFile(&script_path, PYTHON_SCRIPTS_SUBDIR, preferredName, ".py", false); + ret = searchFile(&script_path, PYTHON_SCRIPTS_SUBDIR, filename, ".py", false); else if (ext == PM3_UNSPECIFIED) - PrintAndLogEx(FAILED, "Error - can't find %s.[lua|cmd|py]", preferredName); + PrintAndLogEx(FAILED, "Error - can't find %s.[lua|cmd|py]", filename); #else else if (ext == PM3_UNSPECIFIED) - PrintAndLogEx(FAILED, "Error - can't find %s.[lua|cmd]", preferredName); + PrintAndLogEx(FAILED, "Error - can't find %s.[lua|cmd]", filename); #endif free(script_path); return ret;