diff --git a/CHANGELOG.md b/CHANGELOG.md index 1049fd0d0..b07ce95dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] - Add lf t55xx sniff to allow extracting commands and passwords used be cloners. (@mwalker33) - - Add options to `lf read` and `lf cmdread` (@doegox) + - Add options to `lf read`, `lf cmdread`, `lf sniff` for repeated acquisitions (@doegox) - Change options of `lf read` to match `lf cmdread`, this affects historical `d` and `s` options (@doegox) - Add `hf waveshare` to upload picture to Waveshare NFC-Powered e-Paper (@doegox) - Add `hf 14a config` to deal with badly configured cards: invalid ATQA/BCC/SAK (@doegox) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 184ac4090..6a315999c 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -786,8 +786,13 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_LF_SNIFF_RAW_ADC: { - uint32_t bits = SniffLF(); - reply_mix(CMD_ACK, bits, 0, 0, 0, 0); + struct p { + uint32_t samples : 31; + bool verbose : 1; + } PACKED; + struct p *payload = (struct p *)packet->data.asBytes; + uint32_t bits = SniffLF(payload->verbose, payload->samples); + reply_ng(CMD_LF_SNIFF_RAW_ADC, PM3_SUCCESS, (uint8_t *)&bits, sizeof(bits)); break; } case CMD_LF_HID_WATCH: { diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 91bde7569..2455a851e 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -397,9 +397,9 @@ uint32_t SampleLF(bool verbose, uint32_t sample_size) { * Initializes the FPGA for sniffer-mode (field off), and acquires the samples. * @return number of bits sampled **/ -uint32_t SniffLF(void) { +uint32_t SniffLF(bool verbose, uint32_t sample_size) { BigBuf_Clear_ext(false); - return ReadLF(false, true, 0); + return ReadLF(false, verbose, sample_size); } /** diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index f60324d70..d10f8279e 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -40,7 +40,7 @@ uint32_t SampleLF(bool verbose, uint32_t sample_size); * Initializes the FPGA for sniff-mode (field off), and acquires the samples. * @return number of bits sampled **/ -uint32_t SniffLF(void); +uint32_t SniffLF(bool verbose, uint32_t sample_size); uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, int16_t trigger_threshold, bool verbose, uint32_t sample_size, uint32_t cancel_after, int32_t samples_to_skip); diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index b6e63f06e..67042259c 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -124,12 +124,19 @@ static int usage_lf_sim(void) { } static int usage_lf_sniff(void) { PrintAndLogEx(NORMAL, "Sniff low frequence signal."); - PrintAndLogEx(NORMAL, "Usage: lf sniff [h]"); + PrintAndLogEx(NORMAL, "Usage: lf sniff [h] [q] [s #samples] [@]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " q silent (optional)"); + PrintAndLogEx(NORMAL, " s #samples number of samples to collect (optional)"); + PrintAndLogEx(NORMAL, " @ run continuously until a key is pressed (optional)"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf sniff"); + PrintAndLogEx(NORMAL, "- oscilloscope style:"); + PrintAndLogEx(NORMAL, " data plot"); + PrintAndLogEx(NORMAL, " lf sniff q s 3000 @"); PrintAndLogEx(NORMAL, "Extras:"); PrintAndLogEx(NORMAL, " use " _YELLOW_("'lf config'")" to set parameters."); - PrintAndLogEx(NORMAL, " use " _YELLOW_("'data samples'")" command to download from device"); PrintAndLogEx(NORMAL, " use " _YELLOW_("'data plot'")" to look at it"); return PM3_SUCCESS; } @@ -741,18 +748,81 @@ int CmdLFRead(const char *Cmd) { return ret; } +int lf_sniff(bool verbose, uint32_t samples) { + if (!session.pm3_present) return PM3_ENOTTY; + + struct p { + uint32_t samples : 31; + bool verbose : 1; + } PACKED; + + struct p payload; + payload.verbose = verbose; + payload.samples = samples; + + clearCommandBuffer(); + SendCommandNG(CMD_LF_SNIFF_RAW_ADC, (uint8_t *)&payload, sizeof(payload)); + PacketResponseNG resp; + if (g_lf_threshold_set) { + WaitForResponse(CMD_LF_SNIFF_RAW_ADC, &resp); + } else { + if (!WaitForResponseTimeout(CMD_LF_SNIFF_RAW_ADC, &resp, 2500)) { + PrintAndLogEx(WARNING, "(lf_read) command execution time out"); + return PM3_ETIMEOUT; + } + } + + // response is number of bits read + uint32_t size = (resp.data.asDwords[0] / 8); + getSamples(size, verbose); + return PM3_SUCCESS; +} + int CmdLFSniff(const char *Cmd) { if (!session.pm3_present) return PM3_ENOTTY; - uint8_t cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_lf_sniff(); + bool errors = false; + bool verbose = true; + bool continuous = false; + uint32_t samples = 0; + uint8_t cmdp = 0; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_lf_sniff(); + case 's': + samples = param_get32ex(Cmd, cmdp + 1, 0, 10); + cmdp += 2; + break; + case 'q': + verbose = false; + cmdp++; + break; + case '@': + continuous = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - clearCommandBuffer(); - SendCommandNG(CMD_LF_SNIFF_RAW_ADC, NULL, 0); - WaitForResponse(CMD_ACK, NULL); - getSamples(0, true); - return PM3_SUCCESS; + //Validations + if (errors) return usage_lf_sniff(); + if (continuous) { + PrintAndLogEx(INFO, "Press " _GREEN_("Enter") " to exit"); + } + int ret = PM3_SUCCESS; + do { + ret = lf_sniff(verbose, samples); + if (kbd_enter_pressed()) { + break; + } + } while (continuous); + return ret; } static void ChkBitstream(void) { diff --git a/client/src/cmdlf.h b/client/src/cmdlf.h index bb0628609..bcc695764 100644 --- a/client/src/cmdlf.h +++ b/client/src/cmdlf.h @@ -33,6 +33,7 @@ int CmdVchDemod(const char *Cmd); int CmdLFfind(const char *Cmd); int lf_read(bool verbose, uint32_t samples); +int lf_sniff(bool verbose, uint32_t samples); int lf_config(sample_config *config); int lf_getconfig(sample_config *config);