From 3d4207f3b673c479e572b960d5a307b1f73a912d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Aug 2016 09:12:16 +0200 Subject: [PATCH 01/16] syntax suger chg: added clearCommandBuffer(); before calls to sendcommand. --- client/cmdhw.c | 118 +++++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 58 deletions(-) diff --git a/client/cmdhw.c b/client/cmdhw.c index 11112118..b561c7d4 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -310,60 +310,66 @@ static void lookupChipID(uint32_t iChipID, uint32_t mem_used) int CmdDetectReader(const char *Cmd) { - UsbCommand c={CMD_LISTEN_READER_FIELD}; - // 'l' means LF - 125/134 kHz - if(*Cmd == 'l') { - c.arg[0] = 1; - } else if (*Cmd == 'h') { - c.arg[0] = 2; - } else if (*Cmd != '\0') { - PrintAndLog("use 'detectreader' or 'detectreader l' or 'detectreader h'"); - return 0; - } - SendCommand(&c); - return 0; + UsbCommand c = {CMD_LISTEN_READER_FIELD}; + // 'l' means LF - 125/134 kHz + if(*Cmd == 'l') { + c.arg[0] = 1; + } else if (*Cmd == 'h') { + c.arg[0] = 2; + } else if (*Cmd != '\0') { + PrintAndLog("use 'detectreader' or 'detectreader l' or 'detectreader h'"); + return 0; + } + clearCommandBuffer(); + SendCommand(&c); + return 0; } // ## FPGA Control int CmdFPGAOff(const char *Cmd) { - UsbCommand c = {CMD_FPGA_MAJOR_MODE_OFF}; - SendCommand(&c); - return 0; + UsbCommand c = {CMD_FPGA_MAJOR_MODE_OFF}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } int CmdLCD(const char *Cmd) { - int i, j; + int i, j; - UsbCommand c={CMD_LCD}; - sscanf(Cmd, "%x %d", &i, &j); - while (j--) { - c.arg[0] = i & 0x1ff; - SendCommand(&c); - } - return 0; + UsbCommand c = {CMD_LCD}; + sscanf(Cmd, "%x %d", &i, &j); + while (j--) { + c.arg[0] = i & 0x1ff; + clearCommandBuffer(); + SendCommand(&c); + } + return 0; } int CmdLCDReset(const char *Cmd) { - UsbCommand c = {CMD_LCD_RESET, {strtol(Cmd, NULL, 0), 0, 0}}; - SendCommand(&c); - return 0; + UsbCommand c = {CMD_LCD_RESET, {strtol(Cmd, NULL, 0), 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } int CmdReadmem(const char *Cmd) { - UsbCommand c = {CMD_READ_MEM, {strtol(Cmd, NULL, 0), 0, 0}}; - SendCommand(&c); - return 0; + UsbCommand c = {CMD_READ_MEM, {strtol(Cmd, NULL, 0), 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } int CmdReset(const char *Cmd) { - UsbCommand c = {CMD_HARDWARE_RESET}; - SendCommand(&c); - return 0; + UsbCommand c = {CMD_HARDWARE_RESET}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } /* @@ -372,30 +378,29 @@ int CmdReset(const char *Cmd) */ int CmdSetDivisor(const char *Cmd) { - UsbCommand c = {CMD_SET_LF_DIVISOR, {strtol(Cmd, NULL, 0), 0, 0}}; - if (c.arg[0] < 19 || c.arg[0] > 255) { - PrintAndLog("divisor must be between 19 and 255"); - } else { - SendCommand(&c); - PrintAndLog("Divisor set, expected freq=%dHz", 12000000 / (c.arg[0]+1)); - } - return 0; + UsbCommand c = {CMD_SET_LF_DIVISOR, {strtol(Cmd, NULL, 0), 0, 0}}; + + if (c.arg[0] < 19 || c.arg[0] > 255) { + PrintAndLog("divisor must be between 19 and 255"); + return 1; + } + + clearCommandBuffer(); + SendCommand(&c); + PrintAndLog("Divisor set, expected freq=%dHz", 12000000 / (c.arg[0]+1)); + return 0; } int CmdSetMux(const char *Cmd) { - UsbCommand c={CMD_SET_ADC_MUX}; - if (strcmp(Cmd, "lopkd") == 0) { - c.arg[0] = 0; - } else if (strcmp(Cmd, "loraw") == 0) { - c.arg[0] = 1; - } else if (strcmp(Cmd, "hipkd") == 0) { - c.arg[0] = 2; - } else if (strcmp(Cmd, "hiraw") == 0) { - c.arg[0] = 3; - } - SendCommand(&c); - return 0; + UsbCommand c = {CMD_SET_ADC_MUX}; + if (strcmp(Cmd, "lopkd") == 0) c.arg[0] = 0; + else if (strcmp(Cmd, "loraw") == 0) c.arg[0] = 1; + else if (strcmp(Cmd, "hipkd") == 0) c.arg[0] = 2; + else if (strcmp(Cmd, "hiraw") == 0) c.arg[0] = 3; + clearCommandBuffer(); + SendCommand(&c); + return 0; } int CmdTune(const char *Cmd) @@ -405,14 +410,13 @@ int CmdTune(const char *Cmd) int CmdVersion(const char *Cmd) { - clearCommandBuffer(); UsbCommand c = {CMD_VERSION}; static UsbCommand resp = {0, {0, 0, 0}}; if (resp.arg[0] == 0 && resp.arg[1] == 0) { // no cached information available SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { PrintAndLog("Prox/RFID mark3 RFID instrument"); PrintAndLog((char*)resp.d.asBytes); lookupChipID(resp.arg[0], resp.arg[1]); @@ -431,13 +435,11 @@ int CmdStatus(const char *Cmd) { uint8_t speed_test_buffer[USB_CMD_DATA_SIZE]; sample_buf = speed_test_buffer; - clearCommandBuffer(); UsbCommand c = {CMD_STATUS}; SendCommand(&c); - if (!WaitForResponseTimeout(CMD_ACK,&c,1900)) { + if (!WaitForResponseTimeout(CMD_ACK, &c, 1900)) PrintAndLog("Status command failed. USB Speed Test timed out"); - } return 0; } @@ -448,7 +450,7 @@ int CmdPing(const char *Cmd) UsbCommand resp; UsbCommand c = {CMD_PING}; SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) + if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) PrintAndLog("Ping successfull"); else PrintAndLog("Ping failed"); -- 2.39.5 From 10c4231ec76454eb691539fcb197d27585e1ef59 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Aug 2016 11:56:06 +0200 Subject: [PATCH 02/16] ADD: 'lf awid brute' is now possible to give a starting cardnumber. if given, the bruteforce loops from it as a mid point. Testing one step up, then one step down until it reaches 65535 and 0. CHG: 'lf awid brute' inputs are now changed, take notice to new format. --- client/cmdlfawid.c | 179 +++++++++++++++++++++++++++++---------------- 1 file changed, 116 insertions(+), 63 deletions(-) diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index 43f54a6f..676a18c1 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -29,13 +29,13 @@ int usage_lf_awid_fskdemod(void) { PrintAndLog("If the [1] option is provided, reader mode is exited after reading a single AWID card."); PrintAndLog(""); PrintAndLog("Usage: lf awid fskdemod [h] [1]"); - PrintAndLog("Options :"); + PrintAndLog("Options:"); PrintAndLog(" h : This help"); PrintAndLog(" 1 : (optional) stop after reading a single card"); PrintAndLog(""); - PrintAndLog("Samples"); - PrintAndLog(" lf awid fskdemod"); - PrintAndLog(" lf awid fskdemod 1"); + PrintAndLog("Samples:"); + PrintAndLog(" lf awid fskdemod"); + PrintAndLog(" lf awid fskdemod 1"); return 0; } @@ -44,13 +44,13 @@ int usage_lf_awid_sim(void) { PrintAndLog("Simulation runs until the button is pressed or another USB command is issued."); PrintAndLog(""); PrintAndLog("Usage: lf awid sim [h] "); - PrintAndLog("Options :"); + PrintAndLog("Options:"); PrintAndLog(" h : This help"); PrintAndLog(" : format length 26|50"); PrintAndLog(" : 8|16bit value facility code"); PrintAndLog(" : 16|32-bit value card number"); PrintAndLog(""); - PrintAndLog("Samples"); + PrintAndLog("Samples:"); PrintAndLog(" lf awid sim 26 224 1337"); PrintAndLog(" lf awid sim 50 2001 13371337"); return 0; @@ -61,14 +61,14 @@ int usage_lf_awid_clone(void) { PrintAndLog("The T55x7 must be on the antenna when issuing this command. T55x7 blocks are calculated and printed in the process."); PrintAndLog(""); PrintAndLog("Usage: lf awid clone [h] [Q5]"); - PrintAndLog("Options :"); + PrintAndLog("Options:"); PrintAndLog(" h : This help"); PrintAndLog(" : format length 26|50"); PrintAndLog(" : 8|16bit value facility code"); PrintAndLog(" : 16|32-bit value card number"); PrintAndLog(" Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip"); PrintAndLog(""); - PrintAndLog("Samples"); + PrintAndLog("Samples:"); PrintAndLog(" lf awid clone 26 224 1337"); PrintAndLog(" lf awid clone 50 2001 13371337"); return 0; @@ -76,21 +76,54 @@ int usage_lf_awid_clone(void) { int usage_lf_awid_brute(void){ PrintAndLog("Enables bruteforce of AWID reader with specified facility-code."); - PrintAndLog("This is a incremental attack against reader."); + PrintAndLog("This is a attack against reader. if cardnumber is given, it starts with it and goes up / down one step"); + PrintAndLog("if cardnumber is not given, it starts with 1 and goes up to 65535"); PrintAndLog(""); - PrintAndLog("Usage: lf awid brute [h] "); - PrintAndLog("Options :"); - PrintAndLog(" h : This help"); - PrintAndLog(" : format length 26|50"); - PrintAndLog(" : 8|16bit value facility code"); - PrintAndLog(" : delay betweens attempts in ms. Default 1000ms"); + PrintAndLog("Usage: lf awid brute [h] a f c d "); + PrintAndLog("Options:"); + PrintAndLog(" h : This help"); + PrintAndLog(" a : format length 26|50"); + PrintAndLog(" f : 8|16bit value facility code"); + PrintAndLog(" c : (optional) cardnumber to start with, max 65535"); + PrintAndLog(" d : delay betweens attempts in ms. Default 1000ms"); PrintAndLog(""); - PrintAndLog("Samples"); - PrintAndLog(" lf awid brute 26 224"); - PrintAndLog(" lf awid brute 50 2001 2000"); + PrintAndLog("Samples:"); + PrintAndLog(" lf awid brute a 26 f 224"); + PrintAndLog(" lf awid brute a 50 f 2001 d 2000"); + PrintAndLog(" lf awid brute a 50 f 2001 c 200 d 2000"); return 0; } +static boolean sendTry(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint32_t delay, uint8_t *bs, size_t bs_len){ + + PrintAndLog("Trying FC: %u; CN: %u", fc, cn); + if ( !getAWIDBits(fmtlen, fc, cn, bs)) { + PrintAndLog("Error with tag bitstream generation."); + return FALSE; + } + + uint64_t arg1 = (10<<8) + 8; // fcHigh = 10, fcLow = 8 + uint64_t arg2 = 50; // clk RF/50 invert=0 + UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, bs_len}}; + memcpy(c.d.asBytes, bs, bs_len); + clearCommandBuffer(); + SendCommand(&c); + msleep(delay); + return TRUE; +} +static int sendPing(){ + UsbCommand resp; + UsbCommand ping = {CMD_PING}; + clearCommandBuffer(); + SendCommand(&ping); + if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { + PrintAndLog("aborted via keyboard!"); + return 0; + } + PrintAndLog("Device didnt respond to ABORT"); + return 1; +} + int CmdAWIDDemodFSK(const char *Cmd) { int findone = 0; if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_awid_fskdemod(); @@ -269,80 +302,100 @@ int CmdAWIDClone(const char *Cmd) { int CmdAWIDBrute(const char *Cmd){ - uint32_t fc = 0, delay = 1000; + bool errors = false; + uint32_t fc = 0, cn = 0, delay = 1000; uint8_t fmtlen = 0; uint8_t bits[96]; uint8_t *bs = bits; size_t size = sizeof(bits); memset(bs, 0x00, size); - - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_awid_brute(); - - fmtlen = param_get8(Cmd, 0); - fc = param_get32ex(Cmd, 1, 0, 10); - if ( !fc ) return usage_lf_awid_brute(); - - // delay between attemps, defaults to 1000ms. - delay = param_get32ex(Cmd, 2, 1000, 10); + uint8_t cmdp = 0; + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch(param_getchar(Cmd, cmdp)) { + case 'h': + case 'H': + return usage_lf_awid_brute(); + case 'f': + case 'F': + fc = param_get32ex(Cmd ,cmdp+1, 0, 10); + if ( !fc ) + errors = true; + cmdp += 2; + break; + case 'd': + case 'D': + // delay between attemps, defaults to 1000ms. + delay = param_get32ex(Cmd, cmdp+1, 1000, 10); + cmdp += 2; + break; + case 'c': + case 'C': + cn = param_get32ex(Cmd, cmdp+1, 0, 10); + // truncate cardnumber. + cn &= 0xFFFF; + cmdp += 2; + break; + case 'a': + case 'A': + fmtlen = param_get8(Cmd, cmdp+1); + cmdp += 2; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + if ( fc == 0 )errors = true; + if ( errors ) return usage_lf_awid_brute(); + + // limit fc according to selected format switch(fmtlen) { case 50: if ((fc & 0xFFFF) != fc) { fc &= 0xFFFF; - PrintAndLog("Facility-Code Truncated to 16-bits (AWID50): %u", fc); + PrintAndLog("Facility-code truncated to 16-bits (AWID50): %u", fc); } break; default: if ((fc & 0xFF) != fc) { fc &= 0xFF; - PrintAndLog("Facility-Code Truncated to 8-bits (AWID26): %u", fc); + PrintAndLog("Facility-code truncated to 8-bits (AWID26): %u", fc); } break; } + // start + PrintAndLog("Bruteforceing AWID %d Reader", fmtlen); PrintAndLog("Press pm3-button to abort simulation or press key"); - uint64_t arg1 = (10<<8) + 8; // fcHigh = 10, fcLow = 8 - uint64_t arg2 = 50; // clk RF/50 invert=0 - UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}}; - - for ( uint16_t cn = 1; cn < 0xFFFF; ++cn){ - - if (ukbhit()) { - UsbCommand resp; - UsbCommand ping = {CMD_PING}; - clearCommandBuffer(); - SendCommand(&ping); - if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { - PrintAndLog("aborted via keyboard!"); - return 0; - } - PrintAndLog("Device didnt respond to ABORT"); - return 1; - } - - PrintAndLog("Trying FC: %u; CN: %u", fc, cn); - if ( !getAWIDBits(fmtlen, fc, cn, bs)) { - PrintAndLog("Error with tag bitstream generation."); - return 1; - } - memcpy(c.d.asBytes, bs, size); - clearCommandBuffer(); - SendCommand(&c); + uint16_t up = cn; + uint16_t down = cn; + + for (;;){ + + if (ukbhit()) return sendPing(); + + // Do one up + if ( up < 0xFFFF ) + if ( !sendTry(fmtlen, fc, up++, delay, bs, size)) return 1; - msleep(delay); + // Do one down (if cardnumber is given) + if ( cn > 1 ) + if ( down > 0 ) + if ( !sendTry(fmtlen, fc, --down, delay, bs, size)) return 1; } return 0; } static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"fskdemod", CmdAWIDDemodFSK, 0, "['1'] Realtime AWID FSK demodulator (option '1' for one tag only)"}, - {"sim", CmdAWIDSim, 0, " -- AWID tag simulator"}, - {"clone", CmdAWIDClone, 0, " -- Clone AWID to T55x7"}, - {"brute", CmdAWIDBrute, 0, " -- bruteforce card number given a FC"}, + {"fskdemod", CmdAWIDDemodFSK, 0, "Realtime AWID FSK demodulator"}, + {"sim", CmdAWIDSim, 0, "AWID tag simulator"}, + {"clone", CmdAWIDClone, 0, "Clone AWID to T55x7"}, + {"brute", CmdAWIDBrute, 0, "Bruteforce card number against reader"}, {NULL, NULL, 0, NULL} }; -- 2.39.5 From f5291a6ce16ef64ab9a4e022976bb2c3de90259b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Aug 2016 12:11:11 +0200 Subject: [PATCH 03/16] FIX: Travis CI complains about missing stdbool.h includes --- client/cmdlfawid.c | 12 +----------- client/cmdlfawid.h | 12 ++++++++++++ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index 676a18c1..e4155319 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -7,19 +7,9 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Low frequency AWID26 commands +// Low frequency AWID26/50 commands //----------------------------------------------------------------------------- - -#include // sscanf -#include "proxmark3.h" // Definitions, USB controls, etc -#include "ui.h" // PrintAndLog -#include "cmdparser.h" // CmdsParse, CmdsHelp #include "cmdlfawid.h" // AWID function declarations -#include "lfdemod.h" // parityTest -#include "util.h" // weigandparity -#include "protocols.h" // for T55xx config register definitions -#include "cmdmain.h" -#include "sleep.h" static int CmdHelp(const char *Cmd); diff --git a/client/cmdlfawid.h b/client/cmdlfawid.h index eeb052fd..d7859f3d 100644 --- a/client/cmdlfawid.h +++ b/client/cmdlfawid.h @@ -11,6 +11,18 @@ #ifndef CMDLFAWID_H__ #define CMDLFAWID_H__ +#include // sscanf +#include // bool +#include "proxmark3.h" // Definitions, USB controls, etc +#include "ui.h" // PrintAndLog +#include "cmdparser.h" // CmdsParse, CmdsHelp +#include "lfdemod.h" // parityTest +#include "util.h" // weigandparity +#include "protocols.h" // for T55xx config register definitions +#include "cmdmain.h" +#include "sleep.h" + + int CmdLFAWID(const char *Cmd); int CmdAWIDDemodFSK(const char *Cmd); int CmdAWIDSim(const char *Cmd); -- 2.39.5 From 05442fa6f7839d1817c1b480a99c733c74c1634d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Aug 2016 12:15:26 +0200 Subject: [PATCH 04/16] fix: wrong spelling --- client/cmdlfawid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index e4155319..a304cf7b 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -84,7 +84,7 @@ int usage_lf_awid_brute(void){ return 0; } -static boolean sendTry(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint32_t delay, uint8_t *bs, size_t bs_len){ +static bool sendTry(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint32_t delay, uint8_t *bs, size_t bs_len){ PrintAndLog("Trying FC: %u; CN: %u", fc, cn); if ( !getAWIDBits(fmtlen, fc, cn, bs)) { -- 2.39.5 From 59e933fc3f9c4283436b3b317b38c77db0e5d0a7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Aug 2016 23:11:07 +0200 Subject: [PATCH 05/16] started fixing the paritiy == 0 special attack against chinese clones with bad prng, which hasnt been working for ages. --- client/cmdhfmf.c | 8 +++--- client/nonce2key/crapto1.c | 20 ++++++--------- client/nonce2key/nonce2key.c | 49 ++++++++++++++++++++---------------- client/nonce2key/nonce2key.h | 6 ++--- 4 files changed, 42 insertions(+), 41 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index d6e39444..5465c4d4 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -213,9 +213,11 @@ start: } printf("\n"); - // par == 0 - if (isOK == -1 && par_list == 0) { - if (!nonce2key_ex(uid, nt, nr, ks_list, &r_key) ){ + // par == 0, and -4 + if (isOK == -4 && par_list == 0) { + // this special attack when parities is zero, uses checkkeys. Which now with block/keytype option also needs. + // but it uses 0|1 instead of 0x60|0x61... + if (!nonce2key_ex(blockNo, keytype - 0x60 , uid, nt, nr, ks_list, &r_key) ){ PrintAndLog("Found valid key: %012"llx" \n", r_key); goto END; } diff --git a/client/nonce2key/crapto1.c b/client/nonce2key/crapto1.c index c17cea7a..a0cd52fe 100644 --- a/client/nonce2key/crapto1.c +++ b/client/nonce2key/crapto1.c @@ -541,24 +541,18 @@ struct Crypto1State* lfsr_common_prefix_ex(uint32_t pfx, uint8_t ks[8]) goto out; } - // for(o = odd; *o + 1; ++o) - // for(e = even; *e + 1; ++e) - // for(top = 0; top < 64; ++top) { - // *o += 1 << 21; - // *e += (!(top & 7) + 1) << 21; - // s = check_pfx_parity_ex(pfx, *o, *e, s); - // } - for(o = odd; *o != -1; ++o) - for(e = even; *e != -1; ++e) + for(o = odd; *o + 1; ++o) + for(e = even; *e + 1; ++e) for(top = 0; top < 64; ++top) { - *o = (*o & 0x1fffff) | (top << 21); - *e = (*e & 0x1fffff) | (top >> 3) << 21; + *o += 1 << 21; + *e += (!(top & 7) + 1) << 21; s = check_pfx_parity_ex(pfx, *o, *e, s); } - s->odd = s->even = -1; + s->odd = s->even = 0; + out: free(odd); free(even); return statelist; -} +} \ No newline at end of file diff --git a/client/nonce2key/nonce2key.c b/client/nonce2key/nonce2key.c index d3fd2ed4..3a902ac5 100644 --- a/client/nonce2key/nonce2key.c +++ b/client/nonce2key/nonce2key.c @@ -45,7 +45,7 @@ int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_ clock_t t1 = clock(); state = lfsr_common_prefix(nr, rr, ks3x, par); - lfsr_rollback_word(state, uid^nt, 0); + lfsr_rollback_word(state, uid ^ nt, 0); crypto1_get_lfsr(state, key); crypto1_destroy(state); @@ -54,22 +54,32 @@ int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_ return 0; } -// call when PAR == 0, special attack? -int nonce2key_ex(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t ks_info, uint64_t * key) { +// call when PAR == 0, special attack? It seems to need two calls. with same uid, block, keytype +int nonce2key_ex(uint8_t blockno, uint8_t keytype, uint32_t uid, uint32_t nt, uint32_t nr, uint64_t ks_info, uint64_t * key) { + struct Crypto1State *state; uint32_t i, pos, key_count; byte_t ks3x[8]; uint64_t key_recovered; + int64_t *state_s; + static uint8_t last_blockno; + static uint8_t last_keytype; static uint32_t last_uid; static int64_t *last_keylist; - - if (last_uid != uid && last_keylist != NULL) { + + if (last_uid != uid && + last_blockno != blockno && + last_keytype != keytype && + last_keylist != NULL) + { free(last_keylist); last_keylist = NULL; } last_uid = uid; + last_blockno = blockno; + last_keytype = keytype; // Reset the last three significant bits of the reader nonce nr &= 0xffffff1f; @@ -80,25 +90,19 @@ int nonce2key_ex(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t ks_info, uint6 ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0f; } - PrintAndLog("parity is all zero,try special attack! just wait for few more seconds"); - - clock_t t1 = clock(); + PrintAndLog("parity is all zero, try special attack. Just wait for few more seconds..."); state = lfsr_common_prefix_ex(nr, ks3x); state_s = (int64_t*)state; + PrintAndLog("Prefix"); - //char filename[50] ; - //sprintf(filename, "nt_%08x_%d.txt", nt, nr); - //printf("name %s\n", filename); - //FILE* fp = fopen(filename,"w"); for (i = 0; (state) && ((state + i)->odd != -1); i++) { - lfsr_rollback_word(state+i, uid^nt, 0); + lfsr_rollback_word(state + i, uid ^ nt, 0); crypto1_get_lfsr(state + i, &key_recovered); *(state_s + i) = key_recovered; - //fprintf(fp, "%012llx\n",key_recovered); } - //fclose(fp); + PrintAndLog("zero"); if(!state) return 1; @@ -107,9 +111,12 @@ int nonce2key_ex(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t ks_info, uint6 //Create the intersection: if ( last_keylist != NULL) { + int64_t *p1, *p2, *p3; p1 = p3 = last_keylist; p2 = state_s; + + PrintAndLog("one"); while ( *p1 != -1 && *p2 != -1 ) { if (compar_int(p1, p2) == 0) { printf("p1:%"llx" p2:%"llx" p3:%"llx" key:%012"llx"\n",(uint64_t)(p1-last_keylist),(uint64_t)(p2-state_s),(uint64_t)(p3-last_keylist),*p1); @@ -129,24 +136,22 @@ int nonce2key_ex(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t ks_info, uint6 printf("key_count:%d\n", key_count); // The list may still contain several key candidates. Test each of them with mfCheckKeys - uint8_t keyBlock[6]; + uint8_t keyBlock[6] = {0,0,0,0,0,0}; uint64_t key64; + PrintAndLog("two"); for (i = 0; i < key_count; i++) { key64 = *(last_keylist + i); num_to_bytes(key64, 6, keyBlock); key64 = 0; - if (!mfCheckKeys(0, 0, TRUE, 1, keyBlock, &key64)) { //block 0,A, + if (!mfCheckKeys(blockno, keytype, false, 1, keyBlock, &key64)) { *key = key64; free(last_keylist); last_keylist = NULL; free(state); return 0; } - } - - t1 = clock() - t1; - if ( t1 > 0 ) PrintAndLog("Time in nonce2key_special: %.0f ticks \n", (float)t1); - + } + free(last_keylist); last_keylist = state_s; return 1; diff --git a/client/nonce2key/nonce2key.h b/client/nonce2key/nonce2key.h index 45bbcea0..e8e2a01b 100644 --- a/client/nonce2key/nonce2key.h +++ b/client/nonce2key/nonce2key.h @@ -18,13 +18,13 @@ #include #include "crapto1.h" #include "common.h" -#include "mifare.h" // nonces_t struct -#include "ui.h" +#include "mifare.h" // nonces_t struct +#include "ui.h" // PrintAndLog #include "proxmark3.h" #include "mifarehost.h" extern int nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t * key); -extern int nonce2key_ex(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t ks_info, uint64_t * key); +extern int nonce2key_ex(uint8_t blockno, uint8_t keytype, uint32_t uid, uint32_t nt, uint32_t nr, uint64_t ks_info, uint64_t * key); //iceman, added these to be able to crack key direct from "hf 14 sim" && "hf mf sim" bool tryMfk32(nonces_t data, uint64_t *outputkey ); -- 2.39.5 From 86db8973b025a3b22dde14c8fb7693a28d030c97 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Aug 2016 23:13:18 +0200 Subject: [PATCH 06/16] CHG; still looking at 14b, this time started to look at the tracelog times not working. --- armsrc/iso14443b.c | 81 +++++++++++++++++++++++++--------------------- client/cmdhf14b.c | 10 +++--- 2 files changed, 50 insertions(+), 41 deletions(-) diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index bfcf83c6..cc8cd65a 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -40,7 +40,7 @@ //#define SEND4STUFFBIT(x) ToSendStuffBit(x); // iceman, this threshold value, what makes 8 a good amplituted for this IQ values? #ifndef SUBCARRIER_DETECT_THRESHOLD -# define SUBCARRIER_DETECT_THRESHOLD 6 +# define SUBCARRIER_DETECT_THRESHOLD 8 #endif static void iso14b_set_timeout(uint32_t timeout); @@ -237,7 +237,7 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { * Card data transmission * - TR1 * - SOF - * - data (each bytes is: 1startbit,8bits, 1stopbit) + * - data (each bytes is: 1startbit, 8bits, 1stopbit) * - CRC_B * - EOF * @@ -280,13 +280,14 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { // Data bits b = cmd[i]; for(j = 0; j < 8; ++j) { - if(b & 1) { - SEND4STUFFBIT(1); - //ToSendStuffBit(1); - } else { - SEND4STUFFBIT(0); - //ToSendStuffBit(0); - } + // if(b & 1) { + // SEND4STUFFBIT(1); + // //ToSendStuffBit(1); + // } else { + // SEND4STUFFBIT(0); + // //ToSendStuffBit(0); + // } + SEND4STUFFBIT( b & 1 ); b >>= 1; } @@ -802,10 +803,9 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { case DEMOD_UNSYNCD: CHECK_FOR_SUBCARRIER(); - if (MF_DBGLEVEL >= 3) { Dbprintf("Demod.state = %d", v); } // subcarrier detected - if(v > SUBCARRIER_DETECT_THRESHOLD) { + if (v > SUBCARRIER_DETECT_THRESHOLD) { Demod.state = DEMOD_PHASE_REF_TRAINING; Demod.sumI = ci; Demod.sumQ = cq; @@ -814,7 +814,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { break; case DEMOD_PHASE_REF_TRAINING: - if(Demod.posCount < 8) { + if (Demod.posCount < 8) { CHECK_FOR_SUBCARRIER(); @@ -837,7 +837,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { MAKE_SOFT_DECISION(); - if(v < 0) { // logic '0' detected + if (v < 0) { // logic '0' detected Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF; Demod.posCount = 0; // start of SOF sequence } else { @@ -852,13 +852,13 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { MAKE_SOFT_DECISION(); - if(v > 0) { + if (v > 0) { // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges - if(Demod.posCount < 8*2) { + if (Demod.posCount < 8*2) { Demod.state = DEMOD_UNSYNCD; } else { LED_C_ON(); // Got SOF - Demod.startTime = GetCountSspClk(); + //Demod.startTime = GetCountSspClk(); Demod.state = DEMOD_AWAITING_START_BIT; Demod.posCount = 0; Demod.len = 0; @@ -904,7 +904,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { Demod.thisBit += v; Demod.shiftReg >>= 1; - // logic '1' + // OR in a logic '1' if (Demod.thisBit > 0) Demod.shiftReg |= 0x200; ++Demod.bitCount; @@ -923,7 +923,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { } else { // this one is a bit hard, either its a correc byte or its unsynced. Demod.state = DEMOD_UNSYNCD; - Demod.endTime = GetCountSspClk(); + //Demod.endTime = GetCountSspClk(); LED_C_OFF(); // This is EOF (start, stop and all data bits == '0' @@ -1018,7 +1018,7 @@ static void GetTagSamplesFor14443bDemod() { Dbhexdump(ISO14443B_DMA_BUFFER_SIZE, (uint8_t *)dmaBuf, FALSE); if ( Demod.len > 0 ) - LogTrace(Demod.output, Demod.len, Demod.startTime, Demod.endTime, NULL, FALSE); + LogTrace(Demod.output, Demod.len, time_0, time_stop, NULL, FALSE); } @@ -1075,8 +1075,7 @@ static void TransmitFor14443b_AsReader(void) { // Code a layer 2 command (string of octets, including CRC) into ToSend[], // so that it is ready to transmit to the tag using TransmitFor14443b(). //----------------------------------------------------------------------------- -static void CodeIso14443bAsReader(const uint8_t *cmd, int len) -{ +static void CodeIso14443bAsReader(const uint8_t *cmd, int len) { /* * Reader data transmission: * - no modulation ONES @@ -1112,14 +1111,24 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) ToSendStuffBit(0); // Data bits b = cmd[i]; - if ( b & 1 ) ToSendStuffBit(1); else ToSendStuffBit(0); - if ( (b>>1) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - if ( (b>>2) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - if ( (b>>3) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - if ( (b>>4) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - if ( (b>>5) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - if ( (b>>6) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - if ( (b>>7) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + // if ( b & 1 ) ToSendStuffBit(1); else ToSendStuffBit(0); + // if ( (b>>1) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + // if ( (b>>2) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + // if ( (b>>3) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + // if ( (b>>4) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + // if ( (b>>5) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + // if ( (b>>6) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + // if ( (b>>7) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + + ToSendStuffBit( b & 1); + ToSendStuffBit( (b>>1) & 1); + ToSendStuffBit( (b>>2) & 1); + ToSendStuffBit( (b>>3) & 1); + ToSendStuffBit( (b>>4) & 1); + ToSendStuffBit( (b>>5) & 1); + ToSendStuffBit( (b>>6) & 1); + ToSendStuffBit( (b>>7) & 1); + // Stop bit ToSendStuffBit(1); // EGT extra guard time @@ -1145,19 +1154,19 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) } -/** - Convenience function to encode, transmit and trace iso 14443b comms - **/ +/* +* Convenience function to encode, transmit and trace iso 14443b comms +*/ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) { + + uint32_t time_start = GetCountSspClk(); CodeIso14443bAsReader(cmd, len); - - uint32_t time_start = GetCountSspClk(); TransmitFor14443b_AsReader(); - + if(trigger) LED_A_ON(); - + LogTrace(cmd, len, time_start, GetCountSspClk()-time_start, NULL, TRUE); } diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index 9dfa9afe..471ac0f3 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -136,7 +136,7 @@ int CmdHF14BSnoop(const char *Cmd) { int CmdHF14BCmdRaw (const char *Cmd) { bool reply = TRUE, power = FALSE, select = FALSE; - char buf[5]=""; + char buf[5] = ""; int i = 0; uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; uint16_t datalen = 0; @@ -202,10 +202,10 @@ int CmdHF14BCmdRaw (const char *Cmd) { return 0; } - if(!power) + if (!power) flags |= ISO14B_DISCONNECT; - if(datalen>0) + if (datalen>0) flags |= ISO14B_RAW; // Max buffer is USB_CMD_DATA_SIZE @@ -249,7 +249,7 @@ static void print_atqb_resp(uint8_t *data, uint8_t cid){ if (BitRate & 0x04) PrintAndLog(" Bit Rate: 847 kbit/s PICC <- PCD supported"); if (BitRate & 0x80) PrintAndLog(" Same bit rate <-> required"); - uint16_t maxFrame = data[5]>>4; + uint16_t maxFrame = data[5] >> 4; if (maxFrame < 5) maxFrame = 8 * maxFrame + 16; else if (maxFrame == 5) maxFrame = 64; else if (maxFrame == 6) maxFrame = 96; @@ -257,7 +257,7 @@ static void print_atqb_resp(uint8_t *data, uint8_t cid){ else if (maxFrame == 8) maxFrame = 256; else maxFrame = 257; - PrintAndLog("Max Frame Size: %u%s bytes",maxFrame, (maxFrame == 257) ? "+ RFU" : ""); + PrintAndLog("Max Frame Size: %u%s bytes", maxFrame, (maxFrame == 257) ? "+ RFU" : ""); uint8_t protocolT = data[5] & 0xF; PrintAndLog(" Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4",(protocolT) ? "" : "not " ); -- 2.39.5 From 6067df30c59dc58dd4bb0bb922fd28087d3f58f9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 10 Aug 2016 10:55:29 +0200 Subject: [PATCH 07/16] FIX: at least now the special zero parity attack, repeats and doesn't crash. However it doesn't find the key either :( --- armsrc/iso14443a.c | 17 ++++++++++------- client/cmdhfmf.c | 7 ++++++- client/nonce2key/crapto1.c | 3 ++- client/nonce2key/nonce2key.c | 2 +- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index a2014079..642e8899 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -867,10 +867,10 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { uint8_t cardAUTHKEY = 0xff; // no authentication // allow collecting up to 8 sets of nonces to allow recovery of up to 8 keys #define ATTACK_KEY_COUNT 8 // keep same as define in cmdhfmf.c -> readerAttack() - nonces_t ar_nr_resp[ATTACK_KEY_COUNT*2]; //*2 for 2 separate attack types (nml, moebius) + nonces_t ar_nr_resp[ATTACK_KEY_COUNT*2]; // for 2 separate attack types (nml, moebius) memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp)); - uint8_t ar_nr_collected[ATTACK_KEY_COUNT*2]; //*2 for 2nd attack type (moebius) + uint8_t ar_nr_collected[ATTACK_KEY_COUNT*2]; // for 2nd attack type (moebius) memset(ar_nr_collected, 0x00, sizeof(ar_nr_collected)); uint8_t nonce1_count = 0; uint8_t nonce2_count = 0; @@ -2218,10 +2218,11 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { set_tracing(TRUE); iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); - - if (first_try) { - sync_time = GetCountSspClk() & 0xfffffff8; - sync_cycles = PRNG_SEQUENCE_LENGTH + 1130; //65536; //0x10000 // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). + sync_time = GetCountSspClk() & 0xfffffff8; + // iceman, i add 1130 because during my observations this makse the syncronization much fast to sync. + sync_cycles = PRNG_SEQUENCE_LENGTH + 1130; //65536; // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). + + if (first_try) { mf_nr_ar3 = 0; nt_attacked = 0; par_low = 0; @@ -2294,7 +2295,9 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { WDT_HIT(); LED_B_ON(); - if (first_try && previous_nt && !nt_attacked) { // we didn't calibrate our clock yet + // we didn't calibrate our clock yet, + // iceman: has to be calibrated every time. + if (previous_nt && !nt_attacked) { nt_distance = dist_nt(previous_nt, nt); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 5465c4d4..65c9dcb7 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -217,7 +217,12 @@ start: if (isOK == -4 && par_list == 0) { // this special attack when parities is zero, uses checkkeys. Which now with block/keytype option also needs. // but it uses 0|1 instead of 0x60|0x61... - if (!nonce2key_ex(blockNo, keytype - 0x60 , uid, nt, nr, ks_list, &r_key) ){ + if (nonce2key_ex(blockNo, keytype - 0x60 , uid, nt, nr, ks_list, &r_key) ){ + PrintAndLog("Key not found (lfsr_common_prefix list is null)."); + PrintAndLog("Failing is expected to happen in 25%% of all cases. Trying again with a different reader nonce..."); + c.arg[0] = false; + goto start; + } else { PrintAndLog("Found valid key: %012"llx" \n", r_key); goto END; } diff --git a/client/nonce2key/crapto1.c b/client/nonce2key/crapto1.c index a0cd52fe..b5532396 100644 --- a/client/nonce2key/crapto1.c +++ b/client/nonce2key/crapto1.c @@ -549,7 +549,8 @@ struct Crypto1State* lfsr_common_prefix_ex(uint32_t pfx, uint8_t ks[8]) s = check_pfx_parity_ex(pfx, *o, *e, s); } - s->odd = s->even = 0; + // in this version, -1 signifies end of states + s->odd = s->even = -1; out: free(odd); diff --git a/client/nonce2key/nonce2key.c b/client/nonce2key/nonce2key.c index 3a902ac5..ac2db645 100644 --- a/client/nonce2key/nonce2key.c +++ b/client/nonce2key/nonce2key.c @@ -94,7 +94,6 @@ int nonce2key_ex(uint8_t blockno, uint8_t keytype, uint32_t uid, uint32_t nt, ui state = lfsr_common_prefix_ex(nr, ks3x); state_s = (int64_t*)state; - PrintAndLog("Prefix"); for (i = 0; (state) && ((state + i)->odd != -1); i++) { lfsr_rollback_word(state + i, uid ^ nt, 0); @@ -152,6 +151,7 @@ int nonce2key_ex(uint8_t blockno, uint8_t keytype, uint32_t uid, uint32_t nt, ui } } + free(last_keylist); last_keylist = state_s; return 1; -- 2.39.5 From 56f1aaa234318f51b77cc4ce555bd7705056c882 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 10 Aug 2016 16:23:59 +0200 Subject: [PATCH 08/16] CHG: on a slow usb connection it seems the pingcmd which stops the bruteforce on deviceside doesnt get there. Lets send three pings to make sure the device gets it. --- client/cmdlfawid.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index a304cf7b..2334e3e3 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -104,8 +104,9 @@ static bool sendTry(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint32_t delay, ui static int sendPing(){ UsbCommand resp; UsbCommand ping = {CMD_PING}; - clearCommandBuffer(); - SendCommand(&ping); + clearCommandBuffer(); SendCommand(&ping); + clearCommandBuffer(); SendCommand(&ping); + clearCommandBuffer(); SendCommand(&ping); if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { PrintAndLog("aborted via keyboard!"); return 0; @@ -374,7 +375,7 @@ int CmdAWIDBrute(const char *Cmd){ // Do one down (if cardnumber is given) if ( cn > 1 ) - if ( down > 0 ) + if ( down > 1 ) if ( !sendTry(fmtlen, fc, --down, delay, bs, size)) return 1; } return 0; -- 2.39.5 From 823ad2e186601e91359de071ac303d3464ba39d1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 10 Aug 2016 16:24:49 +0200 Subject: [PATCH 09/16] CHG: minor code cleaning in 'hf 14a reader' --- client/cmdhf14a.c | 106 ++++++++++------------------------------------ 1 file changed, 22 insertions(+), 84 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 9f40e754..fe308746 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -179,6 +179,7 @@ int CmdHF14AList(const char *Cmd) { } int CmdHF14AReader(const char *Cmd) { + UsbCommand cDisconnect = {CMD_READER_ISO_14443a, {0,0,0}}; UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -192,22 +193,14 @@ int CmdHF14AReader(const char *Cmd) { if(select_status == 0) { if (Cmd[0] != 's') PrintAndLog("iso14443a card select failed"); - // disconnect - c.arg[0] = 0; - c.arg[1] = 0; - c.arg[2] = 0; - SendCommand(&c); + SendCommand(&cDisconnect); return 0; } if(select_status == 3) { PrintAndLog("Card doesn't support standard iso14443-3 anticollision"); PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - // disconnect - c.arg[0] = 0; - c.arg[1] = 0; - c.arg[2] = 0; - SendCommand(&c); + SendCommand(&cDisconnect); return 0; } @@ -218,13 +211,13 @@ int CmdHF14AReader(const char *Cmd) { switch (card.sak) { case 0x00: - //***************************************test**************** + // ******** is card of the MFU type (UL/ULC/NTAG/ etc etc) ul_switch_off_field(); uint32_t tagT = GetHF14AMfU_Type(); ul_print_type(tagT, 0); - //reconnect for further tests + // reconnect for further tests c.arg[0] = ISO14A_CONNECT | ISO14A_NO_DISCONNECT; c.arg[1] = 0; c.arg[2] = 0; @@ -233,7 +226,7 @@ int CmdHF14AReader(const char *Cmd) { SendCommand(&c); UsbCommand resp; - WaitForResponse(CMD_ACK,&resp); + WaitForResponse(CMD_ACK, &resp); memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); @@ -243,27 +236,6 @@ int CmdHF14AReader(const char *Cmd) { ul_switch_off_field(); return 0; } - - /* orig - // check if the tag answers to GETVERSION (0x60) - c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT; - c.arg[1] = 1; - c.arg[2] = 0; - c.d.asBytes[0] = 0x60; - SendCommand(&c); - WaitForResponse(CMD_ACK,&resp); - - uint8_t version[10] = {0}; - memcpy(version, resp.d.asBytes, resp.arg[0] < sizeof(version) ? resp.arg[0] : sizeof(version)); - uint8_t len = resp.arg[0] & 0xff; - switch ( len){ - // todo, identify "Magic UL-C tags". // they usually have a static nonce response to 0x1A command. - // UL-EV1, size, check version[6] == 0x0b (smaller) 0x0b * 4 == 48 - case 0x0A:PrintAndLog("TYPE : NXP MIFARE Ultralight EV1 %d bytes", (version[6] == 0xB) ? 48 : 128); break; - case 0x01:PrintAndLog("TYPE : NXP MIFARE Ultralight C");break; - case 0x00:PrintAndLog("TYPE : NXP MIFARE Ultralight");break; - } - */ break; case 0x01: PrintAndLog("TYPE : NXP TNP3xxx Activision Game Appliance"); break; case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break; @@ -379,59 +351,29 @@ int CmdHF14AReader(const char *Cmd) { PrintAndLog(" %02x -> Length is %d bytes", card.ats[pos + 1], card.ats[pos + 1]); switch (card.ats[pos + 2] & 0xf0) { - case 0x10: - PrintAndLog(" 1x -> MIFARE DESFire"); - break; - case 0x20: - PrintAndLog(" 2x -> MIFARE Plus"); - break; + case 0x10: PrintAndLog(" 1x -> MIFARE DESFire"); break; + case 0x20: PrintAndLog(" 2x -> MIFARE Plus"); break; } switch (card.ats[pos + 2] & 0x0f) { - case 0x00: - PrintAndLog(" x0 -> <1 kByte"); - break; - case 0x01: - PrintAndLog(" x1 -> 1 kByte"); - break; - case 0x02: - PrintAndLog(" x2 -> 2 kByte"); - break; - case 0x03: - PrintAndLog(" x3 -> 4 kByte"); - break; - case 0x04: - PrintAndLog(" x4 -> 8 kByte"); - break; + case 0x00: PrintAndLog(" x0 -> <1 kByte"); break; + case 0x01: PrintAndLog(" x1 -> 1 kByte"); break; + case 0x02: PrintAndLog(" x2 -> 2 kByte"); break; + case 0x03: PrintAndLog(" x3 -> 4 kByte"); break; + case 0x04: PrintAndLog(" x4 -> 8 kByte"); break; } switch (card.ats[pos + 3] & 0xf0) { - case 0x00: - PrintAndLog(" 0x -> Engineering sample"); - break; - case 0x20: - PrintAndLog(" 2x -> Released"); - break; + case 0x00: PrintAndLog(" 0x -> Engineering sample"); break; + case 0x20: PrintAndLog(" 2x -> Released"); break; } switch (card.ats[pos + 3] & 0x0f) { - case 0x00: - PrintAndLog(" x0 -> Generation 1"); - break; - case 0x01: - PrintAndLog(" x1 -> Generation 2"); - break; - case 0x02: - PrintAndLog(" x2 -> Generation 3"); - break; + case 0x00: PrintAndLog(" x0 -> Generation 1"); break; + case 0x01: PrintAndLog(" x1 -> Generation 2"); break; + case 0x02: PrintAndLog(" x2 -> Generation 3"); break; } switch (card.ats[pos + 4] & 0x0f) { - case 0x00: - PrintAndLog(" x0 -> Only VCSL supported"); - break; - case 0x01: - PrintAndLog(" x1 -> VCS, VCSL, and SVC supported"); - break; - case 0x0E: - PrintAndLog(" xE -> no VCS command supported"); - break; + case 0x00: PrintAndLog(" x0 -> Only VCSL supported"); break; + case 0x01: PrintAndLog(" x1 -> VCS, VCSL, and SVC supported"); break; + case 0x0E: PrintAndLog(" xE -> no VCS command supported"); break; } } } @@ -454,11 +396,7 @@ int CmdHF14AReader(const char *Cmd) { PrintAndLog("Answers to magic commands (GEN1): %s", (isOK ? "YES" : "NO") ); // disconnect - c.cmd = CMD_READER_ISO_14443a; - c.arg[0] = 0; - c.arg[1] = 0; - c.arg[2] = 0; - SendCommand(&c); + SendCommand(&cDisconnect); return select_status; } -- 2.39.5 From 31cf80487727e43b6a7e75416a4a1c25d2c4dc8c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 10 Aug 2016 16:25:56 +0200 Subject: [PATCH 10/16] CHG: removed some debug statements, added another. Change the crapto1.c, lets see if the special attack works better now against chinese clones. --- client/nonce2key/crapto1.c | 25 +++++++++++-------------- client/nonce2key/nonce2key.c | 8 +++----- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/client/nonce2key/crapto1.c b/client/nonce2key/crapto1.c index b5532396..9f349e17 100644 --- a/client/nonce2key/crapto1.c +++ b/client/nonce2key/crapto1.c @@ -1,4 +1,4 @@ -/* crapto1.c +1/* crapto1.c This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -383,7 +383,7 @@ uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) /** nonce_distance * x,y valid tag nonces, then prng_successor(x, nonce_distance(x, y)) = y */ -static uint16_t *dist; +static uint16_t *dist = 0; int nonce_distance(uint32_t from, uint32_t to) { uint16_t x, i; @@ -391,7 +391,7 @@ int nonce_distance(uint32_t from, uint32_t to) dist = malloc(2 << 16); if(!dist) return -1; - for (x = 1, i = 1; i; ++i) { + for (x = i = 1; i; ++i) { dist[(x & 0xff) << 8 | x >> 8] = i; x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; } @@ -468,21 +468,18 @@ static struct Crypto1State* check_pfx_parity(uint32_t prefix, uint32_t rresp, ui return sl + good; } static struct Crypto1State* check_pfx_parity_ex(uint32_t prefix, uint32_t odd, uint32_t even, struct Crypto1State* sl) { - struct Crypto1State s; + uint32_t c = 0; - s.odd = odd ^ fastfwd[1][c]; - s.even = even ^ fastfwd[0][c]; - - lfsr_rollback_bit(&s, 0, 0); - lfsr_rollback_bit(&s, 0, 0); - lfsr_rollback_bit(&s, 0, 0); + sl.odd = odd ^ fastfwd[1][c]; + sl.even = even ^ fastfwd[0][c]; - lfsr_rollback_word(&s, 0, 0); - lfsr_rollback_word(&s, prefix | c << 5, 1); + lfsr_rollback_bit(&sl, 0, 0); + lfsr_rollback_bit(&sl, 0, 0); + lfsr_rollback_bit(&sl, 0, 0); + lfsr_rollback_word(&sl, 0, 0); + lfsr_rollback_word(&sl, prefix | c << 5, 1); - sl->odd = s.odd; - sl->even = s.even; return ++sl; } diff --git a/client/nonce2key/nonce2key.c b/client/nonce2key/nonce2key.c index ac2db645..ab97f597 100644 --- a/client/nonce2key/nonce2key.c +++ b/client/nonce2key/nonce2key.c @@ -101,7 +101,6 @@ int nonce2key_ex(uint8_t blockno, uint8_t keytype, uint32_t uid, uint32_t nt, ui *(state_s + i) = key_recovered; } - PrintAndLog("zero"); if(!state) return 1; @@ -115,7 +114,6 @@ int nonce2key_ex(uint8_t blockno, uint8_t keytype, uint32_t uid, uint32_t nt, ui p1 = p3 = last_keylist; p2 = state_s; - PrintAndLog("one"); while ( *p1 != -1 && *p2 != -1 ) { if (compar_int(p1, p2) == 0) { printf("p1:%"llx" p2:%"llx" p3:%"llx" key:%012"llx"\n",(uint64_t)(p1-last_keylist),(uint64_t)(p2-state_s),(uint64_t)(p3-last_keylist),*p1); @@ -127,9 +125,11 @@ int nonce2key_ex(uint8_t blockno, uint8_t keytype, uint32_t uid, uint32_t nt, ui while (compar_int(p1, p2) == 1) ++p2; } } - key_count = p3 - last_keylist;; + key_count = p3 - last_keylist; + PrintAndLog("one A"); } else { key_count = 0; + PrintAndLog("one B"); } printf("key_count:%d\n", key_count); @@ -137,7 +137,6 @@ int nonce2key_ex(uint8_t blockno, uint8_t keytype, uint32_t uid, uint32_t nt, ui // The list may still contain several key candidates. Test each of them with mfCheckKeys uint8_t keyBlock[6] = {0,0,0,0,0,0}; uint64_t key64; - PrintAndLog("two"); for (i = 0; i < key_count; i++) { key64 = *(last_keylist + i); num_to_bytes(key64, 6, keyBlock); @@ -151,7 +150,6 @@ int nonce2key_ex(uint8_t blockno, uint8_t keytype, uint32_t uid, uint32_t nt, ui } } - free(last_keylist); last_keylist = state_s; return 1; -- 2.39.5 From 4ab54914e3e9e24f1d04694ea0d8926c576cf905 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 10 Aug 2016 16:28:23 +0200 Subject: [PATCH 11/16] CHG: more struct errors.. my bad, --- client/nonce2key/crapto1.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/client/nonce2key/crapto1.c b/client/nonce2key/crapto1.c index 9f349e17..6980909c 100644 --- a/client/nonce2key/crapto1.c +++ b/client/nonce2key/crapto1.c @@ -471,14 +471,14 @@ static struct Crypto1State* check_pfx_parity_ex(uint32_t prefix, uint32_t odd, u uint32_t c = 0; - sl.odd = odd ^ fastfwd[1][c]; - sl.even = even ^ fastfwd[0][c]; + sl->odd = odd ^ fastfwd[1][c]; + sl->even = even ^ fastfwd[0][c]; - lfsr_rollback_bit(&sl, 0, 0); - lfsr_rollback_bit(&sl, 0, 0); - lfsr_rollback_bit(&sl, 0, 0); - lfsr_rollback_word(&sl, 0, 0); - lfsr_rollback_word(&sl, prefix | c << 5, 1); + lfsr_rollback_bit(sl, 0, 0); + lfsr_rollback_bit(sl, 0, 0); + lfsr_rollback_bit(sl, 0, 0); + lfsr_rollback_word(sl, 0, 0); + lfsr_rollback_word(sl, prefix | c << 5, 1); return ++sl; } -- 2.39.5 From 2b6ffe75a83baea2c4c1c8d032fd4c82f248555d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 10 Aug 2016 16:29:23 +0200 Subject: [PATCH 12/16] chg: remove a char.. --- client/nonce2key/crapto1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/nonce2key/crapto1.c b/client/nonce2key/crapto1.c index 6980909c..9f6f7f6b 100644 --- a/client/nonce2key/crapto1.c +++ b/client/nonce2key/crapto1.c @@ -1,4 +1,4 @@ -1/* crapto1.c +/* crapto1.c This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License -- 2.39.5 From 7e08450dcc111649b2f0d32bf9882ece522ea271 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 14 Aug 2016 16:29:39 +0200 Subject: [PATCH 13/16] add: annotage Mifare Desfire. from https://github.com/JohannesStoye/proxmark3/commit/3102c1bae358566e112e465e58da27ffb7219bc9#diff-93cfa90a992ea759349344d0de98029e Thanks @johannesStoye --- client/cmdhf.c | 93 ++++++++++++++++++++++++++++++++++++++++++++-- common/protocols.h | 39 +++++++++++++++++++ 2 files changed, 128 insertions(+), 4 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index e1a203e7..0cbca751 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -38,7 +38,7 @@ int CmdHFTune(const char *Cmd) { } -void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) +int applyIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { switch(cmd[0]) { @@ -121,9 +121,13 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) case MIFARE_ULEV1_READSIG : snprintf(exp,size,"READ_SIG"); break; case MIFARE_ULEV1_CHECKTEAR : snprintf(exp,size,"CHK_TEARING(%d)",cmd[1]); break; case MIFARE_ULEV1_VCSL : snprintf(exp,size,"VCSL"); break; - default: snprintf(exp,size,"?"); break; + default: return 0; } - return; + return 1; +} + +void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ + applyIso14443a(exp, size, cmd, cmdsize); } void annotateIclass(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) @@ -253,6 +257,83 @@ void annotateIso7816(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ } } +// MIFARE DESFire +void annotateMfDesfire(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ + + // it's basically a ISO14443a tag, so try annotation from there + if (!applyIso14443a(exp, size, cmd, cmdsize)){ + //PrintAndLog("rest"); + //PrintAndLog("(%d)",cmd[0]); + // S-block 11xxx010 + if ( (cmd[0] & 0xC0) && (cmdsize == 3) ) { + switch ( (cmd[0] & 0x30) ) { + case 0x30 : snprintf(exp, size, "S-block DESELECT"); break; + case 0x00 : snprintf(exp, size, "S-block WTX"); break; + default : snprintf(exp, size, "S-block"); break; + } + } + // R-block (ack) 101xx01x + else if ( ((cmd[0] & 0xB0) == 0xA0) && ( cmdsize > 2) ) { + if ( (cmd[0] & 0x10) == 0 ) + snprintf(exp, size, "R-block ACK(%d)", (cmd[0] & 0x01)); + else + snprintf(exp, size, "R-block NACK(%d)", (cmd[0] & 0x01)); + } + // I-block 000xCN1x + else if ( (cmd[0] & 0xC0) == 0x00){ + // PCB [CID] [NAD] [INF] CRC CRC + int pos = 1; + if ( (cmd[0] & 0x08) == 0x08) // cid byte following + pos = pos + 1; + if ( (cmd[0] & 0x04) == 0x04) // nad byte following + pos = pos + 1; + //PrintAndLog("[%d]",pos); + switch ( cmd[pos] ){ + case MFDES_CREATE_APPLICATION :snprintf(exp, size, "CREATE APPLICATION");break; + case MFDES_DELETE_APPLICATION :snprintf(exp, size, "DELETE APPLICATION");break; + case MFDES_GET_APPLICATION_IDS :snprintf(exp, size, "GET APPLICATION IDS");break; + case MFDES_SELECT_APPLICATION :snprintf(exp, size, "SELECT APPLICATION");break; + case MFDES_FORMAT_PICC :snprintf(exp, size, "FORMAT PICC");break; + case MFDES_GET_VERSION :snprintf(exp, size, "GET VERSION");break; + case MFDES_READ_DATA :snprintf(exp, size, "READ DATA");break; + case MFDES_WRITE_DATA :snprintf(exp, size, "WRITE DATA");break; + case MFDES_GET_VALUE :snprintf(exp, size, "GET VALUE");break; + case MFDES_CREDIT :snprintf(exp, size, "CREDIT");break; + case MFDES_DEBIT :snprintf(exp, size, "DEBIT");break; + case MFDES_LIMITED_CREDIT :snprintf(exp, size, "LIMITED CREDIT");break; + case MFDES_WRITE_RECORD :snprintf(exp, size, "WRITE RECORD");break; + case MFDES_READ_RECORDS :snprintf(exp, size, "READ RECORDS");break; + case MFDES_CLEAR_RECORD_FILE :snprintf(exp, size, "CLEAR RECORD FILE");break; + case MFDES_COMMIT_TRANSACTION :snprintf(exp, size, "COMMIT TRANSACTION");break; + case MFDES_ABORT_TRANSACTION :snprintf(exp, size, "ABORT TRANSACTION");break; + case MFDES_GET_FREE_MEMORY :snprintf(exp, size, "GET FREE MEMORY");break; + case MFDES_GET_FILE_IDS :snprintf(exp, size, "GET FILE IDS");break; + case MFDES_GET_ISOFILE_IDS :snprintf(exp, size, "GET ISOFILE IDS");break; + case MFDES_GET_FILE_SETTINGS :snprintf(exp, size, "GET FILE SETTINGS");break; + case MFDES_CHANGE_FILE_SETTINGS :snprintf(exp, size, "CHANGE FILE SETTINGS");break; + case MFDES_CREATE_STD_DATA_FILE :snprintf(exp, size, "CREATE STD DATA FILE");break; + case MFDES_CREATE_BACKUP_DATA_FILE :snprintf(exp, size, "CREATE BACKUP DATA FILE");break; + case MFDES_CREATE_VALUE_FILE :snprintf(exp, size, "CREATE VALUE FILE");break; + case MFDES_CREATE_LINEAR_RECORD_FILE :snprintf(exp, size, "CREATE LINEAR RECORD FILE");break; + case MFDES_CREATE_CYCLIC_RECORD_FILE :snprintf(exp, size, "CREATE CYCLIC RECORD FILE");break; + case MFDES_DELETE_FILE :snprintf(exp, size, "DELETE FILE");break; + case MFDES_AUTHENTICATE :snprintf(exp, size, "AUTH NATIVE (keyNo %d)", cmd[pos+1]);break; // AUTHENTICATE_NATIVE + case MFDES_AUTHENTICATE_ISO :snprintf(exp, size, "AUTH ISO (keyNo %d)", cmd[pos+1]);break; // AUTHENTICATE_STANDARD + case MFDES_AUTHENTICATE_AES :snprintf(exp, size, "AUTH AES (keyNo %d)", cmd[pos+1]);break; + case MFDES_CHANGE_KEY_SETTINGS :snprintf(exp, size, "CHANGE KEY SETTINGS");break; + case MFDES_GET_KEY_SETTINGS :snprintf(exp, size, "GET KEY SETTINGS");break; + case MFDES_CHANGE_KEY :snprintf(exp, size, "CHANGE KEY");break; + case MFDES_GET_KEY_VERSION :snprintf(exp, size, "GET KEY VERSION");break; + case MFDES_AUTHENTICATION_FRAME :snprintf(exp, size, "AUTH FRAME / NEXT FRAME");break; + default :break; + } + }else{ + // anything else + snprintf(exp,size,"?"); + } + } +} + /** 06 00 = INITIATE 0E xx = SELECT ID (xx = Chip-ID) @@ -520,6 +601,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui crcStatus = iso14443B_CRC_check(isResponse, frame, data_len); break; case ISO_14443A: + case MFDES: crcStatus = iso14443A_CRC_check(isResponse, frame, data_len); break; default: @@ -575,6 +657,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui switch(protocol) { case ICLASS: annotateIclass(explanation,sizeof(explanation),frame,data_len); break; case ISO_14443A: annotateIso14443a(explanation,sizeof(explanation),frame,data_len); break; + case MFDES: annotateMfDesfire(explanation,sizeof(explanation),frame,data_len); break; case ISO_14443B: annotateIso14443b(explanation,sizeof(explanation),frame,data_len); break; case TOPAZ: annotateTopaz(explanation,sizeof(explanation),frame,data_len); break; case ISO_7816_4: annotateIso7816(explanation,sizeof(explanation),frame,data_len); break; @@ -623,6 +706,7 @@ int usage_hf_list(){ PrintAndLog(" raw - just show raw data without annotations"); PrintAndLog(" 14a - interpret data as iso14443a communications"); PrintAndLog(" 14b - interpret data as iso14443b communications"); + PrintAndLog(" des - interpret data as DESFire communications"); PrintAndLog(" iclass - interpret data as iclass communications"); PrintAndLog(" topaz - interpret data as topaz communications"); PrintAndLog(" 7816 - interpret data as iso7816-4 communications"); @@ -685,7 +769,8 @@ int CmdHFList(const char *Cmd) else if(strcmp(type, "14a") == 0) protocol = ISO_14443A; else if(strcmp(type, "14b") == 0) protocol = ISO_14443B; else if(strcmp(type, "topaz")== 0) protocol = TOPAZ; - else if(strcmp(type, "7816")== 0) protocol = ISO_7816_4; + else if(strcmp(type, "7816")== 0) protocol = ISO_7816_4; + else if(strcmp(type,"des")== 0) protocol = MFDES; else if(strcmp(type, "raw")== 0) protocol = -1;//No crc, no annotations else errors = true; diff --git a/common/protocols.h b/common/protocols.h index ba3a9a90..b47a2ae2 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -251,6 +251,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define ISO_14443B 2 #define TOPAZ 3 #define ISO_7816_4 4 +#define MFDES 5 //-- Picopass fuses #define FUSE_FPERS 0x80 @@ -284,6 +285,44 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define ISO7816_OK 0x9000 // 6x xx = ERROR +// MIFARE DESFire command set: +#define MFDES_CREATE_APPLICATION 0xca +#define MFDES_DELETE_APPLICATION 0xda +#define MFDES_GET_APPLICATION_IDS 0x6a +#define MFDES_SELECT_APPLICATION 0x5a +#define MFDES_FORMAT_PICC 0xfc +#define MFDES_GET_VERSION 0x60 +#define MFDES_READ_DATA 0xbd +#define MFDES_WRITE_DATA 0x3d +#define MFDES_GET_VALUE 0x6c +#define MFDES_CREDIT 0x0c +#define MFDES_DEBIT 0xdc +#define MFDES_LIMITED_CREDIT 0x1c +#define MFDES_WRITE_RECORD 0x3b +#define MFDES_READ_RECORDS 0xbb +#define MFDES_CLEAR_RECORD_FILE 0xeb +#define MFDES_COMMIT_TRANSACTION 0xc7 +#define MFDES_ABORT_TRANSACTION 0xa7 +#define MFDES_GET_FREE_MEMORY 0x6e +#define MFDES_GET_FILE_IDS 0x6f +#define MFDES_GET_ISOFILE_IDS 0x61 +#define MFDES_GET_FILE_SETTINGS 0xf5 +#define MFDES_CHANGE_FILE_SETTINGS 0x5f +#define MFDES_CREATE_STD_DATA_FILE 0xcd +#define MFDES_CREATE_BACKUP_DATA_FILE 0xcb +#define MFDES_CREATE_VALUE_FILE 0xcc +#define MFDES_CREATE_LINEAR_RECORD_FILE 0xc1 +#define MFDES_CREATE_CYCLIC_RECORD_FILE 0xc0 +#define MFDES_DELETE_FILE 0xdf +#define MFDES_AUTHENTICATE 0x0a // AUTHENTICATE_NATIVE +#define MFDES_AUTHENTICATE_ISO 0x1a // AUTHENTICATE_STANDARD +#define MFDES_AUTHENTICATE_AES 0xaa +#define MFDES_CHANGE_KEY_SETTINGS 0x54 +#define MFDES_GET_KEY_SETTINGS 0x45 +#define MFDES_CHANGE_KEY 0xc4 +#define MFDES_GET_KEY_VERSION 0x64 +#define MFDES_AUTHENTICATION_FRAME 0xAF + void printIclassDumpInfo(uint8_t* iclass_dump); void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb); -- 2.39.5 From ab74872d40cf1f6b91344909e307ae788a3f8497 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 14 Aug 2016 17:04:40 +0200 Subject: [PATCH 14/16] ADD: added a sanity check in T55x7 commands info/trace/detect against useing the commands when device is in offline but user didn't use '1' in arguments. --- client/cmdlft55xx.c | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 6ddd84b1..f0a6fe94 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -456,6 +456,14 @@ bool DecodeT5555TraceBlock() { return (bool) ASKDemod("64 0 1", FALSE, FALSE, 1); } +// sanity check. Don't use proxmark if it is offline and you didn't specify useGraphbuf +static int SanityOfflineCheck( bool useGraphBuffer ){ + if ( !useGraphBuffer && offline) { + PrintAndLog("Your proxmark3 device is offline. Specify [1] to use graphbuffer data instead"); + return 0; + } + return 1; +} int CmdT55xxDetect(const char *Cmd){ bool errors = FALSE; @@ -488,15 +496,18 @@ int CmdT55xxDetect(const char *Cmd){ } if (errors) return usage_t55xx_detect(); + // sanity check. + if (!SanityOfflineCheck(useGB)) return 1; + if ( !useGB) { if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password) ) - return 0; + return 1; } if ( !tryDetectModulation() ) PrintAndLog("Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'"); - return 1; + return 0; } // detect configuration? @@ -985,17 +996,21 @@ int CmdT55xxReadTrace(const char *Cmd) { uint32_t password = 0; if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') return usage_t55xx_trace(); - if (strlen(Cmd)==0) + if (strlen(Cmd)==0) { + // sanity check. + if (!SanityOfflineCheck(FALSE)) return 1; + if ( !AquireData( T55x7_PAGE1, REGULAR_READ_MODE_BLOCK, pwdmode, password ) ) - return 0; + return 1; + } if ( config.Q5 ){ - if (!DecodeT5555TraceBlock()) return 0; + if (!DecodeT5555TraceBlock()) return 1; } else { - if (!DecodeT55xxBlock()) return 0; + if (!DecodeT55xxBlock()) return 1; } - if ( !DemodBufferLen ) return 0; + if ( !DemodBufferLen ) return 1; RepaintGraphWindow(); uint8_t repeat = (config.offset > 5) ? 32 : 0; @@ -1009,7 +1024,7 @@ int CmdT55xxReadTrace(const char *Cmd) { if (hdr != 0x1FF) { PrintAndLog("Invalid Q5 Trace data header (expected 0x1FF, found %X)", hdr); - return 0; + return 1; } t5555_tracedata_t data = {.bl1 = bl1, .bl2 = bl2, .icr = 0, .lotidc = '?', .lotid = 0, .wafer = 0, .dw =0}; @@ -1048,7 +1063,7 @@ int CmdT55xxReadTrace(const char *Cmd) { data.acl = PackBits(si, 8, DemodBuffer); si += 8; if ( data.acl != 0xE0 ) { PrintAndLog("The modulation is most likely wrong since the ACL is not 0xE0. "); - return 0; + return 1; } data.mfc = PackBits(si, 8, DemodBuffer); si += 8; @@ -1148,9 +1163,13 @@ int CmdT55xxInfo(const char *Cmd){ if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') return usage_t55xx_info(); - if (strlen(Cmd)==0) + if (strlen(Cmd)==0){ + // sanity check. + if (!SanityOfflineCheck(FALSE)) return 1; + if ( !AquireData( T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, pwdmode, password ) ) return 1; + } if (!DecodeT55xxBlock()) return 1; @@ -1656,7 +1675,7 @@ done: static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"bruteforce",CmdT55xxBruteForce,0, " [i <*.dic>] Simple bruteforce attack to find password"}, + {"bruteforce", CmdT55xxBruteForce,0, " [i <*.dic>] Simple bruteforce attack to find password"}, {"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"}, {"detect", CmdT55xxDetect, 1, "[1] Try detecting the tag modulation from reading the configuration block."}, {"dump", CmdT55xxDump, 0, "[password] [o] Dump T55xx card block 0-7. Optional [password], [override]"}, -- 2.39.5 From f2abf6732bbcd63a21cbd24975e416366f25e667 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 14 Aug 2016 17:11:42 +0200 Subject: [PATCH 15/16] help text adjustments --- client/cmdlft55xx.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index f0a6fe94..f8865c8d 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -42,13 +42,13 @@ void Set_t55xx_Config(t55xx_conf_block_t conf){ int usage_t55xx_config(){ PrintAndLog("Usage: lf t55xx config [d ] [i 1] [o ] [Q5]"); PrintAndLog("Options:"); - PrintAndLog(" h This help"); - PrintAndLog(" b <8|16|32|40|50|64|100|128> Set bitrate"); - PrintAndLog(" d Set demodulation FSK / ASK / PSK / NRZ / Biphase / Biphase A"); - PrintAndLog(" i [1] Invert data signal, defaults to normal"); - PrintAndLog(" o [offset] Set offset, where data should start decode in bitstream"); - PrintAndLog(" Q5 Set as Q5(T5555) chip instead of T55x7"); - PrintAndLog(" ST Set Sequence Terminator on"); + PrintAndLog(" h - This help"); + PrintAndLog(" b <8|16|32|40|50|64|100|128> - Set bitrate"); + PrintAndLog(" d - Set demodulation FSK / ASK / PSK / NRZ / Biphase / Biphase A"); + PrintAndLog(" i [1] - Invert data signal, defaults to normal"); + PrintAndLog(" o [offset] - Set offset, where data should start decode in bitstream"); + PrintAndLog(" Q5 - Set as Q5(T5555) chip instead of T55x7"); + PrintAndLog(" ST - Set Sequence Terminator on"); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx config d FSK - FSK demodulation"); @@ -92,7 +92,7 @@ int usage_t55xx_write(){ int usage_t55xx_trace() { PrintAndLog("Usage: lf t55xx trace [1]"); PrintAndLog("Options:"); - PrintAndLog(" [graph buffer data] - if set, use Graphbuffer otherwise read data from tag."); + PrintAndLog(" 1 - if set, use Graphbuffer otherwise read data from tag."); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx trace"); @@ -103,7 +103,7 @@ int usage_t55xx_trace() { int usage_t55xx_info() { PrintAndLog("Usage: lf t55xx info [1]"); PrintAndLog("Options:"); - PrintAndLog(" [graph buffer data] - if set, use Graphbuffer otherwise read data from tag."); + PrintAndLog(" 1 - if set, use Graphbuffer otherwise read data from tag."); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx info"); @@ -150,7 +150,7 @@ int usage_t55xx_wakup(){ int usage_t55xx_bruteforce(){ PrintAndLog("This command uses A) bruteforce to scan a number range"); PrintAndLog(" B) a dictionary attack"); - PrintAndLog("Usage: lf t55xx bruteforce [i <*.dic>]"); + PrintAndLog("Usage: lf t55xx bruteforce [h] [i <*.dic>]"); PrintAndLog(" password must be 4 bytes (8 hex symbols)"); PrintAndLog("Options:"); PrintAndLog(" h - this help"); @@ -172,7 +172,7 @@ int usage_t55xx_recoverpw(){ PrintAndLog(" default password is 51243648, used by many cloners"); PrintAndLog("Options:"); PrintAndLog(" h - this help"); - PrintAndLog(" [password] - 4 byte hex value of password written by cloner"); + PrintAndLog(" [password] - 4 byte hex value of password written by cloner"); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx recoverpw"); -- 2.39.5 From af17926620a2537d165d8b00d97ce8a88d2944d2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 14 Aug 2016 17:38:11 +0200 Subject: [PATCH 16/16] chg; syntax suger --- client/cmdlf.c | 598 +++++++++++++++++++++++-------------------------- 1 file changed, 283 insertions(+), 315 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index 6bfbec8d..eb9aec68 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -183,81 +183,68 @@ int CmdLFCommandRead(const char *Cmd) { int CmdFlexdemod(const char *Cmd) { - int i; - for (i = 0; i < GraphTraceLen; ++i) { - if (GraphBuffer[i] < 0) { - GraphBuffer[i] = -1; - } else { - GraphBuffer[i] = 1; - } - } - -#define LONG_WAIT 100 - int start; - for (start = 0; start < GraphTraceLen - LONG_WAIT; start++) { - int first = GraphBuffer[start]; - for (i = start; i < start + LONG_WAIT; i++) { - if (GraphBuffer[i] != first) { - break; - } - } - if (i == (start + LONG_WAIT)) { - break; - } - } - if (start == GraphTraceLen - LONG_WAIT) { - PrintAndLog("nothing to wait for"); - return 0; - } - - GraphBuffer[start] = 2; - GraphBuffer[start+1] = -2; +#define LONG_WAIT 100 + int i, j, start, bit, sum; + int phase = 0; + + for (i = 0; i < GraphTraceLen; ++i) + GraphBuffer[i] = (GraphBuffer[i] < 0) ? -1 : 1; + + for (start = 0; start < GraphTraceLen - LONG_WAIT; start++) { + int first = GraphBuffer[start]; + for (i = start; i < start + LONG_WAIT; i++) { + if (GraphBuffer[i] != first) { + break; + } + } + if (i == (start + LONG_WAIT)) + break; + } + + if (start == GraphTraceLen - LONG_WAIT) { + PrintAndLog("nothing to wait for"); + return 0; + } + + GraphBuffer[start] = 2; + GraphBuffer[start+1] = -2; uint8_t bits[64] = {0x00}; - int bit, sum; - i = start; - for (bit = 0; bit < 64; bit++) { + i = start; + for (bit = 0; bit < 64; bit++) { sum = 0; for (int j = 0; j < 16; j++) { - sum += GraphBuffer[i++]; - } - + sum += GraphBuffer[i++]; + } bits[bit] = (sum > 0) ? 1 : 0; + PrintAndLog("bit %d sum %d", bit, sum); + } - PrintAndLog("bit %d sum %d", bit, sum); - } - - for (bit = 0; bit < 64; bit++) { - int j; - int sum = 0; - for (j = 0; j < 16; j++) { - sum += GraphBuffer[i++]; - } - if (sum > 0 && bits[bit] != 1) { - PrintAndLog("oops1 at %d", bit); - } - if (sum < 0 && bits[bit] != 0) { - PrintAndLog("oops2 at %d", bit); - } - } + for (bit = 0; bit < 64; bit++) { + sum = 0; + for (j = 0; j < 16; j++) + sum += GraphBuffer[i++]; + + if (sum > 0 && bits[bit] != 1) PrintAndLog("oops1 at %d", bit); + + if (sum < 0 && bits[bit] != 0) PrintAndLog("oops2 at %d", bit); + + } // HACK writing back to graphbuffer. - GraphTraceLen = 32*64; - i = 0; - int phase = 0; - for (bit = 0; bit < 64; bit++) { - + GraphTraceLen = 32*64; + i = 0; + for (bit = 0; bit < 64; bit++) { + phase = (bits[bit] == 0) ? 0 : 1; - int j; - for (j = 0; j < 32; j++) { - GraphBuffer[i++] = phase; - phase = !phase; - } - } - - RepaintGraphWindow(); - return 0; + for (j = 0; j < 32; j++) { + GraphBuffer[i++] = phase; + phase = !phase; + } + } + RepaintGraphWindow(); + return 0; } int CmdIndalaDemod(const char *Cmd) @@ -270,10 +257,9 @@ int CmdIndalaDemod(const char *Cmd) // worst case with GraphTraceLen=64000 is < 4096 // under normal conditions it's < 2048 - uint8_t rawbits[4096]; - int rawbit = 0; - int worst = 0, worstPos = 0; + + int rawbit = 0, worst = 0, worstPos = 0; // PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32); // loop through raw signal - since we know it is psk1 rf/32 fc/2 skip every other value (+=2) @@ -448,51 +434,49 @@ int CmdIndalaDemod(const char *Cmd) return 1; } -int CmdIndalaClone(const char *Cmd) -{ - UsbCommand c; +int CmdIndalaClone(const char *Cmd){ + UsbCommand c; unsigned int uid1, uid2, uid3, uid4, uid5, uid6, uid7; uid1 = uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0; - int n = 0, i = 0; - - if (strchr(Cmd,'l') != 0) { - while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { - uid1 = (uid1 << 4) | (uid2 >> 28); - uid2 = (uid2 << 4) | (uid3 >> 28); - uid3 = (uid3 << 4) | (uid4 >> 28); - uid4 = (uid4 << 4) | (uid5 >> 28); - uid5 = (uid5 << 4) | (uid6 >> 28); - uid6 = (uid6 << 4) | (uid7 >> 28); - uid7 = (uid7 << 4) | (n & 0xf); - } - PrintAndLog("Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7); - c.cmd = CMD_INDALA_CLONE_TAG_L; - c.d.asDwords[0] = uid1; - c.d.asDwords[1] = uid2; - c.d.asDwords[2] = uid3; - c.d.asDwords[3] = uid4; - c.d.asDwords[4] = uid5; - c.d.asDwords[5] = uid6; - c.d.asDwords[6] = uid7; + int n = 0, i = 0; + + if (strchr(Cmd,'l') != 0) { + while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { + uid1 = (uid1 << 4) | (uid2 >> 28); + uid2 = (uid2 << 4) | (uid3 >> 28); + uid3 = (uid3 << 4) | (uid4 >> 28); + uid4 = (uid4 << 4) | (uid5 >> 28); + uid5 = (uid5 << 4) | (uid6 >> 28); + uid6 = (uid6 << 4) | (uid7 >> 28); + uid7 = (uid7 << 4) | (n & 0xf); + } + PrintAndLog("Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7); + c.cmd = CMD_INDALA_CLONE_TAG_L; + c.d.asDwords[0] = uid1; + c.d.asDwords[1] = uid2; + c.d.asDwords[2] = uid3; + c.d.asDwords[3] = uid4; + c.d.asDwords[4] = uid5; + c.d.asDwords[5] = uid6; + c.d.asDwords[6] = uid7; } else { - while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { - uid1 = (uid1 << 4) | (uid2 >> 28); - uid2 = (uid2 << 4) | (n & 0xf); - } - PrintAndLog("Cloning 64bit tag with UID %x%08x", uid1, uid2); - c.cmd = CMD_INDALA_CLONE_TAG; - c.arg[0] = uid1; - c.arg[1] = uid2; - } + while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { + uid1 = (uid1 << 4) | (uid2 >> 28); + uid2 = (uid2 << 4) | (n & 0xf); + } + PrintAndLog("Cloning 64bit tag with UID %x%08x", uid1, uid2); + c.cmd = CMD_INDALA_CLONE_TAG; + c.arg[0] = uid1; + c.arg[1] = uid2; + } clearCommandBuffer(); - SendCommand(&c); - return 0; + SendCommand(&c); + return 0; } -int CmdLFSetConfig(const char *Cmd) -{ +int CmdLFSetConfig(const char *Cmd) { uint8_t divisor = 0;//Frequency divisor uint8_t bps = 0; // Bits per sample uint8_t decimation = 0; //How many to keep @@ -502,10 +486,8 @@ int CmdLFSetConfig(const char *Cmd) uint8_t unsigned_trigg = 0; uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00) - { - switch(param_getchar(Cmd, cmdp)) - { + while(param_getchar(Cmd, cmdp) != 0x00) { + switch(param_getchar(Cmd, cmdp)) { case 'h': return usage_lf_config(); case 'H': @@ -564,8 +546,7 @@ int CmdLFSetConfig(const char *Cmd) return 0; } -int CmdLFRead(const char *Cmd) -{ +int CmdLFRead(const char *Cmd) { bool arg1 = false; uint8_t cmdp = param_getchar(Cmd, 0); @@ -584,8 +565,7 @@ int CmdLFRead(const char *Cmd) return 0; } -int CmdLFSnoop(const char *Cmd) -{ +int CmdLFSnoop(const char *Cmd) { uint8_t cmdp = param_getchar(Cmd, 0); if(cmdp == 'h' || cmdp == 'H') return usage_lf_snoop(); @@ -596,22 +576,18 @@ int CmdLFSnoop(const char *Cmd) return 0; } -static void ChkBitstream(const char *str) -{ - int i; - - /* convert to bitstream if necessary */ - for (i = 0; i < (int)(GraphTraceLen / 2); i++){ +static void ChkBitstream(const char *str) { + // convert to bitstream if necessary + for (int i = 0; i < (int)(GraphTraceLen / 2); i++){ if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0) { - CmdGetBitStream(""); - break; - } - } + CmdGetBitStream(""); + break; + } + } } //Attempt to simulate any wave in buffer (one bit per output sample) // converts GraphBuffer to bitstream (based on zero crossings) if needed. -int CmdLFSim(const char *Cmd) -{ +int CmdLFSim(const char *Cmd) { int i,j; static int gap; @@ -655,10 +631,8 @@ int CmdLFfskSim(const char *Cmd) int dataLen = 0; uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00) - { - switch(param_getchar(Cmd, cmdp)) - { + while(param_getchar(Cmd, cmdp) != 0x00) { + switch(param_getchar(Cmd, cmdp)){ case 'h': return usage_lf_simfsk(); case 'i': @@ -838,197 +812,191 @@ int CmdLFaskSim(const char *Cmd) // by marshmellow - sim psk data given carrier, clock, invert // - allow pull data from DemodBuffer or parameters -int CmdLFpskSim(const char *Cmd) -{ - //might be able to autodetect FC and clock from Graphbuffer if using demod buffer - //will need carrier, Clock, and bitstream - uint8_t carrier=0, clk=0; - uint8_t invert=0; - bool errors = FALSE; - char hexData[32] = {0x00}; // store entered hex data - uint8_t data[255] = {0x00}; - int dataLen = 0; - uint8_t cmdp = 0; - uint8_t pskType = 1; - while(param_getchar(Cmd, cmdp) != 0x00) - { - switch(param_getchar(Cmd, cmdp)) - { - case 'h': - return usage_lf_simpsk(); - case 'i': - invert = 1; - cmdp++; - break; - case 'c': - errors |= param_getdec(Cmd,cmdp+1,&clk); - cmdp+=2; - break; - case 'r': - errors |= param_getdec(Cmd,cmdp+1,&carrier); - cmdp+=2; - break; - case '1': - pskType=1; - cmdp++; - break; - case '2': - pskType=2; - cmdp++; - break; - case '3': - pskType=3; - cmdp++; - break; - case 'd': - dataLen = param_getstr(Cmd, cmdp+1, hexData); - if (dataLen==0) { - errors=TRUE; - } else { - dataLen = hextobinarray((char *)data, hexData); - } - if (dataLen==0) errors=TRUE; - if (errors) PrintAndLog ("Error getting hex data"); - cmdp+=2; - break; - default: - PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = TRUE; - break; - } - if (errors) break; - } - if (cmdp == 0 && DemodBufferLen == 0) - { - errors = TRUE;// No args - } - - //Validations - if (errors) - { - return usage_lf_simpsk(); - } - if (dataLen == 0){ //using DemodBuffer - PrintAndLog("Getting Clocks"); - if (clk==0) clk = GetPskClock("", FALSE, FALSE); - PrintAndLog("clk: %d",clk); - if (!carrier) carrier = GetPskCarrier("", FALSE, FALSE); - PrintAndLog("carrier: %d", carrier); - } else { - setDemodBuf(data, dataLen, 0); - } - - if (clk <= 0) clk = 32; - if (carrier == 0) carrier = 2; - if (pskType != 1){ - if (pskType == 2){ - //need to convert psk2 to psk1 data before sim - psk2TOpsk1(DemodBuffer, DemodBufferLen); - } else { - PrintAndLog("Sorry, PSK3 not yet available"); - } - } - uint16_t arg1, arg2; - arg1 = clk << 8 | carrier; - arg2 = invert; - size_t size=DemodBufferLen; - if (size > USB_CMD_DATA_SIZE) { - PrintAndLog("DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE); - size=USB_CMD_DATA_SIZE; - } - UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}}; - PrintAndLog("DEBUG: Sending DemodBuffer Length: %d", size); - memcpy(c.d.asBytes, DemodBuffer, size); - clearCommandBuffer(); - SendCommand(&c); +int CmdLFpskSim(const char *Cmd) { + //might be able to autodetect FC and clock from Graphbuffer if using demod buffer + //will need carrier, Clock, and bitstream + uint8_t carrier=0, clk=0; + uint8_t invert=0; + bool errors = FALSE; + char hexData[32] = {0x00}; // store entered hex data + uint8_t data[255] = {0x00}; + int dataLen = 0; + uint8_t cmdp = 0; + uint8_t pskType = 1; + + while(param_getchar(Cmd, cmdp) != 0x00) { + switch(param_getchar(Cmd, cmdp)) { + case 'h': + return usage_lf_simpsk(); + case 'i': + invert = 1; + cmdp++; + break; + case 'c': + errors |= param_getdec(Cmd,cmdp+1,&clk); + cmdp +=2; + break; + case 'r': + errors |= param_getdec(Cmd,cmdp+1,&carrier); + cmdp += 2; + break; + case '1': + pskType = 1; + cmdp++; + break; + case '2': + pskType = 2; + cmdp++; + break; + case '3': + pskType = 3; + cmdp++; + break; + case 'd': + dataLen = param_getstr(Cmd, cmdp+1, hexData); + if (dataLen == 0) + errors = TRUE; + else + dataLen = hextobinarray((char *)data, hexData); + + if (dataLen == 0) errors = TRUE; + if (errors) PrintAndLog ("Error getting hex data"); + cmdp+=2; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = TRUE; + break; + } + if (errors) break; + } + // No args + if (cmdp == 0 && DemodBufferLen == 0) + errors = TRUE; + + //Validations + if (errors) return usage_lf_simpsk(); + + if (dataLen == 0){ //using DemodBuffer + PrintAndLog("Getting Clocks"); + + if (clk==0) clk = GetPskClock("", FALSE, FALSE); + PrintAndLog("clk: %d",clk); + + if (!carrier) carrier = GetPskCarrier("", FALSE, FALSE); + PrintAndLog("carrier: %d", carrier); + + } else { + setDemodBuf(data, dataLen, 0); + } + + if (clk <= 0) clk = 32; + + if (carrier == 0) carrier = 2; - return 0; + if (pskType != 1){ + if (pskType == 2){ + //need to convert psk2 to psk1 data before sim + psk2TOpsk1(DemodBuffer, DemodBufferLen); + } else { + PrintAndLog("Sorry, PSK3 not yet available"); + } + } + uint16_t arg1, arg2; + arg1 = clk << 8 | carrier; + arg2 = invert; + size_t size = DemodBufferLen; + if (size > USB_CMD_DATA_SIZE) { + PrintAndLog("DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE); + size = USB_CMD_DATA_SIZE; + } + UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}}; + PrintAndLog("DEBUG: Sending DemodBuffer Length: %d", size); + memcpy(c.d.asBytes, DemodBuffer, size); + clearCommandBuffer(); + SendCommand(&c); + return 0; } -int CmdLFSimBidir(const char *Cmd) -{ - // Set ADC to twice the carrier for a slight supersampling - // HACK: not implemented in ARMSRC. - PrintAndLog("Not implemented yet."); - UsbCommand c = {CMD_LF_SIMULATE_BIDIR, {47, 384, 0}}; - SendCommand(&c); - return 0; +int CmdLFSimBidir(const char *Cmd) { + // Set ADC to twice the carrier for a slight supersampling + // HACK: not implemented in ARMSRC. + PrintAndLog("Not implemented yet."); + UsbCommand c = {CMD_LF_SIMULATE_BIDIR, {47, 384, 0}}; + SendCommand(&c); + return 0; } -int CmdVchDemod(const char *Cmd) -{ - // Is this the entire sync pattern, or does this also include some - // data bits that happen to be the same everywhere? That would be - // lovely to know. - static const int SyncPattern[] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - }; - - // So first, we correlate for the sync pattern, and mark that. - int bestCorrel = 0, bestPos = 0; - int i; - // It does us no good to find the sync pattern, with fewer than - // 2048 samples after it... - for (i = 0; i < (GraphTraceLen-2048); i++) { - int sum = 0; - int j; - for (j = 0; j < ARRAYLEN(SyncPattern); j++) { - sum += GraphBuffer[i+j]*SyncPattern[j]; - } - if (sum > bestCorrel) { - bestCorrel = sum; - bestPos = i; - } - } - PrintAndLog("best sync at %d [metric %d]", bestPos, bestCorrel); - - char bits[257]; - bits[256] = '\0'; - - int worst = INT_MAX; - int worstPos = 0; - - for (i = 0; i < 2048; i += 8) { - int sum = 0; - int j; - for (j = 0; j < 8; j++) { - sum += GraphBuffer[bestPos+i+j]; - } - if (sum < 0) { - bits[i/8] = '.'; - } else { - bits[i/8] = '1'; - } - if(abs(sum) < worst) { - worst = abs(sum); - worstPos = i; - } - } - PrintAndLog("bits:"); - PrintAndLog("%s", bits); - PrintAndLog("worst metric: %d at pos %d", worst, worstPos); - - if (strcmp(Cmd, "clone")==0) { - GraphTraceLen = 0; - char *s; - for(s = bits; *s; s++) { - int j; - for(j = 0; j < 16; j++) { - GraphBuffer[GraphTraceLen++] = (*s == '1') ? 1 : 0; - } - } - RepaintGraphWindow(); - } - return 0; +int CmdVchDemod(const char *Cmd) { + // Is this the entire sync pattern, or does this also include some + // data bits that happen to be the same everywhere? That would be + // lovely to know. + static const int SyncPattern[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }; + + // So first, we correlate for the sync pattern, and mark that. + int bestCorrel = 0, bestPos = 0; + int i, j, sum = 0; + + // It does us no good to find the sync pattern, with fewer than 2048 samples after it. + + for (i = 0; i < (GraphTraceLen - 2048); i++) { + for (j = 0; j < ARRAYLEN(SyncPattern); j++) { + sum += GraphBuffer[i+j] * SyncPattern[j]; + } + if (sum > bestCorrel) { + bestCorrel = sum; + bestPos = i; + } + } + PrintAndLog("best sync at %d [metric %d]", bestPos, bestCorrel); + + char bits[257]; + bits[256] = '\0'; + + int worst = INT_MAX, worstPos = 0; + + for (i = 0; i < 2048; i += 8) { + sum = 0; + for (j = 0; j < 8; j++) + sum += GraphBuffer[bestPos+i+j]; + + if (sum < 0) + bits[i/8] = '.'; + else + bits[i/8] = '1'; + + if(abs(sum) < worst) { + worst = abs(sum); + worstPos = i; + } + } + PrintAndLog("bits:"); + PrintAndLog("%s", bits); + PrintAndLog("worst metric: %d at pos %d", worst, worstPos); + + // clone + if (strcmp(Cmd, "clone")==0) { + GraphTraceLen = 0; + char *s; + for(s = bits; *s; s++) { + for(j = 0; j < 16; j++) { + GraphBuffer[GraphTraceLen++] = (*s == '1') ? 1 : 0; + } + } + RepaintGraphWindow(); + } + return 0; } //by marshmellow -- 2.39.5