]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - client/cmdhflegic.c
CHG: `lf read` - optional timeout, to be used when configured a threshold limit.
[proxmark3-svn] / client / cmdhflegic.c
index 60c2e858bb21ee84c5010a2da0f135843f0aedfd..4414efa1d2c2bd2ed979435030ce5a48b514e258 100644 (file)
@@ -149,7 +149,16 @@ int usage_legic_esave(void){
        PrintAndLog("      hf legic esave 2 myfile");
        return 0;
 }
-
+int usage_legic_wipe(void){
+       PrintAndLog("Fills a legic tag memory with zeros. From byte7 and to the end.");
+       PrintAndLog(" Usage:  hf legic wipe [h]");
+       PrintAndLog("Options:");
+       PrintAndLog("      h             : this help");
+       PrintAndLog("");
+       PrintAndLog("Samples:");        
+       PrintAndLog("      hf legic wipe");
+       return 0;
+}
 /*
  *  Output BigBuf and deobfuscate LEGIC RF tag data.
  *  This is based on information given in the talk held
@@ -506,8 +515,8 @@ int CmdLegicRdmem(const char *Cmd) {
                return 1;
        }
        
-       PrintAndLog("\n ##  | Data");
-       PrintAndLog("-----+-----");
+       PrintAndLog("\n ##  |  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F");
+       PrintAndLog("-----+------------------------------------------------------------------------------------------------");
        print_hex_break( data, readlen, 32);
        free(data);
        return 0;
@@ -518,7 +527,7 @@ int CmdLegicRdmem(const char *Cmd) {
 // int phase, int frame, int reqresp
 int CmdLegicRfSim(const char *Cmd) {
        UsbCommand c = {CMD_SIMULATE_TAG_LEGIC_RF, {6,3,0}};
-       sscanf(Cmd, " %"lli" %"lli" %"lli, &c.arg[0], &c.arg[1], &c.arg[2]);
+       sscanf(Cmd, " %" SCNi64 " %" SCNi64 " %" SCNi64 , &c.arg[0], &c.arg[1], &c.arg[2]);
        clearCommandBuffer();
        SendCommand(&c);
        return 0;
@@ -551,11 +560,19 @@ int CmdLegicRfWrite(const char *Cmd) {
                                errors = true;
                                break;
                        }
+                       
+                       // limit number of bytes to write. This is not a 'restore' command.
+                       if ( (len>>1) > 100 ){
+                               PrintAndLog("Max bound on 100bytes to write a one time.");
+                               PrintAndLog("Use the 'hf legic restore' command if you want to write the whole tag at once");
+                               errors = true;
+                       }
 
                        // it's possible for user to accidentally enter "b" parameter
                        // more than once - we have to clean previous malloc
                        if (data)
                                free(data);
+                       
                        data = malloc(len >> 1);
                        if ( data == NULL ) {
                                PrintAndLog("Can't allocate memory. exiting");
@@ -604,27 +621,41 @@ int CmdLegicRfWrite(const char *Cmd) {
        legic_print_type(card.cardsize, 0);
        
        // OUT-OF-BOUNDS checks
-       // UID 4 bytes can't be written to.
-       if ( offset < 4 ) {
-               PrintAndLog("Out-of-bounds, UID 4bytes can't be written to. Offset = %d", offset);
+       // UID 4+1 bytes can't be written to.
+       if ( offset < 5 ) {
+               PrintAndLog("Out-of-bounds, bytes 0-1-2-3-4 can't be written to. Offset = %d", offset);
                return -2;
        }
        
-       if ( len + offset + 4 >= card.cardsize ) {
-               PrintAndLog("Out-of-bounds, Cardsize = %d, [offset+len = %d ]", card.cardsize, len + offset + 4);
+       if ( len + offset >= card.cardsize ) {
+               PrintAndLog("Out-of-bounds, Cardsize = %d, [offset+len = %d ]", card.cardsize, len + offset);
                return -2;
        }
 
+       if (offset == 5 || offset == 6) {
+               PrintAndLog("############# DANGER ################");
+               PrintAndLog("# changing the DCF is irreversible  #");
+               PrintAndLog("#####################################");
+               char *answer = NULL;
+               answer = readline("do you really want to continue? y(es) n(o) : ");
+               bool overwrite = (answer[0] == 'y' || answer[0] == 'Y');
+               if (!overwrite){
+                       PrintAndLog("command cancelled");
+                       return 0;
+               }
+       }
+       
        legic_chk_iv(&IV);
        
        PrintAndLog("Writing to tag");
-    UsbCommand c = {CMD_WRITER_LEGIC_RF, {offset, len, IV}};
-       memcpy(c.d.asBytes, data, len);
-       
-       clearCommandBuffer();
-    SendCommand(&c);
+
+       UsbCommand c = {CMD_WRITER_LEGIC_RF, {offset, len, IV}};
+       memcpy(c.d.asBytes, data, len); 
        UsbCommand resp;
-       if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
+       clearCommandBuffer();
+       SendCommand(&c);
+       
+       if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
                PrintAndLog("command execution time out");
                return 1;
        }
@@ -633,20 +664,10 @@ int CmdLegicRfWrite(const char *Cmd) {
                PrintAndLog("failed writing tag");
                return 1;
        }
-       
+
     return 0;
 }
 
-/*
-       PrintAndLog("############# DANGER !! #############");
-       PrintAndLog("# changing the DCF is irreversible  #");
-       PrintAndLog("#####################################");
-       PrintAndLog("do youe really want to continue? y(es) n(o)");             
-       // if (scanf(" %c", &answer) > 0 && (answer == 'y' || answer == 'Y')) {
-               // return 0;
-       // }
-*/
-
 int CmdLegicCalcCrc(const char *Cmd){
 
        uint8_t *data = NULL;
@@ -903,7 +924,8 @@ int CmdLegicDump(const char *Cmd){
        else
                sprintf(fnameptr + fileNlen,".bin");
 
-       if ((f = fopen(filename,"wb")) == NULL) { 
+       f = fopen(filename,"wb");
+       if (!f) { 
                PrintAndLog("Could not create file name %s", filename);
                if (data)
                        free(data);
@@ -922,7 +944,7 @@ int CmdLegicRestore(const char *Cmd){
        char filename[FILE_PATH_SIZE] = {0x00};
        char *fnameptr = filename;
        size_t fileNlen = 0;
-       bool errors = false;
+       bool errors = true;
        uint16_t numofbytes;    
        uint8_t cmdp = 0;
        
@@ -938,17 +960,20 @@ int CmdLegicRestore(const char *Cmd){
                        case 'I':
                                fileNlen = param_getstr(Cmd, cmdp+1, filename);
                                if (!fileNlen) 
-                                       errors = true; 
+                                       errors = true;
+                               else 
+                                       errors = false;
+                               
                                if (fileNlen > FILE_PATH_SIZE-5) 
                                        fileNlen = FILE_PATH_SIZE-5;
-                               cmdp += 2;
+                               cmdp += 2;                              
                                break;
                        default:
                                PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
                                errors = true;
                                break;
                }
-               if(errors) break;
+               if (errors) break;
        }
 
        //Validations
@@ -966,7 +991,7 @@ int CmdLegicRestore(const char *Cmd){
        uint8_t *data = malloc(numofbytes);
        if (!data) {
                PrintAndLog("Fail, cannot allocate memory");
-               return 3;               
+               return 2;               
        }
        memset(data, 0, numofbytes);
        
@@ -975,34 +1000,66 @@ int CmdLegicRestore(const char *Cmd){
        // set up file
        fnameptr += fileNlen;
        sprintf(fnameptr, ".bin");
-       
-       PrintAndLog("Reading binary file...");
 
-       if ((f = fopen(filename,"rb")) == NULL) {
+       f = fopen(filename,"rb");
+       if (!f) {
                PrintAndLog("File %s not found or locked", filename);
-               return 2;
+               return 3;
        }       
        
-       // verify size of dumpfile is the same as card.
+       // verify size of dumpfile is the same as card. 
+       fseek(f, 0, SEEK_END); // seek to end of file
+       size_t filesize = ftell(f); // get current file pointer
+       fseek(f, 0, SEEK_SET); // seek back to beginning of file
+       
+       if ( filesize != numofbytes) {
+               PrintAndLog("Fail, filesize and cardsize is not equal. [%u != %u]", filesize, numofbytes);
+               free(data);
+               fclose(f);
+               return 4;
+       }
 
        // load file
        size_t bytes_read = fread(data, 1, numofbytes, f);
+       fclose(f);
+       
        if ( bytes_read == 0){
                PrintAndLog("File reading error");
                free(data);
-               fclose(f);
                return 2;
        }
-       fclose(f);
-
-       PrintAndLog("Restoring %s to card", filename);
-
-       //loop writing :)
+       
+       PrintAndLog("Restoring to card");
 
-       //endloop
+       // transfer to device
+       size_t len = 0;
+       UsbCommand c = {CMD_WRITER_LEGIC_RF, {0, 0, 0x55}};
+       UsbCommand resp;
+       for(size_t i = 7; i < numofbytes; i += USB_CMD_DATA_SIZE) {
+               
+               len = MIN((numofbytes - i), USB_CMD_DATA_SIZE);         
+               c.arg[0] = i; // offset
+               c.arg[1] = len; // number of bytes
+               memcpy(c.d.asBytes, data+i, len); 
+               clearCommandBuffer();
+               SendCommand(&c);
+       
+               if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
+                       PrintAndLog("command execution time out");
+                       free(data);     
+                       return 1;
+               }
+               uint8_t isOK = resp.arg[0] & 0xFF;
+               if ( !isOK ) {
+                       PrintAndLog("failed writing tag [msg = %u]", resp.arg[1] & 0xFF);
+                       free(data);     
+                       return 1;
+               }
+               PrintAndLog("Wrote chunk [offset %d | len %d | total %d", i, len, i+len);
+       }       
        
        free(data);     
-       PrintAndLog("\nLoaded %d bytes from file: %s  to emulator memory", numofbytes, filename);
+       PrintAndLog("\nWrote %d bytes to card from file %s", numofbytes, filename);
        return 0;
 }
 
@@ -1041,7 +1098,8 @@ int CmdLegicELoad(const char *Cmd) {
        sprintf(fnameptr, ".bin");
        
        // open file
-       if ((f = fopen(filename,"rb")) == NULL) { 
+       f = fopen(filename,"rb");
+       if (!f) { 
                PrintAndLog("File %s not found or locked", filename);
                free(data);
                return 1;
@@ -1053,9 +1111,11 @@ int CmdLegicELoad(const char *Cmd) {
                PrintAndLog("File reading error");
                free(data);
                fclose(f);
+               f = NULL;               
                return 2;
        }
        fclose(f);
+       f = NULL;
        
        // transfer to device
        legic_seteml(data, 0, numofbytes);
@@ -1115,7 +1175,8 @@ int CmdLegicESave(const char *Cmd) {
                sprintf(fnameptr + fileNlen,".bin");
        
        // open file
-       if ((f = fopen(filename,"wb")) == NULL) { 
+       f = fopen(filename,"wb");
+       if (!f) { 
                PrintAndLog("Could not create file name %s", filename);
                free(data);
                return 1;
@@ -1127,6 +1188,61 @@ int CmdLegicESave(const char *Cmd) {
        return 0;
 }
 
+int CmdLegicWipe(const char *Cmd){
+
+       char cmdp = param_getchar(Cmd, 0);
+       
+       if ( cmdp == 'h' || cmdp == 'H') return usage_legic_wipe();
+       
+       // tagtype
+       legic_card_select_t card;
+       if (legic_get_type(&card)) {
+               PrintAndLog("Failed to identify tagtype");
+               return 1;
+       }
+       
+       // set up buffer
+       uint8_t *data = malloc(card.cardsize);
+       if (!data) {
+               PrintAndLog("Fail, cannot allocate memory");
+               return 2;               
+       }
+       memset(data, 0, card.cardsize);
+       
+       legic_print_type(card.cardsize, 0);
+
+       printf("Erasing");
+       
+       // transfer to device
+       size_t len = 0;
+       UsbCommand c = {CMD_WRITER_LEGIC_RF, {0, 0, 0x55}};
+       UsbCommand resp;
+       for(size_t i = 7; i < card.cardsize; i += USB_CMD_DATA_SIZE) {
+               
+               printf(".");
+               len = MIN((card.cardsize - i), USB_CMD_DATA_SIZE);              
+               c.arg[0] = i; // offset
+               c.arg[1] = len; // number of bytes
+               memcpy(c.d.asBytes, data+i, len); 
+               clearCommandBuffer();
+               SendCommand(&c);
+       
+               if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
+                       PrintAndLog("command execution time out");
+                       free(data);     
+                       return 3;
+               }
+               uint8_t isOK = resp.arg[0] & 0xFF;
+               if ( !isOK ) {
+                       PrintAndLog("failed writing tag [msg = %u]", resp.arg[1] & 0xFF);
+                       free(data);     
+                       return 4;
+               }
+       }
+       printf("ok\n");
+       return 0;
+}
+
 int CmdLegicList(const char *Cmd) {
        CmdHFList("legic");
        return 0;
@@ -1145,6 +1261,7 @@ static command_t CommandTable[] =  {
        {"eload",       CmdLegicELoad,          1, "Load binary dump to emulator memory"},
        {"esave",       CmdLegicESave,          1, "Save emulator memory to binary file"},
        {"list",        CmdLegicList,           1, "[Deprecated] List LEGIC history"},
+       {"wipe",        CmdLegicWipe,           1, "Wipe a LEGIC Prime tag"},
        {NULL, NULL, 0, NULL}
 };
 
Impressum, Datenschutz