- // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
-
- int state = -1;
- int count = 0;
- int i, j;
- // 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;
- PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32);
- for (i = 0; i < GraphTraceLen-1; i += 2) {
- count += 1;
- if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
- if (state == 0) {
- for (j = 0; j < count - 8; j += 16) {
- rawbits[rawbit++] = 0;
- }
- if ((abs(count - j)) > worst) {
- worst = abs(count - j);
- worstPos = i;
- }
- }
- state = 1;
- count = 0;
- } else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {
- if (state == 1) {
- for (j = 0; j < count - 8; j += 16) {
- rawbits[rawbit++] = 1;
- }
- if ((abs(count - j)) > worst) {
- worst = abs(count - j);
- worstPos = i;
- }
- }
- state = 0;
- count = 0;
- }
- }
- PrintAndLog("Recovered %d raw bits", rawbit);
- PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
-
- // Finding the start of a UID
- int uidlen, long_wait;
- if (strcmp(Cmd, "224") == 0) {
- uidlen = 224;
- long_wait = 30;
- } else {
- uidlen = 64;
- long_wait = 29;
- }
- int start;
- int first = 0;
- for (start = 0; start <= rawbit - uidlen; start++) {
- first = rawbits[start];
- for (i = start; i < start + long_wait; i++) {
- if (rawbits[i] != first) {
- break;
- }
- }
- if (i == (start + long_wait)) {
- break;
- }
- }
- if (start == rawbit - uidlen + 1) {
- PrintAndLog("nothing to wait for");
- return 0;
- }
-
- // Inverting signal if needed
- if (first == 1) {
- for (i = start; i < rawbit; i++) {
- rawbits[i] = !rawbits[i];
- }
- }
-
- // Dumping UID
- uint8_t bits[224];
- char showbits[225];
- showbits[uidlen]='\0';
- int bit;
- i = start;
- int times = 0;
- if (uidlen > rawbit) {
- PrintAndLog("Warning: not enough raw bits to get a full UID");
- for (bit = 0; bit < rawbit; bit++) {
- bits[bit] = rawbits[i++];
- // As we cannot know the parity, let's use "." and "/"
- showbits[bit] = '.' + bits[bit];
- }
- showbits[bit+1]='\0';
- PrintAndLog("Partial UID=%s", showbits);
- return 0;
- } else {
- for (bit = 0; bit < uidlen; bit++) {
- bits[bit] = rawbits[i++];
- showbits[bit] = '0' + bits[bit];
- }
- times = 1;
- }
- PrintAndLog("UID=%s", showbits);
-
- // Checking UID against next occurences
- for (; i + uidlen <= rawbit;) {
- int failed = 0;
- for (bit = 0; bit < uidlen; bit++) {
- if (bits[bit] != rawbits[i++]) {
- failed = 1;
- break;
- }
- }
- if (failed == 1) {
- break;
- }
- times += 1;
- }
- PrintAndLog("Occurences: %d (expected %d)", times, (rawbit - start) / uidlen);
-
- // Remodulating for tag cloning
- GraphTraceLen = 32*uidlen;
- i = 0;
- int phase = 0;
- for (bit = 0; bit < uidlen; bit++) {
- if (bits[bit] == 0) {
- phase = 0;
- } else {
- phase = 1;
- }
- int j;
- for (j = 0; j < 32; j++) {
- GraphBuffer[i++] = phase;
- phase = !phase;
- }
- }
-
- RepaintGraphWindow();
- return 0;
+ // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
+
+ int state = -1;
+ int count = 0;
+ int i, j;
+
+ // 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;
+ // PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32);
+ for (i = 0; i < GraphTraceLen-1; i += 2) {
+ count += 1;
+ if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
+ if (state == 0) {
+ for (j = 0; j < count - 8; j += 16) {
+ rawbits[rawbit++] = 0;
+ }
+ if ((abs(count - j)) > worst) {
+ worst = abs(count - j);
+ worstPos = i;
+ }
+ }
+ state = 1;
+ count = 0;
+ } else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {
+ if (state == 1) {
+ for (j = 0; j < count - 8; j += 16) {
+ rawbits[rawbit++] = 1;
+ }
+ if ((abs(count - j)) > worst) {
+ worst = abs(count - j);
+ worstPos = i;
+ }
+ }
+ state = 0;
+ count = 0;
+ }
+ }
+
+ if (rawbit>0){
+ PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32);
+ PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
+ } else {
+ return 0;
+ }
+
+ // Finding the start of a UID
+ int uidlen, long_wait;
+ if (strcmp(Cmd, "224") == 0) {
+ uidlen = 224;
+ long_wait = 30;
+ } else {
+ uidlen = 64;
+ long_wait = 29;
+ }
+
+ int start;
+ int first = 0;
+ for (start = 0; start <= rawbit - uidlen; start++) {
+ first = rawbits[start];
+ for (i = start; i < start + long_wait; i++) {
+ if (rawbits[i] != first) {
+ break;
+ }
+ }
+ if (i == (start + long_wait)) {
+ break;
+ }
+ }
+
+ if (start == rawbit - uidlen + 1) {
+ PrintAndLog("nothing to wait for");
+ return 0;
+ }
+
+ // Inverting signal if needed
+ if (first == 1) {
+ for (i = start; i < rawbit; i++) {
+ rawbits[i] = !rawbits[i];
+ }
+ }
+
+ // Dumping UID
+ uint8_t bits[224] = {0x00};
+ char showbits[225] = {0x00};
+ int bit;
+ i = start;
+ int times = 0;
+
+ if (uidlen > rawbit) {
+ PrintAndLog("Warning: not enough raw bits to get a full UID");
+ for (bit = 0; bit < rawbit; bit++) {
+ bits[bit] = rawbits[i++];
+ // As we cannot know the parity, let's use "." and "/"
+ showbits[bit] = '.' + bits[bit];
+ }
+ showbits[bit+1]='\0';
+ PrintAndLog("Partial UID=%s", showbits);
+ return 0;
+ } else {
+ for (bit = 0; bit < uidlen; bit++) {
+ bits[bit] = rawbits[i++];
+ showbits[bit] = '0' + bits[bit];
+ }
+ times = 1;
+ }
+
+ //convert UID to HEX
+ uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
+ int idx;
+ uid1 = uid2 = 0;
+
+ if (uidlen==64){
+ for( idx=0; idx<64; idx++) {
+ if (showbits[idx] == '0') {
+ uid1=(uid1<<1)|(uid2>>31);
+ uid2=(uid2<<1)|0;
+ } else {
+ uid1=(uid1<<1)|(uid2>>31);
+ uid2=(uid2<<1)|1;
+ }
+ }
+ PrintAndLog("UID=%s (%x%08x)", showbits, uid1, uid2);
+ }
+ else {
+ uid3 = uid4 = uid5 = uid6 = uid7 = 0;
+
+ for( idx=0; idx<224; idx++) {
+ uid1=(uid1<<1)|(uid2>>31);
+ uid2=(uid2<<1)|(uid3>>31);
+ uid3=(uid3<<1)|(uid4>>31);
+ uid4=(uid4<<1)|(uid5>>31);
+ uid5=(uid5<<1)|(uid6>>31);
+ uid6=(uid6<<1)|(uid7>>31);
+
+ if (showbits[idx] == '0')
+ uid7 = (uid7<<1) | 0;
+ else
+ uid7 = (uid7<<1) | 1;
+ }
+ PrintAndLog("UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7);
+ }
+
+ // Checking UID against next occurrences
+ int failed = 0;
+ for (; i + uidlen <= rawbit;) {
+ failed = 0;
+ for (bit = 0; bit < uidlen; bit++) {
+ if (bits[bit] != rawbits[i++]) {
+ failed = 1;
+ break;
+ }
+ }
+ if (failed == 1) {
+ break;
+ }
+ times += 1;
+ }
+
+ PrintAndLog("Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen);
+
+ // Remodulating for tag cloning
+ // HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod)
+ // since this changes graphbuffer data.
+ GraphTraceLen = 32*uidlen;
+ i = 0;
+ int phase = 0;
+ for (bit = 0; bit < uidlen; bit++) {
+ if (bits[bit] == 0) {
+ phase = 0;
+ } else {
+ phase = 1;
+ }
+ int j;
+ for (j = 0; j < 32; j++) {
+ GraphBuffer[i++] = phase;
+ phase = !phase;
+ }
+ }
+
+ RepaintGraphWindow();
+ return 1;
+}
+
+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;
+ } 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;
+ }
+
+ SendCommand(&c);
+ return 0;
+}
+
+int usage_lf_read()
+{
+ PrintAndLog("Usage: lf read");
+ PrintAndLog("Options: ");
+ PrintAndLog(" h This help");
+ PrintAndLog(" s silent run no printout");
+ PrintAndLog("This function takes no arguments. ");
+ PrintAndLog("Use 'lf config' to set parameters.");
+ return 0;
+}
+int usage_lf_snoop()
+{
+ PrintAndLog("Usage: lf snoop");
+ PrintAndLog("Options: ");
+ PrintAndLog(" h This help");
+ PrintAndLog("This function takes no arguments. ");
+ PrintAndLog("Use 'lf config' to set parameters.");
+ return 0;
+}
+
+int usage_lf_config()
+{
+ PrintAndLog("Usage: lf config [H|<divisor>] [b <bps>] [d <decim>] [a 0|1]");
+ PrintAndLog("Options: ");
+ PrintAndLog(" h This help");
+ PrintAndLog(" L Low frequency (125 KHz)");
+ PrintAndLog(" H High frequency (134 KHz)");
+ PrintAndLog(" q <divisor> Manually set divisor. 88-> 134KHz, 95-> 125 Hz");
+ PrintAndLog(" b <bps> Sets resolution of bits per sample. Default (max): 8");
+ PrintAndLog(" d <decim> Sets decimation. A value of N saves only 1 in N samples. Default: 1");
+ PrintAndLog(" a [0|1] Averaging - if set, will average the stored sample value when decimating. Default: 1");
+ PrintAndLog(" t <threshold> Sets trigger threshold. 0 means no threshold");
+ PrintAndLog("Examples:");
+ PrintAndLog(" lf config b 8 L");
+ PrintAndLog(" Samples at 125KHz, 8bps.");
+ PrintAndLog(" lf config H b 4 d 3");
+ PrintAndLog(" Samples at 134KHz, averages three samples into one, stored with ");
+ PrintAndLog(" a resolution of 4 bits per sample.");
+ PrintAndLog(" lf read");
+ PrintAndLog(" Performs a read (active field)");
+ PrintAndLog(" lf snoop");
+ PrintAndLog(" Performs a snoop (no active field)");
+ return 0;
+}
+
+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
+ bool averaging = 1; // Defaults to true
+ bool errors = FALSE;
+ int trigger_threshold =-1;//Means no change
+ uint8_t unsigned_trigg = 0;
+
+ uint8_t cmdp =0;
+ while(param_getchar(Cmd, cmdp) != 0x00)
+ {
+ switch(param_getchar(Cmd, cmdp))
+ {
+ case 'h':
+ return usage_lf_config();
+ case 'H':
+ divisor = 88;
+ cmdp++;
+ break;
+ case 'L':
+ divisor = 95;
+ cmdp++;
+ break;
+ case 'q':
+ errors |= param_getdec(Cmd,cmdp+1,&divisor);
+ cmdp+=2;
+ break;
+ case 't':
+ errors |= param_getdec(Cmd,cmdp+1,&unsigned_trigg);
+ cmdp+=2;
+ if(!errors) trigger_threshold = unsigned_trigg;
+ break;
+ case 'b':
+ errors |= param_getdec(Cmd,cmdp+1,&bps);
+ cmdp+=2;
+ break;
+ case 'd':
+ errors |= param_getdec(Cmd,cmdp+1,&decimation);
+ cmdp+=2;
+ break;
+ case 'a':
+ averaging = param_getchar(Cmd,cmdp+1) == '1';
+ cmdp+=2;
+ break;
+ default:
+ PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+ errors = 1;
+ break;
+ }
+ if(errors) break;
+ }
+ if(cmdp == 0)
+ {
+ errors = 1;// No args
+ }
+
+ //Validations
+ if(errors)
+ {
+ return usage_lf_config();
+ }
+ //Bps is limited to 8, so fits in lower half of arg1
+ if(bps >> 8) bps = 8;
+
+ sample_config config = {
+ decimation,bps,averaging,divisor,trigger_threshold
+ };
+ //Averaging is a flag on high-bit of arg[1]
+ UsbCommand c = {CMD_SET_LF_SAMPLING_CONFIG};
+ memcpy(c.d.asBytes,&config,sizeof(sample_config));
+ SendCommand(&c);
+ return 0;