X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/0e8cabed8d180d2e03ba0cc04c853dad501cff7a..b816886806bc301aad60573e9ba6c35c1bfe4ea5:/client/cmdhflegic.c diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index d544a91c..88994243 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -13,10 +13,10 @@ static int CmdHelp(const char *Cmd); #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 u c "); + PrintAndLog("Usage: hf legic crc [h] b u c "); PrintAndLog("Options:"); PrintAndLog(" h : this help"); PrintAndLog(" b : hex bytes"); @@ -24,8 +24,8 @@ int usage_legic_calccrc8(void){ PrintAndLog(" c : 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){ @@ -60,28 +60,15 @@ int usage_legic_sim(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] "); + PrintAndLog("Usage: hf legic write [h] o d "); PrintAndLog("Options:"); PrintAndLog(" h : this help"); - PrintAndLog(" : offset in data array to start writing from (hex)"); - PrintAndLog(" : number of bytes to write (hex)"); - PrintAndLog(" : (optional) Initialization vector to use (ODD and 7bits)"); + PrintAndLog(" o : offset in data array to start writing"); + //PrintAndLog(" : (optional) Initialization vector to use (ODD and 7bits)"); + PrintAndLog(" d : 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] "); - PrintAndLog("Options:"); - PrintAndLog(" h : this help"); - PrintAndLog(" : offset to write to (hex)"); - PrintAndLog(" : value (hex)"); - PrintAndLog(" : (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){ @@ -119,7 +106,6 @@ int usage_legic_dump(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] "); @@ -152,7 +138,6 @@ int usage_legic_esave(void){ return 0; } - /* * Output BigBuf and deobfuscate LEGIC RF tag data. * This is based on information given in the talk held @@ -447,11 +432,11 @@ int CmdLegicInfo(const char *Cmd) { 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(); @@ -470,39 +455,39 @@ int CmdLegicRdmem(const char *Cmd) { 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; } @@ -553,7 +538,6 @@ int CmdLegicLoad(const char *Cmd) { 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(); @@ -655,20 +639,74 @@ int CmdLegicRfSim(const char *Cmd) { 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)) { @@ -679,107 +717,48 @@ int CmdLegicRfWrite(const char *Cmd) { 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; @@ -849,16 +828,13 @@ int CmdLegicCalcCrc8(const char *Cmd){ //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; @@ -912,18 +888,15 @@ void legic_chk_iv(uint32_t *iv){ 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); @@ -1023,6 +996,7 @@ int CmdLegicDump(const char *Cmd){ 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); @@ -1148,8 +1122,7 @@ int CmdLegicESave(const char *Cmd) { 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"); @@ -1186,7 +1159,7 @@ static command_t CommandTable[] = { {"load", CmdLegicLoad, 0, " -- Restore samples"}, {"sim", CmdLegicRfSim, 0, "[phase drift [frame drift [req/resp drift]]] Start tag simulator (use after load or read)"}, {"write", CmdLegicRfWrite, 0, " -- Write sample buffer (user after load or read)"}, - {"crc8", CmdLegicCalcCrc8, 1, "Calculate Legic CRC8 over given hexbytes"}, + {"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}