added obsfuscation optionally for dump/restore/eload/esave, consider it wip. As of byte 22.

This commit is contained in:
iceman1001 2020-04-03 20:51:01 +02:00
commit 45223ee5d5

View file

@ -104,23 +104,26 @@ static int usage_legic_dump(void) {
PrintAndLogEx(NORMAL, "Read all memory from LEGIC Prime MIM22, MIM256, MIM1024"); PrintAndLogEx(NORMAL, "Read all memory from LEGIC Prime MIM22, MIM256, MIM1024");
PrintAndLogEx(NORMAL, "and saves bin/eml/json dump file"); PrintAndLogEx(NORMAL, "and saves bin/eml/json dump file");
PrintAndLogEx(NORMAL, "It autodetects card type.\n"); PrintAndLogEx(NORMAL, "It autodetects card type.\n");
PrintAndLogEx(NORMAL, "Usage: hf legic dump [h] f <filename w/o .bin>\n"); PrintAndLogEx(NORMAL, "Usage: hf legic dump [h] [x] [f <filename w/o .bin>]\n");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " f <filename> : filename w/o '.bin' to dump bytes"); PrintAndLogEx(NORMAL, " f <filename> : filename w/o '.bin' to dump bytes");
PrintAndLogEx(NORMAL, " x : deobfuscate dump data");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic dump -- uses UID as filename")); PrintAndLogEx(NORMAL, _YELLOW_(" hf legic dump -- uses UID as filename"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic dump f myfile")); PrintAndLogEx(NORMAL, _YELLOW_(" hf legic dump f myfile"));
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic dump x"));
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static int usage_legic_restore(void) { static int usage_legic_restore(void) {
PrintAndLogEx(NORMAL, "Reads binary file and it autodetects card type and verifies that the file has the same size"); PrintAndLogEx(NORMAL, "Reads binary file and it autodetects card type and verifies that the file has the same size");
PrintAndLogEx(NORMAL, "Then write the data back to card. All bytes except the first 7bytes [UID(4) MCC(1) DCF(2)]\n"); PrintAndLogEx(NORMAL, "Then write the data back to card. All bytes except the first 7bytes [UID(4) MCC(1) DCF(2)]\n");
PrintAndLogEx(NORMAL, "Usage: hf legic restore [h] [f <filename w/o .bin>]\n"); PrintAndLogEx(NORMAL, "Usage: hf legic restore [h] [x] [f <filename w/o .bin>]\n");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, " h : this help");
PrintAndLogEx(NORMAL, " f <filename> : filename w/o '.bin' to restore bytes on to card from"); PrintAndLogEx(NORMAL, " f <filename> : filename w/o '.bin' to restore bytes on to card from");
PrintAndLogEx(NORMAL, " x : obfuscate dump data");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic restore f myfile")); PrintAndLogEx(NORMAL, _YELLOW_(" hf legic restore f myfile"));
@ -166,6 +169,25 @@ static int usage_legic_wipe(void) {
PrintAndLogEx(NORMAL, _YELLOW_(" hf legic wipe")); PrintAndLogEx(NORMAL, _YELLOW_(" hf legic wipe"));
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static bool legic_xor(uint8_t *data, uint8_t cardsize) {
bool ret = true;
uint8_t crc = data[4];
uint32_t calc_crc = CRC8Legic(data, 4);
if (crc != calc_crc) {
PrintAndLogEx(INFO, "Crc mismatch, obsfuscation not possible");
ret = false;
} else if (cardsize <= 22) {
PrintAndLogEx(INFO, "No obsfuscation such small dump");
} else {
for(uint16_t i = 22; i < cardsize - 22; i++) {
data[i] ^= crc;
}
PrintAndLogEx(SUCCESS, "Obsfuscation done");
}
return ret;
}
/* /*
* Output BigBuf and deobfuscate LEGIC RF tag data. * 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
@ -531,7 +553,6 @@ static int CmdLegicRdbl(const char *Cmd) {
} }
static int CmdLegicSim(const char *Cmd) { static int CmdLegicSim(const char *Cmd) {
char cmdp = tolower(param_getchar(Cmd, 0)); char cmdp = tolower(param_getchar(Cmd, 0));
if (strlen(Cmd) == 0 || cmdp == 'h') return usage_legic_sim(); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_legic_sim();
@ -869,7 +890,7 @@ static int CmdLegicDump(const char *Cmd) {
int fileNameLen = 0; int fileNameLen = 0;
char filename[FILE_PATH_SIZE] = {0x00}; char filename[FILE_PATH_SIZE] = {0x00};
char *fptr = filename; char *fptr = filename;
bool errors = false; bool errors = false, shall_deobsfuscate = false;
uint16_t dumplen; uint16_t dumplen;
uint8_t cmdp = 0; uint8_t cmdp = 0;
@ -885,6 +906,10 @@ static int CmdLegicDump(const char *Cmd) {
fileNameLen = FILE_PATH_SIZE - 5; fileNameLen = FILE_PATH_SIZE - 5;
cmdp += 2; cmdp += 2;
break; break;
case 'x':
shall_deobsfuscate = true;
cmdp++;
break;
default: default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true; errors = true;
@ -950,6 +975,10 @@ static int CmdLegicDump(const char *Cmd) {
fptr += sprintf(fptr, "hf-legic-"); fptr += sprintf(fptr, "hf-legic-");
FillFileNameByUID(fptr, data, "-dump", 4); FillFileNameByUID(fptr, data, "-dump", 4);
} }
if (shall_deobsfuscate) {
legic_xor(data, card.cardsize);
}
saveFile(filename, ".bin", data, readlen); saveFile(filename, ".bin", data, readlen);
saveFileEML(filename, data, readlen, 8); saveFileEML(filename, data, readlen, 8);
@ -959,12 +988,10 @@ static int CmdLegicDump(const char *Cmd) {
static int CmdLegicRestore(const char *Cmd) { static int CmdLegicRestore(const char *Cmd) {
FILE *f;
char filename[FILE_PATH_SIZE] = {0x00}; char filename[FILE_PATH_SIZE] = {0x00};
char *fnameptr = filename;
size_t fileNlen = 0; size_t fileNlen = 0;
bool errors = false; bool errors = false, shall_obsfuscate = false;
uint16_t numofbytes; size_t numofbytes;
uint8_t cmdp = 0; uint8_t cmdp = 0;
memset(filename, 0, sizeof(filename)); memset(filename, 0, sizeof(filename));
@ -974,7 +1001,7 @@ static int CmdLegicRestore(const char *Cmd) {
case 'h': case 'h':
errors = true; errors = true;
break; break;
case 'i': case 'f':
fileNlen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); fileNlen = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE);
if (!fileNlen) if (!fileNlen)
errors = true; errors = true;
@ -983,6 +1010,10 @@ static int CmdLegicRestore(const char *Cmd) {
fileNlen = FILE_PATH_SIZE - 5; fileNlen = FILE_PATH_SIZE - 5;
cmdp += 2; cmdp += 2;
break; break;
case 'x':
shall_obsfuscate = true;
cmdp++;
break;
default: default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true; errors = true;
@ -998,48 +1029,30 @@ static int CmdLegicRestore(const char *Cmd) {
PrintAndLogEx(WARNING, "Failed to identify tagtype"); PrintAndLogEx(WARNING, "Failed to identify tagtype");
return PM3_ESOFT; return PM3_ESOFT;
} }
numofbytes = card.cardsize;
legic_print_type(card.cardsize, 0);
// set up buffer // set up buffer
uint8_t *data = calloc(numofbytes, sizeof(uint8_t)); uint8_t *data = calloc(card.cardsize, sizeof(uint8_t));
if (!data) { if (!data) {
PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
return PM3_EMALLOC; return PM3_EMALLOC;
} }
legic_print_type(numofbytes, 0); if (loadFile_safe(filename, ".bin", (void **)&data, &numofbytes) != PM3_SUCCESS) {
free(data);
PrintAndLogEx(WARNING, "Error, reading file");
return PM3_EFILE;
}
// set up file if (card.cardsize != numofbytes) {
fnameptr += fileNlen; PrintAndLogEx(WARNING, "Fail, filesize and cardsize is not equal. [%zu != %u]", card.cardsize, numofbytes);
sprintf(fnameptr, ".bin");
f = fopen(filename, "rb");
if (!f) {
PrintAndLogEx(WARNING, "File %s not found or locked", filename);
free(data); free(data);
return PM3_EFILE; return PM3_EFILE;
} }
// verify size of dumpfile is the same as card. if (shall_obsfuscate){
fseek(f, 0, SEEK_END); // seek to end of file legic_xor(data, card.cardsize);
size_t filesize = ftell(f); // get current file pointer
fseek(f, 0, SEEK_SET); // seek back to beginning of file
if (filesize != numofbytes) {
PrintAndLogEx(WARNING, "Fail, filesize and cardsize is not equal. [%zu != %u]", filesize, numofbytes);
free(data);
fclose(f);
return PM3_EFILE;
}
// load file
size_t bytes_read = fread(data, 1, numofbytes, f);
fclose(f);
if (bytes_read == 0) {
PrintAndLogEx(ERR, "File reading error");
free(data);
return PM3_EFILE;
} }
PrintAndLogEx(SUCCESS, "Restoring to card"); PrintAndLogEx(SUCCESS, "Restoring to card");
@ -1082,7 +1095,7 @@ static int CmdLegicRestore(const char *Cmd) {
} }
free(data); free(data);
PrintAndLogEx(SUCCESS, "\nWrote %d bytes to card from file %s", numofbytes, filename); PrintAndLogEx(SUCCESS, "Done");
return PM3_SUCCESS; return PM3_SUCCESS;
} }
@ -1091,7 +1104,7 @@ static int CmdLegicELoad(const char *Cmd) {
size_t numofbytes = 256; size_t numofbytes = 256;
int fileNameLen = 0; int fileNameLen = 0;
char filename[FILE_PATH_SIZE] = {0x00}; char filename[FILE_PATH_SIZE] = {0x00};
bool errors = false; bool errors = false, shall_obsfuscate = false;
uint8_t cmdp = 0; uint8_t cmdp = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
@ -1106,6 +1119,10 @@ static int CmdLegicELoad(const char *Cmd) {
fileNameLen = FILE_PATH_SIZE - 5; fileNameLen = FILE_PATH_SIZE - 5;
cmdp += 2; cmdp += 2;
break; break;
case 'x':
shall_obsfuscate = true;
cmdp++;
break;
case '0' : case '0' :
numofbytes = 22; numofbytes = 22;
cmdp++; cmdp++;
@ -1140,8 +1157,11 @@ static int CmdLegicELoad(const char *Cmd) {
return PM3_EFILE; return PM3_EFILE;
} }
PrintAndLogEx(SUCCESS, "Uploading to emulator memory"); if (shall_obsfuscate) {
legic_xor(data, numofbytes);
}
PrintAndLogEx(SUCCESS, "Uploading to emulator memory");
legic_seteml(data, 0, numofbytes); legic_seteml(data, 0, numofbytes);
free(data); free(data);
@ -1155,7 +1175,7 @@ static int CmdLegicESave(const char *Cmd) {
char *fptr = filename; char *fptr = filename;
int fileNameLen = 0; int fileNameLen = 0;
size_t numofbytes = 256; size_t numofbytes = 256;
bool errors = false; bool errors = false, shall_deobsfuscate = false;
uint8_t cmdp = 0; uint8_t cmdp = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) { switch (tolower(param_getchar(Cmd, cmdp))) {
@ -1169,6 +1189,10 @@ static int CmdLegicESave(const char *Cmd) {
fileNameLen = FILE_PATH_SIZE - 5; fileNameLen = FILE_PATH_SIZE - 5;
cmdp += 2; cmdp += 2;
break; break;
case 'x':
shall_deobsfuscate = true;
cmdp++;
break;
case '0' : case '0' :
numofbytes = 22; numofbytes = 22;
cmdp++; cmdp++;
@ -1212,6 +1236,10 @@ static int CmdLegicESave(const char *Cmd) {
FillFileNameByUID(fptr, data, "-dump", 4); FillFileNameByUID(fptr, data, "-dump", 4);
} }
if (shall_deobsfuscate) {
legic_xor(data, numofbytes);
}
saveFile(filename, ".bin", data, numofbytes); saveFile(filename, ".bin", data, numofbytes);
saveFileEML(filename, data, numofbytes, 8); saveFileEML(filename, data, numofbytes, 8);
saveFileJSON(filename, jsfLegic, data, numofbytes); saveFileJSON(filename, jsfLegic, data, numofbytes);