#define MAX_LENGTH 1024
-int usage_legic_calccrc8(void){
+int usage_legic_calccrc(void){
PrintAndLog("Calculates the legic crc8/crc16 on the input hexbytes.");
PrintAndLog("There must be an even number of hexsymbols as input.");
- PrintAndLog("Usage: hf legic crc8 [h] b <hexbytes> u <uidcrc> c <crc type>");
+ PrintAndLog("Usage: hf legic crc [h] b <hexbytes> u <uidcrc> c <crc type>");
PrintAndLog("Options:");
PrintAndLog(" h : this help");
PrintAndLog(" b <hexbytes> : hex bytes");
PrintAndLog(" c <crc type> : 8|16 bit crc size");
PrintAndLog("");
PrintAndLog("Samples:");
- PrintAndLog(" hf legic crc8 b deadbeef1122");
- PrintAndLog(" hf legic crc8 b deadbeef1122 u 9A c 16");
+ PrintAndLog(" hf legic crc b deadbeef1122");
+ PrintAndLog(" hf legic crc b deadbeef1122 u 9A c 16");
return 0;
}
int usage_legic_load(void){
}
int usage_legic_write(void){
PrintAndLog(" Write sample buffer to a legic tag. (use after load or read)");
- PrintAndLog("Usage: hf legic write [h] <offset> <length> <IV>");
+ PrintAndLog("Usage: hf legic write [h] o <offset> d <data (hex symbols)>");
PrintAndLog("Options:");
PrintAndLog(" h : this help");
- PrintAndLog(" <offset> : offset in data array to start writing from (hex)");
- PrintAndLog(" <length> : number of bytes to write (hex)");
- PrintAndLog(" <IV> : (optional) Initialization vector to use (ODD and 7bits)");
+ PrintAndLog(" o <offset> : offset in data array to start writing");
+ //PrintAndLog(" <IV> : (optional) Initialization vector to use (ODD and 7bits)");
+ PrintAndLog(" d <data> : bytes to write (hex symbols)");
PrintAndLog("");
PrintAndLog("Samples:");
- PrintAndLog(" hf legic write 10 4 - writes 0x4 to byte[0x10]");
- return 0;
-}
-int usage_legic_rawwrite(void){
- PrintAndLog("Write raw data direct to a specific offset on legic tag.");
- PrintAndLog("Usage: hf legic writeraw [h] <offset> <value> <IV>");
- PrintAndLog("Options:");
- PrintAndLog(" h : this help");
- PrintAndLog(" <offset> : offset to write to (hex)");
- PrintAndLog(" <value> : value (hex)");
- PrintAndLog(" <IV> : (optional) Initialization vector to use (hex, odd and 7bits)");
- PrintAndLog("");
- PrintAndLog("Samples:");
- PrintAndLog(" hf legic writeraw 10 4 - writes 0x4 to byte[0x10]");
+ PrintAndLog(" hf legic write o 10 d 11223344 - Write 0x11223344 starting from offset 0x10");
return 0;
}
int usage_legic_reader(void){
PrintAndLog(" hf legic dump o myfile");
return 0;
}
-
int usage_legic_eload(void){
PrintAndLog("It loads binary dump from the file `filename.bin`");
PrintAndLog("Usage: hf legic eload [h] [card memory] <file name w/o `.bin`>");
return 0;
}
-
/*
* Output BigBuf and deobfuscate LEGIC RF tag data.
* This is based on information given in the talk held
return 0;
}
+// params:
+// offset in data memory
+// number of bytes to read
int CmdLegicRdmem(const char *Cmd) {
- // params:
- // offset in data memory
- // number of bytes to read
char cmdp = param_getchar(Cmd, 0);
if ( cmdp == 'H' || cmdp == 'h' ) return usage_legic_rdmem();
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
- if (WaitForResponseTimeout(CMD_ACK, &resp, 3000)) {
- uint8_t isOK = resp.arg[0] & 0xFF;
- uint16_t readlen = resp.arg[1];
- if ( isOK ) {
-
- uint8_t *data = malloc(readlen);
- if ( !data ){
- PrintAndLog("Cannot allocate memory");
- return 2;
- }
+ if ( !WaitForResponseTimeout(CMD_ACK, &resp, 3000) ) {
+ PrintAndLog("command execution time out");
+ return 1;
+ }
+
+ uint8_t isOK = resp.arg[0] & 0xFF;
+ uint16_t readlen = resp.arg[1];
+ if ( !isOK ) {
+ PrintAndLog("failed reading tag");
+ return 2;
+ }
+
+ uint8_t *data = malloc(readlen);
+ if ( !data ){
+ PrintAndLog("Cannot allocate memory");
+ return 2;
+ }
- if ( readlen != len )
- PrintAndLog("Fail, only managed to read 0x%02X bytes", readlen);
+ if ( readlen != len )
+ PrintAndLog("Fail, only managed to read 0x%02X bytes", readlen);
- // copy data from device
- GetEMLFromBigBuf(data, readlen, 0);
- if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500)){
- PrintAndLog("Command execute timeout");
- if ( data )
- free(data);
- return 1;
- }
-
- PrintAndLog("\n ## | Data");
- PrintAndLog("-----+-----");
- print_hex_break( data, readlen, 32);
- } else {
- PrintAndLog("failed reading tag");
- }
- } else {
- PrintAndLog("command execution time out");
+ // copy data from device
+ GetEMLFromBigBuf(data, readlen, 0);
+ if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500)){
+ PrintAndLog("Command execute timeout");
+ free(data);
return 1;
}
+
+ PrintAndLog("\n ## | Data");
+ PrintAndLog("-----+-----");
+ print_hex_break( data, readlen, 32);
+ free(data);
return 0;
}
index += res;
if ( index == USB_CMD_DATA_SIZE ){
-// PrintAndLog("sent %d | %d | %d", index, offset, totalbytes);
UsbCommand c = { CMD_DOWNLOADED_SIM_SAMPLES_125K, {offset, 0, 0}};
memcpy(c.d.asBytes, data, sizeof(data));
clearCommandBuffer();
int CmdLegicRfWrite(const char *Cmd) {
- // offset - in tag memory
- // length - num of bytes to be written
-
- char cmdp = param_getchar(Cmd, 0);
- if ( cmdp == 'H' || cmdp == 'h' ) return usage_legic_write();
-
- uint32_t offset = 0, len = 0, IV = 0;
-
- int res = sscanf(Cmd, "%x %x %x", &offset, &len, &IV);
- if(res < 2) {
- PrintAndLog("Please specify the offset and length as two hex strings and, optionally, the IV also as an hex string");
- return -1;
- }
+ uint8_t *data = NULL;
+ uint8_t cmdp = 0;
+ bool errors = false;
+ int len = 0, bg, en;
+ uint32_t offset = 0, IV = 0x55;
+ while(param_getchar(Cmd, cmdp) != 0x00) {
+ switch(param_getchar(Cmd, cmdp)) {
+ case 'd':
+ case 'D':
+ // peek at length of the input string so we can
+ // figure out how many elements to malloc in "data"
+ bg=en=0;
+ if (param_getptr(Cmd, &bg, &en, cmdp+1)) {
+ errors = true;
+ break;
+ }
+ len = (en - bg + 1);
+
+ // check that user entered even number of characters
+ // for hex data string
+ if (len & 1) {
+ errors = true;
+ break;
+ }
+
+ // 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");
+ errors = true;
+ break;
+ }
+
+ if (param_gethex(Cmd, cmdp+1, data, len)) {
+ errors = true;
+ break;
+ }
+
+ len >>= 1;
+ cmdp += 2;
+ break;
+ case 'o':
+ case 'O':
+ offset = param_get32ex(Cmd, cmdp+1, 4, 10);
+ cmdp += 2;
+ break;
+ case 'h':
+ case 'H':
+ errors = true;
+ break;
+ default:
+ PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+ errors = true;
+ break;
+ }
+ if (errors) break;
+ }
+ //Validations
+ if (errors){
+ if (data)
+ free(data);
+ return usage_legic_write();
+ }
+
// tagtype
legic_card_select_t card;
if (legic_get_type(&card)) {
legic_print_type(card.cardsize, 0);
// OUT-OF-BOUNDS check
- if ( len + offset > card.cardsize ) {
- PrintAndLog("Out-of-bounds, Cardsize = %d, [offset+len = %d ]", card.cardsize, len + offset);
+ // UID 4 bytes can't be written to.
+ if ( len + offset + 4 >= card.cardsize ) {
+ PrintAndLog("Out-of-bounds, Cardsize = %d, [offset+len = %d ]", card.cardsize, len + offset + 4);
return -2;
}
-
+
legic_chk_iv(&IV);
- UsbCommand c = {CMD_WRITER_LEGIC_RF, {offset, len, IV}};
+ PrintAndLog("Writing to tag");
+ UsbCommand c = {CMD_WRITER_LEGIC_RF, {offset, len, IV}};
+ memcpy(c.d.asBytes, data, len);
+
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;
- if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
- uint8_t isOK = resp.arg[0] & 0xFF;
- if ( !isOK )
- PrintAndLog("failed writing tag");
- } else {
+ if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) {
PrintAndLog("command execution time out");
return 1;
}
+ uint8_t isOK = resp.arg[0] & 0xFF;
+ if ( !isOK ) {
+ PrintAndLog("failed writing tag");
+ return 1;
+ }
return 0;
}
+/*
int CmdLegicRfRawWrite(const char *Cmd) {
-
- char cmdp = param_getchar(Cmd, 0);
- if ( cmdp == 'H' || cmdp == 'h' ) return usage_legic_rawwrite();
-
- uint32_t offset = 0, data = 0, IV = 0;
- char answer;
-
- int res = sscanf(Cmd, "%x %x %x", &offset, &data, &IV);
- if(res < 2)
- return usage_legic_rawwrite();
-
- // OUT-OF-BOUNDS check
- if ( offset > MAX_LENGTH ) {
- PrintAndLog("Out-of-bound, offset");
- return 1;
- }
-
- if ( (IV & 0x7F) != IV ){
- IV &= 0x7F;
- PrintAndLog("Truncating IV to 7bits");
- }
- if ( (IV & 1) == 0 ){
- IV |= 0x01; // IV must be odd
- PrintAndLog("LSB of IV must be SET");
- }
-
- UsbCommand c = { CMD_RAW_WRITER_LEGIC_RF, {offset, data, IV} };
-
- if (c.arg[0] == 0x05 || c.arg[0] == 0x06) {
- 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')) {
- SendCommand(&c);
- return 0;
- }
- return -1;
- }
-
- clearCommandBuffer();
- SendCommand(&c);
+ 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;
+ // }
return 0;
}
+*/
-void static calc4(uint8_t *cmd, uint8_t len){
- crc_t crc;
- //crc_init_ref(&crc, 4, 0x19 >> 1, 0x5, 0, TRUE, TRUE);
- crc_init(&crc, 4, 0x19 >> 1, 0x5, 0);
-
- crc_clear(&crc);
- crc_update(&crc, 1, 1); /* CMD_READ */
- crc_update(&crc, cmd[0], 8);
- crc_update(&crc, cmd[1], 8);
- printf("crc4 %X\n", reflect(crc_finish(&crc), 4) ) ;
-
- crc_clear(&crc);
- crc_update(&crc, 1, 1); /* CMD_READ */
- crc_update(&crc, cmd[0], 8);
- crc_update(&crc, cmd[1], 8);
- printf("crc4 %X\n", crc_finish(&crc) ) ;
-
- printf("---- old ---\n");
- crc_update2(&crc, 1, 1); /* CMD_READ */
- crc_update2(&crc, cmd[0], 8);
- crc_update2(&crc, cmd[1], 8);
- printf("crc4 %X \n", reflect(crc_finish(&crc), 4) ) ;
-
-
- crc_clear(&crc);
- crc_update2(&crc, 1, 1); /* CMD_READ */
- crc_update2(&crc, cmd[0], 8);
- crc_update2(&crc, cmd[1], 8);
- printf("crc4 %X\n", crc_finish(&crc) ) ;
-}
-
-int CmdLegicCalcCrc8(const char *Cmd){
+int CmdLegicCalcCrc(const char *Cmd){
uint8_t *data = NULL;
uint8_t cmdp = 0, uidcrc = 0, type=0;
//Validations
if (errors){
if (data) free(data);
- return usage_legic_calccrc8();
+ return usage_legic_calccrc();
}
switch (type){
case 16:
PrintAndLog("Legic crc16: %X", CRC16Legic(data, len, uidcrc));
break;
- case 4:
- calc4(data, 0);
- break;
default:
PrintAndLog("Legic crc8: %X", CRC8Legic(data, len) );
break;
PrintAndLog("LSB of IV must be SET %u", *iv);
}
}
-
void legic_seteml(uint8_t *src, uint32_t offset, uint32_t numofbytes) {
-
size_t len = 0;
UsbCommand c = {CMD_LEGIC_ESET, {0, 0, 0}};
-
for(size_t i = 0; 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, src, len);
+ memcpy(c.d.asBytes, src+i, len);
clearCommandBuffer();
SendCommand(&c);
PrintAndLog("ICE: offset %d | len %d", i, len);
PrintAndLog("Fail, cannot allocate memory");
return 3;
}
+ memset(data, 0, readlen);
if ( readlen != dumplen )
PrintAndLog("Fail, only managed to read 0x%02X bytes of 0x%02X", readlen, dumplen);
memset(data, 0, numofbytes);
// download emulator memory
- PrintAndLog("Reading emulator memory...");
-
+ PrintAndLog("Reading emulator memory...");
GetEMLFromBigBuf(data, numofbytes, 0);
if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500)) {
PrintAndLog("Fail, transfer from device time-out");
{"save", CmdLegicSave, 0, "<filename> [<length>] -- Store samples"},
{"load", CmdLegicLoad, 0, "<filename> -- Restore samples"},
{"sim", CmdLegicRfSim, 0, "[phase drift [frame drift [req/resp drift]]] Start tag simulator (use after load or read)"},
- {"write", CmdLegicRfWrite, 0, "<offset> <length> <iv> -- Write sample buffer (user after load or read)"},
- {"crc8", CmdLegicCalcCrc8, 1, "Calculate Legic CRC8 over given hexbytes"},
+ {"write", CmdLegicRfWrite, 0, "Write data to tag"},
+ {"crc", CmdLegicCalcCrc, 1, "Calculate Legic CRC over given hexbytes"},
{"eload", CmdLegicELoad, 1, "Load binary dump to emulator memory"},
{"esave", CmdLegicESave, 1, "Save emulator memory to binary file"},
{NULL, NULL, 0, NULL}