Proxmark3 community

Research, development and trades concerning the powerful Proxmark3 device.

Remember; sharing is caring. Bring something back to the community.


"Learn the tools of the trade the hard way." +Fravia

You are not logged in.

Announcement

Time changes and with it the technology
Proxmark3 @ discord

Users of this forum, please be aware that information stored on this site is not private.

#1 2009-10-13 15:43:17

marekroy
Member
Registered: 2009-09-01
Posts: 2

Kantech ioProx

Hi,

Has anyone started doing work on Kantech XSF (eXtended Secure Format) / ioProx?

It would be interesting to see what we could get out of this.

Regards,
Marek

Offline

#2 2009-10-13 16:24:13

TomBu
Contributor
From: Delft, The Netherlands
Registered: 2008-10-27
Posts: 55
Website

Re: Kantech ioProx

marekroy wrote:

Hi,

Has anyone started doing work on Kantech XSF (eXtended Secure Format) / ioProx?

It would be interesting to see what we could get out of this.

Regards,
Marek

I haven't done any research on them but what I can make out from their online documents they smell like regular LF tags to me.

Offline

#3 2009-10-13 16:58:59

marekroy
Member
Registered: 2009-09-01
Posts: 2

Re: Kantech ioProx

As per :
http://www.homeandinternetsecurity.com/ … eaders.pdf

They are operating under 125kHz with XSF encryption,

Offline

#4 2014-02-16 16:25:31

genexis
Contributor
Registered: 2014-01-25
Posts: 78

Re: Kantech ioProx

anybody has any success decoding this card?
link to data sheet: http://www.kantech.com/Resources/GetDoc.aspx?p=1&id=40314

Offline

#5 2014-02-17 07:24:10

app_o1
Contributor
Registered: 2013-06-22
Posts: 247

Re: Kantech ioProx

http://www.sendspace.com/file/e1nmqy
Printed on the card : XSF(01)3B:44725

000000001111000010011101110000000111010111011011010110111000011 (?)


i am not a pro but it looks quite similar. On top, original. Bottom, copy.
f-IOPROX5301c63a00157755.jpg

I let you do your homework and guess what configuration I used.

Last edited by app_o1 (2014-02-17 09:18:08)

Offline

#6 2014-02-17 18:27:26

asper
Contributor
Registered: 2008-08-24
Posts: 1,409

Re: Kantech ioProx

63bit stream ?

Anyway I found a (weak) correlation between printed numbers and bit "stream"; more tags are needed to improve it.

Hope you will give us the homework answer app_o1 wink

Offline

#7 2014-02-17 20:33:24

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

0000000001111000010011101110000000111010111011011010110111000011 (app_o1 was missing one leading zero) = XSF(01)3B:44725

another card:

0000000001111000011011111010000000110000101111100001111000001011 = XSF(01)BE:03011

bit stream is FSK

Offline

#8 2014-02-18 05:18:09

app_o1
Contributor
Registered: 2013-06-22
Posts: 247

Re: Kantech ioProx

oups ^^

I won't be able to tell if it really works. I just knew I had an old card in the bottom of a drawer..

Offline

#9 2014-02-18 09:25:01

asper
Contributor
Registered: 2008-08-24
Posts: 1,409

Re: Kantech ioProx

Probably found bits for the 2-character hex value (3B and BE in the examples - that was easy); still working to decode the other value; if you have other examples please post them wink

EDIT: I think I found the correct bit pattern (it was easy, I was only too headaching to see it...).

Numbering bits from 1 to 64:

(b19-b26) -> hex

(b37-b45)concatenate(b47-b53) -> dec

from 64 total bits only 24 concur to produce the result.

Last edited by asper (2014-02-19 13:55:30)

Offline

#10 2014-02-19 04:54:30

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

nice work asper,  it appears bit 45 or 46 could be the static bit (I'd lean towards bit 45, but more card samples are needed) and it appears there may be an 8 bit checksum at the end: b54-b61

Offline

#11 2014-02-19 14:12:13

asper
Contributor
Registered: 2008-08-24
Posts: 1,409

Re: Kantech ioProx

Looking at the datasheet it should support (ioProx) Wiegand 26 bit AND XSF but nowhere is written how many bits is XSF format... where does those 64 stream bits come from ?

Offline

#12 2014-03-11 13:53:45

pentura_prox
Contributor
From: England,UK
Registered: 2014-03-11
Posts: 22
Website

Re: Kantech ioProx

First attempt at implementing ioProx tags into the proxmark3 - I only have one tag to practice with and appears to work; probably needs more testing.

SVN diff against version 844

Index: armsrc/appmain.c
===================================================================
--- armsrc/appmain.c    (revision 844)
+++ armsrc/appmain.c    (working copy)
@@ -636,10 +636,16 @@
                case CMD_HID_DEMOD_FSK:
                        CmdHIDdemodFSK(0, 0, 0, 1);                                     // Demodulate HID tag
                        break;
+               case CMD_IO_DEMOD_FSK:
+                       CmdIOdemodFSK(1, 0, 0, 1);                                      // Demodulate HID tag
+                       break;
+               case CMD_IO_CLONE_TAG: // Clone HID tag by ID to T55x7
+                       CopyIOtoT55x7(c->arg[0], c->arg[1], c->d.asBytes[0]);
+                       break;
                case CMD_HID_SIM_TAG:
-                       CmdHIDsimTAG(c->arg[0], c->arg[1], 1);                                  // Simulate HID tag by ID
+                       CmdHIDsimTAG(c->arg[0], c->arg[1], 1);                          // Simulate HID tag by ID
                        break;
-    case CMD_HID_CLONE_TAG: // Clone HID tag by ID to T55x7
+               case CMD_HID_CLONE_TAG: // Clone HID tag by ID to T55x7
                        CopyHIDtoT55x7(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]);
                        break;
                case CMD_EM410X_WRITE_TAG:
Index: armsrc/apps.h
===================================================================
--- armsrc/apps.h       (revision 844)
+++ armsrc/apps.h       (working copy)
@@ -117,6 +117,8 @@
 void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
 void CmdHIDsimTAG(int hi, int lo, int ledcontrol);
 void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol);
+void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol);
+void CopyIOtoT55x7(uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an ioProx card to T5557/T5567
 void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
 void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567
 void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo);
Index: armsrc/lfops.c
===================================================================
--- armsrc/lfops.c      (revision 844)
+++ armsrc/lfops.c      (working copy)
@@ -807,6 +807,264 @@
        }
 }
 
+void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
+{
+       uint8_t *dest = (uint8_t *)BigBuf;
+       int m=0, n=0, i=0, idx=0, lastval=0;
+       int found=0;
+       uint32_t code=0, code2=0;
+       //uint32_t hi2=0, hi=0, lo=0;
+
+       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
+
+       // Connect the A/D to the peak-detected low-frequency path.
+       SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
+
+       // Give it a bit of time for the resonant antenna to settle.
+       SpinDelay(50);
+
+       // Now set up the SSC to get the ADC samples that are now streaming at us.
+       FpgaSetupSsc();
+
+       for(;;) {
+               WDT_HIT();
+               if (ledcontrol)
+                       LED_A_ON();
+               if(BUTTON_PRESS()) {
+                       DbpString("Stopped");
+                       if (ledcontrol)
+                               LED_A_OFF();
+                       return;
+               }
+
+               i = 0;
+               m = sizeof(BigBuf);
+               memset(dest,128,m);
+               for(;;) {
+                       if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+                               AT91C_BASE_SSC->SSC_THR = 0x43;
+                               if (ledcontrol)
+                                       LED_D_ON();
+                       }
+                       if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+                               dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
+                               // we don't care about actual value, only if it's more or less than a
+                               // threshold essentially we capture zero crossings for later analysis
+                               if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;
+                               i++;
+                               if (ledcontrol)
+                                       LED_D_OFF();
+                               if(i >= m) {
+                                       break;
+                               }
+                       }
+               }
+
+               // FSK demodulator
+
+               // sync to first lo-hi transition
+               for( idx=1; idx<m; idx++) {
+                       if (dest[idx-1]<dest[idx])
+                               lastval=idx;
+                               break;
+               }
+               WDT_HIT();
+
+               // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
+               // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere
+               // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
+               for( i=0; idx<m; idx++) {
+                       if (dest[idx-1]<dest[idx]) {
+                               dest[i]=idx-lastval;
+                               if (dest[i] <= 8) {
+                                               dest[i]=1;
+                               } else {
+                                               dest[i]=0;
+                               }
+
+                               lastval=idx;
+                               i++;
+                       }
+               }
+               m=i;
+               WDT_HIT();
+
+               // we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns
+               lastval=dest[0];
+               idx=0;
+               i=0;
+               n=0;
+               for( idx=0; idx<m; idx++) {
+                       if (dest[idx]==lastval) {
+                               n++;
+                       } else {
+                               // a bit time is five fc/10 or six fc/8 cycles so figure out how many bits a pattern width represents,
+                               // an extra fc/8 pattern preceeds every 4 bits (about 200 cycles) just to complicate things but it gets
+                               // swallowed up by rounding
+                               // expected results are 1 or 2 bits, any more and it's an invalid manchester encoding
+                               // special start of frame markers use invalid manchester states (no transitions) by using sequences
+                               // like 111000
+                               if (dest[idx-1]) {
+                                       n=(n+1)/7;                      // fc/8 in sets of 7
+                               } else {
+                                       n=(n+1)/6;                      // fc/10 in sets of 6
+                               }
+                               switch (n) {                    // stuff appropriate bits in buffer
+                                       case 0:
+                                       case 1: // one bit
+                                               dest[i++]=dest[idx-1]^1;
+                                               //Dbprintf("%d",dest[idx-1]);
+                                               break;
+                                       case 2: // two bits
+                                               dest[i++]=dest[idx-1]^1;
+                                               dest[i++]=dest[idx-1]^1;
+                                               //Dbprintf("%d",dest[idx-1]);
+                                               //Dbprintf("%d",dest[idx-1]);
+                                               break;
+                                       case 3: // 3 bit start of frame markers
+                                               for(int j=0; j<3; j++){
+                                                 dest[i++]=dest[idx-1]^1;
+                                               //  Dbprintf("%d",dest[idx-1]);
+                                               }
+                                               break;
+                                       case 4:
+                                               for(int j=0; j<4; j++){
+                                                 dest[i++]=dest[idx-1]^1;
+                                               //  Dbprintf("%d",dest[idx-1]);
+                                               }
+                                               break;
+                                       case 5:
+                                               for(int j=0; j<5; j++){
+                                                 dest[i++]=dest[idx-1]^1;
+                                               //  Dbprintf("%d",dest[idx-1]);
+                                               }
+                                               break;
+                                       case 6:
+                                               for(int j=0; j<6; j++){
+                                                 dest[i++]=dest[idx-1]^1;
+                                               //  Dbprintf("%d",dest[idx-1]);
+                                               }
+                                               break;
+                                       case 7:
+                                               for(int j=0; j<7; j++){
+                                                 dest[i++]=dest[idx-1]^1;
+                                               //  Dbprintf("%d",dest[idx-1]);
+                                               }
+                                               break;
+                                       case 8:
+                                               for(int j=0; j<8; j++){
+                                                 dest[i++]=dest[idx-1]^1;
+                                               //  Dbprintf("%d",dest[idx-1]);
+                                               }
+                                               break;
+                                       case 9:
+                                               for(int j=0; j<9; j++){
+                                                 dest[i++]=dest[idx-1]^1;
+                                               //  Dbprintf("%d",dest[idx-1]);
+                                               }
+                                               break;
+                                       case 10:
+                                               for(int j=0; j<10; j++){
+                                                 dest[i++]=dest[idx-1]^1;
+                                               //  Dbprintf("%d",dest[idx-1]);
+                                               }
+                                               break;
+                                       case 11:
+                                               for(int j=0; j<11; j++){
+                                                 dest[i++]=dest[idx-1]^1;
+                                               //  Dbprintf("%d",dest[idx-1]);
+                                               }
+                                               break;
+                                       case 12:
+                                               for(int j=0; j<12; j++){
+                                                 dest[i++]=dest[idx-1]^1;
+                                                // Dbprintf("%d",dest[idx-1]);
+                                               }
+                                               break;
+                                       default:        // this shouldn't happen, don't stuff any bits
+                                               //Dbprintf("%d",dest[idx-1]);
+                                               break;
+                               }
+                               n=0;
+                               lastval=dest[idx];
+                       }
+               }//end for
+               /*for(int j=0; j<64;j+=8){
+                 Dbprintf("%d%d%d%d%d%d%d%d",dest[j],dest[j+1],dest[j+2],dest[j+3],dest[j+4],dest[j+5],dest[j+6],dest[j+7]);
+               }
+               Dbprintf("\n");*/
+               m=i;
+               WDT_HIT();
+
+        for( idx=0; idx<m-9; idx++) {
+         if ( !(dest[idx]) && !(dest[idx+1]) && !(dest[idx+2]) && !(dest[idx+3]) && !(dest[idx+4]) && !(dest[idx+5]) && !(dest[idx+6]) && !(dest[idx+7]) 
&& !(dest[idx+8])&& (dest[idx+9])){
+               found=1;
+               //idx+=9;
+               if (found) {
+                   Dbprintf("%d%d%d%d%d%d%d%d",dest[idx],   dest[idx+1],   dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7]);
+                   Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+8], dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15]);         
+                   Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+16],dest[idx+17],dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23]);
+                   Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+24],dest[idx+25],dest[idx+26],dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31]);
+                   Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35],dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39]);
+                   Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44],dest[idx+45],dest[idx+46],dest[idx+47]);
+                   Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53],dest[idx+54],dest[idx+55]);
+                   Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]);
+
+                   short version='\x00';
+                   char unknown='\x00';
+                   uint16_t number=0;
+                   for(int j=14;j<18;j++){
+                      //Dbprintf("%d",dest[idx+j]);
+                      version <<=1;
+                      if (dest[idx+j]) version |= 1;
+                   }
+                   for(int j=19;j<27;j++){
+                      //Dbprintf("%d",dest[idx+j]);
+                      unknown <<=1;
+                      if (dest[idx+j]) unknown |= 1;
+                   }
+                   for(int j=36;j<45;j++){
+                      //Dbprintf("%d",dest[idx+j]);
+                      number <<=1;
+                      if (dest[idx+j]) number |= 1;
+                   }
+                   for(int j=46;j<53;j++){
+                      //Dbprintf("%d",dest[idx+j]);
+                      number <<=1;
+                      if (dest[idx+j]) number |= 1;
+                   }
+                   for(int j=0; j<32; j++){
+                       code <<=1;
+                       if(dest[idx+j]) code |= 1;
+                   }
+                   for(int j=32; j<64; j++){
+                       code2 <<=1;
+                       if(dest[idx+j]) code2 |= 1;
+                   }
+                   
+                   Dbprintf("XSF(%02d)%02x:%d (%08x%08x)",version,unknown,number,code,code2);
+                   if (ledcontrol)
+                       LED_D_OFF();
+               }
+               // if we're only looking for one tag 
+               if (findone){
+                       //*high = hi;
+                       //*low = lo;
+                       LED_A_OFF();
+                       return;
+               }
+      
+               //hi=0;
+               //lo=0;
+               found=0;
+         }
+
+       }
+       }
+       WDT_HIT();
+}
+
 /*------------------------------
  * T5555/T5557/T5567 routines
  *------------------------------
@@ -1166,6 +1424,26 @@
        DbpString("DONE!");
 }
 
+void CopyIOtoT55x7(uint32_t hi, uint32_t lo, uint8_t longFMT)
+{
+   int data1=0, data2=0; //up to six blocks for long format
+  
+    data1 = hi;  // load preamble
+    data2 = lo;
+    
+    LED_D_ON();
+    // Program the data blocks for supplied ID
+    // and the block 0 for HID format
+    T55xxWriteBlock(data1,1,0,0);
+    T55xxWriteBlock(data2,2,0,0);
+
+    //Config Block
+    T55xxWriteBlock(0x00147040,0,0,0);
+    LED_D_OFF();
+
+    DbpString("DONE!");
+}
+
 // Define 9bit header for EM410x tags
 #define EM410X_HEADER          0x1FF
 #define EM410X_ID_LENGTH       40
Index: client/Makefile
===================================================================
--- client/Makefile     (revision 844)
+++ client/Makefile     (working copy)
@@ -75,6 +75,7 @@
                        cmdhw.c \
                        cmdlf.c \
                        cmdlfhid.c \
+                       cmdlfio.c \
                        cmdlfem4x.c \
                        cmdlfhitag.c \
                        cmdlfti.c \
Index: client/cmdlf.c
===================================================================
--- client/cmdlf.c      (revision 844)
+++ client/cmdlf.c      (working copy)
@@ -27,6 +27,7 @@
 #include "cmdlfhitag.h"
 #include "cmdlft55xx.h"
 #include "cmdlfpcf7931.h"
+#include "cmdlfio.h"
 
 static int CmdHelp(const char *Cmd);
 
@@ -128,7 +129,7 @@
   RepaintGraphWindow();
   return 0;
 }
-
+  
 int CmdIndalaDemod(const char *Cmd)
 {
   // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
@@ -532,6 +533,7 @@
   {"em4x",        CmdLFEM4X,          1, "{ EM4X RFIDs... }"},
   {"flexdemod",   CmdFlexdemod,       1, "Demodulate samples for FlexPass"},
   {"hid",         CmdLFHID,           1, "{ HID RFIDs... }"},
+  {"io",         CmdLFIO,            1, "{ ioProx tags... }"},
   {"indalademod", CmdIndalaDemod,     1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
   {"indalaclone", CmdIndalaClone,     1, "<UID> ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"},
   {"read",        CmdLFRead,          0, "['h'|<divisor>] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134, alternatively: f=12MHz/(divisor+1))"},
Index: include/usb_cmd.h
===================================================================
--- include/usb_cmd.h   (revision 844)
+++ include/usb_cmd.h   (working copy)
@@ -79,6 +79,8 @@
 #define CMD_PCF7931_READ                                                  0x0217
 #define CMD_EM4X_READ_WORD                                                0x0218
 #define CMD_EM4X_WRITE_WORD                                               0x0219
+#define CMD_IO_DEMOD_FSK                                                  0x021A
+#define CMD_IO_CLONE_TAG                                                  0x021B
 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
 
 // For the 13.56 MHz tags

Offline

#13 2014-03-12 23:54:52

asper
Contributor
Registered: 2008-08-24
Posts: 1,409

Re: Kantech ioProx

Thank you man!
So was my bit "descrambling" pattern correct? It seems so...

Offline

#14 2014-03-13 09:02:33

midnitesnake
Contributor
Registered: 2012-05-11
Posts: 151

Re: Kantech ioProx

thanks man, looks like it...

I also only have 1 key, when i tested your code above, I successfully cloned my door-fob smile

Last edited by midnitesnake (2014-03-13 09:04:17)

Offline

#15 2014-03-13 10:57:28

asper
Contributor
Registered: 2008-08-24
Posts: 1,409

Re: Kantech ioProx

Good, i will add new commands to the gui; can someone upload the modified source files somewhere ?

EDIT: GUI modified, waiting for the new sources to be integrated with official release !

Last edited by asper (2014-03-14 12:47:59)

Offline

#16 2014-03-23 14:01:20

holiman
Contributor
Registered: 2013-05-03
Posts: 566

Re: Kantech ioProx

The patch does not work well when I try to apply the patch. Could you try again, or upload the patch somewhere instead of pasting it into the forum?

Offline

#17 2014-03-23 18:55:01

pentura_prox
Contributor
From: England,UK
Registered: 2014-03-11
Posts: 22
Website

Re: Kantech ioProx

Zip file with three patches (used the old fashioned diff -Npaur) command for these

http://www.datafilehost.com/d/22d15b44

Offline

#18 2014-03-23 22:47:07

holiman
Contributor
Registered: 2013-05-03
Posts: 566

Re: Kantech ioProx

Thanks!
I looked at the patches a bit more in-depth now, a few comments:

The big switch in armsrc:

+				switch (n) {			// stuff appropriate bits in buffer
+					case 0:
+					case 1:	// one bit
+						dest[i++]=dest[idx-1]^1;
+						//Dbprintf("%d",dest[idx-1]);
+						break;
+					case 2: // two bits
+						dest[i++]=dest[idx-1]^1;
+						dest[i++]=dest[idx-1]^1;
+						//Dbprintf("%d",dest[idx-1]);
+						//Dbprintf("%d",dest[idx-1]);
+						break;
+					case 3: // 3 bit start of frame markers
+						for(int j=0; j<3; j++){
+						  dest[i++]=dest[idx-1]^1;
+						//  Dbprintf("%d",dest[idx-1]);
+						}
+						break;
+					case 4:
+						for(int j=0; j<4; j++){
+						  dest[i++]=dest[idx-1]^1;
+						//  Dbprintf("%d",dest[idx-1]);
+						}
+						break;
+					case 5:
+						for(int j=0; j<5; j++){
+						  dest[i++]=dest[idx-1]^1;
+						//  Dbprintf("%d",dest[idx-1]);
+						}
+						break;
+					case 6:
+						for(int j=0; j<6; j++){
+						  dest[i++]=dest[idx-1]^1;
+						//  Dbprintf("%d",dest[idx-1]);
+						}
+						break;
+					case 7:
+						for(int j=0; j<7; j++){
+						  dest[i++]=dest[idx-1]^1;
+						//  Dbprintf("%d",dest[idx-1]);
+						}
+						break;

looks like it can be replaced with :

if (n < 13){
 for(int j=0; j<n; j++){
	  dest[i++]=dest[idx-1]^1;
 }
}

Could you see if that works instead?

Also, this chunk of code:

+        for( idx=0; idx<m-9; idx++) {
+	  if ( !(dest[idx]) && !(dest[idx+1]) && !(dest[idx+2]) && !(dest[idx+3]) && !(dest[idx+4]) && !(dest[idx+5]) && !(dest[idx+6]) && !(dest[idx+7]) && !(dest[idx+8])&& (dest[idx+9])){
+		found=1;
+		//idx+=9;
+		if (found) {
+		    Dbprintf("%d%d%d%d%d%d%d%d",dest[idx],   dest[idx+1],   dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7]);
+		    Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+8], dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15]);			  
+		    Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+16],dest[idx+17],dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23]);
+		    Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+24],dest[idx+25],dest[idx+26],dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31]);
+		    Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35],dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39]);
+		    Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44],dest[idx+45],dest[idx+46],dest[idx+47]);
+		    Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53],dest[idx+54],dest[idx+55]);
+		    Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]);

It looks like you're searching for a pattern, something like "0 0 0 0 0 0 0 0 0 1"? Could you replace that with a memcmp that you roll across the data instead?

Also, these chunks:

for(int j=14;j<18;j++){
		       //Dbprintf("%d",dest[idx+j]);
		       version <<=1;
		       if (dest[idx+j]) version |= 1;
	    }

It looks like you are just trying to pick out a four-byte sequence of bytes into a 'short'. Couldn't you reuse num_to_bytes or something similar?
I'll look through the rest later, a bit late now. I could try to clean it up a bit, but it's going to take a while before I have enough time and I don't have any tags to test with.

Offline

#19 2014-04-01 08:15:58

holiman
Contributor
Registered: 2013-05-03
Posts: 566

Re: Kantech ioProx

I did a heavy refactoring of lfops.c now. Both kantec and hid were changed, and I've only been able to test hid.
Previously, 'lf hid fskdemod' produced quite a lot of erroneous reads:

default:
0001 0100
#db# TAG ID: 20 06e2 31df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 400c231df (6383)   <              
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 006e231df (6383)   <              
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 801b881df (16623)  <             
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383)                 
#db# TAG ID: 2006e231df (6383) 

With my changes, it happens a lot less frequently.
Right now, it's on a branch in my forked proxmark: https://github.com/holiman/proxmark3/commits/ioprox_fixes
I'll commit it to main once I've gotten ioprox tag reading tested.

I'll do some initial testing on the two bitstreams posted by marshmellow.

Offline

#20 2014-04-16 18:09:41

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

marshmellow wrote:

nice work asper,  it appears bit 45 or 46 could be the static bit (I'd lean towards bit 45, but more card samples are needed) and it appears there may be an 8 bit checksum at the end: b54-b61

I have confirmed that the bit 45 is the static bit not 46.  46 should be included in the sequence number. 
the current implementation in the firmware is incorrect:
proxmark3> lf io fskdemod
proxmark3>
proxmark3> #db# 00000000                 
proxmark3> #db# 01111000                 
proxmark3> #db# 01110011                 
proxmark3> #db# 01100000                 
proxmark3> #db# 00110110                 
proxmark3> #db# 11111010                 
proxmark3> #db# 10101101                 
proxmark3> #db# 11110111                 
proxmark3> #db# XSF(01)9b:28629 (0078736036faadf7)       
   
should have read XSF(01)CD:28501 (0078736036faadf7)

it also appears the 9B is one digit off in the calculation- it appears to be using bit 20-27 not 19-26.

I'd fix it if I understood the code... sad

Other than that, I like the IO prox reading functions smile

Last edited by marshmellow (2014-04-16 18:10:58)

Offline

#21 2014-04-16 20:40:37

midnitesnake
Contributor
Registered: 2012-05-11
Posts: 151

Re: Kantech ioProx

Yeah - I've noticed a bit (worth 128decimal) appears in the wrong place, guessing it was also bit 45-46.  I haven't noticed any difference in the hex after the version?(bit in brackets).

Guess I was lucky when i cloned my door fob and it fell within an accepted range; my first fob didn't have a number on it to check.

Offline

#22 2014-04-16 20:51:22

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

The hex isn't affected, just the interpretation of the hex which gives you the numbers usually printed on the tag.

Offline

#23 2014-05-07 19:35:03

blogfish
Contributor
Registered: 2013-06-05
Posts: 17

Re: Kantech ioProx

7A : 40951 => 00785ea039ffbffb (source: -have card-)
7A : 40953 => 00785ea039ffcff3 (source: -have card-)
7A : 40954 => 00785ea039ffd7ef (source: -have card-)
7A : 40955 => 00785ea039ffdfeb (source: -have card-)
CD : 28501 => 0078736036faadf7 (source: marshmellow)
3B : 44725 => 00784ee03aedadc3 (source: carl)
BE : 03011 => 00786fa030be1e0b (source: carl)
C4 : 00949 => 00787120303dae4b (source: -have card-)
C4 : 00950 => 00787120303db643 (source: I guessed)
C5 : 00948 => 00787160303da64b (source: I guessed)
C5 : 00950 => 00787160303db643 (source: I guessed)

Also have the following info from tech support:
family code (between parentheses), 8 bits, available only when reading as XSF facility code,
8 bits card number,
16 bits facility code
2 bits parity
5 bits security (perhaps a checksum?)

And same cards but broken out into fields.

000000000111100001 01111010 1 00000001 1 100111111 1 1110111 1 11111110 1
000000000111100001 01111010 1 00000001 1 100111111 1 1111001 1 11111100 1
000000000111100001 01111010 1 00000001 1 100111111 1 1111010 1 11111011 1
000000000111100001 01111010 1 00000001 1 100111111 1 1111011 1 11111010 1
000000000111100001 00111011 1 00000001 1 101011101 1 0110101 1 01110000 1
000000000111100001 10111110 1 00000001 1 000010111 1 1000011 1 10000010 1
000000000111100001 11000100 1 00000001 1 000000111 1 0110101 1 10010010 1
000000000111100001 11000100 1 00000001 1 000000111 1 0110110 1 10010000 1
000000000111100001 11000101 1 00000001 1 000000111 1 0110100 1 10010010 1
000000000111100001 11000101 1 00000001 1 000000111 1 0110110 1 10010000 1
preamble     facility     family    num1    num2     checksum

It looks to me that there are 8 parity/checksum bits not 7 like tech support said. Perhaps 1 bit just duplicates another bit field. Any ideas on how to figure out the parity bits?

Offline

#24 2014-05-07 19:38:14

blogfish
Contributor
Registered: 2013-06-05
Posts: 17

Re: Kantech ioProx

oops this should have been:

Also have the following info from tech support:
8 bits family code (between parentheses), available only when reading as XSF
8 bits facility code
16 bits card number
2 bits parity
5 bits security

Offline

#25 2014-05-07 20:12:27

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

Your binary is short 1 bit (a 1 at the end of all of them) 
also note your break between num1 and num2 is off one bit (each broken out bits between the static 1's should be 8 bits)
interesting information from tech support.  Thanks.
if we knew where the parity were it would be just a matter of running enough samples to get what bits are used to calculate them.
the checksum would pose a larger issue in identifying the algorithm used to calculate it. (not my forte)
I agree that there appears to be 8 bits parity/checksum not 7.

Question:  you mention you "Guessed", does that mean you ran a bunch of possible bits until one correctly read with a ioProx reader?  (in other words are they verified working guesses?)

I'll take another look at these new samples to see if I see any parity patterns.

Offline

#26 2014-05-07 20:28:00

blogfish
Contributor
Registered: 2013-06-05
Posts: 17

Re: Kantech ioProx

No, num1 is 9 bits wide and num2 is 7 bits wide based on the binary string. Asper showed that (b37-b45)concatenate(b47-b53) = number. Perhaps I am missing something though.

Yes I was very bored one day and tried hundreds of combinations of parity and those came up correctly read with a rfideas ioprox reader.

Offline

#27 2014-05-07 20:53:35

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

I have several tags that shows the num1 and num2 need to be 8 bits or it doesn't calculate right (I outlined one in a previous post - where bit 46 = 0).  the samples asper had to work from originally did not have enough diversity to identify this.  (and in fact, your samples would calculate correctly either way as both bits 45 and 46 are 1's)

if you get bored again, try: 0000000001111000011100010010000000110000001111011010011001001111
(just a guess to test a theory)  card (01) C4 00948

Last edited by marshmellow (2014-05-08 03:12:34)

Offline

#28 2014-05-07 21:30:54

blogfish
Contributor
Registered: 2013-06-05
Posts: 17

Re: Kantech ioProx

Thank you marshmellow. That worked!

Offline

#29 2014-05-07 21:56:08

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

it appears that the calculation used in the checksum often is counting backwards when the card number is counting up. 
example:

card# - num2 - checksum(8bits to hex)
40953 - F9   - FC
40954 - FA   - FB
40955 - FB   - FA
00948 - B4   - 93
00949 - B5   - 92
00950 - B6   - 91? or 90?

I find that strange.  the first 4bits of the checksum I have no idea the calc, but the last four might be able to be guessed with a fairly good % of hits up to 16 cards?  I'm not sure.  (don't have an ioProx reader)

Offline

#30 2014-05-07 23:12:17

holiman
Contributor
Registered: 2013-05-03
Posts: 566

Re: Kantech ioProx

Edit: Never mind, I came up with the the same solution asper made. Just made an indexing error smile


I dont think there are any parity bits. At least no single, spread out parity bits. I tried doing a parity stream across the bits - if there are parity bits there, all different parity streams should always have the same value (0 or 1) at those positions - but that does not appear to be the case. So must be some kind of  "two-bit parity" or n-bit crc:s. But I may be wrong..

Last edited by holiman (2014-05-07 23:15:33)

Offline

#31 2014-10-10 16:11:17

14400bps
Contributor
Registered: 2014-10-10
Posts: 16

Re: Kantech ioProx

Hello,

I'm trying to figure out which thread I go to for latest ioProx updates.

- There is development discussed here http://www.proxmark.org/forum/viewtopic.php?id=1901  (ioProx code committed 2014-03-21)
- My proxmark3 came with gitbhub-20140401 and has "lf io fskdemod" functionatlity.  It sort of works.  When I scan ioProx dongle I get a result immediately and every time, however, each result is different.  I tried under Windows and Linux.  Same results.  I have scanned the same dongle 10 times and I get approx 8 unique readings.   Is that a known problem that you're discussing fixing in this thread?

Are you guys the same group working on the two versions I mentioned above?  Or are there couple of groups trying to accomplish the same thing in parallel?

Thank you

Offline

#32 2014-10-10 16:21:12

blogfish
Contributor
Registered: 2013-06-05
Posts: 17

Re: Kantech ioProx

I get slightly better results. Maybe 4 unique readings in 10 reads. I usually find that about half will be correct. (or at least I take it to be correct smile

Offline

#33 2014-10-10 17:33:21

14400bps
Contributor
Registered: 2014-10-10
Posts: 16

Re: Kantech ioProx

I tried again today and I got much more consistent results.  The only things that changed was that I was in a different room.  I was using the same software, the same proxmark, same commands.  Could interference play a role?   

My new results (placed in the center of the scanner):
ioProx card A: 10 scans 6 result=X, 4 with result=Y  (let's call this 6/4)
ioProx card B: 10 scans 9 result=X, 1 with result=Y  (let's call this 9/1)

Compare that with yesterday's results:
ioProx card A: 10 scans (2/1/1/1/1/1/1/1/1)

I also noticed several other things:
- If I held the tag in my fingers or dangled it over the scanner on a keyring, I would get (3/2/1/1/1/1/1) almost every scan unique
- If I placed the tag on the scanner slightly off center I would get (6/2/2)

I wish I could visually confirm which readings were right because my XSF(01) numbers are completely worn off.   I'll try to clone the winning entry (most common result) and see if it works I guess.

Offline

#34 2014-10-10 18:19:07

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

antenna strength and positioning of the card is key for FSK IO Prox reading.  typically a card held about an inch away from a good antenna will yield best results (in my opinion)

Offline

#35 2014-10-10 19:32:51

14400bps
Contributor
Registered: 2014-10-10
Posts: 16

Re: Kantech ioProx

I got my hands on a fob with a XSF number that's clearly visible.  FSK reading is pretty consistent now .... but wrong.   It's not even a close match.
I would post the number here, but this particular fob is one that is meant for a secured area, and I wouldn't want someone smart to come along and clone my fob from as we reveal more specifics here.

Offline

#36 2014-10-10 20:20:29

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

there is an known issue with the card number calculation in the proxmark firmware.  I've mentioned this in multiple posts including post #21 in this thread.

Offline

#37 2014-10-10 20:27:43

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

bit 45 should be static and not part of the num1, and bit 46 should be part of num2 not static.

Offline

#38 2014-10-10 20:28:45

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

the binary that the proxmark outputs is correct and can be used to calculate the correct number manually, and can be used to clone.

Offline

#39 2014-10-11 05:01:29

14400bps
Contributor
Registered: 2014-10-10
Posts: 16

Re: Kantech ioProx

Thanks marshmellow, I was able to clone using your suggestion.
I also verified your numbering scheme.  When I converted manually, I got the right XSF number.

You mentioned that if you were a programmer, you'd fix this problem yourself.  I know little bit of C, so I thought I'd fix it.   Trouble is it seems to be fixed already.

You suggest: number = 37-45 concatenated with 47-53

That's exactly what the patch (and the latest committed code does)

[== C++ ==]
		    for(int j=36;j<45;j++){ //36 because computers start counting at 0 ... so this is same as your 37. Ditto for 45
		       number <<=1; //number is shifted left to make space for the new bit that will be written in the next step.
		       if (dest[idx+j]) number |= 1; //if we are reading a 1 then put a 1 in the rightmost position. Else just keep going (default will be 0)
		    }
		    for(int j=46;j<53;j++){ //46 because computers start counting at 0 ... so this is same as your 47.  Ditto for 53
		       number <<=1;  //number is shifted left to make space for the new bit that will be written in the next step.
		       if (dest[idx+j]) number |= 1; /if we are reading a 1 then put a 1 in the rightmost position.  Else just keep going (default will be 0)
		    }

I can't see anything wrong here, but I must be missing something.  Unless we are using a wrong build.  But I can see that this was committed only once, so there should not be a bad version of this code out there.  I guess I could build from source to confirm, but right now I'm leaning towards the more likely possibility that I'm missing something when verifying this C code.

Offline

#40 2014-10-11 05:11:32

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

It should be j<44.  And then j = 45

We want to skip 45.  37-44 = 8 bits. Then 46-53 = 8 bits

Offline

#41 2014-10-11 05:21:26

14400bps
Contributor
Registered: 2014-10-10
Posts: 16

Re: Kantech ioProx

No, the skip of 45 is fine, but you made me realize that the first group is too long in the beginning.  It starts at 36, but should start at 37.  Correct code should be

[== C ==]
		    for(int j=37;j<45;j++){
		       number <<=1; 
		       if (dest[idx+j]) number |= 1;
		    }
		    for(int j=46;j<54;j++){ 
		       number <<=1; 
		       if (dest[idx+j]) number |= 1; 
		    }

Offline

#42 2014-10-11 05:23:03

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

Remember the loop may start at 0 instead of 1.

Offline

#43 2014-10-11 05:26:44

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

Which would make our ID bits 36-43 & 45-53

Offline

#44 2014-10-11 05:27:45

14400bps
Contributor
Registered: 2014-10-10
Posts: 16

Re: Kantech ioProx

While looking at that, I found another improvement.  Since bits 45,54,64 (and 63?) are always 0, the line

[== C ==]
 if ( !(dest[idx]) && !(dest[idx+1]) && !(dest[idx+2]) && !(dest[idx+3]) && !(dest[idx+4]) && !(dest[idx+5]) && !(dest[idx+6]) && !(dest[idx+7]) && !(dest[idx+8])&& (dest[idx+9])){

should be

[== C ==]
 if ( !(dest[idx]) && !(dest[idx+1]) && !(dest[idx+2]) && !(dest[idx+3]) && !(dest[idx+4]) && !(dest[idx+5]) && !(dest[idx+6]) && !(dest[idx+7]) && !(dest[idx+8])&& (dest[idx+9]) && (dest[idx+45]) && (dest[idx+54]) && !(dest[idx+64])){

What will that accomplish?  I noticed that a lot of the "bad scans" attributed to random chance and placing the fob incorrectly in front of the antenna can be filtered out because they don't match this pattern.  Any match that doesn't follow this pattern can be safely thrown away as incorrect.

Offline

#45 2014-10-11 05:32:23

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

Your array index starts at 0.  You will need to subtract one from each of those bit position numbers you added.

Offline

#46 2014-10-11 05:32:27

14400bps
Contributor
Registered: 2014-10-10
Posts: 16

Re: Kantech ioProx

Which would make our ID bits 36-43 & 45-53

Yes, I will have to be careful as the alignment (idx) may not be what I expect.  Nevertheless, the old code clearly has a size problem.  First group in old code is 9 and second group 7.  Has to be 8 and 8 and I can fix that.

I'll see if I can get my build environment setup for this, and I'll try to get a patch to with these two tweaks.  May take me a while as I'm away this weekend.

Offline

#47 2014-10-11 05:33:48

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

Cool.  And thx

Offline

#48 2014-10-11 05:35:45

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

Now if only I could figure out the xor checksum calc used at the end of the data...  smile

Last edited by marshmellow (2014-10-11 05:43:42)

Offline

#49 2014-10-11 06:04:09

14400bps
Contributor
Registered: 2014-10-10
Posts: 16

Re: Kantech ioProx

I was thinking CRC.  But CRC8 has 9 bits.   Do you know if you can have CRC of any length?  You mentioned xor checksum.  How do you figure it's XOR?

Offline

#50 2014-10-11 14:21:53

marshmellow
Contributor
From: US
Registered: 2013-06-10
Posts: 2,302

Re: Kantech ioProx

The way it counts backwards.  But I could be very wrong.

Offline

Board footer

Powered by FluxBB