diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 6800a36f8..eeb986501 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -571,7 +571,7 @@ int HF15Reader(const char *Cmd, bool verbose) { return 0; } - PrintAndLog(" UID : %s", sprintUID(NULL, uid)); + PrintAndLog(" UID : %s", sprintUID(NULL, uid)); PrintAndLog(" TYPE : %s", getTagInfo_15(uid)); return 1; } @@ -621,20 +621,56 @@ int CmdHF15Afi(const char *Cmd) { return 0; } +typedef struct { + uint8_t lock; + uint8_t block[4]; +} t15memory; + // Reads all memory pages // need to write to file // helptext int CmdHF15Dump(const char*Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_15_dump(); - + uint8_t fileNameLen = 0; + char filename[FILE_PATH_SIZE] = {0}; + char * fptr = filename; + bool errors = false; + uint8_t cmdp = 0; + uint8_t uid[8] = {0,0,0,0,0,0,0,0}; - if (!getUID(uid)) { - PrintAndLog("No Tag found."); - return 0; + PrintAndLog("No tag found."); + return 1; } + + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch(param_getchar(Cmd, cmdp)) { + case 'h': + case 'H': + return usage_15_dump(); + case 'f': + case 'F': + fileNameLen = param_getstr(Cmd, cmdp+1, filename); + if (fileNameLen < 1) { + PrintAndLog("Using UID as filename"); + + fptr += sprintf(fptr, "dump15_"); + + for (int j = sizeof(uid)-1; j >=0 ; j--) { + fptr += sprintf(fptr, "%02X", uid[j]); + } + } + cmdp += 2; + break; + default: + PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + //Validations + if (errors) return usage_15_dump(); + // detect blocksize from card :) PrintAndLog("Reading memory from tag UID %s", sprintUID(NULL, uid)); @@ -642,6 +678,9 @@ int CmdHF15Dump(const char*Cmd) { int reqlen = 0, blocknum = 0; uint8_t *recv = NULL; + // memory. + t15memory mem[256]; + uint8_t data[256*4] = {0}; memset(data, 0, sizeof(data)); @@ -677,6 +716,9 @@ int CmdHF15Dump(const char*Cmd) { if (!(recv[0] & ISO15_RES_ERROR)) { + mem[blocknum].lock = resp.d.asBytes[0]; + memcpy(mem[blocknum].block, resp.d.asBytes + 1, 4); + memcpy(data + (blocknum * 4), resp.d.asBytes + 1, 4); retry = 0; @@ -686,32 +728,33 @@ int CmdHF15Dump(const char*Cmd) { } else { PrintAndLog("\nTag returned Error %i: %s", recv[1], TagErrorStr(recv[1]) ); break; - // return 1; } + } else { + PrintAndLog("crc fail"); } } } printf("\n"); - PrintAndLog("Blk| data | ascii"); - PrintAndLog("---+---------------------+----------"); - for (int i=0; i < blocknum; i++) { - PrintAndLog("%02x | %s", i, sprint_hex_ascii(data + (i*4) , 4 ) ); + PrintAndLog("Block# | Data |lck| Ascii"); + PrintAndLog("---------+--------------+---+----------"); + for (int i = 0; i < blocknum; i++) { + PrintAndLog("%3d/0x%02X | %s | %d | %s", i, i, sprint_hex(mem[i].block, 4 ), mem[i].lock, sprint_ascii(mem[i].block, 4) ); } - - // TODO: need fix -// if (resp.arg[0]<3) -// PrintAndLog("Lost Connection"); -// else if (ISO15_CRC_CHECK != Crc(resp.d.asBytes, resp.arg[0]-2)) -// PrintAndLog("CRC Failed"); -// else -// PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1])); - return 1; + + printf("\n"); + + size_t datalen = blocknum*4; + saveFileEML(filename, "eml", data, datalen, 4); + saveFile(filename, "bin", data, datalen); + return 0; } int CmdHF15Restore(const char*Cmd) { // read from file - // write to tag + // loop file + // write block to tag + // end loop return usage_15_restore(); } @@ -949,7 +992,7 @@ int CmdHF15Readmulti(const char *Cmd) { recv = resp.d.asBytes; - if (ISO15_CRC_CHECK == Crc(recv, status-2)) { + if (ISO15_CRC_CHECK == Crc(recv, status)) { PrintAndLog("CRC failed"); return 2; } @@ -1017,7 +1060,7 @@ int CmdHF15Read(const char *Cmd) { recv = resp.d.asBytes; - if (ISO15_CRC_CHECK == Crc(recv, status-2)) { + if (ISO15_CRC_CHECK == Crc(recv, status)) { PrintAndLog("CRC failed"); return 2; } @@ -1097,7 +1140,7 @@ int CmdHF15Write(const char *Cmd) { recv = resp.d.asBytes; - if (ISO15_CRC_CHECK == Crc(recv, status-2)) { + if (ISO15_CRC_CHECK == Crc(recv, status)) { PrintAndLog("CRC failed"); return 2; } diff --git a/client/cmdhf15.h b/client/cmdhf15.h index ba605c5ed..8a0011d1f 100644 --- a/client/cmdhf15.h +++ b/client/cmdhf15.h @@ -25,6 +25,7 @@ #include "iso15693tools.h" // iso15 crc #include "cmdmain.h" #include "cmddata.h" // getsamples +#include "loclass/fileutils.h" // savefileEML int CmdHF15(const char *Cmd); diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 2ed19ac78..f442e0cfb 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -63,33 +63,82 @@ int fileExists(const char *filename) { int saveFile(const char *preferredName, const char *suffix, const void* data, size_t datalen) { - int size = sizeof(char) * (strlen(preferredName)+strlen(suffix)+10); + int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10); char * fileName = malloc(size); - memset(fileName,0,size); + memset(fileName, 0, size); int num = 1; sprintf(fileName,"%s.%s", preferredName, suffix); - while(fileExists(fileName)) - { + while (fileExists(fileName)) { sprintf(fileName,"%s-%d.%s", preferredName, num, suffix); num++; } /* We should have a valid filename now, e.g. dumpdata-3.bin */ /*Opening file for writing in binary mode*/ - FILE *f = fopen(fileName,"wb"); + FILE *f = fopen(fileName, "wb"); if (!f) { - prnlog("Failed to write to file '%s'", fileName); + prnlog("File not found or locked. '%s'", fileName); free(fileName); return 1; } fwrite(data, 1, datalen, f); - if (f) - fclose(f); - prnlog("Saved data to '%s'", fileName); + fflush(f); + fclose(f); + prnlog("Saved %u bytes to binary file %s", datalen, fileName); free(fileName); return 0; } +int saveFileEML(const char *preferredName, const char *suffix, uint8_t* data, size_t datalen, size_t blocksize) { + + if ( preferredName == NULL ) return 1; + if ( suffix == NULL ) return 1; + if ( data == NULL ) return 1; + + int retval = 0; + int blocks = datalen/blocksize; + int i,j; + int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10); + char * fileName = malloc(size); + + memset(fileName, 0, size); + int num = 1; + sprintf(fileName,"%s.%s", preferredName, suffix); + while (fileExists(fileName)) { + sprintf(fileName,"%s-%d.%s", preferredName, num, suffix); + num++; + } + + /* We should have a valid filename now, e.g. dumpdata-3.bin */ + + /*Opening file for writing in text mode*/ + FILE *f = fopen(fileName, "w+"); + if (!f) { + prnlog("File not found or locked. '%s'", fileName); + retval = 1; + goto out; + } + + for (i = 0; i < datalen; i++) { + fprintf(f, "%02X", data[i] ); + if ( (i+1) % 4 == 0) + fprintf(f, "\n"); + } + // left overs + if ( datalen % blocksize != 0) { + int index = blocks * blocksize; + for (j = 0; j < datalen % blocksize; j++) { + fprintf(f, "%02X", data[index + j] ); + } + } + fflush(f); + fclose(f); + prnlog("Saved %d blocks to text file %s", blocks, fileName); + +out: + free(fileName); + return retval; +} /** * Utility function to print to console. This is used consistently within the library instead @@ -107,7 +156,6 @@ void prnlog(char *fmt, ...) vsprintf (buffer,fmt, args); va_end(args); PrintAndLog(buffer); - } #else //if we're on ARM void prnlog(char *fmt,...) diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index f18472ab4..a59704f34 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -41,8 +41,9 @@ #ifndef ON_DEVICE +#include /** - * @brief Utility function to save data to a file. This method takes a preferred name, but if that + * @brief Utility function to save data to a binary file. This method takes a preferred name, but if that * file already exists, it tries with another name until it finds something suitable. * E.g. dumpdata-15.txt * @param preferredName @@ -51,7 +52,20 @@ * @param datalen the length of the data * @return 0 for ok, 1 for failz */ -int saveFile(const char *preferredName, const char *suffix, const void* data, size_t datalen); +extern int saveFile(const char *preferredName, const char *suffix, const void* data, size_t datalen); + +/** + * @brief Utility function to save data to a textfile. This method takes a preferred name, but if that + * file already exists, it tries with another name until it finds something suitable. + * E.g. dumpdata-15.txt + * @param preferredName + * @param suffix the file suffix. Leave out the ".". + * @param data The binary data to write to the file + * @param datalen the length of the data + * @param blocksize the length of one row + * @return 0 for ok, 1 for failz +*/ +extern int saveFileEML(const char *preferredName, const char *suffix, uint8_t* data, size_t datalen, size_t blocksize); /** * @brief Utility function to save load binary data from a a file. This method takes a filename, * Should only be used for fixed-size binary files