diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 01eb4b8f8..08b869378 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -28,6 +28,8 @@ #include "protocols.h" // t55 defines #include "cmdlft55xx.h" // verifywrite +#define INDALA_ARR_LEN 64 + static int CmdHelp(const char *Cmd); //large 224 bit indala formats (different preamble too...) @@ -140,7 +142,7 @@ static void decodeHeden2L(uint8_t *bits) { if (bits[offset + 7]) cardnumber += 16384; if (bits[offset + 23]) cardnumber += 32768; - PrintAndLogEx(SUCCESS, "\tHeden-2L | %u", cardnumber); + PrintAndLogEx(SUCCESS, "\tHeden-2L | " _YELLOW_("%u"), cardnumber); } // Indala 26 bit decode @@ -192,7 +194,7 @@ static int CmdIndalaDemod(const char *Cmd) { if (DemodBufferLen == 64) { PrintAndLogEx( SUCCESS - , "Indala Found - bitlength %zu, Raw %x%08x" + , "Indala Found - bitlength %zu, Raw " _YELLOW_("%x%08x") , DemodBufferLen , uid1 , uid2 @@ -244,14 +246,18 @@ static int CmdIndalaDemod(const char *Cmd) { checksum |= DemodBuffer[63] << 0; // b1 PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "Fmt 26 bit FC " _YELLOW_("%u") ", CN " _YELLOW_("%u") ", checksum %1d%1d" + , fc + , csn + , checksum >> 1 & 0x01 + , checksum & 0x01 + ); + PrintAndLogEx(SUCCESS, "Possible de-scramble patterns"); PrintAndLogEx(SUCCESS, "\tPrinted | __%04d__ [0x%X]", p1, p1); PrintAndLogEx(SUCCESS, "\tInternal ID | %" PRIu64, foo); decodeHeden2L(DemodBuffer); - PrintAndLogEx(SUCCESS, "Fmt 26 bit FC %u , CSN %u , checksum %1d%1d", fc, csn, checksum >> 1 & 0x01, checksum & 0x01); - - } else { uint32_t uid3 = bytebits_to_byte(DemodBuffer + 64, 32); uint32_t uid4 = bytebits_to_byte(DemodBuffer + 96, 32); @@ -542,49 +548,62 @@ static int CmdIndalaSim(const char *Cmd) { static int CmdIndalaClone(const char *Cmd) { - bool is_long_uid = false, got_cn = false; + bool is_long_uid = false, got_cn = false, got_26 = false; bool is_t5555 = false; int32_t cardnumber; uint32_t blocks[8] = {0}; uint8_t max = 0; uint8_t data[7 * 4]; int datalen = 0; + uint8_t fc = 0; + uint16_t cn = 0; CLIParserInit("lf indala clone", "clone INDALA tag to T55x7 (or to q5/T5555)", "Examples:\n" "\tlf indala clone -c 888\n" + "\tlf indala clone -fc 123 -csn 1337\n" "\tlf indala clone -r a0000000a0002021\n" "\tlf indala clone -l -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5"); void *argtable[] = { arg_param_begin, - arg_lit0("lL", "long", "optional - long UID 224 bits"), - arg_int0("cC", "cn", "", "Cardnumber for Heden 2L format"), - arg_strx0("rR", "raw", "", "raw bytes"), - arg_lit0("qQ", "Q5", "optional - specify write to Q5 (t5555 instead of t55x7)"), + arg_lit0("lL", "long", "optional - long UID 224 bits"), + arg_int0("cC", "heden", "", "Cardnumber for Heden 2L format"), + arg_strx0("rR", "raw", "", "raw bytes"), + arg_lit0("qQ", "Q5", "optional - specify write to Q5 (t5555 instead of t55x7)"), + arg_int0("", "fc", "", "Facility Code (26 bit format)"), + arg_int0("", "cn", "", "Cardnumber (26 bit format)"), arg_param_end }; CLIExecWithReturn(Cmd, argtable, false); is_long_uid = arg_get_lit(1); - if (is_long_uid == false) { - cardnumber = arg_get_int_def(2, -1); - got_cn = (cardnumber != -1); - } - if (got_cn == false) { - CLIGetHexWithReturn(3, data, &datalen); - } + // raw param + CLIGetHexWithReturn(3, data, &datalen); is_t5555 = arg_get_lit(4); + if (is_long_uid == false) { + + // Heden param + cardnumber = arg_get_int_def(2, -1); + got_cn = (cardnumber != -1); + + // 26b FC/CN param + fc = arg_get_int_def(5, 0); + cn = arg_get_int_def(6, 0); + got_26 = (fc != 0 && cn != 0); + } + CLIParserFree(); if (is_long_uid) { // 224 BIT UID // config for Indala (RF/32;PSK2 with RF/2;Maxblock=7) - PrintAndLogEx(INFO, "Preparing to clone Indala 224bit tag with RawID %s", sprint_hex(data, datalen)); + PrintAndLogEx(INFO, "Preparing to clone Indala 224bit tag"); + PrintAndLogEx(INFO, "RawID %s", sprint_hex(data, datalen)); if (is_t5555) blocks[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_PSK2 | (7 << T5555_MAXBLOCK_SHIFT); @@ -602,12 +621,41 @@ static int CmdIndalaClone(const char *Cmd) { } else { // 64 BIT UID if (got_cn) { + PrintAndLogEx(INFO, "Using Indala HEDEN cardnumber %u", cardnumber); encodeHeden2L(data, cardnumber); datalen = 8; + } else if (got_26) { + + PrintAndLogEx(INFO, "Using Indala 26b FC %u CN %u", fc, cn); + + // Used with the 26bit FC/CSN + uint8_t *bits = calloc(INDALA_ARR_LEN, sizeof(uint8_t)); + if (bits == NULL) { + PrintAndLogEx(WARNING, "Failed to allocate memory"); + return PM3_EMALLOC; + } + + if (getIndalaBits(fc, cn, bits) != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Error with tag bitstream generation."); + return PM3_ESOFT; + } + + data[0] = bytebits_to_byte(bits, 8); + data[1] = bytebits_to_byte(bits + 8, 8); + data[2] = bytebits_to_byte(bits + 16, 8); + data[3] = bytebits_to_byte(bits + 24, 8); + data[4] = bytebits_to_byte(bits + 32, 8); + data[5] = bytebits_to_byte(bits + 40, 8); + data[6] = bytebits_to_byte(bits + 48, 8); + data[7] = bytebits_to_byte(bits + 56, 8); + datalen = 8; + + free(bits); } // config for Indala 64 format (RF/32;PSK1 with RF/2;Maxblock=2) - PrintAndLogEx(INFO, "Preparing to clone Indala 64bit tag with RawID %s", sprint_hex(data, datalen)); + PrintAndLogEx(INFO, "Preparing to clone Indala 64bit tag"); + PrintAndLogEx(INFO, "RawID %s", sprint_hex(data, datalen)); if (is_t5555) blocks[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | (2 << T5555_MAXBLOCK_SHIFT); @@ -647,6 +695,50 @@ int CmdLFINDALA(const char *Cmd) { return CmdsParse(CommandTable, Cmd); } +int getIndalaBits(uint8_t fc, uint16_t cn, uint8_t *bits) { + // preamble + // is there a preamble? + bits[0] = 1; + bits[2] = 1; + bits[32] = 1; + + // add fc + bits[57] = ((fc >> 7) & 1); // b8 + bits[49] = ((fc >> 6) & 1); // b7 + bits[44] = ((fc >> 5) & 1); // b6 + bits[47] = ((fc >> 4) & 1); // b5 + bits[48] = ((fc >> 3) & 1); // b4 + bits[53] = ((fc >> 2) & 1); // b3 + bits[39] = ((fc >> 1) & 1); // b2 + bits[58] = (fc & 1); // b1 + + // add cn + bits[42] = ((cn >> 15) & 1); // b16 + bits[45] = ((cn >> 14) & 1); // b15 + bits[43] = ((cn >> 13) & 1); // b14 + bits[40] = ((cn >> 12) & 1); // b13 + bits[52] = ((cn >> 11) & 1); // b12 + bits[36] = ((cn >> 10) & 1); // b11 + bits[35] = ((cn >> 9) & 1); // b10 + bits[51] = ((cn >> 8) & 1); // b9 + bits[46] = ((cn >> 7) & 1); // b8 + bits[33] = ((cn >> 6) & 1); // b7 + bits[37] = ((cn >> 5) & 1); // b6 + bits[54] = ((cn >> 4) & 1); // b5 + bits[56] = ((cn >> 3) & 1); // b4 + bits[59] = ((cn >> 2) & 1); // b3 + bits[50] = ((cn >> 1) & 1); // b2 + bits[41] = (cn & 1); // b1 + + // checksum + // ICEMAN: todo: needs to calc + uint8_t chk = 3; + bits[62] = ((chk >> 1) & 1); // b2 + bits[63] = (chk & 1); // b1 + + return PM3_SUCCESS; +} + // redesigned by marshmellow adjusted from existing decode functions // indala id decoding int detectIndala(uint8_t *dest, size_t *size, uint8_t *invert) {