diff --git a/CHANGELOG.md b/CHANGELOG.md index 9aa7ff298..ff51fbd4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added 122 new keys from Flipper Zero community to `mfc_default_keys.dic` (@UberGuidoZ) - Added showing password for the read command in the `lf t55xx sniff` command (@merlokk) - Added reading texcom tk13 and tk17 tags with `hf texkom read` command (@merlokk @iceman1001) + - Added simulating texcom tk13 and tk17 tags with `hf texkom sim` command (@merlokk) ## [Frostbit.4.14831][2022-01-11] - Changed Wiegand format lookup - now case-insensitive (@iceman1001) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 5254368ae..5e84aec4e 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1392,6 +1392,13 @@ static void PacketReceived(PacketCommandNG *packet) { HfReadADC(samplesCount, true); break; } + case CMD_HF_TEXKOM_SIMULATE: { + uint32_t timeout = 0; + memcpy(&timeout, &packet->data.asBytes[9], 4); + HfWriteTkm(packet->data.asBytes, packet->data.asBytes[8], timeout); + break; + } + #endif #ifdef WITH_ISO14443a diff --git a/armsrc/hfops.c b/armsrc/hfops.c index 3bf060c56..591e80fda 100644 --- a/armsrc/hfops.c +++ b/armsrc/hfops.c @@ -19,6 +19,7 @@ #include "hfops.h" #include +#include "appmain.h" #include "proxmark3_arm.h" #include "cmd.h" #include "BigBuf.h" @@ -90,4 +91,177 @@ int HfReadADC(uint32_t samplesCount, bool ledcontrol) { return 0; } +uint8_t encode_acc = 0; +uint8_t encode_acc_bit_count = 0; +uint32_t encode_indx = 0; +static void EncodeInit(void) { + encode_acc = 0; + encode_acc_bit_count = 0; + encode_indx = 0; +} + +static void EncodeAddBit(uint8_t *data, uint8_t bit, uint8_t bit_count) { + for (int i = 0; i < bit_count; i++) { + encode_acc = (encode_acc << 1) | (bit & 0x01); + encode_acc_bit_count++; + if (encode_acc_bit_count > 7) { + data[encode_indx++] = encode_acc; + encode_acc = 0; + encode_acc_bit_count = 0; + } + } +} + +static uint32_t EncodeFinish(uint8_t *data) { + if (encode_acc_bit_count > 0) { + encode_acc = encode_acc << (8 - encode_acc_bit_count); + data[encode_indx++] = encode_acc; + } + + return encode_indx; +} + +static uint32_t HfEncodeTkm(uint8_t *uid, uint8_t modulation, uint8_t *data) { + uint32_t len = 0; + if (modulation == 0) { + // TK-13 + // 74ns 1 field cycle, + // carrier frequency is fc/64 (212kHz), 4.7 mks + // 100 field cycle = impulse 1.6 ( 1 bit from real tag) + // 1000 field cycle = `1` 15.6 (17 bit from real tag) + // 500 field cycle = `0` 7.8 ( 7 bit from real tag) + + EncodeInit(); + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) { + if (((uid[i] << j) & 0x80) != 0) { + // `1` + EncodeAddBit(data, 1, 1); + EncodeAddBit(data, 0, 17); + EncodeAddBit(data, 1, 1); + EncodeAddBit(data, 0, 7); + } else { + // `0` + EncodeAddBit(data, 1, 1); + EncodeAddBit(data, 0, 7); + EncodeAddBit(data, 1, 1); + EncodeAddBit(data, 0, 17); + } + } + } + len = EncodeFinish(data); + } else { + // TK-17 + // 74ns 1 field cycle, + // carrier frequency is fc/64 (212kHz), 4.7 mks + // 0 --- 8 --- 12-15 --- 18-19 --- 26-28 --- 32 + // DO NOT NORMALIZE!!!! it must be with some error like this!!!! + // `00` -- 1-25-1-5 + // `01` -- 1-12-1-18 + // `10` -- 1-17-1-13 + // `11` -- 1-7-1-23 + + EncodeInit(); + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j += 2) { + uint8_t twobit = ((uid[i] >> j) & 0x03); + if (twobit == 0x00) { + // `00` + EncodeAddBit(data, 1, 1); + EncodeAddBit(data, 0, 25); + EncodeAddBit(data, 1, 1); + EncodeAddBit(data, 0, 5); + } else if (twobit == 0x01) { + // `01` + EncodeAddBit(data, 1, 1); + EncodeAddBit(data, 0, 12); + EncodeAddBit(data, 1, 1); + EncodeAddBit(data, 0, 18); + } else if (twobit == 0x02) { + // `10` + EncodeAddBit(data, 1, 1); + EncodeAddBit(data, 0, 17); + EncodeAddBit(data, 1, 1); + EncodeAddBit(data, 0, 13); + } else { // twobit == 0x03 + // `11` + EncodeAddBit(data, 1, 1); + EncodeAddBit(data, 0, 7); + EncodeAddBit(data, 1, 1); + EncodeAddBit(data, 0, 23); + } + } + } + EncodeAddBit(data, 1, 1); + len = EncodeFinish(data); + } + + return len; +} + +int HfWriteTkm(uint8_t *uid, uint8_t modulation, uint32_t timeout) { + // free eventually allocated BigBuf memory + BigBuf_free_keep_EM(); + + LEDsoff(); + + uint8_t *data = BigBuf_calloc(256); + uint32_t elen = HfEncodeTkm(uid, modulation, data); + if (elen == 0) { + DbpString("encode error"); + reply_ng(CMD_HF_TEXKOM_SIMULATE, PM3_EAPDU_ENCODEFAIL, NULL, 0); + return PM3_EAPDU_ENCODEFAIL; + } + + LED_C_ON(); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_212K); + FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR); + + int vHf = 0; // in mV + bool button_pressed = false; + bool exit_loop = false; + bool field_on = false; + while (exit_loop == false) { + + button_pressed = BUTTON_PRESS(); + if (button_pressed || data_available()) + break; + + WDT_HIT(); + + vHf = (MAX_ADC_HF_VOLTAGE * SumAdc(ADC_CHAN_HF, 32)) >> 15; + if (vHf > MF_MINFIELDV) { + if (!field_on) { + LED_A_ON(); + SpinDelay(50); + } + field_on = true; + } else { + if (field_on) { + LED_A_OFF(); + } + field_on = false; + continue; + } + + SpinDelay(3); + for (int i = 0; i < elen;) { + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { + AT91C_BASE_SSC->SSC_THR = data[i]; + i++; + } + } + } + + switch_off(); + + if (button_pressed) + DbpString("button pressed"); + + reply_ng(CMD_HF_TEXKOM_SIMULATE, PM3_SUCCESS, NULL, 0); + + return PM3_SUCCESS; +} diff --git a/armsrc/hfops.h b/armsrc/hfops.h index 489c99bc6..91f1de539 100644 --- a/armsrc/hfops.h +++ b/armsrc/hfops.h @@ -22,5 +22,6 @@ #include "common.h" int HfReadADC(uint32_t samplesCount, bool ledcontrol); +int HfWriteTkm(uint8_t *uid, uint8_t modulation, uint32_t timeout); -#endif \ No newline at end of file +#endif diff --git a/client/src/cmdhftexkom.c b/client/src/cmdhftexkom.c index 615f0c0df..7cd04b408 100644 --- a/client/src/cmdhftexkom.c +++ b/client/src/cmdhftexkom.c @@ -550,12 +550,97 @@ static int CmdHFTexkomReader(const char *Cmd) { } +static int CmdHFTexkomSim(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf texkom sim", + "Simulate a texkom tag", + "hf texkom sim \r\n" + "hf texkom sim --raw FFFF638C7DC45553 -> simulate TK13 tag with id 8C7DC455\r\n" + "hf texkom sim --tk17 --raw FFFFCA17F31EC512 -> simulate TK17 tag with id 17F31EC5\r\n" + "hf texkom sim --id 8C7DC455 -> simulate TK13 tag with id 8C7DC455\r\n" + "hf texkom sim --id 8C7DC455 --tk17 -> simulate TK17 tag with id 17F31EC5"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("v", "verbose", "Verbose work"), + arg_lit0("t", "tk17", "Use TK-17 modulation (TK-13 by default)"), + arg_str0(NULL, "raw", "", "Raw data for texkom card, 8 bytes. Manual modulation select."), + arg_str0(NULL, "id", "", "Raw data for texkom card, 8 bytes. Manual modulation select."), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool verbose = arg_get_lit(ctx, 1); + uint32_t cmdtimeout = 0; + uint8_t modulation = 0; // tk-13 + if (arg_get_lit(ctx, 2)) + modulation = 1; //tk-17 + + uint8_t rawdata[250] = {0}; + int rawdatalen = 0; + CLIGetHexWithReturn(ctx, 3, rawdata, &rawdatalen); + + uint8_t iddata[250] = {0}; + int iddatalen = 0; + CLIGetHexWithReturn(ctx, 4, iddata, &iddatalen); + + CLIParserFree(ctx); + + if (rawdatalen == 0 && iddatalen == 0) { + PrintAndLogEx(ERR, " or must be specified to simulate"); + return PM3_EINVARG; + } + + if (iddatalen > 0 && iddatalen != 4) { + PrintAndLogEx(ERR, " must be 4 bytes long instead of: %d", iddatalen); + return PM3_EINVARG; + } + + if (iddatalen == 4) { + rawdata[0] = 0xff; + rawdata[1] = 0xff; + rawdata[2] = (modulation == 0) ? 0x63 : 0xca; + memcpy(&rawdata[3], iddata, 4); + rawdata[7] = (modulation == 0) ? TexcomTK13CRC(iddata) : TexcomTK17CRC(iddata); + rawdatalen = 8; + } + + if (rawdatalen > 0 && rawdatalen != 8) { + PrintAndLogEx(ERR, " must be 8 bytes long instead of: %d", rawdatalen); + return PM3_EINVARG; + } + + // + uint8_t data[13] = {0}; + memcpy(data, rawdata, 8); + + data[8] = modulation; + memcpy(&data[9], &cmdtimeout, 4); + clearCommandBuffer(); + SendCommandNG(CMD_HF_TEXKOM_SIMULATE, data, sizeof(data)); + + if (cmdtimeout > 0 && cmdtimeout < 2800) { + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_HF_TEXKOM_SIMULATE, &resp, 3000)) { + if (verbose) + PrintAndLogEx(WARNING, "(hf texkom simulate) command execution time out"); + return PM3_ETIMEOUT; + } + PrintAndLogEx(INFO, "simulate command execution done"); + } else { + PrintAndLogEx(INFO, "simulate command started"); + } + + return PM3_SUCCESS; +} + + static int CmdHelp(const char *Cmd); static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"reader", CmdHFTexkomReader, IfPm3Iso14443a, "Act like a Texkom reader"}, - //{"sim", CmdHFTexkomSim, IfPm3Iso14443a, "Simulate a Texkom tag"}, + {"sim", CmdHFTexkomSim, IfPm3Iso14443a, "Simulate a Texkom tag"}, //{"write", CmdHFTexkomWrite, IfPm3Iso14443a, "Write a Texkom tag"}, {NULL, NULL, 0, NULL} }; diff --git a/doc/commands.json b/doc/commands.json index 5fb476e59..dfc8a4647 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -6324,6 +6324,27 @@ ], "usage": "hf texkom reader [-hv]" }, + "hf texkom sim": { + "command": "hf texkom sim", + "description": "Simulate a texkom tag", + "notes": [ + "hf texkom sim", + "", + "hf texkom sim --raw FFFF638C7DC45553 -> simulate TK13 tag with id 8C7DC455", + "hf texkom sim --tk17 --raw FFFFCA17F31EC512 -> simulate TK17 tag with id 17F31EC5", + "hf texkom sim --id 8C7DC455 -> simulate TK13 tag with id 8C7DC455", + "hf texkom sim --id 8C7DC455 --tk17 -> simulate TK17 tag with id 17F31EC5" + ], + "offline": false, + "options": [ + "-h, --help This help", + "-v, --verbose Verbose work", + "-t, --tk17 Use TK-17 modulation (TK-13 by default)", + "--raw Raw data for texkom card, 8 bytes. Manual modulation select.", + "--id Raw data for texkom card, 8 bytes. Manual modulation select." + ], + "usage": "hf texkom sim [-hvt] [--raw ] [--id ]" + }, "hf thinfilm help": { "command": "hf thinfilm help", "description": "help This help list List NFC Barcode / Thinfilm history - not correct", @@ -6585,8 +6606,8 @@ "command": "hw connect", "description": "Connects to a Proxmark3 device via specified serial port. Baudrate here is only for physical UART or UART-BT, NOT for USB-CDC or blue shark add-on", "notes": [ - "hw connect -p /dev/ttyACM0", - "hw connect -p /dev/ttyACM0 -b 115200" + "hw connect -p /dev/ttyacm0", + "hw connect -p /dev/ttyacm0 -b 115200" ], "offline": true, "options": [ @@ -11055,8 +11076,8 @@ } }, "metadata": { - "commands_extracted": 698, + "commands_extracted": 699, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2022-06-30T19:19:33" + "extracted_on": "2022-07-03T21:31:15" } } \ No newline at end of file diff --git a/doc/commands.md b/doc/commands.md index fe57dfbdb..4f03dee72 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -654,6 +654,7 @@ Check column "offline" for their availability. |------- |------- |----------- |`hf texkom help `|Y |`This help` |`hf texkom reader `|N |`Act like a Texkom reader` +|`hf texkom sim `|N |`Simulate a Texkom tag` ### hf xerox diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index e53132309..69d9fed5b 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -522,6 +522,7 @@ typedef struct { #define CMD_HF_ISO15693_CSETUID 0x0316 #define CMD_HF_ISO15693_SLIX_L_DISABLE_PRIVACY 0x0317 #define CMD_HF_ISO15693_SLIX_L_DISABLE_AESAFI 0x0318 +#define CMD_HF_TEXKOM_SIMULATE 0x0320 #define CMD_LF_SNIFF_RAW_ADC 0x0360