]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - client/cmdhflegic.c
ADD: added a comment about Q5 settings. needs to be verified
[proxmark3-svn] / client / cmdhflegic.c
index 8310da8619f01ba53f07f214e88af5984b4410cd..0262f81c5560a7e1160b9dde859d7fb9f8d26e04 100644 (file)
@@ -38,9 +38,20 @@ int usage_legic_load(void){
        return 0;
 }
 
+int usage_legic_read(void){    
+       PrintAndLog("Read data from a legic tag.");
+       PrintAndLog("Usage:  hf legic read <offset> <num of bytes>");
+       PrintAndLog("Options :");
+       PrintAndLog("  <offset>        : offset in data array to start download from");
+       PrintAndLog("  <num of bytes>  : number of bytes to download");
+       PrintAndLog("");
+       PrintAndLog(" sample: hf legic read");
+       return 0;
+}
+
 /*
  *  Output BigBuf and deobfuscate LEGIC RF tag data.
- *   This is based on information given in the talk held
+ *  This is based on information given in the talk held
  *  by Henryk Ploetz and Karsten Nohl at 26c3
  */
 int CmdLegicDecode(const char *Cmd) {
@@ -53,11 +64,11 @@ int CmdLegicDecode(const char *Cmd) {
        int crc = 0;
        int wrp = 0;
        int wrc = 0;
-       uint8_t data_buf[1200]; // receiver buffer,  should be 1024..
+       uint8_t data_buf[1024]; // receiver buffer,  should be 1024..
        char token_type[4];
 
-       // copy data from proxmark into buffer
-       GetFromBigBuf(data_buf, sizeof(data_buf), 0);
+       // download EML memory, where the "legic read" command puts the data.
+       GetEMLFromBigBuf(data_buf, sizeof(data_buf), 0);
        if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2000)){
                PrintAndLog("Command execute timeout");
                return 1;
@@ -68,7 +79,7 @@ int CmdLegicDecode(const char *Cmd) {
        uint32_t calc_crc =  CRC8Legic(data_buf, 4);    
        
        PrintAndLog("\nCDF: System Area");
-
+       PrintAndLog("------------------------------------------------------");
        PrintAndLog("MCD: %02x, MSN: %02x %02x %02x, MCC: %02x %s",
                data_buf[0],
                data_buf[1],
@@ -118,8 +129,24 @@ int CmdLegicDecode(const char *Cmd) {
        uint32_t segCalcCRC = 0;
        uint32_t segCRC = 0;
 
+       // see if user area is xored or just zeros.
+       int numOfZeros = 0;
+       for (int index=22; index < 256; ++index){
+               if ( data_buf[index] == 0x00 )
+                       ++numOfZeros;
+       }
+       // if possible zeros is less then 60%, lets assume data is xored
+       // 256  - 22 (header) = 234
+       // 1024 - 22 (header) = 1002
+       int isXored = (numOfZeros*100/stamp_len) < 50;
+       PrintAndLog("is data xored?  %d  ( %d %)", isXored, (numOfZeros*100/stamp_len));
+
+       print_hex_break( data_buf, 33, 16);
+       
+       return 0;
+       
        PrintAndLog("\nADF: User Area");
-       printf("-------------------------------------\n");
+       PrintAndLog("------------------------------------------------------");
        i = 22;  
        // 64 potential segements
        // how to detect there is no segments?!?
@@ -148,7 +175,7 @@ int CmdLegicDecode(const char *Cmd) {
                segCalcCRC = CRC8Legic(segCrcBytes, 8);
                segCRC = data_buf[i+4]^crc;
 
-               PrintAndLog("Segment %02u \nraw header=0x%02X 0x%02X 0x%02X 0x%02X \nSegment len: %u,  Flag: 0x%X (valid:%01u, last:%01u), WRP: %02u, WRC: %02u, RD: %01u, CRC: 0x%02X (%s)",
+               PrintAndLog("Segment %02u \nraw header | 0x%02X 0x%02X 0x%02X 0x%02X \nSegment len: %u,  Flag: 0x%X (valid:%01u, last:%01u), WRP: %02u, WRC: %02u, RD: %01u, CRC: 0x%02X (%s)",
                        segmentNum,
                        data_buf[i]^crc,
                        data_buf[i+1]^crc,
@@ -169,9 +196,10 @@ int CmdLegicDecode(const char *Cmd) {
     
                if ( hasWRC ) {
                        PrintAndLog("WRC protected area:   (I %d | K %d| WRC %d)", i, k, wrc);
-
+                       PrintAndLog("\nrow  | data");
+                       PrintAndLog("-----+------------------------------------------------");
                        // de-xor?  if not zero, assume it needs xoring.
-                       if ( data_buf[i] > 0) {
+                       if ( isXored) {
                                for ( k=i; k < wrc; ++k)
                                        data_buf[k] ^= crc;
                        }
@@ -182,9 +210,10 @@ int CmdLegicDecode(const char *Cmd) {
     
                if ( hasWRP ) {
                        PrintAndLog("Remaining write protected area:  (I %d | K %d | WRC %d | WRP %d  WRP_LEN %d)",i, k, wrc, wrp, wrp_len);
+                       PrintAndLog("\nrow  | data");
+                       PrintAndLog("-----+------------------------------------------------");
 
-                       // de-xor?  if not zero, assume it needs xoring.
-                       if ( data_buf[i] > 0) {
+                       if (isXored) {
                                for (k=i; k < wrp_len; ++k)
                                        data_buf[k] ^= crc;
                        }
@@ -199,8 +228,9 @@ int CmdLegicDecode(const char *Cmd) {
                }
     
                PrintAndLog("Remaining segment payload:  (I %d | K %d | Remain LEN %d)", i, k, remain_seg_payload_len);
-               
-               if ( data_buf[i] > 0 ) {
+               PrintAndLog("\nrow  | data");
+               PrintAndLog("-----+------------------------------------------------");
+               if ( isXored ) {
                        for ( k=i; k < remain_seg_payload_len; ++k)
                                data_buf[k] ^= crc;
                }
@@ -209,7 +239,7 @@ int CmdLegicDecode(const char *Cmd) {
     
                i += remain_seg_payload_len;
                
-               printf("\n-------------------------------------\n");
+               PrintAndLog("-----+------------------------------------------------\n");
 
                // end with last segment
                if (segment_flag & 0x8) return 0;
@@ -219,6 +249,13 @@ int CmdLegicDecode(const char *Cmd) {
 }
 
 int CmdLegicRFRead(const char *Cmd) {
+       
+       // params:
+       // offset in data
+       // number of bytes.
+       char cmdp = param_getchar(Cmd, 0);
+       if ( cmdp == 'H' || cmdp == 'h' ) return usage_legic_read();
+       
        int byte_count=0, offset=0;
        sscanf(Cmd, "%i %i", &offset, &byte_count);
        if(byte_count == 0) byte_count = -1;
@@ -332,18 +369,18 @@ int CmdLegicSave(const char *Cmd) {
                return 0;
        }
 
-       FILE *f = fopen(filename, "w");
-       if(!f) {
-               PrintAndLog("couldn't open '%s'", Cmd+1);
-               return -1;
-       }
-
        GetFromBigBuf(got, requested, offset);
        if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2000)){
-               PrintAndLog("Command execute timeout");
+               PrintAndLog("Command execute timeout"); 
                return 1;
        }
 
+       FILE *f = fopen(filename, "w");
+       if(!f) {
+               PrintAndLog("couldn't open '%s'", Cmd+1);
+               return -1;
+       }
+       
        for (int j = 0; j < requested; j += 8) {
                fprintf(f, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
                        got[j+0], got[j+1], got[j+2], got[j+3],
@@ -407,12 +444,16 @@ int CmdLegicRfFill(const char *Cmd) {
 int CmdLegicCalcCrc8(const char *Cmd){
 
        int len =  strlen(Cmd); 
-       if (len & 1 ) return usage_legic_calccrc8(); 
+       if ( len & 1 ) return usage_legic_calccrc8(); 
        
-       uint8_t *data = malloc(len);
+       // add 1 for null terminator.
+       uint8_t *data = malloc(len+1);
        if ( data == NULL ) return 1;
                
-       param_gethex(Cmd, 0, data, len );
+       if (param_gethex(Cmd, 0, data, len )) {
+               free(data);
+               return usage_legic_calccrc8();  
+       }
        
        uint32_t checksum =  CRC8Legic(data, len/2);    
        PrintAndLog("Bytes: %s || CRC8: %X", sprint_hex(data, len/2), checksum );
Impressum, Datenschutz